Mercurial > prosody-hg
comparison tools/openfire2prosody.lua @ 5104:27b45d2c19fe
Merge 0.9->trunk
| author | Matthew Wild <mwild1@gmail.com> |
|---|---|
| date | Sun, 26 Aug 2012 19:58:59 +0100 |
| parents | a5b683909f79 |
| children | f2becd36d1d0 |
comparison
equal
deleted
inserted
replaced
| 5103:5a1488369c35 | 5104:27b45d2c19fe |
|---|---|
| 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 |
