Update for pass->bitwarden CSV

This commit is contained in:
Daniel 2024-02-03 23:15:19 -05:00
parent 9cb3f40167
commit a602b8064c
3 changed files with 52 additions and 10 deletions

1
.gitignore vendored
View file

@ -5,3 +5,4 @@ __pycache__/
build/ build/
dist/ dist/
venv/ venv/
*.csv

View file

@ -1,6 +1,7 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) The pass2csv authors Copyright (c) The pass2csv authors
Copyright (c) 2024, Daniel Ponte
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View file

@ -7,6 +7,8 @@ import sys
import gnupg import gnupg
from collections import OrderedDict
__version__ = '1.1.1' __version__ = '1.1.1'
@ -74,21 +76,59 @@ def set_data(entry, data, exclude, get_fields, get_lines):
entry['notes'] = '\n'.join(final_tail).strip() entry['notes'] = '\n'.join(final_tail).strip()
bwFieldSet = OrderedDict({
'folder': 'group',
'favorite': None,
'type': 'type',
'name': 'title',
'notes': 'notes',
'fields': '__fields',
'reprompt': 'reprompt',
'login_uri': 'url',
'login_username': 'username',
'login_password': 'password',
'login_totp': 'otp'
})
header = [key for key, value in bwFieldSet.items()]
def write(file, entries, get_fields, get_lines): def write(file, entries, get_fields, get_lines):
get_field_names = set(x[0] for x in get_fields) get_field_names = set(x[0] for x in get_fields)
get_line_names = set(x[0] for x in get_lines) get_line_names = set(x[0] for x in get_lines)
field_names = get_field_names | get_line_names field_names = get_field_names | get_line_names
header = ["Group(/)", "Title", "Password", *field_names, "Notes"]
csvw = csv.writer(file, dialect='unix') csvw = csv.writer(file, dialect='unix')
stderr(f"\nWriting data to {file.name}\n") stderr(f"\nWriting data to {file.name}\n")
csvw.writerow(header) csvw.writerow(header)
for entry in entries: for entry in entries:
fields = [entry['fields'].get(name) for name in field_names] if entry['title'] == 'ChromePasswords':
columns = [ continue
entry['group'], entry['title'], entry['password'], columns = []
*fields, fieldIndex = -1
entry['notes'] for bwf, pf in bwFieldSet.items():
] if pf is None:
columns.append('')
elif pf == 'type':
columns.append('login')
elif pf == '__fields':
columns.append('')
fieldIndex = len(columns) - 1
pass
elif pf in ['group', 'title', 'notes', 'password']:
try:
columns.append(entry[pf])
except KeyError:
columns.append('')
else:
try:
columns.append(entry['fields'][pf])
del entry['fields'][pf]
except KeyError:
columns.append('')
# get remaining fields
fields = ""
for fKey, value in entry['fields'].items():
fields += "{}: {}\n".format(fKey, value)
columns[fieldIndex] = fields.rstrip('\n')
csvw.writerow(columns) csvw.writerow(columns)
@ -202,7 +242,7 @@ def parse_args(args=None):
metavar='pattern', metavar='pattern',
action='append', action='append',
type=str, type=str,
default=[], default=['^autotype:'],
help=( help=(
"regexp for lines which should not be exported, can be specified" "regexp for lines which should not be exported, can be specified"
" multiple times" " multiple times"
@ -216,7 +256,7 @@ def parse_args(args=None):
action='append', action='append',
nargs=2, nargs=2,
type=str, type=str,
default=[], default=[['pin', '^(phone)?pin: '], ['username', '^(user(name)?|login): ']],
help=( help=(
"a name and a regexp, the part of the line matching the regexp" "a name and a regexp, the part of the line matching the regexp"
" will be removed and the remaining line will be added to a field" " will be removed and the remaining line will be added to a field"
@ -232,7 +272,7 @@ def parse_args(args=None):
action='append', action='append',
nargs=2, nargs=2,
type=str, type=str,
default=[], default=[['otp', 'otpauth://'], ['url', 'https?://']],
help=( help=(
"a name and a regexp for which all lines that match are included" "a name and a regexp for which all lines that match are included"
" in a field with the chosen name" " in a field with the chosen name"