def import_data(self, input, password): " Import data from a file into the entry store" entrystore = data.EntryStore() # Maintain a hash of folder names to folder entries so we # can use each category encountered to create a new folder # by that name, or use an existing one if we've already # created it: folders = {} for line in input.splitlines()[1:]: f_csv = csv.reader([line.decode()]) for row in f_csv: # Raise FormatError if we don't have all 9 fields # KeepasXC 2.5 to 2.6.1 has 6 fields # KeepasXC 2.6.2 has 10 fields if len(row) != 6 and len(row) != 10: raise base.FormatError # If URL is present create WebEntry if row[4]: new_entry = entry.WebEntry() new_entry[entry.URLField] = row[4] else: new_entry = entry.GenericEntry() new_entry.name = row[1] new_entry[entry.UsernameField] = row[2] new_entry[entry.PasswordField] = row[3] new_entry.notes = row[5] # TODO As Last modified and creationtime are from newer # keepassXC releases, set to current time for now new_entry.updated = time.time() # Create and/or add to folder # TODO split folder name and correctly group them if row[0] in folders: parent = folders[row[0]] else: folder = entry.FolderEntry() folder.name = row[0] parent = entrystore.add_entry(folder) folders[row[0]] = parent # Add the entry entrystore.add_entry(new_entry, parent) return entrystore
def import_data(self, input, password): " Import data from a file into the entry store" # Replace any vertical tabs with spaces, SplashID seems to use # these to seperate lines within a Notes field: if input.count(b'\x0b'): input = input.replace(b'\x0b', b' ') entrystore = data.EntryStore() # Maintain a hash of folder names to folder entries so we # can use each category encountered to create a new folder # by that name, or use an existing one if we've already # created it: folders = {} for line in input.splitlines(): for row in csv.reader([line.decode()]): # Raise FormatError if we don't have all 9 fields if len(row) != 9: raise base.FormatError # Import the entry e = entry.GenericEntry() e.name = row[1] e.description = " / ".join( [desc.strip() for desc in row[5:8] if desc.strip() != ""]) e.updated = time.time() e[entry.UsernameField] = row[2] e[entry.PasswordField] = row[3] e[entry.HostnameField] = row[4] # Create and/or add to folder based on category: if row[8] in folders: parent = folders[category] else: folder = entry.FolderEntry() folder.name = category parent = entrystore.add_entry(new_folder) folders[row[8]] = parent # Add the entry entrystore.add_entry(e, parent) return entrystore
def __setup_group(self, entrystore, groupmap, group): "Sets up a group folder, or returns an existing one" if group in (None, ""): return None if group in groupmap: return groupmap[group] if "." in group: parent, groupname = group.rsplit(".", 1) parentiter = self.__setup_group(entrystore, groupmap, parent) else: groupname = group parentiter = None e = entry.FolderEntry() e.name = groupname iter = entrystore.add_entry(e, parentiter) groupmap[group] = iter return iter
def import_data(self, input, password): "Imports data from a data stream to an entrystore" plaintext = decrypt(input, password, "GPassFile version 1.1.0") entrystore = data.EntryStore() foldermap = {} while len(plaintext) > 0: # parse data id = self.__getint(plaintext[:4]) plaintext = plaintext[4:] parentid = self.__getint(plaintext[:4]) plaintext = plaintext[4:] entrytype = self.__getstr(plaintext) plaintext = plaintext[4 + len(entrytype):] attrdata = self.__getstr(plaintext) plaintext = plaintext[4 + len(attrdata):] l, name = self.__unpackstr(attrdata) attrdata = attrdata[l:] l, desc = self.__unpackstr(attrdata) attrdata = attrdata[l:] l, ctime = self.__unpackint(attrdata) attrdata = attrdata[l:] l, mtime = self.__unpackint(attrdata) attrdata = attrdata[l:] l, expire = self.__unpackint(attrdata) attrdata = attrdata[l:] l, etime = self.__unpackint(attrdata) attrdata = attrdata[l:] if entrytype == "general": l, username = self.__unpackstr(attrdata) attrdata = attrdata[l:] l, password = self.__unpackstr(attrdata) attrdata = attrdata[l:] l, hostname = self.__unpackstr(attrdata) attrdata = attrdata[l:] else: username = password = hostname = "" # create entry if entrytype == "general": e = entry.GenericEntry() e.name = self.__normstr(name) e.description = self.__normstr(desc) e.updated = mtime e[entry.HostnameField] = self.__normstr(hostname) e[entry.UsernameField] = self.__normstr(username) e[entry.PasswordField] = self.__normstr(password) elif entrytype == "folder": e = entry.FolderEntry() e.name = self.__normstr(name) e.description = self.__normstr(desc) e.updated = mtime else: continue # add entry to entrystore if foldermap.has_key(parentid): parent = foldermap[parentid] else: parent = None iter = entrystore.add_entry(e, parent) if type(e) == entry.FolderEntry: foldermap[id] = iter return entrystore
def import_data(self, input, password): "Imports data into an entrystore" try: # check and load data self.check(input) dom = xml.dom.minidom.parseString(input.strip()) if dom.documentElement.nodeName != "FPM": raise base.FormatError # set up decryption engine, and check if password is correct keynode = dom.documentElement.getElementsByTagName("KeyInfo")[0] salt = keynode.attributes["salt"].nodeValue vstring = keynode.attributes["vstring"].nodeValue password = MD5.new(salt + password).digest() cipher = Blowfish.new(password) if self.__decrypt(cipher, vstring) != "FIGARO": raise base.PasswordError except ExpatError: raise base.FormatError except ( IndexError, KeyError ): raise base.FormatError # import entries into entrystore entrystore = data.EntryStore() folders = {} for node in dom.getElementsByTagName("PasswordItem"): parent = None e = entry.GenericEntry() for fieldnode in [ node for node in node.childNodes if node.nodeType == node.ELEMENT_NODE ]: content = self.__decrypt(cipher, util.dom_text(fieldnode)) if content == "": continue elif fieldnode.nodeName == "title": e.name = content elif fieldnode.nodeName == "user": e.get_field(entry.UsernameField).value = content elif fieldnode.nodeName == "url": e.get_field(entry.HostnameField).value = content elif fieldnode.nodeName == "password": e.get_field(entry.PasswordField).value = content elif fieldnode.nodeName == "notes": e.description = content elif fieldnode.nodeName == "category": if content in folders: parent = folders[content] else: folderentry = entry.FolderEntry() folderentry.name = content parent = entrystore.add_entry(folderentry) folders[content] = parent entrystore.add_entry(e, parent) return entrystore