From 74ddd9b8e30cb871573cfe571550fc26fbdc5024 Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Tue, 10 Jul 2018 17:51:55 -0400 Subject: [PATCH] keepass2 xml importer --- src/importers/keepass2XmlImporter.ts | 86 ++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 src/importers/keepass2XmlImporter.ts diff --git a/src/importers/keepass2XmlImporter.ts b/src/importers/keepass2XmlImporter.ts new file mode 100644 index 0000000000..46d566713e --- /dev/null +++ b/src/importers/keepass2XmlImporter.ts @@ -0,0 +1,86 @@ +import { BaseImporter } from './baseImporter'; +import { Importer } from './importer'; + +import { ImportResult } from '../models/domain/importResult'; + +import { FolderView } from '../models/view/folderView'; + +export class KeePass2XmlImporter extends BaseImporter implements Importer { + result = new ImportResult(); + + parse(data: string): ImportResult { + const doc = this.parseXml(data); + if (doc == null) { + this.result.success = false; + return this.result; + } + + const rootGroup = doc.querySelector('KeePassFile > Root > Group'); + if (rootGroup == null) { + this.result.errorMessage = 'Missing `KeePassFile > Root > Group` node.'; + this.result.success = false; + return this.result; + } + + this.traverse(rootGroup, true, ''); + + this.result.success = true; + return this.result; + } + + traverse(node: Element, isRootNode: boolean, groupPrefixName: string) { + const folderIndex = this.result.folders.length; + let groupName = groupPrefixName; + + if (!isRootNode) { + if (groupName !== '') { + groupName += ' > '; + } + const nameEl = this.querySelectorDirectChild(node, 'Name'); + groupName += nameEl == null ? '-' : nameEl.textContent; + const folder = new FolderView(); + folder.name = groupName; + this.result.folders.push(folder); + } + + Array.from(this.querySelectorAllDirectChild(node, 'Entry')).forEach((entry) => { + const cipherIndex = this.result.ciphers.length; + + const cipher = this.initLoginCipher(); + Array.from(this.querySelectorAllDirectChild(entry, 'String')).forEach((entryString) => { + const valueEl = this.querySelectorDirectChild(entryString, 'Value'); + const value = valueEl != null ? valueEl.textContent : null; + if (this.isNullOrWhitespace(value)) { + return; + } + const keyEl = this.querySelectorDirectChild(entryString, 'Key'); + const key = keyEl != null ? keyEl.textContent : null; + + if (key === 'URL') { + cipher.login.uris = this.makeUriArray(value); + } else if (key === 'UserName') { + cipher.login.username = value; + } else if (key === 'Password') { + cipher.login.password = value; + } else if (key === 'Title') { + cipher.name = value; + } else if (key === 'Notes') { + cipher.notes += (value + '\n'); + } else { + this.processKvp(cipher, key, value); + } + }); + + this.cleanupCipher(cipher); + this.result.ciphers.push(cipher); + + if (!isRootNode) { + this.result.folderRelationships.push([cipherIndex, folderIndex]); + } + }); + + Array.from(this.querySelectorAllDirectChild(node, 'Group')).forEach((group) => { + this.traverse(group, false, groupName); + }); + } +}