1
2
3
4
5
6
7
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2012 Juhamatti Niemelä <iiska@iki.fi>. All Rights Reserved.
# Copyright (C) 2014 Diggory Hardy <diggory.hardy@gmail.com>. All Rights Reserved.
# This file is licensed under the GPLv2+. Please see COPYING for more information.
import sys
import re
from subprocess import Popen, PIPE
from xml.etree import ElementTree
HEAD = '/passwords/'
def insert_data(path,text):
""" Insert data into the password store.
(1) removes HEAD from path
(2) ensures text ends with a new line and encodes in UTF-8
(3) inserts
"""
global HEAD
if path.startswith(HEAD):
path = path[len(HEAD):]
if not text.endswith('\n'):
text = text + '\n'
text = text.encode('utf8')
#print "Import: " + path + ": " + text
proc = Popen(['pass', 'insert', '--multiline', '--force', path],
stdin=PIPE, stdout=PIPE)
proc.communicate(text)
proc.wait()
def space_to_camelcase(value):
output = ""
first_word_passed = False
for word in value.split(" "):
if not word:
output += "_"
continue
if first_word_passed:
output += word.capitalize()
else:
output += word.lower()
first_word_passed = True
return output
def cleanTitle(title):
# make the title more command line friendly
title = re.sub("(\\|\||\(|\)|/)", "-", title)
title = re.sub("-$", "", title)
title = re.sub("\@", "At", title)
title = re.sub("'", "", title)
return title
def path_for(element, path=''):
""" Generate path name from elements title and current path """
title = cleanTitle(space_to_camelcase(element.attrib['name']))
return '/'.join([path, title])
def unexpected(element, path):
print "Unexpected element: " + path + '/' + element.tag + "\tAttributes: " + str(element.attrib)
def import_map(element, path):
npath = path_for(element, path)
nEntries = 0
text = 'Map'
for child in element:
if child.tag == 'mapentry':
name = child.attrib['name']
text = text + '\n\n' + name + '\n' + child.text
nEntries += 1
for child2 in child:
unexpected(child, path_for(child, npath))
else:
unexpected(child, npath)
insert_data(npath, text)
print "Map " + npath + " [" + str(nEntries) + " entries]"
def import_password(element, path=''):
""" Import new password entry to password-store using pass insert
command """
npath = path_for(element, path)
text = element.text
if text == None:
print "Password " + npath + ": no text"
text = ""
insert_data(npath, text)
for child in element:
unexpected(child, npath)
def import_folder(element, path=''):
""" Import all entries and folders from given folder """
npath = path_for(element, path)
print "Importing folder " + npath
nPasswords = 0
for child in element:
if child.tag == 'folder':
import_folder(child, npath)
elif child.tag == 'password':
import_password(child, npath)
nPasswords += 1
elif child.tag == 'map':
import_map(child, npath)
else:
unexpected(child, npath)
if nPasswords > 0:
print "[" + str(nPasswords) + " passwords]"
def main(xml_file):
""" Parse XML entries from a KWallet """
element = ElementTree.parse(xml_file).getroot()
assert element.tag == 'wallet'
import_folder(element)
if __name__ == '__main__':
main(sys.argv[1])
|