This commit is contained in:
parent
4eba9027ec
commit
6e4713238e
6 changed files with 385 additions and 0 deletions
41
Makefile
Normal file
41
Makefile
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#-------------------------------------------------------------------%
|
||||||
|
#
|
||||||
|
# JABSYNC: Synchronizer
|
||||||
|
#
|
||||||
|
#-------------------------------------------------------------------%
|
||||||
|
#
|
||||||
|
# Author :
|
||||||
|
# Glenn ROLLAND <glenux@fr.st>
|
||||||
|
#
|
||||||
|
# Contributors:
|
||||||
|
# (none)
|
||||||
|
#
|
||||||
|
#-------------------------------------------------------------------%
|
||||||
|
|
||||||
|
PRJNAME=JabSync
|
||||||
|
GDATE:= $(shell date +"%Y-%m-%d_r%H%M")
|
||||||
|
GFILENAME:= $(PRJNAME)-$(GDATE).tar.bz2
|
||||||
|
PATH_GFILENAME:= ../$(GFILENAME)
|
||||||
|
GFILESIZE:=
|
||||||
|
LOCALDIR=$(shell pwd)
|
||||||
|
|
||||||
|
all: usage
|
||||||
|
|
||||||
|
usage:
|
||||||
|
@echo "Usage: make [package] [clean]"
|
||||||
|
|
||||||
|
#doc:
|
||||||
|
# $(MAKE) -C doc/rapport
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@rm -f *.pyc
|
||||||
|
|
||||||
|
package: clean createpackage sendtoarchives
|
||||||
|
|
||||||
|
createpackage:
|
||||||
|
tar -cjvf $(PATH_GFILENAME) -C ../ $(PRJNAME)
|
||||||
|
|
||||||
|
sendtoarchives:
|
||||||
|
mkdir -p ../Archives
|
||||||
|
mv $(PATH_GFILENAME) ../Archives
|
||||||
|
|
4
TODO
Normal file
4
TODO
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
- add something to remember servers (jabber/transports) that
|
||||||
|
were previously entered
|
||||||
|
- add the ability to modify an XML file (not the configuration file) to save the list of jabber servers
|
||||||
|
- add the ability to modify the XML configuration file to add the transports notincluded in the defaut "Service Browse" of servers.
|
134
account.py
Normal file
134
account.py
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
#/usr/bin/env python
|
||||||
|
|
||||||
|
import jabber
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def _gdisconnectHD(param=None):
|
||||||
|
if param:
|
||||||
|
print " Disconnecting : "+param
|
||||||
|
return None
|
||||||
|
|
||||||
|
class Account:
|
||||||
|
def __init__(self):
|
||||||
|
self._host=None
|
||||||
|
self._login=None
|
||||||
|
self._password=None
|
||||||
|
self._rosterHash={}
|
||||||
|
self._proto2transport={}
|
||||||
|
self._transport2proto={}
|
||||||
|
self._cnx=None
|
||||||
|
|
||||||
|
def setHost(self,hostName):
|
||||||
|
self._host=hostName
|
||||||
|
|
||||||
|
def setLogin(self,userName):
|
||||||
|
self._login=userName
|
||||||
|
|
||||||
|
def setPassword(self,passWord):
|
||||||
|
self._password=passWord
|
||||||
|
|
||||||
|
def setProtocol(self,protocolName,transportName):
|
||||||
|
self._proto2transport[protocolName]=transportName
|
||||||
|
|
||||||
|
def setTransport(self,transportName,protocolName):
|
||||||
|
self._transport2proto[transportName]=protocolName
|
||||||
|
|
||||||
|
def getTransport(self,protocolName):
|
||||||
|
if self._proto2transport.has_key(protocolName):
|
||||||
|
return self._proto2transport[protocolName]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def getProtocol(self,hostName):
|
||||||
|
if self._transport2proto.has_key(hostName):
|
||||||
|
return self._transport2proto[hostName]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def connect(self):
|
||||||
|
# se connecte et choppe le roster
|
||||||
|
## connexion au serveur
|
||||||
|
self._cnx=jabber.Client(host=self._host)
|
||||||
|
self._cnx.setDisconnectHandler(_gdisconnectHD)
|
||||||
|
if self._cnx:
|
||||||
|
try:
|
||||||
|
self._cnx.connect()
|
||||||
|
sys.stderr.write("* Connected to "+self._host+"\n")
|
||||||
|
## authentification
|
||||||
|
if self._login and self._password \
|
||||||
|
and self._cnx.auth(self._login, self._password, 'default'):
|
||||||
|
sys.stderr.write(" Authenticated\n")
|
||||||
|
else:
|
||||||
|
sys.stderr.write(" Not Athenticated. \n")
|
||||||
|
sys.stderr.write(" Disconnecting from "+self._host+"\n")
|
||||||
|
self._cnx=None
|
||||||
|
except IOError, e:
|
||||||
|
print e
|
||||||
|
self._cnx=None
|
||||||
|
|
||||||
|
def disconnect(self):
|
||||||
|
if self._cnx:
|
||||||
|
self._cnx.disconnect()
|
||||||
|
sys.stderr.write(" Disconnected from"+self._host+"\n")
|
||||||
|
|
||||||
|
|
||||||
|
def getAgents(self):
|
||||||
|
if self._cnx:
|
||||||
|
agentsList=self._cnx.requestAgents()
|
||||||
|
sys.stderr.write(" Agents list downloaded:\n")
|
||||||
|
print agentsList
|
||||||
|
for agent in agentsList.keys():
|
||||||
|
if agent:
|
||||||
|
self.setProtocol(agentsList[agent]["service"],agent)
|
||||||
|
self.setTransport(agent,agentsList[agent]["service"])
|
||||||
|
print " - "+agent+" @ "+agentsList[agent]["service"]
|
||||||
|
return self._transport2proto
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def getRoster(self):
|
||||||
|
if self._cnx:
|
||||||
|
roster=self._cnx.requestRoster()
|
||||||
|
sys.stderr.write(" Roster downloaded\n")
|
||||||
|
jid_list=roster.getJIDs()
|
||||||
|
for jid in jid_list:
|
||||||
|
transport=jid.getDomain()
|
||||||
|
node=jid.getNode()
|
||||||
|
if not self._rosterHash.has_key(transport):
|
||||||
|
self._rosterHash[transport]={}
|
||||||
|
if not self._rosterHash[transport].has_key(node):
|
||||||
|
self._rosterHash[transport][node]=1
|
||||||
|
return roster
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def setRoster(self,rosterHash):
|
||||||
|
# on se connecte
|
||||||
|
if self._cnx:
|
||||||
|
for trans_proto in rosterHash.keys():
|
||||||
|
trans_host=self.getTransport(trans_proto)
|
||||||
|
if not trans_host: trans_host=trans_proto
|
||||||
|
# pour chaque id connue dans ce proto
|
||||||
|
for proto_id in rosterHash[trans_proto]:
|
||||||
|
if proto_id:
|
||||||
|
jid=jabber.JID()
|
||||||
|
jid.setNode(proto_id)
|
||||||
|
jid.setDomain(trans_host)
|
||||||
|
jid.setResource("")
|
||||||
|
jid_name,jid_groups=rosterHash[trans_proto][proto_id]
|
||||||
|
sys.stdout.write(" -> "+proto_id)
|
||||||
|
sys.stdout.write(" @ "+trans_host)
|
||||||
|
sys.stdout.write(" = "+jid_name.encode('iso-8859-1','replace')+"...")
|
||||||
|
sys.stdout.flush()
|
||||||
|
if not(self._rosterHash.has_key(trans_host) \
|
||||||
|
and self._rosterHash[trans_host].has_key(proto_id)):
|
||||||
|
self._cnx.addRosterItem(jid)
|
||||||
|
sys.stdout.write(" [done]\n")
|
||||||
|
else:
|
||||||
|
#ne pas faire la mise a jour, le contact existe deja la-bas
|
||||||
|
sys.stdout.write(" [exists]\n")
|
||||||
|
# on met d'abord a jour le nom
|
||||||
|
self._cnx.updateRosterItem(jid,name=jid_name)
|
||||||
|
# puis le groupe
|
||||||
|
self._cnx.updateRosterItem(jid,name=jid_name,groups=jid_groups)
|
||||||
|
|
44
config.py
Normal file
44
config.py
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
from xml.dom.ext import *
|
||||||
|
from xml.dom.ext.reader.Sax import *
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from account import Account
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
def __init__(self):
|
||||||
|
# create an empty list
|
||||||
|
self.account_list=None
|
||||||
|
# initialise xmlTree
|
||||||
|
self.xmlTree=None
|
||||||
|
|
||||||
|
def loadFromFile(self,configFile):
|
||||||
|
self.xmlTree=FromXmlFile(configFile)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def getAccounts(self):
|
||||||
|
if self.xmlTree:
|
||||||
|
xmlAccountList = self.xmlTree.getElementsByTagName("account")
|
||||||
|
accountList=[]
|
||||||
|
for xmlAccount in xmlAccountList:
|
||||||
|
account=Account()
|
||||||
|
account.setHost(xmlAccount.getAttribute("host"))
|
||||||
|
account.setLogin(xmlAccount.getAttribute("login"))
|
||||||
|
account.setPassword(xmlAccount.getAttribute("password"))
|
||||||
|
xmlTransportList=xmlAccount.getElementsByTagName("transport")
|
||||||
|
for xmlTransport in xmlTransportList:
|
||||||
|
isdefault=xmlTransport.getAttribute("default")
|
||||||
|
if isdefault=="true":
|
||||||
|
account.setTransport(\
|
||||||
|
xmlTransport.getAttribute("host"),\
|
||||||
|
xmlTransport.getAttribute("protocol"))
|
||||||
|
account.setProtocol(\
|
||||||
|
xmlTransport.getAttribute("protocol"),\
|
||||||
|
xmlTransport.getAttribute("host"))
|
||||||
|
#TODO:add something to override servers' defaults
|
||||||
|
accountList.append(account)
|
||||||
|
return accountList
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
14
dot.jabsync
Normal file
14
dot.jabsync
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>
|
||||||
|
<jabsync version="0.4">
|
||||||
|
<account host="jabber.dk" login="fooman" password="barpassword">
|
||||||
|
<transport host="icq.myjabber.net" protocol="icq" />
|
||||||
|
<transport host="aim.myjabber.net" protocol="aim"/>
|
||||||
|
</account>
|
||||||
|
<!-- <account host="jabber.freenet.de" login="fooman" password="barpassword" /> -->
|
||||||
|
<account host="jabber.ru" login="fooman" password="barpassword" >
|
||||||
|
<transport host="aim.jabber.ru" protocol="aim" default="true" />
|
||||||
|
<transport host="icq.jabber.ru" protocol="icq" default="true" />
|
||||||
|
<transport host="msn.jabber.ru" protocol="msn" default="true" />
|
||||||
|
<transport host="yahoo.jabber.ru" protocol="yahoo" default="true" />
|
||||||
|
</account>
|
||||||
|
</jabsync>
|
148
start.py
Executable file
148
start.py
Executable file
|
@ -0,0 +1,148 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import string
|
||||||
|
#from qt import *
|
||||||
|
from jabber import *
|
||||||
|
import StringIO
|
||||||
|
#import time
|
||||||
|
from account import Account
|
||||||
|
from config import Config
|
||||||
|
#from re import *
|
||||||
|
from optparse import OptionParser
|
||||||
|
|
||||||
|
#from threading import *
|
||||||
|
from xml.sax import saxutils
|
||||||
|
from xml.sax import make_parser
|
||||||
|
# for prettyprint
|
||||||
|
from xml.dom.ext import *
|
||||||
|
from xml.dom.ext.reader.Sax import *
|
||||||
|
|
||||||
|
class Answer:
|
||||||
|
def __init__(self,question,answerlist):
|
||||||
|
self._answer=None
|
||||||
|
while not self._answer:
|
||||||
|
sys.stderr.write(question)
|
||||||
|
tmp_ans=raw_input()
|
||||||
|
if tmp_ans in (answerlist): self._answer=tmp_ans
|
||||||
|
|
||||||
|
def get(self):
|
||||||
|
return self._answer;
|
||||||
|
|
||||||
|
|
||||||
|
class JabSync:
|
||||||
|
def __init__(self):
|
||||||
|
# init des var
|
||||||
|
self._commonJIDs={}
|
||||||
|
self._commonTransports={}
|
||||||
|
self._configFile=None
|
||||||
|
self._config=None
|
||||||
|
self._accountList=None
|
||||||
|
self._jabservers={}
|
||||||
|
|
||||||
|
def parseCmdLine(self):
|
||||||
|
parser=OptionParser()
|
||||||
|
parser.add_option("-c","--config",\
|
||||||
|
action="store", type="string", dest="filename",\
|
||||||
|
help="Use file a configuration file",metavar="config")
|
||||||
|
(options,args)=parser.parse_args()
|
||||||
|
if options.filename:
|
||||||
|
self._configFile=options.filename
|
||||||
|
else:
|
||||||
|
self._configFile=os.path.join(os.path.expanduser("~"),".jabsync")
|
||||||
|
print "Configuration file: "+self._configFile
|
||||||
|
def init(self):
|
||||||
|
self._config=Config()
|
||||||
|
self._config.loadFromFile(self._configFile)
|
||||||
|
self._accountList=self._config.getAccounts()
|
||||||
|
for account in self._accountList:
|
||||||
|
account.connect()
|
||||||
|
agents=account.getAgents()
|
||||||
|
self._commonTransports.update(agents)
|
||||||
|
for transport in self._commonTransports.keys():
|
||||||
|
print "Transport: "+transport
|
||||||
|
|
||||||
|
def giveTransport(self,hostName):
|
||||||
|
if self._jabservers.has_key(hostName):
|
||||||
|
trans_proto=hostName
|
||||||
|
return trans_proto
|
||||||
|
else:
|
||||||
|
if self._commonTransports.has_key(hostName):
|
||||||
|
trans_proto=self._commonTransports[hostName]
|
||||||
|
return trans_proto
|
||||||
|
else:
|
||||||
|
# TODO: ask user input
|
||||||
|
is_jabber=Answer(\
|
||||||
|
"# ERR : is "+hostName+" a jabber server ? [y/n]\n",\
|
||||||
|
["y","n"]).get()
|
||||||
|
if is_jabber == "y":
|
||||||
|
self._jabservers[hostName]=1
|
||||||
|
else:
|
||||||
|
what_tp_ans={\
|
||||||
|
"a" : "aim",\
|
||||||
|
"i" : "icq",\
|
||||||
|
"r" : "irc",\
|
||||||
|
"g" : "gadu",\
|
||||||
|
"m" : "msn",\
|
||||||
|
"p" : "public",\
|
||||||
|
"v" : "private",\
|
||||||
|
"y" : "yahoo",\
|
||||||
|
"-" : "forget"}
|
||||||
|
what_transport=Answer(\
|
||||||
|
" Select transport type :\n"+\
|
||||||
|
" [a]im"+\
|
||||||
|
" [i]cq"+\
|
||||||
|
" i[r]c):"+\
|
||||||
|
" [g]adu"+\
|
||||||
|
" [m]sn"+\
|
||||||
|
" [p]ublic:"+\
|
||||||
|
" pri[v]ate:"+\
|
||||||
|
" [y]ahoo"+\
|
||||||
|
" [-] Forget JIDs using this host",\
|
||||||
|
what_tp_ans.keys())
|
||||||
|
trans_proto=what_tp_ans[what_transport]
|
||||||
|
if trans_proto == "forget":
|
||||||
|
# TODO: ajouter regles d'exclusion
|
||||||
|
zero=0
|
||||||
|
else:
|
||||||
|
# TODO: ajouter transport a la config XML
|
||||||
|
zero=0
|
||||||
|
return self.giveTransport(hostName)
|
||||||
|
|
||||||
|
def get(self):
|
||||||
|
#get Roster
|
||||||
|
for account in self._accountList:
|
||||||
|
roster=account.getRoster()
|
||||||
|
# fusionner les roster
|
||||||
|
jid_list=roster.getJIDs()
|
||||||
|
for jid in jid_list:
|
||||||
|
transport=jid.getDomain()
|
||||||
|
trans_proto=self.giveTransport(transport)
|
||||||
|
if not self._commonJIDs.has_key(trans_proto):
|
||||||
|
self._commonJIDs[trans_proto]={}
|
||||||
|
jid_name=roster.getName(jid)
|
||||||
|
jid_groups=roster.getGroups(jid)
|
||||||
|
if not jid_name: jid_name=jid.getNode()
|
||||||
|
if not self._commonJIDs[trans_proto].has_key(jid.getNode()):
|
||||||
|
self._commonJIDs[trans_proto][jid.getNode()]=(jid_name,jid_groups)
|
||||||
|
# print " <- "+jid.getNode()+" @ "+trans_proto+" = "+jid_name
|
||||||
|
print "\x1B[G <- "+jid.getNode()+" @ "+trans_proto+" = "+jid_name
|
||||||
|
|
||||||
|
#upload rosters
|
||||||
|
def set(self):
|
||||||
|
for account in self._accountList:
|
||||||
|
account.setRoster(self._commonJIDs)
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
for account in self._accountList:
|
||||||
|
account.disconnect()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
jabsync=JabSync()
|
||||||
|
jabsync.parseCmdLine()
|
||||||
|
jabsync.init()
|
||||||
|
jabsync.get()
|
||||||
|
jabsync.set()
|
||||||
|
jabsync.stop()
|
||||||
|
|
Loading…
Reference in a new issue