OI Safe Importer
Mark Feit
mfeit+passwordstore at notonthe.net
Sat Jun 12 12:59:34 UTC 2021
Attached is a Python program that imports CSV files exported by OI Safe
for the contrib/importers directory.
Enjoy.
--Mark
-------------- next part --------------
#!/usr/bin/env python3
'''
Import an OI Safe-exported CSV to pass
See 'oisafe2pass --help' for usage.
Entry format:
<password> Empty if not present
User: <user> Not provided if not present
Site: <site> Not provided if not present
<notes> Not provided if not present
Copyright 2021 Mark Feit <mfeit+pass at notonthe.net>. All Rights
Reserved. This file is licensed under the GPLv2+. Please see COPYING
for more information.
'''
import csv
import argparse
import subprocess
import sys
def run_program(args, stdin=None):
'''
Run a program from args, provide stdin
Returns (status, stdout, stderr)
'''
try:
proc = subprocess.Popen(args,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
output, error = proc.communicate(stdin.encode('utf8')
if stdin is not None else '')
proc.wait()
return proc.returncode, output, error
except Exception as ex:
return 1, None, str(ex)
def import_record(record, dry_run=False, verbose=False):
'''
Import a single record as inhaled by the CSV module
'''
(category, description, site, user, password, notes, _edited) = record
path = '/'.join([
category.replace('/', '_'),
description.replace('/', '_')
])
if path in [ '', '/' ]:
print('Skipping record missing path and description', file=sys.stderr)
return
lines = [password or '']
if len(user):
lines.append('{:6s}{}'.format('User:', user))
if len(site):
lines.append('{:6s}{}'.format('Site:', site))
if notes:
lines.append('')
lines.append(notes)
# This forces a newline at the end
lines.append('')
args = ['pass', 'insert', '--multiline', '--force', path]
content = '\n'.join(lines)
if dry_run:
print(' '.join(args))
print(content)
print()
else:
if verbose:
print("Inserting {}".format(path))
status, stdout, stderr = run_program(args, stdin=content)
if status != 0:
print('Inserting {} failed:\n{}'.format(path, stderr), file=sys.stderr)
exit(1)
#
# Main Program
#
parser = argparse.ArgumentParser(description='Import a CSV exported from OI Safe')
parser.add_argument('infile', nargs='?',
help='Input file (stdin if not provided)')
parser.add_argument('--dry-run', dest='dry_run', action='store_true', default=False,
help='Print commands and content to stdout')
parser.add_argument('--verbose', dest='verbose', action='store_true', default=False,
help='Show progress on stdout')
args = parser.parse_args()
try:
if args.infile is None:
raise IndexError()
input_file = open(args.infile, 'r')
except IndexError:
input_file = sys.stdin
first = True
for line in csv.reader(input_file, dialect='excel'):
if first:
# First line contains headers
first = False
continue
import_record(line, dry_run=args.dry_run, verbose=args.verbose)
exit(0)
More information about the Password-Store
mailing list