Comparison

tools/openfire2prosody.lua @ 5089:a5b683909f79

tools/openfire2prosody: Initial commit.
author Waqas Hussain <waqas20@gmail.com>
date Sat, 11 Aug 2012 06:14:12 +0500
child 5217:f2becd36d1d0
comparison
equal deleted inserted replaced
5088:d5bb9cd2e6df 5089:a5b683909f79
1 #!/usr/bin/env lua
2 -- Prosody IM
3 -- Copyright (C) 2008-2009 Waqas Hussain
4 --
5 -- This project is MIT/X11 licensed. Please see the
6 -- COPYING file in the source package for more information.
7 --
8
9 package.path = package.path..";../?.lua";
10 package.cpath = package.cpath..";../?.so"; -- needed for util.pposix used in datamanager
11
12 -- ugly workaround for getting datamanager to work outside of prosody :(
13 prosody = { };
14 prosody.platform = "unknown";
15 if os.getenv("WINDIR") then
16 prosody.platform = "windows";
17 elseif package.config:sub(1,1) == "/" then
18 prosody.platform = "posix";
19 end
20
21 local lxp = require "lxp";
22 local st = require "util.stanza";
23
24 local parse_xml = (function()
25 local ns_prefixes = {
26 ["http://www.w3.org/XML/1998/namespace"] = "xml";
27 };
28 local ns_separator = "\1";
29 local ns_pattern = "^([^"..ns_separator.."]*)"..ns_separator.."?(.*)$";
30 return function(xml)
31 local handler = {};
32 local stanza = st.stanza("root");
33 function handler:StartElement(tagname, attr)
34 local curr_ns,name = tagname:match(ns_pattern);
35 if name == "" then
36 curr_ns, name = "", curr_ns;
37 end
38 if curr_ns ~= "" then
39 attr.xmlns = curr_ns;
40 end
41 for i=1,#attr do
42 local k = attr[i];
43 attr[i] = nil;
44 local ns, nm = k:match(ns_pattern);
45 if nm ~= "" then
46 ns = ns_prefixes[ns];
47 if ns then
48 attr[ns..":"..nm] = attr[k];
49 attr[k] = nil;
50 end
51 end
52 end
53 stanza:tag(name, attr);
54 end
55 function handler:CharacterData(data)
56 stanza:text(data);
57 end
58 function handler:EndElement(tagname)
59 stanza:up();
60 end
61 local parser = lxp.new(handler, "\1");
62 local ok, err, line, col = parser:parse(xml);
63 if ok then ok, err, line, col = parser:parse(); end
64 --parser:close();
65 if ok then
66 return stanza.tags[1];
67 else
68 return ok, err.." (line "..line..", col "..col..")";
69 end
70 end;
71 end)();
72
73 -----------------------------------------------------------------------
74
75 package.loaded["util.logger"] = {init = function() return function() end; end}
76 local dm = require "util.datamanager"
77 dm.set_data_path("data");
78
79 local arg = ...;
80 local help = "/? -? ? /h -h /help -help --help";
81 if not arg or help:find(arg, 1, true) then
82 print([[Openfire importer for Prosody
83
84 Usage: openfire2prosody.lua filename.xml hostname
85
86 ]]);
87 os.exit(1);
88 end
89
90 local host = select(2, ...) or "localhost";
91
92 local file = assert(io.open(arg));
93 local data = assert(file:read("*a"));
94 file:close();
95
96 local xml = assert(parse_xml(data));
97
98 assert(xml.name == "Openfire", "The input file is not an Openfire XML export");
99
100 local substatus_mapping = { ["0"] = "none", ["1"] = "to", ["2"] = "from", ["3"] = "both" };
101
102 for _,tag in ipairs(xml.tags) do
103 if tag.name == "User" then
104 local username, password, roster;
105
106 for _,tag in ipairs(tag.tags) do
107 if tag.name == "Username" then
108 username = tag:get_text();
109 elseif tag.name == "Password" then
110 password = tag:get_text();
111 elseif tag.name == "Roster" then
112 roster = {};
113 local pending = {};
114 for _,tag in ipairs(tag.tags) do
115 if tag.name == "Item" then
116 local jid = assert(tag.attr.jid, "Roster item has no JID");
117 if tag.attr.substatus ~= "-1" then
118 local item = {};
119 item.name = tag.attr.name;
120 item.subscription = assert(substatus_mapping[tag.attr.substatus], "invalid substatus");
121 item.ask = tag.attr.askstatus == "0" and "subscribe" or nil;
122
123 local groups = {};
124 for _,tag in ipairs(tag) do
125 if tag.name == "Group" then
126 groups[tag:get_text()] = true;
127 end
128 end
129 item.groups = groups;
130 roster[jid] = item;
131 end
132 if tag.attr.recvstatus == "1" then pending[jid] = true; end
133 end
134 end
135
136 if next(pending) then
137 roster[false] = { pending = pending };
138 end
139 end
140 end
141
142 assert(username and password, "No username or password");
143
144 local ret, err = dm.store(username, host, "accounts", {password = password});
145 print("["..(err or "success").."] stored account: "..username.."@"..host.." = "..password);
146
147 if roster then
148 local ret, err = dm.store(username, host, "roster", roster);
149 print("["..(err or "success").."] stored roster: "..username.."@"..host.." = "..password);
150 end
151 end
152 end
153