Skip to content

Instantly share code, notes, and snippets.

@CookedApps
Created August 5, 2019 20:27
Show Gist options
  • Select an option

  • Save CookedApps/b5be361088b9b850739abde440101c10 to your computer and use it in GitHub Desktop.

Select an option

Save CookedApps/b5be361088b9b850739abde440101c10 to your computer and use it in GitHub Desktop.
Python script for importing a SafeInCloud XML export to pass (the unix password manager)
"""
Import a SafeInCloud XML export to pass.
Created by Sandro Wahl on 05.08.2019
"""
import sys
import re
from subprocess import Popen, PIPE
from xml.etree import ElementTree
TYPES = ["login", "password", "email", "pin", "text"]
def insert_data(path, text):
"""
Insert data into the password store.
(1) ensures text ends with a new line and encodes in UTF-8
(2) inserts
"""
if not text.endswith('\n'):
text = text + '\n'
text = text.encode('utf8')
print("Inserting {}".format(path))
proc = Popen(['pass', 'insert', '--multiline', '--force', path], stdin=PIPE, stdout=PIPE)
proc.communicate(text)
proc.wait()
def clean_string(value):
"""
Make the string more commandline friendly.
"""
value = value.strip()
value = '_'.join(value.split())
value = re.sub("(\\|\||\(|\)|/|\"|')", "", value)
value = re.sub("\@", "At", value)
value = re.sub("-", "_", value)
value = '_'.join(value.split('_'))
return value
def parse_database(element):
cards = 0
for card in element.findall("card"):
if is_not(card, "deleted") and is_not(card, "template"):
parse_card(card)
cards += 1
print("Imported {} cards".format(cards))
def is_not(element, attrib):
return (attrib not in element.attrib) or (attrib in element.attrib and element.attrib[attrib] == "false")
def parse_card(element):
path = clean_string(element.attrib["title"])
for field in element.findall("field"):
parse_field(field, path)
def parse_field(element, path):
if element.attrib["type"] in TYPES:
path += "/"
path += clean_string(element.attrib["name"])
insert_data(path, element.text)
def main(xml_file):
""" Parse XML entries from a SafeInCloud """
element = ElementTree.parse(xml_file).getroot()
assert element.tag == 'database'
parse_database(element)
if __name__ == '__main__':
main(sys.argv[1])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment