aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/contrib/importers/keepassx2pass.py
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2014-03-22 12:01:52 -0600
committerJason A. Donenfeld <Jason@zx2c4.com>2014-03-22 12:03:12 -0600
commit47fed2c5d47a03fad7b91bfb890eed257e9c1b2d (patch)
tree46666ba401340524ab9c217a062c366f6e5ec818 /contrib/importers/keepassx2pass.py
parentclip: suppress kill error (diff)
downloadpassword-store-47fed2c5d47a03fad7b91bfb890eed257e9c1b2d.tar.xz
password-store-47fed2c5d47a03fad7b91bfb890eed257e9c1b2d.zip
Makefile: do not use recursion and organize
Diffstat (limited to 'contrib/importers/keepassx2pass.py')
-rwxr-xr-xcontrib/importers/keepassx2pass.py76
1 files changed, 76 insertions, 0 deletions
diff --git a/contrib/importers/keepassx2pass.py b/contrib/importers/keepassx2pass.py
new file mode 100755
index 0000000..dc4b1e5
--- /dev/null
+++ b/contrib/importers/keepassx2pass.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2012 Juhamatti Niemelä <iiska@iki.fi>. 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
+
+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.find('title').text))
+ return '/'.join([path, title])
+
+def password_data(element):
+ """ Return password data and additional info if available from
+ password entry element. """
+ passwd = element.find('password').text
+ ret = passwd + "\n" if passwd else "\n"
+ for field in ['username', 'url', 'comment']:
+ fel = element.find(field)
+ if fel.text is not None:
+ ret = "%s%s: %s\n" % (ret, fel.tag, fel.text)
+ return ret
+
+def import_entry(element, path=''):
+ """ Import new password entry to password-store using pass insert
+ command """
+ proc = Popen(['pass', 'insert', '--multiline', '--force',
+ path_for(element, path)],
+ stdin=PIPE, stdout=PIPE)
+ proc.communicate(password_data(element).encode('utf8'))
+ proc.wait()
+
+def import_group(element, path=''):
+ """ Import all entries and sub-groups from given group """
+ npath = path_for(element, path)
+ for group in element.findall('group'):
+ import_group(group, npath)
+ for entry in element.findall('entry'):
+ import_entry(entry, npath)
+
+
+def main(xml_file):
+ """ Parse given KeepassX XML file and import password groups from it """
+ with open(xml_file) as xml:
+ for group in ElementTree.XML(xml.read()).findall('group'):
+ import_group(group)
+
+if __name__ == '__main__':
+ main(sys.argv[1])