Skip to content

Instantly share code, notes, and snippets.

@schewara
Created April 30, 2014 23:01
Show Gist options
  • Save schewara/9196fd3b83b8f9cfb98d to your computer and use it in GitHub Desktop.
Save schewara/9196fd3b83b8f9cfb98d to your computer and use it in GitHub Desktop.
Conversion from Revelation XML to KeePassX XML
#!/usr/bin/env ruby
# converter.rb - Convert Revelation XML output to KeepassX input
# Copyright (c) 2008 Maxim Burgerhout
# Author: Maxim Burgerhout <[email protected]>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# To do:
# - convert Revelation items that have attached keyfiles
# - convert several other Revelation item types
## (see the list of generics down below)
# - convert KeepassX output back to Revelation XML
# - warn if Revelation XML is not convertable (items in root)
# - test some more
require "rexml/document"
include REXML
def print_usage
puts "Usage: converter.rb input_filename output_filename"
puts "input_filename: your Revelation XML export file."
puts "output_filename: newly converted XML, ready for KeepassX."
exit 1
end
if ARGV.length != 2
print_usage
end
old_filename = ARGV[0]
new_filename = ARGV[1]
old_doc = Document.new File.open(old_filename, "r")
old_root = old_doc.root
new_doc = Document.new("<!DOCTYPE KEEPASSX_DATABASE>
<database>
</database>")
new_root = new_doc.root
new_file = File.new(new_filename, "w+")
def parse_folder(old_element, new_parent)
old_element.elements.each { |e|
if e.name == "entry" and e.attributes["type"] == "folder"
entry = new_parent.add_element "group"
icon = entry.add_element "icon"
icon.text = "1"
parse_folder(e, entry)
elsif e.name == "entry" and e.attributes["type"] != "folder"
entry = new_parent.add_element "entry"
icon = entry.add_element "icon"
icon.text = "1"
expire = entry.add_element "expire"
expire.text = "Never"
parse_folder(e, entry)
else
entry = new_parent
end
if e.name == "name"
title = entry.add_element "title"
title.text = e.text
end
if e.name == "updated" and new_parent.name != "group"
lastmod_time = e.text.to_i
lastmod_time = Time.at(lastmod_time)
lastmod_time = lastmod_time.strftime("%Y-%m-%dT%H:%M:%S")
lastmod = entry.add_element "lastmod"
lastaccess = entry.add_element "lastaccess"
creation = entry.add_element "creation"
lastmod.text = lastmod_time
creation.text = lastmod_time
lastaccess.text = lastmod_time
end
if e.name == "field" and new_parent.name != "group"
case e.attributes["id"]
when "generic-username"
username = entry.add_element "username"
username.text = e.text
when "generic-password"
password = entry.add_element "password"
password.text = e.text
when "generic-hostname"
url = entry.add_element "url"
url.text = e.text
when "generic-url"
url = entry.add_element "url"
url.text = e.text
when "generic-certificate"
when "generic-code"
when "generic-database"
when "generic-domain"
when "generic-email"
when "generic-keyfile"
when "generic-location"
when "generic-pin"
when "generic-port"
end
end
if e.name == "description" and new_parent.name != "group"
desc = entry.add_element "comment"
desc.text = e.text
end
#
}
end
parse_folder(old_root, new_root)
formatter = REXML::Formatters::Pretty.new()
formatter.compact = true
formatter.write(new_doc, new_file)
@wzzrd
Copy link

wzzrd commented May 1, 2014

Hi,

Thanks for adapting this script. If you send me a pull request for wzzrd/keepass-converter, I'll merge it in the repo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment