![]() |
index : Sleek Migrate | |
| Migration tool for Jabber/XMPP servers | Remko Tronçon |
| summaryrefslogtreecommitdiffstats |
Unidiff
| -rwxr-xr-x | sleekmigrate.py | 44 |
1 files changed, 36 insertions, 8 deletions
diff --git a/sleekmigrate.py b/sleekmigrate.py index 56607f5..7db55cc 100755 --- a/sleekmigrate.py +++ b/sleekmigrate.py | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | import logging | 20 | import logging |
| 21 | import sleekxmpp | 21 | import sleekxmpp |
| 22 | from optparse import OptionParser | 22 | from optparse import OptionParser |
| 23 | import xml.dom.minidom | ||
| 23 | from xml.etree import cElementTree as ET | 24 | from xml.etree import cElementTree as ET |
| 24 | 25 | ||
| 25 | import os | 26 | import os |
| @@ -27,6 +28,13 @@ import time | |||
| 27 | import csv | 28 | import csv |
| 28 | import codecs | 29 | import codecs |
| 29 | 30 | ||
| 31 | def getText(node): | ||
| 32 | rc = "" | ||
| 33 | for node in node.childNodes: | ||
| 34 | if node.nodeType in [node.TEXT_NODE, node.CDATA_SECTION_NODE]: | ||
| 35 | rc += node.data | ||
| 36 | return rc | ||
| 37 | |||
| 30 | class Account(object): | 38 | class Account(object): |
| 31 | def __init__(self, jid, password): | 39 | def __init__(self, jid, password): |
| 32 | self.jid = jid | 40 | self.jid = jid |
| @@ -136,7 +144,7 @@ class XMPPAccountExtractor(sleekxmpp.ClientXMPP): | |||
| 136 | self.sessionOkay = False | 144 | self.sessionOkay = False |
| 137 | self.timeout = 30 | 145 | self.timeout = 30 |
| 138 | self.privatesToRequest = ("{exodus:prefs}exodus","{storage:bookmarks}storage", "{storage:rosternotes}storage", "{storage:metacontacts}storage") | 146 | self.privatesToRequest = ("{exodus:prefs}exodus","{storage:bookmarks}storage", "{storage:rosternotes}storage", "{storage:metacontacts}storage") |
| 139 | 147 | ||
| 140 | def start(self, event): | 148 | def start(self, event): |
| 141 | self.sessionOkay = True | 149 | self.sessionOkay = True |
| 142 | self.getRoster() | 150 | self.getRoster() |
| @@ -144,9 +152,9 @@ class XMPPAccountExtractor(sleekxmpp.ClientXMPP): | |||
| 144 | while not self.vcardDone or not self.rosterDone or not self.privatesDone: | 152 | while not self.vcardDone or not self.rosterDone or not self.privatesDone: |
| 145 | time.sleep(1) | 153 | time.sleep(1) |
| 146 | self.disconnect() | 154 | self.disconnect() |
| 147 | 155 | ||
| 148 | 156 | ||
| 149 | 157 | ||
| 150 | def fetch_privates(self): | 158 | def fetch_privates(self): |
| 151 | self.account.privateElements = [] | 159 | self.account.privateElements = [] |
| 152 | for privateToRequest in self.privatesToRequest: | 160 | for privateToRequest in self.privatesToRequest: |
| @@ -176,7 +184,7 @@ class XMPPAccountExtractor(sleekxmpp.ClientXMPP): | |||
| 176 | self.vcardDone = True | 184 | self.vcardDone = True |
| 177 | self.fetch_privates() | 185 | self.fetch_privates() |
| 178 | 186 | ||
| 179 | 187 | ||
| 180 | 188 | ||
| 181 | def receive_roster(self, event): | 189 | def receive_roster(self, event): |
| 182 | for jid in event: | 190 | for jid in event: |
| @@ -190,6 +198,21 @@ class XMPPAccountExtractor(sleekxmpp.ClientXMPP): | |||
| 190 | def getAccount(self): | 198 | def getAccount(self): |
| 191 | return self.account | 199 | return self.account |
| 192 | 200 | ||
| 201 | def authDetailsFromOpenFireFile(filename, domain): | ||
| 202 | """ Return a list of auth dicts | ||
| 203 | """ | ||
| 204 | file = open(filename) | ||
| 205 | document = xml.dom.minidom.parseString(file.read()) | ||
| 206 | file.close() | ||
| 207 | users = document.getElementsByTagName("User") | ||
| 208 | |||
| 209 | auths = [] | ||
| 210 | for user in users : | ||
| 211 | auths.append({ | ||
| 212 | 'jid': getText(user.getElementsByTagName("Username")[0]) + "@" + domain, | ||
| 213 | 'pass': getText(user.getElementsByTagName("Password")[0])}) | ||
| 214 | return auths | ||
| 215 | |||
| 193 | def authDetailsFromFile(filename): | 216 | def authDetailsFromFile(filename): |
| 194 | """ Return a list of auth dicts | 217 | """ Return a list of auth dicts |
| 195 | """ | 218 | """ |
| @@ -210,12 +233,17 @@ if __name__ == '__main__': | |||
| 210 | optp.add_option('-s','--server', help='domain to export', dest='hostname', default=None) | 233 | optp.add_option('-s','--server', help='domain to export', dest='hostname', default=None) |
| 211 | #optp.add_option("-c","--config", dest="configfile", default="config.xml", help="set config file to use") | 234 | #optp.add_option("-c","--config", dest="configfile", default="config.xml", help="set config file to use") |
| 212 | optp.add_option("-f","--user-file", dest="userFile", default="users.csv", help="name of CSV uname/password pairs file") | 235 | optp.add_option("-f","--user-file", dest="userFile", default="users.csv", help="name of CSV uname/password pairs file") |
| 236 | optp.add_option("-o","--openfire-user-file", dest="openFireUserFile", default="", help="name of the OpenFire user export XML file") | ||
| 213 | opts,args = optp.parse_args() | 237 | opts,args = optp.parse_args() |
| 214 | 238 | ||
| 215 | logging.basicConfig(level=opts.loglevel, format='%(levelname)-8s %(message)s') | 239 | logging.basicConfig(level=opts.loglevel, format='%(levelname)-8s %(message)s') |
| 216 | 240 | ||
| 217 | logging.info("Loading user file: %s" % opts.userFile) | 241 | if len(opts.openFireUserFile) != 0 : |
| 218 | authDetails = authDetailsFromFile(opts.userFile) | 242 | logging.info("Loading OpenFire user export file: %s" % opts.openFireUserFile) |
| 243 | authDetails = authDetailsFromOpenFireFile(opts.openFireUserFile, opts.hostname) | ||
| 244 | else : | ||
| 245 | logging.info("Loading user file: %s" % opts.userFile) | ||
| 246 | authDetails = authDetailsFromFile(opts.userFile) | ||
| 219 | 247 | ||
| 220 | plugin_config = {} | 248 | plugin_config = {} |
| 221 | exporterType = opts.exportFormatter | 249 | exporterType = opts.exportFormatter |
| @@ -225,7 +253,7 @@ if __name__ == '__main__': | |||
| 225 | exporter = TigaseCSVExporter('out.txt') | 253 | exporter = TigaseCSVExporter('out.txt') |
| 226 | else: | 254 | else: |
| 227 | logging.error("Unexpected Exporter type %s." % exporterType) | 255 | logging.error("Unexpected Exporter type %s." % exporterType) |
| 228 | 256 | ||
| 229 | for auth in authDetails: | 257 | for auth in authDetails: |
| 230 | extractor = XMPPAccountExtractor(auth['jid'], auth['pass'], plugin_config=plugin_config, plugin_whitelist=[]) | 258 | extractor = XMPPAccountExtractor(auth['jid'], auth['pass'], plugin_config=plugin_config, plugin_whitelist=[]) |
| 231 | if opts.hostname is None: | 259 | if opts.hostname is None: |
