Skip to content

Instantly share code, notes, and snippets.

@Quintus
Created October 24, 2015 14:50
Show Gist options
  • Save Quintus/fe7a2fb399a9632a131b to your computer and use it in GitHub Desktop.
Save Quintus/fe7a2fb399a9632a131b to your computer and use it in GitHub Desktop.
Convert prosody 0.9.7’s filesystem data into the PIEFXIS format defined by XEP-0227
#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
#
# prosodyconv.rb -- converts prosody rosters into PIEFXIS format as per XEP-0227.
#
# Copyright © 2015 Marvin Gülker
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
require "yaml"
require "cgi"
require "pathname"
def parse_prosody_roster(str)
# Convert Lua file structure into YAML by means of some simple substitutions
str = str.sub("return ", "").delete("[]").gsub(" =", ":").gsub(";", ",")
# Now we can easily transform it into a Ruby hash
YAML.load(str)
end
def convert_prosody_roster(str)
xml = "<query xmlns='jabber:iq:roster'>\n"
hsh = parse_prosody_roster(str)
hsh.each_pair do |jid, info|
next unless jid # Prosody version meta element is false
next if jid == "pending" # useless element?
$stderr.puts " Found contact #{jid} in roster, subscription=#{info["subscription"]}."
xml << "<item jid='#{jid}'"
xml << " name='#{info["name"]}'" if info["name"]
xml << " subscription='#{info["subscription"]}'>\n"
info["groups"].each_key do |groupname|
xml << "<group>#{groupname}</group>\n"
end
xml << "</item>\n"
end
xml << "</query>\n"
xml
end
def convert_prosody_dir(dir)
$stderr.print "Analysing '#{dir}'... "
host = CGI.unescape(dir.basename.to_s) # prosody uses CGI-escaped names with lots of % signs
$stderr.puts host
xml = "<host jid='#{host}'>\n"
Dir.glob("#{dir}/accounts/*.dat").sort.each do |accountfile|
accountfile = Pathname.new(accountfile)
username = CGI.unescape(accountfile.basename.sub_ext("").to_s)
$stderr.puts " Found user #{username}."
xml << "<user name='#{username}' password='changeme'>\n"
xml << convert_prosody_roster(File.read(dir + "roster" + accountfile.basename))
xml << "</user>\n"
end
xml << "</host>\n"
xml
end
def convert(directory)
xml = <<XML
<?xml version='1.0' encoding='UTF-8'?>
<server-data xmlns='urn:xmpp:pie:0'>
XML
Dir.glob("#{directory}/*").sort.each do |dir|
xml << convert_prosody_dir(Pathname.new(dir))
end
xml << "</server-data>\n"
xml
end
if ARGV.empty? || ARGV.include?("-h") || ARGV.include?("--help")
$stderr.puts <<HELP
prosodyconv.rb PROSODYDIR
This program takes a prosody data directory and converts all hosts,
users, and rosters found inside that directory into the PIEFXIS format
described in XEP-0227. It does not convert anything more than these
basic pieces of information, although subscription info is preserved
(but not outstanding subscription requests). Passwords for the users
cannot be preserved, because Prosody stores them as salted hashes with
no easy way to recover the plaintext password (which is good). So instead,
the passwords of all users are set to "changeme" (without the quotes).
Pass the directory to the Prosody data as an argument to this script;
no further arguments are accepted. The resulting XML is printed to
standard output.
The script prints informative progress to the standard error stream.
The script only works with prosody's default filesystem storage.
HELP
exit 0
end
$stderr.puts "prosodyconv.rb, Copyright © 2015 Marvin Gülker"
puts convert(ARGV[0])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment