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