pwman-tools

Check-in [05989bbd9b]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Use sublists in PWman to match groups in Lastpass.

I hadn't realised PWman supports sublists (groups), therefore can match
the grouping structure used in Lastpass.

- Now reads in CSV file to hashtable. Since CSV file is not ordered by
group, using a hashtable means we can loop through and create a key
for a group if it doesn't exists, or collate entries against a
existing group/key.
- Writing out hasn't changed much. Loops through the keys of the hash
table and loops within each key/group as well.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | master | trunk
Files: files | file ages | folders
SHA3-256: 05989bbd9bbe37fdf42df917146eb1c7b4e956caa36803724290b40fb1deb514
User & Date: atomicules@lavabit.com 2012-12-10 09:47:33
Context
2012-12-10
10:02
Remove spurious spaces check-in: adf34078f1 user: atomicules@lavabit.com tags: master, trunk
09:47
Use sublists in PWman to match groups in Lastpass.

I hadn't realised PWman supports sublists (groups), therefore can match
the grouping structure used in Lastpass.

- Now reads in CSV file to hashtable. Since CSV file is not ordered by
group, using a hashtable means we can loop through and create a key
for a group if it doesn't exists, or collate entries against a
existing group/key.
- Writing out hasn't changed much. Loops through the keys of the hash
table and loops within each key/group as well. check-in: 05989bbd9b user: atomicules@lavabit.com tags: master, trunk

09:40
Capitalise name. check-in: 35b06b14a8 user: atomicules@lavabit.com tags: master, trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to lastpass2pwman.lisp.

8
9
10
11
12
13
14
15







16
17
18

19






20
21
22
23
24
25
26
27


28
29
30
31
32
33
34
(ql:quickload "xmls")

;Note to self: Start with 2nd *posix-argv* as first is always /path/to/sbcl, etc.
;gpgid to encrypt file with
(defparameter gpgid (second *posix-argv*))
;Check for supplied filename, otherwise assume called lastpass.csv
(defparameter infile (if (null (third *posix-argv*)) "lastpass.csv" (third *posix-argv*)))
;read the lastpass file and convert to PWman format







(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>"))
;Move original file to backup
(rename-file (concatenate 'string (sb-unix::posix-getenv "HOME") "/.pwman.db") (concatenate 'string (sb-unix::posix-getenv "HOME") "/.pwman.db.bak")) 
;gpg encrpyt the file
(let ((proc (sb-ext:run-program "gpg" (list "-r" gpgid "-o" (concatenate 'string (sb-unix::posix-getenv "HOME") "/.pwman.db") "-e" "pwman.txt") :search :environment)))
	(if (= 0 (sb-ext:process-exit-code proc))
		;If that was successful, then delete the un-encrypted files







|
>
>
>
>
>
>
>


|
>
|
>
>
>
>
>
>
|
|
|
|
|
|
|
|
>
>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
(ql:quickload "xmls")

;Note to self: Start with 2nd *posix-argv* as first is always /path/to/sbcl, etc.
;gpgid to encrypt file with
(defparameter gpgid (second *posix-argv*))
;Check for supplied filename, otherwise assume called lastpass.csv
(defparameter infile (if (null (third *posix-argv*)) "lastpass.csv" (third *posix-argv*)))
;read the lastpass file and build up hash for each group, then write lists at the end.
(defparameter *lastpass* (make-hash-table))
(csv-parser:map-csv-file infile
	(lambda (ln)
		(if (gethash (read-from-string (substitute #\- #\Space (sixth ln))) *lastpass*) ;Group
			;Note, without (intern (string-upcase or (read-from-string keys aren't set properly and something bizarre happens.
			(setf (gethash (read-from-string (substitute #\- #\Space (sixth ln))) *lastpass*) (append (gethash (read-from-string (substitute #\- #\Space (sixth ln))) *lastpass*) (list ln))) ;append key
			(setf (gethash (read-from-string (substitute #\- #\Space (sixth ln))) *lastpass*) (list ln)))) :skip-lines 1) ;create key
(with-open-file (stream "pwman.txt" :direction :output :if-exists :supersede)
	(format stream "<?xml version=\"1.0\"?><PWMan_PasswordList version=\"3\"><PwList name=\"Main\">")
	;For each key in hash
	(with-hash-table-iterator (group *lastpass*)
		(loop
			(multiple-value-bind (returned? key value) (group)
			(if returned? 
				(progn
					(format stream "<PwList name=\"~a\">" key)	
					;Then loop through each entry in value
					(loop for entry in value
						  do (format stream
								"<PwItem><name>~a</name><host>~a</host><user>~a</user><passwd>~a</passwd><launch></launch></PwItem>"
								(xmls:toxml (fifth entry))
								(xmls:toxml (first entry))
								(xmls:toxml (second entry))
								(if (null (third entry)) ;Secure Notes have no password 
									(xmls:toxml (fourth entry)) ;Use extra field if Secure Note
									(xmls:toxml (third entry)))))
					(format stream "</PwList>"))
				(return)))))
	(format stream "</PwList></PWMan_PasswordList>"))
;Move original file to backup
(rename-file (concatenate 'string (sb-unix::posix-getenv "HOME") "/.pwman.db") (concatenate 'string (sb-unix::posix-getenv "HOME") "/.pwman.db.bak")) 
;gpg encrpyt the file
(let ((proc (sb-ext:run-program "gpg" (list "-r" gpgid "-o" (concatenate 'string (sb-unix::posix-getenv "HOME") "/.pwman.db") "-e" "pwman.txt") :search :environment)))
	(if (= 0 (sb-ext:process-exit-code proc))
		;If that was successful, then delete the un-encrypted files