From bd8cbd12331cf965c54645a5397e0acfe90b4c96 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Tue, 6 May 2014 16:10:32 +0200 Subject: Import new kwallet importer. --- contrib/importers/kwallet2pass.py | 121 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100755 contrib/importers/kwallet2pass.py diff --git a/contrib/importers/kwallet2pass.py b/contrib/importers/kwallet2pass.py new file mode 100755 index 0000000..2a9034c --- /dev/null +++ b/contrib/importers/kwallet2pass.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012 Juhamatti Niemelä . All Rights Reserved. +# Copyright (C) 2014 Diggory Hardy . 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]) -- cgit v1.2.3-59-g8ed1b