#!/usr/bin/perl

use XML::Twig;
use Tie::IxHash;

my $spooldir = shift;
die "usage: $0 <spool_directory>\n\n" unless (-d $spooldir);

my $twig = XML::Twig->new();

my $output = XML::Twig::Elt->new('Openfire');
$output->set_pretty_print('indented');

opendir(DIR, $spooldir) or die "unable to open $spooldir: $!";
for my $file (readdir(DIR))
{
	next unless ($file =~ /\.xml$/);
	my $filename = $spooldir . '/' . $file;
	my ($mtime, $ctime, $username, $password, $email, $name);

	my $userxml = XML::Twig::Elt->new('User');
	my $rosterxml = XML::Twig::Elt->new('Roster');

	$name = XML::Twig::Elt->new('Name');
	$email = XML::Twig::Elt->new('Email');

	$twig->parsefile($filename);
	my $root = $twig->root;

	my @stat = stat($filename);

	$mtime = XML::Twig::Elt->new('ModifiedDate');
	$mtime->set_text($stat[9]);

	$ctime = XML::Twig::Elt->new('CreationDate');
	$ctime->set_text($stat[10]);

	for my $query ($root->children('query'))
	{
		# username/password "registration"
		if ($query->att('xmlns') eq 'jabber:iq:register')
		{
			if ($query->first_child_text('username'))
			{
				$username = XML::Twig::Elt->new('Username');
				$username->set_text($query->first_child_text('username'));
				$name->set_text($query->first_child_text('username'));
			}
			if ($query->first_child_text('password'))
			{
				$password = XML::Twig::Elt->new('Password');
				$password->set_text($query->first_child_text('password'));
			}
		}

		# roster information
		if ($query->att('xmlns') eq 'jabber:iq:roster')
		{
			for my $item ($query->children('item'))
			{
				my $jid          = $item->att('jid');
				my $subscription = $item->att('subscription');
				my $name         = $item->att('name');

				my $xml = XML::Twig::Elt->new('Item');
				$xml->set_keep_atts_order(1);
				$xml->set_att('jid',  $jid)  if ($jid);

				if ($subscription eq 'both')
				{
					$xml->set_att('askstatus', '-1');
					$xml->set_att('recvstatus', '-1');
					$xml->set_att('substatus', '3');
				}
				elsif ($subscription eq 'none')
				{
					$xml->set_att('substatus', '0');
					$xml->set_att('askstatus', '0');
					$xml->set_att('recvstatus', '-1');
				}
				elsif ($subscription eq 'to')
				{
					$xml->set_att('substatus', '1');
					$xml->set_att('askstatus', '0');
					$xml->set_att('recvstatus', '-1');
				}
				elsif ($subscription eq 'from')
				{
					$xml->set_att('substatus', '2');
					$xml->set_att('askstatus', '0');
					$xml->set_att('recvstatus', '-1');
				}

				$xml->set_att('name', $name) if ($name);

				my @groups = ($item->children('group'));
				if (@groups)
				{
					for my $group ($item->children('group'))
					{
						my $groupxml = XML::Twig::Elt->new('Group');
						$groupxml->set_text($group->text);
						$groupxml->paste('last_child', $xml);
					}
				} else {
					my $groupxml = XML::Twig::Elt->new('Group');
					$groupxml->paste('last_child', $xml);
				}

				$xml->paste('last_child', $rosterxml);
			}
		}
	}

	$username->paste('last_child',  $userxml);
	$password->paste('last_child',  $userxml);
	$email->paste('last_child',     $userxml);
	$name->paste('last_child',      $userxml);
	$ctime->paste('last_child',     $userxml);
	$mtime->paste('last_child',     $userxml);
	$rosterxml->paste('last_child', $userxml);

	$userxml->paste('last_child', $output);
}

print '<?xml version="1.0" encoding="UTF-8"?>', "\n\n";
$output->print;

__END__
Sample input schema:

<xdb>
    <password xmlns='jabber:iq:auth' xdbns='jabber:iq:auth'>mypassword</password>
    <query xmlns='jabber:iq:register' xdbns='jabber:iq:register'>
        <username>user</username>
        <password xmlns='jabber:iq:auth'>mypassword</password>
    </query>
    <foo xdbns='jabber:xdb:nslist' xmlns='jabber:xdb:nslist'>
        <ns type='private'>jabberim:prefs</ns>
    </foo>
    <zerok xmlns='jabber:iq:auth:0k' xdbns='jabber:iq:auth:0k'>
        <token>hex-string</token>
        <sequence>0</sequence>
        <hash>hash-string</hash>
    </zerok>
    <query xmlns='jabber:iq:roster' xdbns='jabber:iq:roster'>
        <item jid='someuser@input-server' name='someuser' subscription='both'>
            <group>Friends</group>
        </item>
    </query>
    <jabberim xmlns='jabberim:prefs' UseAutoAway='true' AwayTime='5' XATime='30' AwayStatus='Away (auto)' XAStatus='Ext. Away (auto)' WizardShown='false' ReadSystemSettings='true' CheckVCard='true' RosterFontName='Arial' RosterFo
ntSize='10' RosterColor='-2147483643' NewMsgWAV='C:\Program Files\Jabber\msg02.wav' OnlineWAV='C:\Program Files\Jabber\msg01.wav' OfflineWAV='C:\Program Files\Jabber\msg01.wav' ShowFilters='1' ViewJIDAs='0' ShowToolBar='true' Sho
wStatusBar='true' NoFiles='false' ShowLogonServerInfo='false' AutoSubscription='false' EnableResources='false' MyResources='false' OnlineSound='true' ShowExitConfirm='false' UseXHTML='true' EmbededCR='false' ChatFontName='Arial' 
ChatFontSize='10' ChatFontStyle='0' PopChatWindows='false' NewMsgSound='true' BringToTop='true' NoMessageLogging='false' OfflineSound='true' DAVServer='files.jabber.com' DAVPath='' DAVPort='80' UseP2P='false' XferDir='C:\Document
s and Settings\abalog\Application Data\JabberIM' BlockNonRoster='false' DeleteLogs='false' ShowResources='false' ShowPriorities='false' j_private_flag='1' xdbns='jabberim:prefs'>
        <StatusOnline S0='Available' S1='Free for Chat' S2='Gone to do ponies'/>
        <StatusAway S0='Away' S1='Be Right Back' S2='On The Phone' S3='Not At My Desk' S4='Out To Lunch' S5='Stepped Out' S6='Gone to do ponies'/>
        <StatusXA S0='Extended Away' S1='Gone Home' S2='Sleeping' S3='On Vacation'/>
        <StatusDND S0='Do Not Disturb' S1='In A Meeting' S2='Busy' S3='Working'/>
        <MinimizedGroups/>
        <IgnoreList/>
    </jabberim>
    <query xmlns='jabber:iq:last' last='1216290535' xdbns='jabber:iq:last'>Replaced by new connection</query>
    <foo xmlns='jabber:x:offline' xdbns='jabber:x:offline'/>
</xdb>


Sample output schema:

<User>
  <Username>user</Username>
  <Password>mypassword</Password>
  <Email>user@input-server</Email>
  <Name>full name</Name>
  <CreationDate>1125442154664</CreationDate>
  <ModifiedDate>1125442154664</ModifiedDate>
  <Roster>
    <Item jid="someuser@input-server" askstatus="-1" recvstatus="-1" substatus="3" name="someuser">
      <Group>Friends</Group>
    </Item>
  </Roster>
</User>

