Example #1
0
        def testRoster():
            global count, num
            num = 400
            count = 0
            def _presence(stanza):
                global count, num
                count += 1
                if count >= 400:
                    print 'received all presence'
            xs.addObserver('/presence', _presence)

            _jid = jid.JID(tuple=(None, self.network, None))
            r = domish.Element((None, 'iq'))
            r.addUniqueId()
            r['type'] = 'get'
            q = r.addElement((xmppim.NS_ROSTER, 'query'))
            for n in range(num):
                _jid.user = util.rand_str(util.USERID_LENGTH, util.CHARSBOX_HEX_LOWERCASE)
                item = q.addElement((None, 'item'))
                item['jid'] = _jid.userhost()
            xs.send(r)

            if self.peer is not None:
                _jid = util.userid_to_jid(self.peer, self.network)
                r = domish.Element((None, 'iq'))
                r['type'] = 'get'
                r['id'] = util.rand_str(8)
                q = r.addElement((xmppim.NS_ROSTER, 'query'))
                item = q.addElement((None, 'item'))
                item['jid'] = _jid.userhost()
                xs.send(r)
Example #2
0
 def testProbe():
     if self.peer is not None:
         userid, resource = util.split_userid(self.peer)
         presence = xmppim.Presence(
             jid.JID(tuple=(userid, self.network, resource)), 'probe')
         presence['id'] = util.rand_str(8)
         xs.send(presence)
