xmpppy changes:
- Sync with latest CVS version + gajim patches. - streamErrorHandler disabled. If you want enable it - unrem it at line 66 of dispatcher.py - TLS re-enabled. Should work fine now - disconnection TLS plugout re-enabled. Didn't successed in reproducing problem though so maybe not fixed. - My temporary fixes replaced with CVS ones. gajim connection.py changes (in chunks order): - getTags is incorrect. Replaced with getChildren - browseAgents is absent from xmpppy. Fixed with manual node send. Made use of buildReply method and con argument - formatting fix - crude fixed register problem. I do not know how to do it properly. It is client stuff. Honest! I have no idea how to make it non-blocking and yet make library to fallback to older protocols. getInstructions() moved to xmpppy Thanks Alexey !
This commit is contained in:
parent
66249dafb5
commit
56d60f3fd5
|
@ -328,7 +328,7 @@ class Connection:
|
||||||
for key in q.getAttrs().keys():
|
for key in q.getAttrs().keys():
|
||||||
attr[key.encode('utf8')] = q.getAttr(key).encode('utf8')
|
attr[key.encode('utf8')] = q.getAttr(key).encode('utf8')
|
||||||
identities = [attr]
|
identities = [attr]
|
||||||
for node in q.getTags():
|
for node in q.getChildren():
|
||||||
if node.getName() == 'ns':
|
if node.getName() == 'ns':
|
||||||
features.append(node.getData())
|
features.append(node.getData())
|
||||||
else:
|
else:
|
||||||
|
@ -387,24 +387,22 @@ class Connection:
|
||||||
features.append(i.getAttr('var'))
|
features.append(i.getAttr('var'))
|
||||||
jid = str(iq_obj.getFrom())
|
jid = str(iq_obj.getFrom())
|
||||||
if not identities:
|
if not identities:
|
||||||
self.connection.browseAgents(jid, node)
|
self.connection.send(common.xmpp.Iq(typ = 'get', queryNS = \
|
||||||
|
common.xmpp.NS_AGENTS))
|
||||||
else:
|
else:
|
||||||
self.dispatch('AGENT_INFO_INFO', (jid, node, identities, features))
|
self.dispatch('AGENT_INFO_INFO', (jid, node, identities, features))
|
||||||
self.discoverItems(jid, node)
|
self.discoverItems(jid, node)
|
||||||
|
|
||||||
def _VersionCB(self, con, iq_obj):
|
def _VersionCB(self, con, iq_obj):
|
||||||
gajim.log.debug('VersionCB')
|
gajim.log.debug('VersionCB')
|
||||||
f = iq_obj.getFrom()
|
iq_obj = iq_obj.buildReply('result')
|
||||||
iq_obj.setFrom(iq_obj.getTo())
|
|
||||||
iq_obj.setTo(f)
|
|
||||||
iq_obj.setType('result')
|
|
||||||
qp = iq_obj.getTag('query')
|
qp = iq_obj.getTag('query')
|
||||||
qp.setTagData('name', 'Gajim')
|
qp.setTagData('name', 'Gajim')
|
||||||
qp.setTagData('version', gajim.version)
|
qp.setTagData('version', gajim.version)
|
||||||
send_os = gajim.config.get('send_os_info')
|
send_os = gajim.config.get('send_os_info')
|
||||||
if send_os:
|
if send_os:
|
||||||
qp.setTagData('os', get_os_info())
|
qp.setTagData('os', get_os_info())
|
||||||
self.connection.send(iq_obj)
|
con.send(iq_obj)
|
||||||
|
|
||||||
def _VersionResultCB(self, con, iq_obj):
|
def _VersionResultCB(self, con, iq_obj):
|
||||||
gajim.log.debug('VersionResultCB')
|
gajim.log.debug('VersionResultCB')
|
||||||
|
@ -638,8 +636,7 @@ class Connection:
|
||||||
prio = str(gajim.config.get_per('accounts', self.name, 'priority'))
|
prio = str(gajim.config.get_per('accounts', self.name, 'priority'))
|
||||||
p = common.xmpp.Presence(typ = ptype, priority = prio, show = status,
|
p = common.xmpp.Presence(typ = ptype, priority = prio, show = status,
|
||||||
status = msg)
|
status = msg)
|
||||||
if signed: p.setTag(common.xmpp.NS_SIGNED + ' x').setData(
|
if signed: p.setTag(common.xmpp.NS_SIGNED + ' x').setData(signed)
|
||||||
signed)
|
|
||||||
self.connection.send(p)
|
self.connection.send(p)
|
||||||
self.dispatch('STATUS', status)
|
self.dispatch('STATUS', status)
|
||||||
|
|
||||||
|
@ -712,17 +709,14 @@ class Connection:
|
||||||
|
|
||||||
def request_agents(self, jid, node):
|
def request_agents(self, jid, node):
|
||||||
if self.connection:
|
if self.connection:
|
||||||
|
self.connection.send(common.xmpp.Iq(to = jid, typ = 'get',
|
||||||
|
queryNS = common.xmpp.NS_BROWSE))
|
||||||
self.discoverInfo(jid, node)
|
self.discoverInfo(jid, node)
|
||||||
|
|
||||||
def ask_register_agent_info(self, agent):
|
def ask_register_agent_info(self, agent):
|
||||||
if not self.connection:
|
if not self.connection:
|
||||||
return None
|
return None
|
||||||
data = common.xmpp.features.getRegInfo(self.connection, agent) # FIXME: blocking
|
return common.xmpp.features.getRegInfo(self.connection, agent).asDict() # FIXME: blocking
|
||||||
info = data.asDict()
|
|
||||||
instructions = data.getInstructions()
|
|
||||||
if instructions:
|
|
||||||
info['instructions'] = instructions
|
|
||||||
return info
|
|
||||||
|
|
||||||
def register_agent(self, agent, info):
|
def register_agent(self, agent, info):
|
||||||
if not self.connection:
|
if not self.connection:
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
## GNU General Public License for more details.
|
## GNU General Public License for more details.
|
||||||
|
|
||||||
# $Id: auth.py,v 1.25 2005/03/08 19:36:29 snakeru Exp $
|
# $Id: auth.py,v 1.27 2005/04/30 10:17:20 snakeru Exp $
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Provides library with all Non-SASL and SASL authentication mechanisms.
|
Provides library with all Non-SASL and SASL authentication mechanisms.
|
||||||
|
@ -97,7 +97,8 @@ class NonSASL(PlugIn):
|
||||||
class SASL(PlugIn):
|
class SASL(PlugIn):
|
||||||
""" Implements SASL authentication. """
|
""" Implements SASL authentication. """
|
||||||
def plugin(self,owner):
|
def plugin(self,owner):
|
||||||
self.startsasl=None
|
if not self._owner.Dispatcher.Stream._document_attrs.has_key('version'): self.startsasl='not-supported'
|
||||||
|
else: self.startsasl=None
|
||||||
|
|
||||||
def auth(self,username,password):
|
def auth(self,username,password):
|
||||||
""" Start authentication. Result can be obtained via "SASL.startsasl" attribute and will be
|
""" Start authentication. Result can be obtained via "SASL.startsasl" attribute and will be
|
||||||
|
@ -120,7 +121,7 @@ class SASL(PlugIn):
|
||||||
def FeaturesHandler(self,conn,feats):
|
def FeaturesHandler(self,conn,feats):
|
||||||
""" Used to determine if server supports SASL auth. Used internally. """
|
""" Used to determine if server supports SASL auth. Used internally. """
|
||||||
if not feats.getTag('mechanisms',namespace=NS_SASL):
|
if not feats.getTag('mechanisms',namespace=NS_SASL):
|
||||||
self.startsasl='failure'
|
self.startsasl='not-supported'
|
||||||
self.DEBUG('SASL not supported by server','error')
|
self.DEBUG('SASL not supported by server','error')
|
||||||
return
|
return
|
||||||
mecs=[]
|
mecs=[]
|
||||||
|
@ -213,7 +214,7 @@ class Bind(PlugIn):
|
||||||
except NodeProcessed: pass
|
except NodeProcessed: pass
|
||||||
else: self._owner.RegisterHandler('features',self.FeaturesHandler,xmlns=NS_STREAMS)
|
else: self._owner.RegisterHandler('features',self.FeaturesHandler,xmlns=NS_STREAMS)
|
||||||
|
|
||||||
def plugout(self,owner):
|
def plugout(self):
|
||||||
""" Remove Bind handler from owner's dispatcher. Used internally. """
|
""" Remove Bind handler from owner's dispatcher. Used internally. """
|
||||||
self._owner.UnregisterHandler('features',self.FeaturesHandler,xmlns=NS_STREAMS)
|
self._owner.UnregisterHandler('features',self.FeaturesHandler,xmlns=NS_STREAMS)
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
## GNU General Public License for more details.
|
## GNU General Public License for more details.
|
||||||
|
|
||||||
# $Id: browser.py,v 1.8 2004/12/24 19:56:35 snakeru Exp $
|
# $Id: browser.py,v 1.9 2005/04/30 07:13:33 snakeru Exp $
|
||||||
|
|
||||||
"""Browser module provides DISCO server framework for your application.
|
"""Browser module provides DISCO server framework for your application.
|
||||||
This functionality can be used for very different purposes - from publishing
|
This functionality can be used for very different purposes - from publishing
|
||||||
|
@ -27,7 +27,9 @@ from dispatcher import *
|
||||||
from client import PlugIn
|
from client import PlugIn
|
||||||
|
|
||||||
class Browser(PlugIn):
|
class Browser(PlugIn):
|
||||||
""" Standart xmpppy class that is ancestor of PlugIn and can be attached
|
""" WARNING! This class is for components only. It will not work in client mode!
|
||||||
|
|
||||||
|
Standart xmpppy class that is ancestor of PlugIn and can be attached
|
||||||
to your application.
|
to your application.
|
||||||
All processing will be performed in the handlers registered in the browser
|
All processing will be performed in the handlers registered in the browser
|
||||||
instance. You can register any number of handlers ensuring that for each
|
instance. You can register any number of handlers ensuring that for each
|
||||||
|
@ -85,14 +87,14 @@ class Browser(PlugIn):
|
||||||
def plugin(self, owner):
|
def plugin(self, owner):
|
||||||
""" Registers it's own iq handlers in your application dispatcher instance.
|
""" Registers it's own iq handlers in your application dispatcher instance.
|
||||||
Used internally."""
|
Used internally."""
|
||||||
owner.RegisterHandler('iq',self._DiscoveryHandler,ns=NS_DISCO_INFO)
|
owner.RegisterHandler('iq',self._DiscoveryHandler,typ='get',ns=NS_DISCO_INFO)
|
||||||
owner.RegisterHandler('iq',self._DiscoveryHandler,ns=NS_DISCO_ITEMS)
|
owner.RegisterHandler('iq',self._DiscoveryHandler,typ='get',ns=NS_DISCO_ITEMS)
|
||||||
|
|
||||||
def plugout(self):
|
def plugout(self):
|
||||||
""" Unregisters browser's iq handlers from your application dispatcher instance.
|
""" Unregisters browser's iq handlers from your application dispatcher instance.
|
||||||
Used internally."""
|
Used internally."""
|
||||||
self._owner.UnregisterHandler('iq',self._DiscoveryHandler,ns=NS_DISCO_INFO)
|
self._owner.UnregisterHandler('iq',self._DiscoveryHandler,typ='get',ns=NS_DISCO_INFO)
|
||||||
self._owner.UnregisterHandler('iq',self._DiscoveryHandler,ns=NS_DISCO_ITEMS)
|
self._owner.UnregisterHandler('iq',self._DiscoveryHandler,typ='get',ns=NS_DISCO_ITEMS)
|
||||||
|
|
||||||
def _traversePath(self,node,jid,set=0):
|
def _traversePath(self,node,jid,set=0):
|
||||||
""" Returns dictionary and key or None,None
|
""" Returns dictionary and key or None,None
|
||||||
|
@ -136,7 +138,7 @@ class Browser(PlugIn):
|
||||||
{'jid':'jid2','action':'action2','node':'node2','name':'name2'},
|
{'jid':'jid2','action':'action2','node':'node2','name':'name2'},
|
||||||
{'jid':'jid3','node':'node3','name':'name3'},
|
{'jid':'jid3','node':'node3','name':'name3'},
|
||||||
{'jid':'jid4','node':'node4'}
|
{'jid':'jid4','node':'node4'}
|
||||||
]
|
],
|
||||||
'info' :{
|
'info' :{
|
||||||
'ids':[
|
'ids':[
|
||||||
{'category':'category1','type':'type1','name':'name1'},
|
{'category':'category1','type':'type1','name':'name1'},
|
||||||
|
@ -182,7 +184,9 @@ class Browser(PlugIn):
|
||||||
to handle the request. Used internally.
|
to handle the request. Used internally.
|
||||||
"""
|
"""
|
||||||
handler=self.getDiscoHandler(request.getQuerynode(),request.getTo())
|
handler=self.getDiscoHandler(request.getQuerynode(),request.getTo())
|
||||||
if not handler: return conn.send(Error(request,ERR_ITEM_NOT_FOUND))
|
if not handler:
|
||||||
|
conn.send(Error(request,ERR_ITEM_NOT_FOUND))
|
||||||
|
raise NodeProcessed
|
||||||
rep=request.buildReply('result')
|
rep=request.buildReply('result')
|
||||||
q=rep.getTag('query')
|
q=rep.getTag('query')
|
||||||
if request.getQueryNS()==NS_DISCO_ITEMS:
|
if request.getQueryNS()==NS_DISCO_ITEMS:
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
## GNU General Public License for more details.
|
## GNU General Public License for more details.
|
||||||
|
|
||||||
# $Id: client.py,v 1.33 2005/04/10 08:09:23 snakeru Exp $
|
# $Id: client.py,v 1.35 2005/04/30 10:17:19 snakeru Exp $
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Provides PlugIn class functionality to develop extentions for xmpppy.
|
Provides PlugIn class functionality to develop extentions for xmpppy.
|
||||||
|
@ -105,7 +105,7 @@ class CommonClient:
|
||||||
self.debug_flags.append(self.DBG)
|
self.debug_flags.append(self.DBG)
|
||||||
self._owner=self
|
self._owner=self
|
||||||
self._registered_name=None
|
self._registered_name=None
|
||||||
# self.RegisterDisconnectHandler(self.DisconnectHandler)
|
self.RegisterDisconnectHandler(self.DisconnectHandler)
|
||||||
self.connected=''
|
self.connected=''
|
||||||
|
|
||||||
def RegisterDisconnectHandler(self,handler):
|
def RegisterDisconnectHandler(self,handler):
|
||||||
|
@ -123,7 +123,7 @@ class CommonClient:
|
||||||
self.disconnect_handlers.reverse()
|
self.disconnect_handlers.reverse()
|
||||||
for i in self.disconnect_handlers: i()
|
for i in self.disconnect_handlers: i()
|
||||||
self.disconnect_handlers.reverse()
|
self.disconnect_handlers.reverse()
|
||||||
# if self.__dict__.has_key('TLS'): self.TLS.PlugOut()
|
if self.__dict__.has_key('TLS'): self.TLS.PlugOut()
|
||||||
|
|
||||||
def DisconnectHandler(self):
|
def DisconnectHandler(self):
|
||||||
""" Default disconnect handler. Just raises an IOError.
|
""" Default disconnect handler. Just raises an IOError.
|
||||||
|
@ -156,9 +156,9 @@ class CommonClient:
|
||||||
if not connected: return
|
if not connected: return
|
||||||
self._Server,self._Proxy=server,proxy
|
self._Server,self._Proxy=server,proxy
|
||||||
self.connected='tcp'
|
self.connected='tcp'
|
||||||
# if self.Connection.getPort()==5223:
|
if self.Connection.getPort()==5223:
|
||||||
# transports.TLS().PlugIn(self,now=1)
|
transports.TLS().PlugIn(self,now=1)
|
||||||
# self.connected='tls'
|
self.connected='tls'
|
||||||
dispatcher.Dispatcher().PlugIn(self)
|
dispatcher.Dispatcher().PlugIn(self)
|
||||||
while self.Dispatcher.Stream._document_attrs is None: self.Process(1)
|
while self.Dispatcher.Stream._document_attrs is None: self.Process(1)
|
||||||
if self.Dispatcher.Stream._document_attrs.has_key('version') and self.Dispatcher.Stream._document_attrs['version']=='1.0':
|
if self.Dispatcher.Stream._document_attrs.has_key('version') and self.Dispatcher.Stream._document_attrs['version']=='1.0':
|
||||||
|
@ -173,32 +173,32 @@ class Client(CommonClient):
|
||||||
specify it's address and credentials (if needed) in the second argument.
|
specify it's address and credentials (if needed) in the second argument.
|
||||||
Example: connect(('192.168.5.5':5222),{'host':'proxy.my.net','port':8080,'user':'me','password':'secret'})"""
|
Example: connect(('192.168.5.5':5222),{'host':'proxy.my.net','port':8080,'user':'me','password':'secret'})"""
|
||||||
if not CommonClient.connect(self,server,proxy): return self.connected
|
if not CommonClient.connect(self,server,proxy): return self.connected
|
||||||
# transports.TLS().PlugIn(self)
|
transports.TLS().PlugIn(self)
|
||||||
if not self.Dispatcher.Stream._document_attrs.has_key('version') or not self.Dispatcher.Stream._document_attrs['version']=='1.0': return self.connected
|
if not self.Dispatcher.Stream._document_attrs.has_key('version') or not self.Dispatcher.Stream._document_attrs['version']=='1.0': return self.connected
|
||||||
while not self.Dispatcher.Stream.features and self.Process(): pass # If we get version 1.0 stream the features tag MUST BE presented
|
while not self.Dispatcher.Stream.features and self.Process(): pass # If we get version 1.0 stream the features tag MUST BE presented
|
||||||
# if not self.Dispatcher.Stream.features.getTag('starttls'): return self.connected # TLS not supported by server
|
if not self.Dispatcher.Stream.features.getTag('starttls'): return self.connected # TLS not supported by server
|
||||||
# while not self.TLS.starttls and self.Process(): pass
|
while not self.TLS.starttls and self.Process(): pass
|
||||||
# if self.TLS.starttls<>'success': self.event('tls_failed'); return self.connected
|
if self.TLS.starttls<>'success': self.event('tls_failed'); return self.connected
|
||||||
# self.connected='tls'
|
self.connected='tls'
|
||||||
return self.connected
|
return self.connected
|
||||||
|
|
||||||
def auth(self,user,password,resource=''):
|
def auth(self,user,password,resource=''):
|
||||||
""" Authenticate connnection and bind resource. If resource is not provided
|
""" Authenticate connnection and bind resource. If resource is not provided
|
||||||
random one or library name used. """
|
random one or library name used. """
|
||||||
self._User,self._Password,self._Resource=user,password,resource
|
self._User,self._Password,self._Resource=user,password,resource
|
||||||
auth.SASL().PlugIn(self)
|
|
||||||
self.SASL.auth(user,password)
|
|
||||||
while not self.Dispatcher.Stream._document_attrs and self.Process(): pass
|
while not self.Dispatcher.Stream._document_attrs and self.Process(): pass
|
||||||
if self.Dispatcher.Stream._document_attrs.has_key('version') and self.Dispatcher.Stream._document_attrs['version']=='1.0':
|
if self.Dispatcher.Stream._document_attrs.has_key('version') and self.Dispatcher.Stream._document_attrs['version']=='1.0':
|
||||||
while not self.Dispatcher.Stream.features and self.Process(): pass # If we get version 1.0 stream the features tag MUST BE presented
|
while not self.Dispatcher.Stream.features and self.Process(): pass # If we get version 1.0 stream the features tag MUST BE presented
|
||||||
while self.SASL.startsasl=='in-process' and self.Process(): pass
|
auth.SASL().PlugIn(self)
|
||||||
else: self.SASL.startsasl='failure'
|
if self.SASL.startsasl=='not-supported':
|
||||||
if self.SASL.startsasl=='failure':
|
|
||||||
if not resource: resource='xmpppy'
|
if not resource: resource='xmpppy'
|
||||||
if auth.NonSASL(user,password,resource).PlugIn(self):
|
if auth.NonSASL(user,password,resource).PlugIn(self):
|
||||||
self.connected+='+old_auth'
|
self.connected+='+old_auth'
|
||||||
return 'old_auth'
|
return 'old_auth'
|
||||||
else:
|
return
|
||||||
|
self.SASL.auth(user,password)
|
||||||
|
while self.SASL.startsasl=='in-process' and self.Process(): pass
|
||||||
|
if self.SASL.startsasl=='success':
|
||||||
auth.Bind().PlugIn(self)
|
auth.Bind().PlugIn(self)
|
||||||
while self.Bind.bound is None: self.Process()
|
while self.Bind.bound is None: self.Process()
|
||||||
if self.Bind.Bind(resource):
|
if self.Bind.Bind(resource):
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
## $Id: commands.py,v 1.3 2005/03/08 19:50:43 snakeru Exp $
|
## $Id: commands.py,v 1.4 2005/04/30 07:33:11 snakeru Exp $
|
||||||
|
|
||||||
## Ad-Hoc Command manager
|
## Ad-Hoc Command manager
|
||||||
## Mike Albon (c) 5th January 2005
|
## Mike Albon (c) 5th January 2005
|
||||||
|
@ -34,8 +34,6 @@ What it supplies:
|
||||||
from xmpp.protocol import *
|
from xmpp.protocol import *
|
||||||
from xmpp.client import PlugIn
|
from xmpp.client import PlugIn
|
||||||
|
|
||||||
NS_COMMANDS='http://jabber.org/protocol/commands'
|
|
||||||
|
|
||||||
class Commands(PlugIn):
|
class Commands(PlugIn):
|
||||||
"""Commands is an ancestor of Plugin and can be attached to any session.
|
"""Commands is an ancestor of Plugin and can be attached to any session.
|
||||||
|
|
||||||
|
@ -167,7 +165,10 @@ class Commands(PlugIn):
|
||||||
return self._handlers[jid][name]
|
return self._handlers[jid][name]
|
||||||
|
|
||||||
class Command_Handler_Prototype(PlugIn):
|
class Command_Handler_Prototype(PlugIn):
|
||||||
"""This is a prototype command handler, as each command uses a disco method and execute method you can implement it any way you like, however this is my first attempt at making a generic handler that you can hang process stages on too. There is an example command below.
|
"""This is a prototype command handler, as each command uses a disco method
|
||||||
|
and execute method you can implement it any way you like, however this is
|
||||||
|
my first attempt at making a generic handler that you can hang process
|
||||||
|
stages on too. There is an example command below.
|
||||||
|
|
||||||
The parameters are as follows:
|
The parameters are as follows:
|
||||||
name : the name of the command within the jabber environment
|
name : the name of the command within the jabber environment
|
||||||
|
@ -241,14 +242,19 @@ class Command_Handler_Prototype(PlugIn):
|
||||||
return self.discoinfo
|
return self.discoinfo
|
||||||
|
|
||||||
class TestCommand(Command_Handler_Prototype):
|
class TestCommand(Command_Handler_Prototype):
|
||||||
|
""" Example class. You should read source if you wish to understate how it works.
|
||||||
|
Generally, it presents a "master" that giudes user through to calculate something.
|
||||||
|
"""
|
||||||
name = 'testcommand'
|
name = 'testcommand'
|
||||||
description = 'a noddy example command'
|
description = 'a noddy example command'
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
""" Init internal constants. """
|
||||||
Command_Handler_Prototype.__init__(self)
|
Command_Handler_Prototype.__init__(self)
|
||||||
self.pi = 3.14
|
self.pi = 3.14
|
||||||
self.initial = {'execute':self.cmdFirstStage}
|
self.initial = {'execute':self.cmdFirstStage}
|
||||||
|
|
||||||
def cmdFirstStage(self,conn,request):
|
def cmdFirstStage(self,conn,request):
|
||||||
|
""" Determine """
|
||||||
# This is the only place this should be repeated as all other stages should have SessionIDs
|
# This is the only place this should be repeated as all other stages should have SessionIDs
|
||||||
try:
|
try:
|
||||||
session = request.getTagAttr('command','sessionid')
|
session = request.getTagAttr('command','sessionid')
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
## GNU General Public License for more details.
|
## GNU General Public License for more details.
|
||||||
|
|
||||||
# $Id: dispatcher.py,v 1.31 2005/03/08 19:36:29 snakeru Exp $
|
# $Id: dispatcher.py,v 1.34 2005/05/02 08:36:41 snakeru Exp $
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Main xmpppy mechanism. Provides library with methods to assign different handlers
|
Main xmpppy mechanism. Provides library with methods to assign different handlers
|
||||||
|
@ -55,6 +55,7 @@ class Dispatcher(PlugIn):
|
||||||
self.handlers=handlers
|
self.handlers=handlers
|
||||||
|
|
||||||
def _init(self):
|
def _init(self):
|
||||||
|
""" Registers default namespaces/protocols/handlers. Used internally. """
|
||||||
self.RegisterNamespace('unknown')
|
self.RegisterNamespace('unknown')
|
||||||
self.RegisterNamespace(NS_STREAMS)
|
self.RegisterNamespace(NS_STREAMS)
|
||||||
self.RegisterNamespace(self._owner.defaultNamespace)
|
self.RegisterNamespace(self._owner.defaultNamespace)
|
||||||
|
@ -62,6 +63,7 @@ class Dispatcher(PlugIn):
|
||||||
self.RegisterProtocol('presence',Presence)
|
self.RegisterProtocol('presence',Presence)
|
||||||
self.RegisterProtocol('message',Message)
|
self.RegisterProtocol('message',Message)
|
||||||
self.RegisterDefaultHandler(self.returnStanzaHandler)
|
self.RegisterDefaultHandler(self.returnStanzaHandler)
|
||||||
|
# self.RegisterHandler('error',self.streamErrorHandler,xmlns=NS_STREAMS)
|
||||||
|
|
||||||
def plugin(self, owner):
|
def plugin(self, owner):
|
||||||
""" Plug the Dispatcher instance into Client class instance and send initial stream header. Used internally."""
|
""" Plug the Dispatcher instance into Client class instance and send initial stream header. Used internally."""
|
||||||
|
@ -74,6 +76,7 @@ class Dispatcher(PlugIn):
|
||||||
self.StreamInit()
|
self.StreamInit()
|
||||||
|
|
||||||
def plugout(self):
|
def plugout(self):
|
||||||
|
""" Prepares instance to be destructed. """
|
||||||
self.Stream.dispatch=None
|
self.Stream.dispatch=None
|
||||||
self.Stream.DEBUG=None
|
self.Stream.DEBUG=None
|
||||||
self.Stream.features=None
|
self.Stream.features=None
|
||||||
|
@ -99,7 +102,10 @@ class Dispatcher(PlugIn):
|
||||||
Returns:
|
Returns:
|
||||||
1) length of processed data if some data were processed;
|
1) length of processed data if some data were processed;
|
||||||
2) '0' string if no data were processed but link is alive;
|
2) '0' string if no data were processed but link is alive;
|
||||||
3) 0 (zero) if underlying connection is closed."""
|
3) 0 (zero) if underlying connection is closed.
|
||||||
|
Take note that in case of disconnection detect during Process() call
|
||||||
|
disconnect handlers are called automatically.
|
||||||
|
"""
|
||||||
if time.time() > self._lastIncome + 60: #1 min
|
if time.time() > self._lastIncome + 60: #1 min
|
||||||
iq = Iq('get', NS_LAST, to=self._owner.Server)
|
iq = Iq('get', NS_LAST, to=self._owner.Server)
|
||||||
self.send(iq)
|
self.send(iq)
|
||||||
|
@ -107,10 +113,12 @@ class Dispatcher(PlugIn):
|
||||||
self.disconnected()
|
self.disconnected()
|
||||||
for handler in self._cycleHandlers: handler(self)
|
for handler in self._cycleHandlers: handler(self)
|
||||||
if self._owner.Connection.pending_data(timeout):
|
if self._owner.Connection.pending_data(timeout):
|
||||||
data=self._owner.Connection.receive()
|
try: data=self._owner.Connection.receive()
|
||||||
|
except IOError: return
|
||||||
self.Stream.Parse(data)
|
self.Stream.Parse(data)
|
||||||
self._lastIncome = time.time()
|
if data:
|
||||||
return len(data)
|
self._lastIncome = time.time()
|
||||||
|
return len(data)
|
||||||
return '0' # It means that nothing is received but link is alive.
|
return '0' # It means that nothing is received but link is alive.
|
||||||
|
|
||||||
def RegisterNamespace(self,xmlns,order='info'):
|
def RegisterNamespace(self,xmlns,order='info'):
|
||||||
|
@ -190,6 +198,16 @@ class Dispatcher(PlugIn):
|
||||||
if stanza.getType() in ['get','set']:
|
if stanza.getType() in ['get','set']:
|
||||||
conn.send(Error(stanza,ERR_FEATURE_NOT_IMPLEMENTED))
|
conn.send(Error(stanza,ERR_FEATURE_NOT_IMPLEMENTED))
|
||||||
|
|
||||||
|
def streamErrorHandler(self,conn,error):
|
||||||
|
name,text='error',error.getData()
|
||||||
|
for tag in error.getChildren():
|
||||||
|
if tag.getNamespace()==NS_XMPP_STREAMS:
|
||||||
|
if tag.getName()=='text': text=tag.getData()
|
||||||
|
else: name=tag.getName()
|
||||||
|
if name in stream_exceptions.keys(): exc=stream_exceptions[name]
|
||||||
|
else: exc=StreamError
|
||||||
|
raise exc((name,text))
|
||||||
|
|
||||||
def RegisterCycleHandler(self,handler):
|
def RegisterCycleHandler(self,handler):
|
||||||
""" Register handler that will be called on every Dispatcher.Process() call. """
|
""" Register handler that will be called on every Dispatcher.Process() call. """
|
||||||
if handler not in self._cycleHandlers: self._cycleHandlers.append(handler)
|
if handler not in self._cycleHandlers: self._cycleHandlers.append(handler)
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
## GNU General Public License for more details.
|
## GNU General Public License for more details.
|
||||||
|
|
||||||
# $Id: features.py,v 1.19 2004/12/25 20:06:59 snakeru Exp $
|
# $Id: features.py,v 1.20 2005/04/30 07:43:01 snakeru Exp $
|
||||||
|
|
||||||
"""
|
"""
|
||||||
This module contains variable stuff that is not worth splitting into separate modules.
|
This module contains variable stuff that is not worth splitting into separate modules.
|
||||||
|
@ -88,10 +88,9 @@ def getRegInfo(disp,host,info={}):
|
||||||
if df: return DataForm(node=df)
|
if df: return DataForm(node=df)
|
||||||
df=DataForm(typ='form')
|
df=DataForm(typ='form')
|
||||||
for i in resp.getQueryPayload():
|
for i in resp.getQueryPayload():
|
||||||
try: #FIXME: temporary patch by Alexey to make it work :|
|
if type(i)<>type(iq): pass
|
||||||
if i.getName()=='instructions': df.addInstructions(i.getData())
|
elif i.getName()=='instructions': df.addInstructions(i.getData())
|
||||||
else: df.setField(i.getName()).setValue(i.getData())
|
else: df.setField(i.getName()).setValue(i.getData())
|
||||||
except: pass
|
|
||||||
return df
|
return df
|
||||||
|
|
||||||
def register(disp,host,info):
|
def register(disp,host,info):
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
## GNU General Public License for more details.
|
## GNU General Public License for more details.
|
||||||
|
|
||||||
# $Id: protocol.py,v 1.39 2005/03/08 19:36:29 snakeru Exp $
|
# $Id: protocol.py,v 1.41 2005/05/02 08:36:41 snakeru Exp $
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Protocol module contains tools that is needed for processing of
|
Protocol module contains tools that is needed for processing of
|
||||||
|
@ -28,13 +28,13 @@ NS_AUTH ='jabber:iq:auth'
|
||||||
NS_BIND ='urn:ietf:params:xml:ns:xmpp-bind'
|
NS_BIND ='urn:ietf:params:xml:ns:xmpp-bind'
|
||||||
NS_BROWSE ='jabber:iq:browse'
|
NS_BROWSE ='jabber:iq:browse'
|
||||||
NS_CLIENT ='jabber:client'
|
NS_CLIENT ='jabber:client'
|
||||||
|
NS_COMMANDS ='http://jabber.org/protocol/commands'
|
||||||
NS_COMPONENT_ACCEPT='jabber:component:accept'
|
NS_COMPONENT_ACCEPT='jabber:component:accept'
|
||||||
NS_DATA ='jabber:x:data' # JEP-0004
|
NS_DATA ='jabber:x:data' # JEP-0004
|
||||||
NS_DELAY ='jabber:x:delay'
|
NS_DELAY ='jabber:x:delay'
|
||||||
NS_DIALBACK ='jabber:server:dialback'
|
NS_DIALBACK ='jabber:server:dialback'
|
||||||
NS_DISCO_INFO ='http://jabber.org/protocol/disco#info'
|
NS_DISCO_INFO ='http://jabber.org/protocol/disco#info'
|
||||||
NS_DISCO_ITEMS ='http://jabber.org/protocol/disco#items'
|
NS_DISCO_ITEMS ='http://jabber.org/protocol/disco#items'
|
||||||
NS_ENCRYPTED ='jabber:x:encrypted' # JEP-0027
|
|
||||||
NS_GROUPCHAT ='gc-1.0'
|
NS_GROUPCHAT ='gc-1.0'
|
||||||
NS_IBB ='http://jabber.org/protocol/ibb'
|
NS_IBB ='http://jabber.org/protocol/ibb'
|
||||||
NS_INVISIBLE ='presence-invisible' # jabberd2
|
NS_INVISIBLE ='presence-invisible' # jabberd2
|
||||||
|
@ -42,8 +42,9 @@ NS_IQ ='iq' # jabberd2
|
||||||
NS_LAST ='jabber:iq:last'
|
NS_LAST ='jabber:iq:last'
|
||||||
NS_MESSAGE ='message' # jabberd2
|
NS_MESSAGE ='message' # jabberd2
|
||||||
NS_MUC ='http://jabber.org/protocol/muc'
|
NS_MUC ='http://jabber.org/protocol/muc'
|
||||||
NS_MUC_OWNER ='http://jabber.org/protocol/muc#owner'
|
NS_MUC_USER ='http://jabber.org/protocol/muc#user'
|
||||||
NS_MUC_ADMIN ='http://jabber.org/protocol/muc#admin'
|
NS_MUC_ADMIN ='http://jabber.org/protocol/muc#admin'
|
||||||
|
NS_MUC_OWNER ='http://jabber.org/protocol/muc#owner'
|
||||||
NS_OFFLINE ='http://www.jabber.org/jeps/jep-0030.html' # JEP-0013
|
NS_OFFLINE ='http://www.jabber.org/jeps/jep-0030.html' # JEP-0013
|
||||||
NS_PRESENCE ='presence' # jabberd2
|
NS_PRESENCE ='presence' # jabberd2
|
||||||
NS_PRIVACY ='jabber:iq:privacy'
|
NS_PRIVACY ='jabber:iq:privacy'
|
||||||
|
@ -55,7 +56,6 @@ NS_SASL ='urn:ietf:params:xml:ns:xmpp-sasl'
|
||||||
NS_SEARCH ='jabber:iq:search'
|
NS_SEARCH ='jabber:iq:search'
|
||||||
NS_SERVER ='jabber:server'
|
NS_SERVER ='jabber:server'
|
||||||
NS_SESSION ='urn:ietf:params:xml:ns:xmpp-session'
|
NS_SESSION ='urn:ietf:params:xml:ns:xmpp-session'
|
||||||
NS_SIGNED ='jabber:x:signed' # JEP-0027
|
|
||||||
NS_STANZAS ='urn:ietf:params:xml:ns:xmpp-stanzas'
|
NS_STANZAS ='urn:ietf:params:xml:ns:xmpp-stanzas'
|
||||||
NS_STREAMS ='http://etherx.jabber.org/streams'
|
NS_STREAMS ='http://etherx.jabber.org/streams'
|
||||||
NS_TIME ='jabber:iq:time'
|
NS_TIME ='jabber:iq:time'
|
||||||
|
@ -63,7 +63,9 @@ NS_TLS ='urn:ietf:params:xml:ns:xmpp-tls'
|
||||||
NS_VACATION ='http://jabber.org/protocol/vacation'
|
NS_VACATION ='http://jabber.org/protocol/vacation'
|
||||||
NS_VCARD ='vcard-temp'
|
NS_VCARD ='vcard-temp'
|
||||||
NS_VERSION ='jabber:iq:version'
|
NS_VERSION ='jabber:iq:version'
|
||||||
|
NS_ENCRYPTED ='jabber:x:encrypted' # JEP-0027
|
||||||
NS_XMPP_STREAMS ='urn:ietf:params:xml:ns:xmpp-streams'
|
NS_XMPP_STREAMS ='urn:ietf:params:xml:ns:xmpp-streams'
|
||||||
|
NS_SIGNED ='jabber:x:signed' # JEP-0027
|
||||||
|
|
||||||
xmpp_stream_error_conditions="""
|
xmpp_stream_error_conditions="""
|
||||||
bad-format -- -- -- The entity has sent XML that cannot be processed.
|
bad-format -- -- -- The entity has sent XML that cannot be processed.
|
||||||
|
@ -140,8 +142,60 @@ def isResultNode(node):
|
||||||
def isErrorNode(node):
|
def isErrorNode(node):
|
||||||
""" Returns true if the node is a negative reply. """
|
""" Returns true if the node is a negative reply. """
|
||||||
return node and node.getType()=='error'
|
return node and node.getType()=='error'
|
||||||
|
|
||||||
class NodeProcessed(Exception):
|
class NodeProcessed(Exception):
|
||||||
""" Exception that should be raised by handler when the handling should be stopped. """
|
""" Exception that should be raised by handler when the handling should be stopped. """
|
||||||
|
class StreamError(Exception):
|
||||||
|
""" Base exception class for stream errors."""
|
||||||
|
class BadFormat(StreamError): pass
|
||||||
|
class BadNamespacePrefix(StreamError): pass
|
||||||
|
class Conflict(StreamError): pass
|
||||||
|
class ConnectionTimeout(StreamError): pass
|
||||||
|
class HostGone(StreamError): pass
|
||||||
|
class HostUnknown(StreamError): pass
|
||||||
|
class ImproperAddressing(StreamError): pass
|
||||||
|
class InternalServerError(StreamError): pass
|
||||||
|
class InvalidFrom(StreamError): pass
|
||||||
|
class InvalidID(StreamError): pass
|
||||||
|
class InvalidNamespace(StreamError): pass
|
||||||
|
class InvalidXML(StreamError): pass
|
||||||
|
class NotAuthorized(StreamError): pass
|
||||||
|
class PolicyViolation(StreamError): pass
|
||||||
|
class RemoteConnectionFailed(StreamError): pass
|
||||||
|
class ResourceConstraint(StreamError): pass
|
||||||
|
class RestrictedXML(StreamError): pass
|
||||||
|
class SeeOtherHost(StreamError): pass
|
||||||
|
class SystemShutdown(StreamError): pass
|
||||||
|
class UndefinedCondition(StreamError): pass
|
||||||
|
class UnsupportedEncoding(StreamError): pass
|
||||||
|
class UnsupportedStanzaType(StreamError): pass
|
||||||
|
class UnsupportedVersion(StreamError): pass
|
||||||
|
class XMLNotWellFormed(StreamError): pass
|
||||||
|
|
||||||
|
stream_exceptions = {'bad-format': BadFormat,
|
||||||
|
'bad-namespace-prefix': BadNamespacePrefix,
|
||||||
|
'conflict': Conflict,
|
||||||
|
'connection-timeout': ConnectionTimeout,
|
||||||
|
'host-gone': HostGone,
|
||||||
|
'host-unknown': HostUnknown,
|
||||||
|
'improper-addressing': ImproperAddressing,
|
||||||
|
'internal-server-error': InternalServerError,
|
||||||
|
'invalid-from': InvalidFrom,
|
||||||
|
'invalid-id': InvalidID,
|
||||||
|
'invalid-namespace': InvalidNamespace,
|
||||||
|
'invalid-xml': InvalidXML,
|
||||||
|
'not-authorized': NotAuthorized,
|
||||||
|
'policy-violation': PolicyViolation,
|
||||||
|
'remote-connection-failed': RemoteConnectionFailed,
|
||||||
|
'resource-constraint': ResourceConstraint,
|
||||||
|
'restricted-xml': RestrictedXML,
|
||||||
|
'see-other-host': SeeOtherHost,
|
||||||
|
'system-shutdown': SystemShutdown,
|
||||||
|
'undefined-condition': UndefinedCondition,
|
||||||
|
'unsupported-encoding': UnsupportedEncoding,
|
||||||
|
'unsupported-stanza-type': UnsupportedStanzaType,
|
||||||
|
'unsupported-version': UnsupportedVersion,
|
||||||
|
'xml-not-well-formed': XMLNotWellFormed}
|
||||||
|
|
||||||
class JID:
|
class JID:
|
||||||
""" JID object. JID can be built from string, modified, compared, serialised into string. """
|
""" JID object. JID can be built from string, modified, compared, serialised into string. """
|
||||||
|
@ -345,6 +399,16 @@ class Presence(Protocol):
|
||||||
def getStatus(self):
|
def getStatus(self):
|
||||||
""" Returns the status string of the message. """
|
""" Returns the status string of the message. """
|
||||||
return self.getTagData('status')
|
return self.getTagData('status')
|
||||||
|
def setPriority(self,val):
|
||||||
|
""" Sets the priority of the message. """
|
||||||
|
self.setTagData('priority',val)
|
||||||
|
def setShow(self,val):
|
||||||
|
""" Sets the show value of the message. """
|
||||||
|
self.setTagData('show',val)
|
||||||
|
def setStatus(self,val):
|
||||||
|
""" Sets the status string of the message. """
|
||||||
|
self.setTagData('status',val)
|
||||||
|
|
||||||
def _muc_getItemAttr(self,tag,attr):
|
def _muc_getItemAttr(self,tag,attr):
|
||||||
for xtag in self.getTags('x'):
|
for xtag in self.getTags('x'):
|
||||||
for child in xtag.getTags(tag):
|
for child in xtag.getTags(tag):
|
||||||
|
@ -373,15 +437,6 @@ class Presence(Protocol):
|
||||||
def getStatusCode(self):
|
def getStatusCode(self):
|
||||||
"""Returns the status code of the presence (for groupchat)"""
|
"""Returns the status code of the presence (for groupchat)"""
|
||||||
return self._muc_getItemAttr('status','code')
|
return self._muc_getItemAttr('status','code')
|
||||||
def setPriority(self,val):
|
|
||||||
""" Sets the priority of the message. """
|
|
||||||
self.setTagData('priority',val)
|
|
||||||
def setShow(self,val):
|
|
||||||
""" Sets the show value of the message. """
|
|
||||||
self.setTagData('show',val)
|
|
||||||
def setStatus(self,val):
|
|
||||||
""" Sets the status string of the message. """
|
|
||||||
self.setTagData('status',val)
|
|
||||||
|
|
||||||
class Iq(Protocol):
|
class Iq(Protocol):
|
||||||
""" XMPP Iq object - get/set dialog mechanism. """
|
""" XMPP Iq object - get/set dialog mechanism. """
|
||||||
|
@ -613,6 +668,7 @@ class DataForm(Node):
|
||||||
for i in field.getTags('value'): val.append(i.getData())
|
for i in field.getTags('value'): val.append(i.getData())
|
||||||
else: val=field.getTagData('value')
|
else: val=field.getTagData('value')
|
||||||
ret[name]=val
|
ret[name]=val
|
||||||
|
if self.getTag('instructions'): ret['instructions']=self.getInstructions()
|
||||||
return ret
|
return ret
|
||||||
def __getitem__(self,name):
|
def __getitem__(self,name):
|
||||||
""" Simple dictionary interface for getting datafields values by their names."""
|
""" Simple dictionary interface for getting datafields values by their names."""
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
## GNU General Public License for more details.
|
## GNU General Public License for more details.
|
||||||
|
|
||||||
# $Id: roster.py,v 1.16 2005/02/25 05:49:03 snakeru Exp $
|
# $Id: roster.py,v 1.17 2005/05/02 08:38:49 snakeru Exp $
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Simple roster implementation. Can be used though for different tasks like
|
Simple roster implementation. Can be used though for different tasks like
|
||||||
|
@ -98,7 +98,7 @@ class Roster(PlugIn):
|
||||||
if not pres.getTimestamp(): pres.setTimestamp()
|
if not pres.getTimestamp(): pres.setTimestamp()
|
||||||
res['timestamp']=pres.getTimestamp()
|
res['timestamp']=pres.getTimestamp()
|
||||||
elif typ=='unavailable' and item['resources'].has_key(jid.getResource()): del item['resources'][jid.getResource()]
|
elif typ=='unavailable' and item['resources'].has_key(jid.getResource()): del item['resources'][jid.getResource()]
|
||||||
# Need to handle type='error' also
|
# Need to handle type='error' also
|
||||||
|
|
||||||
def _getItemData(self,jid,dataname):
|
def _getItemData(self,jid,dataname):
|
||||||
""" Return specific jid's representation in internal format. Used internally. """
|
""" Return specific jid's representation in internal format. Used internally. """
|
||||||
|
@ -159,9 +159,6 @@ class Roster(PlugIn):
|
||||||
def getItems(self):
|
def getItems(self):
|
||||||
""" Return list of all [bare] JIDs that the roster is currently tracks."""
|
""" Return list of all [bare] JIDs that the roster is currently tracks."""
|
||||||
return self._data.keys()
|
return self._data.keys()
|
||||||
def getRaw(self):
|
|
||||||
""" Returns internal representation of roster."""
|
|
||||||
return self._data
|
|
||||||
def keys(self):
|
def keys(self):
|
||||||
""" Same as getItems. Provided for the sake of dictionary interface."""
|
""" Same as getItems. Provided for the sake of dictionary interface."""
|
||||||
return self._data.keys()
|
return self._data.keys()
|
||||||
|
@ -184,3 +181,6 @@ class Roster(PlugIn):
|
||||||
""" Unauthorise JID 'jid'. Use for declining authorisation request
|
""" Unauthorise JID 'jid'. Use for declining authorisation request
|
||||||
or for removing existing authorization. """
|
or for removing existing authorization. """
|
||||||
self._owner.send(Presence(jid,'unsubscribed'))
|
self._owner.send(Presence(jid,'unsubscribed'))
|
||||||
|
def getRaw(self):
|
||||||
|
"""Returns the internal data representation of the roster."""
|
||||||
|
return self._data
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
## GNU General Public License for more details.
|
## GNU General Public License for more details.
|
||||||
|
|
||||||
# $Id: simplexml.py,v 1.26 2005/04/10 08:21:35 snakeru Exp $
|
# $Id: simplexml.py,v 1.27 2005/04/30 07:20:27 snakeru Exp $
|
||||||
|
|
||||||
"""Simplexml module provides xmpppy library with all needed tools to handle XML nodes and XML streams.
|
"""Simplexml module provides xmpppy library with all needed tools to handle XML nodes and XML streams.
|
||||||
I'm personally using it in many other separate projects. It is designed to be as standalone as possible."""
|
I'm personally using it in many other separate projects. It is designed to be as standalone as possible."""
|
||||||
|
@ -77,9 +77,9 @@ class Node:
|
||||||
else: self.data.append(ustr(i))
|
else: self.data.append(ustr(i))
|
||||||
|
|
||||||
def __str__(self,fancy=0):
|
def __str__(self,fancy=0):
|
||||||
s = (fancy-1) * 2 * ' ' + "<" + self.name
|
|
||||||
""" Method used to dump node into textual representation.
|
""" Method used to dump node into textual representation.
|
||||||
if "fancy" argument is set to True produces indented output for readability."""
|
if "fancy" argument is set to True produces indented output for readability."""
|
||||||
|
s = (fancy-1) * 2 * ' ' + "<" + self.name
|
||||||
if self.namespace:
|
if self.namespace:
|
||||||
if not self.parent or self.parent.namespace!=self.namespace:
|
if not self.parent or self.parent.namespace!=self.namespace:
|
||||||
s = s + ' xmlns="%s"'%self.namespace
|
s = s + ' xmlns="%s"'%self.namespace
|
||||||
|
@ -249,7 +249,7 @@ class Node:
|
||||||
raise AttributeError
|
raise AttributeError
|
||||||
|
|
||||||
class T:
|
class T:
|
||||||
""" Auxiliary class used to quick acces to node's child nodes. """
|
""" Auxiliary class used to quick access to node's child nodes. """
|
||||||
def __init__(self,node): self.__dict__['node']=node
|
def __init__(self,node): self.__dict__['node']=node
|
||||||
def __getattr__(self,attr): return self.node.setTag(attr)
|
def __getattr__(self,attr): return self.node.setTag(attr)
|
||||||
def __setattr__(self,attr,val):
|
def __setattr__(self,attr,val):
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
## GNU General Public License for more details.
|
## GNU General Public License for more details.
|
||||||
|
|
||||||
# $Id: transports.py,v 1.15 2004/12/25 20:06:59 snakeru Exp $
|
# $Id: transports.py,v 1.18 2005/04/30 08:56:36 snakeru Exp $
|
||||||
|
|
||||||
"""
|
"""
|
||||||
This module contains the low-level implementations of xmpppy connect methods or
|
This module contains the low-level implementations of xmpppy connect methods or
|
||||||
|
@ -42,6 +42,7 @@ class error:
|
||||||
"""Serialise exception into pre-cached descriptive string."""
|
"""Serialise exception into pre-cached descriptive string."""
|
||||||
return self._comment
|
return self._comment
|
||||||
|
|
||||||
|
BUFLEN=1024
|
||||||
class TCPsocket(PlugIn):
|
class TCPsocket(PlugIn):
|
||||||
""" This class defines direct TCP connection method. """
|
""" This class defines direct TCP connection method. """
|
||||||
def __init__(self, server=None):
|
def __init__(self, server=None):
|
||||||
|
@ -89,21 +90,27 @@ class TCPsocket(PlugIn):
|
||||||
del self._owner.Connection
|
del self._owner.Connection
|
||||||
|
|
||||||
def receive(self):
|
def receive(self):
|
||||||
""" Reads all pending incoming data. Calls owner's disconnected() method if appropriate."""
|
""" Reads all pending incoming data.
|
||||||
try: received = self._recv(1024)
|
In case of disconnection calls owner's disconnected() method and then raises IOError exception."""
|
||||||
|
try: received = self._recv(BUFLEN)
|
||||||
|
except socket.sslerror:
|
||||||
|
self._seen_data=0
|
||||||
|
return ''
|
||||||
except: received = ''
|
except: received = ''
|
||||||
|
|
||||||
while select.select([self._sock],[],[],0)[0]:
|
while self.pending_data(0):
|
||||||
try: add = self._recv(1024)
|
try: add = self._recv(BUFLEN)
|
||||||
except: add=''
|
except: add=''
|
||||||
received +=add
|
received +=add
|
||||||
if not add: break
|
if not add: break
|
||||||
|
|
||||||
if len(received): # length of 0 means disconnect
|
if len(received): # length of 0 means disconnect
|
||||||
|
self._seen_data=1
|
||||||
self.DEBUG(received,'got')
|
self.DEBUG(received,'got')
|
||||||
else:
|
else:
|
||||||
self.DEBUG('Socket error while receiving data','error')
|
self.DEBUG('Socket error while receiving data','error')
|
||||||
self._owner.disconnected()
|
self._owner.disconnected()
|
||||||
|
raise IOError("Disconnected from server")
|
||||||
return received
|
return received
|
||||||
|
|
||||||
def send(self,raw_data):
|
def send(self,raw_data):
|
||||||
|
@ -167,18 +174,28 @@ class HTTPPROXYsocket(TCPsocket):
|
||||||
connector.append('Proxy-Authorization: Basic '+credentials)
|
connector.append('Proxy-Authorization: Basic '+credentials)
|
||||||
connector.append('\r\n')
|
connector.append('\r\n')
|
||||||
self.send('\r\n'.join(connector))
|
self.send('\r\n'.join(connector))
|
||||||
reply = self.receive().replace('\r','')
|
try: reply = self.receive().replace('\r','')
|
||||||
|
except IOError:
|
||||||
|
self.DEBUG('Proxy suddenly disconnected','error')
|
||||||
|
self._owner.disconnected()
|
||||||
|
return
|
||||||
try: proto,code,desc=reply.split('\n')[0].split(' ',2)
|
try: proto,code,desc=reply.split('\n')[0].split(' ',2)
|
||||||
except: raise error('Invalid proxy reply')
|
except: raise error('Invalid proxy reply')
|
||||||
if code<>'200':
|
if code<>'200':
|
||||||
self.DEBUG('Invalid proxy reply: %s %s %s'%(proto,code,desc),'error')
|
self.DEBUG('Invalid proxy reply: %s %s %s'%(proto,code,desc),'error')
|
||||||
self._owner.disconnected()
|
self._owner.disconnected()
|
||||||
return
|
return
|
||||||
while reply.find('\n\n') == -1: reply += self.receive().replace('\r','')
|
while reply.find('\n\n') == -1:
|
||||||
|
try: reply += self.receive().replace('\r','')
|
||||||
|
except IOError:
|
||||||
|
self.DEBUG('Proxy suddenly disconnected','error')
|
||||||
|
self._owner.disconnected()
|
||||||
|
return
|
||||||
self.DEBUG("Authentification successfull. Jabber server contacted.",'ok')
|
self.DEBUG("Authentification successfull. Jabber server contacted.",'ok')
|
||||||
return 'ok'
|
return 'ok'
|
||||||
|
|
||||||
def DEBUG(self,text,severity):
|
def DEBUG(self,text,severity):
|
||||||
|
"""Overwrites DEBUG tag to allow debug output be presented as "CONNECTproxy"."""
|
||||||
return self._owner.DEBUG(DBG_CONNECT_PROXY,text,severity)
|
return self._owner.DEBUG(DBG_CONNECT_PROXY,text,severity)
|
||||||
|
|
||||||
class TLS(PlugIn):
|
class TLS(PlugIn):
|
||||||
|
@ -202,8 +219,8 @@ class TLS(PlugIn):
|
||||||
""" Unregisters TLS handler's from owner's dispatcher. Take note that encription
|
""" Unregisters TLS handler's from owner's dispatcher. Take note that encription
|
||||||
can not be stopped once started. You can only break the connection and start over."""
|
can not be stopped once started. You can only break the connection and start over."""
|
||||||
self._owner.UnregisterHandler('features',self.FeaturesHandler,xmlns=NS_STREAMS)
|
self._owner.UnregisterHandler('features',self.FeaturesHandler,xmlns=NS_STREAMS)
|
||||||
# self._owner.UnregisterHandler('proceed',self.StartTLSHandler,xmlns=NS_TLS)
|
self._owner.UnregisterHandlerOnce('proceed',self.StartTLSHandler,xmlns=NS_TLS)
|
||||||
# self._owner.UnregisterHandler('failure',self.StartTLSHandler,xmlns=NS_TLS)
|
self._owner.UnregisterHandlerOnce('failure',self.StartTLSHandler,xmlns=NS_TLS)
|
||||||
|
|
||||||
def FeaturesHandler(self, conn, feats):
|
def FeaturesHandler(self, conn, feats):
|
||||||
""" Used to analyse server <features/> tag for TLS support.
|
""" Used to analyse server <features/> tag for TLS support.
|
||||||
|
@ -217,14 +234,25 @@ class TLS(PlugIn):
|
||||||
self._owner.Connection.send('<starttls xmlns="%s"/>'%NS_TLS)
|
self._owner.Connection.send('<starttls xmlns="%s"/>'%NS_TLS)
|
||||||
raise NodeProcessed
|
raise NodeProcessed
|
||||||
|
|
||||||
|
def pending_data(self,timeout=0):
|
||||||
|
""" Returns true if there possible is a data ready to be read. """
|
||||||
|
return self._tcpsock._seen_data or select.select([self._tcpsock._sock],[],[],timeout)[0]
|
||||||
|
|
||||||
def _startSSL(self):
|
def _startSSL(self):
|
||||||
""" Immidiatedly switch socket to TLS mode. Used internally."""
|
""" Immidiatedly switch socket to TLS mode. Used internally."""
|
||||||
|
""" Here we should switch pending_data to hint mode."""
|
||||||
tcpsock=self._owner.Connection
|
tcpsock=self._owner.Connection
|
||||||
tcpsock._sslObj = socket.ssl(tcpsock._sock, None, None)
|
tcpsock._sslObj = socket.ssl(tcpsock._sock, None, None)
|
||||||
tcpsock._sslIssuer = tcpsock._sslObj.issuer()
|
tcpsock._sslIssuer = tcpsock._sslObj.issuer()
|
||||||
tcpsock._sslServer = tcpsock._sslObj.server()
|
tcpsock._sslServer = tcpsock._sslObj.server()
|
||||||
tcpsock._recv = tcpsock._sslObj.read
|
tcpsock._recv = tcpsock._sslObj.read
|
||||||
tcpsock._send = tcpsock._sslObj.write
|
tcpsock._send = tcpsock._sslObj.write
|
||||||
|
|
||||||
|
tcpsock._seen_data=1
|
||||||
|
self._tcpsock=tcpsock
|
||||||
|
tcpsock.pending_data=self.pending_data
|
||||||
|
tcpsock._sock.setblocking(0)
|
||||||
|
|
||||||
self.starttls='success'
|
self.starttls='success'
|
||||||
|
|
||||||
def StartTLSHandler(self, conn, starttls):
|
def StartTLSHandler(self, conn, starttls):
|
||||||
|
|
Loading…
Reference in New Issue