diff --git a/README.md b/README.md index 10047fb..3cc8e71 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,66 @@ Needs [python-gnupg](https://pypi.python.org/pypi/python-gnupg). Run with path to password store as argument. -The csv is written to `pass.csv`. The format for KeePassXC importer is: +There are two ways to export CSV data: -`Group(/),Title,User,Password,URL,Notes` +1. The format for the KeePass Generic CSV Importer: -Where 'Password' is the first line of the entry in `pass` and 'Notes' are all -subsequent lines. '\\' should not be interpreted as an escape character. + Group(/),Title,Password,Notes + + Where 'Password' is the first line of the entry in `pass` and 'Notes' are all + subsequent lines. '\\' should not be interpreted as an escape character. + + To enable, set `KPX_FORMAT=False` in `pass2csv.py` + +2. The format for the KeePassXC Importer: + + Group(/),Title,Login,Password,URL,Notes + + Where 'Password' is the first line of the entry in `pass`, 'User' is configured + with `LOGIN_FIELDS`, URL is extracted if `GET_URL` is set, and 'Notes' contains + any other fields that do not match `EXCLUDE_ROWS`. + + To enable, set `KPX_FORMAT=True` and configure the variables mentioned above in + `pass2csv.py`. + + 'User' field is chosen by searching for the first field with a name in + LOGIN_FIELDS. Once the field is found, the login is set and the field is + removed from notes. + +### Example KeePassXC Import +- Variable definitions (`pass2csv.py`) + + KPX_FORMAT=True + + LOGIN_FIELDS=['username', 'login', 'email'] + GET_URL=True + EXCLUDE_ROWS=['^---$'] + +- Password entry (`sites/example`) + + password123 + --- + username: user_name + email: user@example.com + url: example.com + some_note + +- Output CSV row (formatted) + + sites, example, user_name, password123, example.com, "email: user@example.com\nsome_note" + +- `user_name` was chosen because `username` was the first filled entry in + `LOGIN_FIELDS`. +- Both logn and URL fields were excluded from the notes field because they were used +in another field. +- `---` Was not included in the notes field because it was matched in `EXCLUDE_ROWS`. + +### Example KeePass Generic CSV Importer +- Variable definitions (`pass2csv.py`) + + KPX_FORMAT=False + +- Password entry: Same as above +- Output CSV row (formatted) + + sites, example, password123, "---\nusername: user_name\nemail: user@example.com\nurl: example.com\nsome_note" diff --git a/pass2csv.py b/pass2csv.py index da67ee5..f2a50cd 100644 --- a/pass2csv.py +++ b/pass2csv.py @@ -9,12 +9,19 @@ import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) -# A list of possible fields (in order) that could be converted to login fields -LOGIN_FIELDS=['login', 'user', 'username', 'email'] -# Set to True to extract url fields -GET_URL=True -# A regular expression list of lines that should be excluded from the notes field -EXCLUDE_ROWS=['^---$', '^autotype ?: ?'] +# Set to True to allow for alternate password csv to be created +# See README for differences +KPX_FORMAT=True + +if KPX_FORMAT: + # A list of possible fields (in order) that could be converted to login fields + LOGIN_FIELDS=['login', 'user', 'username', 'email'] + # Set to True to extract url fields + GET_URL=True + # A regular expression list of lines that should be excluded from the notes field + EXCLUDE_ROWS=['^---$', '^autotype ?: ?'] + +logger.info("Using KPX format: %s", KPX_FORMAT) def traverse(path): for root, dirs, files in os.walk(path): @@ -75,10 +82,16 @@ def parse(basepath, path, data): group = os.path.dirname(os.path.os.path.relpath(path, basepath)) split_data = data.split('\n', maxsplit=1) password = split_data[0] + # Perform if/else in case there are no notes for a field notes = split_data[1] if len(split_data) > 1 else "" - user, url, notes = getMetadata(notes) - logger.info("Processed %s" % (name,)) - return [group, name, user, password, url, notes] + logger.info("Processing %s" % (name,)) + if KPX_FORMAT: + # We are using the advanced format; try extracting user and url + user, url, notes = getMetadata(notes) + return [group, name, user, password, url, notes] + else: + # We are not using KPX format; just use notes + return [group, name, password, notes] def main(path):