password-store

Simple password manager using gpg and ordinary unix directories
git clone https://git.zx2c4.com/password-store
Log | Files | Refs | README | LICENSE

keepassx2pass.py (2711B)


      1 #!/usr/bin/env python3
      2 #
      3 # Copyright (C) 2012 Juhamatti Niemelä <iiska@iki.fi>. All Rights Reserved.
      4 # This file is licensed under the GPLv2+. Please see COPYING for more information.
      5 #
      6 # Usage ./keepassx2pass.py export.xml
      7 
      8 import sys
      9 import re
     10 
     11 from subprocess import Popen, PIPE
     12 from xml.etree import ElementTree
     13 
     14 def space_to_camelcase(value):
     15     output = ""
     16     first_word_passed = False
     17     for word in value.split(" "):
     18         if not word:
     19             output += "_"
     20             continue
     21         if first_word_passed:
     22             output += word.capitalize()
     23         else:
     24             output += word.lower()
     25         first_word_passed = True
     26     return output
     27 
     28 def cleanTitle(title):
     29     # make the title more command line friendly
     30     title = re.sub("(\\|\||\(|\)|/)", "-", title)
     31     title = re.sub("-$", "", title)
     32     title = re.sub("\@", "At", title)
     33     title = re.sub("'", "", title)
     34     return title
     35 
     36 def path_for(element, path=''):
     37     """ Generate path name from elements title and current path """
     38     title_text = element.find('title').text
     39     if title_text is None:
     40         title_text = ''
     41     title = cleanTitle(space_to_camelcase(title_text))
     42     return '/'.join([path, title])
     43 
     44 def password_data(element):
     45     """ Return password data and additional info if available from
     46     password entry element. """
     47     passwd = element.find('password').text
     48     ret = (passwd + "\n") if passwd else "\n"
     49     for field in ['username', 'url', 'comment']:
     50         fel = element.find(field)
     51         children = [(e.text or '') + (e.tail or '') for e in list(fel)]
     52         if len(children) > 0:
     53             children.insert(0, '')
     54         text = (fel.text or '') + "\n".join(children)
     55         if len(text) > 0:
     56             ret = "%s%s: %s\n" % (ret, fel.tag, text)
     57     return ret
     58 
     59 def import_entry(element, path=''):
     60     """ Import new password entry to password-store using pass insert
     61     command """
     62     print("Importing " + path_for(element, path))
     63     proc = Popen(['pass', 'insert', '--multiline', '--force',
     64                   path_for(element, path)],
     65                   stdin=PIPE, stdout=PIPE)
     66     proc.communicate(password_data(element).encode())
     67     proc.wait()
     68 
     69 def import_group(element, path=''):
     70     """ Import all entries and sub-groups from given group """
     71     npath = path_for(element, path)
     72     for group in element.findall('group'):
     73         import_group(group, npath)
     74     for entry in element.findall('entry'):
     75         import_entry(entry, npath)
     76 
     77 
     78 def main(xml_file):
     79     """ Parse given KeepassX XML file and import password groups from it """
     80     for group in ElementTree.parse(xml_file).findall('group'):
     81         import_group(group)
     82 
     83 if __name__ == '__main__':
     84     main(sys.argv[1])