<commit_before>;CLisp script to convert lastpass CSV export to pwman format
;Tested in SBCL. Use as follows
;
;	sbcl --script /path/to/this/script </path/to/lastpass/export>
;
;The path to the Lastpass export is optional. If not supplied assumes file is
;called "lastpass.csv" and is in current directory. Exports a file called
;"pwman.txt" to current directory. This is in plain text and so needs encoding 
;via GPG. 
;
;	gpg -r <<EMAIL>> -o ~/.pwman.db -e pwman.txt
;
;This will overwrite the pwman password database
;Remember to delete the plain text files afterwards!

;Load quicklisp
(load "~/.sbclrc")
;Load libraries
(ql:quickload "csv-parser")
(ql:quickload "xmls")

;Check for supplied filename, otherwise assume called lastpass.csv
;It's 2nd *posix-argv* as first is always /path/to/sbcl, etc.
(defparameter infile (if (null (second *posix-argv*)) "lastpass.csv" (second *posix-argv*)))

(with-open-file (stream "pwman.txt" :direction :output :if-exists :supersede)
	(format stream "<?xml version=\"1.0\"?><PWMan_PasswordList version=\"3\"><PwList name=\"Main\">")
	(csv-parser:map-csv-file infile 
		(lambda (ln)
			(format stream
				"<PwItem><name>~a</name><host>~a</host><user>~a</user><passwd>~a</passwd><launch></launch></PwItem>"
				(xmls:toxml (fifth ln))
				(xmls:toxml (first ln))
				(xmls:toxml (second ln))
				(if (null (third ln)) ;Secure Notes have no password 
					(xmls:toxml (fourth ln)) ;Use extra field if Secure Note
					(xmls:toxml (third ln))))))
	(format stream "</PwList></PWMan_PasswordList>"))<commit_msg>Skip first line of the CSV file (header)<commit_after>;CLisp script to convert lastpass CSV export to pwman format
;Tested in SBCL. Use as follows
;
;	sbcl --script /path/to/this/script </path/to/lastpass/export>
;
;The path to the Lastpass export is optional. If not supplied assumes file is
;called "lastpass.csv" and is in current directory. Exports a file called
;"pwman.txt" to current directory. This is in plain text and so needs encoding 
;via GPG. 
;
;	gpg -r <<EMAIL>> -o ~/.pwman.db -e pwman.txt
;
;This will overwrite the pwman password database
;Remember to delete the plain text files afterwards!

;Load quicklisp
(load "~/.sbclrc")
;Load libraries
(ql:quickload "csv-parser")
(ql:quickload "xmls")

;Check for supplied filename, otherwise assume called lastpass.csv
;It's 2nd *posix-argv* as first is always /path/to/sbcl, etc.
(defparameter infile (if (null (second *posix-argv*)) "lastpass.csv" (second *posix-argv*)))

(with-open-file (stream "pwman.txt" :direction :output :if-exists :supersede)
	(format stream "<?xml version=\"1.0\"?><PWMan_PasswordList version=\"3\"><PwList name=\"Main\">")
	(csv-parser:map-csv-file infile 
		(lambda (ln)
			(format stream
				"<PwItem><name>~a</name><host>~a</host><user>~a</user><passwd>~a</passwd><launch></launch></PwItem>"
				(xmls:toxml (fifth ln))
				(xmls:toxml (first ln))
				(xmls:toxml (second ln))
				(if (null (third ln)) ;Secure Notes have no password 
					(xmls:toxml (fourth ln)) ;Use extra field if Secure Note
					(xmls:toxml (third ln))))) :skip-lines 1)
	(format stream "</PwList></PWMan_PasswordList>"))
{'fraction_non_alphanumeric': 0.15311004784688995, 'fraction_numerical': 0.0028708133971291866, 'mean_word_length': 4.511423550087874, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 2, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 24}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5174149', 'n_tokens_mistral': 1178, 'n_tokens_neox': 1086, 'n_words': 350}