Merge
[prosody.git] / tools / ejabberd2prosody.lua
1 #!/usr/bin/env lua
2 -- Prosody IM v0.4
3 -- Copyright (C) 2008-2009 Matthew Wild
4 -- Copyright (C) 2008-2009 Waqas Hussain
5 -- 
6 -- This project is MIT/X11 licensed. Please see the
7 -- COPYING file in the source package for more information.
8 --
9
10
11 \r
12 require "erlparse";\r
13 \r
14 package.path = package.path ..";../?.lua";\r
15 local serialize = require "util.serialization".serialize;
16 local st = require "util.stanza";\r
17 package.loaded["util.logger"] = {init = function() return function() end; end}\r
18 local dm = require "util.datamanager"\r
19 dm.set_data_path("data");\r
20 \r
21 function build_stanza(tuple, stanza)\r
22         if tuple[1] == "xmlelement" then\r
23                 local name = tuple[2];\r
24                 local attr = {};\r
25                 for _, a in ipairs(tuple[3]) do attr[a[1]] = a[2]; end\r
26                 local up;\r
27                 if stanza then stanza:tag(name, attr); up = true; else stanza = st.stanza(name, attr); end\r
28                 for _, a in ipairs(tuple[4]) do build_stanza(a, stanza); end\r
29                 if up then stanza:up(); else return stanza end\r
30         elseif tuple[1] == "xmlcdata" then\r
31                 stanza:text(tuple[2]);\r
32         else\r
33                 error("unknown element type: "..serialize(tuple));\r
34         end\r
35 end\r
36 function build_time(tuple)\r
37         local Megaseconds,Seconds,Microseconds = unpack(tuple);\r
38         return Megaseconds * 1000000 + Seconds;\r
39 end\r
40 \r
41 function vcard(node, host, stanza)\r
42         local ret, err = dm.store(node, host, "vcard", st.preserialize(stanza));\r
43         print("["..(err or "success").."] vCard: "..node.."@"..host);\r
44 end\r
45 function password(node, host, password)\r
46         local ret, err = dm.store(node, host, "accounts", {password = password});\r
47         print("["..(err or "success").."] accounts: "..node.."@"..host.." = "..password);\r
48 end\r
49 function roster(node, host, jid, item)
50         local roster = dm.load(node, host, "roster") or {};
51         roster[jid] = item;
52         local ret, err = dm.store(node, host, "roster", roster);
53         print("["..(err or "success").."] roster: " ..node.."@"..host.." - "..jid);
54 end
55 function roster_pending(node, host, jid)
56         local roster = dm.load(node, host, "roster") or {};
57         roster.pending = roster.pending or {};
58         roster.pending[jid] = true;
59         local ret, err = dm.store(node, host, "roster", roster);
60         print("["..(err or "success").."] roster: " ..node.."@"..host.." - "..jid);
61 end
62 function private_storage(node, host, xmlns, stanza)\r
63         local private = dm.load(node, host, "private") or {};\r
64         private[xmlns] = st.preserialize(stanza);\r
65         local ret, err = dm.store(node, host, "private", private);\r
66         print("["..(err or "success").."] private: " ..node.."@"..host.." - "..xmlns);\r
67 end\r
68 function offline_msg(node, host, t, stanza)\r
69         stanza.attr.stamp = os.date("!%Y-%m-%dT%H:%M:%SZ", t);\r
70         stanza.attr.stamp_legacy = os.date("!%Y%m%dT%H:%M:%S", t);\r
71         local ret, err = dm.list_append(node, host, "offline", st.preserialize(stanza));\r
72         print("["..(err or "success").."] offline: " ..node.."@"..host.." - "..os.date("!%Y-%m-%dT%H:%M:%SZ", t));\r
73 end\r
74 \r
75 \r
76 local filters = {\r
77         passwd = function(tuple)\r
78                 password(tuple[2][1], tuple[2][2], tuple[3]);\r
79         end;\r
80         vcard = function(tuple)\r
81                 vcard(tuple[2][1], tuple[2][2], build_stanza(tuple[3]));\r
82         end;\r
83         roster = function(tuple)\r
84                 local node = tuple[3][1]; local host = tuple[3][2];\r
85                 local contact = (type(tuple[4][1]) == "table") and tuple[4][2] or tuple[4][1].."@"..tuple[4][2];\r
86                 local name = tuple[5]; local subscription = tuple[6];\r
87                 local ask = tuple[7]; local groups = tuple[8];\r
88                 if type(name) ~= type("") then name = nil; end\r
89                 if ask == "none" then ask = nil; elseif ask == "out" then ask = "subscribe" elseif ask == "in" then
90                         roster_pending(node, host, contact);
91                         return;
92                 else error(ask) end\r
93                 if subscription ~= "both" and subscription ~= "from" and subscription ~= "to" and subscription ~= "none" then error(subscription) end\r
94                 local item = {name = name, ask = ask, subscription = subscription, groups = {}};\r
95                 for _, g in ipairs(groups) do item.groups[g] = true; end\r
96                 roster(node, host, contact, item);\r
97         end;\r
98         private_storage = function(tuple)\r
99                 private_storage(tuple[2][1], tuple[2][2], tuple[2][3], build_stanza(tuple[3]));\r
100         end;\r
101         offline_msg = function(tuple)\r
102                 offline_msg(tuple[2][1], tuple[2][2], build_time(tuple[3]), build_stanza(tuple[7]));\r
103         end;\r
104         config = function(tuple)\r
105                 if tuple[2] == "hosts" then\r
106                         local output = io.output(); io.output("prosody.cfg.lua");\r
107                         io.write("-- Configuration imported from ejabberd --\n");\r
108                         io.write([[Host "*"\r
109         modules_enabled = {\r
110                 "saslauth"; -- Authentication for clients and servers. Recommended if you want to log in.\r
111                 "legacyauth"; -- Legacy authentication. Only used by some old clients and bots.\r
112                 "roster"; -- Allow users to have a roster. Recommended ;)\r
113                 "register"; -- Allow users to register on this server using a client\r
114                 "tls"; -- Add support for secure TLS on c2s/s2s connections\r
115                 "vcard"; -- Allow users to set vCards\r
116                 "private"; -- Private XML storage (for room bookmarks, etc.)\r
117                 "version"; -- Replies to server version requests\r
118                 "dialback"; -- s2s dialback support\r
119                 "uptime";\r
120                 "disco";\r
121                 "time";\r
122                 "ping";\r
123                 --"selftests";\r
124         };\r
125 ]]);\r
126                         for _, h in ipairs(tuple[3]) do\r
127                                 io.write("Host \"" .. h .. "\"\n");\r
128                         end\r
129                         io.output(output);\r
130                         print("prosody.cfg.lua created");\r
131                 end\r
132         end;\r
133 };\r
134 \r
135 local arg = ...;\r
136 local help = "/? -? ? /h -h /help -help --help";\r
137 if not arg or help:find(arg, 1, true) then\r
138         print([[ejabberd db dump importer for Prosody\r
139 \r
140   Usage: ejabberd2prosody.lua filename.txt\r
141 \r
142 The file can be generated from ejabberd using:\r
143   sudo ./bin/ejabberdctl dump filename.txt\r
144 \r
145 Note: The path of ejabberdctl depends on your ejabberd installation, and ejabberd needs to be running for ejabberdctl to work.]]);\r
146         os.exit(1);\r
147 end\r
148 local count = 0;\r
149 local t = {};\r
150 for item in erlparse.parseFile(arg) do\r
151         count = count + 1;\r
152         local name = item[1];\r
153         t[name] = (t[name] or 0) + 1;\r
154         --print(count, serialize(item));\r
155         if filters[name] then filters[name](item); end\r
156 end\r
157 --print(serialize(t));\r