Example #3
0
    def doSubscribe(self, to, subscriber, gid=None, response_only=False, send_subscribed=True):
        """Subscribe a given user to events from another one."""

        if not response_only:
            try:
                if subscriber not in self.subscriptions[to]:
                    self.subscriptions[to].append(subscriber)
            except:
                self.subscriptions[to] = [subscriber]

        if send_subscribed:
            # send subscription accepted immediately
            pres = domish.Element((None, "presence"))
            if gid:
                pres['id'] = gid
            pres['to'] = subscriber.full()
            pres['from'] = to.userhost()
            pres['type'] = 'subscribed'
            pres.consumed = True
            self.send(pres)

        if not response_only:
            # simulate a presence probe response
            if not gid:
                gid = util.rand_str(8)
            self.cache.send_user_presence(gid, subscriber, to)

        """
Example #4
0
    def network_presence_probe(self, to):
        """
        Broadcast a presence probe to find the given L{JID}.
        @return: a list of stanza IDs sent to the network that can be watched to
        for responses
        """
        """
        presence = domish.Element((None, 'presence'))
        presence['type'] = 'probe'
        presence['from'] = self.parent.network
        idList = []
        #to = jid.JID(tuple=(to.user, to.host, to.resource))
        for server in self.parent.keyring.hostlist():
            #to.host = server
            presence['to'] = to.user + '@' + server
            if to.resource:
                presence['to'] += '/' + to.resource
            presence.addUniqueId()
            #presence['id'] = util.rand_str(8, util.CHARSBOX_AZN_LOWERCASE)
            self.send(presence)
            idList.append(presence['id'])
        """
        # we need to be fast here
        idList = []
        presence = "<presence type='probe' from='%s' to='%%s' id='%%s'/>" % (self.parent.network, )
        for server in self.parent.keyring.hostlist():
            packetId = util.rand_str(8, util.CHARSBOX_AZN_LOWERCASE)
            dest = to.user + '@' + server
            if to.resource:
                dest += '/' + to.resource
            self.send(presence % (dest, packetId))
            idList.append(packetId)

        return idList
Example #5
0
    def broadcast_public_key(self, userid, keydata):
        """Broadcasts to all remote c2s the given public key."""
        # create vcard
        iq_vcard = domish.Element((None, 'iq'))
        iq_vcard['type'] = 'set'
        iq_vcard['from'] = util.userid_to_jid(
            userid, self.xmlstream.thisEntity.host).full()

        # add vcard
        vcard = iq_vcard.addElement((xmlstream2.NS_XMPP_VCARD4, 'vcard'))
        if keydata:
            vcard_key = vcard.addElement((None, 'key'))
            vcard_data = vcard_key.addElement((None, 'uri'))
            vcard_data.addContent(xmlstream2.DATA_PGP_PREFIX +
                                  base64.b64encode(keydata))

        # send vcard to remote c2s
        for server in self.keyring.hostlist():
            if server != self.servername:
                iq_vcard['id'] = util.rand_str(8)
                # remote server
                iq_vcard['to'] = util.component_jid(server, util.COMPONENT_C2S)
                # consume any response (very high priority)
                self.xmlstream.addOnetimeObserver(
                    "/iq[@id='%s']" % iq_vcard['id'], self.consume, 500)
                # send!
                self.send_wrapped(iq_vcard, self.xmlstream.thisEntity.full())
Example #6
0
 def testBad():
     receipt = domish.Element((None, 'message'))
     receipt['id'] = util.rand_str(8)
     receipt['type'] = 'chat'
     receipt['to'] = self.peer + '@' + self.network
     child = receipt.addElement(('urn:xmpp:server-receipts', 'received'))
     #child['id'] = util.rand_str(40)
     xs.send(receipt)
    def testSubscribe(self):
        jid_from = jid.JID('*****@*****.**')
        jid_to = jid.JID('*****@*****.**')
        gid = util.rand_str(8)
        self.resolver.subscribe(self.resolver.translateJID(jid_from),
            self.resolver.translateJID(jid_to), gid, False)

        subscriptions = { jid.JID('*****@*****.**') : [ jid.JID('*****@*****.**') ] }
        self.assertDictEqual(self.resolver.subscriptions, subscriptions, 'Subscriptions not maching.')
    def testSubscribe(self):
        jid_from = jid.JID('[email protected]/TEST001')
        jid_to = jid.JID('*****@*****.**')
        gid = util.rand_str(8)
        self.resolver.subscribe(self.resolver.translateJID(jid_from),
            self.resolver.translateJID(jid_to), gid, False)

        subscriptions = { jid.JID('*****@*****.**') : [ jid.JID('[email protected]/TEST001') ] }
        self.assertDictEqual(self.resolver.subscriptions, subscriptions, 'Subscriptions not maching.')
Example #9
0
 def testMessage():
     jid = xs.authenticator.jid
     message = domish.Element((None, 'message'))
     message['id'] = 'kontalk' + util.rand_str(8, util.CHARSBOX_AZN_LOWERCASE)
     message['type'] = 'chat'
     if self.peer:
         message['to'] = util.userid_to_jid(self.peer, self.network).full()
     else:
         message['to'] = jid.userhost()
     message.addElement((None, 'body'), content='test message')
     message.addElement(('urn:xmpp:server-receipts', 'request'))
     xs.send(message)
Example #10
0
 def _ping(self):
     """Sends a ping request to client."""
     ping = domish.Element((None, 'iq'))
     ping['from'] = self.parent.network
     ping['type'] = 'get'
     ping['id'] = util.rand_str(8, util.CHARSBOX_AZN_LOWERCASE)
     ping.addElement((xmlstream2.NS_XMPP_PING, 'ping'))
     self.send(ping)
     # setup ping timeout
     self.pinger = None
     self.ping_timeout = reactor.callLater(self.PING_TIMEOUT, self._timeout)
     # observe pong
     self.xmlstream.addObserver("/iq[@type='result'][@id='%s']" % (ping['id'], ), self.pong, 600)
Example #11
0
 def _ping(self):
     """Sends a ping request to client."""
     ping = domish.Element((None, 'iq'))
     ping['from'] = self.parent.network
     ping['type'] = 'get'
     ping['id'] = util.rand_str(8, util.CHARSBOX_AZN_LOWERCASE)
     ping.addElement((xmlstream2.NS_XMPP_PING, 'ping'))
     self.send(ping)
     # setup ping timeout
     self.pinger = None
     self.ping_timeout = reactor.callLater(self.PING_TIMEOUT, self._timeout)
     # observe pong
     self.xmlstream.addObserver("/iq[@type='result'][@id='%s']" % (ping['id'], ), self.pong, 600)
Example #12
0
    def execute(self, stanza):
        stanza.consumed = True
        res = xmlstream.toResponse(stanza, "result")
        cmd = res.addElement((xmlstream2.NS_PROTO_COMMANDS, "command"))
        cmd["sessionid"] = util.rand_str(16)
        cmd["node"] = stanza.command["node"]
        cmd["status"] = "completed"

        slist = cmd.addElement(("http://kontalk.org/extensions/serverlist", "serverlist"))
        for host in self.handler.parent.router.keyring.hostlist():
            item = slist.addElement((None, "item"))
            item["node"] = host

        return res
Example #13
0
    def _broadcast_privacy_list_change(self, dest, src, node):
        # broadcast to all resolvers
        iq = domish.Element((None, 'iq'))
        iq['from'] = dest
        iq['type'] = 'set'
        iq['id'] = util.rand_str(8)
        nodeElement = iq.addElement((xmlstream2.NS_IQ_BLOCKING, node))
        elem = nodeElement.addElement((None, 'item'))
        elem['jid'] = src

        from_component = util.component_jid(self.servername, util.COMPONENT_C2S)
        for server in self.keyring.hostlist():
            if server != self.servername:
                iq['to'] = util.component_jid(server, util.COMPONENT_C2S)
                self.send_wrapped(iq, from_component)
Example #14
0
        def testSubscribe():
            # subscription request
            self.index = 0
            if self.peer is not None:
                userid, resource = util.split_userid(self.peer)
                presence = xmppim.Presence(jid.JID(tuple=(userid, self.network, None)), 'subscribe')
                presence['id'] = util.rand_str(8)
                xs.send(presence)
            else:
                def pres():
                    self.index += 1
                    presence = xmppim.AvailablePresence(statuses={None: 'status message (%d)' % (self.index, )})
                    xs.send(presence)

                LoopingCall(pres).start(2, False)
Example #15
0
    def execute(self, stanza):
        stanza.consumed = True
        res = xmlstream.toResponse(stanza, 'result')
        cmd = res.addElement((xmlstream2.NS_PROTO_COMMANDS, 'command'))
        cmd['sessionid'] = util.rand_str(16)
        cmd['node'] = stanza.command['node']
        cmd['status'] = 'completed'

        slist = cmd.addElement(
            ('http://kontalk.org/extensions/serverlist', 'serverlist'))
        for host in self.handler.parent.router.keyring.hostlist():
            item = slist.addElement((None, 'item'))
            item['node'] = host

        return res
Example #16
0
        def testMassProbe():
            global count, num
            num = 400
            count = 0
            def _presence(stanza):
                global count, num
                count += 1
                if count >= 400:
                    print 'received all presence'
            xs.addObserver('/presence', _presence)

            for n in range(num):
                userid = util.rand_str(util.USERID_LENGTH, util.CHARSBOX_HEX_LOWERCASE)
                presence = xmppim.Presence(jid.JID(tuple=(userid, self.network, None)), 'probe')
                xs.send(presence)
Example #17
0
    def send_privacy_lists(self, pname, plist, addr_from):
        sender = util.component_jid(self.parent.servername, util.COMPONENT_C2S)
        for user, wl in plist.iteritems():
            iq = domish.Element((None, 'iq'))
            iq['from'] = '%s@%s' % (user, self.parent.network)
            iq['type'] = 'set'
            iq['id'] = util.rand_str(8)
            iq['to'] = addr_from
            allow = iq.addElement((xmlstream2.NS_IQ_BLOCKING, pname))

            for item in wl:
                elem = allow.addElement((None, 'item'))
                elem['jid'] = item

            self.parent.send_wrapped(iq, sender)
Example #18
0
    def message(self, stanza):
        # generate message id if receipt is requested by client
        if xmlstream2.extract_receipt(stanza, 'request'):
            stanza.request['id'] = util.rand_str(30,
                                                 util.CHARSBOX_AZN_LOWERCASE)

        # no to address, presume sender bare JID
        if not stanza.hasAttribute('to'):
            stanza['to'] = self.xmlstream.otherEntity.userhost()

        # if message is a received receipt, we can delete the original message
        # TODO move this to MessageHandler
        if stanza.getAttribute('type') == 'chat':
            received = xmlstream2.extract_receipt(stanza, 'received')
            if stanza.received:
                # delete the received message
                # TODO safe delete with sender/recipient
                self.router.message_offline_delete(received['id'], stanza.name)
Example #19
0
 def _send():
     _jid = self.client.xmlstream.authenticator.jid
     message = domish.Element((None, 'message'))
     message['id'] = 'kontalk' + util.rand_str(8, util.CHARSBOX_AZN_LOWERCASE)
     message['type'] = 'chat'
     if peer:
         message['to'] = peer
     else:
         message['to'] = _jid.userhost()
     message.addElement((None, 'body'), content=content)
     if request:
         message.addElement(('urn:xmpp:server-receipts', 'request'))
     self.client.send(message)
     self.stats('messages:outgoing')
     if request:
         self.stats('messages:pending')
     else:
         self.stats('messages:sent')
Example #20
0
    def render_POST(self, request):
        #log.debug("request from %s: %s" % (self.userid, request.requestHeaders))

        # check mime type
        mime = request.getHeader('content-type')
        if mime not in self.config['upload']['accept_content']:
            return self._quick_response(request, 406,
                                        'unacceptable content type')

        # check length
        length = request.getHeader('content-length')
        if length != None:
            length = long(length)
            if length <= self.config['upload']['max_size']:
                # store file to storage
                # TODO convert to file-object management for less memory consumption
                data = request.content.read()
                if len(data) == length:
                    fileid = util.rand_str(40)
                    filename = self.fileserver.storage.store_data(
                        fileid, mime, data)
                    if filename:
                        log.debug(
                            "file stored to disk (filename=%s, fileid=%s)" %
                            (filename, fileid))
                        request.setHeader('content-type', 'text/url')
                        return str(self.config['upload']['url']) % (fileid, )
                    else:
                        log.error("error storing file")
                        return self._quick_response(request, 500,
                                                    'unable to store file')

                else:
                    log.warn(
                        "file length not matching content-length header (%d/%d)"
                        % (len(data), length))
                    return self._quick_response(request, 400, 'bad request')
            else:
                log.warn("file too big (%d bytes)" % length)
                return self._quick_response(request, 413, 'request too large')
        else:
            log.warn("content-length header not found")
            return self._quick_response(request, 411,
                                        'content length not declared')
Example #21
0
 def _send():
     _jid = self.client.xmlstream.authenticator.jid
     message = domish.Element((None, 'message'))
     message['id'] = 'kontalk' + util.rand_str(
         8, util.CHARSBOX_AZN_LOWERCASE)
     message['type'] = 'chat'
     if peer:
         message['to'] = peer
     else:
         message['to'] = _jid.userhost()
     message.addElement((None, 'body'), content=content)
     if request:
         message.addElement(('urn:xmpp:server-receipts', 'request'))
     self.client.send(message)
     self.stats('messages:outgoing')
     if request:
         self.stats('messages:pending')
     else:
         self.stats('messages:sent')
Example #22
0
    def message(self, stanza):
        # generate message id if receipt is requested by client
        if xmlstream2.extract_receipt(stanza, 'request'):
            stanza.request['id'] = util.rand_str(30, util.CHARSBOX_AZN_LOWERCASE)

        # no to address, presume sender bare JID
        if not stanza.hasAttribute('to'):
            stanza['to'] = self.xmlstream.otherEntity.userhost()

        # if message is a received receipt, we can delete the original message
        # TODO move this to MessageHandler
        if stanza.getAttribute('type') == 'chat':
            received = xmlstream2.extract_receipt(stanza, 'received')
            if stanza.received:
                # delete the received message
                # TODO safe delete with sender/recipient
                self.router.message_offline_delete(received['id'], stanza.name)

        self.handle(stanza)
Example #23
0
    def bind(self, name):
        stanzaId = util.rand_str(8)

        # register for response
        def _bind(stanza, name):
            if not stanza.hasAttribute('error'):
                # no errors, register route
                unused, host = util.jid_component(name)

                if host not in self.routes:
                    self.routes[host] = []

                self.routes[host].append(name)
                log.debug("ROUTES: %s" % (self.routes, ))

        self.xmlstream.addOnetimeObserver("/bind[@id='%s']" % (stanzaId, ), _bind, name=name)

        bind = domish.Element((None, 'bind'))
        bind['id'] = stanzaId
        bind['name'] = name
        self.send(bind)
Example #24
0
    def bind(self, name):
        stanzaId = util.rand_str(8)

        # register for response
        def _bind(stanza, name):
            if not stanza.hasAttribute('error'):
                # no errors, register route
                unused, host = util.jid_component(name)

                if host not in self.routes:
                    self.routes[host] = []

                self.routes[host].append(name)
                log.debug("ROUTES: %s" % (self.routes, ))

        self.xmlstream.addOnetimeObserver("/bind[@id='%s']" % (stanzaId, ),
                                          _bind,
                                          name=name)

        bind = domish.Element((None, 'bind'))
        bind['id'] = stanzaId
        bind['name'] = name
        self.send(bind)
Example #25
0
    def broadcast_public_key(self, userid, keydata):
        """Broadcasts to all remote c2s the given public key."""
        # create vcard
        iq_vcard = domish.Element((None, 'iq'))
        iq_vcard['type'] = 'set'
        iq_vcard['from'] = util.userid_to_jid(userid, self.xmlstream.thisEntity.host).full()

        # add vcard
        vcard = iq_vcard.addElement((xmlstream2.NS_XMPP_VCARD4, 'vcard'))
        if keydata:
            vcard_key = vcard.addElement((None, 'key'))
            vcard_data = vcard_key.addElement((None, 'uri'))
            vcard_data.addContent(xmlstream2.DATA_PGP_PREFIX + base64.b64encode(keydata))

        # send vcard to remote c2s
        for server in self.keyring.hostlist():
            if server != self.servername:
                iq_vcard['id'] = util.rand_str(8)
                # remote server
                iq_vcard['to'] = util.component_jid(server, util.COMPONENT_C2S)
                # consume any response (very high priority)
                self.xmlstream.addOnetimeObserver("/iq[@id='%s']" % iq_vcard['id'], self.consume, 500)
                # send!
                self.send_wrapped(iq_vcard, self.xmlstream.thisEntity.full())
Example #26
0
    def render_POST(self, request):
        # log.debug("request from %s: %s" % (self.userid, request.requestHeaders))

        # check mime type
        mime = request.getHeader("content-type")
        if mime not in self.config["upload"]["accept_content"]:
            return self._quick_response(request, 406, "unacceptable content type")

        # check length
        length = request.getHeader("content-length")
        if length != None:
            length = long(length)
            if length <= self.config["upload"]["max_size"]:
                # store file to storage
                # TODO convert to file-object management for less memory consumption
                data = request.content.read()
                if len(data) == length:
                    fileid = util.rand_str(40)
                    filename = self.fileserver.storage.store_data(fileid, mime, data)
                    if filename:
                        log.debug("file stored to disk (filename=%s, fileid=%s)" % (filename, fileid))
                        request.setHeader("content-type", "text/url")
                        return str(self.config["upload"]["url"]) % (fileid,)
                    else:
                        log.error("error storing file")
                        return self._quick_response(request, 500, "unable to store file")

                else:
                    log.warn("file length not matching content-length header (%d/%d)" % (len(data), length))
                    return self._quick_response(request, 400, "bad request")
            else:
                log.warn("file too big (%d bytes)" % length)
                return self._quick_response(request, 413, "request too large")
        else:
            log.warn("content-length header not found")
            return self._quick_response(request, 411, "content length not declared")
Example #27
0
 def testProbe():
     if self.peer is not None:
         userid, resource = util.split_userid(self.peer)
         presence = xmppim.Presence(jid.JID(tuple=(userid, self.network, resource)), 'probe')
         presence['id'] = util.rand_str(8)
         xs.send(presence)
Example #28
0
    def roster(self, stanza):
        if not xmlstream2.has_element(stanza.query, uri=xmlstream2.NS_IQ_ROSTER, name="item"):
            # requesting initial roster - enter XMPP compatibility mode
            self.parent.compatibility_mode = True

        _items = stanza.query.elements(uri=xmlstream2.NS_IQ_ROSTER, name="item")
        requester = jid.JID(stanza["from"])
        stanza.consumed = True

        # items present, requesting roster lookup
        response = xmlstream.toResponse(stanza, "result")
        roster = response.addElement((xmlstream2.NS_IQ_ROSTER, "query"))

        probes = []
        # this will be true if roster lookup is requested
        roster_lookup = False
        for item in _items:
            # items present, meaning roster lookup
            roster_lookup = True

            itemJid = jid.internJID(item["jid"])

            # include the entry in the roster reply anyway
            entry = self.parent.router.cache.lookup(itemJid)
            if entry:
                allowed = self.parent.router.is_presence_allowed(requester, itemJid)
                if allowed != -1:
                    item = roster.addElement((None, "item"))
                    item["jid"] = self.parent.router.translateJID(entry.jid).userhost()

                if allowed == 1:
                    probes.append(entry.presence())

        # roster lookup, send presence data and vcards
        if roster_lookup:

            # lookup response
            self.send(response)

            # simulate a presence probe and send vcards
            # we'll use one group ID so the client knows when to stop waiting
            gid = stanza.getAttribute("id")
            if not gid:
                gid = util.rand_str(8, util.CHARSBOX_AZN_LOWERCASE)

            i = sum([len(x) for x in probes])
            for presence_list in probes:
                for presence in presence_list:
                    presence = deepcopy(presence)
                    presence["to"] = stanza["from"]
                    group = presence.addElement((xmlstream2.NS_XMPP_STANZA_GROUP, "group"))
                    group["id"] = gid
                    group["count"] = str(i)
                    i -= 1
                    self.send(presence)

                # send vcard for this user
                jid_from = jid.JID(presence_list[0]["from"])
                iq = domish.Element((None, "iq"))
                iq["type"] = "set"
                iq["from"] = jid_from.userhost()
                iq["to"] = stanza["from"]
                try:
                    self.parent.router.build_vcard(jid_from.user, iq)
                    self.send(iq)
                except keyring.KeyNotFoundException:
                    pass

        # no roster lookup, XMPP standard roster instead
        else:

            # include items from the user's whitelist
            wl = self.parent.router.get_whitelist(requester)
            probes = None
            if wl:
                subscriptions = []
                for e in wl:
                    item = roster.addElement((None, "item"))
                    item["jid"] = e

                    itemJid = jid.JID(e)

                    # check if subscription status is 'both' or just 'from'
                    allowed = self.parent.router.is_presence_allowed(requester, itemJid)
                    if allowed == 1:
                        status = "both"
                    else:
                        status = "from"

                    # TODO include name from PGP key?
                    item["subscription"] = status

                    # add to subscription list
                    subscriptions.append(itemJid)

            # send the roster
            self.send(response)

            # subscribe to all users (without sending subscribed stanza of course)
            if wl:
                for itemJid in subscriptions:
                    self.parent.router.subscribe(requester, itemJid, send_subscribed=False)
Example #29
0
 def send_fake_receipt(self, stanza):
     """Sends back a fake sent receipt, while silently discard the message."""
     msg = xmlstream.toResponse(stanza, stanza["type"])
     r = msg.addElement((xmlstream2.NS_XMPP_SERVER_RECEIPTS, "sent"))
     r["id"] = util.rand_str(30, util.CHARSBOX_AZN_LOWERCASE)
     self.parent.send(msg)
Example #30
0
 def send_fake_receipt(self, stanza):
     """Sends back a fake sent receipt, while silently discard the message."""
     msg = xmlstream.toResponse(stanza, stanza['type'])
     r = msg.addElement((xmlstream2.NS_XMPP_SERVER_RECEIPTS, 'sent'))
     r['id'] = util.rand_str(30, util.CHARSBOX_AZN_LOWERCASE)
     self.parent.send(msg)
Example #31
0
    def roster(self, stanza):
        if not xmlstream2.has_element(
                stanza.query, uri=xmlstream2.NS_IQ_ROSTER, name='item'):
            # requesting initial roster - enter XMPP compatibility mode
            self.parent.compatibility_mode = True

        _items = stanza.query.elements(uri=xmlstream2.NS_IQ_ROSTER,
                                       name='item')
        requester = jid.JID(stanza['from'])
        stanza.consumed = True

        # items present, requesting roster lookup
        response = xmlstream.toResponse(stanza, 'result')
        roster = response.addElement((xmlstream2.NS_IQ_ROSTER, 'query'))

        probes = []
        # this will be true if roster lookup is requested
        roster_lookup = False
        for item in _items:
            # items present, meaning roster lookup
            roster_lookup = True

            itemJid = jid.internJID(item['jid'])

            # include the entry in the roster reply anyway
            entry = self.parent.router.cache.lookup(itemJid)
            if entry:
                allowed = self.parent.router.is_presence_allowed(
                    requester, itemJid)
                if allowed != -1:
                    item = roster.addElement((None, 'item'))
                    item['jid'] = self.parent.router.translateJID(
                        entry.jid).userhost()

                if allowed == 1:
                    probes.append(entry.presence())

        # roster lookup, send presence data and vcards
        if roster_lookup:

            # lookup response
            self.send(response)

            # simulate a presence probe and send vcards
            # we'll use one group ID so the client knows when to stop waiting
            gid = stanza.getAttribute('id')
            if not gid:
                gid = util.rand_str(8, util.CHARSBOX_AZN_LOWERCASE)

            i = sum([len(x) for x in probes])
            for presence_list in probes:
                for presence in presence_list:
                    presence = deepcopy(presence)
                    presence['to'] = stanza['from']
                    group = presence.addElement(
                        (xmlstream2.NS_XMPP_STANZA_GROUP, 'group'))
                    group['id'] = gid
                    group['count'] = str(i)
                    i -= 1
                    self.send(presence)

                # send vcard for this user
                jid_from = jid.JID(presence_list[0]['from'])
                iq = domish.Element((None, 'iq'))
                iq['type'] = 'set'
                iq['from'] = jid_from.userhost()
                iq['to'] = stanza['from']
                try:
                    self.parent.router.build_vcard(jid_from.user, iq)
                    self.send(iq)
                except keyring.KeyNotFoundException:
                    pass

        # no roster lookup, XMPP standard roster instead
        else:

            # include items from the user's whitelist
            wl = self.parent.router.get_whitelist(requester)
            probes = None
            if wl:
                subscriptions = []
                for e in wl:
                    item = roster.addElement((None, 'item'))
                    item['jid'] = e

                    itemJid = jid.JID(e)

                    # check if subscription status is 'both' or just 'from'
                    allowed = self.parent.router.is_presence_allowed(
                        requester, itemJid)
                    if allowed == 1:
                        status = 'both'
                    else:
                        status = 'from'

                    # TODO include name from PGP key?
                    item['subscription'] = status

                    # add to subscription list
                    subscriptions.append(itemJid)

            # send the roster
            self.send(response)

            # subscribe to all users (without sending subscribed stanza of course)
            if wl:
                for itemJid in subscriptions:
                    self.parent.router.subscribe(requester,
                                                 itemJid,
                                                 send_subscribed=False)
Example #32
0
    def process_message(self, stanza, hold=False):
        if stanza.hasAttribute('to'):
            to = jid.JID(stanza['to'])
            # process only our JIDs
            if util.jid_local(util.COMPONENT_C2S, self, to):
                chat_msg = (stanza.getAttribute('type') == 'chat')
                if to.user is not None:
                    keepId = None
                    receipt = xmlstream2.extract_receipt(stanza, 'request')
                    received = xmlstream2.extract_receipt(stanza, 'received')
                    has_storage = xmlstream2.has_element(stanza, xmlstream2.NS_XMPP_STORAGE, 'storage')
                    try:
                        """
                        We are deliberately ignoring messages with sent
                        receipt because they are supposed to be volatile.
                        """
                        if chat_msg and not has_storage and (receipt or received):
                            """
                            Apply generated id if we are getting a received receipt.
                            This way stanza is received by the client with the
                            correct id to cancel preemptive storage.
                            """
                            if received:
                                keepId = stanza['id'] = util.rand_str(30, util.CHARSBOX_AZN_LOWERCASE)

                            # send message to offline storage just to be safe (delayed)
                            keepId = self.message_offline_store(stanza, delayed=True, reuseId=keepId)

                        if hold:
                            raise Exception()

                        # send message to sm only to non-negative resources
                        log.debug("sending message %s" % (stanza['id'], ))
                        self.sfactory.dispatch(stanza)

                    except:
                        # manager not found or holding -- send to offline storage
                        if hold:
                            log.debug("holding stanza for %s" % (stanza['to'], ))
                        else:
                            log.debug("c2s manager for %s not found" % (stanza['to'], ))

                        """
                        Since our previous call to message_offline_store()
                        was with delayed parameter, we need to store for
                        real now.
                        Do not store messages from local storage because
                        """
                        if chat_msg and not has_storage and (stanza.body or stanza.e2e or received):
                            self.message_offline_store(stanza, delayed=False, reuseId=keepId)
                        if self.push_manager and chat_msg and (stanza.body or stanza.e2e) and (not receipt or receipt.name == 'request'):
                            self.push_manager.notify(to)

                    # if message is a received receipt, we can delete the original message
                    if chat_msg and received:
                        # delete the received message
                        # TODO safe delete with sender/recipient
                        self.message_offline_delete(received['id'], stanza.name)

                    stamp = time.time()

                    """
                    Receipts will be sent only if message is not coming from
                    storage or message is from a remote server.
                    This is because if the message is coming from storage,
                    it means that it's a user collecting its offline
                    messages, so we don't need to send a <sent/> again.
                    If a message is coming from a remote server, it means
                    that is being delivered by a remote c2s by either:
                     * sm request (direct message from client)
                     * offline delivery (triggered by an initial presence from this server)
                    """
                    host = util.jid_host(stanza['from'])

                    from_storage = xmlstream2.has_element(stanza, xmlstream2.NS_XMPP_STORAGE, 'storage')

                    try:
                        log.debug("host(unparsed): %s" % (host, ))
                        unused, host = util.jid_component(host, util.COMPONENT_C2S)
                        log.debug("host(parsed): %s" % (host, ))
                        from_remote = host != self.servername
                    except:
                        from_remote = False

                    if chat_msg and (not from_storage or from_remote):

                        # send ack only for chat messages (if requested)
                        # do not send if coming from remote storage
                        if receipt and not from_storage:
                            self.send_ack(stanza, 'sent', stamp)

                        # send receipt to originating server, if requested
                        receipt = None
                        # receipt request: send <sent/>
                        if stanza.request:
                            receipt = stanza.request
                            request = 'request'
                            delivery = 'sent'
                        # received receipt: send <ack/>
                        elif stanza.received:
                            receipt = stanza.received
                            request = 'received'
                            delivery = 'ack'

                        # now send what we prepared
                        if receipt:
                            try:
                                from_server = receipt['from']
                                if not util.hostjid_local(util.COMPONENT_C2S, self, from_server):
                                    stanza['from'] = from_server
                                    self.send_ack(stanza, delivery, stamp, request)
                            except KeyError:
                                pass

                else:
                    # deliver local stanza
                    self.local(stanza)

                """
                If message is a receipt coming from a remote server, delete
                the message from our storage.
                """
                r_sent = xmlstream2.extract_receipt(stanza, 'sent')
                if chat_msg and r_sent:
                    sender_host = util.jid_host(stanza['from'])
                    """
                    We are receiving a sent receipt from another server,
                    meaning that the server has now responsibility for the
                    message - we can delete it now.
                    Special case is the sender domain being the network
                    domain, meaning the resolver rejected the message.
                    """
                    unused, sender_host = util.jid_component(sender_host)
                    if sender_host != self.servername:
                        log.debug("remote server now has responsibility for message %s - deleting" % (r_sent['id'], ))
                        # TODO safe delete with sender/recipient
                        self.message_offline_delete(r_sent['id'], stanza.name)

            else:
                log.debug("stanza is not our concern or is an error")
Example #33
0
        def _db(presence, stanza):
            log.debug("presence: %r" % (presence, ))
            if type(presence) == list and len(presence) > 0:
                chain = domish.Element(
                    (xmlstream2.NS_XMPP_STANZA_GROUP, 'group'))
                chain['id'] = stanza['id']
                chain['count'] = str(len(presence))

                for user in presence:
                    response = xmlstream.toResponse(stanza)
                    response['id'] = util.rand_str(8,
                                                   util.CHARSBOX_AZN_LOWERCASE)
                    response_from = util.userid_to_jid(
                        user['userid'], self.xmlstream.thisEntity.host)
                    response['from'] = response_from.full()

                    if user['status'] is not None:
                        response.addElement((None, 'status'),
                                            content=user['status'])
                    if user['show'] is not None:
                        response.addElement((None, 'show'),
                                            content=user['show'])

                    if not self.parent.sfactory.client_connected(
                            response_from):
                        response['type'] = 'unavailable'
                        delay = domish.Element(('urn:xmpp:delay', 'delay'))
                        delay['stamp'] = user['timestamp'].strftime(
                            xmlstream2.XMPP_STAMP_FORMAT)
                        response.addChild(delay)

                    response.addChild(chain)

                    self.send(response)

                    if self.parent.logTraffic:
                        log.debug("probe result sent: %s" %
                                  (response.toXml().encode('utf-8'), ))
                    else:
                        log.debug("probe result sent: %s" %
                                  (response['from'], ))

            elif presence is not None and type(presence) != list:
                chain = domish.Element(
                    (xmlstream2.NS_XMPP_STANZA_GROUP, 'group'))
                chain['id'] = stanza['id']
                chain['count'] = '1'

                response = xmlstream.toResponse(stanza)

                if presence['status'] is not None:
                    response.addElement((None, 'status'),
                                        content=presence['status'])
                if presence['show'] is not None:
                    response.addElement((None, 'show'),
                                        content=presence['show'])

                response_from = util.userid_to_jid(presence['userid'],
                                                   self.parent.servername)
                if not self.parent.sfactory.client_connected(response_from):
                    response['type'] = 'unavailable'
                    delay = domish.Element(('urn:xmpp:delay', 'delay'))
                    delay['stamp'] = presence['timestamp'].strftime(
                        xmlstream2.XMPP_STAMP_FORMAT)
                    response.addChild(delay)

                response.addChild(chain)
                self.send(response)

                if self.parent.logTraffic:
                    log.debug("probe result sent: %s" %
                              (response.toXml().encode('utf-8'), ))
                else:
                    log.debug("probe result sent: %s" % (response['from'], ))
            else:
                log.debug("probe: user not found")
                # TODO return error?
                response = xmlstream.toResponse(stanza, 'error')

                chain = domish.Element(
                    (xmlstream2.NS_XMPP_STANZA_GROUP, 'group'))
                chain['id'] = stanza['id']
                chain['count'] = '1'
                response.addChild(chain)

                self.send(response)
Example #34
0
    def local_vcard(self, user, stanza):
        """
        Called by SM when receiving a vCard from a local client.
        It checks vcard info (including public key) and if positive, sends the
        vCard to all remote c2s.
        @return: iq result or error stanza for the client
        """
        if self.logTraffic:
            log.debug("client sent vcard: %s" % (stanza.toXml(), ))
        else:
            log.debug("client sent vcard: %s" % (stanza['to'], ))
        stanza.consumed = True

        stanza_to = stanza.getAttribute('to')
        if stanza_to:
            entity = jid.JID(stanza_to)
        else:
            entity = None

        # setting our own vcard
        if not entity or (entity.userhost() == user.userhost()):
            # TODO parse vcard for interesting sections

            if stanza.vcard.key is not None:
                # we do this because of the uri member in domish.Element
                keydata = stanza.vcard.key.firstChildElement()
                if keydata and keydata.name == 'uri':
                    keydata = str(keydata)

                    if keydata.startswith(xmlstream2.DATA_PGP_PREFIX):
                        try:
                            keydata = base64.b64decode(keydata[len(xmlstream2.DATA_PGP_PREFIX):])
                        except:
                            log.debug("invalid base64 data")
                            e = xmlstream.error.StanzaError('bad-request', text='Invalid public key.')
                            iq = xmlstream.toResponse(stanza, 'error')
                            iq.addChild(e.getElement())
                            return iq

                        # check key
                        fp = self.keyring.check_user_key(keydata, user.user)
                        if fp:
                            # generate response beforing tampering with the stanza
                            response = xmlstream.toResponse(stanza, 'result')
                            # update presencedb
                            self.presencedb.public_key(user.user, fp)

                            # send vcard to all remote c2s
                            for server in self.keyring.hostlist():
                                if server != self.servername:
                                    stanza['id'] = util.rand_str(8)
                                    stanza['to'] = util.component_jid(server, util.COMPONENT_C2S)
                                    # consume any response (very high priority)
                                    self.xmlstream.addOnetimeObserver("/iq[@id='%s']" % stanza['id'], self.consume, 500)

                                    # wrap stanza in an envelope because we want errors to return to us
                                    self.send_wrapped(stanza, self.xmlstream.thisEntity.full())

                            # send response
                            return response
                        else:
                            log.debug("invalid key - authorization to vCard denied")
                            e = xmlstream.error.StanzaError('bad-request', text='Invalid public key.')
                            iq = xmlstream.toResponse(stanza, 'error')
                            iq.addChild(e.getElement())
                            return iq
        else:
            log.debug("authorization to vCard denied")
            e = xmlstream.error.StanzaError('not-allowed', text='Not authorized.')
            iq = xmlstream.toResponse(stanza, 'error')
            iq.addChild(e.getElement())
            return iq
Example #35
0
    def send(self, stanza, force=False):
        """Send stanza to client, setting to and id attributes if not present."""

        if stanza.hasAttribute('original-to'):
            origTo = stanza.getAttribute('original-to')
            del stanza['original-to']

            """
            Extract original recipient from stanza.
            If original-to is not present, we will assume that
            stanza was intended to the full JID.
            """
            origTo = jid.JID(origTo)

            if self.router.logTraffic:
                log.debug("sending message to client %s (original was %s)" % (self.xmlstream.otherEntity, origTo))
                if self._presence:
                    log.debug("_presence: %s" % (self._presence.toXml(), ))

            # sending to bare JID
            # initial presence found
            # negative resource
            # => DROP STANZA
            try:
                if not origTo.resource and int(str(self._presence.priority)) < 0:
                    return None
            except:
                pass

        # FIXME using deepcopy is not safe
        from copy import deepcopy
        stanza = deepcopy(stanza)

        util.resetNamespace(stanza, component.NS_COMPONENT_ACCEPT, self.namespace)

        # translate sender to network JID
        sender = stanza.getAttribute('from')
        if sender and sender != self.network:
            sender = jid.JID(stanza['from'])
            sender.host = self.network
            stanza['from'] = sender.full()
        # TODO should we force self.network if no sender?

        # remove reserved elements
        if stanza.name in ('presence', 'message'):
            # storage child
            if stanza.storage and stanza.storage.uri == xmlstream2.NS_XMPP_STORAGE:
                stanza.children.remove(stanza.storage)
            # origin in receipt
            if stanza.request and stanza.request.hasAttribute('from'):
                del stanza.request['from']
            elif stanza.received and stanza.received.hasAttribute('from'):
                del stanza.received['from']
        if stanza.name == 'presence':
            # push device id
            for c in stanza.elements(name='c', uri=xmlstream2.NS_PRESENCE_PUSH):
                stanza.children.remove(c)
                break

        # force destination address
        if self.xmlstream.otherEntity:
            stanza['to'] = self.xmlstream.otherEntity.full()

        if not stanza.hasAttribute('id'):
            stanza['id'] = util.rand_str(8, util.CHARSBOX_AZN_LOWERCASE)
        xmlstream2.StreamManager.send(self, stanza, force)
Example #36
0
    def local_vcard(self, user, stanza):
        """
        Called by SM when receiving a vCard from a local client.
        It checks vcard info (including public key) and if positive, sends the
        vCard to all remote c2s.
        @return: iq result or error stanza for the client
        """
        if self.logTraffic:
            log.debug("client sent vcard: %s" % (stanza.toXml(), ))
        else:
            log.debug("client sent vcard: %s" % (stanza['to'], ))
        stanza.consumed = True

        stanza_to = stanza.getAttribute('to')
        if stanza_to:
            entity = jid.JID(stanza_to)
        else:
            entity = None

        # setting our own vcard
        if not entity or (entity.userhost() == user.userhost()):
            # TODO parse vcard for interesting sections

            if stanza.vcard.key is not None:
                # we do this because of the uri member in domish.Element
                keydata = stanza.vcard.key.firstChildElement()
                if keydata and keydata.name == 'uri':
                    keydata = str(keydata)

                    if keydata.startswith(xmlstream2.DATA_PGP_PREFIX):
                        try:
                            keydata = base64.b64decode(
                                keydata[len(xmlstream2.DATA_PGP_PREFIX):])
                        except:
                            log.debug("invalid base64 data")
                            e = xmlstream.error.StanzaError(
                                'bad-request', text='Invalid public key.')
                            iq = xmlstream.toResponse(stanza, 'error')
                            iq.addChild(e.getElement())
                            return iq

                        # check key
                        fp = self.keyring.check_user_key(keydata, user.user)
                        if fp:
                            # generate response beforing tampering with the stanza
                            response = xmlstream.toResponse(stanza, 'result')
                            # update presencedb
                            self.presencedb.public_key(user.user, fp)

                            # send vcard to all remote c2s
                            for server in self.keyring.hostlist():
                                if server != self.servername:
                                    stanza['id'] = util.rand_str(8)
                                    stanza['to'] = util.component_jid(
                                        server, util.COMPONENT_C2S)
                                    # consume any response (very high priority)
                                    self.xmlstream.addOnetimeObserver(
                                        "/iq[@id='%s']" % stanza['id'],
                                        self.consume, 500)

                                    # wrap stanza in an envelope because we want errors to return to us
                                    self.send_wrapped(
                                        stanza,
                                        self.xmlstream.thisEntity.full())

                            # send response
                            return response
                        else:
                            log.debug(
                                "invalid key - authorization to vCard denied")
                            e = xmlstream.error.StanzaError(
                                'bad-request', text='Invalid public key.')
                            iq = xmlstream.toResponse(stanza, 'error')
                            iq.addChild(e.getElement())
                            return iq
        else:
            log.debug("authorization to vCard denied")
            e = xmlstream.error.StanzaError('not-allowed',
                                            text='Not authorized.')
            iq = xmlstream.toResponse(stanza, 'error')
            iq.addChild(e.getElement())
            return iq
Example #37
0
    def process_message(self, stanza, hold=False):
        if stanza.hasAttribute('to'):
            to = jid.JID(stanza['to'])
            # process only our JIDs
            if util.jid_local(util.COMPONENT_C2S, self, to):
                chat_msg = (stanza.getAttribute('type') == 'chat')
                if to.user is not None:
                    keepId = None
                    receipt = xmlstream2.extract_receipt(stanza, 'request')
                    received = xmlstream2.extract_receipt(stanza, 'received')
                    has_storage = xmlstream2.has_element(
                        stanza, xmlstream2.NS_XMPP_STORAGE, 'storage')
                    try:
                        """
                        We are deliberately ignoring messages with sent
                        receipt because they are supposed to be volatile.
                        """
                        if chat_msg and not has_storage and (receipt
                                                             or received):
                            """
                            Apply generated id if we are getting a received receipt.
                            This way stanza is received by the client with the
                            correct id to cancel preemptive storage.
                            """
                            if received:
                                keepId = stanza['id'] = util.rand_str(
                                    30, util.CHARSBOX_AZN_LOWERCASE)

                            # send message to offline storage just to be safe (delayed)
                            keepId = self.message_offline_store(stanza,
                                                                delayed=True,
                                                                reuseId=keepId)

                        if hold:
                            raise Exception()

                        # send message to sm only to non-negative resources
                        log.debug("sending message %s" % (stanza['id'], ))
                        self.sfactory.dispatch(stanza)

                    except:
                        # manager not found or holding -- send to offline storage
                        if hold:
                            log.debug("holding stanza for %s" %
                                      (stanza['to'], ))
                        else:
                            log.debug("c2s manager for %s not found" %
                                      (stanza['to'], ))
                        """
                        Since our previous call to message_offline_store()
                        was with delayed parameter, we need to store for
                        real now.
                        Do not store messages from local storage because
                        """
                        if chat_msg and not has_storage and (stanza.body
                                                             or stanza.e2e
                                                             or received):
                            self.message_offline_store(stanza,
                                                       delayed=False,
                                                       reuseId=keepId)
                        if self.push_manager and chat_msg and (
                                stanza.body or stanza.e2e) and (
                                    not receipt or receipt.name == 'request'):
                            self.push_manager.notify(to)

                    # if message is a received receipt, we can delete the original message
                    if chat_msg and received:
                        # delete the received message
                        # TODO safe delete with sender/recipient
                        self.message_offline_delete(received['id'],
                                                    stanza.name)

                    stamp = time.time()
                    """
                    Receipts will be sent only if message is not coming from
                    storage or message is from a remote server.
                    This is because if the message is coming from storage,
                    it means that it's a user collecting its offline
                    messages, so we don't need to send a <sent/> again.
                    If a message is coming from a remote server, it means
                    that is being delivered by a remote c2s by either:
                     * sm request (direct message from client)
                     * offline delivery (triggered by an initial presence from this server)
                    """
                    host = util.jid_host(stanza['from'])

                    from_storage = xmlstream2.has_element(
                        stanza, xmlstream2.NS_XMPP_STORAGE, 'storage')

                    try:
                        log.debug("host(unparsed): %s" % (host, ))
                        unused, host = util.jid_component(
                            host, util.COMPONENT_C2S)
                        log.debug("host(parsed): %s" % (host, ))
                        from_remote = host != self.servername
                    except:
                        from_remote = False

                    if chat_msg and (not from_storage or from_remote):

                        # send ack only for chat messages (if requested)
                        # do not send if coming from remote storage
                        if receipt and not from_storage:
                            self.send_ack(stanza, 'sent', stamp)

                        # send receipt to originating server, if requested
                        receipt = None
                        # receipt request: send <sent/>
                        if stanza.request:
                            receipt = stanza.request
                            request = 'request'
                            delivery = 'sent'
                        # received receipt: send <ack/>
                        elif stanza.received:
                            receipt = stanza.received
                            request = 'received'
                            delivery = 'ack'

                        # now send what we prepared
                        if receipt:
                            try:
                                from_server = receipt['from']
                                if not util.hostjid_local(
                                        util.COMPONENT_C2S, self, from_server):
                                    stanza['from'] = from_server
                                    self.send_ack(stanza, delivery, stamp,
                                                  request)
                            except KeyError:
                                pass

                else:
                    # deliver local stanza
                    self.local(stanza)
                """
                If message is a receipt coming from a remote server, delete
                the message from our storage.
                """
                r_sent = xmlstream2.extract_receipt(stanza, 'sent')
                if chat_msg and r_sent:
                    sender_host = util.jid_host(stanza['from'])
                    """
                    We are receiving a sent receipt from another server,
                    meaning that the server has now responsibility for the
                    message - we can delete it now.
                    Special case is the sender domain being the network
                    domain, meaning the resolver rejected the message.
                    """
                    unused, sender_host = util.jid_component(sender_host)
                    if sender_host != self.servername:
                        log.debug(
                            "remote server now has responsibility for message %s - deleting"
                            % (r_sent['id'], ))
                        # TODO safe delete with sender/recipient
                        self.message_offline_delete(r_sent['id'], stanza.name)

            else:
                log.debug("stanza is not our concern or is an error")
Example #38
0
        def _db(presence, stanza):
            log.debug("presence: %r" % (presence, ))
            if type(presence) == list and len(presence) > 0:
                chain = domish.Element((xmlstream2.NS_XMPP_STANZA_GROUP, 'group'))
                chain['id'] = stanza['id']
                chain['count'] = str(len(presence))

                for user in presence:
                    response = xmlstream.toResponse(stanza)
                    response['id'] = util.rand_str(8, util.CHARSBOX_AZN_LOWERCASE)
                    response_from = util.userid_to_jid(user['userid'], self.xmlstream.thisEntity.host)
                    response['from'] = response_from.full()

                    if user['status'] is not None:
                        response.addElement((None, 'status'), content=user['status'])
                    if user['show'] is not None:
                        response.addElement((None, 'show'), content=user['show'])

                    if not self.parent.sfactory.client_connected(response_from):
                        response['type'] = 'unavailable'
                        delay = domish.Element(('urn:xmpp:delay', 'delay'))
                        delay['stamp'] = user['timestamp'].strftime(xmlstream2.XMPP_STAMP_FORMAT)
                        response.addChild(delay)

                    response.addChild(chain)

                    self.send(response)

                    if self.parent.logTraffic:
                        log.debug("probe result sent: %s" % (response.toXml().encode('utf-8'), ))
                    else:
                        log.debug("probe result sent: %s" % (response['from'], ))

            elif presence is not None and type(presence) != list:
                chain = domish.Element((xmlstream2.NS_XMPP_STANZA_GROUP, 'group'))
                chain['id'] = stanza['id']
                chain['count'] = '1'

                response = xmlstream.toResponse(stanza)

                if presence['status'] is not None:
                    response.addElement((None, 'status'), content=presence['status'])
                if presence['show'] is not None:
                    response.addElement((None, 'show'), content=presence['show'])

                response_from = util.userid_to_jid(presence['userid'], self.parent.servername)
                if not self.parent.sfactory.client_connected(response_from):
                    response['type'] = 'unavailable'
                    delay = domish.Element(('urn:xmpp:delay', 'delay'))
                    delay['stamp'] = presence['timestamp'].strftime(xmlstream2.XMPP_STAMP_FORMAT)
                    response.addChild(delay)

                response.addChild(chain)
                self.send(response)

                if self.parent.logTraffic:
                    log.debug("probe result sent: %s" % (response.toXml().encode('utf-8'), ))
                else:
                    log.debug("probe result sent: %s" % (response['from'], ))
            else:
                log.debug("probe: user not found")
                # TODO return error?
                response = xmlstream.toResponse(stanza, 'error')

                chain = domish.Element((xmlstream2.NS_XMPP_STANZA_GROUP, 'group'))
                chain['id'] = stanza['id']
                chain['count'] = '1'
                response.addChild(chain)

                self.send(response)
Example #39
0
    def send(self, stanza, force=False):
        """Send stanza to client, setting to and id attributes if not present."""

        if stanza.hasAttribute('original-to'):
            origTo = stanza.getAttribute('original-to')
            del stanza['original-to']
            """
            Extract original recipient from stanza.
            If original-to is not present, we will assume that
            stanza was intended to the full JID.
            """
            origTo = jid.JID(origTo)

            if self.router.logTraffic:
                log.debug("sending message to client %s (original was %s)" %
                          (self.xmlstream.otherEntity, origTo))
                if self._presence:
                    log.debug("_presence: %s" %
                              (self._presence.toXml().encode('utf-8'), ))

            # sending to bare JID
            # initial presence found
            # negative resource
            # => DROP STANZA
            try:
                if not origTo.resource and int(str(
                        self._presence.priority)) < 0:
                    return None
            except:
                pass

        # FIXME using deepcopy is not safe
        from copy import deepcopy
        stanza = deepcopy(stanza)

        util.resetNamespace(stanza, component.NS_COMPONENT_ACCEPT,
                            self.namespace)

        # translate sender to network JID
        sender = stanza.getAttribute('from')
        if sender and sender != self.network:
            sender = jid.JID(stanza['from'])
            sender.host = self.network
            stanza['from'] = sender.full()
        # TODO should we force self.network if no sender?

        # remove reserved elements
        if stanza.direct and stanza.direct.uri == xmlstream2.NS_XMPP_DIRECT:
            stanza.children.remove(stanza.direct)
        if stanza.name in ('presence', 'message'):
            # storage child
            if stanza.storage and stanza.storage.uri == xmlstream2.NS_XMPP_STORAGE:
                stanza.children.remove(stanza.storage)
            # origin in receipt
            if stanza.request and stanza.request.hasAttribute('from'):
                del stanza.request['from']
            elif stanza.received and stanza.received.hasAttribute('from'):
                del stanza.received['from']
        if stanza.name == 'presence':
            # push device id
            for c in stanza.elements(name='c',
                                     uri=xmlstream2.NS_PRESENCE_PUSH):
                stanza.children.remove(c)
                break

        # force destination address
        if self.xmlstream.otherEntity:
            stanza['to'] = self.xmlstream.otherEntity.full()

        if not stanza.hasAttribute('id'):
            stanza['id'] = util.rand_str(8, util.CHARSBOX_AZN_LOWERCASE)
        xmlstream2.StreamManager.send(self, stanza, force)