diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d577305 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.vscode +export.json +export.csv \ No newline at end of file diff --git a/README.md b/README.md index 1e6b398..717522b 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ # psono-json-to-bitwarden-csv -Script to convert psono exports (JSON) to bitwarden import compatible CSV \ No newline at end of file +Script to convert psono exports (JSON) to bitwarden import compatible CSV + +usage: + convert.php export.json + +This will export a file called export.csv that you can import into Bitwarden as a generic CSV. \ No newline at end of file diff --git a/convert.php b/convert.php new file mode 100644 index 0000000..c65015c --- /dev/null +++ b/convert.php @@ -0,0 +1,81 @@ +' . PHP_EOL; + exit; +} + +/** + * Recursively get all items into a single array. + * + * @param array $data - parent data + * @param array $items - List of items + * + * @return array + */ +function recursivelyGetItems(array $data, array &$items = []): array +{ + if (array_key_exists('items', $data)) { + $items = array_merge($items, $data['items']); + } + + // If sub folder.. call again! + if (array_key_exists('folders', $data)) { + foreach ($data['folders'] as $folder) { + if (array_key_exists('items', $folder)) { + foreach ($folder['items'] as $subItem) { + $items[] = array_merge(['folder' => $folder['name']], $subItem); + } + } + } + } + return $items; +} + +// Open source JSON and decode into array +$rawData = file_get_contents($argv[1]); +$data = json_decode($rawData, true); +unset($rawData); +if (!is_array($data)) { + echo 'Error decoding JSON.' . PHP_EOL; + exit; +} + +$bitwardenHeaders = [ + 'folder', + 'favorite', + 'type', + 'name', + 'notes', + 'fields', + 'login_uri', + 'login_username', + 'login_password', + 'login_totp' +]; + +// Open new file for writing +$fp = fopen('export.csv', 'w'); +fputcsv($fp, $bitwardenHeaders); + +// Get items from nested JSON array +$items = recursivelyGetItems($data); + +foreach ($items as $item) { + $mapper = [ + $item['folder'] ?? '', + '', + 'login', + $item['name'], + ($item['note_notes'] ?? ($item['website_password_notes'] ?? '')), + '', + $item['website_password_url'] ?? '', + $item['website_password_username'] ?? '', + $item['login_password_password'] ?? '', + '' + ]; + + fputcsv($fp, $mapper); +} + +fclose($fp);