-# Copyright 2004-2005 James Bunton <james@delx.cjb.net>
+# Copyright 2004-2006 James Bunton <james@delx.cjb.net>
# Licensed for distribution under the GPL version 2, check COPYING for details
-import utils
-if(utils.checkTwisted()):
- from twisted.xish.domish import Element
- from twisted.words.protocols.jabber import jid
-else:
- from tlib.domish import Element
- from tlib.jabber import jid
+from debug import LogEvent, INFO, WARN, ERROR
+
from twisted.internet.defer import Deferred
from twisted.internet import reactor
-from debug import LogEvent, INFO, WARN, ERROR
+from twisted.words.xish.domish import Element
+from twisted.words.protocols.jabber.jid import internJID
+
import sys
-import config
-import legacy
+
import lang
+import utils
+import config
XMPP_STANZAS = "urn:ietf:params:xml:ns:xmpp-stanzas"
DISCO = "http://jabber.org/protocol/disco"
DISCO_INFO = DISCO + "#info"
COMMANDS = "http://jabber.org/protocol/commands"
CAPS = "http://jabber.org/protocol/caps"
-SUBSYNC = "http://jabber.org/protocol/roster-subsync"
+SUBSYNC = "http://delx.cjb.net/protocol/roster-subsync"
MUC = "http://jabber.org/protocol/muc"
MUC_USER = MUC + "#user"
+FEATURE_NEG = "http://jabber.org/protocol/feature-neg"
SI = "http://jabber.org/protocol/si"
FT = "http://jabber.org/protocol/si/profile/file-transfer"
S5B = "http://jabber.org/protocol/bytestreams"
XEVENT = "jabber:x:event"
XDELAY = "jabber:x:delay"
XAVATAR = "jabber:x:avatar"
+XDATA = "jabber:x:data"
STORAGEAVATAR = "storage:client:avatar"
XVCARDUPDATE = "vcard-temp:x:update"
VCARDTEMP = "vcard-temp"
self.addFeature(DISCO, None, config.jid)
self.addFeature(DISCO, None, "USER")
+ self.addFeature(DISCO, None, "ROOM")
+
+ def _makeSearchJID(self, jid):
+ if jid.find('@') > 0:
+ if jid.find('%') > 0:
+ return "USER"
+ else:
+ return "ROOM"
+ elif config.compjid and to == config.compjid:
+ return config.jid
+ else:
+ return jid
def sendIq(self, el, timeout=15):
""" Used for sending IQ packets.
Returns a deferred which will fire with the matching IQ response as it's sole argument. """
def checkDeferred():
if(not d.called):
- d.errback()
+ d.errback(Exception("Timeout"))
del self.deferredIqs[(jid, ID)]
jid = el.getAttribute("to")
return d
def addIdentity(self, category, ctype, name, jid):
- """ Adds an identity to this JID's discovery profile. If jid == "USER" then MSN users will get this identity. """
+ """ Adds an identity to this JID's discovery profile. If jid == "USER" then MSN users will get this identity, jid == "ROOM" is for groupchat rooms. """
LogEvent(INFO)
if not self.identities.has_key(jid):
self.identities[jid] = []
self.identities[jid].append((category, ctype, name))
def addFeature(self, var, handler, jid):
- """ Adds a feature to this JID's discovery profile. If jid == "USER" then MSN users will get this feature. """
+ """ Adds a feature to this JID's discovery profile. If jid == "USER" then MSN users will get this feature, jid == "ROOM" is for groupchat rooms. """
LogEvent(INFO)
if not self.features.has_key(jid):
self.features[jid] = []
self.features[jid].append((var, handler))
def addNode(self, node, handler, name, jid, rootnode):
- """ Adds a node to this JID's discovery profile. If jid == "USER" then MSN users will get this node. """
+ """ Adds a node to this JID's discovery profile. If jid == "USER" then MSN users will get this node, jid == "ROOM" is for groupchat rooms. """
LogEvent(INFO)
if not self.nodes.has_key(jid):
self.nodes[jid] = {}
iqType = el.getAttribute("type")
ulang = utils.getLang(el)
try: # Stringprep
- froj = jid.JID(fro)
- to = jid.JID(to).full()
- except Exception, e:
+ froj = internJID(fro)
+ to = internJID(to).full()
+ except Exception:
LogEvent(WARN, "", "Dropping IQ because of stringprep error")
# Check if it's a response to a send IQ
LogEvent(INFO, "", "Looking for handler")
for query in el.elements():
- xmlns = query.defaultUri
+ xmlns = query.uri
node = query.getAttribute("node")
if xmlns.startswith(DISCO) and node:
self.sendDiscoItemsResponse(to=fro, ID=ID, ulang=ulang, jid=to)
return
- if to.find('@') > 0:
- searchjid = "USER"
- else:
- searchjid = to
- for (feature, handler) in self.features.get(searchjid, []):
+ for (feature, handler) in self.features.get(self._makeSearchJID(to), []):
if feature == xmlns and handler:
LogEvent(INFO, "Handler found")
handler(el)
query = iq.addElement("query")
query.attributes["xmlns"] = DISCO_INFO
- searchjid = jid
- if(jid.find('@') > 0): searchjid = "USER"
+ searchjid = self._makeSearchJID(jid)
+
# Add any identities
for (category, ctype, name) in self.identities.get(searchjid, []):
identity = query.addElement("identity")
query = iq.addElement("query")
query.attributes["xmlns"] = DISCO_ITEMS
- searchjid = jid
- if(jid.find('@') > 0): searchjid = "USER"
+ searchjid = self._makeSearchJID(jid)
for node in self.nodes.get(searchjid, []):
handler, name, rootnode = self.nodes[jid][node]
if rootnode:
error.attributes["type"] = etype
error.attributes["code"] = str(utils.errorCodeMap[condition])
cond = error.addElement(condition)
+ cond.attributes["xmlns"] = XMPP_STANZAS
self.pytrans.send(el)
features = []
- query = el.getElement("query")
- if not query:
+ for child in el.elements():
+ if child.name == "query":
+ query = child
+ break
+ else:
return []
for child in query.elements():
return features
- def discoFail(self):
+ def discoFail(self, err):
return []