Migrating Jabberd to Wildfire

Does anyone have some script for converting the Jabberd /var/spool/jabberd rosters to the Wildfire XML import format?


In the end I wrote my own script. It’‘s probably missing some stuff and has no comments, but I’‘ll post it here in case it’‘s useful for anyone else. I don’‘t see how to quote code in this forum software, so I’'ll have to leave the code formatted.



  1. Migration script for jabberd1.4 to Wildfire.

  1. Copyright © 2006 Mario Camou

  1. This script converts a jabberd1.4 spool directory into an import file for Wildfire. It migrates only the users

  2. and rosters, not the offline messages, VCards, etc. The import file gets sent to stdout.

  1. Revision history:

  2. 2006-12-06 - Initial release

require “rexml/document”

if not ARGV[0] then

$stderr.puts(’‘ERROR: You must specify the domain (server id) to use.’’)



domain = ARGV[0]

if not File.stat(domain).directory? then

$stderr.puts(’‘ERROR: You must be in the spool directory’’)



outdoc = REXML::Document.new


Dir.foreach(domain) do |file|

username = file.clone.gsub!(/.xml$/, ‘’’’)

  1. Note: jabberd 1.4 doesn’‘t store pending unsubs, so askstatus = 1 isn’'t possible
  2. TODO: Do we get recvstatus from anywhere? Should be:
  3. -1: There are no subscriptions that have been received but not presented to the user.
  4. 1: The server has received a subscribe request, but has not forwarded it to the user.
  5. 2: The server has received an unsubscribe request, but has not forwarded it to the user.
  6. Missing tags:
  7. jabber:iq:last query’’
  8. jabber:x:offline foo’’
  9. vcard-temp vCard
  10. Other arbitrary data:
  11. Private (with attribute j_private_flag=’‘1’’) or non-private
    filename = “#/#” if not File.stat(filename).directory? and not filename.include?(’’%’’) and file =~ /^[a-zA-Z0-9]/ then
    $stderr.puts "Migrating #"
    pass_elem = email_elem = name_elem = crdate_elem = moddate_elem = roster_elem = nil user_elem = outdoc.root.add_element(’‘User’’)
    username_elem = user_elem.add_element(’‘Username’’)
    username_elem.add_text(username) file = File.new(filename)
    doc = REXML::Document.new(file)
    doc.root.elements.each do |element|
    qname = element.name
    qname = “#{element.namespace} #” if element.namespace
    case qname
    when ‘‘jabber:iq:browse user’‘
    name_elem = REXML::Element.new(’‘Name’’)
    when ‘‘jabber:iq:auth password’‘
    pass_elem = REXML::Element.new(’‘Password’’)
    pass_elem.add_text(element.text) when ‘‘jabber:iq:roster query’‘
    roster_elem = REXML::Element.new(’‘Roster’’) element.elements.each(’‘item’’) do |item|
    item_jid = item.attributes[’‘jid’’]
    if item_jid =~ /^[a-zA-Z0-9]/ and not (item_jid.include?(’’%’’) or item_jid.include?(’’@.’’) or item_jid =~ /(yahoo|aim|icq|msn).messenger.cie/ or item_jid =~ /.$/) then
    case item.attributes[’‘subscription’’]
    when ‘‘none’‘
    substatus = 0
    when ‘‘to’‘
    substatus = 1
    when ‘‘from’‘
    substatus = 2
    when ‘‘both’‘
    substatus = 3
    end if (item.attributes[’‘ask’’] == ‘‘subscribe’’) then
    askstatus = 0
    askstatus = -1
    end recvstatus = -1 item_name = item.attributes[’‘name’’]
    item_name = item_jid unless item_name item_elem = roster_elem.add_element(’‘Item’’, {’‘jid’’ => item_jid,
    ’‘askstatus’’ => askstatus,
    ’‘recvstatus’’ => recvstatus,
    ’‘substatus’’ => substatus,
    ’‘name’’ => item_name}) group_added = nil
    item.elements.each(’‘group’’) do |group|
    if group.text then
    group_added = 1
    end item_elem.add_element(’‘Group’’) unless group_added
    end end
    end pass_elem = REXML::Element.new(’‘Password’’) unless pass_elem
    user_elem.add_element(pass_elem) email_elem = REXML::Element.new(’‘Email’’)
    user_elem.add_element(email_elem) name_elem = REXML::Element.new(’‘Name’’) unless name_elem
    user_elem.add_element(name_elem) crdate_elem = REXML::Element.new(’‘CreationDate’’)
    user_elem.add_element(crdate_elem) moddate_elem = REXML::Element.new(’‘ModifiedDate’’)
    user_elem.add_element(moddate_elem) roster_elem = REXML::Element.new(’‘Roster’’) unless roster_elem
    end $stderr.puts ‘‘Writing out XML file’’ puts outdoc $stderr.puts “Finished migrating #”