Gajim now uses python-nbxmpp library instead of embedding it.

This commit is contained in:
Yann Leboulanger 2012-12-09 21:37:51 +01:00
parent 0c6117a778
commit 77775cf0af
59 changed files with 898 additions and 8805 deletions

View File

@ -16,6 +16,7 @@
<ul>
<li>python2.5 or higher</li>
<li>pygtk2.22 or higher</li>
<li>python-nbxmpp</li>
</ul>
<h2>Optional Runtime Requirements</h2>

View File

@ -28,7 +28,9 @@
import gobject
import gtk
from common import xmpp, gajim, dataforms
import nbxmpp
from common import gajim
from common import dataforms
import gtkgui_helpers
import dialogs
@ -386,7 +388,7 @@ class CommandWindow:
self.send_command(action)
def stage3_next_form(self, command):
if not isinstance(command, xmpp.Node):
if not isinstance(command, nbxmpp.Node):
self.stage5(error=_('Service sent malformed data'), senderror=True)
return
@ -506,8 +508,8 @@ class CommandWindow:
if errorid:
# we've got error code, display appropriate message
try:
errorname = xmpp.NS_STANZAS + ' ' + str(errorid)
errordesc = xmpp.ERRORS[errorname][2]
errorname = nbxmpp.NS_STANZAS + ' ' + str(errorid)
errordesc = nbxmpp.ERRORS[errorname][2]
error = errordesc.decode('utf-8')
del errorname, errordesc
except KeyError: # when stanza doesn't have error description
@ -570,9 +572,9 @@ class CommandWindow:
"""
Request the command list. Change stage on delivery
"""
query = xmpp.Iq(typ='get', to=xmpp.JID(self.jid),
queryNS=xmpp.NS_DISCO_ITEMS)
query.setQuerynode(xmpp.NS_COMMANDS)
query = nbxmpp.Iq(typ='get', to=xmpp.JID(self.jid),
queryNS=nbxmpp.NS_DISCO_ITEMS)
query.setQuerynode(nbxmpp.NS_COMMANDS)
def callback(response):
'''Called on response to query.'''
@ -580,14 +582,14 @@ class CommandWindow:
# is error => error stage
error = response.getError()
if error:
# extracting error description from xmpp/protocol.py
self.stage5(errorid = error)
# extracting error description
self.stage5(errorid=error)
return
# no commands => no commands stage
# commands => command selection stage
query = response.getTag('query')
if query and query.getAttr('node') == xmpp.NS_COMMANDS:
if query and query.getAttr('node') == nbxmpp.NS_COMMANDS:
items = query.getTags('item')
else:
items = []
@ -609,9 +611,9 @@ class CommandWindow:
assert isinstance(self.commandnode, unicode)
assert action in ('execute', 'prev', 'next', 'complete')
stanza = xmpp.Iq(typ='set', to=self.jid)
cmdnode = stanza.addChild('command', namespace=xmpp.NS_COMMANDS, attrs={
'node':self.commandnode, 'action':action})
stanza = nbxmpp.Iq(typ='set', to=self.jid)
cmdnode = stanza.addChild('command', namespace=nbxmpp.NS_COMMANDS,
attrs={'node':self.commandnode, 'action':action})
if self.sessionid:
cmdnode.setAttr('sessionid', self.sessionid)
@ -636,8 +638,8 @@ class CommandWindow:
assert self.commandnode
if self.sessionid and self.account.connection:
# we already have sessionid, so the service sent at least one reply.
stanza = xmpp.Iq(typ='set', to=self.jid)
stanza.addChild('command', namespace=xmpp.NS_COMMANDS, attrs={
stanza = nbxmpp.Iq(typ='set', to=self.jid)
stanza.addChild('command', namespace=nbxmpp.NS_COMMANDS, attrs={
'node':self.commandnode,
'sessionid':self.sessionid,
'action':'cancel'

View File

@ -51,10 +51,11 @@ from common.stanza_session import EncryptedStanzaSession, ArchivingStanzaSession
from common.contacts import GC_Contact
from common.logger import constants
from common.pep import MOODS, ACTIVITIES
from common.xmpp.protocol import NS_XHTML, NS_XHTML_IM, NS_FILE, NS_MUC
from common.xmpp.protocol import NS_RECEIPTS, NS_ESESSION
from common.xmpp.protocol import NS_JINGLE_RTP_AUDIO, NS_JINGLE_RTP_VIDEO, NS_JINGLE_ICE_UDP, NS_JINGLE_FILE_TRANSFER
from common.xmpp.protocol import NS_CHATSTATES
from nbxmpp.protocol import NS_XHTML, NS_XHTML_IM, NS_FILE, NS_MUC
from nbxmpp.protocol import NS_RECEIPTS, NS_ESESSION
from nbxmpp.protocol import NS_JINGLE_RTP_AUDIO, NS_JINGLE_RTP_VIDEO
from nbxmpp.protocol import NS_JINGLE_ICE_UDP, NS_JINGLE_FILE_TRANSFER
from nbxmpp.protocol import NS_CHATSTATES
from common.connection_handlers_events import MessageOutgoingEvent
from common.exceptions import GajimGeneralException

View File

@ -29,10 +29,10 @@ if you need
# suggestion: rewrite functions that return dates to return standard python time tuples,
# exteneded to contain timezone
import xmpp
import nbxmpp
import time
class PersonConstruct(xmpp.Node, object):
class PersonConstruct(nb.Node, object):
"""
Not used for now, as we don't need authors/contributors in pubsub.com feeds.
They rarely exist there
@ -40,7 +40,7 @@ class PersonConstruct(xmpp.Node, object):
def __init__(self, node):
''' Create person construct from node. '''
xmpp.Node.__init__(self, node=node)
nbxmpp.Node.__init__(self, node=node)
def get_name(self):
return self.getTagData('name')
@ -63,14 +63,14 @@ class PersonConstruct(xmpp.Node, object):
'''Conveys an e-mail address associated with the person. Might be None when
not set.''')
class Entry(xmpp.Node, object):
class Entry(nbxmpp.Node, object):
def __init__(self, node=None):
xmpp.Node.__init__(self, 'entry', node=node)
nbxmpp.Node.__init__(self, 'entry', node=node)
def __repr__(self):
return '<Atom:Entry object of id="%r">' % self.getAttr('id')
class OldEntry(xmpp.Node, object):
class OldEntry(nbxmpp.Node, object):
"""
Parser for feeds from pubsub.com. They use old Atom 0.3 format with their
extensions
@ -78,7 +78,7 @@ class OldEntry(xmpp.Node, object):
def __init__(self, node=None):
''' Create new Atom 0.3 entry object. '''
xmpp.Node.__init__(self, 'entry', node=node)
nbxmpp.Node.__init__(self, 'entry', node=node)
def __repr__(self):
return '<Atom0.3:Entry object of id="%r">' % self.getAttr('id')

View File

@ -37,11 +37,13 @@ import hashlib
import logging
log = logging.getLogger('gajim.c.caps_cache')
from common.xmpp import (NS_XHTML_IM, NS_RECEIPTS, NS_ESESSION, NS_CHATSTATES,
NS_JINGLE_ICE_UDP, NS_JINGLE_RTP_AUDIO, NS_JINGLE_RTP_VIDEO, NS_CAPS, NS_JINGLE_FILE_TRANSFER)
from nbxmpp import (NS_XHTML_IM, NS_RECEIPTS, NS_ESESSION, NS_CHATSTATES,
NS_JINGLE_ICE_UDP, NS_JINGLE_RTP_AUDIO, NS_JINGLE_RTP_VIDEO, NS_CAPS,
NS_JINGLE_FILE_TRANSFER)
# Features where we cannot safely assume that the other side supports them
FEATURE_BLACKLIST = [NS_CHATSTATES, NS_XHTML_IM, NS_RECEIPTS, NS_ESESSION,
NS_JINGLE_ICE_UDP, NS_JINGLE_RTP_AUDIO, NS_JINGLE_RTP_VIDEO, NS_JINGLE_FILE_TRANSFER]
NS_JINGLE_ICE_UDP, NS_JINGLE_RTP_AUDIO, NS_JINGLE_RTP_VIDEO,
NS_JINGLE_FILE_TRANSFER]
# Query entry status codes
NEW = 0
@ -96,7 +98,7 @@ def compute_caps_hash(identities, features, dataforms=[], hash_method='sha-1'):
"""
Compute caps hash according to XEP-0115, V1.5
dataforms are xmpp.DataForms objects as common.dataforms don't allow several
dataforms are nbxmpp.DataForms objects as common.dataforms don't allow several
values without a field type list-multi
"""
def sort_identities_func(i1, i2):

View File

@ -22,7 +22,7 @@
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
##
import xmpp
import nbxmpp
import helpers
import dataforms
import gajim
@ -33,7 +33,7 @@ log = logging.getLogger('gajim.c.commands')
class AdHocCommand:
commandnode = 'command'
commandname = 'The Command'
commandfeatures = (xmpp.NS_DATA,)
commandfeatures = (nbxmpp.NS_DATA,)
@staticmethod
def isVisibleFor(samejid):
@ -56,7 +56,7 @@ class AdHocCommand:
assert status in ('executing', 'completed', 'canceled')
response = request.buildReply('result')
cmd = response.getTag('command', namespace=xmpp.NS_COMMANDS)
cmd = response.getTag('command', namespace=nbxmpp.NS_COMMANDS)
cmd.setAttr('sessionid', self.sessionid)
cmd.setAttr('node', self.commandnode)
cmd.setAttr('status', status)
@ -72,8 +72,8 @@ class AdHocCommand:
return response, cmd
def badRequest(self, stanza):
self.connection.connection.send(xmpp.Error(stanza, xmpp.NS_STANZAS + \
' bad-request'))
self.connection.connection.send(nbxmpp.Error(stanza,
nbxmpp.NS_STANZAS + ' bad-request'))
def cancel(self, request):
response = self.buildResponse(request, status = 'canceled')[0]
@ -354,14 +354,14 @@ class ConnectionCommands:
"""
Test if the bare jid given is the same as our bare jid
"""
return xmpp.JID(jid).getStripped() == self.getOurBareJID()
return nbxmpp.JID(jid).getStripped() == self.getOurBareJID()
def commandListQuery(self, con, iq_obj):
iq = iq_obj.buildReply('result')
jid = helpers.get_full_jid_from_iq(iq_obj)
q = iq.getTag('query')
# buildReply don't copy the node attribute. Re-add it
q.setAttr('node', xmpp.NS_COMMANDS)
q.setAttr('node', nbxmpp.NS_COMMANDS)
for node, cmd in self.__commands.iteritems():
if cmd.isVisibleFor(self.isSameJID(jid)):
@ -394,7 +394,7 @@ class ConnectionCommands:
q.addChild('identity', attrs = {'type': 'command-node',
'category': 'automation',
'name': cmd.commandname})
q.addChild('feature', attrs = {'var': xmpp.NS_COMMANDS})
q.addChild('feature', attrs = {'var': nbxmpp.NS_COMMANDS})
for feature in cmd.commandfeatures:
q.addChild('feature', attrs = {'var': feature})
@ -436,8 +436,8 @@ class ConnectionCommands:
# and command exist
if node not in self.__commands.keys():
self.connection.send(
xmpp.Error(iq_obj, xmpp.NS_STANZAS + ' item-not-found'))
raise xmpp.NodeProcessed
nbxmpp.Error(iq_obj, nbxmpp.NS_STANZAS + ' item-not-found'))
raise nbxmpp.NodeProcessed
newcmd = self.__commands[node]
if not newcmd.isVisibleFor(self.isSameJID(jid)):
@ -451,7 +451,7 @@ class ConnectionCommands:
rc = obj.execute(iq_obj)
if rc:
self.__sessions[(jid, sessionid, node)] = obj
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
else:
# the command is already running, check for it
magictuple = (jid, sessionid, node)
@ -486,4 +486,4 @@ class ConnectionCommands:
if not rc:
del self.__sessions[magictuple]
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed

View File

@ -52,7 +52,7 @@ import signal
if os.name != 'nt':
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
import common.xmpp
import nbxmpp
from common import helpers
from common import gajim
from common import gpg
@ -61,7 +61,7 @@ from common import exceptions
from common import check_X509
from connection_handlers import *
from xmpp import Smacks
from nbxmpp import Smacks
from string import Template
import logging
log = logging.getLogger('gajim.c.connection')
@ -357,21 +357,21 @@ class CommonConnection:
label, forward_from, delayed, session, form_node, user_nick, attention,
callback):
if type_ == 'chat':
msg_iq = common.xmpp.Message(to=fjid, body=msgtxt, typ=type_,
msg_iq = nbxmpp.Message(to=fjid, body=msgtxt, typ=type_,
xhtml=xhtml)
else:
if subject:
msg_iq = common.xmpp.Message(to=fjid, body=msgtxt, typ='normal',
msg_iq = nbxmpp.Message(to=fjid, body=msgtxt, typ='normal',
subject=subject, xhtml=xhtml)
else:
msg_iq = common.xmpp.Message(to=fjid, body=msgtxt, typ='normal',
msg_iq = nbxmpp.Message(to=fjid, body=msgtxt, typ='normal',
xhtml=xhtml)
if msg_id:
msg_iq.setID(msg_id)
if msgenc:
msg_iq.setTag(common.xmpp.NS_ENCRYPTED + ' x').setData(msgenc)
msg_iq.setTag(nbxmpp.NS_ENCRYPTED + ' x').setData(msgenc)
if form_node:
msg_iq.addChild(node=form_node)
@ -380,7 +380,7 @@ class CommonConnection:
# XEP-0172: user_nickname
if user_nick:
msg_iq.setTag('nick', namespace = common.xmpp.NS_NICK).setData(
msg_iq.setTag('nick', namespace = nbxmpp.NS_NICK).setData(
user_nick)
# TODO: We might want to write a function so we don't need to
@ -399,7 +399,7 @@ class CommonConnection:
if forward_from:
addresses = msg_iq.addChild('addresses',
namespace=common.xmpp.NS_ADDRESS)
namespace=nbxmpp.NS_ADDRESS)
addresses.addChild('address', attrs = {'type': 'ofrom',
'jid': forward_from})
@ -408,14 +408,14 @@ class CommonConnection:
our_jid = gajim.get_jid_from_account(self.name) + '/' + \
self.server_resource
timestamp = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime(delayed))
msg_iq.addChild('delay', namespace=common.xmpp.NS_DELAY2,
msg_iq.addChild('delay', namespace=nbxmpp.NS_DELAY2,
attrs={'from': our_jid, 'stamp': timestamp})
# XEP-0184
if msgtxt and gajim.config.get_per('accounts', self.name,
'request_receipt') and contact and contact.supports(
common.xmpp.NS_RECEIPTS):
msg_iq.setTag('request', namespace=common.xmpp.NS_RECEIPTS)
nbxmpp.NS_RECEIPTS):
msg_iq.setTag('request', namespace=nbxmpp.NS_RECEIPTS)
if session:
# XEP-0201
@ -428,7 +428,7 @@ class CommonConnection:
# XEP-0224
if attention:
msg_iq.setTag('attention', namespace=common.xmpp.NS_ATTENTION)
msg_iq.setTag('attention', namespace=nbxmpp.NS_ATTENTION)
if callback:
callback(jid, msg, keyID, forward_from, session, original_message,
@ -453,7 +453,7 @@ class CommonConnection:
try:
if xhtml and gajim.config.get('log_xhtml_messages'):
log_msg = '<body xmlns="%s">%s</body>' % (
common.xmpp.NS_XHTML, xhtml)
nbxmpp.NS_XHTML, xhtml)
gajim.logger.write(kind, jid, log_msg)
except exceptions.PysqliteOperationalError, e:
self.dispatch('DB_ERROR', (_('Disk Write Error'),
@ -546,8 +546,7 @@ class CommonConnection:
to_whom_jid = jid
if resource:
to_whom_jid += '/' + resource
iq = common.xmpp.Iq(to=to_whom_jid, typ='get', queryNS=\
common.xmpp.NS_LAST)
iq = nbxmpp.Iq(to=to_whom_jid, typ='get', queryNS=nbxmpp.NS_LAST)
id_ = self.connection.getAnID()
iq.setID(id_)
if groupchat_jid:
@ -615,10 +614,10 @@ class CommonConnection:
def _event_dispatcher(self, realm, event, data):
if realm == '':
if event == common.xmpp.transports_nb.DATA_RECEIVED:
if event == nbxmpp.transports_nb.DATA_RECEIVED:
gajim.nec.push_incoming_event(StanzaReceivedEvent(None,
conn=self, stanza_str=unicode(data, errors='ignore')))
elif event == common.xmpp.transports_nb.DATA_SENT:
elif event == nbxmpp.transports_nb.DATA_SENT:
gajim.nec.push_incoming_event(StanzaSentEvent(None, conn=self,
stanza_str=unicode(data)))
@ -646,7 +645,7 @@ class CommonConnection:
if show == 'offline':
self.connected = 0
if self.connection:
p = common.xmpp.Presence(typ = 'unavailable')
p = nbxmpp.Presence(typ = 'unavailable')
p = self.add_sha(p, False)
if msg:
p.setStatus(msg)
@ -868,8 +867,8 @@ class Connection(CommonConnection, ConnectionHandlers):
def _event_dispatcher(self, realm, event, data):
CommonConnection._event_dispatcher(self, realm, event, data)
if realm == common.xmpp.NS_REGISTER:
if event == common.xmpp.features_nb.REGISTER_DATA_RECEIVED:
if realm == nbxmpp.NS_REGISTER:
if event == nbxmpp.features_nb.REGISTER_DATA_RECEIVED:
# data is (agent, DataFrom, is_form, error_msg)
if self.new_account_info and \
self.new_account_info['hostname'] == data[0]:
@ -887,7 +886,7 @@ class Connection(CommonConnection, ConnectionHandlers):
helpers.replace_dataform_media(conf, data[4])
if self.new_account_form:
def _on_register_result(result):
if not common.xmpp.isResultNode(result):
if not nbxmpp.isResultNode(result):
gajim.nec.push_incoming_event(AccountNotCreatedEvent(
None, conn=self, reason=result.getError()))
return
@ -908,7 +907,7 @@ class Connection(CommonConnection, ConnectionHandlers):
# typed, so send them
if is_form:
#TODO: Check if form has changed
iq = common.xmpp.Iq('set', common.xmpp.NS_REGISTER,
iq = nbxmpp.Iq('set', nbxmpp.NS_REGISTER,
to=self._hostname)
iq.setTag('query').addChild(node=self.new_account_form)
self.connection.SendAndCallForResponse(iq,
@ -922,7 +921,7 @@ class Connection(CommonConnection, ConnectionHandlers):
gajim.nec.push_incoming_event(AccountNotCreatedEvent(
None, conn=self, reason=reason))
return
common.xmpp.features_nb.register(self.connection,
nbxmpp.features_nb.register(self.connection,
self._hostname, self.new_account_form,
_on_register_result)
return
@ -944,12 +943,12 @@ class Connection(CommonConnection, ConnectionHandlers):
gajim.nec.push_incoming_event(RegisterAgentInfoReceivedEvent(
None, conn=self, agent=data[0], config=conf,
is_form=is_form))
elif realm == common.xmpp.NS_PRIVACY:
if event == common.xmpp.features_nb.PRIVACY_LISTS_RECEIVED:
elif realm == nbxmpp.NS_PRIVACY:
if event == nbxmpp.features_nb.PRIVACY_LISTS_RECEIVED:
# data is (list)
gajim.nec.push_incoming_event(PrivacyListsReceivedEvent(None,
conn=self, lists_list=data))
elif event == common.xmpp.features_nb.PRIVACY_LIST_RECEIVED:
elif event == nbxmpp.features_nb.PRIVACY_LIST_RECEIVED:
# data is (resp)
if not data:
return
@ -971,7 +970,7 @@ class Connection(CommonConnection, ConnectionHandlers):
'order':dict_item['order'], 'child':childs})
gajim.nec.push_incoming_event(PrivacyListReceivedEvent(None,
conn=self, list_name=name, rules=rules))
elif event == common.xmpp.features_nb.PRIVACY_LISTS_ACTIVE_DEFAULT:
elif event == nbxmpp.features_nb.PRIVACY_LISTS_ACTIVE_DEFAULT:
# data is (dict)
gajim.nec.push_incoming_event(PrivacyListActiveDefaultEvent(
None, conn=self, active_list=data['active'],
@ -1116,7 +1115,7 @@ class Connection(CommonConnection, ConnectionHandlers):
if self._proxy and self._proxy['type']=='bosh':
# with BOSH, we can't do TLS negotiation with <starttls>, we do only "plain"
# connection and TLS with handshake right after TCP connecting ("ssl")
scheme = common.xmpp.transports_nb.urisplit(self._proxy['bosh_uri'])[0]
scheme = nbxmpp.transports_nb.urisplit(self._proxy['bosh_uri'])[0]
if scheme=='https':
self._connection_types = ['ssl']
else:
@ -1172,14 +1171,14 @@ class Connection(CommonConnection, ConnectionHandlers):
mycerts = common.gajim.MY_CACERTS
secure_tuple = (self._current_type, cacerts, mycerts)
con = common.xmpp.NonBlockingClient(
con = nbxmpp.NonBlockingClient(
domain=self._hostname,
caller=self,
idlequeue=gajim.idlequeue)
self.last_connection = con
# increase default timeout for server responses
common.xmpp.dispatcher_nb.DEFAULT_TIMEOUT_SECONDS = \
nbxmpp.dispatcher_nb.DEFAULT_TIMEOUT_SECONDS = \
self.try_connecting_for_foo_secs
# FIXME: this is a hack; need a better way
if self.on_connect_success == self._on_new_account:
@ -1231,9 +1230,9 @@ class Connection(CommonConnection, ConnectionHandlers):
sectxt = _('Check your connection or try again later.')
if self.streamError:
# show error dialog
key = common.xmpp.NS_XMPP_STREAMS + ' ' + self.streamError
if key in common.xmpp.ERRORS:
sectxt2 = _('Server replied: %s') % common.xmpp.ERRORS[key][2]
key = nbxmpp.NS_XMPP_STREAMS + ' ' + self.streamError
if key in nbxmpp.ERRORS:
sectxt2 = _('Server replied: %s') % nbxmpp.ERRORS[key][2]
gajim.nec.push_incoming_event(InformationEvent(None,
conn=self, level='error', pri_txt=pritxt,
sec_txt='%s\n%s' % (sectxt2, sectxt)))
@ -1433,7 +1432,7 @@ class Connection(CommonConnection, ConnectionHandlers):
def get_privacy_lists(self):
if not gajim.account_is_connected(self.name):
return
common.xmpp.features_nb.getPrivacyLists(self.connection)
nbxmpp.features_nb.getPrivacyLists(self.connection)
def send_keepalive(self):
# nothing received for the last foo seconds
@ -1460,12 +1459,12 @@ class Connection(CommonConnection, ConnectionHandlers):
else:
to = gajim.config.get_per('accounts', self.name, 'hostname')
self.awaiting_xmpp_ping_id = id_
iq = common.xmpp.Iq('get', to=to)
iq.addChild(name = 'ping', namespace = common.xmpp.NS_PING)
iq = nbxmpp.Iq('get', to=to)
iq.addChild(name='ping', namespace=nbxmpp.NS_PING)
iq.setID(id_)
def _on_response(resp):
timePong = time_time()
if not common.xmpp.isResultNode(resp):
if not nbxmpp.isResultNode(resp):
gajim.nec.push_incoming_event(PingErrorEvent(None, conn=self,
contact=pingTo))
return
@ -1478,12 +1477,12 @@ class Connection(CommonConnection, ConnectionHandlers):
else:
self.connection.SendAndCallForResponse(iq, self._on_xmpp_ping_answer)
gajim.idlequeue.set_alarm(self.check_pingalive, gajim.config.get_per(
'accounts', self.name, 'time_for_ping_alive_answer'))
'accounts', self.name, 'time_for_ping_alive_answer'))
def get_active_default_lists(self):
if not gajim.account_is_connected(self.name):
return
common.xmpp.features_nb.getActiveAndDefaultPrivacyLists(self.connection)
nbxmpp.features_nb.getActiveAndDefaultPrivacyLists(self.connection)
def del_privacy_list(self, privacy_list):
if not gajim.account_is_connected(self.name):
@ -1498,41 +1497,42 @@ class Connection(CommonConnection, ConnectionHandlers):
'list'), sec_txt=_('Privacy list %s has not been removed. '
'It is maybe active in one of your connected resources. '
'Deactivate it and try again.') % privacy_list))
common.xmpp.features_nb.delPrivacyList(self.connection, privacy_list,
_on_del_privacy_list_result)
nbxmpp.features_nb.delPrivacyList(self.connection, privacy_list,
_on_del_privacy_list_result)
def get_privacy_list(self, title):
if not gajim.account_is_connected(self.name):
return
common.xmpp.features_nb.getPrivacyList(self.connection, title)
nbxmpp.features_nb.getPrivacyList(self.connection, title)
def set_privacy_list(self, listname, tags):
if not gajim.account_is_connected(self.name):
return
common.xmpp.features_nb.setPrivacyList(self.connection, listname, tags)
nbxmpp.features_nb.setPrivacyList(self.connection, listname, tags)
def set_active_list(self, listname):
if not gajim.account_is_connected(self.name):
return
common.xmpp.features_nb.setActivePrivacyList(self.connection, listname, 'active')
nbxmpp.features_nb.setActivePrivacyList(self.connection, listname,
'active')
def set_default_list(self, listname):
if not gajim.account_is_connected(self.name):
return
common.xmpp.features_nb.setDefaultPrivacyList(self.connection, listname)
nbxmpp.features_nb.setDefaultPrivacyList(self.connection, listname)
def build_privacy_rule(self, name, action, order=1):
"""
Build a Privacy rule stanza for invisibility
"""
iq = common.xmpp.Iq('set', common.xmpp.NS_PRIVACY, xmlns = '')
iq = nbxmpp.Iq('set', nbxmpp.NS_PRIVACY, xmlns='')
l = iq.setQuery().setTag('list', {'name': name})
i = l.setTag('item', {'action': action, 'order': str(order)})
i.setTag('presence-out')
return iq
def build_invisible_rule(self):
iq = common.xmpp.Iq('set', common.xmpp.NS_PRIVACY, xmlns = '')
iq = nbxmpp.Iq('set', nbxmpp.NS_PRIVACY, xmlns='')
l = iq.setQuery().setTag('list', {'name': 'invisible'})
if self.name in gajim.interface.status_sent_to_groups and \
len(gajim.interface.status_sent_to_groups[self.name]) > 0:
@ -1562,7 +1562,7 @@ class Connection(CommonConnection, ConnectionHandlers):
"""
if not gajim.account_is_connected(self.name):
return
iq = common.xmpp.Iq('set', common.xmpp.NS_PRIVACY, xmlns = '')
iq = nbxmpp.Iq('set', nbxmpp.NS_PRIVACY, xmlns='')
iq.setQuery().setTag('active', {'name': name})
self.connection.send(iq)
@ -1581,7 +1581,7 @@ class Connection(CommonConnection, ConnectionHandlers):
# offline presence first as it's required by XEP-0126
if self.connected > 1 and self.privacy_rules_supported:
self.on_purpose = True
p = common.xmpp.Presence(typ = 'unavailable')
p = nbxmpp.Presence(typ='unavailable')
p = self.add_sha(p, False)
if msg:
p.setStatus(msg)
@ -1602,12 +1602,12 @@ class Connection(CommonConnection, ConnectionHandlers):
self.connected = gajim.SHOW_LIST.index('invisible')
self.status = msg
priority = unicode(gajim.get_priority(self.name, 'invisible'))
p = common.xmpp.Presence(priority = priority)
p = nbxmpp.Presence(priority=priority)
p = self.add_sha(p, True)
if msg:
p.setStatus(msg)
if signed:
p.setTag(common.xmpp.NS_SIGNED + ' x').setData(signed)
p.setTag(nbxmpp.NS_SIGNED + ' x').setData(signed)
self.connection.send(p)
self.priority = priority
gajim.nec.push_incoming_event(OurShowEvent(None, conn=self,
@ -1669,7 +1669,7 @@ class Connection(CommonConnection, ConnectionHandlers):
def _request_privacy(self):
if not gajim.account_is_connected(self.name) or not self.connection:
return
iq = common.xmpp.Iq('get', common.xmpp.NS_PRIVACY, xmlns = '')
iq = nbxmpp.Iq('get', nbxmpp.NS_PRIVACY, xmlns='')
id_ = self.connection.getAnID()
iq.setID(id_)
self.awaiting_answers[id_] = (PRIVACY_ARRIVED, )
@ -1704,44 +1704,43 @@ class Connection(CommonConnection, ConnectionHandlers):
hostname = gajim.config.get_per('accounts', self.name, 'hostname')
our_jid = gajim.get_jid_from_account(self.name)
if obj.fjid == hostname:
if common.xmpp.NS_GMAILNOTIFY in obj.features:
if nbxmpp.NS_GMAILNOTIFY in obj.features:
gajim.gmail_domains.append(obj.fjid)
self.request_gmail_notifications()
if common.xmpp.NS_SECLABEL in obj.features:
if nbxmpp.NS_SECLABEL in obj.features:
self.seclabel_supported = True
for identity in obj.identities:
if identity['category'] == 'pubsub' and identity.get(
'type') == 'pep':
self.pep_supported = True
break
if common.xmpp.NS_VCARD in obj.features:
if nbxmpp.NS_VCARD in obj.features:
self.vcard_supported = True
if common.xmpp.NS_PUBSUB in obj.features:
if nbxmpp.NS_PUBSUB in obj.features:
self.pubsub_supported = True
if common.xmpp.NS_PUBSUB_PUBLISH_OPTIONS in obj.features:
if nbxmpp.NS_PUBSUB_PUBLISH_OPTIONS in obj.features:
self.pubsub_publish_options_supported = True
else:
# Remove stored bookmarks accessible to everyone.
self.send_pb_purge(our_jid, 'storage:bookmarks')
self.send_pb_delete(our_jid, 'storage:bookmarks')
if common.xmpp.NS_ARCHIVE in obj.features:
if nbxmpp.NS_ARCHIVE in obj.features:
self.archiving_supported = True
if common.xmpp.NS_ARCHIVE_AUTO in obj.features:
if nbxmpp.NS_ARCHIVE_AUTO in obj.features:
self.archive_auto_supported = True
if common.xmpp.NS_ARCHIVE_MANAGE in obj.features:
if nbxmpp.NS_ARCHIVE_MANAGE in obj.features:
self.archive_manage_supported = True
if common.xmpp.NS_ARCHIVE_MANUAL in obj.features:
if nbxmpp.NS_ARCHIVE_MANUAL in obj.features:
self.archive_manual_supported = True
if common.xmpp.NS_ARCHIVE_PREF in obj.features:
if nbxmpp.NS_ARCHIVE_PREF in obj.features:
self.archive_pref_supported = True
if common.xmpp.NS_CARBONS in obj.features and \
gajim.config.get_per('accounts', self.name,
'enable_message_carbons'):
if nbxmpp.NS_CARBONS in obj.features and gajim.config.get_per(
'accounts', self.name, 'enable_message_carbons'):
# Server supports carbons, activate it
iq = common.xmpp.Iq('set')
iq.setTag('enable', namespace=common.xmpp.NS_CARBONS)
iq = nbxmpp.Iq('set')
iq.setTag('enable', namespace=nbxmpp.NS_CARBONS)
self.connection.send(iq)
if common.xmpp.NS_BYTESTREAM in obj.features and \
if nbxmpp.NS_BYTESTREAM in obj.features and \
gajim.config.get_per('accounts', self.name, 'use_ft_proxies'):
our_fjid = helpers.parse_jid(our_jid + '/' + \
self.server_resource)
@ -1749,7 +1748,7 @@ class Connection(CommonConnection, ConnectionHandlers):
'test_ft_proxies_on_startup')
gajim.proxy65_manager.resolve(obj.fjid, self.connection,
our_fjid, default=self.name, testit=testit)
if common.xmpp.NS_MUC in obj.features and is_muc:
if nbxmpp.NS_MUC in obj.features and is_muc:
type_ = transport_type or 'jabber'
self.muc_jid[type_] = obj.fjid
if transport_type:
@ -1770,20 +1769,19 @@ class Connection(CommonConnection, ConnectionHandlers):
if not msg:
msg = ''
if show == 'offline':
p = common.xmpp.Presence(typ = 'unavailable', to = jid)
p = nbxmpp.Presence(typ='unavailable', to=jid)
p = self.add_sha(p, False)
if msg:
p.setStatus(msg)
else:
signed = self.get_signed_presence(msg)
priority = unicode(gajim.get_priority(self.name, sshow))
p = common.xmpp.Presence(typ = None, priority = priority, show = sshow,
to = jid)
p = nbxmpp.Presence(typ=None, priority=priority, show=sshow, to=jid)
p = self.add_sha(p)
if msg:
p.setStatus(msg)
if signed:
p.setTag(common.xmpp.NS_SIGNED + ' x').setData(signed)
p.setTag(nbxmpp.NS_SIGNED + ' x').setData(signed)
self.connection.send(p)
def _change_to_invisible(self, msg):
@ -1802,24 +1800,24 @@ class Connection(CommonConnection, ConnectionHandlers):
def _update_status(self, show, msg):
xmpp_show = helpers.get_xmpp_show(show)
priority = unicode(gajim.get_priority(self.name, xmpp_show))
p = common.xmpp.Presence(typ=None, priority=priority, show=xmpp_show)
p = nbxmpp.Presence(typ=None, priority=priority, show=xmpp_show)
p = self.add_sha(p)
if msg:
p.setStatus(msg)
signed = self.get_signed_presence(msg)
if signed:
p.setTag(common.xmpp.NS_SIGNED + ' x').setData(signed)
p.setTag(nbxmpp.NS_SIGNED + ' x').setData(signed)
if self.connection:
self.connection.send(p)
self.priority = priority
gajim.nec.push_incoming_event(OurShowEvent(None, conn=self,
show=show))
def send_motd(self, jid, subject = '', msg = '', xhtml = None):
def send_motd(self, jid, subject='', msg='', xhtml=None):
if not gajim.account_is_connected(self.name):
return
msg_iq = common.xmpp.Message(to = jid, body = msg, subject = subject,
xhtml = xhtml)
msg_iq = nbxmpp.Message(to=jid, body=msg, subject=subject,
xhtml=xhtml)
self.connection.send(msg_iq)
@ -1887,8 +1885,8 @@ class Connection(CommonConnection, ConnectionHandlers):
for contact in contacts:
msg += '\n "%s" (%s)' % (contact.get_full_jid(),
contact.get_shown_name())
msg_iq = common.xmpp.Message(to=jid, body=msg)
x = msg_iq.addChild(name='x', namespace=common.xmpp.NS_ROSTERX)
msg_iq = nbxmpp.Message(to=jid, body=msg)
x = msg_iq.addChild(name='x', namespace=nbxmpp.NS_ROSTERX)
for contact in contacts:
x.addChild(name='item', attrs={'action': 'add', 'jid': contact.jid,
'name': contact.get_shown_name()})
@ -1906,14 +1904,14 @@ class Connection(CommonConnection, ConnectionHandlers):
if not gajim.account_is_connected(self.name):
return
log.debug('ack\'ing subscription complete for %s' % jid)
p = common.xmpp.Presence(jid, 'subscribe')
p = nbxmpp.Presence(jid, 'subscribe')
self.connection.send(p)
def ack_unsubscribed(self, jid):
if not gajim.account_is_connected(self.name):
return
log.debug('ack\'ing unsubscription complete for %s' % jid)
p = common.xmpp.Presence(jid, 'unsubscribe')
p = nbxmpp.Presence(jid, 'unsubscribe')
self.connection.send(p)
def request_subscription(self, jid, msg='', name='', groups=[],
@ -1927,16 +1925,16 @@ class Connection(CommonConnection, ConnectionHandlers):
infos = {'jid': jid}
if name:
infos['name'] = name
iq = common.xmpp.Iq('set', common.xmpp.NS_ROSTER)
iq = nbxmpp.Iq('set', nbxmpp.NS_ROSTER)
q = iq.setQuery()
item = q.addChild('item', attrs=infos)
for g in groups:
item.addChild('group').setData(g)
self.connection.send(iq)
p = common.xmpp.Presence(jid, 'subscribe')
p = nbxmpp.Presence(jid, 'subscribe')
if user_nick:
p.setTag('nick', namespace = common.xmpp.NS_NICK).setData(user_nick)
p.setTag('nick', namespace = nbxmpp.NS_NICK).setData(user_nick)
p = self.add_sha(p)
if msg:
p.setStatus(msg)
@ -1945,14 +1943,14 @@ class Connection(CommonConnection, ConnectionHandlers):
def send_authorization(self, jid):
if not gajim.account_is_connected(self.name):
return
p = common.xmpp.Presence(jid, 'subscribed')
p = nbxmpp.Presence(jid, 'subscribed')
p = self.add_sha(p)
self.connection.send(p)
def refuse_authorization(self, jid):
if not gajim.account_is_connected(self.name):
return
p = common.xmpp.Presence(jid, 'unsubscribed')
p = nbxmpp.Presence(jid, 'unsubscribed')
p = self.add_sha(p)
self.connection.send(p)
@ -1972,7 +1970,7 @@ class Connection(CommonConnection, ConnectionHandlers):
def unsubscribe_agent(self, agent):
if not gajim.account_is_connected(self.name):
return
iq = common.xmpp.Iq('set', common.xmpp.NS_REGISTER, to = agent)
iq = nbxmpp.Iq('set', nbxmpp.NS_REGISTER, to=agent)
iq.setQuery().setTag('remove')
id_ = self.connection.getAnID()
iq.setID(id_)
@ -2019,7 +2017,7 @@ class Connection(CommonConnection, ConnectionHandlers):
return
self.on_connect_failure = None
self.connection = con
common.xmpp.features_nb.getRegInfo(con, self._hostname)
nbxmpp.features_nb.getRegInfo(con, self._hostname)
def request_os_info(self, jid, resource, groupchat_jid=None):
"""
@ -2035,8 +2033,7 @@ class Connection(CommonConnection, ConnectionHandlers):
to_whom_jid = jid
if resource:
to_whom_jid += '/' + resource
iq = common.xmpp.Iq(to=to_whom_jid, typ='get', queryNS=\
common.xmpp.NS_VERSION)
iq = nbxmpp.Iq(to=to_whom_jid, typ='get', queryNS=nbxmpp.NS_VERSION)
id_ = self.connection.getAnID()
iq.setID(id_)
if groupchat_jid:
@ -2058,8 +2055,8 @@ class Connection(CommonConnection, ConnectionHandlers):
to_whom_jid = jid
if resource:
to_whom_jid += '/' + resource
iq = common.xmpp.Iq(to=to_whom_jid, typ='get')
iq.addChild('time', namespace=common.xmpp.NS_TIME_REVISED)
iq = nbxmpp.Iq(to=to_whom_jid, typ='get')
iq.addChild('time', namespace=nbxmpp.NS_TIME_REVISED)
id_ = self.connection.getAnID()
iq.setID(id_)
if groupchat_jid:
@ -2075,8 +2072,8 @@ class Connection(CommonConnection, ConnectionHandlers):
typ_ = 'set'
else:
typ_ = 'get'
iq = common.xmpp.Iq(typ=typ_, to=jid)
query = iq.addChild(name='query', namespace=common.xmpp.NS_GATEWAY)
iq = nbxmpp.Iq(typ=typ_, to=jid)
query = iq.addChild(name='query', namespace=nbxmpp.NS_GATEWAY)
if prompt:
query.setTagData('prompt', prompt)
self.connection.SendAndCallForResponse(iq, _on_prompt_result)
@ -2087,8 +2084,8 @@ class Connection(CommonConnection, ConnectionHandlers):
"""
if not gajim.account_is_connected(self.name):
return
iq = common.xmpp.Iq(typ='get')
iq2 = iq.addChild(name='query', namespace=common.xmpp.NS_PRIVATE)
iq = nbxmpp.Iq(typ='get')
iq2 = iq.addChild(name='query', namespace=nbxmpp.NS_PRIVATE)
iq2.addChild(name='gajim', namespace='gajim:prefs')
self.connection.send(iq)
@ -2097,8 +2094,8 @@ class Connection(CommonConnection, ConnectionHandlers):
return
self.seclabel_catalogue_request(to, callback)
server = gajim.get_jid_from_account(self.name).split("@")[1] # Really, no better way?
iq = common.xmpp.Iq(typ='get', to=server)
iq2 = iq.addChild(name='catalog', namespace=common.xmpp.NS_SECLABEL_CATALOG)
iq = nbxmpp.Iq(typ='get', to=server)
iq2 = iq.addChild(name='catalog', namespace=nbxmpp.NS_SECLABEL_CATALOG)
iq2.setAttr('to', to)
self.connection.send(iq)
@ -2135,8 +2132,8 @@ class Connection(CommonConnection, ConnectionHandlers):
def _request_bookmarks_xml(self):
if not gajim.account_is_connected(self.name):
return
iq = common.xmpp.Iq(typ='get')
iq2 = iq.addChild(name='query', namespace=common.xmpp.NS_PRIVATE)
iq = nbxmpp.Iq(typ='get')
iq2 = iq.addChild(name='query', namespace=nbxmpp.NS_PRIVATE)
iq2.addChild(name='storage', namespace='storage:bookmarks')
self.connection.send(iq)
@ -2170,7 +2167,7 @@ class Connection(CommonConnection, ConnectionHandlers):
"""
if not gajim.account_is_connected(self.name):
return
iq = common.xmpp.Node(tag='storage', attrs={'xmlns': 'storage:bookmarks'})
iq = nbxmpp.Node(tag='storage', attrs={'xmlns': 'storage:bookmarks'})
for bm in self.bookmarks:
iq2 = iq.addChild(name = "conference")
iq2.setAttr('jid', bm['jid'])
@ -2189,11 +2186,11 @@ class Connection(CommonConnection, ConnectionHandlers):
if self.pubsub_supported and self.pubsub_publish_options_supported and \
storage_type != 'xml':
options = common.xmpp.Node(common.xmpp.NS_DATA + ' x',
options = nbxmpp.Node(nbxmpp.NS_DATA + ' x',
attrs={'type': 'submit'})
f = options.addChild('field', attrs={'var': 'FORM_TYPE',
'type': 'hidden'})
f.setTagData('value', common.xmpp.NS_PUBSUB_PUBLISH_OPTIONS)
f.setTagData('value', nbxmpp.NS_PUBSUB_PUBLISH_OPTIONS)
f = options.addChild('field', attrs={'var': 'pubsub#persist_items'})
f.setTagData('value', 'true')
f = options.addChild('field', attrs={'var': 'pubsub#access_model'})
@ -2201,8 +2198,8 @@ class Connection(CommonConnection, ConnectionHandlers):
self.send_pb_publish('', 'storage:bookmarks', iq, 'current',
options=options)
if storage_type != 'pubsub':
iqA = common.xmpp.Iq(typ='set')
iqB = iqA.addChild(name='query', namespace=common.xmpp.NS_PRIVATE)
iqA = nbxmpp.Iq(typ='set')
iqB = iqA.addChild(name='query', namespace=nbxmpp.NS_PRIVATE)
iqB.addChild(node=iq)
self.connection.send(iqA)
@ -2213,8 +2210,8 @@ class Connection(CommonConnection, ConnectionHandlers):
self.annotations = {}
if not gajim.account_is_connected(self.name):
return
iq = common.xmpp.Iq(typ='get')
iq2 = iq.addChild(name='query', namespace=common.xmpp.NS_PRIVATE)
iq = nbxmpp.Iq(typ='get')
iq2 = iq.addChild(name='query', namespace=nbxmpp.NS_PRIVATE)
iq2.addChild(name='storage', namespace='storage:rosternotes')
self.connection.send(iq)
@ -2224,8 +2221,8 @@ class Connection(CommonConnection, ConnectionHandlers):
"""
if not gajim.account_is_connected(self.name):
return
iq = common.xmpp.Iq(typ='set')
iq2 = iq.addChild(name='query', namespace=common.xmpp.NS_PRIVATE)
iq = nbxmpp.Iq(typ='set')
iq2 = iq.addChild(name='query', namespace=nbxmpp.NS_PRIVATE)
iq3 = iq2.addChild(name='storage', namespace='storage:rosternotes')
for jid in self.annotations.keys():
if self.annotations[jid]:
@ -2240,8 +2237,8 @@ class Connection(CommonConnection, ConnectionHandlers):
"""
if not gajim.account_is_connected(self.name):
return
iq = common.xmpp.Iq(typ='get')
iq2 = iq.addChild(name='query', namespace=common.xmpp.NS_PRIVATE)
iq = nbxmpp.Iq(typ='get')
iq2 = iq.addChild(name='query', namespace=nbxmpp.NS_PRIVATE)
iq2.addChild(name='roster', namespace='roster:delimiter')
id_ = self.connection.getAnID()
iq.setID(id_)
@ -2254,8 +2251,8 @@ class Connection(CommonConnection, ConnectionHandlers):
"""
if not gajim.account_is_connected(self.name):
return
iq = common.xmpp.Iq(typ='set')
iq2 = iq.addChild(name='query', namespace=common.xmpp.NS_PRIVATE)
iq = nbxmpp.Iq(typ='set')
iq2 = iq.addChild(name='query', namespace=nbxmpp.NS_PRIVATE)
iq3 = iq2.addChild(name='roster', namespace='roster:delimiter')
iq3.setData(delimiter)
@ -2267,8 +2264,8 @@ class Connection(CommonConnection, ConnectionHandlers):
"""
if not gajim.account_is_connected(self.name):
return
iq = common.xmpp.Iq(typ='get')
iq2 = iq.addChild(name='query', namespace=common.xmpp.NS_PRIVATE)
iq = nbxmpp.Iq(typ='get')
iq2 = iq.addChild(name='query', namespace=nbxmpp.NS_PRIVATE)
iq2.addChild(name='storage', namespace='storage:metacontacts')
id_ = self.connection.getAnID()
iq.setID(id_)
@ -2281,8 +2278,8 @@ class Connection(CommonConnection, ConnectionHandlers):
"""
if not gajim.account_is_connected(self.name):
return
iq = common.xmpp.Iq(typ='set')
iq2 = iq.addChild(name='query', namespace=common.xmpp.NS_PRIVATE)
iq = nbxmpp.Iq(typ='set')
iq2 = iq.addChild(name='query', namespace=nbxmpp.NS_PRIVATE)
iq3 = iq2.addChild(name='storage', namespace='storage:metacontacts')
for tag in tags_list:
for data in tags_list[tag]:
@ -2290,14 +2287,14 @@ class Connection(CommonConnection, ConnectionHandlers):
dict_ = {'jid': jid, 'tag': tag}
if 'order' in data:
dict_['order'] = data['order']
iq3.addChild(name = 'meta', attrs = dict_)
iq3.addChild(name='meta', attrs=dict_)
self.connection.send(iq)
def request_roster(self):
version = None
features = self.connection.Dispatcher.Stream.features
if features and features.getTag('ver',
namespace=common.xmpp.NS_ROSTER_VER):
namespace=nbxmpp.NS_ROSTER_VER):
version = gajim.config.get_per('accounts', self.name,
'roster_version')
if version and not gajim.contacts.get_contacts_jid_list(
@ -2313,26 +2310,26 @@ class Connection(CommonConnection, ConnectionHandlers):
if not gajim.account_is_connected(self.name):
return
show = helpers.get_xmpp_show(gajim.SHOW_LIST[self.connected])
p = common.xmpp.Presence(to = agent, typ = ptype, show = show)
p = nbxmpp.Presence(to=agent, typ=ptype, show=show)
p = self.add_sha(p, ptype != 'unavailable')
self.connection.send(p)
def send_captcha(self, jid, form_node):
if not gajim.account_is_connected(self.name):
return
iq = common.xmpp.Iq(typ='set', to=jid)
captcha = iq.addChild(name='captcha', namespace=common.xmpp.NS_CAPTCHA)
iq = nbxmpp.Iq(typ='set', to=jid)
captcha = iq.addChild(name='captcha', namespace=nbxmpp.NS_CAPTCHA)
captcha.addChild(node=form_node)
self.connection.send(iq)
def check_unique_room_id_support(self, server, instance):
if not gajim.account_is_connected(self.name):
return
iq = common.xmpp.Iq(typ = 'get', to = server)
iq = nbxmpp.Iq(typ='get', to=server)
iq.setAttr('id', 'unique1')
iq.addChild('unique', namespace=common.xmpp.NS_MUC_UNIQUE)
iq.addChild('unique', namespace=nbxmpp.NS_MUC_UNIQUE)
def _on_response(resp):
if not common.xmpp.isResultNode(resp):
if not nbxmpp.isResultNode(resp):
gajim.nec.push_incoming_event(UniqueRoomIdNotSupportedEvent(
None, conn=self, instance=instance, server=server))
return
@ -2369,7 +2366,7 @@ class Connection(CommonConnection, ConnectionHandlers):
last_log = 0
self.last_history_time[room_jid] = last_log
p = common.xmpp.Presence(to='%s/%s' % (room_jid, nick),
p = nbxmpp.Presence(to='%s/%s' % (room_jid, nick),
show=show, status=self.status)
h = hmac.new(self.secret_hmac, room_jid).hexdigest()[:6]
id_ = self.connection.getAnID()
@ -2379,7 +2376,7 @@ class Connection(CommonConnection, ConnectionHandlers):
p = self.add_sha(p)
self.add_lang(p)
if not change_nick:
t = p.setTag(common.xmpp.NS_MUC + ' x')
t = p.setTag(nbxmpp.NS_MUC + ' x')
tags = {}
timeout = gajim.config.get_per('room', room_jid,
'muc_restore_timeout')
@ -2407,13 +2404,13 @@ class Connection(CommonConnection, ConnectionHandlers):
t.setTagData('password', password)
self.connection.send(p)
def send_gc_message(self, jid, msg, xhtml = None, label = None):
def send_gc_message(self, jid, msg, xhtml=None, label=None):
if not gajim.account_is_connected(self.name):
return
if not xhtml and gajim.config.get('rst_formatting_outgoing_messages'):
from common.rst_xhtml_generator import create_xhtml
xhtml = create_xhtml(msg)
msg_iq = common.xmpp.Message(jid, msg, typ = 'groupchat', xhtml = xhtml)
msg_iq = nbxmpp.Message(jid, msg, typ='groupchat', xhtml=xhtml)
if label is not None:
msg_iq.addChild(node = label)
self.connection.send(msg_iq)
@ -2423,22 +2420,22 @@ class Connection(CommonConnection, ConnectionHandlers):
def send_gc_subject(self, jid, subject):
if not gajim.account_is_connected(self.name):
return
msg_iq = common.xmpp.Message(jid, typ = 'groupchat', subject = subject)
msg_iq = nbxmpp.Message(jid, typ='groupchat', subject=subject)
self.connection.send(msg_iq)
def request_gc_config(self, room_jid):
if not gajim.account_is_connected(self.name):
return
iq = common.xmpp.Iq(typ = 'get', queryNS = common.xmpp.NS_MUC_OWNER,
to = room_jid)
iq = nbxmpp.Iq(typ='get', queryNS=nbxmpp.NS_MUC_OWNER,
to=room_jid)
self.add_lang(iq)
self.connection.send(iq)
def destroy_gc_room(self, room_jid, reason = '', jid = ''):
if not gajim.account_is_connected(self.name):
return
iq = common.xmpp.Iq(typ = 'set', queryNS = common.xmpp.NS_MUC_OWNER,
to = room_jid)
iq = nbxmpp.Iq(typ='set', queryNS=nbxmpp.NS_MUC_OWNER,
to=room_jid)
destroy = iq.setQuery().setTag('destroy')
if reason:
destroy.setTagData('reason', reason)
@ -2455,8 +2452,8 @@ class Connection(CommonConnection, ConnectionHandlers):
if show == 'offline':
ptype = 'unavailable'
xmpp_show = helpers.get_xmpp_show(show)
p = common.xmpp.Presence(to = '%s/%s' % (jid, nick), typ = ptype,
show = xmpp_show, status = status)
p = nbxmpp.Presence(to='%s/%s' % (jid, nick), typ=ptype,
show=xmpp_show, status=status)
h = hmac.new(self.secret_hmac, jid).hexdigest()[:6]
id_ = self.connection.getAnID()
id_ = 'gajim_muc_' + id_ + '_' + h
@ -2478,19 +2475,18 @@ class Connection(CommonConnection, ConnectionHandlers):
"""
gajim.logger.set_room_last_message_time(room_jid, self.last_history_time[room_jid])
def gc_set_role(self, room_jid, nick, role, reason = ''):
def gc_set_role(self, room_jid, nick, role, reason=''):
"""
Role is for all the life of the room so it's based on nick
"""
if not gajim.account_is_connected(self.name):
return
iq = common.xmpp.Iq(typ = 'set', to = room_jid, queryNS =\
common.xmpp.NS_MUC_ADMIN)
iq = nbxmpp.Iq(typ='set', to=room_jid, queryNS=nbxmpp.NS_MUC_ADMIN)
item = iq.setQuery().setTag('item')
item.setAttr('nick', nick)
item.setAttr('role', role)
if reason:
item.addChild(name = 'reason', payload = reason)
item.addChild(name='reason', payload=reason)
self.connection.send(iq)
def gc_set_affiliation(self, room_jid, jid, affiliation, reason = ''):
@ -2499,8 +2495,7 @@ class Connection(CommonConnection, ConnectionHandlers):
"""
if not gajim.account_is_connected(self.name):
return
iq = common.xmpp.Iq(typ = 'set', to = room_jid, queryNS =\
common.xmpp.NS_MUC_ADMIN)
iq = nbxmpp.Iq(typ='set', to=room_jid, queryNS=nbxmpp.NS_MUC_ADMIN)
item = iq.setQuery().setTag('item')
item.setAttr('jid', jid)
item.setAttr('affiliation', affiliation)
@ -2511,8 +2506,7 @@ class Connection(CommonConnection, ConnectionHandlers):
def send_gc_affiliation_list(self, room_jid, users_dict):
if not gajim.account_is_connected(self.name):
return
iq = common.xmpp.Iq(typ = 'set', to = room_jid, queryNS = \
common.xmpp.NS_MUC_ADMIN)
iq = nbxmpp.Iq(typ='set', to=room_jid, queryNS=nbxmpp.NS_MUC_ADMIN)
item = iq.setQuery()
for jid in users_dict:
item_tag = item.addChild('item', {'jid': jid,
@ -2524,8 +2518,7 @@ class Connection(CommonConnection, ConnectionHandlers):
def get_affiliation_list(self, room_jid, affiliation):
if not gajim.account_is_connected(self.name):
return
iq = common.xmpp.Iq(typ = 'get', to = room_jid, queryNS = \
common.xmpp.NS_MUC_ADMIN)
iq = nbxmpp.Iq(typ='get', to=room_jid, queryNS=nbxmpp.NS_MUC_ADMIN)
item = iq.setQuery().setTag('item')
item.setAttr('affiliation', affiliation)
self.connection.send(iq)
@ -2533,8 +2526,7 @@ class Connection(CommonConnection, ConnectionHandlers):
def send_gc_config(self, room_jid, form):
if not gajim.account_is_connected(self.name):
return
iq = common.xmpp.Iq(typ = 'set', to = room_jid, queryNS =\
common.xmpp.NS_MUC_OWNER)
iq = nbxmpp.Iq(typ='set', to=room_jid, queryNS=nbxmpp.NS_MUC_OWNER)
query = iq.setQuery()
form.setAttr('type', 'submit')
query.addChild(node = form)
@ -2545,8 +2537,8 @@ class Connection(CommonConnection, ConnectionHandlers):
return
hostname = gajim.config.get_per('accounts', self.name, 'hostname')
username = gajim.config.get_per('accounts', self.name, 'name')
iq = common.xmpp.Iq(typ = 'set', to = hostname)
q = iq.setTag(common.xmpp.NS_REGISTER + ' query')
iq = nbxmpp.Iq(typ='set', to=hostname)
q = iq.setTag(nbxmpp.NS_REGISTER + ' query')
q.setTagData('username', username)
q.setTagData('password', password)
self.connection.send(iq)
@ -2610,10 +2602,10 @@ class Connection(CommonConnection, ConnectionHandlers):
self.on_connect_auth = None
if gajim.account_is_connected(self.name):
hostname = gajim.config.get_per('accounts', self.name, 'hostname')
iq = common.xmpp.Iq(typ = 'set', to = hostname)
iq = nbxmpp.Iq(typ='set', to=hostname)
id_ = self.connection.getAnID()
iq.setID(id_)
iq.setTag(common.xmpp.NS_REGISTER + ' query').setTag('remove')
iq.setTag(nbxmpp.NS_REGISTER + ' query').setTag('remove')
def _on_answer(con, result):
if result.getID() == id_:
on_remove_success(True)
@ -2639,8 +2631,8 @@ class Connection(CommonConnection, ConnectionHandlers):
"""
Send invitation
"""
message=common.xmpp.Message(to=room)
c = message.addChild(name='x', namespace=common.xmpp.NS_MUC_USER)
message=nbxmpp.Message(to=room)
c = message.addChild(name='x', namespace=nbxmpp.NS_MUC_USER)
c = c.addChild(name='invite', attrs={'to': to})
if continue_tag:
c.addChild(name='continue')
@ -2652,8 +2644,8 @@ class Connection(CommonConnection, ConnectionHandlers):
"""
decline a groupchat invitation
"""
message=common.xmpp.Message(to=room)
c = message.addChild(name='x', namespace=common.xmpp.NS_MUC_USER)
message=nbxmpp.Message(to=room)
c = message.addChild(name='x', namespace=nbxmpp.NS_MUC_USER)
c = c.addChild(name='decline', attrs={'to': to})
if reason != '':
c.setTagData('reason', reason)
@ -2663,11 +2655,11 @@ class Connection(CommonConnection, ConnectionHandlers):
"""
Request voice in a moderated room
"""
message = common.xmpp.Message(to=room)
message = nbxmpp.Message(to=room)
x = xmpp.DataForm(typ='submit')
x.addChild(node=xmpp.DataField(name='FORM_TYPE',
value=common.xmpp.NS_MUC + '#request'))
value=nbxmpp.NS_MUC + '#request'))
x.addChild(node=xmpp.DataField(name='muc#role', value='participant',
typ='text-single'))
@ -2692,13 +2684,11 @@ class Connection(CommonConnection, ConnectionHandlers):
self.time_to_reconnect = None
def request_search_fields(self, jid):
iq = common.xmpp.Iq(typ = 'get', to = jid, queryNS = \
common.xmpp.NS_SEARCH)
iq = nbxmpp.Iq(typ='get', to=jid, queryNS=nbxmpp.NS_SEARCH)
self.connection.send(iq)
def send_search_form(self, jid, form, is_form):
iq = common.xmpp.Iq(typ = 'set', to = jid, queryNS = \
common.xmpp.NS_SEARCH)
iq = nbxmpp.Iq(typ='set', to=jid, queryNS=nbxmpp.NS_SEARCH)
item = iq.setQuery()
if is_form:
item.addChild(node=form)

View File

@ -38,7 +38,7 @@ from time import (altzone, daylight, gmtime, localtime, mktime, strftime,
time as time_time, timezone, tzname)
from calendar import timegm
import common.xmpp
import nbxmpp
import common.caps_cache as capscache
from common import helpers
@ -101,7 +101,7 @@ class ConnectionDisco:
jid is mandatory;
name, node, action is optional.
"""
self._discover(common.xmpp.NS_DISCO_ITEMS, jid, node, id_prefix)
self._discover(nbxmpp.NS_DISCO_ITEMS, jid, node, id_prefix)
def discoverInfo(self, jid, node=None, id_prefix=None):
"""
@ -109,12 +109,12 @@ class ConnectionDisco:
For identity: category, type is mandatory, name is optional.
For feature: var is mandatory.
"""
self._discover(common.xmpp.NS_DISCO_INFO, jid, node, id_prefix)
self._discover(nbxmpp.NS_DISCO_INFO, jid, node, id_prefix)
def request_register_agent_info(self, agent):
if not self.connection or self.connected < 2:
return None
iq = common.xmpp.Iq('get', common.xmpp.NS_REGISTER, to=agent)
iq = nbxmpp.Iq('get', nbxmpp.NS_REGISTER, to=agent)
id_ = self.connection.getAnID()
iq.setID(id_)
# Wait the answer during 30 secondes
@ -132,7 +132,7 @@ class ConnectionDisco:
self.request_subscription(agent, auto_auth=True)
self.agent_registrations[agent]['roster_push'] = True
if self.agent_registrations[agent]['sub_received']:
p = common.xmpp.Presence(agent, 'subscribed')
p = nbxmpp.Presence(agent, 'subscribed')
p = self.add_sha(p)
self.connection.send(p)
if resp.getType() == 'error':
@ -146,7 +146,7 @@ class ConnectionDisco:
if not self.connection or self.connected < 2:
return
if is_form:
iq = common.xmpp.Iq('set', common.xmpp.NS_REGISTER, to=agent)
iq = nbxmpp.Iq('set', nbxmpp.NS_REGISTER, to=agent)
query = iq.setQuery()
info.setAttr('type', 'submit')
query.addChild(node=info)
@ -154,7 +154,7 @@ class ConnectionDisco:
self._agent_registered_cb, {'agent': agent})
else:
# fixed: blocking
common.xmpp.features_nb.register(self.connection, agent, info,
nbxmpp.features_nb.register(self.connection, agent, info,
self._agent_registered_cb, {'agent': agent})
self.agent_registrations[agent] = {'roster_push': False,
'sub_received': False}
@ -162,7 +162,7 @@ class ConnectionDisco:
def _discover(self, ns, jid, node=None, id_prefix=None):
if not self.connection or self.connected < 2:
return
iq = common.xmpp.Iq(typ='get', to=jid, queryNS=ns)
iq = nbxmpp.Iq(typ='get', to=jid, queryNS=ns)
if id_prefix:
id_ = self.connection.getAnID()
iq.setID('%s%s' % (id_prefix, id_))
@ -171,7 +171,7 @@ class ConnectionDisco:
self.connection.send(iq)
def _ReceivedRegInfo(self, con, resp, agent):
common.xmpp.features_nb._ReceivedRegInfo(con, resp, agent)
nbxmpp.features_nb._ReceivedRegInfo(con, resp, agent)
self._IqCB(con, resp)
def _discoGetCB(self, con, iq_obj):
@ -183,23 +183,21 @@ class ConnectionDisco:
frm = helpers.get_full_jid_from_iq(iq_obj)
to = unicode(iq_obj.getAttr('to'))
id_ = unicode(iq_obj.getAttr('id'))
iq = common.xmpp.Iq(to=frm, typ='result', queryNS=common.xmpp.NS_DISCO,
frm=to)
iq = nbxmpp.Iq(to=frm, typ='result', queryNS=nbxmpp.NS_DISCO, frm=to)
iq.setAttr('id', id_)
query = iq.setTag('query')
query.setAttr('node', 'http://gajim.org#' + gajim.version.split('-', 1)[
0])
for f in (common.xmpp.NS_BYTESTREAM, common.xmpp.NS_SI,
common.xmpp.NS_FILE, common.xmpp.NS_COMMANDS,
common.xmpp.NS_JINGLE_FILE_TRANSFER, common.xmpp.NS_JINGLE_XTLS,
common.xmpp.NS_PUBKEY_PUBKEY, common.xmpp.NS_PUBKEY_REVOKE,
common.xmpp.NS_PUBKEY_ATTEST):
feature = common.xmpp.Node('feature')
for f in (nbxmpp.NS_BYTESTREAM, nbxmpp.NS_SI, nbxmpp.NS_FILE,
nbxmpp.NS_COMMANDS, nbxmpp.NS_JINGLE_FILE_TRANSFER,
nbxmpp.NS_JINGLE_XTLS, nbxmpp.NS_PUBKEY_PUBKEY, nbxmpp.NS_PUBKEY_REVOKE,
nbxmpp.NS_PUBKEY_ATTEST):
feature = nbxmpp.Node('feature')
feature.setAttr('var', f)
query.addChild(node=feature)
self.connection.send(iq)
raise common.xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
def _DiscoverItemsErrorCB(self, con, iq_obj):
log.debug('DiscoverItemsErrorCB')
@ -218,15 +216,15 @@ class ConnectionDisco:
return
if self.commandItemsQuery(con, iq_obj):
raise common.xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
node = iq_obj.getTagAttr('query', 'node')
if node is None:
result = iq_obj.buildReply('result')
self.connection.send(result)
raise common.xmpp.NodeProcessed
if node == common.xmpp.NS_COMMANDS:
raise nbxmpp.NodeProcessed
if node == nbxmpp.NS_COMMANDS:
self.commandListQuery(con, iq_obj)
raise common.xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
def _DiscoverInfoGetCB(self, con, iq_obj):
log.debug('DiscoverInfoGetCB')
@ -235,12 +233,12 @@ class ConnectionDisco:
node = iq_obj.getQuerynode()
if self.commandInfoQuery(con, iq_obj):
raise common.xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
id_ = unicode(iq_obj.getAttr('id'))
if id_[:6] == 'Gajim_':
# We get this request from echo.server
raise common.xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
iq = iq_obj.buildReply('result')
q = iq.setQuery()
@ -257,7 +255,7 @@ class ConnectionDisco:
if q.getChildren():
self.connection.send(iq)
raise common.xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
def _DiscoverInfoErrorCB(self, con, iq_obj):
log.debug('DiscoverInfoErrorCB')
@ -279,7 +277,7 @@ class ConnectionVcard:
self.room_jids = []
def add_sha(self, p, send_caps=True):
c = p.setTag('x', namespace=common.xmpp.NS_VCARD_UPDATE)
c = p.setTag('x', namespace=nbxmpp.NS_VCARD_UPDATE)
if self.vcard_sha is not None:
c.setTagData('photo', self.vcard_sha)
if send_caps:
@ -288,7 +286,7 @@ class ConnectionVcard:
def _add_caps(self, p):
''' advertise our capabilities in presence stanza (xep-0115)'''
c = p.setTag('c', namespace=common.xmpp.NS_CAPS)
c = p.setTag('c', namespace=nbxmpp.NS_CAPS)
c.setAttr('hash', 'sha-1')
c.setAttr('node', 'http://gajim.org')
c.setAttr('ver', gajim.caps_hash[self.name])
@ -357,7 +355,7 @@ class ConnectionVcard:
c = f.read()
f.close()
try:
card = common.xmpp.Node(node=c)
card = nbxmpp.Node(node=c)
except Exception:
# We are unable to parse it. Remove it
os.remove(path_to_file)
@ -386,10 +384,10 @@ class ConnectionVcard:
"""
if not self.connection or self.connected < 2:
return
iq = common.xmpp.Iq(typ='get')
iq = nbxmpp.Iq(typ='get')
if jid:
iq.setTo(jid)
iq.setQuery('vCard').setNamespace(common.xmpp.NS_VCARD)
iq.setQuery('vCard').setNamespace(nbxmpp.NS_VCARD)
id_ = self.connection.getAnID()
iq.setID(id_)
@ -407,8 +405,8 @@ class ConnectionVcard:
def send_vcard(self, vcard):
if not self.connection or self.connected < 2:
return
iq = common.xmpp.Iq(typ='set')
iq2 = iq.setTag(common.xmpp.NS_VCARD + ' vCard')
iq = nbxmpp.Iq(typ='set')
iq2 = iq.setTag(nbxmpp.NS_VCARD + ' vCard')
for i in vcard:
if i == 'jid':
continue
@ -481,7 +479,7 @@ class ConnectionVcard:
self.vcard_sha = new_sha
sshow = helpers.get_xmpp_show(gajim.SHOW_LIST[
self.connected])
p = common.xmpp.Presence(typ=None, priority=self.priority,
p = nbxmpp.Presence(typ=None, priority=self.priority,
show=sshow, status=self.status)
p = self.add_sha(p)
self.connection.send(p)
@ -587,7 +585,7 @@ class ConnectionVcard:
if not conf:
return
node = conf.getAttr('node')
form_tag = conf.getTag('x', namespace=common.xmpp.NS_DATA)
form_tag = conf.getTag('x', namespace=nbxmpp.NS_DATA)
if form_tag:
form = common.dataforms.ExtendForm(node=form_tag)
gajim.nec.push_incoming_event(PEPConfigReceivedEvent(None,
@ -664,7 +662,7 @@ class ConnectionVcard:
"""
if not vc.getTag('vCard'):
return
if not vc.getTag('vCard').getNamespace() == common.xmpp.NS_VCARD:
if not vc.getTag('vCard').getNamespace() == nbxmpp.NS_VCARD:
return
id_ = vc.getID()
frm_iq = vc.getFrom()
@ -745,7 +743,7 @@ class ConnectionVcard:
if not self.connection:
return
sshow = helpers.get_xmpp_show(gajim.SHOW_LIST[self.connected])
p = common.xmpp.Presence(typ=None, priority=self.priority,
p = nbxmpp.Presence(typ=None, priority=self.priority,
show=sshow, status=self.status)
p = self.add_sha(p)
self.connection.send(p)
@ -1020,7 +1018,7 @@ class ConnectionHandlersBase:
if obj.receipt_request_tag and gajim.config.get_per('accounts',
self.name, 'answer_receipts') and ((contact and contact.sub \
not in (u'to', u'none')) or gc_contact) and obj.mtype != 'error':
receipt = common.xmpp.Message(to=obj.fjid, typ='chat')
receipt = nbxmpp.Message(to=obj.fjid, typ='chat')
receipt.setID(obj.id_)
receipt.setTag('received', namespace='urn:xmpp:receipts',
attrs={'id': obj.id_})
@ -1205,7 +1203,7 @@ class ConnectionHandlersBase:
if not cls:
cls = gajim.default_session_type
sess = cls(self, common.xmpp.JID(jid), thread_id, type_)
sess = cls(self, nbxmpp.JID(jid), thread_id, type_)
# determine if this session is a pm session
# if not, discard the resource so that all sessions are stored bare
@ -1370,8 +1368,7 @@ ConnectionJingle, ConnectionIBBytestream):
reply.addChild(node=confirm)
self.connection.send(reply)
elif answer == 'no':
err = common.xmpp.Error(iq_obj,
common.xmpp.protocol.ERR_NOT_AUTHORIZED)
err = nbxmpp.Error(iq_obj, nbxmpp.protocol.ERR_NOT_AUTHORIZED)
self.connection.send(err)
def _nec_http_auth_received(self, obj):
@ -1385,7 +1382,7 @@ ConnectionJingle, ConnectionIBBytestream):
log.debug('HttpAuthCB')
gajim.nec.push_incoming_event(HttpAuthReceivedEvent(None, conn=self,
stanza=iq_obj))
raise common.xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
def _ErrorCB(self, con, iq_obj):
log.debug('ErrorCB')
@ -1466,7 +1463,7 @@ ConnectionJingle, ConnectionIBBytestream):
log.debug('rosterSetCB')
gajim.nec.push_incoming_event(RosterSetReceivedEvent(None, conn=self,
stanza=iq_obj))
raise common.xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
def _nec_roster_set_received(self, obj):
if obj.conn.name != self.name:
@ -1489,7 +1486,7 @@ ConnectionJingle, ConnectionIBBytestream):
return
gajim.nec.push_incoming_event(VersionRequestEvent(None, conn=self,
stanza=iq_obj))
raise common.xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
def _nec_version_request_received(self, obj):
if obj.conn.name != self.name:
@ -1503,7 +1500,7 @@ ConnectionJingle, ConnectionIBBytestream):
qp.setTagData('os', helpers.get_os_info())
else:
iq_obj = obj.stanza.buildReply('error')
err = common.xmpp.ErrorNode(name=common.xmpp.NS_STANZAS + \
err = nbxmpp.ErrorNode(name=nbxmpp.NS_STANZAS + \
' service-unavailable')
iq_obj.addChild(node=err)
self.connection.send(iq_obj)
@ -1514,7 +1511,7 @@ ConnectionJingle, ConnectionIBBytestream):
return
gajim.nec.push_incoming_event(LastRequestEvent(None, conn=self,
stanza=iq_obj))
raise common.xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
def _nec_last_request_received(self, obj):
global HAS_IDLE
@ -1527,7 +1524,7 @@ ConnectionJingle, ConnectionIBBytestream):
qp.attrs['seconds'] = int(self.sleeper.getIdleSec())
else:
iq_obj = obj.stanza.buildReply('error')
err = common.xmpp.ErrorNode(name=common.xmpp.NS_STANZAS + \
err = nbxmpp.ErrorNode(name=nbxmpp.NS_STANZAS + \
' service-unavailable')
iq_obj.addChild(node=err)
self.connection.send(iq_obj)
@ -1543,7 +1540,7 @@ ConnectionJingle, ConnectionIBBytestream):
return
gajim.nec.push_incoming_event(TimeRequestEvent(None, conn=self,
stanza=iq_obj))
raise common.xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
def _nec_time_request_received(self, obj):
if obj.conn.name != self.name:
@ -1557,7 +1554,7 @@ ConnectionJingle, ConnectionIBBytestream):
localtime())))
else:
iq_obj = obj.stanza.buildReply('error')
err = common.xmpp.ErrorNode(name=common.xmpp.NS_STANZAS + \
err = nbxmpp.ErrorNode(name=nbxmpp.NS_STANZAS + \
' service-unavailable')
iq_obj.addChild(node=err)
self.connection.send(iq_obj)
@ -1568,14 +1565,14 @@ ConnectionJingle, ConnectionIBBytestream):
return
gajim.nec.push_incoming_event(TimeRevisedRequestEvent(None, conn=self,
stanza=iq_obj))
raise common.xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
def _nec_time_revised_request_received(self, obj):
if obj.conn.name != self.name:
return
if gajim.config.get_per('accounts', self.name, 'send_time_info'):
iq_obj = obj.stanza.buildReply('result')
qp = iq_obj.setTag('time', namespace=common.xmpp.NS_TIME_REVISED)
qp = iq_obj.setTag('time', namespace=nbxmpp.NS_TIME_REVISED)
qp.setTagData('utc', strftime('%Y-%m-%dT%H:%M:%SZ', gmtime()))
isdst = localtime().tm_isdst
zone = -(timezone, altzone)[isdst] / 60.0
@ -1583,7 +1580,7 @@ ConnectionJingle, ConnectionIBBytestream):
qp.setTagData('tzo', '%+03d:%02d' % (tzo))
else:
iq_obj = obj.stanza.buildReply('error')
err = common.xmpp.ErrorNode(name=common.xmpp.NS_STANZAS + \
err = nbxmpp.ErrorNode(name=nbxmpp.NS_STANZAS + \
' service-unavailable')
iq_obj.addChild(node=err)
self.connection.send(iq_obj)
@ -1600,7 +1597,7 @@ ConnectionJingle, ConnectionIBBytestream):
log.debug('gMailNewMailCB')
gajim.nec.push_incoming_event(GmailNewMailReceivedEvent(None, conn=self,
stanza=iq_obj))
raise common.xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
def _nec_gmail_new_mail_received(self, obj):
if obj.conn.name != self.name:
@ -1611,9 +1608,9 @@ ConnectionJingle, ConnectionIBBytestream):
jid = gajim.get_jid_from_account(self.name)
log.debug('Got notification of new gmail e-mail on %s. Asking the '
'server for more info.' % jid)
iq = common.xmpp.Iq(typ='get')
iq = nbxmpp.Iq(typ='get')
query = iq.setTag('query')
query.setNamespace(common.xmpp.NS_GMAILNOTIFY)
query.setNamespace(nbxmpp.NS_GMAILNOTIFY)
# we want only be notified about newer mails
if self.gmail_last_tid:
query.setAttr('newer-than-tid', self.gmail_last_tid)
@ -1629,7 +1626,7 @@ ConnectionJingle, ConnectionIBBytestream):
log.debug('gMailQueryCB')
gajim.nec.push_incoming_event(GMailQueryReceivedEvent(None, conn=self,
stanza=iq_obj))
raise common.xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
def _rosterItemExchangeCB(self, con, msg):
"""
@ -1638,7 +1635,7 @@ ConnectionJingle, ConnectionIBBytestream):
log.debug('rosterItemExchangeCB')
gajim.nec.push_incoming_event(RosterItemExchangeEvent(None, conn=self,
stanza=msg))
raise common.xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
def _messageCB(self, con, msg):
"""
@ -1662,7 +1659,7 @@ ConnectionJingle, ConnectionIBBytestream):
return
if result.getType() == 'result':
data = msg.getTags('data', namespace=common.xmpp.NS_BOB)
data = msg.getTags('data', namespace=nbxmpp.NS_BOB)
if data.getAttr('cid') == cid:
for func in self.awaiting_cids[cid]:
cb = func[0]
@ -1697,9 +1694,9 @@ ConnectionJingle, ConnectionIBBytestream):
self.awaiting_cids[cid].appends((callback, args, position))
else:
self.awaiting_cids[cid] = [(callback, args, position)]
iq = common.xmpp.Iq(to=to, typ='get')
iq = nbxmpp.Iq(to=to, typ='get')
data = iq.addChild(name='data', attrs={'cid': cid},
namespace=common.xmpp.NS_BOB)
namespace=nbxmpp.NS_BOB)
self.connection.SendAndCallForResponse(iq, self._on_bob_received,
{'cid': cid})
@ -1828,7 +1825,7 @@ ConnectionJingle, ConnectionIBBytestream):
log.debug('IqPingCB')
gajim.nec.push_incoming_event(PingReceivedEvent(None, conn=self,
stanza=iq_obj))
raise common.xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
def _nec_ping_received(self, obj):
if obj.conn.name != self.name:
@ -1852,7 +1849,7 @@ ConnectionJingle, ConnectionIBBytestream):
if q:
result.delChild(q)
self.connection.send(result)
raise common.xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
def _getRoster(self):
log.debug('getRosterCB')
@ -1947,12 +1944,12 @@ ConnectionJingle, ConnectionIBBytestream):
vcard = self.get_cached_vcard(our_jid)
if vcard and 'PHOTO' in vcard and 'SHA' in vcard['PHOTO']:
self.vcard_sha = vcard['PHOTO']['SHA']
p = common.xmpp.Presence(typ=None, priority=priority, show=sshow)
p = nbxmpp.Presence(typ=None, priority=priority, show=sshow)
p = self.add_sha(p)
if msg:
p.setStatus(msg)
if signed:
p.setTag(common.xmpp.NS_SIGNED + ' x').setData(signed)
p.setTag(nbxmpp.NS_SIGNED + ' x').setData(signed)
if self.connection:
self.connection.send(p)
@ -1982,18 +1979,18 @@ ConnectionJingle, ConnectionIBBytestream):
our_jid = helpers.parse_jid(gajim.get_jid_from_account(self.name))
log.debug(('%s is a gmail account. Setting option '
'to get e-mail notifications on the server.') % (our_jid))
iq = common.xmpp.Iq(typ='set', to=our_jid)
iq = nbxmpp.Iq(typ='set', to=our_jid)
iq.setAttr('id', 'MailNotify')
query = iq.setTag('usersetting')
query.setNamespace(common.xmpp.NS_GTALKSETTING)
query.setNamespace(nbxmpp.NS_GTALKSETTING)
query = query.setTag('mailnotifications')
query.setAttr('value', 'true')
self.connection.send(iq)
# Ask how many messages there are now
iq = common.xmpp.Iq(typ='get')
iq = nbxmpp.Iq(typ='get')
iq.setID(self.connection.getAnID())
query = iq.setTag('query')
query.setNamespace(common.xmpp.NS_GMAILNOTIFY)
query.setNamespace(nbxmpp.NS_GMAILNOTIFY)
self.connection.send(iq)
def _SearchCB(self, con, iq_obj):
@ -2003,11 +2000,11 @@ ConnectionJingle, ConnectionIBBytestream):
def _search_fields_received(self, con, iq_obj):
jid = jid = helpers.get_jid_from_iq(iq_obj)
tag = iq_obj.getTag('query', namespace = common.xmpp.NS_SEARCH)
tag = iq_obj.getTag('query', namespace = nbxmpp.NS_SEARCH)
if not tag:
self.dispatch('SEARCH_FORM', (jid, None, False))
return
df = tag.getTag('x', namespace = common.xmpp.NS_DATA)
df = tag.getTag('x', namespace=nbxmpp.NS_DATA)
if df:
self.dispatch('SEARCH_FORM', (jid, df, True))
return
@ -2021,7 +2018,7 @@ ConnectionJingle, ConnectionIBBytestream):
jid_from = helpers.get_full_jid_from_iq(iq_obj)
sid = iq_obj.getAttr('id')
jingle_xtls.send_cert(con, jid_from, sid)
raise common.xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
def _PubkeyResultCB(self, con, iq_obj):
log.info('PubkeyResultCB')
@ -2048,76 +2045,68 @@ ConnectionJingle, ConnectionIBBytestream):
# We also don't check for namespace, else it cannot stop _messageCB to
# be called
con.RegisterHandler('message', self._pubsubEventCB, makefirst=True)
con.RegisterHandler('iq', self._vCardCB, 'result', common.xmpp.NS_VCARD)
con.RegisterHandler('iq', self._rosterSetCB, 'set',
common.xmpp.NS_ROSTER)
con.RegisterHandler('iq', self._siSetCB, 'set', common.xmpp.NS_SI)
con.RegisterHandler('iq', self._vCardCB, 'result', nbxmpp.NS_VCARD)
con.RegisterHandler('iq', self._rosterSetCB, 'set', nbxmpp.NS_ROSTER)
con.RegisterHandler('iq', self._siSetCB, 'set', nbxmpp.NS_SI)
con.RegisterHandler('iq', self._rosterItemExchangeCB, 'set',
common.xmpp.NS_ROSTERX)
con.RegisterHandler('iq', self._siErrorCB, 'error', common.xmpp.NS_SI)
con.RegisterHandler('iq', self._siResultCB, 'result', common.xmpp.NS_SI)
con.RegisterHandler('iq', self._discoGetCB, 'get', common.xmpp.NS_DISCO)
nbxmpp.NS_ROSTERX)
con.RegisterHandler('iq', self._siErrorCB, 'error', nbxmpp.NS_SI)
con.RegisterHandler('iq', self._siResultCB, 'result', nbxmpp.NS_SI)
con.RegisterHandler('iq', self._discoGetCB, 'get', nbxmpp.NS_DISCO)
con.RegisterHandler('iq', self._bytestreamSetCB, 'set',
common.xmpp.NS_BYTESTREAM)
nbxmpp.NS_BYTESTREAM)
con.RegisterHandler('iq', self._bytestreamResultCB, 'result',
common.xmpp.NS_BYTESTREAM)
nbxmpp.NS_BYTESTREAM)
con.RegisterHandler('iq', self._bytestreamErrorCB, 'error',
common.xmpp.NS_BYTESTREAM)
nbxmpp.NS_BYTESTREAM)
con.RegisterHandlerOnce('iq', self.IBBAllIqHandler)
con.RegisterHandler('iq', self.IBBIqHandler, ns=common.xmpp.NS_IBB)
con.RegisterHandler('message', self.IBBMessageHandler,
ns=common.xmpp.NS_IBB)
con.RegisterHandler('iq', self.IBBIqHandler, ns=nbxmpp.NS_IBB)
con.RegisterHandler('message', self.IBBMessageHandler, ns=nbxmpp.NS_IBB)
con.RegisterHandler('iq', self._DiscoverItemsCB, 'result',
common.xmpp.NS_DISCO_ITEMS)
nbxmpp.NS_DISCO_ITEMS)
con.RegisterHandler('iq', self._DiscoverItemsErrorCB, 'error',
common.xmpp.NS_DISCO_ITEMS)
nbxmpp.NS_DISCO_ITEMS)
con.RegisterHandler('iq', self._DiscoverInfoCB, 'result',
common.xmpp.NS_DISCO_INFO)
nbxmpp.NS_DISCO_INFO)
con.RegisterHandler('iq', self._DiscoverInfoErrorCB, 'error',
common.xmpp.NS_DISCO_INFO)
con.RegisterHandler('iq', self._VersionCB, 'get',
common.xmpp.NS_VERSION)
con.RegisterHandler('iq', self._TimeCB, 'get', common.xmpp.NS_TIME)
nbxmpp.NS_DISCO_INFO)
con.RegisterHandler('iq', self._VersionCB, 'get', nbxmpp.NS_VERSION)
con.RegisterHandler('iq', self._TimeCB, 'get', nbxmpp.NS_TIME)
con.RegisterHandler('iq', self._TimeRevisedCB, 'get',
common.xmpp.NS_TIME_REVISED)
con.RegisterHandler('iq', self._LastCB, 'get', common.xmpp.NS_LAST)
con.RegisterHandler('iq', self._LastResultCB, 'result',
common.xmpp.NS_LAST)
nbxmpp.NS_TIME_REVISED)
con.RegisterHandler('iq', self._LastCB, 'get', nbxmpp.NS_LAST)
con.RegisterHandler('iq', self._LastResultCB, 'result', nbxmpp.NS_LAST)
con.RegisterHandler('iq', self._VersionResultCB, 'result',
common.xmpp.NS_VERSION)
nbxmpp.NS_VERSION)
con.RegisterHandler('iq', self._TimeRevisedResultCB, 'result',
common.xmpp.NS_TIME_REVISED)
nbxmpp.NS_TIME_REVISED)
con.RegisterHandler('iq', self._MucOwnerCB, 'result',
common.xmpp.NS_MUC_OWNER)
nbxmpp.NS_MUC_OWNER)
con.RegisterHandler('iq', self._MucAdminCB, 'result',
common.xmpp.NS_MUC_ADMIN)
con.RegisterHandler('iq', self._PrivateCB, 'result',
common.xmpp.NS_PRIVATE)
nbxmpp.NS_MUC_ADMIN)
con.RegisterHandler('iq', self._PrivateCB, 'result', nbxmpp.NS_PRIVATE)
con.RegisterHandler('iq', self._SecLabelCB, 'result',
common.xmpp.NS_SECLABEL_CATALOG)
con.RegisterHandler('iq', self._HttpAuthCB, 'get',
common.xmpp.NS_HTTP_AUTH)
nbxmpp.NS_SECLABEL_CATALOG)
con.RegisterHandler('iq', self._HttpAuthCB, 'get', nbxmpp.NS_HTTP_AUTH)
con.RegisterHandler('iq', self._CommandExecuteCB, 'set',
common.xmpp.NS_COMMANDS)
nbxmpp.NS_COMMANDS)
con.RegisterHandler('iq', self._gMailNewMailCB, 'set',
common.xmpp.NS_GMAILNOTIFY)
nbxmpp.NS_GMAILNOTIFY)
con.RegisterHandler('iq', self._gMailQueryCB, 'result',
common.xmpp.NS_GMAILNOTIFY)
nbxmpp.NS_GMAILNOTIFY)
con.RegisterHandler('iq', self._DiscoverInfoGetCB, 'get',
common.xmpp.NS_DISCO_INFO)
nbxmpp.NS_DISCO_INFO)
con.RegisterHandler('iq', self._DiscoverItemsGetCB, 'get',
common.xmpp.NS_DISCO_ITEMS)
con.RegisterHandler('iq', self._IqPingCB, 'get', common.xmpp.NS_PING)
con.RegisterHandler('iq', self._SearchCB, 'result',
common.xmpp.NS_SEARCH)
con.RegisterHandler('iq', self._PrivacySetCB, 'set',
common.xmpp.NS_PRIVACY)
con.RegisterHandler('iq', self._ArchiveCB, ns=common.xmpp.NS_ARCHIVE)
nbxmpp.NS_DISCO_ITEMS)
con.RegisterHandler('iq', self._IqPingCB, 'get', nbxmpp.NS_PING)
con.RegisterHandler('iq', self._SearchCB, 'result', nbxmpp.NS_SEARCH)
con.RegisterHandler('iq', self._PrivacySetCB, 'set', nbxmpp.NS_PRIVACY)
con.RegisterHandler('iq', self._ArchiveCB, ns=nbxmpp.NS_ARCHIVE)
con.RegisterHandler('iq', self._PubSubCB, 'result')
con.RegisterHandler('iq', self._PubSubErrorCB, 'error')
con.RegisterHandler('iq', self._JingleCB, 'result')
con.RegisterHandler('iq', self._JingleCB, 'error')
con.RegisterHandler('iq', self._JingleCB, 'set', common.xmpp.NS_JINGLE)
con.RegisterHandler('iq', self._JingleCB, 'set', nbxmpp.NS_JINGLE)
con.RegisterHandler('iq', self._ErrorCB, 'error')
con.RegisterHandler('iq', self._IqCB)
con.RegisterHandler('iq', self._StanzaArrivedCB)
@ -2125,8 +2114,8 @@ ConnectionJingle, ConnectionIBBytestream):
con.RegisterHandler('presence', self._StanzaArrivedCB)
con.RegisterHandler('message', self._StanzaArrivedCB)
con.RegisterHandler('unknown', self._StreamCB,
common.xmpp.NS_XMPP_STREAMS, xmlns=common.xmpp.NS_STREAMS)
nbxmpp.NS_XMPP_STREAMS, xmlns=nbxmpp.NS_STREAMS)
con.RegisterHandler('iq', self._PubkeyGetCB, 'get',
common.xmpp.NS_PUBKEY_PUBKEY)
nbxmpp.NS_PUBKEY_PUBKEY)
con.RegisterHandler('iq', self._PubkeyResultCB, 'result',
common.xmpp.NS_PUBKEY_PUBKEY)
nbxmpp.NS_PUBKEY_PUBKEY)

View File

@ -29,13 +29,13 @@ from common import atom
from common import nec
from common import helpers
from common import gajim
from common import xmpp
import nbxmpp
from common import dataforms
from common import exceptions
from common.zeroconf import zeroconf
from common.logger import LOG_DB_PATH
from common.pep import SUPPORTED_PERSONAL_USER_EVENTS
from common.xmpp.protocol import NS_CHATSTATES
from nbxmpp.protocol import NS_CHATSTATES
from common.jingle_transport import JingleTransportSocks5
from common.file_props import FilesProp
@ -102,7 +102,7 @@ class HelperEvent:
self.chatstate = None
# chatstates - look for chatstate tags in a message if not delayed
delayed = self.stanza.getTag('x', namespace=xmpp.NS_DELAY) is not None
delayed = self.stanza.getTag('x', namespace=nbxmpp.NS_DELAY) is not None
if not delayed:
children = self.stanza.getChildren()
for child in children:
@ -243,7 +243,7 @@ class GMailQueryReceivedEvent(nec.NetworkIncomingEvent):
if not mb.getAttr('url'):
return
self.conn.gmail_url = mb.getAttr('url')
if mb.getNamespace() != xmpp.NS_GMAILNOTIFY:
if mb.getNamespace() != nbxmpp.NS_GMAILNOTIFY:
return
self.newmsgs = mb.getAttr('total-matched')
if not self.newmsgs:
@ -303,7 +303,7 @@ class RosterItemExchangeEvent(nec.NetworkIncomingEvent, HelperEvent):
self.action = items_list[0].getAttr('action')
if self.action is None:
self.action = 'add'
for item in self.stanza.getTag('x', namespace=xmpp.NS_ROSTERX).\
for item in self.stanza.getTag('x', namespace=nbxmpp.NS_ROSTERX).\
getChildren():
try:
jid = helpers.parse_jid(item.getAttr('jid'))
@ -412,7 +412,7 @@ class RosterSetReceivedEvent(nec.NetworkIncomingEvent):
self.items[jid] = {'name': name, 'sub': sub, 'ask': ask,
'groups': groups}
if self.conn.connection and self.conn.connected > 1:
reply = xmpp.Iq(typ='result', attrs={'id': self.stanza.getID()},
reply = nbxmpp.Iq(typ='result', attrs={'id': self.stanza.getID()},
to=self.stanza.getFrom(), frm=self.stanza.getTo(), xmlns=None)
self.conn.connection.send(reply)
return True
@ -430,7 +430,7 @@ class MucOwnerReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
qp = self.stanza.getQueryPayload()
self.form_node = None
for q in qp:
if q.getNamespace() == xmpp.NS_DATA:
if q.getNamespace() == nbxmpp.NS_DATA:
self.form_node = q
self.dataform = dataforms.ExtendForm(node=self.form_node)
return True
@ -442,7 +442,7 @@ class MucAdminReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
def generate(self):
self.get_jid_resource()
items = self.stanza.getTag('query',
namespace=xmpp.NS_MUC_ADMIN).getTags('item')
namespace=nbxmpp.NS_MUC_ADMIN).getTags('item')
self.users_dict = {}
for item in items:
if item.has_attr('jid') and item.has_attr('affiliation'):
@ -514,7 +514,7 @@ BookmarksHelper):
def generate(self):
self.conn = self.base_event.conn
self.storage_node = self.base_event.storage_node
if self.base_event.namespace != xmpp.NS_BOOKMARKS:
if self.base_event.namespace != nbxmpp.NS_BOOKMARKS:
return
self.parse_bookmarks()
return True
@ -535,7 +535,7 @@ class PrivateStorageRosternotesReceivedEvent(nec.NetworkIncomingEvent):
def generate(self):
self.conn = self.base_event.conn
if self.base_event.namespace != xmpp.NS_ROSTERNOTES:
if self.base_event.namespace != nbxmpp.NS_ROSTERNOTES:
return
notes = self.base_event.storage_node.getTags('note')
self.annotations = {}
@ -587,7 +587,7 @@ class PubsubBookmarksReceivedEvent(nec.NetworkIncomingEvent, BookmarksHelper):
self.conn = self.base_event.conn
self.storage_node = self.base_event.node
ns = self.storage_node.getNamespace()
if ns != xmpp.NS_BOOKMARKS:
if ns != nbxmpp.NS_BOOKMARKS:
return
self.parse_bookmarks()
return True
@ -600,10 +600,10 @@ class SearchFormReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
self.get_jid_resource()
self.data = None
self.is_dataform = False
tag = self.stanza.getTag('query', namespace=xmpp.NS_SEARCH)
tag = self.stanza.getTag('query', namespace=nbxmpp.NS_SEARCH)
if not tag:
return True
self.data = tag.getTag('x', namespace=xmpp.NS_DATA)
self.data = tag.getTag('x', namespace=nbxmpp.NS_DATA)
if self.data:
self.is_dataform = True
return True
@ -621,10 +621,10 @@ class SearchResultReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
self.get_jid_resource()
self.data = None
self.is_dataform = False
tag = self.stanza.getTag('query', namespace=xmpp.NS_SEARCH)
tag = self.stanza.getTag('query', namespace=nbxmpp.NS_SEARCH)
if not tag:
return True
self.data = tag.getTag('x', namespace=xmpp.NS_DATA)
self.data = tag.getTag('x', namespace=nbxmpp.NS_DATA)
if self.data:
self.is_dataform = True
return True
@ -655,7 +655,8 @@ class GmailNewMailReceivedEvent(nec.NetworkIncomingEvent):
def generate(self):
if not self.stanza.getTag('new-mail'):
return
if self.stanza.getTag('new-mail').getNamespace() != xmpp.NS_GMAILNOTIFY:
if self.stanza.getTag('new-mail').getNamespace() != \
nbxmpp.NS_GMAILNOTIFY:
return
return True
@ -769,20 +770,20 @@ PresenceHelperEvent):
self.contact_nickname = None
self.transport_auto_auth = False
# XEP-0203
delay_tag = self.stanza.getTag('delay', namespace=xmpp.NS_DELAY2)
delay_tag = self.stanza.getTag('delay', namespace=nbxmpp.NS_DELAY2)
if delay_tag:
self._generate_timestamp(self.stanza.getTimestamp2())
xtags = self.stanza.getTags('x')
for x in xtags:
namespace = x.getNamespace()
if namespace.startswith(xmpp.NS_MUC):
if namespace.startswith(nbxmpp.NS_MUC):
self.is_gc = True
elif namespace == xmpp.NS_SIGNED:
elif namespace == nbxmpp.NS_SIGNED:
sig_tag = x
elif namespace == xmpp.NS_VCARD_UPDATE:
elif namespace == nbxmpp.NS_VCARD_UPDATE:
self.avatar_sha = x.getTagData('photo')
self.contact_nickname = x.getTagData('nickname')
elif namespace == xmpp.NS_DELAY and not self.timestamp:
elif namespace == nbxmpp.NS_DELAY and not self.timestamp:
# XEP-0091
self._generate_timestamp(self.stanza.getTimestamp())
elif namespace == 'http://delx.cjb.net/protocol/roster-subsync':
@ -922,7 +923,7 @@ class GcPresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
# NOTE: if it's a gc presence, don't ask vcard here.
# We may ask it to real jid in gui part.
self.status_code = []
ns_muc_user_x = self.stanza.getTag('x', namespace=xmpp.NS_MUC_USER)
ns_muc_user_x = self.stanza.getTag('x', namespace=nbxmpp.NS_MUC_USER)
if ns_muc_user_x:
destroy = ns_muc_user_x.getTag('destroy')
else:
@ -1007,13 +1008,13 @@ class MessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
account = self.conn.name
# check if the message is a roster item exchange (XEP-0144)
if self.stanza.getTag('x', namespace=xmpp.NS_ROSTERX):
if self.stanza.getTag('x', namespace=nbxmpp.NS_ROSTERX):
gajim.nec.push_incoming_event(RosterItemExchangeEvent(None,
conn=self.conn, stanza=self.stanza))
return
# check if the message is a XEP-0070 confirmation request
if self.stanza.getTag('confirm', namespace=xmpp.NS_HTTP_AUTH):
if self.stanza.getTag('confirm', namespace=nbxmpp.NS_HTTP_AUTH):
gajim.nec.push_incoming_event(HttpAuthReceivedEvent(None,
conn=self.conn, stanza=self.stanza))
return
@ -1027,7 +1028,8 @@ class MessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
'ignored.')))
return
address_tag = self.stanza.getTag('addresses', namespace=xmpp.NS_ADDRESS)
address_tag = self.stanza.getTag('addresses',
namespace=nbxmpp.NS_ADDRESS)
# Be sure it comes from one of our resource, else ignore address element
if address_tag and self.jid == gajim.get_jid_from_account(account):
address = address_tag.getTag('address', attrs={'type': 'ofrom'})
@ -1040,15 +1042,17 @@ class MessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
return
self.jid = gajim.get_jid_without_resource(self.fjid)
carbon_marker = self.stanza.getTag('sent', namespace=xmpp.NS_CARBONS)
carbon_marker = self.stanza.getTag('sent', namespace=nbxmpp.NS_CARBONS)
if not carbon_marker:
carbon_marker = self.stanza.getTag('received', namespace=xmpp.NS_CARBONS)
carbon_marker = self.stanza.getTag('received',
namespace=nbxmpp.NS_CARBONS)
# Be sure it comes from one of our resource, else ignore forward element
if carbon_marker and self.jid == gajim.get_jid_from_account(account):
forward_tag = self.stanza.getTag('forwarded', namespace=xmpp.NS_FORWARD)
forward_tag = self.stanza.getTag('forwarded',
namespace=nbxmpp.NS_FORWARD)
if forward_tag:
msg = forward_tag.getTag('message')
self.stanza = xmpp.Message(node=msg)
self.stanza = nbxmpp.Message(node=msg)
if carbon_marker.getName() == 'sent':
to = self.stanza.getTo()
self.stanza.setTo(self.stanza.getFrom())
@ -1065,18 +1069,18 @@ class MessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
return
self.forwarded = True
self.enc_tag = self.stanza.getTag('x', namespace=xmpp.NS_ENCRYPTED)
self.enc_tag = self.stanza.getTag('x', namespace=nbxmpp.NS_ENCRYPTED)
self.invite_tag = None
self.decline_tag = None
if not self.enc_tag:
self.invite_tag = self.stanza.getTag('x',
namespace=xmpp.NS_MUC_USER)
namespace=nbxmpp.NS_MUC_USER)
if self.invite_tag and not self.invite_tag.getTag('invite'):
self.invite_tag = None
self.decline_tag = self.stanza.getTag('x',
namespace=xmpp.NS_MUC_USER)
namespace=nbxmpp.NS_MUC_USER)
if self.decline_tag and not self.decline_tag.getTag('decline'):
self.decline_tag = None
@ -1111,11 +1115,11 @@ class MessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
# check if the message is a XEP-0020 feature negotiation request
if not self.forwarded and self.stanza.getTag('feature',
namespace=xmpp.NS_FEATURE):
namespace=nbxmpp.NS_FEATURE):
if gajim.HAVE_PYCRYPTO:
feature = self.stanza.getTag(name='feature',
namespace=xmpp.NS_FEATURE)
form = xmpp.DataForm(node=feature.getTag('x'))
namespace=nbxmpp.NS_FEATURE)
form = nbxmpp.DataForm(node=feature.getTag('x'))
if form['FORM_TYPE'] == 'urn:xmpp:ssn':
self.session.handle_negotiation(form)
@ -1123,16 +1127,16 @@ class MessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
reply = self.stanza.buildReply()
reply.setType('error')
reply.addChild(feature)
err = xmpp.ErrorNode('service-unavailable', typ='cancel')
err = nbxmpp.ErrorNode('service-unavailable', typ='cancel')
reply.addChild(node=err)
self.conn.connection.send(reply)
return
if not self.forwarded and self.stanza.getTag('init',
namespace=xmpp.NS_ESESSION_INIT):
namespace=nbxmpp.NS_ESESSION_INIT):
init = self.stanza.getTag(name='init',
namespace=xmpp.NS_ESESSION_INIT)
form = xmpp.DataForm(node=init.getTag('x'))
namespace=nbxmpp.NS_ESESSION_INIT)
form = nbxmpp.DataForm(node=init.getTag('x'))
self.session.handle_negotiation(form)
@ -1142,7 +1146,7 @@ class MessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
self.encrypted = False
xep_200_encrypted = self.stanza.getTag('c',
namespace=xmpp.NS_STANZA_CRYPTO)
namespace=nbxmpp.NS_STANZA_CRYPTO)
if xep_200_encrypted:
if self.forwarded:
# Ignore E2E forwarded encrypted messages
@ -1248,22 +1252,22 @@ class DecryptedMessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
self.attention = False # XEP-0224
self.receipt_request_tag = self.stanza.getTag('request',
namespace=xmpp.NS_RECEIPTS)
namespace=nbxmpp.NS_RECEIPTS)
self.receipt_received_tag = self.stanza.getTag('received',
namespace=xmpp.NS_RECEIPTS)
namespace=nbxmpp.NS_RECEIPTS)
self.subject = self.stanza.getSubject()
self.displaymarking = None
self.seclabel = self.stanza.getTag('securitylabel',
namespace=xmpp.NS_SECLABEL)
namespace=nbxmpp.NS_SECLABEL)
if self.seclabel:
self.displaymarking = self.seclabel.getTag('displaymarking')
if self.stanza.getTag('attention', namespace=xmpp.NS_ATTENTION):
if self.stanza.getTag('attention', namespace=nbxmpp.NS_ATTENTION):
self.attention = True
self.form_node = self.stanza.getTag('x', namespace=xmpp.NS_DATA)
self.form_node = self.stanza.getTag('x', namespace=nbxmpp.NS_DATA)
if gajim.config.get('ignore_incoming_xhtml'):
self.xhtml = None
@ -1343,7 +1347,7 @@ class GcMessageReceivedEvent(nec.NetworkIncomingEvent):
self.displaymarking = None
seclabel = self.stanza.getTag('securitylabel')
if seclabel and seclabel.getNamespace() == xmpp.NS_SECLABEL:
if seclabel and seclabel.getNamespace() == nbxmpp.NS_SECLABEL:
# Ignore message from room in which we are not
self.displaymarking = seclabel.getTag('displaymarking')
@ -1351,9 +1355,10 @@ class GcMessageReceivedEvent(nec.NetworkIncomingEvent):
return
self.captcha_form = None
captcha_tag = self.stanza.getTag('captcha', namespace=xmpp.NS_CAPTCHA)
captcha_tag = self.stanza.getTag('captcha', namespace=nbxmpp.NS_CAPTCHA)
if captcha_tag:
self.captcha_form = captcha_tag.getTag('x', namespace=xmpp.NS_DATA)
self.captcha_form = captcha_tag.getTag('x',
namespace=nbxmpp.NS_DATA)
for field in self.captcha_form.getTags('field'):
for media in field.getTags('media'):
for uri in media.getTags('uri'):
@ -1362,7 +1367,7 @@ class GcMessageReceivedEvent(nec.NetworkIncomingEvent):
uri_data = uri_data[4:]
found = False
for data in self.stanza.getTags('data',
namespace=xmpp.NS_BOB):
namespace=nbxmpp.NS_BOB):
if data.getAttr('cid') == uri_data:
uri.setData(data.getData())
found = True
@ -1644,7 +1649,7 @@ PresenceHelperEvent):
base_network_events = ['raw-pres-received']
def _extract_caps_from_presence(self):
caps_tag = self.stanza.getTag('c', namespace=xmpp.NS_CAPS)
caps_tag = self.stanza.getTag('c', namespace=nbxmpp.NS_CAPS)
if caps_tag:
self.hash_method = caps_tag['hash']
self.node = caps_tag['node']
@ -1722,11 +1727,11 @@ class PEPReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
# for each entry in feed (there shouldn't be more than one, but to
# be sure...
for item in items.getTags('item'):
entry = item.getTag('entry', namespace=xmpp.NS_ATOM)
entry = item.getTag('entry', namespace=nbxmpp.NS_ATOM)
if entry:
gajim.nec.push_incoming_event(AtomEntryReceived(None,
conn=self.conn, node=entry))
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
class AtomEntryReceived(nec.NetworkIncomingEvent):
name = 'atom-entry-received'
@ -1878,7 +1883,7 @@ class AgentItemsReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
qp = []
for i in qp:
# CDATA payload is not processed, only nodes
if not isinstance(i, xmpp.simplexml.Node):
if not isinstance(i, nbxmpp.simplexml.Node):
continue
attr = {}
for key in i.getAttrs():
@ -1940,8 +1945,8 @@ class AgentInfoReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
var = i.getAttr('var')
if var:
self.features.append(var)
elif i.getName() == 'x' and i.getNamespace() == xmpp.NS_DATA:
self.data.append(xmpp.DataForm(node=i))
elif i.getName() == 'x' and i.getNamespace() == nbxmpp.NS_DATA:
self.data.append(nbxmpp.DataForm(node=i))
if not self.identities:
# ejabberd doesn't send identities when we browse online users
@ -1992,7 +1997,7 @@ class FileRequestReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
host['initiator'] = self.FT_content.session.initiator
host['target'] = self.FT_content.session.responder
self.file_props.session_type = 'jingle'
self.file_props.stream_methods = xmpp.NS_BYTESTREAM
self.file_props.stream_methods = nbxmpp.NS_BYTESTREAM
desc = self.jingle_content.getTag('description')
if desc.getTag('offer'):
file_tag = desc.getTag('offer').getTag('file')
@ -2031,14 +2036,14 @@ class FileRequestReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
unicode(si.getAttr('id'))
)
profile = si.getAttr('profile')
if profile != xmpp.NS_FILE:
if profile != nbxmpp.NS_FILE:
self.conn.send_file_rejection(self.file_props, code='400',
typ='profile')
raise xmpp.NodeProcessed
feature_tag = si.getTag('feature', namespace=xmpp.NS_FEATURE)
raise nbxmpp.NodeProcessed
feature_tag = si.getTag('feature', namespace=nbxmpp.NS_FEATURE)
if not feature_tag:
return
form_tag = feature_tag.getTag('x', namespace=xmpp.NS_DATA)
form_tag = feature_tag.getTag('x', namespace=nbxmpp.NS_DATA)
if not form_tag:
return
self.dataform = dataforms.ExtendForm(node=form_tag)
@ -2046,12 +2051,13 @@ class FileRequestReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
if f.var == 'stream-method' and f.type_ == 'list-single':
values = [o[1] for o in f.options]
self.file_props.stream_methods = ' '.join(values)
if xmpp.NS_BYTESTREAM in values or xmpp.NS_IBB in values:
if nbxmpp.NS_BYTESTREAM in values or \
nbxmpp.NS_IBB in values:
break
else:
self.conn.send_file_rejection(self.file_props, code='400',
typ='stream')
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
file_tag = si.getTag('file')
for name, val in file_tag.getAttrs().items():
if val is None:

View File

@ -26,19 +26,19 @@ This module contains wrappers for different parts of data forms (JEP 0004). For
information how to use them, read documentation
"""
import xmpp
import nbxmpp
import helpers
# exceptions used in this module
# base class
class Error(Exception): pass
# when we get xmpp.Node which we do not understand
# when we get nbxmpp.Node which we do not understand
class UnknownDataForm(Error): pass
# when we get xmpp.Node which contains bad fields
# when we get nbxmpp.Node which contains bad fields
class WrongFieldValue(Error): pass
# helper class to change class of already existing object
class ExtendedNode(xmpp.Node, object):
class ExtendedNode(nbxmpp.Node, object):
@classmethod
def __new__(cls, *a, **b):
if 'extend' not in b.keys() or not b['extend']:
@ -234,7 +234,7 @@ class DataField(ExtendedNode):
Media data
"""
def fget(self):
media = self.getTag('media', namespace=xmpp.NS_DATA_MEDIA)
media = self.getTag('media', namespace=nbxmpp.NS_DATA_MEDIA)
if media:
return Media(media)
@ -252,9 +252,9 @@ class DataField(ExtendedNode):
def is_valid(self):
return True
class Uri(xmpp.Node):
class Uri(nbxmpp.Node):
def __init__(self, uri_tag):
xmpp.Node.__init__(self, node=uri_tag)
nbxmpp.Node.__init__(self, node=uri_tag)
@nested_property
def type_():
@ -288,9 +288,9 @@ class Uri(xmpp.Node):
return locals()
class Media(xmpp.Node):
class Media(nbxmpp.Node):
def __init__(self, media_tag):
xmpp.Node.__init__(self, node=media_tag)
nbxmpp.Node.__init__(self, node=media_tag)
@nested_property
def uris():
@ -522,12 +522,12 @@ class DataRecord(ExtendedNode):
self.vars = {}
if extend is None:
# we have to build this object from scratch
xmpp.Node.__init__(self)
nbxmpp.Node.__init__(self)
if fields is not None:
self.fields = fields
else:
# we already have xmpp.Node inside - try to convert all
# we already have nbxmpp.Node inside - try to convert all
# fields into DataField objects
if fields is None:
for field in self.iterTags('field'):
@ -588,7 +588,7 @@ class DataForm(ExtendedNode):
def __init__(self, type_=None, title=None, instructions=None, extend=None):
if extend is None:
# we have to build form from scratch
xmpp.Node.__init__(self, 'x', attrs={'xmlns': xmpp.NS_DATA})
nbxmpp.Node.__init__(self, 'x', attrs={'xmlns': nbxmpp.NS_DATA})
if type_ is not None:
self.type_=type_
@ -700,7 +700,7 @@ class MultipleDataForm(DataForm):
if items is not None:
self.items = items
else:
# we already have xmpp.Node inside - try to convert all
# we already have nbxmpp.Node inside - try to convert all
# fields into DataField objects
if items is None:
self.items = list(self.iterTags('item'))

View File

@ -32,7 +32,7 @@ import logging
import locale
import config
import xmpp
import nbxmpp
import defs
import common.ged
@ -203,15 +203,16 @@ except ImportError:
gajim_identity = {'type': 'pc', 'category': 'client', 'name': 'Gajim'}
gajim_common_features = [xmpp.NS_BYTESTREAM, xmpp.NS_SI, xmpp.NS_FILE,
xmpp.NS_MUC, xmpp.NS_MUC_USER, xmpp.NS_MUC_ADMIN, xmpp.NS_MUC_OWNER,
xmpp.NS_MUC_CONFIG, xmpp.NS_COMMANDS, xmpp.NS_DISCO_INFO, 'ipv6',
'jabber:iq:gateway', xmpp.NS_LAST, xmpp.NS_PRIVACY, xmpp.NS_PRIVATE,
xmpp.NS_REGISTER, xmpp.NS_VERSION, xmpp.NS_DATA, xmpp.NS_ENCRYPTED, 'msglog',
'sslc2s', 'stringprep', xmpp.NS_PING, xmpp.NS_TIME_REVISED, xmpp.NS_SSN,
xmpp.NS_MOOD, xmpp.NS_ACTIVITY, xmpp.NS_NICK, xmpp.NS_ROSTERX, xmpp.NS_SECLABEL,
xmpp.NS_HASHES, xmpp.NS_HASHES_MD5, xmpp.NS_HASHES_SHA1,
xmpp.NS_HASHES_SHA256, xmpp.NS_HASHES_SHA512]
gajim_common_features = [nbxmpp.NS_BYTESTREAM, nbxmpp.NS_SI, nbxmpp.NS_FILE,
nbxmpp.NS_MUC, nbxmpp.NS_MUC_USER, nbxmpp.NS_MUC_ADMIN, nbxmpp.NS_MUC_OWNER,
nbxmpp.NS_MUC_CONFIG, nbxmpp.NS_COMMANDS, nbxmpp.NS_DISCO_INFO, 'ipv6',
'jabber:iq:gateway', nbxmpp.NS_LAST, nbxmpp.NS_PRIVACY, nbxmpp.NS_PRIVATE,
nbxmpp.NS_REGISTER, nbxmpp.NS_VERSION, nbxmpp.NS_DATA, nbxmpp.NS_ENCRYPTED,
'msglog', 'sslc2s', 'stringprep', nbxmpp.NS_PING, nbxmpp.NS_TIME_REVISED,
nbxmpp.NS_SSN, nbxmpp.NS_MOOD, nbxmpp.NS_ACTIVITY, nbxmpp.NS_NICK,
nbxmpp.NS_ROSTERX, nbxmpp.NS_SECLABEL, nbxmpp.NS_HASHES,
nbxmpp.NS_HASHES_MD5, nbxmpp.NS_HASHES_SHA1, nbxmpp.NS_HASHES_SHA256,
nbxmpp.NS_HASHES_SHA512]
# Optional features gajim supports per account
gajim_optional_features = {}

View File

@ -27,7 +27,7 @@ Global Events Dispatcher module.
import traceback
from common.xmpp import NodeProcessed
from nbxmpp import NodeProcessed
import logging
log = logging.getLogger('gajim.c.ged')

View File

@ -142,7 +142,7 @@ def parse_resource(resource):
"""
if resource:
try:
from xmpp.stringprepare import resourceprep
from nbxmpp.stringprepare import resourceprep
return resourceprep.prepare(unicode(resource))
except UnicodeError:
raise InvalidFormat, 'Invalid character in resource.'
@ -157,7 +157,7 @@ def prep(user, server, resource):
if len(user) < 1 or len(user) > 1023:
raise InvalidFormat, _('Username must be between 1 and 1023 chars')
try:
from xmpp.stringprepare import nodeprep
from nbxmpp.stringprepare import nodeprep
user = nodeprep.prepare(unicode(user))
except UnicodeError:
raise InvalidFormat, _('Invalid character in username.')
@ -168,7 +168,7 @@ def prep(user, server, resource):
if len(server) < 1 or len(server) > 1023:
raise InvalidFormat, _('Server must be between 1 and 1023 chars')
try:
from xmpp.stringprepare import nameprep
from nbxmpp.stringprepare import nameprep
server = nameprep.prepare(unicode(server))
except UnicodeError:
raise InvalidFormat, _('Invalid character in hostname.')
@ -179,7 +179,7 @@ def prep(user, server, resource):
if len(resource) < 1 or len(resource) > 1023:
raise InvalidFormat, _('Resource must be between 1 and 1023 chars')
try:
from xmpp.stringprepare import resourceprep
from nbxmpp.stringprepare import resourceprep
resource = resourceprep.prepare(unicode(resource))
except UnicodeError:
raise InvalidFormat, _('Invalid character in resource.')
@ -1300,7 +1300,7 @@ def prepare_and_validate_gpg_keyID(account, jid, keyID):
return keyID
def update_optional_features(account = None):
import xmpp
import nbxmpp
if account:
accounts = [account]
else:
@ -1308,38 +1308,41 @@ def update_optional_features(account = None):
for a in accounts:
gajim.gajim_optional_features[a] = []
if gajim.config.get_per('accounts', a, 'subscribe_mood'):
gajim.gajim_optional_features[a].append(xmpp.NS_MOOD + '+notify')
gajim.gajim_optional_features[a].append(nbxmpp.NS_MOOD + '+notify')
if gajim.config.get_per('accounts', a, 'subscribe_activity'):
gajim.gajim_optional_features[a].append(xmpp.NS_ACTIVITY + '+notify')
gajim.gajim_optional_features[a].append(nbxmpp.NS_ACTIVITY + \
'+notify')
if gajim.config.get_per('accounts', a, 'publish_tune'):
gajim.gajim_optional_features[a].append(xmpp.NS_TUNE)
gajim.gajim_optional_features[a].append(nbxmpp.NS_TUNE)
if gajim.config.get_per('accounts', a, 'publish_location'):
gajim.gajim_optional_features[a].append(xmpp.NS_LOCATION)
gajim.gajim_optional_features[a].append(nbxmpp.NS_LOCATION)
if gajim.config.get_per('accounts', a, 'subscribe_tune'):
gajim.gajim_optional_features[a].append(xmpp.NS_TUNE + '+notify')
gajim.gajim_optional_features[a].append(nbxmpp.NS_TUNE + '+notify')
if gajim.config.get_per('accounts', a, 'subscribe_nick'):
gajim.gajim_optional_features[a].append(xmpp.NS_NICK + '+notify')
gajim.gajim_optional_features[a].append(nbxmpp.NS_NICK + '+notify')
if gajim.config.get_per('accounts', a, 'subscribe_location'):
gajim.gajim_optional_features[a].append(xmpp.NS_LOCATION + '+notify')
gajim.gajim_optional_features[a].append(nbxmpp.NS_LOCATION + \
'+notify')
if gajim.config.get('outgoing_chat_state_notifactions') != 'disabled':
gajim.gajim_optional_features[a].append(xmpp.NS_CHATSTATES)
gajim.gajim_optional_features[a].append(nbxmpp.NS_CHATSTATES)
if not gajim.config.get('ignore_incoming_xhtml'):
gajim.gajim_optional_features[a].append(xmpp.NS_XHTML_IM)
gajim.gajim_optional_features[a].append(nbxmpp.NS_XHTML_IM)
if gajim.HAVE_PYCRYPTO \
and gajim.config.get_per('accounts', a, 'enable_esessions'):
gajim.gajim_optional_features[a].append(xmpp.NS_ESESSION)
gajim.gajim_optional_features[a].append(nbxmpp.NS_ESESSION)
if gajim.config.get_per('accounts', a, 'answer_receipts'):
gajim.gajim_optional_features[a].append(xmpp.NS_RECEIPTS)
gajim.gajim_optional_features[a].append(nbxmpp.NS_RECEIPTS)
if gajim.HAVE_FARSTREAM:
gajim.gajim_optional_features[a].append(xmpp.NS_JINGLE)
gajim.gajim_optional_features[a].append(xmpp.NS_JINGLE_RTP)
gajim.gajim_optional_features[a].append(xmpp.NS_JINGLE_RTP_AUDIO)
gajim.gajim_optional_features[a].append(xmpp.NS_JINGLE_RTP_VIDEO)
gajim.gajim_optional_features[a].append(xmpp.NS_JINGLE_ICE_UDP)
gajim.gajim_optional_features[a].append(xmpp.NS_JINGLE_FILE_TRANSFER)
gajim.gajim_optional_features[a].append(xmpp.NS_JINGLE_XTLS)
gajim.gajim_optional_features[a].append(xmpp.NS_JINGLE_BYTESTREAM)
gajim.gajim_optional_features[a].append(xmpp.NS_JINGLE_IBB)
gajim.gajim_optional_features[a].append(nbxmpp.NS_JINGLE)
gajim.gajim_optional_features[a].append(nbxmpp.NS_JINGLE_RTP)
gajim.gajim_optional_features[a].append(nbxmpp.NS_JINGLE_RTP_AUDIO)
gajim.gajim_optional_features[a].append(nbxmpp.NS_JINGLE_RTP_VIDEO)
gajim.gajim_optional_features[a].append(nbxmpp.NS_JINGLE_ICE_UDP)
gajim.gajim_optional_features[a].append(
nbxmpp.NS_JINGLE_FILE_TRANSFER)
gajim.gajim_optional_features[a].append(nbxmpp.NS_JINGLE_XTLS)
gajim.gajim_optional_features[a].append(nbxmpp.NS_JINGLE_BYTESTREAM)
gajim.gajim_optional_features[a].append(nbxmpp.NS_JINGLE_IBB)
gajim.caps_hash[a] = caps_cache.compute_caps_hash([gajim.gajim_identity],
gajim.gajim_common_features + gajim.gajim_optional_features[a])
# re-send presence with new hash
@ -1381,7 +1384,7 @@ def get_subscription_request_msg(account=None):
return s
def replace_dataform_media(form, stanza):
import xmpp
import nbxmpp
found = False
for field in form.getTags('field'):
for media in field.getTags('media'):
@ -1389,7 +1392,7 @@ def replace_dataform_media(form, stanza):
uri_data = uri.getData()
if uri_data.startswith('cid:'):
uri_data = uri_data[4:]
for data in stanza.getTags('data', namespace=xmpp.NS_BOB):
for data in stanza.getTags('data', namespace=nbxmpp.NS_BOB):
if data.getAttr('cid') == uri_data:
uri.setData(data.getData())
found = True

View File

@ -26,7 +26,7 @@ Handles the jingle signalling protocol
# * config:
# - codecs
import xmpp
import nbxmpp
import helpers
import gajim
@ -80,7 +80,7 @@ class ConnectionJingle(object):
if (jid, id_) in self.__iq_responses.keys():
self.__iq_responses[(jid, id_)].on_stanza(stanza)
del self.__iq_responses[(jid, id_)]
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
jingle = stanza.getTag('jingle')
# a jingle element is not necessary in iq-result stanza
# don't check for that
@ -105,7 +105,7 @@ class ConnectionJingle(object):
if sid in self._sessions and \
self._sessions[sid].state == JingleStates.ended:
self.delete_jingle_session(sid)
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
def start_audio(self, jid):
if self.get_jingle_session(jid, media='audio'):
@ -143,15 +143,15 @@ class ConnectionJingle(object):
contact = gajim.contacts.get_gc_contact(self.name, gcc[0], gcc[1])
if contact is None:
return
use_security = contact.supports(xmpp.NS_JINGLE_XTLS)
use_security = contact.supports(nbxmpp.NS_JINGLE_XTLS)
jingle = JingleSession(self, weinitiate=True, jid=jid, werequest=request)
# this is a file transfer
jingle.session_type_FT = True
self._sessions[jingle.sid] = jingle
file_props.sid = jingle.sid
if contact.supports(xmpp.NS_JINGLE_BYTESTREAM):
if contact.supports(nbxmpp.NS_JINGLE_BYTESTREAM):
transport = JingleTransportSocks5()
elif contact.supports(xmpp.NS_JINGLE_IBB):
elif contact.supports(nbxmpp.NS_JINGLE_IBB):
transport = JingleTransportIBB()
c = JingleFileTransfer(jingle, transport=transport,
file_props=file_props, use_security=use_security)
@ -161,14 +161,14 @@ class ConnectionJingle(object):
return c.transport.sid
def __hash_support(self, contact):
if contact.supports(xmpp.NS_HASHES):
if contact.supports(xmpp.NS_HASHES_MD5):
if contact.supports(nbxmpp.NS_HASHES):
if contact.supports(nbxmpp.NS_HASHES_MD5):
return 'md5'
elif contact.supports(xmpp.NS_HASHES_SHA1):
elif contact.supports(nbxmpp.NS_HASHES_SHA1):
return 'sha-1'
elif contact.supports(xmpp.NS_HASHES_SHA256):
elif contact.supports(nbxmpp.NS_HASHES_SHA256):
return 'sha-256'
elif contact.supports(xmpp.NS_HASHES_SHA512):
elif contact.supports(nbxmpp.NS_HASHES_SHA512):
return 'sha-512'
return None

View File

@ -16,7 +16,7 @@ Handles Jingle contents (XEP 0166)
"""
import gajim
import xmpp
import nbxmpp
from jingle_transport import JingleTransportIBB
contents = {}
@ -127,7 +127,7 @@ class JingleContent(object):
"""
Build a XML content-wrapper for our data
"""
return xmpp.Node('content',
return nbxmpp.Node('content',
attrs={'name': self.name, 'creator': self.creator},
payload=payload)
@ -164,29 +164,29 @@ class JingleContent(object):
content.addChild(node=self.transport.make_transport())
def _fill_content(self, content):
description_node = xmpp.simplexml.Node(
tag=xmpp.NS_JINGLE_FILE_TRANSFER + ' description')
description_node = nbxmpp.simplexml.Node(
tag=nbxmpp.NS_JINGLE_FILE_TRANSFER + ' description')
if self.session.werequest:
simode = xmpp.simplexml.Node(tag='request')
simode = nbxmpp.simplexml.Node(tag='request')
else:
simode = xmpp.simplexml.Node(tag='offer')
file_tag = simode.setTag('file', namespace=xmpp.NS_FILE)
simode = nbxmpp.simplexml.Node(tag='offer')
file_tag = simode.setTag('file', namespace=nbxmpp.NS_FILE)
if self.file_props.name:
node = xmpp.simplexml.Node(tag='name')
node = nbxmpp.simplexml.Node(tag='name')
node.addData(self.file_props.name)
file_tag.addChild(node=node)
if self.file_props.date:
node = xmpp.simplexml.Node(tag='date')
node = nbxmpp.simplexml.Node(tag='date')
node.addData(self.file_props.date)
file_tag.addChild(node=node)
if self.file_props.size:
node = xmpp.simplexml.Node(tag='size')
node = nbxmpp.simplexml.Node(tag='size')
node.addData(self.file_props.size)
file_tag.addChild(node=node)
if self.file_props.type_ == 'r':
if self.file_props.hash_:
h = file_tag.addChild('hash', attrs={
'algo': self.file_props.algo}, namespace=xmpp.NS_HASHES,
'algo': self.file_props.algo}, namespace=nbxmpp.NS_HASHES,
payload=self.file_props.hash_)
else:
# if the file is less than 10 mb, then it is small
@ -209,11 +209,11 @@ class JingleContent(object):
desc.setData(self.file_props.desc)
description_node.addChild(node=simode)
if self.use_security:
security = xmpp.simplexml.Node(
tag=xmpp.NS_JINGLE_XTLS + ' security')
security = nbxmpp.simplexml.Node(
tag=nbxmpp.NS_JINGLE_XTLS + ' security')
# TODO: add fingerprint element
for m in ('x509', ): # supported authentication methods
method = xmpp.simplexml.Node(tag='method')
method = nbxmpp.simplexml.Node(tag='method')
method.setAttr('name', m)
security.addChild(node=method)
content.addChild(node=security)

View File

@ -21,7 +21,7 @@ Handles Jingle File Transfer (XEP 0234)
import hashlib
import gajim
import xmpp
import nbxmpp
from jingle_content import contents, JingleContent
from jingle_transport import *
from common import helpers
@ -70,7 +70,7 @@ class JingleFileTransfer(JingleContent):
self.use_security = use_security
self.file_props = file_props
self.weinitiate = self.session.weinitiate
self.werequest = self.session.werequest
self.werequest = self.session.werequest
if self.file_props is not None:
if self.session.werequest:
self.file_props.sender = self.session.peerjid
@ -130,9 +130,9 @@ class JingleFileTransfer(JingleContent):
def __send_hash(self):
# Send hash in a session info
checksum = xmpp.Node(tag='checksum', payload=[xmpp.Node(tag='file',
checksum = nbxmpp.Node(tag='checksum', payload=[nbxmpp.Node(tag='file',
payload=[self._calcHash()])])
checksum.setNamespace(xmpp.NS_JINGLE_FILE_TRANSFER)
checksum.setNamespace(nbxmpp.NS_JINGLE_FILE_TRANSFER)
self.session.__session_info(checksum )
pjid = gajim.get_jid_without_resource(self.session.peerjid)
file_info = {'name' : self.file_props.name,
@ -153,7 +153,7 @@ class JingleFileTransfer(JingleContent):
except:
# can't open file
return
h = xmpp.Hashes()
h = nbxmpp.Hashes()
hash_ = h.calculateHash(self.file_props.algo, file_)
# DEBUG
#hash_ = '1294809248109223'
@ -177,10 +177,10 @@ class JingleFileTransfer(JingleContent):
con.connection.send(response)
# If we are requesting we don't have the file
if self.session.werequest:
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
# We send the file
self.__state_changed(STATE_TRANSFERING)
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
self.file_props.streamhosts = self.transport.remote_candidates
# Calculate file hash in a new thread
# if we haven't sent the hash already.
@ -205,7 +205,7 @@ class JingleFileTransfer(JingleContent):
receiving=False)
return
self.__state_changed(STATE_TRANSFERING)
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
def __on_session_terminate(self, stanza, content, error, action):
log.info("__on_session_terminate")
@ -228,7 +228,7 @@ class JingleFileTransfer(JingleContent):
candUsed = content.getTag('transport').getTag('candidate-used')
if (candError or candUsed) and \
self.state >= STATE_CAND_SENT_AND_RECEIVED:
raise xmpp.OutOfOrder
raise nbxmpp.OutOfOrder
if candError:
if not gajim.socks5queue.listener.connections:
gajim.socks5queue.listener.disconnect()
@ -244,7 +244,7 @@ class JingleFileTransfer(JingleContent):
response.delChild(response.getQuery())
self.session.connection.connection.send(response)
self.__state_changed(STATE_TRANSFERING)
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
else:
args = {'candError' : True}
self.__state_changed(STATE_CAND_RECEIVED, args)
@ -273,7 +273,7 @@ class JingleFileTransfer(JingleContent):
response.delChild(response.getQuery())
self.session.connection.connection.send(response)
self.__state_changed(STATE_TRANSFERING)
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
else:
self.__state_changed(STATE_CAND_RECEIVED, args)
@ -376,4 +376,4 @@ class JingleFileTransfer(JingleContent):
def get_content(desc):
return JingleFileTransfer
contents[xmpp.NS_JINGLE_FILE_TRANSFER] = get_content
contents[nbxmpp.NS_JINGLE_FILE_TRANSFER] = get_content

View File

@ -12,7 +12,7 @@
##
import gajim
import xmpp
import nbxmpp
from jingle_transport import *
from common.socks5 import Socks5ReceiverClient, Socks5SenderClient
@ -65,13 +65,13 @@ class StateCandSent(JingleFileTransferStates):
# Send candidate used
streamhost = args['streamhost']
self.jft.nominated_cand['our-cand'] = streamhost
content = xmpp.Node('content')
content = nbxmpp.Node('content')
content.setAttr('creator', 'initiator')
content.setAttr('name', self.jft.name)
transport = xmpp.Node('transport')
transport.setNamespace(xmpp.NS_JINGLE_BYTESTREAM)
transport = nbxmpp.Node('transport')
transport.setNamespace(nbxmpp.NS_JINGLE_BYTESTREAM)
transport.setAttr('sid', self.jft.transport.sid)
candidateused = xmpp.Node('candidate-used')
candidateused = nbxmpp.Node('candidate-used')
candidateused.setAttr('cid', streamhost['cid'])
transport.addChild(node=candidateused)
content.addChild(node=transport)

View File

@ -20,7 +20,7 @@ from collections import deque
import gobject
import socket
import xmpp
import nbxmpp
import farstream, gst
from glib import GError
@ -151,7 +151,7 @@ class JingleRTPContent(JingleContent):
self.p2psession.stop_telephony_event()
def _fill_content(self, content):
content.addChild(xmpp.NS_JINGLE_RTP + ' description',
content.addChild(nbxmpp.NS_JINGLE_RTP + ' description',
attrs={'media': self.media}, payload=self.iter_codecs())
def _setup_funnel(self):
@ -190,7 +190,7 @@ class JingleRTPContent(JingleContent):
elif name == 'farstream-component-state-changed':
state = message.structure['state']
if state == farstream.STREAM_STATE_FAILED:
reason = xmpp.Node('reason')
reason = nbxmpp.Node('reason')
reason.setTag('failed-transport')
self.session.remove_content(self.creator, self.name, reason)
elif name == 'farstream-error':
@ -222,7 +222,7 @@ class JingleRTPContent(JingleContent):
self.src_bin.get_pad('src').link(sink_pad)
self.stream_failed_once = True
else:
reason = xmpp.Node('reason')
reason = nbxmpp.Node('reason')
reason.setTag('failed-application')
self.session.remove_content(self.creator, self.name, reason)
@ -276,11 +276,11 @@ class JingleRTPContent(JingleContent):
if codec.clock_rate:
attrs['clockrate'] = codec.clock_rate
if codec.optional_params:
payload = (xmpp.Node('parameter', {'name': name, 'value': value})
for name, value in codec.optional_params)
payload = (nbxmpp.Node('parameter', {'name': name,
'value': value}) for name, value in codec.optional_params)
else:
payload = ()
yield xmpp.Node('payload-type', attrs, payload)
yield nbxmpp.Node('payload-type', attrs, payload)
def __stop(self, *things):
self.pipeline.set_state(gst.STATE_NULL)
@ -408,4 +408,4 @@ def get_content(desc):
elif desc['media'] == 'video':
return JingleVideo
contents[xmpp.NS_JINGLE_RTP] = get_content
contents[nbxmpp.NS_JINGLE_RTP] = get_content

View File

@ -27,7 +27,7 @@ Handles Jingle sessions (XEP 0166)
# * timeout
import gajim #Get rid of that?
import xmpp
import nbxmpp
from jingle_transport import get_jingle_transport, JingleTransportIBB
from jingle_content import get_jingle_content, JingleContentSetupException
from jingle_content import JingleContent
@ -105,9 +105,9 @@ class JingleSession(object):
# use .prepend() to add new callbacks, especially when you're going
# to send error instead of ack
self.callbacks = {
'content-accept': [self.__ack, self.__on_content_accept,
'content-accept': [self.__ack, self.__on_content_accept,
self.__broadcast],
'content-add': [self.__ack,
'content-add': [self.__ack,
self.__on_content_add, self.__broadcast
], #TODO
'content-modify': [self.__ack], #TODO
@ -118,14 +118,14 @@ class JingleSession(object):
'session-accept': [self.__ack, self.__on_session_accept,
self.__on_content_accept,
self.__broadcast],
'session-info': [self.__ack, self.__broadcast,
'session-info': [self.__ack, self.__broadcast,
self.__on_session_info ],
'session-initiate': [self.__ack, self.__on_session_initiate,
'session-initiate': [self.__ack, self.__on_session_initiate,
self.__broadcast],
'session-terminate': [self.__ack,self.__on_session_terminate,
'session-terminate': [self.__ack,self.__on_session_terminate,
self.__broadcast_all],
'transport-info': [self.__ack, self.__broadcast],
'transport-replace': [self.__ack, self.__broadcast,
'transport-replace': [self.__ack, self.__broadcast,
self.__on_transport_replace], #TODO
'transport-accept': [self.__ack], #TODO
'transport-reject': [self.__ack], #TODO
@ -147,15 +147,15 @@ class JingleSession(object):
"""
Called when user declines session in UI (when we aren't the initiator)
"""
reason = xmpp.Node('reason')
reason = nbxmpp.Node('reason')
reason.addChild('decline')
self._session_terminate(reason)
def cancel_session(self):
"""
Called when user declines session in UI (when we aren't the initiator)
"""
reason = xmpp.Node('reason')
reason = nbxmpp.Node('reason')
reason.addChild('cancel')
self._session_terminate(reason)
@ -177,7 +177,7 @@ class JingleSession(object):
"""
Called when user stops or cancel session in UI
"""
reason = xmpp.Node('reason')
reason = nbxmpp.Node('reason')
if self.state == JingleStates.active:
reason.addChild('success')
else:
@ -227,7 +227,7 @@ class JingleSession(object):
self.end_session()
def modify_content(self, creator, name, transport = None):
'''
'''
Currently used for transport replacement
'''
content = self.contents[(creator,name)]
@ -314,7 +314,7 @@ class JingleSession(object):
"""
A callback for ConnectionJingle. It gets stanza, then tries to send it to
all internally registered callbacks. First one to raise
xmpp.NodeProcessed breaks function
nbxmpp.NodeProcessed breaks function
"""
jingle = stanza.getTag('jingle')
error = stanza.getTag('error')
@ -339,7 +339,7 @@ class JingleSession(object):
try:
for call in callables:
call(stanza=stanza, jingle=jingle, error=error, action=action)
except xmpp.NodeProcessed:
except nbxmpp.NodeProcessed:
pass
except TieBreak:
self.__send_error(stanza, 'conflict', 'tiebreak')
@ -360,10 +360,10 @@ class JingleSession(object):
text = error.getTagData('text')
error_name = None
for child in error.getChildren():
if child.getNamespace() == xmpp.NS_JINGLE_ERRORS:
if child.getNamespace() == nbxmpp.NS_JINGLE_ERRORS:
error_name = child.getName()
break
elif child.getNamespace() == xmpp.NS_STANZAS:
elif child.getNamespace() == nbxmpp.NS_STANZAS:
error_name = child.getName()
self.__dispatch_error(error_name, text, error.getAttr('type'))
@ -387,12 +387,12 @@ class JingleSession(object):
name = content['name']
if (creator, name) in self.contents:
transport_ns = content.getTag('transport').getNamespace()
if transport_ns == xmpp.NS_JINGLE_ICE_UDP:
if transport_ns == nbxmpp.NS_JINGLE_ICE_UDP:
# FIXME: We don't manage anything else than ICE-UDP now...
# What was the previous transport?!?
# Anyway, content's transport is not modifiable yet
pass
elif transport_ns == xmpp.NS_JINGLE_IBB:
elif transport_ns == nbxmpp.NS_JINGLE_IBB:
transport = JingleTransportIBB()
self.modify_content(creator, name, transport)
self.state = JingleStates.pending
@ -406,7 +406,7 @@ class JingleSession(object):
'name': name})
content.setTag('transport', namespace=transport_ns)
self.connection.connection.send(stanza)
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
else:
# FIXME: This ressource is unknown to us, what should we do?
# For now, reject the transport
@ -415,7 +415,7 @@ class JingleSession(object):
'name': name})
c.setTag('transport', namespace=transport_ns)
self.connection.connection.send(stanza)
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
def __on_session_info(self, stanza, jingle, error, action):
# TODO: ringing, active, (un)hold, (un)mute
@ -424,18 +424,18 @@ class JingleSession(object):
payload = jingle.getPayload()
for p in payload:
if p.getName() == 'checksum':
hash_ = p.getTag('file').getTag(name='hash',
namespace=xmpp.NS_HASHES)
hash_ = p.getTag('file').getTag(name='hash',
namespace=nbxmpp.NS_HASHES)
algo = hash_.getAttr('algo')
if algo in xmpp.Hashes.supported:
if algo in nbxmpp.Hashes.supported:
file_props = FilesProp.getFileProp(self.connection.name,
self.sid)
file_props.algo = algo
file_props.hash_ = hash_.getData()
raise xmpp.NodeProcessed
self.__send_error(stanza, 'feature-not-implemented', 'unsupported-info',
raise nbxmpp.NodeProcessed
self.__send_error(stanza, 'feature-not-implemented', 'unsupported-info',
type_='modify')
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
def __on_content_remove(self, stanza, jingle, error, action):
for content in jingle.iterTags('content'):
@ -449,7 +449,7 @@ class JingleSession(object):
media=content.media, reason='removed'))
content.destroy()
if not self.contents:
reason = xmpp.Node('reason')
reason = nbxmpp.Node('reason')
reason.setTag('success')
self._session_terminate(reason)
@ -507,12 +507,12 @@ class JingleSession(object):
if contents[0][0] != 'file':
for session in self.connection.iter_jingle_sessions(self.peerjid):
if not session is self:
reason = xmpp.Node('reason')
reason = nbxmpp.Node('reason')
alternative_session = reason.setTag('alternative-session')
alternative_session.setTagData('sid', session.sid)
self.__ack(stanza, jingle, error, action)
self._session_terminate(reason)
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
else:
# Stop if we don't have the requested file or the peer is not
# allowed to request the file
@ -533,15 +533,15 @@ class JingleSession(object):
'file that we dont have or ' + \
'it is not allowed to request')
self.decline_session()
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
# If there's no content we understand...
if not contents:
# TODO: http://xmpp.org/extensions/xep-0166.html#session-terminate
reason = xmpp.Node('reason')
reason = nbxmpp.Node('reason')
reason.setTag(reason_txt)
self.__ack(stanza, jingle, error, action)
self._session_terminate(reason)
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
self.state = JingleStates.pending
# Send event about starting a session
gajim.nec.push_incoming_event(JingleRequestReceivedEvent(None,
@ -566,7 +566,7 @@ class JingleSession(object):
if (creator, name) not in self.contents:
text = 'Content %s (created by %s) does not exist' % (name, creator)
self.__send_error(stanza, 'bad-request', text=text, type_='_modify')
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
else:
cn = self.contents[(creator, name)]
cn.on_stanza(stanza, content, error, action)
@ -654,23 +654,24 @@ class JingleSession(object):
return (reason, text)
def __make_jingle(self, action, reason=None):
stanza = xmpp.Iq(typ='set', to=xmpp.JID(self.peerjid),
frm=self.ourjid)
stanza = nbxmpp.Iq(typ='set', to=nbxmpp.JID(self.peerjid),
frm=self.ourjid)
attrs = {'action': action,
'sid': self.sid,
'initiator' : self.initiator}
jingle = stanza.addChild('jingle', attrs=attrs, namespace=xmpp.NS_JINGLE)
jingle = stanza.addChild('jingle', attrs=attrs,
namespace=nbxmpp.NS_JINGLE)
if reason is not None:
jingle.addChild(node=reason)
return stanza, jingle
def __send_error(self, stanza, error, jingle_error=None, text=None, type_=None):
err_stanza = xmpp.Error(stanza, '%s %s' % (xmpp.NS_STANZAS, error))
err_stanza = nbxmpp.Error(stanza, '%s %s' % (nbxmpp.NS_STANZAS, error))
err = err_stanza.getTag('error')
if type_:
err.setAttr('type', type_)
if jingle_error:
err.setTag(jingle_error, namespace=xmpp.NS_JINGLE_ERRORS)
err.setTag(jingle_error, namespace=nbxmpp.NS_JINGLE_ERRORS)
if text:
err.setTagData('text', text)
self.connection.connection.send(err_stanza)
@ -718,7 +719,7 @@ class JingleSession(object):
if payload:
jingle.addChild(node=payload)
self.connection.connection.send(stanza)
def _JingleFileTransfer__session_info(self, p):
# For some strange reason when I call
# self.session.__session_info(h) from the jingleFileTransfer object

View File

@ -15,7 +15,7 @@
Handles Jingle Transports (currently only ICE-UDP)
"""
import xmpp
import nbxmpp
import socket
from common import gajim
from common.protocol.bytestream import ConnectionSocks5Bytestream
@ -70,7 +70,7 @@ class JingleTransport(object):
candidates = self._iter_candidates()
else:
candidates = (self.make_candidate(candidate) for candidate in candidates)
transport = xmpp.Node('transport', payload=candidates)
transport = nbxmpp.Node('transport', payload=candidates)
return transport
def parse_transport_stanza(self, transport):
@ -120,7 +120,7 @@ class JingleTransportSocks5(JingleTransport):
'type': candidate['type']
}
return xmpp.Node('candidate', attrs=attrs)
return nbxmpp.Node('candidate', attrs=attrs)
def make_transport(self, candidates=None, add_candidates = True):
if add_candidates:
@ -129,8 +129,8 @@ class JingleTransportSocks5(JingleTransport):
self._add_proxy_candidates()
transport = JingleTransport.make_transport(self, candidates)
else:
transport = xmpp.Node('transport')
transport.setNamespace(xmpp.NS_JINGLE_BYTESTREAM)
transport = nbxmpp.Node('transport')
transport.setNamespace(nbxmpp.NS_JINGLE_BYTESTREAM)
transport.setAttr('sid', self.sid)
if self.file_props.dstaddr:
transport.setAttr('dstaddr', self.file_props.dstaddr)
@ -266,10 +266,10 @@ class JingleTransportSocks5(JingleTransport):
if sesn is None:
return
iq = xmpp.Iq(to=proxy['jid'], frm=self.ourjid, typ='set')
iq = nbxmpp.Iq(to=proxy['jid'], frm=self.ourjid, typ='set')
auth_id = "au_" + proxy['sid']
iq.setID(auth_id)
query = iq.setTag('query', namespace=xmpp.NS_BYTESTREAM)
query = iq.setTag('query', namespace=nbxmpp.NS_BYTESTREAM)
query.setAttr('sid', proxy['sid'])
activate = query.setTag('activate')
activate.setData(sesn.peerjid)
@ -277,14 +277,14 @@ class JingleTransportSocks5(JingleTransport):
self.connection.connection.send(iq)
content = xmpp.Node('content')
content = nbxmpp.Node('content')
content.setAttr('creator', 'initiator')
c = self.get_content()
content.setAttr('name', c.name)
transport = xmpp.Node('transport')
transport.setNamespace(xmpp.NS_JINGLE_BYTESTREAM)
transport = nbxmpp.Node('transport')
transport.setNamespace(nbxmpp.NS_JINGLE_BYTESTREAM)
transport.setAttr('sid', proxy['sid'])
activated = xmpp.Node('activated')
activated = nbxmpp.Node('activated')
cid = None
if 'cid' in proxy:
@ -322,8 +322,8 @@ class JingleTransportIBB(JingleTransport):
def make_transport(self):
transport = xmpp.Node('transport')
transport.setNamespace(xmpp.NS_JINGLE_IBB)
transport = nbxmpp.Node('transport')
transport.setNamespace(nbxmpp.NS_JINGLE_IBB)
transport.setAttr('block-size', self.block_sz)
transport.setAttr('sid', self.sid)
return transport
@ -360,11 +360,11 @@ class JingleTransportICEUDP(JingleTransport):
else:
# we actually don't handle properly different tcp options in jingle
attrs['protocol'] = 'tcp'
return xmpp.Node('candidate', attrs=attrs)
return nbxmpp.Node('candidate', attrs=attrs)
def make_transport(self, candidates=None):
transport = JingleTransport.make_transport(self, candidates)
transport.setNamespace(xmpp.NS_JINGLE_ICE_UDP)
transport.setNamespace(nbxmpp.NS_JINGLE_ICE_UDP)
if self.candidates and self.candidates[0].username and \
self.candidates[0].password:
transport.setAttr('ufrag', self.candidates[0].username)
@ -405,6 +405,6 @@ class JingleTransportICEUDP(JingleTransport):
self.remote_candidates.extend(candidates)
return candidates
transports[xmpp.NS_JINGLE_ICE_UDP] = JingleTransportICEUDP
transports[xmpp.NS_JINGLE_BYTESTREAM] = JingleTransportSocks5
transports[xmpp.NS_JINGLE_IBB] = JingleTransportIBB
transports[nbxmpp.NS_JINGLE_ICE_UDP] = JingleTransportICEUDP
transports[nbxmpp.NS_JINGLE_BYTESTREAM] = JingleTransportSocks5
transports[nbxmpp.NS_JINGLE_IBB] = JingleTransportIBB

View File

@ -17,6 +17,7 @@
##
import os
import nbxmpp
import logging
import common
@ -56,7 +57,7 @@ def default_callback(connection, certificate, error_num, depth, return_code):
def load_cert_file(cert_path, cert_store):
"""
This is almost identical to the one in common.xmpp.tls_nb
This is almost identical to the one in nbxmpp.tls_nb
"""
if not os.path.isfile(cert_path):
return
@ -118,11 +119,11 @@ def send_cert(con, jid_from, sid):
for line in certfile.readlines():
if not line.startswith('-'):
certificate += line
iq = common.xmpp.Iq('result', to=jid_from);
iq = nbxmpp.Iq('result', to=jid_from);
iq.setAttr('id', sid)
pubkey = iq.setTag('pubkeys')
pubkey.setNamespace(common.xmpp.NS_PUBKEY_PUBKEY)
pubkey.setNamespace(nbxmpp.NS_PUBKEY_PUBKEY)
keyinfo = pubkey.setTag('keyinfo')
name = keyinfo.setTag('name')
@ -151,11 +152,11 @@ def handle_new_cert(con, obj, jid_from):
approve_pending_content(id_)
def send_cert_request(con, to_jid):
iq = common.xmpp.Iq('get', to=to_jid)
iq = nbxmpp.Iq('get', to=to_jid)
id_ = con.connection.getAnID()
iq.setAttr('id', id_)
pubkey = iq.setTag('pubkeys')
pubkey.setNamespace(common.xmpp.NS_PUBKEY_PUBKEY)
pubkey.setNamespace(nbxmpp.NS_PUBKEY_PUBKEY)
con.connection.send(iq)
return unicode(id_)

View File

@ -18,7 +18,7 @@
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
##
import common.xmpp
import nbxmpp
from common import gajim
from common import ged
from common.connection_handlers_events import ArchivingReceivedEvent
@ -52,16 +52,16 @@ class ConnectionArchive:
self._nec_archiving_changed_received)
def request_message_archiving_preferences(self):
iq_ = common.xmpp.Iq('get')
iq_.setTag('pref', namespace=common.xmpp.NS_ARCHIVE)
iq_ = nbxmpp.Iq('get')
iq_.setTag('pref', namespace=nbxmpp.NS_ARCHIVE)
self.connection.send(iq_)
def set_pref(self, name, **data):
'''
data contains names and values of pref name attributes.
'''
iq_ = common.xmpp.Iq('set')
pref = iq_.setTag('pref', namespace=common.xmpp.NS_ARCHIVE)
iq_ = nbxmpp.Iq('set')
pref = iq_.setTag('pref', namespace=nbxmpp.NS_ARCHIVE)
tag = pref.setTag(name)
for key, value in data.items():
if value is not None:
@ -81,21 +81,21 @@ class ConnectionArchive:
self.set_pref('item', jid=jid, otr=otr, save=save)
def remove_item(self, jid):
iq_ = common.xmpp.Iq('set')
itemremove = iq_.setTag('itemremove', namespace=common.xmpp.NS_ARCHIVE)
iq_ = nbxmpp.Iq('set')
itemremove = iq_.setTag('itemremove', namespace=nbxmpp.NS_ARCHIVE)
item = itemremove.setTag('item')
item.setAttr('jid', jid)
self.connection.send(iq_)
def stop_archiving_session(self, thread_id):
iq_ = common.xmpp.Iq('set')
pref = iq_.setTag('pref', namespace=common.xmpp.NS_ARCHIVE)
iq_ = nbxmpp.Iq('set')
pref = iq_.setTag('pref', namespace=nbxmpp.NS_ARCHIVE)
session = pref.setTag('session', attrs={'thread': thread_id,
'save': 'false', 'otr': 'concede'})
self.connection.send(iq_)
def get_item_pref(self, jid):
jid = common.xmpp.JID(jid)
jid = nbxmpp.JID(jid)
if unicode(jid) in self.items:
return self.items[jid]
@ -142,7 +142,7 @@ class ConnectionArchive:
log.debug('_ArchiveCB %s' % iq_obj.getType())
gajim.nec.push_incoming_event(ArchivingReceivedEvent(None, conn=self,
stanza=iq_obj))
raise common.xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
def _nec_archiving_changed_received(self, obj):
if obj.conn.name != self.name:
@ -160,8 +160,8 @@ class ConnectionArchive:
def request_collections_list_page(self, with_='', start=None, end=None,
after=None, max=30, exact_match=False):
iq_ = common.xmpp.Iq('get')
list_ = iq_.setTag('list', namespace=common.xmpp.NS_ARCHIVE)
iq_ = nbxmpp.Iq('get')
list_ = iq_.setTag('list', namespace=nbxmpp.NS_ARCHIVE)
if with_:
list_.setAttr('with', with_)
if exact_match:
@ -170,7 +170,7 @@ class ConnectionArchive:
list_.setAttr('start', start)
if end:
list_.setAttr('end', end)
set_ = list_.setTag('set', namespace=common.xmpp.NS_RSM)
set_ = list_.setTag('set', namespace=nbxmpp.NS_RSM)
set_.setTagData('max', max)
if after:
set_.setTagData('after', after)
@ -181,12 +181,12 @@ class ConnectionArchive:
def request_collection_page(self, with_, start, end=None, after=None,
max=30, exact_match=False):
iq_ = common.xmpp.Iq('get')
retrieve = iq_.setTag('retrieve', namespace=common.xmpp.NS_ARCHIVE,
iq_ = nbxmpp.Iq('get')
retrieve = iq_.setTag('retrieve', namespace=nbxmpp.NS_ARCHIVE,
attrs={'with': with_, 'start': start})
if exact_match:
retrieve.setAttr('exactmatch', 'true')
set_ = retrieve.setTag('set', namespace=common.xmpp.NS_RSM)
set_ = retrieve.setTag('set', namespace=nbxmpp.NS_RSM)
set_.setTagData('max', max)
if after:
set_.setTagData('after', after)
@ -197,8 +197,8 @@ class ConnectionArchive:
def remove_collection(self, with_='', start=None, end=None,
exact_match=False, open=False):
iq_ = common.xmpp.Iq('set')
remove = iq_.setTag('remove', namespace=common.xmpp.NS_ARCHIVE)
iq_ = nbxmpp.Iq('set')
remove = iq_.setTag('remove', namespace=nbxmpp.NS_ARCHIVE)
if with_:
remove.setAttr('with', with_)
if exact_match:
@ -212,10 +212,10 @@ class ConnectionArchive:
self.connection.send(iq_)
def request_modifications_page(self, start, max=30):
iq_ = common.xmpp.Iq('get')
moified = iq_.setTag('modified', namespace=common.xmpp.NS_ARCHIVE,
iq_ = nbxmpp.Iq('get')
moified = iq_.setTag('modified', namespace=nbxmpp.NS_ARCHIVE,
attrs={'start': start})
set_ = moified.setTag('set', namespace=common.xmpp.NS_RSM)
set_ = moified.setTag('set', namespace=nbxmpp.NS_RSM)
set_.setTagData('max', max)
id_ = self.connection.getAnID()
iq_.setID(id_)

View File

@ -221,7 +221,7 @@ import logging
log = logging.getLogger('gajim.c.pep')
from common import helpers
from common import xmpp
import nbxmpp
from common import gajim
import gtkgui_helpers
@ -281,7 +281,7 @@ class UserMoodPEP(AbstractPEP):
'''XEP-0107: User Mood'''
type_ = 'mood'
namespace = xmpp.NS_MOOD
namespace = nbxmpp.NS_MOOD
def _extract_info(self, items):
mood_dict = {}
@ -327,7 +327,7 @@ class UserTunePEP(AbstractPEP):
'''XEP-0118: User Tune'''
type_ = 'tune'
namespace = xmpp.NS_TUNE
namespace = nbxmpp.NS_TUNE
def _extract_info(self, items):
tune_dict = {}
@ -373,7 +373,7 @@ class UserActivityPEP(AbstractPEP):
'''XEP-0108: User Activity'''
type_ = 'activity'
namespace = xmpp.NS_ACTIVITY
namespace = nbxmpp.NS_ACTIVITY
def _extract_info(self, items):
activity_dict = {}
@ -439,7 +439,7 @@ class UserNicknamePEP(AbstractPEP):
'''XEP-0172: User Nickname'''
type_ = 'nickname'
namespace = xmpp.NS_NICK
namespace = nbxmpp.NS_NICK
def _extract_info(self, items):
nick = ''
@ -468,7 +468,7 @@ class UserLocationPEP(AbstractPEP):
'''XEP-0080: User Location'''
type_ = 'location'
namespace = xmpp.NS_LOCATION
namespace = nbxmpp.NS_LOCATION
def _extract_info(self, items):
location_dict = {}
@ -562,7 +562,7 @@ class ConnectionPEP(object):
return
if not self.pep_supported:
return
item = xmpp.Node('activity', {'xmlns': xmpp.NS_ACTIVITY})
item = nbxmpp.Node('activity', {'xmlns': nbxmpp.NS_ACTIVITY})
if activity:
i = item.addChild(activity)
if subactivity:
@ -570,14 +570,15 @@ class ConnectionPEP(object):
if message:
i = item.addChild('text')
i.addData(message)
self._pubsub_connection.send_pb_publish('', xmpp.NS_ACTIVITY, item, '0')
self._pubsub_connection.send_pb_publish('', nbxmpp.NS_ACTIVITY, item,
'0')
def retract_activity(self):
if not self.pep_supported:
return
self.send_activity(None)
# not all client support new XEP, so we still retract
self._pubsub_connection.send_pb_retract('', xmpp.NS_ACTIVITY, '0')
self._pubsub_connection.send_pb_retract('', nbxmpp.NS_ACTIVITY, '0')
def send_mood(self, mood, message=None):
if self.connected == 1:
@ -587,20 +588,20 @@ class ConnectionPEP(object):
return
if not self.pep_supported:
return
item = xmpp.Node('mood', {'xmlns': xmpp.NS_MOOD})
item = nbxmpp.Node('mood', {'xmlns': nbxmpp.NS_MOOD})
if mood:
item.addChild(mood)
if message:
i = item.addChild('text')
i.addData(message)
self._pubsub_connection.send_pb_publish('', xmpp.NS_MOOD, item, '0')
self._pubsub_connection.send_pb_publish('', nbxmpp.NS_MOOD, item, '0')
def retract_mood(self):
if not self.pep_supported:
return
self.send_mood(None)
# not all client support new XEP, so we still retract
self._pubsub_connection.send_pb_retract('', xmpp.NS_MOOD, '0')
self._pubsub_connection.send_pb_retract('', nbxmpp.NS_MOOD, '0')
def send_tune(self, artist='', title='', source='', track=0, length=0,
items=None):
@ -611,7 +612,7 @@ class ConnectionPEP(object):
return
if not self.pep_supported:
return
item = xmpp.Node('tune', {'xmlns': xmpp.NS_TUNE})
item = nbxmpp.Node('tune', {'xmlns': nbxmpp.NS_TUNE})
if artist:
i = item.addChild('artist')
i.addData(artist)
@ -629,14 +630,14 @@ class ConnectionPEP(object):
i.addData(length)
if items:
item.addChild(payload=items)
self._pubsub_connection.send_pb_publish('', xmpp.NS_TUNE, item, '0')
self._pubsub_connection.send_pb_publish('', nbxmpp.NS_TUNE, item, '0')
def retract_tune(self):
if not self.pep_supported:
return
self.send_tune(None)
# not all client support new XEP, so we still retract
self._pubsub_connection.send_pb_retract('', xmpp.NS_TUNE, '0')
self._pubsub_connection.send_pb_retract('', nbxmpp.NS_TUNE, '0')
def send_nickname(self, nick):
if self.connected == 1:
@ -646,16 +647,16 @@ class ConnectionPEP(object):
return
if not self.pep_supported:
return
item = xmpp.Node('nick', {'xmlns': xmpp.NS_NICK})
item = nbxmpp.Node('nick', {'xmlns': nbxmpp.NS_NICK})
item.addData(nick)
self._pubsub_connection.send_pb_publish('', xmpp.NS_NICK, item, '0')
self._pubsub_connection.send_pb_publish('', nbxmpp.NS_NICK, item, '0')
def retract_nickname(self):
if not self.pep_supported:
return
self.send_nickname(None)
# not all client support new XEP, so we still retract
self._pubsub_connection.send_pb_retract('', xmpp.NS_NICK, '0')
self._pubsub_connection.send_pb_retract('', nbxmpp.NS_NICK, '0')
def send_location(self, info):
if self.connected == 1:
@ -665,16 +666,16 @@ class ConnectionPEP(object):
return
if not self.pep_supported:
return
item = xmpp.Node('geoloc', {'xmlns': xmpp.NS_LOCATION})
item = nbxmpp.Node('geoloc', {'xmlns': nbxmpp.NS_LOCATION})
for field in LOCATION_DATA:
if info.get(field, None):
i = item.addChild(field)
i.addData(info[field])
self._pubsub_connection.send_pb_publish('', xmpp.NS_LOCATION, item, '0')
self._pubsub_connection.send_pb_publish('', nbxmpp.NS_LOCATION, item, '0')
def retract_location(self):
if not self.pep_supported:
return
self.send_location({})
# not all client support new XEP, so we still retract
self._pubsub_connection.send_pb_retract('', xmpp.NS_LOCATION, '0')
self._pubsub_connection.send_pb_retract('', nbxmpp.NS_LOCATION, '0')

View File

@ -33,7 +33,7 @@ import base64
import gobject
import time
from common import xmpp
import nbxmpp
from common import gajim
from common import helpers
from common import dataforms
@ -109,25 +109,25 @@ class ConnectionBytestream:
return
file_props.sender = self._ft_get_our_jid()
fjid = self._ft_get_receiver_jid(file_props)
iq = xmpp.Iq(to=fjid, typ='set')
iq = nbxmpp.Iq(to=fjid, typ='set')
iq.setID(file_props.sid)
si = iq.setTag('si', namespace=xmpp.NS_SI)
si.setAttr('profile', xmpp.NS_FILE)
si = iq.setTag('si', namespace=nbxmpp.NS_SI)
si.setAttr('profile', nbxmpp.NS_FILE)
si.setAttr('id', file_props.sid)
file_tag = si.setTag('file', namespace=xmpp.NS_FILE)
file_tag = si.setTag('file', namespace=nbxmpp.NS_FILE)
file_tag.setAttr('name', file_props.name)
file_tag.setAttr('size', file_props.size)
desc = file_tag.setTag('desc')
if file_props.desc:
desc.setData(file_props.desc)
file_tag.setTag('range')
feature = si.setTag('feature', namespace=xmpp.NS_FEATURE)
_feature = xmpp.DataForm(typ='form')
feature = si.setTag('feature', namespace=nbxmpp.NS_FEATURE)
_feature = nbxmpp.DataForm(typ='form')
feature.addChild(node=_feature)
field = _feature.setField('stream-method')
field.setAttr('type', 'list-single')
field.addOption(xmpp.NS_BYTESTREAM)
field.addOption(xmpp.NS_IBB)
field.addOption(nbxmpp.NS_BYTESTREAM)
field.addOption(nbxmpp.NS_IBB)
self.connection.send(iq)
def send_file_approval(self, file_props):
@ -163,22 +163,22 @@ class ConnectionBytestream:
session.approve_content('file', content.name)
return
iq = xmpp.Iq(to=unicode(file_props.sender), typ='result')
iq = nbxmpp.Iq(to=unicode(file_props.sender), typ='result')
iq.setAttr('id', file_props.request_id)
si = iq.setTag('si', namespace=xmpp.NS_SI)
si = iq.setTag('si', namespace=nbxmpp.NS_SI)
if file_props.offset:
file_tag = si.setTag('file', namespace=xmpp.NS_FILE)
file_tag = si.setTag('file', namespace=nbxmpp.NS_FILE)
range_tag = file_tag.setTag('range')
range_tag.setAttr('offset', file_props.offset)
feature = si.setTag('feature', namespace=xmpp.NS_FEATURE)
_feature = xmpp.DataForm(typ='submit')
feature = si.setTag('feature', namespace=nbxmpp.NS_FEATURE)
_feature = nbxmpp.DataForm(typ='submit')
feature.addChild(node=_feature)
field = _feature.setField('stream-method')
field.delAttr('type')
if xmpp.NS_BYTESTREAM in file_props.stream_methods:
field.setValue(xmpp.NS_BYTESTREAM)
if nbxmpp.NS_BYTESTREAM in file_props.stream_methods:
field.setValue(nbxmpp.NS_BYTESTREAM)
else:
field.setValue(xmpp.NS_IBB)
field.setValue(nbxmpp.NS_IBB)
self.connection.send(iq)
def send_file_rejection(self, file_props, code='403', typ=None):
@ -195,7 +195,7 @@ class ConnectionBytestream:
jingle = self._sessions[file_props.sid]
jingle.cancel_session()
return
iq = xmpp.Iq(to=unicode(file_props.sender), typ='error')
iq = nbxmpp.Iq(to=unicode(file_props.sender), typ='error')
iq.setAttr('id', file_props.request_id)
if code == '400' and typ in ('stream', 'profile'):
name = 'bad-request'
@ -203,12 +203,12 @@ class ConnectionBytestream:
else:
name = 'forbidden'
text = 'Offer Declined'
err = xmpp.ErrorNode(code=code, typ='cancel', name=name, text=text)
err = nbxmpp.ErrorNode(code=code, typ='cancel', name=name, text=text)
if code == '400' and typ in ('stream', 'profile'):
if typ == 'stream':
err.setTag('no-valid-streams', namespace=xmpp.NS_SI)
err.setTag('no-valid-streams', namespace=nbxmpp.NS_SI)
else:
err.setTag('bad-profile', namespace=xmpp.NS_SI)
err.setTag('bad-profile', namespace=nbxmpp.NS_SI)
iq.addChild(node=err)
self.connection.send(iq)
@ -233,25 +233,25 @@ class ConnectionBytestream:
if length:
file_props.length = int(length)
feature = si.setTag('feature')
if feature.getNamespace() != xmpp.NS_FEATURE:
if feature.getNamespace() != nbxmpp.NS_FEATURE:
return
form_tag = feature.getTag('x')
form = xmpp.DataForm(node=form_tag)
form = nbxmpp.DataForm(node=form_tag)
field = form.getField('stream-method')
if field.getValue() == xmpp.NS_BYTESTREAM:
if field.getValue() == nbxmpp.NS_BYTESTREAM:
self._send_socks5_info(file_props)
raise xmpp.NodeProcessed
if field.getValue() == xmpp.NS_IBB:
raise nbxmpp.NodeProcessed
if field.getValue() == nbxmpp.NS_IBB:
sid = file_props.sid
fp = open(file_props.file_name, 'r')
self.OpenStream(sid, file_props.receiver, fp)
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
def _siSetCB(self, con, iq_obj):
from common.connection_handlers_events import FileRequestReceivedEvent
gajim.nec.push_incoming_event(FileRequestReceivedEvent(None, conn=self,
stanza=iq_obj))
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
def _nec_file_request_received(self, obj):
pass
@ -259,7 +259,7 @@ class ConnectionBytestream:
def _siErrorCB(self, con, iq_obj):
si = iq_obj.getTag('si')
profile = si.getAttr('profile')
if profile != xmpp.NS_FILE:
if profile != nbxmpp.NS_FILE:
return
file_props = FilesProp.getFileProp(con.name, iq_obj.getAttr('id'))
if not file_props:
@ -269,7 +269,7 @@ class ConnectionBytestream:
from common.connection_handlers_events import FileRequestErrorEvent
gajim.nec.push_incoming_event(FileRequestErrorEvent(None, conn=self,
jid=jid, file_props=file_props, error_msg=''))
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
class ConnectionSocks5Bytestream(ConnectionBytestream):
@ -281,10 +281,10 @@ class ConnectionSocks5Bytestream(ConnectionBytestream):
return
if streamhost is None:
return None
iq = xmpp.Iq(to=streamhost['initiator'], typ='result',
iq = nbxmpp.Iq(to=streamhost['initiator'], typ='result',
frm=streamhost['target'])
iq.setAttr('id', streamhost['id'])
query = iq.setTag('query', namespace=xmpp.NS_BYTESTREAM)
query = iq.setTag('query', namespace=nbxmpp.NS_BYTESTREAM)
stream_tag = query.setTag('streamhost-used')
stream_tag.setAttr('jid', streamhost['jid'])
self.connection.send(iq)
@ -358,10 +358,10 @@ class ConnectionSocks5Bytestream(ConnectionBytestream):
self._connect_error(unicode(receiver), file_props.sid,
file_props.sid, code=406)
else:
iq = xmpp.Iq(to=unicode(receiver), typ='set')
iq = nbxmpp.Iq(to=unicode(receiver), typ='set')
file_props.request_id = 'id_' + file_props.sid
iq.setID(file_props.request_id)
query = iq.setTag('query', namespace=xmpp.NS_BYTESTREAM)
query = iq.setTag('query', namespace=nbxmpp.NS_BYTESTREAM)
query.setAttr('sid', file_props.sid)
self._add_addiditional_streamhosts_to_query(query, file_props)
@ -372,7 +372,7 @@ class ConnectionSocks5Bytestream(ConnectionBytestream):
def _add_streamhosts_to_query(self, query, sender, port, hosts):
for host in hosts:
streamhost = xmpp.Node(tag='streamhost')
streamhost = nbxmpp.Node(tag='streamhost')
query.addChild(node=streamhost)
streamhost.setAttr('port', unicode(port))
streamhost.setAttr('host', host)
@ -560,7 +560,7 @@ class ConnectionSocks5Bytestream(ConnectionBytestream):
to = file_props.receiver
else:
to = file_props.sender
iq = xmpp.Iq(to=to, typ='error')
iq = nbxmpp.Iq(to=to, typ='error')
iq.setAttr('id', file_props.sid)
err = iq.setTag('error')
err.setAttr('code', unicode(code))
@ -581,10 +581,10 @@ class ConnectionSocks5Bytestream(ConnectionBytestream):
if not self.connection or self.connected < 2:
return
file_props = FilesProp.getFileProp(self.name, proxy['sid'])
iq = xmpp.Iq(to=proxy['initiator'], typ='set')
iq = nbxmpp.Iq(to=proxy['initiator'], typ='set')
auth_id = "au_" + proxy['sid']
iq.setID(auth_id)
query = iq.setTag('query', namespace=xmpp.NS_BYTESTREAM)
query = iq.setTag('query', namespace=nbxmpp.NS_BYTESTREAM)
query.setAttr('sid', proxy['sid'])
activate = query.setTag('activate')
activate.setData(file_props.proxy_receiver)
@ -606,7 +606,7 @@ class ConnectionSocks5Bytestream(ConnectionBytestream):
from common.connection_handlers_events import FileRequestErrorEvent
gajim.nec.push_incoming_event(FileRequestErrorEvent(None, conn=self,
jid=jid, file_props=file_props, error_msg=''))
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
def _bytestreamSetCB(self, con, iq_obj):
target = unicode(iq_obj.getAttr('to'))
@ -643,16 +643,16 @@ class ConnectionSocks5Bytestream(ConnectionBytestream):
file_props.streamhosts = streamhosts
gajim.socks5queue.connect_to_hosts(self.name, sid,
self.send_success_connect_reply, None)
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
else:
log.warn('Gajim got streamhosts for unknown transfer. Ignoring it.')
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
file_props.streamhosts = streamhosts
if file_props.type_ == 'r':
gajim.socks5queue.connect_to_hosts(self.name, sid,
self.send_success_connect_reply, self._connect_error)
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
def _ResultCB(self, con, iq_obj):
# if we want to respect xep-0065 we have to check for proxy
@ -667,7 +667,7 @@ class ConnectionSocks5Bytestream(ConnectionBytestream):
for host in file_props.proxyhosts:
if host['initiator'] == frm and 'idx' in host:
gajim.socks5queue.activate_proxy(host['idx'])
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
def _bytestreamResultCB(self, con, iq_obj):
frm = self._ft_get_from(iq_obj)
@ -682,30 +682,30 @@ class ConnectionSocks5Bytestream(ConnectionBytestream):
id_ = real_id[3:]
file_props = FilesProp.getFileProp(self.name, id_)
if file_props is None:
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
if streamhost is None:
# proxy approves the activate query
if real_id.startswith('au_'):
if file_props.streamhost_used is False:
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
if not file_props.proxyhosts:
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
for host in file_props.proxyhosts:
if host['initiator'] == frm and \
unicode(query.getAttr('sid')) == file_props.sid:
gajim.socks5queue.activate_proxy(host['idx'])
break
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
jid = self._ft_get_streamhost_jid_attr(streamhost)
if file_props.streamhost_used is True:
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
if real_id.startswith('au_'):
if file_props.stopped:
self.remove_transfer(file_props)
else:
gajim.socks5queue.send_file(file_props, self.name)
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
proxy = None
if file_props.proxyhosts:
@ -715,7 +715,7 @@ class ConnectionSocks5Bytestream(ConnectionBytestream):
if file_props.stopped:
self.remove_transfer(file_props)
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
if proxy is not None:
file_props.streamhost_used = True
file_props.streamhosts.append(proxy)
@ -729,7 +729,7 @@ class ConnectionSocks5Bytestream(ConnectionBytestream):
gajim.socks5queue.add_sockobj(self.name, sender, 'sender')
proxy['idx'] = sender.queue_idx
gajim.socks5queue.on_success[file_props.sid] = self._proxy_auth_ok
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
else:
if file_props.stopped:
@ -737,7 +737,7 @@ class ConnectionSocks5Bytestream(ConnectionBytestream):
else:
gajim.socks5queue.send_file(file_props, self.name, 'server')
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
class ConnectionIBBytestream(ConnectionBytestream):
@ -753,17 +753,17 @@ class ConnectionIBBytestream(ConnectionBytestream):
"""
typ = stanza.getType()
log.debug('IBBIqHandler called typ->%s' % typ)
if typ == 'set' and stanza.getTag('open', namespace=xmpp.NS_IBB):
if typ == 'set' and stanza.getTag('open', namespace=nbxmpp.NS_IBB):
self.StreamOpenHandler(conn, stanza)
elif typ == 'set' and stanza.getTag('close', namespace=xmpp.NS_IBB):
elif typ == 'set' and stanza.getTag('close', namespace=nbxmpp.NS_IBB):
self.StreamCloseHandler(conn, stanza)
elif typ == 'result':
self.SendHandler()
elif typ == 'error':
gajim.socks5queue.error_cb()
else:
conn.send(xmpp.Error(stanza, xmpp.ERR_BAD_REQUEST))
raise xmpp.NodeProcessed
conn.send(nbxmpp.Error(stanza, nbxmpp.ERR_BAD_REQUEST))
raise nbxmpp.NodeProcessed
def StreamOpenHandler(self, conn, stanza):
"""
@ -778,16 +778,16 @@ class ConnectionIBBytestream(ConnectionBytestream):
try:
blocksize = int(blocksize)
except:
err = xmpp.ERR_BAD_REQUEST
err = nbxmpp.ERR_BAD_REQUEST
if not sid or not blocksize:
err = xmpp.ERR_BAD_REQUEST
err = nbxmpp.ERR_BAD_REQUEST
elif not file_props:
err = xmpp.ERR_UNEXPECTED_REQUEST
err = nbxmpp.ERR_UNEXPECTED_REQUEST
if err:
rep = xmpp.Error(stanza, err)
rep = nbxmpp.Error(stanza, err)
else:
log.debug("Opening stream: id %s, block-size %s" % (sid, blocksize))
rep = xmpp.Protocol('iq', stanza.getFrom(), 'result',
rep = nbxmpp.Protocol('iq', stanza.getFrom(), 'result',
stanza.getTo(), {'id': stanza.getID()})
file_props.block_size = blocksize
file_props.seq = 0
@ -811,7 +811,7 @@ class ConnectionIBBytestream(ConnectionBytestream):
Take into account that recommended stanza size is 4k and IBB uses
base64 encoding that increases size of data by 1/3.
"""
if not xmpp.JID(to).getResource():
if not nbxmpp.JID(to).getResource():
return
file_props = FilesProp.getFilePropBySid(sid)
file_props.direction = '|>' + to
@ -826,8 +826,9 @@ class ConnectionIBBytestream(ConnectionBytestream):
file_props.completed = False
file_props.disconnect_cb = None
file_props.continue_cb = None
syn = xmpp.Protocol('iq', to, 'set', payload=[xmpp.Node(xmpp.NS_IBB + \
' open', {'sid': sid, 'block-size': blocksize, 'stanza': 'iq'})])
syn = nbxmpp.Protocol('iq', to, 'set', payload=[nbxmpp.Node(
nbxmpp.NS_IBB + ' open', {'sid': sid, 'block-size': blocksize,
'stanza': 'iq'})])
self.connection.send(syn)
file_props.syn_id = syn.getID()
return file_props
@ -850,15 +851,15 @@ class ConnectionIBBytestream(ConnectionBytestream):
continue
chunk = file_props.fp.read(file_props.block_size)
if chunk:
datanode = xmpp.Node(xmpp.NS_IBB + ' data', {'sid': sid,
datanode = nbxmpp.Node(nbxmpp.NS_IBB + ' data', {'sid': sid,
'seq': file_props.seq}, base64.encodestring(chunk))
file_props.seq += 1
file_props.started = True
if file_props.seq == 65536:
file_props.seq = 0
self.last_sent_ibb_id = self.connection.send(xmpp.Protocol(
name='iq', to=file_props.direction[1:], typ='set',
payload=[datanode]))
self.last_sent_ibb_id = self.connection.send(
nbxmpp.Protocol(name='iq', to=file_props.direction[1:],
typ='set', payload=[datanode]))
current_time = time.time()
file_props.elapsed_time += current_time - file_props.last_time
file_props.last_time = current_time
@ -869,9 +870,9 @@ class ConnectionIBBytestream(ConnectionBytestream):
# notify the other side about stream closing
# notify the local user about sucessfull send
# delete the local stream
self.connection.send(xmpp.Protocol('iq',
self.connection.send(nbxmpp.Protocol('iq',
file_props.direction[1:], 'set',
payload=[xmpp.Node(xmpp.NS_IBB + ' close',
payload=[nbxmpp.Node(nbxmpp.NS_IBB + ' close',
{'sid':sid})]))
file_props.completed = True
@ -893,12 +894,12 @@ class ConnectionIBBytestream(ConnectionBytestream):
err = None
file_props = FilesProp.getFileProp(self.name, sid)
if file_props is None:
err = xmpp.ERR_ITEM_NOT_FOUND
err = nbxmpp.ERR_ITEM_NOT_FOUND
else:
if not data:
err = xmpp.ERR_BAD_REQUEST
err = nbxmpp.ERR_BAD_REQUEST
elif seq <> file_props.seq:
err = xmpp.ERR_UNEXPECTED_REQUEST
err = nbxmpp.ERR_UNEXPECTED_REQUEST
else:
log.debug('Successfull receive sid->%s %s+%s bytes' % (sid,
file_props.fp.tell(), len(data)))
@ -914,9 +915,9 @@ class ConnectionIBBytestream(ConnectionBytestream):
file_props.completed = True
if err:
log.debug('Error on receive: %s' % err)
conn.send(xmpp.Error(xmpp.Iq(to=stanza.getFrom(),
conn.send(nbxmpp.Error(nbxmpp.Iq(to=stanza.getFrom(),
frm=stanza.getTo(),
payload=[xmpp.Node(xmpp.NS_IBB + ' close')]), err, reply=0))
payload=[nbxmpp.Node(nbxmpp.NS_IBB + ' close')]), err, reply=0))
else:
return True
@ -940,7 +941,7 @@ class ConnectionIBBytestream(ConnectionBytestream):
file_props.fp.close()
gajim.socks5queue.complete_transfer_cb(self.name, file_props)
else:
conn.send(xmpp.Error(stanza, xmpp.ERR_ITEM_NOT_FOUND))
conn.send(nbxmpp.Error(stanza, nbxmpp.ERR_ITEM_NOT_FOUND))
def IBBAllIqHandler(self, conn, stanza):
"""
@ -966,8 +967,8 @@ class ConnectionIBBytestream(ConnectionBytestream):
file_props.direction = file_props.direction[1:]
self.SendHandler()
else:
conn.send(xmpp.Error(stanza,
xmpp.ERR_UNEXPECTED_REQUEST))
conn.send(nbxmpp.Error(stanza,
nbxmpp.ERR_UNEXPECTED_REQUEST))
break
else:
if stanza.getTag('data'):
@ -975,7 +976,7 @@ class ConnectionIBBytestream(ConnectionBytestream):
reply = stanza.buildReply('result')
reply.delChild('data')
conn.send(reply)
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
elif syn_id == self.last_sent_ibb_id:
self.SendHandler()

View File

@ -26,11 +26,11 @@ import errno
import logging
log = logging.getLogger('gajim.c.proxy65_manager')
import common.xmpp
import nbxmpp
from common import gajim
from common import helpers
from socks5 import Socks5
from common.xmpp.idlequeue import IdleObject
from nbxmpp.idlequeue import IdleObject
from common.file_props import FilesProp
S_INITIAL = 0
@ -90,7 +90,7 @@ class Proxy65Manager:
self.proxies[proxy]._on_connect_failure()
self.proxies[proxy].resolve_result(host, port, jid)
# we can have only one streamhost
raise common.xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
def error_cb(self, proxy, query):
sid = query.getAttr('sid')
@ -138,9 +138,9 @@ class ProxyResolver:
def _on_connect_success(self):
log.debug('Host successfully connected %s:%s' % (self.host, self.port))
iq = common.xmpp.Protocol(name='iq', to=self.jid, typ='set')
iq = nbxmpp.Protocol(name='iq', to=self.jid, typ='set')
query = iq.setTag('query')
query.setNamespace(common.xmpp.NS_BYTESTREAM)
query.setNamespace(nbxmpp.NS_BYTESTREAM)
query.setAttr('sid', self.sid)
activate = query.setTag('activate')
@ -212,9 +212,9 @@ class ProxyResolver:
"""
self.state = S_STARTED
self.active_connection = connection
iq = common.xmpp.Protocol(name='iq', to=self.proxy, typ='get')
iq = nbxmpp.Protocol(name='iq', to=self.proxy, typ='get')
query = iq.setTag('query')
query.setNamespace(common.xmpp.NS_BYTESTREAM)
query.setNamespace(nbxmpp.NS_BYTESTREAM)
connection.send(iq)
def __init__(self, proxy, sender_jid, testit):

View File

@ -21,7 +21,7 @@
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
##
import xmpp
import nbxmpp
import gajim
import connection_handlers
import ged
@ -44,8 +44,8 @@ class ConnectionPubSub:
def send_pb_subscription_query(self, jid, cb, *args, **kwargs):
if not self.connection or self.connected < 2:
return
query = xmpp.Iq('get', to=jid)
pb = query.addChild('pubsub', namespace=xmpp.NS_PUBSUB)
query = nbxmpp.Iq('get', to=jid)
pb = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB)
pb.addChild('subscriptions')
id_ = self.connection.send(query)
@ -56,8 +56,8 @@ class ConnectionPubSub:
if not self.connection or self.connected < 2:
return
our_jid = gajim.get_jid_from_account(self.name)
query = xmpp.Iq('set', to=jid)
pb = query.addChild('pubsub', namespace=xmpp.NS_PUBSUB)
query = nbxmpp.Iq('set', to=jid)
pb = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB)
pb.addChild('subscribe', {'node': node, 'jid': our_jid})
id_ = self.connection.send(query)
@ -68,8 +68,8 @@ class ConnectionPubSub:
if not self.connection or self.connected < 2:
return
our_jid = gajim.get_jid_from_account(self.name)
query = xmpp.Iq('set', to=jid)
pb = query.addChild('pubsub', namespace=xmpp.NS_PUBSUB)
query = nbxmpp.Iq('set', to=jid)
pb = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB)
pb.addChild('unsubscribe', {'node': node, 'jid': our_jid})
id_ = self.connection.send(query)
@ -82,8 +82,8 @@ class ConnectionPubSub:
"""
if not self.connection or self.connected < 2:
return
query = xmpp.Iq('set', to=jid)
e = query.addChild('pubsub', namespace=xmpp.NS_PUBSUB)
query = nbxmpp.Iq('set', to=jid)
e = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB)
p = e.addChild('publish', {'node': node})
attrs = {}
if id_:
@ -101,8 +101,8 @@ class ConnectionPubSub:
"""
if not self.connection or self.connected < 2:
return
query = xmpp.Iq('get', to=jid)
r = query.addChild('pubsub', namespace=xmpp.NS_PUBSUB)
query = nbxmpp.Iq('get', to=jid)
r = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB)
r = r.addChild('items', {'node': node})
id_ = self.connection.send(query)
@ -115,8 +115,8 @@ class ConnectionPubSub:
"""
if not self.connection or self.connected < 2:
return
query = xmpp.Iq('set', to=jid)
r = query.addChild('pubsub', namespace=xmpp.NS_PUBSUB)
query = nbxmpp.Iq('set', to=jid)
r = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB)
r = r.addChild('retract', {'node': node, 'notify': '1'})
r = r.addChild('item', {'id': id_})
@ -128,8 +128,8 @@ class ConnectionPubSub:
"""
if not self.connection or self.connected < 2:
return
query = xmpp.Iq('set', to=jid)
d = query.addChild('pubsub', namespace=xmpp.NS_PUBSUB_OWNER)
query = nbxmpp.Iq('set', to=jid)
d = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB_OWNER)
d = d.addChild('purge', {'node': node})
self.connection.send(query)
@ -140,8 +140,8 @@ class ConnectionPubSub:
"""
if not self.connection or self.connected < 2:
return
query = xmpp.Iq('set', to=jid)
d = query.addChild('pubsub', namespace=xmpp.NS_PUBSUB_OWNER)
query = nbxmpp.Iq('set', to=jid)
d = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB_OWNER)
d = d.addChild('delete', {'node': node})
def response(con, resp, jid, node):
@ -160,8 +160,8 @@ class ConnectionPubSub:
"""
if not self.connection or self.connected < 2:
return
query = xmpp.Iq('set', to=jid)
c = query.addChild('pubsub', namespace=xmpp.NS_PUBSUB)
query = nbxmpp.Iq('set', to=jid)
c = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB)
c = c.addChild('create', {'node': node})
if configure:
conf = c.addChild('configure')
@ -173,8 +173,8 @@ class ConnectionPubSub:
def send_pb_configure(self, jid, node, form):
if not self.connection or self.connected < 2:
return
query = xmpp.Iq('set', to=jid)
c = query.addChild('pubsub', namespace=xmpp.NS_PUBSUB_OWNER)
query = nbxmpp.Iq('set', to=jid)
c = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB_OWNER)
c = c.addChild('configure', {'node': node})
c.addChild(node=form)
@ -213,8 +213,8 @@ class ConnectionPubSub:
def request_pb_configuration(self, jid, node):
if not self.connection or self.connected < 2:
return
query = xmpp.Iq('get', to=jid)
e = query.addChild('pubsub', namespace=xmpp.NS_PUBSUB_OWNER)
query = nbxmpp.Iq('get', to=jid)
e = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB_OWNER)
e = e.addChild('configure', {'node': node})
id_ = self.connection.getAnID()
query.setID(id_)

View File

@ -31,7 +31,7 @@ if __name__ == '__main__':
common.configpaths.gajimpaths.init_profile()
from common import helpers
from common.xmpp.idlequeue import IdleCommand
from nbxmpp.idlequeue import IdleCommand
# it is good to check validity of arguments, when calling system commands
ns_type_pattern = re.compile('^[a-z]+$')
@ -320,7 +320,7 @@ class NsLookup(IdleCommand):
if __name__ == '__main__':
import gobject
import gtk
from xmpp import idlequeue
from nbxmpp import idlequeue
idlequeue = idlequeue.get_idlequeue()
resolver = get_resolver(idlequeue)

View File

@ -32,7 +32,7 @@ from errno import EINTR
from errno import EISCONN
from errno import EINPROGRESS
from errno import EAFNOSUPPORT
from xmpp.idlequeue import IdleObject
from nbxmpp.idlequeue import IdleObject
from file_props import FilesProp
from common import gajim
import jingle_xtls

View File

@ -23,9 +23,9 @@
##
from common import gajim
from common import xmpp
import nbxmpp
from common.exceptions import DecryptionError, NegotiationError
import xmpp.c14n
import nbxmpp.c14n
import itertools
import random
@ -123,17 +123,18 @@ class StanzaSession(object):
msg.setAttr('to', self.get_to())
self.conn.send_stanza(msg)
if isinstance(msg, xmpp.Message):
if isinstance(msg, nbxmpp.Message):
self.last_send = time.time()
def reject_negotiation(self, body=None):
msg = xmpp.Message()
msg = nbxmpp.Message()
feature = msg.NT.feature
feature.setNamespace(xmpp.NS_FEATURE)
feature.setNamespace(nbxmpp.NS_FEATURE)
x = xmpp.DataForm(typ='submit')
x.addChild(node=xmpp.DataField(name='FORM_TYPE', value='urn:xmpp:ssn'))
x.addChild(node=xmpp.DataField(name='accept', value='0'))
x = nbxmpp.DataForm(typ='submit')
x.addChild(node=nbxmpp.DataField(name='FORM_TYPE',
value='urn:xmpp:ssn'))
x.addChild(node=nbxmpp.DataField(name='accept', value='0'))
feature.addChild(node=x)
@ -160,13 +161,14 @@ class StanzaSession(object):
# have XEP-0201 support
if send_termination and self.last_send > 0 and \
(self.received_thread_id or self.last_receive == 0):
msg = xmpp.Message()
msg = nbxmpp.Message()
feature = msg.NT.feature
feature.setNamespace(xmpp.NS_FEATURE)
feature.setNamespace(nbxmpp.NS_FEATURE)
x = xmpp.DataForm(typ='submit')
x.addChild(node=xmpp.DataField(name='FORM_TYPE', value='urn:xmpp:ssn'))
x.addChild(node=xmpp.DataField(name='terminate', value='1'))
x = nbxmpp.DataForm(typ='submit')
x.addChild(node=nbxmpp.DataField(name='FORM_TYPE',
value='urn:xmpp:ssn'))
x.addChild(node=nbxmpp.DataField(name='terminate', value='1'))
feature.addChild(node=x)
@ -190,24 +192,24 @@ class ArchivingStanzaSession(StanzaSession):
def negotiate_archiving(self):
self.negotiated = {}
request = xmpp.Message()
request = nbxmpp.Message()
feature = request.NT.feature
feature.setNamespace(xmpp.NS_FEATURE)
feature.setNamespace(nbxmpp.NS_FEATURE)
x = xmpp.DataForm(typ='form')
x = nbxmpp.DataForm(typ='form')
x.addChild(node=xmpp.DataField(name='FORM_TYPE', value='urn:xmpp:ssn',
typ='hidden'))
x.addChild(node=xmpp.DataField(name='accept', value='1', typ='boolean',
required=True))
x.addChild(node=nbxmpp.DataField(name='FORM_TYPE', value='urn:xmpp:ssn',
typ='hidden'))
x.addChild(node=nbxmpp.DataField(name='accept', value='1',
typ='boolean', required=True))
x.addChild(node=xmpp.DataField(name='logging', typ='list-single',
options=self.archiving_logging_preference(), required=True))
x.addChild(node=nbxmpp.DataField(name='logging', typ='list-single',
options=self.archiving_logging_preference(), required=True))
x.addChild(node=xmpp.DataField(name='disclosure', typ='list-single',
options=['never'], required=True))
x.addChild(node=xmpp.DataField(name='security', typ='list-single',
options=['none'], required=True))
x.addChild(node=nbxmpp.DataField(name='disclosure', typ='list-single',
options=['never'], required=True))
x.addChild(node=nbxmpp.DataField(name='security', typ='list-single',
options=['none'], required=True))
feature.addChild(node=x)
@ -223,27 +225,28 @@ class ArchivingStanzaSession(StanzaSession):
logging = self.archiving_logging_preference(options)
self.negotiated['logging'] = logging
response = xmpp.Message()
response = nbxmpp.Message()
feature = response.NT.feature
feature.setNamespace(xmpp.NS_FEATURE)
feature.setNamespace(nbxmpp.NS_FEATURE)
x = xmpp.DataForm(typ='submit')
x = nbxmpp.DataForm(typ='submit')
x.addChild(node=xmpp.DataField(name='FORM_TYPE', value='urn:xmpp:ssn'))
x.addChild(node=xmpp.DataField(name='accept', value='true'))
x.addChild(node=nbxmpp.DataField(name='FORM_TYPE',
value='urn:xmpp:ssn'))
x.addChild(node=nbxmpp.DataField(name='accept', value='true'))
x.addChild(node=xmpp.DataField(name='logging', value=logging))
x.addChild(node=nbxmpp.DataField(name='logging', value=logging))
self.status = 'responded-archiving'
feature.addChild(node=x)
if not logging:
response = xmpp.Error(response, xmpp.ERR_NOT_ACCEPTABLE)
response = nbxmpp.Error(response, nbxmpp.ERR_NOT_ACCEPTABLE)
feature = xmpp.Node(xmpp.NS_FEATURE + ' feature')
feature = nbxmpp.Node(nbxmpp.NS_FEATURE + ' feature')
n = xmpp.Node('field')
n = nbxmpp.Node('field')
n['var'] = 'logging'
feature.addChild(node=n)
@ -270,15 +273,15 @@ class ArchivingStanzaSession(StanzaSession):
self.negotiated['logging'] = form['logging']
accept = xmpp.Message()
accept = nbxmpp.Message()
feature = accept.NT.feature
feature.setNamespace(xmpp.NS_FEATURE)
feature.setNamespace(nbxmpp.NS_FEATURE)
result = xmpp.DataForm(typ='result')
result = nbxmpp.DataForm(typ='result')
result.addChild(node=xmpp.DataField(name='FORM_TYPE',
result.addChild(node=nbxmpp.DataField(name='FORM_TYPE',
value='urn:xmpp:ssn'))
result.addChild(node=xmpp.DataField(name='accept', value='1'))
result.addChild(node=nbxmpp.DataField(name='accept', value='1'))
feature.addChild(node=result)
@ -346,7 +349,7 @@ class EncryptedStanzaSession(ArchivingStanzaSession):
def _is_buggy_gajim(self):
c = self._get_contact()
if c and c.supports(xmpp.NS_ROSTERX):
if c and c.supports(nbxmpp.NS_ROSTERX):
return False
return True
@ -429,7 +432,7 @@ class EncryptedStanzaSession(ArchivingStanzaSession):
return stanza
def is_xep_200_encrypted(self, msg):
msg.getTag('c', namespace=xmpp.NS_STANZA_CRYPTO)
msg.getTag('c', namespace=nbxmpp.NS_STANZA_CRYPTO)
def hmac(self, key, content):
return HMAC(key, content, self.hash_alg).digest()
@ -485,7 +488,7 @@ class EncryptedStanzaSession(ArchivingStanzaSession):
plaintext = self.decompress(m_compressed)
try:
parsed = xmpp.Node(node='<node>' + plaintext + '</node>')
parsed = nbxmpp.Node(node='<node>' + plaintext + '</node>')
except Exception:
raise DecryptionError('decrypted <data/> not parseable as XML')
@ -519,7 +522,7 @@ class EncryptedStanzaSession(ArchivingStanzaSession):
def c7lize_mac_id(self, form):
kids = form.getChildren()
macable = [x for x in kids if x.getVar() not in ('mac', 'identity')]
return ''.join(xmpp.c14n.c14n(el, self._is_buggy_gajim()) for el in \
return ''.join(nbxmpp.c14n.c14n(el, self._is_buggy_gajim()) for el in \
macable)
def verify_identity(self, form, dh_i, sigmai, i_o):
@ -539,7 +542,7 @@ class EncryptedStanzaSession(ArchivingStanzaSession):
if self.negotiated['recv_pubkey']:
plaintext = self.decrypt(id_o)
parsed = xmpp.Node(node='<node>' + plaintext + '</node>')
parsed = nbxmpp.Node(node='<node>' + plaintext + '</node>')
if self.negotiated['recv_pubkey'] == 'hash':
# fingerprint = parsed.getTagData('fingerprint')
@ -553,7 +556,7 @@ class EncryptedStanzaSession(ArchivingStanzaSession):
keyvalue.getTagData(x))) for x in ('Modulus', 'Exponent'))
eir_pubkey = RSA.construct((n, long(e)))
pubkey_o = xmpp.c14n.c14n(keyvalue, self._is_buggy_gajim())
pubkey_o = nbxmpp.c14n.c14n(keyvalue, self._is_buggy_gajim())
else:
# FIXME DSA, etc.
raise NotImplementedError()
@ -595,20 +598,20 @@ class EncryptedStanzaSession(ArchivingStanzaSession):
fields = (pubkey.n, pubkey.e)
cb_fields = [base64.b64encode(crypto.encode_mpi(f)) for f in
fields]
fields]
pubkey_s = '<RSAKeyValue xmlns="http://www.w3.org/2000/09/xmldsig#"'
'><Modulus>%s</Modulus><Exponent>%s</Exponent></RSAKeyValue>' % \
tuple(cb_fields)
tuple(cb_fields)
else:
pubkey_s = ''
form_s2 = ''.join(xmpp.c14n.c14n(el, self._is_buggy_gajim()) for el in \
form.getChildren())
form_s2 = ''.join(nbxmpp.c14n.c14n(el, self._is_buggy_gajim()) for el \
in form.getChildren())
old_c_s = self.c_s
content = self.n_o + self.n_s + crypto.encode_mpi(dh_i) + pubkey_s + \
self.form_s + form_s2
self.form_s + form_s2
mac_s = self.hmac(self.ks_s, content)
@ -637,76 +640,76 @@ class EncryptedStanzaSession(ArchivingStanzaSession):
# FIXME save retained secret?
self.check_identity(tuple)
return (xmpp.DataField(name='identity', value=base64.b64encode(id_s)),
xmpp.DataField(name='mac', value=base64.b64encode(m_s)))
return (nbxmpp.DataField(name='identity', value=base64.b64encode(id_s)),
nbxmpp.DataField(name='mac', value=base64.b64encode(m_s)))
def negotiate_e2e(self, sigmai):
self.negotiated = {}
request = xmpp.Message()
request = nbxmpp.Message()
feature = request.NT.feature
feature.setNamespace(xmpp.NS_FEATURE)
feature.setNamespace(nbxmpp.NS_FEATURE)
x = xmpp.DataForm(typ='form')
x = nbxmpp.DataForm(typ='form')
x.addChild(node=xmpp.DataField(name='FORM_TYPE', value='urn:xmpp:ssn',
typ='hidden'))
x.addChild(node=xmpp.DataField(name='accept', value='1', typ='boolean',
required=True))
x.addChild(node=nbxmpp.DataField(name='FORM_TYPE', value='urn:xmpp:ssn',
typ='hidden'))
x.addChild(node=nbxmpp.DataField(name='accept', value='1',
typ='boolean', required=True))
# this field is incorrectly called 'otr' in XEPs 0116 and 0217
x.addChild(node=xmpp.DataField(name='logging', typ='list-single',
options=self.logging_preference(), required=True))
x.addChild(node=nbxmpp.DataField(name='logging', typ='list-single',
options=self.logging_preference(), required=True))
# unsupported options: 'disabled', 'enabled'
x.addChild(node=xmpp.DataField(name='disclosure', typ='list-single',
options=['never'], required=True))
x.addChild(node=xmpp.DataField(name='security', typ='list-single',
options=['e2e'], required=True))
x.addChild(node=xmpp.DataField(name='crypt_algs', value='aes128-ctr',
typ='hidden'))
x.addChild(node=xmpp.DataField(name='hash_algs', value='sha256',
typ='hidden'))
x.addChild(node=xmpp.DataField(name='compress', value='none',
typ='hidden'))
x.addChild(node=nbxmpp.DataField(name='disclosure', typ='list-single',
options=['never'], required=True))
x.addChild(node=nbxmpp.DataField(name='security', typ='list-single',
options=['e2e'], required=True))
x.addChild(node=nbxmpp.DataField(name='crypt_algs', value='aes128-ctr',
typ='hidden'))
x.addChild(node=nbxmpp.DataField(name='hash_algs', value='sha256',
typ='hidden'))
x.addChild(node=nbxmpp.DataField(name='compress', value='none',
typ='hidden'))
# unsupported options: 'iq', 'presence'
x.addChild(node=xmpp.DataField(name='stanzas', typ='list-multi',
options=['message']))
x.addChild(node=nbxmpp.DataField(name='stanzas', typ='list-multi',
options=['message']))
x.addChild(node=xmpp.DataField(name='init_pubkey', options=['none', 'key',
'hash'], typ='list-single'))
x.addChild(node=nbxmpp.DataField(name='init_pubkey', options=['none',
'key', 'hash'], typ='list-single'))
# FIXME store key, use hash
x.addChild(node=xmpp.DataField(name='resp_pubkey', options=['none',
'key'], typ='list-single'))
x.addChild(node=nbxmpp.DataField(name='resp_pubkey', options=['none',
'key'], typ='list-single'))
x.addChild(node=xmpp.DataField(name='ver', value='1.0', typ='hidden'))
x.addChild(node=nbxmpp.DataField(name='ver', value='1.0', typ='hidden'))
x.addChild(node=xmpp.DataField(name='rekey_freq', value='4294967295',
typ='hidden'))
x.addChild(node=nbxmpp.DataField(name='rekey_freq', value='4294967295',
typ='hidden'))
x.addChild(node=xmpp.DataField(name='sas_algs', value='sas28x5',
typ='hidden'))
x.addChild(node=xmpp.DataField(name='sign_algs',
value='http://www.w3.org/2000/09/xmldsig#rsa-sha256', typ='hidden'))
x.addChild(node=nbxmpp.DataField(name='sas_algs', value='sas28x5',
typ='hidden'))
x.addChild(node=nbxmpp.DataField(name='sign_algs',
value='http://www.w3.org/2000/09/xmldsig#rsa-sha256', typ='hidden'))
self.n_s = crypto.generate_nonce()
x.addChild(node=xmpp.DataField(name='my_nonce',
value=base64.b64encode(self.n_s), typ='hidden'))
x.addChild(node=nbxmpp.DataField(name='my_nonce',
value=base64.b64encode(self.n_s), typ='hidden'))
modp_options = [ int(g) for g in gajim.config.get('esession_modp').split(
',') ]
',') ]
x.addChild(node=xmpp.DataField(name='modp', typ='list-single',
options=[[None, y] for y in modp_options]))
x.addChild(node=nbxmpp.DataField(name='modp', typ='list-single',
options=[[None, y] for y in modp_options]))
x.addChild(node=self.make_dhfield(modp_options, sigmai))
self.sigmai = sigmai
self.form_s = ''.join(xmpp.c14n.c14n(el, self._is_buggy_gajim()) for el \
in x.getChildren())
self.form_s = ''.join(nbxmpp.c14n.c14n(el, self._is_buggy_gajim()) for \
el in x.getChildren())
feature.addChild(node=x)
@ -789,19 +792,21 @@ class EncryptedStanzaSession(ArchivingStanzaSession):
"""
4.3 esession response (bob)
"""
response = xmpp.Message()
response = nbxmpp.Message()
feature = response.NT.feature
feature.setNamespace(xmpp.NS_FEATURE)
feature.setNamespace(nbxmpp.NS_FEATURE)
x = xmpp.DataForm(typ='submit')
x = nbxmpp.DataForm(typ='submit')
x.addChild(node=xmpp.DataField(name='FORM_TYPE', value='urn:xmpp:ssn'))
x.addChild(node=xmpp.DataField(name='accept', value='true'))
x.addChild(node=nbxmpp.DataField(name='FORM_TYPE',
value='urn:xmpp:ssn'))
x.addChild(node=nbxmpp.DataField(name='accept', value='true'))
for name in negotiated:
# some fields are internal and should not be sent
if not name in ('send_pubkey', 'recv_pubkey'):
x.addChild(node=xmpp.DataField(name=name, value=negotiated[name]))
x.addChild(node=nbxmpp.DataField(name=name,
value=negotiated[name]))
self.negotiated = negotiated
@ -837,24 +842,24 @@ class EncryptedStanzaSession(ArchivingStanzaSession):
for name in to_add:
b64ed = base64.b64encode(to_add[name])
x.addChild(node=xmpp.DataField(name=name, value=b64ed))
x.addChild(node=nbxmpp.DataField(name=name, value=b64ed))
self.form_o = ''.join(xmpp.c14n.c14n(el, self._is_buggy_gajim()) for el \
in form.getChildren())
self.form_s = ''.join(xmpp.c14n.c14n(el, self._is_buggy_gajim()) for el \
in x.getChildren())
self.form_o = ''.join(nbxmpp.c14n.c14n(el, self._is_buggy_gajim()) for \
el in form.getChildren())
self.form_s = ''.join(nbxmpp.c14n.c14n(el, self._is_buggy_gajim()) for \
el in x.getChildren())
self.status = 'responded-e2e'
feature.addChild(node=x)
if not_acceptable:
response = xmpp.Error(response, xmpp.ERR_NOT_ACCEPTABLE)
response = nbxmpp.Error(response, nbxmpp.ERR_NOT_ACCEPTABLE)
feature = xmpp.Node(xmpp.NS_FEATURE + ' feature')
feature = nbxmpp.Node(nbxmpp.NS_FEATURE + ' feature')
for f in not_acceptable:
n = xmpp.Node('field')
n = nbxmpp.Node('field')
n['var'] = f
feature.addChild(node=n)
@ -904,11 +909,11 @@ class EncryptedStanzaSession(ArchivingStanzaSession):
self.negotiated = negotiated
accept = xmpp.Message()
accept = nbxmpp.Message()
feature = accept.NT.feature
feature.setNamespace(xmpp.NS_FEATURE)
feature.setNamespace(nbxmpp.NS_FEATURE)
result = xmpp.DataForm(typ='result')
result = nbxmpp.DataForm(typ='result')
self.c_s = crypto.decode_mpi(base64.b64decode(form['counter']))
self.c_o = self.c_s ^ (2 ** (self.n - 1))
@ -922,10 +927,10 @@ class EncryptedStanzaSession(ArchivingStanzaSession):
self.d = crypto.decode_mpi(base64.b64decode(form['dhkeys']))
self.k = self.get_shared_secret(self.d, x, p)
result.addChild(node=xmpp.DataField(name='FORM_TYPE',
result.addChild(node=nbxmpp.DataField(name='FORM_TYPE',
value='urn:xmpp:ssn'))
result.addChild(node=xmpp.DataField(name='accept', value='1'))
result.addChild(node=xmpp.DataField(name='nonce',
result.addChild(node=nbxmpp.DataField(name='accept', value='1'))
result.addChild(node=nbxmpp.DataField(name='nonce',
value=base64.b64encode(self.n_o)))
self.kc_s, self.km_s, self.ks_s = self.generate_initiator_keys(self.k)
@ -944,12 +949,13 @@ class EncryptedStanzaSession(ArchivingStanzaSession):
rshashes.append(crypto.random_bytes(rshash_size))
rshashes = [base64.b64encode(rshash) for rshash in rshashes]
result.addChild(node=xmpp.DataField(name='rshashes', value=rshashes))
result.addChild(node=xmpp.DataField(name='dhkeys',
value=base64.b64encode(crypto.encode_mpi(e))))
result.addChild(node=nbxmpp.DataField(name='rshashes',
value=rshashes))
result.addChild(node=nbxmpp.DataField(name='dhkeys',
value=base64.b64encode(crypto.encode_mpi(e))))
self.form_o = ''.join(xmpp.c14n.c14n(el, self._is_buggy_gajim()) for \
el in form.getChildren())
self.form_o = ''.join(nbxmpp.c14n.c14n(el, self._is_buggy_gajim()) \
for el in form.getChildren())
# MUST securely destroy K unless it will be used later to generate the
# final shared secret
@ -970,12 +976,12 @@ class EncryptedStanzaSession(ArchivingStanzaSession):
"""
4.5 esession accept (bob)
"""
response = xmpp.Message()
response = nbxmpp.Message()
init = response.NT.init
init.setNamespace(xmpp.NS_ESESSION_INIT)
init.setNamespace(nbxmpp.NS_ESESSION_INIT)
x = xmpp.DataForm(typ='result')
x = nbxmpp.DataForm(typ='result')
for field in ('nonce', 'dhkeys', 'rshashes', 'identity', 'mac'):
# FIXME: will do nothing in real world...
@ -1024,11 +1030,12 @@ class EncryptedStanzaSession(ArchivingStanzaSession):
else:
srshash = crypto.random_bytes(32)
x.addChild(node=xmpp.DataField(name='FORM_TYPE', value='urn:xmpp:ssn'))
x.addChild(node=xmpp.DataField(name='nonce', value=base64.b64encode(
self.n_o)))
x.addChild(node=xmpp.DataField(name='srshash', value=base64.b64encode(
srshash)))
x.addChild(node=nbxmpp.DataField(name='FORM_TYPE',
value='urn:xmpp:ssn'))
x.addChild(node=nbxmpp.DataField(name='nonce', value=base64.b64encode(
self.n_o)))
x.addChild(node=nbxmpp.DataField(name='srshash', value=base64.b64encode(
srshash)))
for datafield in self.make_identity(x, self.d):
x.addChild(node=datafield)
@ -1151,7 +1158,7 @@ class EncryptedStanzaSession(ArchivingStanzaSession):
dhs.append(base64.b64encode(He))
name = 'dhhashes'
return xmpp.DataField(name=name, typ='hidden', value=dhs)
return nbxmpp.DataField(name=name, typ='hidden', value=dhs)
def terminate_e2e(self):
self.enable_encryption = False
@ -1170,14 +1177,14 @@ class EncryptedStanzaSession(ArchivingStanzaSession):
If fields is None, the remote party has given us a bad cryptographic
value of some kind. Otherwise, list the fields we haven't implemented.
"""
err = xmpp.Error(xmpp.Message(), xmpp.ERR_FEATURE_NOT_IMPLEMENTED)
err = nbxmpp.Error(nbxmpp.Message(), nbxmpp.ERR_FEATURE_NOT_IMPLEMENTED)
err.T.error.T.text.setData(reason)
if fields:
feature = xmpp.Node(xmpp.NS_FEATURE + ' feature')
feature = nbxmpp.Node(nbxmpp.NS_FEATURE + ' feature')
for field in fields:
fn = xmpp.Node('field')
fn = nbxmpp.Node('field')
fn['var'] = field
feature.addChild(node=feature)

View File

@ -1,18 +0,0 @@
# $Id: __init__.py,v 1.9 2005/03/07 09:34:51 snakeru Exp $
"""
Gajim maintains a fork of the xmpppy jabber python library. Most of the code is
inherited but has been extended by implementation of non-blocking transports
and new features like BOSH.
Most of the xmpp classes are ancestors of PlugIn class to share a single set of methods in order to compile a featured and extensible XMPP client.
Thanks and credits to the xmpppy developers. See: http://xmpppy.sourceforge.net/
"""
from protocol import *
import simplexml, protocol, auth_nb, transports_nb, roster_nb
import dispatcher_nb, features_nb, idlequeue, bosh, tls_nb, proxy_connectors
from client_nb import NonBlockingClient
from plugin import PlugIn
from smacks import Smacks

View File

@ -1,724 +0,0 @@
## auth_nb.py
## based on auth.py, changes backported up to revision 1.41
##
## Copyright (C) 2003-2005 Alexey "Snake" Nezhdanov
## modified by Dimitur Kirov <dkirov@gmail.com>
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2, or (at your option)
## any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
"""
Provides plugs for SASL and NON-SASL authentication mechanisms.
Can be used both for client and transport authentication
See client_nb.py
"""
from protocol import NS_SASL, NS_SESSION, NS_STREAMS, NS_BIND, NS_AUTH
from protocol import NS_STREAM_MGMT
from protocol import Node, NodeProcessed, isResultNode, Iq, Protocol, JID
from plugin import PlugIn
from smacks import Smacks
import base64
import random
import itertools
import dispatcher_nb
import hashlib
import hmac
import hashlib
import logging
log = logging.getLogger('gajim.c.x.auth_nb')
def HH(some): return hashlib.md5(some).hexdigest()
def H(some): return hashlib.md5(some).digest()
def C(some): return ':'.join(some)
try:
kerberos = __import__('kerberos')
have_kerberos = True
except ImportError:
have_kerberos = False
GSS_STATE_STEP = 0
GSS_STATE_WRAP = 1
SASL_FAILURE_IN_PROGRESS = 'failure-in-process'
SASL_FAILURE = 'failure'
SASL_SUCCESS = 'success'
SASL_UNSUPPORTED = 'not-supported'
SASL_IN_PROCESS = 'in-process'
def challenge_splitter(data):
"""
Helper function that creates a dict from challenge string
Sample challenge string:
username="example.org",realm="somerealm",\
nonce="OA6MG9tEQGm2hh",cnonce="OA6MHXh6VqTrRk",\
nc=00000001,qop="auth,auth-int,auth-conf",charset=utf-8
Expected result for challan:
dict['qop'] = ('auth','auth-int','auth-conf')
dict['realm'] = 'somerealm'
"""
X_KEYWORD, X_VALUE, X_END = 0, 1, 2
quotes_open = False
keyword, value = '', ''
dict_ = {}
arr = None
expecting = X_KEYWORD
for iter_ in range(len(data) + 1):
end = False
if iter_ == len(data):
expecting = X_END
end = True
else:
char = data[iter_]
if expecting == X_KEYWORD:
if char == '=':
expecting = X_VALUE
elif char in (',', ' ', '\t'):
pass
else:
keyword = '%s%c' % (keyword, char)
elif expecting == X_VALUE:
if char == '"':
if quotes_open:
end = True
else:
quotes_open = True
elif char in (',', ' ', '\t'):
if quotes_open:
if not arr:
arr = [value]
else:
arr.append(value)
value = ""
else:
end = True
else:
value = '%s%c' % (value, char)
if end:
if arr:
arr.append(value)
dict_[keyword] = arr
arr = None
else:
dict_[keyword] = value
value, keyword = '', ''
expecting = X_KEYWORD
quotes_open = False
return dict_
def scram_parse(chatter):
return dict(s.split('=', 1) for s in chatter.split(','))
class SASL(PlugIn):
"""
Implements SASL authentication. Can be plugged into NonBlockingClient
to start authentication
"""
def __init__(self, username, password, on_sasl):
"""
:param user: XMPP username
:param password: XMPP password
:param on_sasl: Callback, will be called after each SASL auth-step.
"""
PlugIn.__init__(self)
self.username = username
self.password = password
self.on_sasl = on_sasl
self.realm = None
def plugin(self, owner):
if 'version' not in self._owner.Dispatcher.Stream._document_attrs:
self.startsasl = SASL_UNSUPPORTED
elif self._owner.Dispatcher.Stream.features:
try:
self.FeaturesHandler(self._owner.Dispatcher,
self._owner.Dispatcher.Stream.features)
except NodeProcessed:
pass
else:
self.startsasl = None
def plugout(self):
"""
Remove SASL handlers from owner's dispatcher. Used internally
"""
if 'features' in self._owner.__dict__:
self._owner.UnregisterHandler('features', self.FeaturesHandler,
xmlns=NS_STREAMS)
if 'challenge' in self._owner.__dict__:
self._owner.UnregisterHandler('challenge', self.SASLHandler,
xmlns=NS_SASL)
if 'failure' in self._owner.__dict__:
self._owner.UnregisterHandler('failure', self.SASLHandler,
xmlns=NS_SASL)
if 'success' in self._owner.__dict__:
self._owner.UnregisterHandler('success', self.SASLHandler,
xmlns=NS_SASL)
def auth(self):
"""
Start authentication. Result can be obtained via "SASL.startsasl"
attribute and will be either SASL_SUCCESS or SASL_FAILURE
Note that successfull auth will take at least two Dispatcher.Process()
calls.
"""
if self.startsasl:
pass
elif self._owner.Dispatcher.Stream.features:
try:
self.FeaturesHandler(self._owner.Dispatcher,
self._owner.Dispatcher.Stream.features)
except NodeProcessed:
pass
else:
self._owner.RegisterHandler('features',
self.FeaturesHandler, xmlns=NS_STREAMS)
def FeaturesHandler(self, conn, feats):
"""
Used to determine if server supports SASL auth. Used internally
"""
if not feats.getTag('mechanisms', namespace=NS_SASL):
self.startsasl='not-supported'
log.info('SASL not supported by server')
return
self.mecs = []
for mec in feats.getTag('mechanisms', namespace=NS_SASL).getTags(
'mechanism'):
self.mecs.append(mec.getData())
self._owner.RegisterHandler('challenge', self.SASLHandler,
xmlns=NS_SASL)
self._owner.RegisterHandler('failure', self.SASLHandler, xmlns=NS_SASL)
self._owner.RegisterHandler('success', self.SASLHandler, xmlns=NS_SASL)
self.MechanismHandler()
def MechanismHandler(self):
if 'ANONYMOUS' in self.mecs and self.username is None:
self.mecs.remove('ANONYMOUS')
node = Node('auth', attrs={'xmlns': NS_SASL,
'mechanism': 'ANONYMOUS'})
self.mechanism = 'ANONYMOUS'
self.startsasl = SASL_IN_PROCESS
self._owner.send(str(node))
raise NodeProcessed
if "EXTERNAL" in self.mecs:
self.mecs.remove('EXTERNAL')
sasl_data = u'%s@%s' % (self.username, self._owner.Server)
sasl_data = sasl_data.encode('utf-8').encode('base64').replace(
'\n', '')
node = Node('auth', attrs={'xmlns': NS_SASL,
'mechanism': 'EXTERNAL'}, payload=[sasl_data])
self.mechanism = 'EXTERNAL'
self.startsasl = SASL_IN_PROCESS
self._owner.send(str(node))
raise NodeProcessed
if 'GSSAPI' in self.mecs and have_kerberos:
self.mecs.remove('GSSAPI')
try:
self.gss_vc = kerberos.authGSSClientInit('xmpp@' + \
self._owner.xmpp_hostname)[1]
kerberos.authGSSClientStep(self.gss_vc, '')
response = kerberos.authGSSClientResponse(self.gss_vc)
node=Node('auth', attrs={'xmlns': NS_SASL,
'mechanism': 'GSSAPI'}, payload=(response or ''))
self.mechanism = 'GSSAPI'
self.gss_step = GSS_STATE_STEP
self.startsasl = SASL_IN_PROCESS
self._owner.send(str(node))
raise NodeProcessed
except kerberos.GSSError, e:
log.info('GSSAPI authentication failed: %s' % str(e))
if 'SCRAM-SHA-1' in self.mecs:
self.mecs.remove('SCRAM-SHA-1')
self.mechanism = 'SCRAM-SHA-1'
self._owner._caller.get_password(self.set_password, self.mechanism)
self.scram_step = 0
self.startsasl = SASL_IN_PROCESS
raise NodeProcessed
if 'DIGEST-MD5' in self.mecs:
self.mecs.remove('DIGEST-MD5')
node = Node('auth', attrs={'xmlns': NS_SASL,
'mechanism': 'DIGEST-MD5'})
self.mechanism = 'DIGEST-MD5'
self.startsasl = SASL_IN_PROCESS
self._owner.send(str(node))
raise NodeProcessed
if 'PLAIN' in self.mecs:
self.mecs.remove('PLAIN')
self.mechanism = 'PLAIN'
self._owner._caller.get_password(self.set_password, self.mechanism)
self.startsasl = SASL_IN_PROCESS
raise NodeProcessed
if 'X-MESSENGER-OAUTH2' in self.mecs:
self.mecs.remove('X-MESSENGER-OAUTH2')
self.mechanism = 'X-MESSENGER-OAUTH2'
self._owner._caller.get_password(self.set_password, self.mechanism)
self.startsasl = SASL_IN_PROCESS
raise NodeProcessed
self.startsasl = SASL_FAILURE
log.info('I can only use EXTERNAL, SCRAM-SHA-1, DIGEST-MD5, GSSAPI and '
'PLAIN mecanisms.')
if self.on_sasl:
self.on_sasl()
return
def SASLHandler(self, conn, challenge):
"""
Perform next SASL auth step. Used internally
"""
if challenge.getNamespace() != NS_SASL:
return
def scram_base64(s):
return ''.join(s.encode('base64').split('\n'))
incoming_data = challenge.getData()
data=base64.decodestring(incoming_data)
### Handle Auth result
def on_auth_fail(reason):
log.info('Failed SASL authentification: %s' % reason)
self._owner.send(str(Node('abort', attrs={'xmlns': NS_SASL})))
if len(self.mecs) > 0:
# There are other mechanisms to test, but wait for <failure>
# answer from server
self.startsasl = SASL_FAILURE_IN_PROGRESS
raise NodeProcessed
if self.on_sasl:
self.on_sasl()
raise NodeProcessed
if challenge.getName() == 'failure':
if self.startsasl == SASL_FAILURE_IN_PROGRESS:
self.MechanismHandler()
raise NodeProcessed
self.startsasl = SASL_FAILURE
try:
reason = challenge.getChildren()[0]
except Exception:
reason = challenge
on_auth_fail(reason)
elif challenge.getName() == 'success':
if self.mechanism == 'SCRAM-SHA-1':
# check data-with-success
data = scram_parse(data)
if data['v'] != scram_base64(self.scram_ServerSignature):
on_auth_fail('ServerSignature is wrong')
self.startsasl = SASL_SUCCESS
log.info('Successfully authenticated with remote server.')
handlers = self._owner.Dispatcher.dumpHandlers()
# Bosh specific dispatcher replugging
# save old features. They will be used in case we won't get response
# on stream restart after SASL auth (happens with XMPP over BOSH
# with Openfire)
old_features = self._owner.Dispatcher.Stream.features
self._owner.Dispatcher.PlugOut()
dispatcher_nb.Dispatcher.get_instance().PlugIn(self._owner,
after_SASL=True, old_features=old_features)
self._owner.Dispatcher.restoreHandlers(handlers)
self._owner.User = self.username
if self.on_sasl:
self.on_sasl()
raise NodeProcessed
### Perform auth step
log.info('Got challenge:' + data)
if self.mechanism == 'GSSAPI':
if self.gss_step == GSS_STATE_STEP:
rc = kerberos.authGSSClientStep(self.gss_vc, incoming_data)
if rc != kerberos.AUTH_GSS_CONTINUE:
self.gss_step = GSS_STATE_WRAP
elif self.gss_step == GSS_STATE_WRAP:
rc = kerberos.authGSSClientUnwrap(self.gss_vc, incoming_data)
response = kerberos.authGSSClientResponse(self.gss_vc)
rc = kerberos.authGSSClientWrap(self.gss_vc, response,
kerberos.authGSSClientUserName(self.gss_vc))
response = kerberos.authGSSClientResponse(self.gss_vc)
if not response:
response = ''
self._owner.send(Node('response', attrs={'xmlns': NS_SASL},
payload=response).__str__())
raise NodeProcessed
if self.mechanism == 'SCRAM-SHA-1':
hashfn = hashlib.sha1
def HMAC(k, s):
return hmac.HMAC(key=k, msg=s, digestmod=hashfn).digest()
def XOR(x, y):
r = (chr(ord(px) ^ ord(py)) for px, py in zip(x, y))
return ''.join(r)
def Hi(s, salt, iters):
ii = 1
try:
s = s.encode('utf-8')
except:
pass
ui_1 = HMAC(s, salt + '\0\0\0\01')
ui = ui_1
for i in range(iters - 1):
ii += 1
ui_1 = HMAC(s, ui_1)
ui = XOR(ui, ui_1)
return ui
def scram_H(s):
return hashfn(s).digest()
if self.scram_step == 0:
self.scram_step = 1
self.scram_soup += ',' + data + ','
data = scram_parse(data)
# TODO: Should check cnonce here.
# TODO: Channel binding data goes in here too.
r = 'c=' + scram_base64(self.scram_gs2)
r += ',r=' + data['r']
self.scram_soup += r
salt = data['s'].decode('base64')
iter = int(data['i'])
SaltedPassword = Hi(self.password, salt, iter)
# TODO: Could cache this, along with salt+iter.
ClientKey = HMAC(SaltedPassword, 'Client Key')
StoredKey = scram_H(ClientKey)
ClientSignature = HMAC(StoredKey, self.scram_soup)
ClientProof = XOR(ClientKey, ClientSignature)
r += ',p=' + scram_base64(ClientProof)
ServerKey = HMAC(SaltedPassword, 'Server Key')
self.scram_ServerSignature = HMAC(ServerKey, self.scram_soup)
sasl_data = scram_base64(r)
node = Node('response', attrs={'xmlns': NS_SASL},
payload=[sasl_data])
self._owner.send(str(node))
raise NodeProcessed
if self.scram_step == 1:
data = scram_parse(data)
if data['v'].decode('base64') != self.scram_ServerSignature:
# TODO: Not clear what to do here - need to abort.
raise Exception
node = Node('response', attrs={'xmlns': NS_SASL});
self._owner.send(str(node))
raise NodeProcessed
# magic foo...
chal = challenge_splitter(data)
if not self.realm and 'realm' in chal:
self.realm = chal['realm']
if 'qop' in chal and ((isinstance(chal['qop'], str) and \
chal['qop'] =='auth') or (isinstance(chal['qop'], list) and 'auth' in \
chal['qop'])):
self.resp = {}
self.resp['username'] = self.username
if self.realm:
self.resp['realm'] = self.realm
else:
self.resp['realm'] = self._owner.Server
self.resp['nonce'] = chal['nonce']
self.resp['cnonce'] = ''.join("%x" % randint(0, 2**28) for randint \
in itertools.repeat(random.randint, 7))
self.resp['nc'] = ('00000001')
self.resp['qop'] = 'auth'
self.resp['digest-uri'] = 'xmpp/' + self._owner.Server
self.resp['charset'] = 'utf-8'
# Password is now required
self._owner._caller.get_password(self.set_password, self.mechanism)
elif 'rspauth' in chal:
# Check rspauth value
if chal['rspauth'] != self.digest_rspauth:
on_auth_fail('rspauth is wrong')
self._owner.send(str(Node('response', attrs={'xmlns':NS_SASL})))
else:
self.startsasl = SASL_FAILURE
log.info('Failed SASL authentification: unknown challenge')
if self.on_sasl:
self.on_sasl()
raise NodeProcessed
@staticmethod
def _convert_to_iso88591(string):
try:
string = string.decode('utf-8').encode('iso-8859-1')
except UnicodeEncodeError:
pass
return string
def set_password(self, password):
self.password = '' if password is None else password
if self.mechanism == 'SCRAM-SHA-1':
nonce = ''.join('%x' % randint(0, 2 ** 28) for randint in \
itertools.repeat(random.randint, 7))
self.scram_soup = 'n=' + self.username + ',r=' + nonce
self.scram_gs2 = 'n,,' # No CB yet.
sasl_data = (self.scram_gs2 + self.scram_soup).encode('base64').\
replace('\n', '')
node = Node('auth', attrs={'xmlns': NS_SASL,
'mechanism': self.mechanism}, payload=[sasl_data])
elif self.mechanism == 'DIGEST-MD5':
hash_username = self._convert_to_iso88591(self.resp['username'])
hash_realm = self._convert_to_iso88591(self.resp['realm'])
hash_password = self._convert_to_iso88591(self.password)
A1 = C([H(C([hash_username, hash_realm, hash_password])),
self.resp['nonce'], self.resp['cnonce']])
A2 = C(['AUTHENTICATE', self.resp['digest-uri']])
response = HH(C([HH(A1), self.resp['nonce'], self.resp['nc'],
self.resp['cnonce'], self.resp['qop'], HH(A2)]))
A2 = C(['', self.resp['digest-uri']])
self.digest_rspauth = HH(C([HH(A1), self.resp['nonce'],
self.resp['nc'], self.resp['cnonce'], self.resp['qop'],
HH(A2)]))
self.resp['response'] = response
sasl_data = u''
for key in ('charset', 'username', 'realm', 'nonce', 'nc', 'cnonce',
'digest-uri', 'response', 'qop'):
if key in ('nc', 'qop', 'response', 'charset'):
sasl_data += u"%s=%s," % (key, self.resp[key])
else:
sasl_data += u'%s="%s",' % (key, self.resp[key])
sasl_data = sasl_data[:-1].encode('utf-8').encode('base64').replace(
'\r', '').replace('\n', '')
node = Node('response', attrs={'xmlns': NS_SASL},
payload=[sasl_data])
elif self.mechanism == 'PLAIN':
sasl_data = u'\x00%s\x00%s' % (self.username, self.password)
sasl_data = sasl_data.encode('utf-8').encode('base64').replace(
'\n', '')
node = Node('auth', attrs={'xmlns': NS_SASL, 'mechanism': 'PLAIN'},
payload=[sasl_data])
elif self.mechanism == 'X-MESSENGER-OAUTH2':
node = Node('auth', attrs={'xmlns': NS_SASL,
'mechanism': 'X-MESSENGER-OAUTH2'})
node.addData(password)
self._owner.send(str(node))
class NonBlockingNonSASL(PlugIn):
"""
Implements old Non-SASL (JEP-0078) authentication used in jabberd1.4 and
transport authentication
"""
def __init__(self, user, password, resource, on_auth):
"""
Caches username, password and resource for auth
"""
PlugIn.__init__(self)
self.user = user
if password is None:
self.password = ''
else:
self.password = password
self.resource = resource
self.on_auth = on_auth
def plugin(self, owner):
"""
Determine the best auth method (digest/0k/plain) and use it for auth.
Returns used method name on success. Used internally
"""
log.info('Querying server about possible auth methods')
self.owner = owner
owner.Dispatcher.SendAndWaitForResponse(
Iq('get', NS_AUTH, payload=[Node('username', payload=[self.user])]),
func=self._on_username)
def _on_username(self, resp):
if not isResultNode(resp):
log.info('No result node arrived! Aborting...')
return self.on_auth(None)
iq=Iq(typ='set', node=resp)
query = iq.getTag('query')
query.setTagData('username', self.user)
query.setTagData('resource', self.resource)
if query.getTag('digest'):
log.info("Performing digest authentication")
query.setTagData('digest',
hashlib.sha1(self.owner.Dispatcher.Stream._document_attrs['id']
+ self.password).hexdigest())
if query.getTag('password'):
query.delChild('password')
self._method = 'digest'
elif query.getTag('token'):
token = query.getTagData('token')
seq = query.getTagData('sequence')
log.info("Performing zero-k authentication")
def hasher(s):
return hashlib.sha1(s).hexdigest()
def hash_n_times(s, count):
return count and hasher(hash_n_times(s, count-1)) or s
hash_ = hash_n_times(hasher(hasher(self.password) + token),
int(seq))
query.setTagData('hash', hash_)
self._method='0k'
else:
log.warn("Secure methods unsupported, performing plain text \
authentication")
self._method = 'plain'
self._owner._caller.get_password(self._on_password, self._method)
return
resp = self.owner.Dispatcher.SendAndWaitForResponse(iq,
func=self._on_auth)
def _on_password(self, password):
self.password = '' if password is None else password
iq=Iq('set', NS_AUTH)
query = iq.getTag('query')
query.setTagData('username', self.user)
query.setTagData('resource', self.resource)
query.setTagData('password', self.password)
resp = self.owner.Dispatcher.SendAndWaitForResponse(iq,
func=self._on_auth)
def _on_auth(self, resp):
if isResultNode(resp):
log.info('Sucessfully authenticated with remote host.')
self.owner.User = self.user
self.owner.Resource = self.resource
self.owner._registered_name = self.owner.User + '@' + \
self.owner.Server+ '/' + self.owner.Resource
return self.on_auth(self._method)
log.info('Authentication failed!')
return self.on_auth(None)
class NonBlockingBind(PlugIn):
"""
Bind some JID to the current connection to allow router know of our
location. Must be plugged after successful SASL auth
"""
def __init__(self):
PlugIn.__init__(self)
self.bound = None
self.supports_sm = False
self.resuming = False
def plugin(self, owner):
''' Start resource binding, if allowed at this time. Used internally. '''
if self._owner.Dispatcher.Stream.features:
try:
self.FeaturesHandler(self._owner.Dispatcher,
self._owner.Dispatcher.Stream.features)
except NodeProcessed:
pass
else:
self._owner.RegisterHandler('features', self.FeaturesHandler,
xmlns=NS_STREAMS)
def FeaturesHandler(self, conn, feats):
"""
Determine if server supports resource binding and set some internal
attributes accordingly.
It also checks if server supports stream management
"""
if feats.getTag('sm', namespace=NS_STREAM_MGMT):
self.supports_sm = True # server supports stream management
if self.resuming:
self._owner._caller.sm.resume_request()
if not feats.getTag('bind', namespace=NS_BIND):
log.info('Server does not requested binding.')
# we try to bind resource anyway
#self.bound='failure'
self.bound = []
return
if feats.getTag('session', namespace=NS_SESSION):
self.session = 1
else:
self.session = -1
self.bound = []
def plugout(self):
"""
Remove Bind handler from owner's dispatcher. Used internally
"""
self._owner.UnregisterHandler('features', self.FeaturesHandler,
xmlns=NS_STREAMS)
def NonBlockingBind(self, resource=None, on_bound=None):
"""
Perform binding. Use provided resource name or random (if not provided).
"""
if self.resuming: # We don't bind if we resume the stream
return
self.on_bound = on_bound
self._resource = resource
if self._resource:
self._resource = [Node('resource', payload=[self._resource])]
else:
self._resource = []
self._owner.onreceive(None)
self._owner.Dispatcher.SendAndWaitForResponse(
Protocol('iq', typ='set', payload=[Node('bind',
attrs={'xmlns': NS_BIND}, payload=self._resource)]),
func=self._on_bound)
def _on_bound(self, resp):
if isResultNode(resp):
if resp.getTag('bind') and resp.getTag('bind').getTagData('jid'):
self.bound.append(resp.getTag('bind').getTagData('jid'))
log.info('Successfully bound %s.' % self.bound[-1])
jid = JID(resp.getTag('bind').getTagData('jid'))
self._owner.User = jid.getNode()
self._owner.Resource = jid.getResource()
# Only negociate stream management after bounded
sm = self._owner._caller.sm
if self.supports_sm:
# starts negociation
sm.set_owner(self._owner)
sm.negociate()
self._owner.Dispatcher.sm = sm
if hasattr(self, 'session') and self.session == -1:
# Server don't want us to initialize a session
log.info('No session required.')
self.on_bound('ok')
else:
self._owner.SendAndWaitForResponse(Protocol('iq', typ='set',
payload=[Node('session', attrs={'xmlns':NS_SESSION})]),
func=self._on_session)
return
if resp:
log.info('Binding failed: %s.' % resp.getTag('error'))
self.on_bound(None)
else:
log.info('Binding failed: timeout expired.')
self.on_bound(None)
def _on_session(self, resp):
self._owner.onreceive(None)
if isResultNode(resp):
log.info('Successfully opened session.')
self.session = 1
self.on_bound('ok')
else:
log.error('Session open failed.')
self.session = 0
self.on_bound(None)

View File

@ -1,581 +0,0 @@
## bosh.py
##
##
## Copyright (C) 2008 Tomas Karasek <tom.to.the.k@gmail.com>
##
## This file is part of Gajim.
##
## Gajim is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published
## by the Free Software Foundation; version 3 only.
##
## Gajim is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
import locale, random
from hashlib import sha1
from transports_nb import NonBlockingTransport, NonBlockingHTTPBOSH,\
CONNECTED, CONNECTING, DISCONNECTED, DISCONNECTING,\
urisplit, DISCONNECT_TIMEOUT_SECONDS
from protocol import BOSHBody, Protocol, NS_CLIENT
from simplexml import Node
import logging
log = logging.getLogger('gajim.c.x.bosh')
KEY_COUNT = 10
# Fake file descriptor - it's used for setting read_timeout in idlequeue for
# BOSH Transport. In TCP-derived transports this is file descriptor of socket.
FAKE_DESCRIPTOR = -1337
class NonBlockingBOSH(NonBlockingTransport):
def __init__(self, raise_event, on_disconnect, idlequeue, estabilish_tls, certs,
xmpp_server, domain, bosh_dict, proxy_creds):
NonBlockingTransport.__init__(self, raise_event, on_disconnect, idlequeue,
estabilish_tls, certs)
self.bosh_sid = None
if locale.getdefaultlocale()[0]:
self.bosh_xml_lang = locale.getdefaultlocale()[0].split('_')[0]
else:
self.bosh_xml_lang = 'en'
self.http_version = 'HTTP/1.1'
self.http_persistent = True
self.http_pipelining = bosh_dict['bosh_http_pipelining']
self.bosh_to = domain
self.route_host, self.route_port = xmpp_server
self.bosh_wait = bosh_dict['bosh_wait']
if not self.http_pipelining:
self.bosh_hold = 1
else:
self.bosh_hold = bosh_dict['bosh_hold']
self.bosh_requests = self.bosh_hold
self.bosh_uri = bosh_dict['bosh_uri']
self.bosh_content = bosh_dict['bosh_content']
self.over_proxy = bosh_dict['bosh_useproxy']
if estabilish_tls:
self.bosh_secure = 'true'
else:
self.bosh_secure = 'false'
self.use_proxy_auth = bosh_dict['useauth']
self.proxy_creds = proxy_creds
self.wait_cb_time = None
self.http_socks = []
self.stanza_buffer = []
self.prio_bosh_stanzas = []
self.current_recv_handler = None
self.current_recv_socket = None
self.key_stack = None
self.ack_checker = None
self.after_init = False
self.proxy_dict = {}
if self.over_proxy and self.estabilish_tls:
self.proxy_dict['type'] = 'http'
# with SSL over proxy, we do HTTP CONNECT to proxy to open a channel to
# BOSH Connection Manager
host, port = urisplit(self.bosh_uri)[1:3]
self.proxy_dict['xmpp_server'] = (host, port)
self.proxy_dict['credentials'] = self.proxy_creds
def connect(self, conn_5tuple, on_connect, on_connect_failure):
NonBlockingTransport.connect(self, conn_5tuple, on_connect, on_connect_failure)
global FAKE_DESCRIPTOR
FAKE_DESCRIPTOR = FAKE_DESCRIPTOR - 1
self.fd = FAKE_DESCRIPTOR
self.stanza_buffer = []
self.prio_bosh_stanzas = []
self.key_stack = KeyStack(KEY_COUNT)
self.ack_checker = AckChecker()
self.after_init = True
self.http_socks.append(self.get_new_http_socket())
self._tcp_connecting_started()
self.http_socks[0].connect(
conn_5tuple = conn_5tuple,
on_connect = self._on_connect,
on_connect_failure = self._on_connect_failure)
def _on_connect(self):
self.peerhost = self.http_socks[0].peerhost
self.ssl_lib = self.http_socks[0].ssl_lib
NonBlockingTransport._on_connect(self)
def set_timeout(self, timeout):
if self.get_state() != DISCONNECTED and self.fd != -1:
NonBlockingTransport.set_timeout(self, timeout)
else:
log.warn('set_timeout: TIMEOUT NOT SET: state is %s, fd is %s' % (self.get_state(), self.fd))
def on_http_request_possible(self):
"""
Called when HTTP request it's possible to send a HTTP request. It can be when
socket is connected or when HTTP response arrived
There should be always one pending request to BOSH CM.
"""
log.debug('on_http_req possible, state:\n%s' % self.get_current_state())
if self.get_state()==DISCONNECTED: return
#Hack for making the non-secure warning dialog work
if self._owner.got_features:
if (hasattr(self._owner, 'NonBlockingNonSASL') or hasattr(self._owner, 'SASL')):
self.send_BOSH(None)
else:
# If we already got features and no auth module was plugged yet, we are
# probably waiting for confirmation of the "not-secure-connection" dialog.
# We don't send HTTP request in that case.
# see http://lists.jabber.ru/pipermail/ejabberd/2008-August/004027.html
return
else:
self.send_BOSH(None)
def get_socket_in(self, state):
"""
Get sockets in desired state
"""
for s in self.http_socks:
if s.get_state()==state: return s
return None
def get_free_socket(self):
"""
Select and returns socket eligible for sending a data to
"""
if self.http_pipelining:
return self.get_socket_in(CONNECTED)
else:
last_recv_time, tmpsock = 0, None
for s in self.http_socks:
# we're interested only in CONNECTED socket with no requests pending
if s.get_state()==CONNECTED and s.pending_requests==0:
# if there's more of them, we want the one with the least recent data receive
# (lowest last_recv_time)
if (last_recv_time==0) or (s.last_recv_time < last_recv_time):
last_recv_time = s.last_recv_time
tmpsock = s
if tmpsock:
return tmpsock
else:
return None
def send_BOSH(self, payload):
"""
Tries to send a stanza in payload by appeding it to a buffer and plugging a
free socket for writing.
"""
total_pending_reqs = sum([s.pending_requests for s in self.http_socks])
# when called after HTTP response (Payload=None) and when there are already
# some pending requests and no data to send, or when the socket is
# disconnected, we do nothing
if payload is None and \
total_pending_reqs > 0 and \
self.stanza_buffer == [] and \
self.prio_bosh_stanzas == [] or \
self.get_state()==DISCONNECTED:
return
# Add xmlns to stanza to help ejabberd server
if payload and isinstance(payload, Protocol):
if not payload.getNamespace():
payload.setNamespace(NS_CLIENT)
# now the payload is put to buffer and will be sent at some point
self.append_stanza(payload)
# if we're about to make more requests than allowed, we don't send - stanzas will be
# sent after HTTP response from CM, exception is when we're disconnecting - then we
# send anyway
if total_pending_reqs >= self.bosh_requests and self.get_state()!=DISCONNECTING:
log.warn('attemp to make more requests than allowed by Connection Manager:\n%s' %
self.get_current_state())
return
# when there's free CONNECTED socket, we plug it for write and the data will
# be sent when write is possible
if self.get_free_socket():
self.plug_socket()
return
# if there is a connecting socket, we just wait for when it connects,
# payload will be sent in a sec when the socket connects
if self.get_socket_in(CONNECTING): return
# being here means there are either DISCONNECTED sockets or all sockets are
# CONNECTED with too many pending requests
s = self.get_socket_in(DISCONNECTED)
# if we have DISCONNECTED socket, lets connect it and plug for send
if s:
self.connect_and_flush(s)
else:
# otherwise create and connect a new one
ss = self.get_new_http_socket()
self.http_socks.append(ss)
self.connect_and_flush(ss)
return
def plug_socket(self):
stanza = None
s = self.get_free_socket()
if s:
s._plug_idle(writable=True, readable=True)
else:
log.error('=====!!!!!!!!====> Couldn\'t get free socket in plug_socket())')
def build_stanza(self, socket):
"""
Build a BOSH body tag from data in buffers and adds key, rid and ack
attributes to it
This method is called from _do_send() of underlying transport. This is to
ensure rid and keys will be processed in correct order. If I generate
them before plugging a socket for write (and did it for two sockets/HTTP
connections) in parallel, they might be sent in wrong order, which
results in violating the BOSH session and server-side disconnect.
"""
if self.prio_bosh_stanzas:
stanza, add_payload = self.prio_bosh_stanzas.pop(0)
if add_payload:
stanza.setPayload(self.stanza_buffer)
self.stanza_buffer = []
else:
stanza = self.boshify_stanzas(self.stanza_buffer)
self.stanza_buffer = []
stanza = self.ack_checker.backup_stanza(stanza, socket)
key, newkey = self.key_stack.get()
if key:
stanza.setAttr('key', key)
if newkey:
stanza.setAttr('newkey', newkey)
log.info('sending msg with rid=%s to sock %s' % (stanza.getAttr('rid'), id(socket)))
self.renew_bosh_wait_timeout(self.bosh_wait + 3)
return stanza
def on_bosh_wait_timeout(self):
log.error('Connection Manager didn\'t respond within %s + 3 seconds --> forcing disconnect' % self.bosh_wait)
self.disconnect()
def renew_bosh_wait_timeout(self, timeout):
if self.wait_cb_time is not None:
self.remove_bosh_wait_timeout()
sched_time = self.idlequeue.set_alarm(self.on_bosh_wait_timeout, timeout)
self.wait_cb_time = sched_time
def remove_bosh_wait_timeout(self):
self.idlequeue.remove_alarm(
self.on_bosh_wait_timeout,
self.wait_cb_time)
def on_persistent_fallback(self, socket):
"""
Called from underlying transport when server closes TCP connection
:param socket: disconnected transport object
"""
if socket.http_persistent:
log.warn('Fallback to nonpersistent HTTP (no pipelining as well)')
socket.http_persistent = False
self.http_persistent = False
self.http_pipelining = False
socket.disconnect(do_callback=False)
self.connect_and_flush(socket)
else:
socket.disconnect()
def handle_body_attrs(self, stanza_attrs):
"""
Called for each incoming body stanza from dispatcher. Checks body
attributes.
"""
self.remove_bosh_wait_timeout()
if self.after_init:
if stanza_attrs.has_key('sid'):
# session ID should be only in init response
self.bosh_sid = stanza_attrs['sid']
if stanza_attrs.has_key('requests'):
self.bosh_requests = int(stanza_attrs['requests'])
if stanza_attrs.has_key('wait'):
self.bosh_wait = int(stanza_attrs['wait'])
self.after_init = False
ack = None
if stanza_attrs.has_key('ack'):
ack = stanza_attrs['ack']
self.ack_checker.process_incoming_ack(ack=ack,
socket=self.current_recv_socket)
if stanza_attrs.has_key('type'):
if stanza_attrs['type'] in ['terminate', 'terminal']:
condition = 'n/a'
if stanza_attrs.has_key('condition'):
condition = stanza_attrs['condition']
if condition == 'n/a':
log.info('Received sesion-ending terminating stanza')
else:
log.error('Received terminating stanza: %s - %s' % (condition,
bosh_errors[condition]))
self.disconnect()
return
if stanza_attrs['type'] == 'error':
# recoverable error
pass
return
def append_stanza(self, stanza):
"""
Append stanza to a buffer to send
"""
if stanza:
if isinstance(stanza, tuple):
# stanza is tuple of BOSH stanza and bool value for whether to add payload
self.prio_bosh_stanzas.append(stanza)
else:
# stanza is XMPP stanza. Will be boshified before send.
self.stanza_buffer.append(stanza)
def send(self, stanza, now=False):
self.send_BOSH(stanza)
def get_current_state(self):
t = '------ SOCKET_ID\tSOCKET_STATE\tPENDING_REQS\n'
for s in self.http_socks:
t = '%s------ %s\t%s\t%s\n' % (t, id(s), s.get_state(), s.pending_requests)
t = '%s------ prio stanzas: %s, queued XMPP stanzas: %s, not_acked stanzas: %s' \
% (t, self.prio_bosh_stanzas, self.stanza_buffer,
self.ack_checker.get_not_acked_rids())
return t
def connect_and_flush(self, socket):
socket.connect(
conn_5tuple = self.conn_5tuple,
on_connect = self.on_http_request_possible,
on_connect_failure = self.disconnect)
def boshify_stanzas(self, stanzas=[], body_attrs=None):
"""
Wraps zero to many stanzas by body tag with xmlns and sid
"""
log.debug('boshify_staza - type is: %s, stanza is %s' % (type(stanzas), stanzas))
tag = BOSHBody(attrs={'sid': self.bosh_sid})
tag.setPayload(stanzas)
return tag
def send_init(self, after_SASL=False):
if after_SASL:
t = BOSHBody(
attrs={ 'to': self.bosh_to,
'sid': self.bosh_sid,
'xml:lang': self.bosh_xml_lang,
'xmpp:restart': 'true',
'secure': self.bosh_secure,
'xmlns:xmpp': 'urn:xmpp:xbosh'})
else:
t = BOSHBody(
attrs={ 'content': self.bosh_content,
'hold': str(self.bosh_hold),
'route': 'xmpp:%s:%s' % (self.route_host, self.route_port),
'to': self.bosh_to,
'wait': str(self.bosh_wait),
'xml:lang': self.bosh_xml_lang,
'xmpp:version': '1.0',
'ver': '1.6',
'xmlns:xmpp': 'urn:xmpp:xbosh'})
self.send_BOSH((t, True))
def start_disconnect(self):
NonBlockingTransport.start_disconnect(self)
self.renew_bosh_wait_timeout(DISCONNECT_TIMEOUT_SECONDS)
self.send_BOSH(
(BOSHBody(attrs={'sid': self.bosh_sid, 'type': 'terminate'}), True))
def get_new_http_socket(self):
http_dict = {'http_uri': self.bosh_uri,
'http_version': self.http_version,
'http_persistent': self.http_persistent,
'add_proxy_headers': self.over_proxy and not self.estabilish_tls}
if self.use_proxy_auth:
http_dict['proxy_user'], http_dict['proxy_pass'] = self.proxy_creds
s = NonBlockingHTTPBOSH(
raise_event=self.raise_event,
on_disconnect=self.disconnect,
idlequeue = self.idlequeue,
estabilish_tls = self.estabilish_tls,
certs = self.certs,
on_http_request_possible = self.on_http_request_possible,
http_dict = http_dict,
proxy_dict = self.proxy_dict,
on_persistent_fallback = self.on_persistent_fallback)
s.onreceive(self.on_received_http)
s.set_stanza_build_cb(self.build_stanza)
return s
def onreceive(self, recv_handler):
if recv_handler is None:
recv_handler = self._owner.Dispatcher.ProcessNonBlocking
self.current_recv_handler = recv_handler
def on_received_http(self, data, socket):
self.current_recv_socket = socket
self.current_recv_handler(data)
def disconnect(self, do_callback=True):
self.remove_bosh_wait_timeout()
if self.get_state() == DISCONNECTED: return
self.fd = -1
for s in self.http_socks:
s.disconnect(do_callback=False)
NonBlockingTransport.disconnect(self, do_callback)
def get_rand_number():
# with 50-bit random initial rid, session would have to go up
# to 7881299347898368 messages to raise rid over 2**53
# (see http://www.xmpp.org/extensions/xep-0124.html#rids)
# it's also used for sequence key initialization
r = random.Random()
r.seed()
return r.getrandbits(50)
class AckChecker():
"""
Class for generating rids and generating and checking acknowledgements in
BOSH messages
"""
def __init__(self):
self.rid = get_rand_number()
self.ack = 1
self.last_rids = {}
self.not_acked = []
def get_not_acked_rids(self): return [rid for rid, st in self.not_acked]
def backup_stanza(self, stanza, socket):
socket.pending_requests += 1
rid = self.get_rid()
self.not_acked.append((rid, stanza))
stanza.setAttr('rid', str(rid))
self.last_rids[socket]=rid
if self.rid != self.ack + 1:
stanza.setAttr('ack', str(self.ack))
return stanza
def process_incoming_ack(self, socket, ack=None):
socket.pending_requests -= 1
if ack:
ack = int(ack)
else:
ack = self.last_rids[socket]
i = len([rid for rid, st in self.not_acked if ack >= rid])
self.not_acked = self.not_acked[i:]
self.ack = ack
def get_rid(self):
self.rid = self.rid + 1
return self.rid
class KeyStack():
"""
Class implementing key sequences for BOSH messages
"""
def __init__(self, count):
self.count = count
self.keys = []
self.reset()
self.first_call = True
def reset(self):
seed = str(get_rand_number())
self.keys = [sha1(seed).hexdigest()]
for i in range(self.count-1):
curr_seed = self.keys[i]
self.keys.append(sha1(curr_seed).hexdigest())
def get(self):
if self.first_call:
self.first_call = False
return (None, self.keys.pop())
if len(self.keys)>1:
return (self.keys.pop(), None)
else:
last_key = self.keys.pop()
self.reset()
new_key = self.keys.pop()
return (last_key, new_key)
# http://www.xmpp.org/extensions/xep-0124.html#errorstatus-terminal
bosh_errors = {
'n/a': 'none or unknown condition in terminating body stanza',
'bad-request': 'The format of an HTTP header or binding element received from the client is unacceptable (e.g., syntax error), or Script Syntax is not supported.',
'host-gone': 'The target domain specified in the "to" attribute or the target host or port specified in the "route" attribute is no longer serviced by the connection manager.',
'host-unknown': 'The target domain specified in the "to" attribute or the target host or port specified in the "route" attribute is unknown to the connection manager.',
'improper-addressing': 'The initialization element lacks a "to" or "route" attribute (or the attribute has no value) but the connection manager requires one.',
'internal-server-error': 'The connection manager has experienced an internal error that prevents it from servicing the request.',
'item-not-found': '(1) "sid" is not valid, (2) "stream" is not valid, (3) "rid" is larger than the upper limit of the expected window, (4) connection manager is unable to resend response, (5) "key" sequence is invalid',
'other-request': 'Another request being processed at the same time as this request caused the session to terminate.',
'policy-violation': 'The client has broken the session rules (polling too frequently, requesting too frequently, too many simultaneous requests).',
'remote-connection-failed': 'The connection manager was unable to connect to, or unable to connect securely to, or has lost its connection to, the server.',
'remote-stream-error': 'Encapsulates an error in the protocol being transported.',
'see-other-uri': 'The connection manager does not operate at this URI (e.g., the connection manager accepts only SSL or TLS connections at some https: URI rather than the http: URI requested by the client). The client may try POSTing to the URI in the content of the <uri/> child element.',
'system-shutdown': 'The connection manager is being shut down. All active HTTP sessions are being terminated. No new sessions can be created.',
'undefined-condition': 'The error is not one of those defined herein; the connection manager SHOULD include application-specific information in the content of the <body/> wrapper.'
}

View File

@ -1,59 +0,0 @@
# -*- coding:utf-8 -*-
## c14n.py
##
## Copyright (C) 2007-2008 Brendan Taylor <whateley AT gmail.com>
##
## This file is part of Gajim.
##
## Gajim is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published
## by the Free Software Foundation; version 3 only.
##
## Gajim is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
##
"""
XML canonicalisation methods (for XEP-0116)
"""
from simplexml import ustr
def c14n(node, is_buggy):
s = "<" + node.name
if node.namespace:
if not node.parent or node.parent.namespace != node.namespace:
s = s + ' xmlns="%s"' % node.namespace
sorted_attrs = sorted(node.attrs.keys())
for key in sorted_attrs:
if not is_buggy and key == 'xmlns':
continue
val = ustr(node.attrs[key])
# like XMLescape() but with whitespace and without &gt;
s = s + ' %s="%s"' % ( key, normalise_attr(val) )
s = s + ">"
cnt = 0
if node.kids:
for a in node.kids:
if (len(node.data)-1) >= cnt:
s = s + normalise_text(node.data[cnt])
s = s + c14n(a, is_buggy)
cnt=cnt+1
if (len(node.data)-1) >= cnt: s = s + normalise_text(node.data[cnt])
if not node.kids and s.endswith('>'):
s=s[:-1]+' />'
else:
s = s + "</" + node.name + ">"
return s.encode('utf-8')
def normalise_attr(val):
return val.replace('&', '&amp;').replace('<', '&lt;').replace('"', '&quot;').replace('\t', '&#x9;').replace('\n', '&#xA;').replace('\r', '&#xD;')
def normalise_text(val):
return val.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;').replace('\r', '&#xD;')

View File

@ -1,629 +0,0 @@
## client_nb.py
## based on client.py, changes backported up to revision 1.60
##
## Copyright (C) 2003-2005 Alexey "Snake" Nezhdanov
## modified by Dimitur Kirov <dkirov@gmail.com>
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2, or (at your option)
## any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
# $Id: client.py,v 1.52 2006/01/02 19:40:55 normanr Exp $
"""
Client class establishs connection to XMPP Server and handles authentication
"""
import socket
import transports_nb, dispatcher_nb, auth_nb, roster_nb, protocol, bosh
from protocol import NS_TLS
import logging
log = logging.getLogger('gajim.c.x.client_nb')
class NonBlockingClient:
"""
Client class is XMPP connection mountpoint. Objects for authentication,
network communication, roster, xml parsing ... are plugged to client object.
Client implements the abstract behavior - mostly negotioation and callbacks
handling, whereas underlying modules take care of feature-specific logic
"""
def __init__(self, domain, idlequeue, caller=None):
"""
Caches connection data
:param domain: domain - for to: attribute (from account info)
:param idlequeue: processing idlequeue
:param caller: calling object - it has to implement methods
_event_dispatcher which is called from dispatcher instance
"""
self.Namespace = protocol.NS_CLIENT
self.defaultNamespace = self.Namespace
self.idlequeue = idlequeue
self.disconnect_handlers = []
self.Server = domain
self.xmpp_hostname = None # FQDN hostname to connect to
# caller is who initiated this client, it is in needed to register
# the EventDispatcher
self._caller = caller
self._owner = self
self._registered_name = None # our full jid, set after successful auth
self.connected = ''
self.ip_addresses = []
self.socket = None
self.on_connect = None
self.on_proxy_failure = None
self.on_connect_failure = None
self.proxy = None
self.got_features = False
self.got_see_other_host = None
self.stream_started = False
self.disconnecting = False
self.protocol_type = 'XMPP'
def disconnect(self, message=''):
"""
Called on disconnection - disconnect callback is picked based on state of
the client.
"""
# to avoid recursive calls
if self.ip_addresses:
self._try_next_ip()
return
if self.disconnecting: return
log.info('Disconnecting NBClient: %s' % message)
sasl_failed = False
if 'NonBlockingRoster' in self.__dict__:
self.NonBlockingRoster.PlugOut()
if 'NonBlockingBind' in self.__dict__:
self.NonBlockingBind.PlugOut()
if 'NonBlockingNonSASL' in self.__dict__:
self.NonBlockingNonSASL.PlugOut()
if 'SASL' in self.__dict__:
if 'startsasl' in self.SASL.__dict__ and \
self.SASL.startsasl == 'failure-in-process':
sasl_failed = True
self.SASL.startsasl = 'failure'
self._on_start_sasl()
else:
self.SASL.PlugOut()
if 'NonBlockingTCP' in self.__dict__:
self.NonBlockingTCP.PlugOut()
if 'NonBlockingHTTP' in self.__dict__:
self.NonBlockingHTTP.PlugOut()
if 'NonBlockingBOSH' in self.__dict__:
self.NonBlockingBOSH.PlugOut()
# FIXME: we never unplug dispatcher, only on next connect
# See _xmpp_connect_machine and SASLHandler
connected = self.connected
stream_started = self.stream_started
self.connected = ''
self.stream_started = False
self.disconnecting = True
log.debug('Client disconnected..')
# Don't call any callback when it's a SASL failure.
# SASL handler is already called
if connected == '' and not sasl_failed:
# if we're disconnecting before connection to XMPP sever is opened,
# we don't call disconnect handlers but on_connect_failure callback
if self.proxy:
# with proxy, we have different failure callback
log.debug('calling on_proxy_failure cb')
self.on_proxy_failure(reason=message)
else:
log.debug('calling on_connect_failure cb')
self.on_connect_failure()
elif not sasl_failed:
# we are connected to XMPP server
if not stream_started:
# if error occur before XML stream was opened, e.g. no response on
# init request, we call the on_connect_failure callback because
# proper connection is not established yet and it's not a proxy
# issue
log.debug('calling on_connect_failure cb')
self._caller.streamError = message
self.on_connect_failure()
else:
# with open connection, we are calling the disconnect handlers
for i in reversed(self.disconnect_handlers):
log.debug('Calling disconnect handler %s' % i)
i()
self.disconnecting = False
def connect(self, on_connect, on_connect_failure, hostname=None, port=5222,
on_proxy_failure=None, on_stream_error_cb=None, proxy=None,
secure_tuple=('plain', None, None)):
"""
Open XMPP connection (open XML streams in both directions)
:param on_connect: called after stream is successfully opened
:param on_connect_failure: called when error occures during connection
:param hostname: hostname of XMPP server from SRV request
:param port: port number of XMPP server
:param on_proxy_failure: called if error occurres during TCP connection to
proxy server or during proxy connecting process
:param proxy: dictionary with proxy data. It should contain at least
values for keys 'host' and 'port' - connection details for proxy serve
and optionally keys 'user' and 'pass' as proxy credentials
:param secure_tuple: tuple of (desired connection type, cacerts, mycerts)
connection type can be 'ssl' - TLS established after TCP connection,
'tls' - TLS established after negotiation with starttls, or 'plain'.
cacerts, mycerts - see tls_nb.NonBlockingTLS constructor for more
details
"""
self.on_connect = on_connect
self.on_connect_failure=on_connect_failure
self.on_proxy_failure = on_proxy_failure
self.on_stream_error_cb = on_stream_error_cb
self.desired_security, self.cacerts, self.mycerts = secure_tuple
self.Connection = None
self.Port = port
self.proxy = proxy
if hostname:
self.xmpp_hostname = hostname
else:
self.xmpp_hostname = self.Server
# We only check for SSL here as for TLS we will first have to start a
# PLAIN connection and negotiate TLS afterwards.
# establish_tls will instruct transport to start secure connection
# directly
establish_tls = self.desired_security == 'ssl'
certs = (self.cacerts, self.mycerts)
proxy_dict = {}
tcp_host = self.xmpp_hostname
tcp_port = self.Port
if proxy:
# with proxies, client connects to proxy instead of directly to
# XMPP server ((hostname, port))
# tcp_host is hostname of machine used for socket connection
# (DNS request will be done for proxy or BOSH CM hostname)
tcp_host, tcp_port, proxy_user, proxy_pass = \
transports_nb.get_proxy_data_from_dict(proxy)
if proxy['type'] == 'bosh':
# Setup BOSH transport
self.socket = bosh.NonBlockingBOSH.get_instance(
on_disconnect=self.disconnect,
raise_event=self.raise_event,
idlequeue=self.idlequeue,
estabilish_tls=establish_tls,
certs=certs,
proxy_creds=(proxy_user, proxy_pass),
xmpp_server=(self.xmpp_hostname, self.Port),
domain=self.Server,
bosh_dict=proxy)
self.protocol_type = 'BOSH'
self.wait_for_restart_response = \
proxy['bosh_wait_for_restart_response']
else:
# http proxy
proxy_dict['type'] = proxy['type']
proxy_dict['xmpp_server'] = (self.xmpp_hostname, self.Port)
proxy_dict['credentials'] = (proxy_user, proxy_pass)
if not proxy or proxy['type'] != 'bosh':
# Setup ordinary TCP transport
self.socket = transports_nb.NonBlockingTCP.get_instance(
on_disconnect=self.disconnect,
raise_event=self.raise_event,
idlequeue=self.idlequeue,
estabilish_tls=establish_tls,
certs=certs,
proxy_dict=proxy_dict)
# plug transport into client as self.Connection
self.socket.PlugIn(self)
self._resolve_hostname(
hostname=tcp_host,
port=tcp_port,
on_success=self._try_next_ip)
def _resolve_hostname(self, hostname, port, on_success):
"""
Wrapper for getaddinfo call
FIXME: getaddinfo blocks
"""
try:
self.ip_addresses = socket.getaddrinfo(hostname, port,
socket.AF_UNSPEC, socket.SOCK_STREAM)
except socket.gaierror, (errnum, errstr):
self.disconnect(message='Lookup failure for %s:%s, hostname: %s - %s' %
(self.Server, self.Port, hostname, errstr))
else:
on_success()
def _try_next_ip(self, err_message=None):
"""
Iterate over IP addresses tries to connect to it
"""
if err_message:
log.debug('While looping over DNS A records: %s' % err_message)
if self.ip_addresses == []:
msg = 'Run out of hosts for name %s:%s.' % (self.Server, self.Port)
msg = msg + ' Error for last IP: %s' % err_message
self.disconnect(msg)
else:
self.current_ip = self.ip_addresses.pop(0)
self.socket.connect(
conn_5tuple=self.current_ip,
on_connect=lambda: self._xmpp_connect(),
on_connect_failure=self._try_next_ip)
def incoming_stream_version(self):
"""
Get version of xml stream
"""
if 'version' in self.Dispatcher.Stream._document_attrs:
return self.Dispatcher.Stream._document_attrs['version']
else:
return None
def _xmpp_connect(self, socket_type=None):
"""
Start XMPP connecting process - open the XML stream. Is called after TCP
connection is established or after switch to TLS when successfully
negotiated with <starttls>.
"""
# socket_type contains info which transport connection was established
if not socket_type:
if self.Connection.ssl_lib:
# When ssl_lib is set we connected via SSL
socket_type = 'ssl'
else:
# PLAIN is default
socket_type = 'plain'
self.connected = socket_type
self._xmpp_connect_machine()
def _xmpp_connect_machine(self, mode=None, data=None):
"""
Finite automaton taking care of stream opening and features tag handling.
Calls _on_stream_start when stream is started, and disconnect() on
failure.
"""
log.info('-------------xmpp_connect_machine() >> mode: %s, data: %s...' %
(mode, str(data)[:20]))
def on_next_receive(mode):
"""
Set desired on_receive callback on transport based on the state of
connect_machine.
"""
log.info('setting %s on next receive' % mode)
if mode is None:
self.onreceive(None) # switch to Dispatcher.ProcessNonBlocking
else:
self.onreceive(lambda _data:self._xmpp_connect_machine(mode, _data))
if not mode:
# starting state
if self.__dict__.has_key('Dispatcher'):
self.Dispatcher.PlugOut()
self.got_features = False
dispatcher_nb.Dispatcher.get_instance().PlugIn(self)
on_next_receive('RECEIVE_DOCUMENT_ATTRIBUTES')
elif mode == 'FAILURE':
self.disconnect('During XMPP connect: %s' % data)
elif mode == 'RECEIVE_DOCUMENT_ATTRIBUTES':
if data:
self.Dispatcher.ProcessNonBlocking(data)
self.ip_addresses = []
if not hasattr(self, 'Dispatcher') or \
self.Dispatcher.Stream._document_attrs is None:
self._xmpp_connect_machine(
mode='FAILURE',
data='Error on stream open')
return
# if terminating stanza was received after init request then client gets
# disconnected from bosh transport plugin and we have to end the stream
# negotiating process straight away.
# fixes #4657
if not self.connected: return
if self.incoming_stream_version() == '1.0':
if not self.got_features:
on_next_receive('RECEIVE_STREAM_FEATURES')
else:
log.info('got STREAM FEATURES in first recv')
self._xmpp_connect_machine(mode='STREAM_STARTED')
else:
log.info('incoming stream version less than 1.0')
self._xmpp_connect_machine(mode='STREAM_STARTED')
elif mode == 'RECEIVE_STREAM_FEATURES':
if data:
# sometimes <features> are received together with document
# attributes and sometimes on next receive...
self.Dispatcher.ProcessNonBlocking(data)
if self.got_see_other_host:
log.info('got see-other-host')
self.onreceive(None)
self.on_stream_error_cb(self, self.got_see_other_host)
elif not self.got_features:
self._xmpp_connect_machine(
mode='FAILURE',
data='Missing <features> in 1.0 stream')
else:
log.info('got STREAM FEATURES in second recv')
self._xmpp_connect_machine(mode='STREAM_STARTED')
elif mode == 'STREAM_STARTED':
self._on_stream_start()
def _on_stream_start(self):
"""
Called after XMPP stream is opened. TLS negotiation may follow if
supported and desired.
"""
self.stream_started = True
if not hasattr(self, 'onreceive'):
# we may already have been disconnected
return
self.onreceive(None)
if self.connected == 'plain':
if self.desired_security == 'plain':
# if we want and have plain connection, we're done now
self._on_connect()
else:
# try to negotiate TLS
if self.incoming_stream_version() != '1.0':
# if stream version is less than 1.0, we can't do more
log.info('While connecting with type = "tls": stream version ' +
'is less than 1.0')
self._on_connect()
return
if self.Dispatcher.Stream.features.getTag('starttls'):
# Server advertises TLS support, start negotiation
self.stream_started = False
log.info('TLS supported by remote server. Requesting TLS start.')
self._tls_negotiation_handler()
else:
log.info('While connecting with type = "tls": TLS unsupported ' +
'by remote server')
self._on_connect()
elif self.connected in ['ssl', 'tls']:
self._on_connect()
else:
assert False, 'Stream opened for unsupported connection'
def _tls_negotiation_handler(self, con=None, tag=None):
"""
Take care of TLS negotioation with <starttls>
"""
log.info('-------------tls_negotiaton_handler() >> tag: %s' % tag)
if not con and not tag:
# starting state when we send the <starttls>
self.RegisterHandlerOnce('proceed', self._tls_negotiation_handler,
xmlns=NS_TLS)
self.RegisterHandlerOnce('failure', self._tls_negotiation_handler,
xmlns=NS_TLS)
self.send('<starttls xmlns="%s"/>' % NS_TLS)
else:
# we got <proceed> or <failure>
if tag.getNamespace() != NS_TLS:
self.disconnect('Unknown namespace: %s' % tag.getNamespace())
return
tagname = tag.getName()
if tagname == 'failure':
self.disconnect('TLS <failure> received: %s' % tag)
return
log.info('Got starttls proceed response. Switching to TLS/SSL...')
# following call wouldn't work for BOSH transport but it doesn't matter
# because <starttls> negotiation with BOSH is forbidden
self.Connection.tls_init(
on_succ = lambda: self._xmpp_connect(socket_type='tls'),
on_fail = lambda: self.disconnect('error while etabilishing TLS'))
def _on_connect(self):
"""
Preceed call of on_connect callback
"""
self.onreceive(None)
self.on_connect(self, self.connected)
def raise_event(self, event_type, data):
"""
Raise event to connection instance. DATA_SENT and DATA_RECIVED events
are used in XML console to show XMPP traffic
"""
log.info('raising event from transport: :::::%s::::\n_____________\n%s\n_____________\n' % (event_type, data))
if hasattr(self, 'Dispatcher'):
self.Dispatcher.Event('', event_type, data)
###############################################################################
### follows code for authentication, resource bind, session and roster download
###############################################################################
def auth(self, user, password, resource='', sasl=True, on_auth=None):
"""
Authenticate connnection and bind resource. If resource is not provided
random one or library name used
:param user: XMPP username
:param password: XMPP password
:param resource: resource that shall be used for auth/connecting
:param sasl: Boolean indicating if SASL shall be used. (default: True)
:param on_auth: Callback, called after auth. On auth failure, argument
is None.
"""
self._User, self._Password = user, password
self._Resource, self._sasl = resource, sasl
self.on_auth = on_auth
self._on_doc_attrs()
return
def _on_old_auth(self, res):
"""
Callback used by NON-SASL auth. On auth failure, res is None
"""
if res:
self.connected += '+old_auth'
self.on_auth(self, 'old_auth')
else:
self.on_auth(self, None)
def _on_sasl_auth(self, res):
"""
Used internally. On auth failure, res is None
"""
self.onreceive(None)
if res:
self.connected += '+sasl'
self.on_auth(self, 'sasl')
else:
self.on_auth(self, None)
def _on_doc_attrs(self):
"""
Plug authentication objects and start auth
"""
if self._sasl:
auth_nb.SASL.get_instance(self._User, self._Password,
self._on_start_sasl).PlugIn(self)
if not hasattr(self, 'SASL'):
return
if not self._sasl or self.SASL.startsasl == 'not-supported':
if not self._Resource:
self._Resource = 'xmpppy'
auth_nb.NonBlockingNonSASL.get_instance(self._User, self._Password,
self._Resource, self._on_old_auth).PlugIn(self)
return
self.SASL.auth()
return True
def _on_start_sasl(self, data=None):
"""
Callback used by SASL, called on each auth step
"""
if data:
self.Dispatcher.ProcessNonBlocking(data)
if not 'SASL' in self.__dict__:
# SASL is pluged out, possible disconnect
return
if self.SASL.startsasl == 'in-process':
return
self.onreceive(None)
if self.SASL.startsasl == 'failure':
# wrong user/pass, stop auth
if 'SASL' in self.__dict__:
self.SASL.PlugOut()
self.connected = None # FIXME: is this intended? We use ''elsewhere
self._on_sasl_auth(None)
elif self.SASL.startsasl == 'success':
nb_bind = auth_nb.NonBlockingBind.get_instance()
sm = self._caller.sm
if sm._owner and sm.resumption:
nb_bind.resuming = True
sm.set_owner(self)
self.Dispatcher.sm = sm
nb_bind.PlugIn(self)
self.on_auth(self, 'sasl')
return
nb_bind.PlugIn(self)
self.onreceive(self._on_auth_bind)
return True
def _on_auth_bind(self, data):
# FIXME: Why use this callback and not bind directly?
if data:
self.Dispatcher.ProcessNonBlocking(data)
if self.NonBlockingBind.bound is None:
return
self.NonBlockingBind.NonBlockingBind(self._Resource, self._on_sasl_auth)
return True
def initRoster(self, version=''):
"""
Plug in the roster
"""
if not self.__dict__.has_key('NonBlockingRoster'):
return roster_nb.NonBlockingRoster.get_instance(version=version).PlugIn(self)
def getRoster(self, on_ready=None, force=False):
"""
Return the Roster instance, previously plugging it in and requesting
roster from server if needed
"""
if self.__dict__.has_key('NonBlockingRoster'):
return self.NonBlockingRoster.getRoster(on_ready, force)
return None
def sendPresence(self, jid=None, typ=None, requestRoster=0):
"""
Send some specific presence state. Can also request roster from server if
according agrument is set
"""
if requestRoster:
# FIXME: used somewhere?
roster_nb.NonBlockingRoster.get_instance().PlugIn(self)
self.send(dispatcher_nb.Presence(to=jid, typ=typ))
###############################################################################
### following methods are moved from blocking client class of xmpppy
###############################################################################
def RegisterDisconnectHandler(self, handler):
"""
Register handler that will be called on disconnect
"""
self.disconnect_handlers.append(handler)
def UnregisterDisconnectHandler(self, handler):
"""
Unregister handler that is called on disconnect
"""
self.disconnect_handlers.remove(handler)
def DisconnectHandler(self):
"""
Default disconnect handler. Just raises an IOError. If you choosed to use
this class in your production client, override this method or at least
unregister it.
"""
raise IOError('Disconnected from server.')
def get_connect_type(self):
"""
Return connection state. F.e.: None / 'tls' / 'plain+non_sasl'
"""
return self.connected
def get_peerhost(self):
"""
Gets the ip address of the account, from which is made connection to the
server (e.g. IP and port of gajim's socket)
We will create listening socket on the same ip
"""
# FIXME: tuple (ip, port) is expected (and checked for) but port num is
# useless
return self.socket.peerhost

View File

@ -1,639 +0,0 @@
## dispatcher_nb.py
## based on dispatcher.py
##
## Copyright (C) 2003-2005 Alexey "Snake" Nezhdanov
## modified by Dimitur Kirov <dkirov@gmail.com>
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2, or (at your option)
## any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
"""
Main xmpp decision making logic. Provides library with methods to assign
different handlers to different XMPP stanzas and namespaces
"""
import simplexml, sys, locale
import re
from xml.parsers.expat import ExpatError
from plugin import PlugIn
from protocol import (NS_STREAMS, NS_XMPP_STREAMS, NS_HTTP_BIND, Iq, Presence,
Message, Protocol, Node, Error, ERR_FEATURE_NOT_IMPLEMENTED, StreamError)
import logging
log = logging.getLogger('gajim.c.x.dispatcher_nb')
#: default timeout to wait for response for our id
DEFAULT_TIMEOUT_SECONDS = 25
outgoingID = 0
XML_DECLARATION = '<?xml version=\'1.0\'?>'
# FIXME: ugly
class Dispatcher():
"""
Why is this here - I needed to redefine Dispatcher for BOSH and easiest way
was to inherit original Dispatcher (now renamed to XMPPDispatcher). Trouble
is that reference used to access dispatcher instance is in Client attribute
named by __class__.__name__ of the dispatcher instance .. long story short:
I wrote following to avoid changing each client.Dispatcher.whatever() in xmpp
If having two kinds of dispatcher will go well, I will rewrite the dispatcher
references in other scripts
"""
def PlugIn(self, client_obj, after_SASL=False, old_features=None):
if client_obj.protocol_type == 'XMPP':
XMPPDispatcher().PlugIn(client_obj)
elif client_obj.protocol_type == 'BOSH':
BOSHDispatcher().PlugIn(client_obj, after_SASL, old_features)
else:
assert False # should never be reached
@classmethod
def get_instance(cls, *args, **kwargs):
"""
Factory Method for object creation
Use this instead of directly initializing the class in order to make
unit testing much easier.
"""
return cls(*args, **kwargs)
class XMPPDispatcher(PlugIn):
"""
Handles XMPP stream and is the first who takes control over a fresh stanza
Is plugged into NonBlockingClient but can be replugged to restart handled
stream headers (used by SASL f.e.).
"""
def __init__(self):
PlugIn.__init__(self)
self.handlers = {}
self._expected = {}
self._defaultHandler = None
self._pendingExceptions = []
self._eventHandler = None
self._cycleHandlers = []
self._exported_methods=[self.RegisterHandler, self.RegisterDefaultHandler,
self.RegisterEventHandler, self.UnregisterCycleHandler,
self.RegisterCycleHandler, self.RegisterHandlerOnce,
self.UnregisterHandler, self.RegisterProtocol,
self.SendAndWaitForResponse, self.SendAndCallForResponse,
self.getAnID, self.Event, self.send]
# Let the dispatcher know if there is support for stream management
self.sm = None
# \ufddo -> \ufdef range
c = u'\ufdd0'
r = c.encode('utf8')
while (c < u'\ufdef'):
c = unichr(ord(c) + 1)
r += '|' + c.encode('utf8')
# \ufffe-\uffff, \u1fffe-\u1ffff, ..., \u10fffe-\u10ffff
c = u'\ufffe'
r += '|' + c.encode('utf8')
r += '|' + unichr(ord(c) + 1).encode('utf8')
while (c < u'\U0010fffe'):
c = unichr(ord(c) + 0x10000)
r += '|' + c.encode('utf8')
r += '|' + unichr(ord(c) + 1).encode('utf8')
self.invalid_chars_re = re.compile(r)
def getAnID(self):
global outgoingID
outgoingID += 1
return repr(outgoingID)
def dumpHandlers(self):
"""
Return set of user-registered callbacks in it's internal format. Used
within the library to carry user handlers set over Dispatcher replugins
"""
return self.handlers
def restoreHandlers(self, handlers):
"""
Restore user-registered callbacks structure from dump previously obtained
via dumpHandlers. Used within the library to carry user handlers set over
Dispatcher replugins.
"""
self.handlers = handlers
def _init(self):
"""
Register default namespaces/protocols/handlers. Used internally
"""
# FIXME: inject dependencies, do not rely that they are defined by our
# owner
self.RegisterNamespace('unknown')
self.RegisterNamespace(NS_STREAMS)
self.RegisterNamespace(self._owner.defaultNamespace)
self.RegisterProtocol('iq', Iq)
self.RegisterProtocol('presence', Presence)
self.RegisterProtocol('message', Message)
self.RegisterDefaultHandler(self.returnStanzaHandler)
self.RegisterEventHandler(self._owner._caller._event_dispatcher)
self.on_responses = {}
def plugin(self, owner):
"""
Plug the Dispatcher instance into Client class instance and send initial
stream header. Used internally
"""
self._init()
self._owner.lastErrNode = None
self._owner.lastErr = None
self._owner.lastErrCode = None
if hasattr(self._owner, 'StreamInit'):
self._owner.StreamInit()
else:
self.StreamInit()
def plugout(self):
"""
Prepare instance to be destructed
"""
self.Stream.dispatch = None
self.Stream.features = None
self.Stream.destroy()
self._owner = None
self.Stream = None
def StreamInit(self):
"""
Send an initial stream header
"""
self._owner.Connection.sendqueue = []
self.Stream = simplexml.NodeBuilder()
self.Stream.dispatch = self.dispatch
self.Stream._dispatch_depth = 2
self.Stream.stream_header_received = self._check_stream_start
self.Stream.features = None
self._metastream = Node('stream:stream')
self._metastream.setNamespace(self._owner.Namespace)
self._metastream.setAttr('version', '1.0')
self._metastream.setAttr('xmlns:stream', NS_STREAMS)
self._metastream.setAttr('to', self._owner.Server)
if locale.getdefaultlocale()[0]:
self._metastream.setAttr('xml:lang',
locale.getdefaultlocale()[0].split('_')[0])
self._owner.send("%s%s>" % (XML_DECLARATION, str(self._metastream)[:-2]))
def _check_stream_start(self, ns, tag, attrs):
if ns != NS_STREAMS or tag!='stream':
raise ValueError('Incorrect stream start: (%s,%s). Terminating.'
% (tag, ns))
def replace_non_character(self, data):
return re.sub(self.invalid_chars_re, u'\ufffd'.encode('utf-8'), data)
def ProcessNonBlocking(self, data):
"""
Check incoming stream for data waiting
:param data: data received from transports/IO sockets
:return:
1) length of processed data if some data were processed;
2) '0' string if no data were processed but link is alive;
3) 0 (zero) if underlying connection is closed.
"""
# FIXME:
# When an error occurs we disconnect the transport directly. Client's
# disconnect method will never be called.
# Is this intended?
# also look at transports start_disconnect()
data = self.replace_non_character(data)
for handler in self._cycleHandlers:
handler(self)
if len(self._pendingExceptions) > 0:
_pendingException = self._pendingExceptions.pop()
raise _pendingException[0], _pendingException[1], _pendingException[2]
try:
self.Stream.Parse(data)
# end stream:stream tag received
if self.Stream and self.Stream.has_received_endtag():
self._owner.disconnect(self.Stream.streamError)
return 0
except ExpatError:
log.error('Invalid XML received from server. Forcing disconnect.')
self._owner.Connection.disconnect()
return 0
except ValueError, e:
log.debug('ValueError: %s' % str(e))
self._owner.Connection.pollend()
return 0
if len(self._pendingExceptions) > 0:
_pendingException = self._pendingExceptions.pop()
raise _pendingException[0], _pendingException[1], _pendingException[2]
if len(data) == 0:
return '0'
return len(data)
def RegisterNamespace(self, xmlns, order='info'):
"""
Create internal structures for newly registered namespace
You can register handlers for this namespace afterwards. By default
one namespace is already registered
(jabber:client or jabber:component:accept depending on context.
"""
log.debug('Registering namespace "%s"' % xmlns)
self.handlers[xmlns] = {}
self.RegisterProtocol('unknown', Protocol, xmlns=xmlns)
self.RegisterProtocol('default', Protocol, xmlns=xmlns)
def RegisterProtocol(self, tag_name, Proto, xmlns=None, order='info'):
"""
Used to declare some top-level stanza name to dispatcher
Needed to start registering handlers for such stanzas. Iq, message and
presence protocols are registered by default.
"""
if not xmlns:
xmlns=self._owner.defaultNamespace
log.debug('Registering protocol "%s" as %s(%s)' %(tag_name, Proto, xmlns))
self.handlers[xmlns][tag_name] = {type:Proto, 'default':[]}
def RegisterNamespaceHandler(self, xmlns, handler, typ='', ns='',
makefirst=0, system=0):
"""
Register handler for processing all stanzas for specified namespace
"""
self.RegisterHandler('default', handler, typ, ns, xmlns, makefirst,
system)
def RegisterHandler(self, name, handler, typ='', ns='', xmlns=None,
makefirst=False, system=False):
"""
Register user callback as stanzas handler of declared type
Callback arguments:
dispatcher instance (for replying), incoming return of previous handlers.
The callback must raise xmpp.NodeProcessed just before return if it wants
to prevent other callbacks to be called with the same stanza as argument
_and_, more importantly library from returning stanza to sender with error set.
:param name: name of stanza. F.e. "iq".
:param handler: user callback.
:param typ: value of stanza's "type" attribute. If not specified any
value will match
:param ns: namespace of child that stanza must contain.
:param makefirst: insert handler in the beginning of handlers list instead
of adding it to the end. Note that more common handlers i.e. w/o "typ"
and " will be called first nevertheless.
:param system: call handler even if NodeProcessed Exception were raised
already.
"""
if not xmlns:
xmlns=self._owner.defaultNamespace
log.debug('Registering handler %s for "%s" type->%s ns->%s(%s)' %
(handler, name, typ, ns, xmlns))
if not typ and not ns:
typ='default'
if xmlns not in self.handlers:
self.RegisterNamespace(xmlns, 'warn')
if name not in self.handlers[xmlns]:
self.RegisterProtocol(name, Protocol, xmlns, 'warn')
if typ+ns not in self.handlers[xmlns][name]:
self.handlers[xmlns][name][typ+ns]=[]
if makefirst:
self.handlers[xmlns][name][typ+ns].insert(0, {'func':handler,
'system':system})
else:
self.handlers[xmlns][name][typ+ns].append({'func':handler,
'system':system})
def RegisterHandlerOnce(self, name, handler, typ='', ns='', xmlns=None,
makefirst=0, system=0):
"""
Unregister handler after first call (not implemented yet)
"""
# FIXME Drop or implement
if not xmlns:
xmlns = self._owner.defaultNamespace
self.RegisterHandler(name, handler, typ, ns, xmlns, makefirst, system)
def UnregisterHandler(self, name, handler, typ='', ns='', xmlns=None):
"""
Unregister handler. "typ" and "ns" must be specified exactly the same as
with registering.
"""
if not xmlns:
xmlns = self._owner.defaultNamespace
if not typ and not ns:
typ='default'
if xmlns not in self.handlers:
return
if name not in self.handlers[xmlns]:
return
if typ+ns not in self.handlers[xmlns][name]:
return
for pack in self.handlers[xmlns][name][typ+ns]:
if pack['func'] == handler:
try:
self.handlers[xmlns][name][typ+ns].remove(pack)
except ValueError:
pass
def RegisterDefaultHandler(self, handler):
"""
Specify the handler that will be used if no NodeProcessed exception were
raised. This is returnStanzaHandler by default.
"""
self._defaultHandler = handler
def RegisterEventHandler(self, handler):
"""
Register handler that will process events. F.e. "FILERECEIVED" event. See
common/connection: _event_dispatcher()
"""
self._eventHandler = handler
def returnStanzaHandler(self, conn, stanza):
"""
Return stanza back to the sender with <feature-not-implemented/> error
set
"""
if stanza.getType() in ('get', 'set'):
conn._owner.send(Error(stanza, ERR_FEATURE_NOT_IMPLEMENTED))
def RegisterCycleHandler(self, handler):
"""
Register handler that will be called on every Dispatcher.Process() call
"""
if handler not in self._cycleHandlers:
self._cycleHandlers.append(handler)
def UnregisterCycleHandler(self, handler):
"""
Unregister handler that will is called on every Dispatcher.Process() call
"""
if handler in self._cycleHandlers:
self._cycleHandlers.remove(handler)
def Event(self, realm, event, data):
"""
Raise some event
:param realm: scope of event. Usually a namespace.
:param event: the event itself. F.e. "SUCCESSFUL SEND".
:param data: data that comes along with event. Depends on event.
"""
if self._eventHandler:
self._eventHandler(realm, event, data)
else:
log.warning('Received unhandled event: %s' % event)
def dispatch(self, stanza, session=None, direct=0):
"""
Main procedure that performs XMPP stanza recognition and calling
apppropriate handlers for it. Called by simplexml
"""
# FIXME: Where do we set session and direct. Why? What are those intended
# to do?
#log.info('dispatch called: stanza = %s, session = %s, direct= %s'
# % (stanza, session, direct))
if not session:
session = self
session.Stream._mini_dom = None
name = stanza.getName()
if name == 'features':
self._owner.got_features = True
session.Stream.features = stanza
if name == 'error':
if stanza.getTag('see-other-host'):
self._owner.got_see_other_host = stanza
xmlns = stanza.getNamespace()
# log.info('in dispatch, getting ns for %s, and the ns is %s'
# % (stanza, xmlns))
if xmlns not in self.handlers:
log.warn("Unknown namespace: " + xmlns)
xmlns = 'unknown'
# features stanza has been handled before
if name not in self.handlers[xmlns]:
if name != 'features':
log.warn("Unknown stanza: " + name)
else:
log.debug("Got %s/%s stanza" % (xmlns, name))
name='unknown'
else:
log.debug("Got %s/%s stanza" % (xmlns, name))
if stanza.__class__.__name__ == 'Node':
# FIXME: this cannot work
stanza=self.handlers[xmlns][name][type](node=stanza)
typ = stanza.getType()
if not typ:
typ = ''
stanza.props = stanza.getProperties()
ID = stanza.getID()
# If server supports stream management
if self.sm and self.sm.enabled and (stanza.getName() != 'r' and
stanza.getName() != 'a' and stanza.getName() != 'enabled' and
stanza.getName() != 'resumed'):
# increments the number of stanzas that has been handled
self.sm.in_h = self.sm.in_h + 1
list_ = ['default'] # we will use all handlers:
if typ in self.handlers[xmlns][name]:
list_.append(typ) # from very common...
for prop in stanza.props:
if prop in self.handlers[xmlns][name]:
list_.append(prop)
if typ and typ+prop in self.handlers[xmlns][name]:
list_.append(typ+prop) # ...to very particular
chain = self.handlers[xmlns]['default']['default']
for key in list_:
if key:
chain = chain + self.handlers[xmlns][name][key]
if ID in session._expected:
user = 0
if isinstance(session._expected[ID], tuple):
cb, args = session._expected[ID]
log.debug("Expected stanza arrived. Callback %s(%s) found!" %
(cb, args))
try:
cb(session,stanza,**args)
except Exception, typ:
if typ.__class__.__name__ != 'NodeProcessed':
raise
else:
log.debug("Expected stanza arrived!")
session._expected[ID] = stanza
else:
user = 1
for handler in chain:
if user or handler['system']:
try:
handler['func'](session, stanza)
except Exception, typ:
if typ.__class__.__name__ != 'NodeProcessed':
self._pendingExceptions.insert(0, sys.exc_info())
return
user=0
if user and self._defaultHandler:
self._defaultHandler(session, stanza)
def _WaitForData(self, data):
"""
Internal wrapper around ProcessNonBlocking. Will check for
"""
if data is None:
return
res = self.ProcessNonBlocking(data)
# 0 result indicates that we have closed the connection, e.g.
# we have released dispatcher, so self._owner has no methods
if not res:
return
for (_id, _iq) in self._expected.items():
if _iq is None:
# If the expected Stanza would have arrived, ProcessNonBlocking
# would have placed the reply stanza in there
continue
if _id in self.on_responses:
if len(self._expected) == 1:
self._owner.onreceive(None)
resp, args = self.on_responses[_id]
del self.on_responses[_id]
if args is None:
resp(_iq)
else:
resp(self._owner, _iq, **args)
del self._expected[_id]
def SendAndWaitForResponse(self, stanza, timeout=None, func=None, args=None):
"""
Send stanza and wait for recipient's response to it. Will call transports
on_timeout callback if response is not retrieved in time
Be aware: Only timeout of latest call of SendAndWait is active.
"""
if timeout is None:
timeout = DEFAULT_TIMEOUT_SECONDS
_waitid = self.send(stanza)
if func:
self.on_responses[_waitid] = (func, args)
if timeout:
self._owner.set_timeout(timeout)
self._owner.onreceive(self._WaitForData)
self._expected[_waitid] = None
return _waitid
def SendAndCallForResponse(self, stanza, func=None, args=None):
"""
Put stanza on the wire and call back when recipient replies. Additional
callback arguments can be specified in args
"""
self.SendAndWaitForResponse(stanza, 0, func, args)
def send(self, stanza, now=False):
"""
Wrap transports send method when plugged into NonBlockingClient. Makes
sure stanzas get ID and from tag.
"""
ID = None
if type(stanza) not in [type(''), type(u'')]:
if isinstance(stanza, Protocol):
ID = stanza.getID()
if ID is None:
stanza.setID(self.getAnID())
ID = stanza.getID()
if self._owner._registered_name and not stanza.getAttr('from'):
stanza.setAttr('from', self._owner._registered_name)
# If no ID then it is a whitespace
if self.sm and self.sm.enabled and ID:
self.sm.uqueue.append(stanza)
self.sm.out_h = self.sm.out_h + 1
if len(self.sm.uqueue) > self.sm.max_queue:
self.sm.request_ack()
self._owner.Connection.send(stanza, now)
return ID
class BOSHDispatcher(XMPPDispatcher):
def PlugIn(self, owner, after_SASL=False, old_features=None):
self.old_features = old_features
self.after_SASL = after_SASL
XMPPDispatcher.PlugIn(self, owner)
def StreamInit(self):
"""
Send an initial stream header
"""
self.Stream = simplexml.NodeBuilder()
self.Stream.dispatch = self.dispatch
self.Stream._dispatch_depth = 2
self.Stream.stream_header_received = self._check_stream_start
self.Stream.features = self.old_features
self._metastream = Node('stream:stream')
self._metastream.setNamespace(self._owner.Namespace)
self._metastream.setAttr('version', '1.0')
self._metastream.setAttr('xmlns:stream', NS_STREAMS)
self._metastream.setAttr('to', self._owner.Server)
if locale.getdefaultlocale()[0]:
self._metastream.setAttr('xml:lang',
locale.getdefaultlocale()[0].split('_')[0])
self.restart = True
self._owner.Connection.send_init(after_SASL=self.after_SASL)
def StreamTerminate(self):
"""
Send a stream terminator
"""
self._owner.Connection.send_terminator()
def ProcessNonBlocking(self, data=None):
if self.restart:
fromstream = self._metastream
fromstream.setAttr('from', fromstream.getAttr('to'))
fromstream.delAttr('to')
data = '%s%s>%s' % (XML_DECLARATION, str(fromstream)[:-2], data)
self.restart = False
return XMPPDispatcher.ProcessNonBlocking(self, data)
def dispatch(self, stanza, session=None, direct=0):
if stanza.getName() == 'body' and stanza.getNamespace() == NS_HTTP_BIND:
stanza_attrs = stanza.getAttrs()
if 'authid' in stanza_attrs:
# should be only in init response
# auth module expects id of stream in document attributes
self.Stream._document_attrs['id'] = stanza_attrs['authid']
self._owner.Connection.handle_body_attrs(stanza_attrs)
children = stanza.getChildren()
if children:
for child in children:
# if child doesn't have any ns specified, simplexml (or expat)
# thinks it's of parent's (BOSH body) namespace, so we have to
# rewrite it to jabber:client
if child.getNamespace() == NS_HTTP_BIND:
child.setNamespace(self._owner.defaultNamespace)
XMPPDispatcher.dispatch(self, child, session, direct)
else:
XMPPDispatcher.dispatch(self, stanza, session, direct)

View File

@ -1,218 +0,0 @@
## features.py
##
## Copyright (C) 2003-2004 Alexey "Snake" Nezhdanov
## Copyright (C) 2007 Julien Pivotto <roidelapluie@gmail.com>
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2, or (at your option)
## any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
# $Id: features.py,v 1.22 2005/09/30 20:13:04 mikealbon Exp $
"""
Different stuff that wasn't worth separating it into modules
(Registration, Privacy Lists, ...)
"""
from protocol import NS_REGISTER, NS_PRIVACY, NS_DATA, Iq, isResultNode, Node
def _on_default_response(disp, iq, cb):
def _on_response(resp):
if isResultNode(resp):
if cb:
cb(True)
elif cb:
cb(False)
disp.SendAndCallForResponse(iq, _on_response)
###############################################################################
### Registration
###############################################################################
REGISTER_DATA_RECEIVED = 'REGISTER DATA RECEIVED'
def getRegInfo(disp, host, info={}, sync=True):
"""
Get registration form from remote host. Info dict can be prefilled
:param disp: plugged dispatcher instance
:param info: dict, like {'username':'joey'}.
See JEP-0077 for details.
"""
iq=Iq('get', NS_REGISTER, to=host)
for i in info.keys():
iq.setTagData(i, info[i])
if sync:
disp.SendAndCallForResponse(iq, lambda resp:
_ReceivedRegInfo(disp.Dispatcher, resp, host))
else:
disp.SendAndCallForResponse(iq, _ReceivedRegInfo, {'agent': host })
def _ReceivedRegInfo(con, resp, agent):
Iq('get', NS_REGISTER, to=agent)
if not isResultNode(resp):
error_msg = resp.getErrorMsg()
con.Event(NS_REGISTER, REGISTER_DATA_RECEIVED, (agent, None, False, error_msg, ''))
return
tag=resp.getTag('query', namespace=NS_REGISTER)
if not tag:
error_msg = resp.getErrorMsg()
con.Event(NS_REGISTER, REGISTER_DATA_RECEIVED, (agent, None, False, error_msg, ''))
return
df=tag.getTag('x', namespace=NS_DATA)
if df:
con.Event(NS_REGISTER, REGISTER_DATA_RECEIVED, (agent, df, True, '',
tag))
return
df={}
for i in resp.getQueryPayload():
if not isinstance(i, Node):
continue
df[i.getName()] = i.getData()
con.Event(NS_REGISTER, REGISTER_DATA_RECEIVED, (agent, df, False, '', ''))
def register(disp, host, info, cb, args=None):
"""
Perform registration on remote server with provided info
If registration fails you can get additional info from the dispatcher's
owner attributes lastErrNode, lastErr and lastErrCode.
"""
iq=Iq('set', NS_REGISTER, to=host)
if not isinstance(info, dict):
info=info.asDict()
for i in info.keys():
iq.setTag('query').setTagData(i, info[i])
disp.SendAndCallForResponse(iq, cb, args)
def unregister(disp, host, cb):
"""
Unregisters with host (permanently removes account). Returns true on success
"""
iq = Iq('set', NS_REGISTER, to=host, payload=[Node('remove')])
_on_default_response(disp, iq, cb)
def changePasswordTo(disp, newpassword, host=None, cb = None):
"""
Changes password on specified or current (if not specified) server. Returns
true on success.
"""
if not host:
host = disp._owner.Server
iq = Iq('set', NS_REGISTER, to=host, payload=[Node('username',
payload=[disp._owner.Server]), Node('password', payload=[newpassword])])
_on_default_response(disp, iq, cb)
###############################################################################
### Privacy List
###############################################################################
PL_TYPE_JID = 'jid'
PL_TYPE_GROUP = 'group'
PL_TYPE_SUBC = 'subscription'
PL_ACT_ALLOW = 'allow'
PL_ACT_DENY = 'deny'
PRIVACY_LISTS_RECEIVED = 'PRIVACY LISTS RECEIVED'
PRIVACY_LIST_RECEIVED = 'PRIVACY LIST RECEIVED'
PRIVACY_LISTS_ACTIVE_DEFAULT = 'PRIVACY LISTS ACTIVE DEFAULT'
def getPrivacyLists(disp):
"""
Request privacy lists from connected server. Returns dictionary of existing
lists on success.
"""
iq = Iq('get', NS_PRIVACY)
def _on_response(resp):
dict_ = {'lists': []}
if not isResultNode(resp):
disp.Event(NS_PRIVACY, PRIVACY_LISTS_RECEIVED, (False))
return
for list_ in resp.getQueryPayload():
if list_.getName()=='list':
dict_['lists'].append(list_.getAttr('name'))
else:
dict_[list_.getName()]=list_.getAttr('name')
disp.Event(NS_PRIVACY, PRIVACY_LISTS_RECEIVED, (dict_))
disp.SendAndCallForResponse(iq, _on_response)
def getActiveAndDefaultPrivacyLists(disp):
iq = Iq('get', NS_PRIVACY)
def _on_response(resp):
dict_ = {'active': '', 'default': ''}
if not isResultNode(resp):
disp.Event(NS_PRIVACY, PRIVACY_LISTS_ACTIVE_DEFAULT, (False))
return
for list_ in resp.getQueryPayload():
if list_.getName() == 'active':
dict_['active'] = list_.getAttr('name')
elif list_.getName() == 'default':
dict_['default'] = list_.getAttr('name')
disp.Event(NS_PRIVACY, PRIVACY_LISTS_ACTIVE_DEFAULT, (dict_))
disp.SendAndCallForResponse(iq, _on_response)
def getPrivacyList(disp, listname):
"""
Request specific privacy list listname. Returns list of XML nodes (rules)
taken from the server responce.
"""
def _on_response(resp):
if not isResultNode(resp):
disp.Event(NS_PRIVACY, PRIVACY_LIST_RECEIVED, (False))
return
disp.Event(NS_PRIVACY, PRIVACY_LIST_RECEIVED, (resp))
iq = Iq('get', NS_PRIVACY, payload=[Node('list', {'name': listname})])
disp.SendAndCallForResponse(iq, _on_response)
def setActivePrivacyList(disp, listname=None, typ='active', cb=None):
"""
Switch privacy list 'listname' to specified type. By default the type is
'active'. Returns true on success.
"""
if listname:
attrs={'name':listname}
else:
attrs={}
iq = Iq('set', NS_PRIVACY, payload=[Node(typ, attrs)])
_on_default_response(disp, iq, cb)
def setDefaultPrivacyList(disp, listname=None):
"""
Set the default privacy list as 'listname'. Returns true on success
"""
return setActivePrivacyList(disp, listname, 'default')
def setPrivacyList(disp, listname, tags):
"""
Set the ruleset
'list' should be the simpleXML node formatted according to RFC 3921
(XMPP-IM) I.e. Node('list',{'name':listname},payload=[...]).
Returns true on success.
"""
iq = Iq('set', NS_PRIVACY, xmlns = '')
list_query = iq.getTag('query').setTag('list', {'name': listname})
for item in tags:
if 'type' in item and 'value' in item:
item_tag = list_query.setTag('item', {'action': item['action'],
'order': item['order'], 'type': item['type'],
'value': item['value']})
else:
item_tag = list_query.setTag('item', {'action': item['action'],
'order': item['order']})
if 'child' in item:
for child_tag in item['child']:
item_tag.setTag(child_tag)
_on_default_response(disp, iq, None)
def delPrivacyList(disp, listname, cb=None):
''' Deletes privacy list 'listname'. Returns true on success. '''
iq = Iq('set', NS_PRIVACY, payload=[Node('list', {'name':listname})])
_on_default_response(disp, iq, cb)

View File

@ -1,550 +0,0 @@
## idlequeue.py
##
## Copyright (C) 2006 Dimitur Kirov <dkirov@gmail.com>
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2, or (at your option)
## any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
"""
Idlequeues are Gajim's network heartbeat. Transports can be plugged as idle
objects and be informed about possible IO
"""
import os
import select
import logging
log = logging.getLogger('gajim.c.x.idlequeue')
# needed for get_idleqeue
try:
import gobject
HAVE_GOBJECT = True
except ImportError:
HAVE_GOBJECT = False
# needed for idlecommand
if os.name == 'nt':
from subprocess import * # python24 only. we ask this for Windows
elif os.name == 'posix':
import fcntl
FLAG_WRITE = 20 # write only
FLAG_READ = 19 # read only
FLAG_READ_WRITE = 23 # read and write
FLAG_CLOSE = 16 # wait for close
PENDING_READ = 3 # waiting read event
PENDING_WRITE = 4 # waiting write event
IS_CLOSED = 16 # channel closed
def get_idlequeue():
"""
Get an appropriate idlequeue
"""
if os.name == 'nt':
# gobject.io_add_watch does not work on windows
return SelectIdleQueue()
else:
if HAVE_GOBJECT:
# Gajim's default Idlequeue
return GlibIdleQueue()
else:
# GUI less implementation
return SelectIdleQueue()
class IdleObject:
"""
Idle listener interface. Listed methods are called by IdleQueue.
"""
def __init__(self):
self.fd = -1 #: filedescriptor, must be unique for each IdleObject
def pollend(self):
"""
Called on stream failure
"""
pass
def pollin(self):
"""
Called on new read event
"""
pass
def pollout(self):
"""
Called on new write event (connect in sockets is a pollout)
"""
pass
def read_timeout(self):
"""
Called when timeout happened
"""
pass
class IdleCommand(IdleObject):
"""
Can be subclassed to execute commands asynchronously by the idlequeue.
Result will be optained via file descriptor of created pipe
"""
def __init__(self, on_result):
IdleObject.__init__(self)
# how long (sec.) to wait for result ( 0 - forever )
# it is a class var, instead of a constant and we can override it.
self.commandtimeout = 0
# when we have some kind of result (valid, ot not) we call this handler
self.result_handler = on_result
# if it is True, we can safetely execute the command
self.canexecute = True
self.idlequeue = None
self.result =''
def set_idlequeue(self, idlequeue):
self.idlequeue = idlequeue
def _return_result(self):
if self.result_handler:
self.result_handler(self.result)
self.result_handler = None
def _compose_command_args(self):
return ['echo', 'da']
def _compose_command_line(self):
"""
Return one line representation of command and its arguments
"""
return reduce(lambda left, right: left + ' ' + right,
self._compose_command_args())
def wait_child(self):
if self.pipe.poll() is None:
# result timeout
if self.endtime < self.idlequeue.current_time():
self._return_result()
self.pipe.stdout.close()
self.pipe.stdin.close()
else:
# child is still active, continue to wait
self.idlequeue.set_alarm(self.wait_child, 0.1)
else:
# child has quit
self.result = self.pipe.stdout.read()
self._return_result()
self.pipe.stdout.close()
self.pipe.stdin.close()
def start(self):
if not self.canexecute:
self.result = ''
self._return_result()
return
if os.name == 'nt':
self._start_nt()
elif os.name == 'posix':
self._start_posix()
def _start_nt(self):
# if gajim is started from noninteraactive shells stdin is closed and
# cannot be forwarded, so we have to keep it open
self.pipe = Popen(self._compose_command_args(), stdout=PIPE,
bufsize = 1024, shell = True, stderr = STDOUT, stdin = PIPE)
if self.commandtimeout >= 0:
self.endtime = self.idlequeue.current_time() + self.commandtimeout
self.idlequeue.set_alarm(self.wait_child, 0.1)
def _start_posix(self):
self.pipe = os.popen(self._compose_command_line())
self.fd = self.pipe.fileno()
fcntl.fcntl(self.pipe, fcntl.F_SETFL, os.O_NONBLOCK)
self.idlequeue.plug_idle(self, False, True)
if self.commandtimeout >= 0:
self.idlequeue.set_read_timeout(self.fd, self.commandtimeout)
def end(self):
self.idlequeue.unplug_idle(self.fd)
try:
self.pipe.close()
except:
pass
def pollend(self):
self.idlequeue.remove_timeout(self.fd)
self.end()
self._return_result()
def pollin(self):
try:
res = self.pipe.read()
except Exception, e:
res = ''
if res == '':
return self.pollend()
else:
self.result += res
def read_timeout(self):
self.end()
self._return_result()
class IdleQueue:
"""
IdleQueue provide three distinct time based features. Uses select.poll()
1. Alarm timeout: Execute a callback after foo seconds
2. Timeout event: Call read_timeout() of an plugged object if a timeout
has been set, but not removed in time.
3. Check file descriptor of plugged objects for read, write and error
events
"""
# (timeout, boolean)
# Boolean is True if timeout is specified in seconds, False means miliseconds
PROCESS_TIMEOUT = (100, False)
def __init__(self):
self.queue = {}
# when there is a timeout it executes obj.read_timeout()
# timeout is not removed automatically!
# {fd1: {timeout1: func1, timeout2: func2}}
# timout are unique (timeout1 must be != timeout2)
# If func1 is None, read_time function is called
self.read_timeouts = {}
# cb, which are executed after XX sec., alarms are removed automatically
self.alarms = {}
self._init_idle()
def _init_idle(self):
"""
Hook method for subclassed. Will be called by __init__
"""
self.selector = select.poll()
def set_alarm(self, alarm_cb, seconds):
"""
Set up a new alarm. alarm_cb will be called after specified seconds.
"""
alarm_time = self.current_time() + seconds
# almost impossible, but in case we have another alarm_cb at this time
if alarm_time in self.alarms:
self.alarms[alarm_time].append(alarm_cb)
else:
self.alarms[alarm_time] = [alarm_cb]
return alarm_time
def remove_alarm(self, alarm_cb, alarm_time):
"""
Remove alarm callback alarm_cb scheduled on alarm_time. Returns True if
it was removed sucessfully, otherwise False
"""
if not alarm_time in self.alarms:
return False
i = -1
for i in range(len(self.alarms[alarm_time])):
# let's not modify the list inside the loop
if self.alarms[alarm_time][i] is alarm_cb:
break
if i != -1:
del self.alarms[alarm_time][i]
if self.alarms[alarm_time] == []:
del self.alarms[alarm_time]
return True
else:
return False
def remove_timeout(self, fd, timeout=None):
"""
Remove the read timeout
"""
log.info('read timeout removed for fd %s' % fd)
if fd in self.read_timeouts:
if timeout:
if timeout in self.read_timeouts[fd]:
del(self.read_timeouts[fd][timeout])
if len(self.read_timeouts[fd]) == 0:
del(self.read_timeouts[fd])
else:
del(self.read_timeouts[fd])
def set_read_timeout(self, fd, seconds, func=None):
"""
Seta a new timeout. If it is not removed after specified seconds,
func or obj.read_timeout() will be called
A filedescriptor fd can have several timeouts.
"""
log_txt = 'read timeout set for fd %s on %s seconds' % (fd, seconds)
if func:
log_txt += ' with function ' + str(func)
log.info(log_txt)
timeout = self.current_time() + seconds
if fd in self.read_timeouts:
self.read_timeouts[fd][timeout] = func
else:
self.read_timeouts[fd] = {timeout: func}
def _check_time_events(self):
"""
Execute and remove alarm callbacks and execute func() or read_timeout()
for plugged objects if specified time has ellapsed
"""
current_time = self.current_time()
for fd, timeouts in self.read_timeouts.items():
if fd not in self.queue:
self.remove_timeout(fd)
continue
for timeout, func in timeouts.items():
if timeout > current_time:
continue
if func:
log.debug('Calling %s for fd %s' % (func, fd))
func()
else:
log.debug('Calling read_timeout for fd %s' % fd)
self.queue[fd].read_timeout()
self.remove_timeout(fd, timeout)
times = self.alarms.keys()
for alarm_time in times:
if alarm_time > current_time:
continue
if alarm_time in self.alarms:
for callback in self.alarms[alarm_time]:
callback()
if alarm_time in self.alarms:
del(self.alarms[alarm_time])
def plug_idle(self, obj, writable=True, readable=True):
"""
Plug an IdleObject into idlequeue. Filedescriptor fd must be set
:param obj: the IdleObject
:param writable: True if obj has data to sent
:param readable: True if obj expects data to be reiceived
"""
if obj.fd == -1:
return
if obj.fd in self.queue:
self.unplug_idle(obj.fd)
self.queue[obj.fd] = obj
if writable:
if not readable:
flags = FLAG_WRITE
else:
flags = FLAG_READ_WRITE
else:
if readable:
flags = FLAG_READ
else:
# when we paused a FT, we expect only a close event
flags = FLAG_CLOSE
self._add_idle(obj.fd, flags)
def _add_idle(self, fd, flags):
"""
Hook method for subclasses, called by plug_idle
"""
self.selector.register(fd, flags)
def unplug_idle(self, fd):
"""
Remove plugged IdleObject, specified by filedescriptor fd
"""
if fd in self.queue:
del(self.queue[fd])
self._remove_idle(fd)
def current_time(self):
from time import time
return time()
def _remove_idle(self, fd):
"""
Hook method for subclassed, called by unplug_idle
"""
self.selector.unregister(fd)
def _process_events(self, fd, flags):
obj = self.queue.get(fd)
if obj is None:
self.unplug_idle(fd)
return False
read_write = False
if flags & PENDING_READ:
#print 'waiting read on %d, flags are %d' % (fd, flags)
obj.pollin()
read_write = True
elif flags & PENDING_WRITE and not flags & IS_CLOSED:
obj.pollout()
read_write = True
if flags & IS_CLOSED:
# io error, don't expect more events
self.remove_timeout(obj.fd)
self.unplug_idle(obj.fd)
obj.pollend()
return False
if read_write:
return True
return False
def process(self):
"""
Process idlequeue. Check for any pending timeout or alarm events. Call
IdleObjects on possible and requested read, write and error events on
their file descriptors
Call this in regular intervals.
"""
if not self.queue:
# check for timeouts/alert also when there are no active fds
self._check_time_events()
return True
try:
waiting_descriptors = self.selector.poll(0)
except select.error, e:
waiting_descriptors = []
if e[0] != 4: # interrupt
raise
for fd, flags in waiting_descriptors:
self._process_events(fd, flags)
self._check_time_events()
return True
class SelectIdleQueue(IdleQueue):
"""
Extends IdleQueue to use select.select() for polling
This class exisists for the sake of gtk2.8 on windows, which doesn't seem to
support io_add_watch properly (yet)
"""
def _init_idle(self):
"""
Create a dict, which maps file/pipe/sock descriptor to glib event id
"""
self.read_fds = {}
self.write_fds = {}
self.error_fds = {}
def _add_idle(self, fd, flags):
"""
This method is called when we plug a new idle object. Remove descriptor
to read/write/error lists, according flags
"""
if flags & 3:
self.read_fds[fd] = fd
if flags & 4:
self.write_fds[fd] = fd
self.error_fds[fd] = fd
def _remove_idle(self, fd):
"""
This method is called when we unplug a new idle object. Remove descriptor
from read/write/error lists
"""
if fd in self.read_fds:
del(self.read_fds[fd])
if fd in self.write_fds:
del(self.write_fds[fd])
if fd in self.error_fds:
del(self.error_fds[fd])
def process(self):
if not self.write_fds and not self.read_fds:
self._check_time_events()
return True
try:
waiting_descriptors = select.select(self.read_fds.keys(),
self.write_fds.keys(), self.error_fds.keys(), 0)
except select.error, e:
waiting_descriptors = ((), (), ())
if e[0] != 4: # interrupt
raise
for fd in waiting_descriptors[0]:
q = self.queue.get(fd)
if q:
q.pollin()
for fd in waiting_descriptors[1]:
q = self.queue.get(fd)
if q:
q.pollout()
for fd in waiting_descriptors[2]:
q = self.queue.get(fd)
if q:
q.pollend()
self._check_time_events()
return True
class GlibIdleQueue(IdleQueue):
"""
Extends IdleQueue to use glib io_add_wath, instead of select/poll In another
'non gui' implementation of Gajim IdleQueue can be used safetly
"""
# (timeout, boolean)
# Boolean is True if timeout is specified in seconds, False means miliseconds
PROCESS_TIMEOUT = (2, True)
def _init_idle(self):
"""
Creates a dict, which maps file/pipe/sock descriptor to glib event id
"""
self.events = {}
# time() is already called in glib, we just get the last value
# overrides IdleQueue.current_time()
self.current_time = gobject.get_current_time
def _add_idle(self, fd, flags):
"""
This method is called when we plug a new idle object. Start listening for
events from fd
"""
res = gobject.io_add_watch(fd, flags, self._process_events,
priority=gobject.PRIORITY_LOW)
# store the id of the watch, so that we can remove it on unplug
self.events[fd] = res
def _process_events(self, fd, flags):
try:
return IdleQueue._process_events(self, fd, flags)
except Exception:
self._remove_idle(fd)
self._add_idle(fd, flags)
raise
def _remove_idle(self, fd):
"""
This method is called when we unplug a new idle object. Stop listening
for events from fd
"""
if not fd in self.events:
return
gobject.source_remove(self.events[fd])
del(self.events[fd])
def process(self):
self._check_time_events()

View File

@ -1,96 +0,0 @@
## plugin.py
##
## Copyright (C) 2003-2005 Alexey "Snake" Nezhdanov
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2, or (at your option)
## any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
# $Id: client.py,v 1.52 2006/01/02 19:40:55 normanr Exp $
"""
Provides PlugIn class functionality to develop extentions for xmpppy
"""
import logging
log = logging.getLogger('gajim.c.x.plugin')
class PlugIn:
"""
Abstract xmpppy plugin infrastructure code, providing plugging in/out and
debugging functionality
Inherit to develop pluggable objects. No code change on the owner class
required (the object where we plug into)
For every instance of PlugIn class the 'owner' is the class in what the plug
was plugged.
"""
def __init__(self):
self._exported_methods=[]
def PlugIn(self, owner):
"""
Attach to owner and register ourself and our _exported_methods in it.
If defined by a subclass, call self.plugin(owner) to execute hook
code after plugging
"""
self._owner=owner
log.info('Plugging %s __INTO__ %s' % (self, self._owner))
if self.__class__.__name__ in owner.__dict__:
log.debug('Plugging ignored: another instance already plugged.')
return
self._old_owners_methods=[]
for method in self._exported_methods:
if method.__name__ in owner.__dict__:
self._old_owners_methods.append(owner.__dict__[method.__name__])
owner.__dict__[method.__name__]=method
if self.__class__.__name__.endswith('Dispatcher'):
# FIXME: I need BOSHDispatcher or XMPPDispatcher on .Dispatcher
# there must be a better way..
owner.__dict__['Dispatcher']=self
else:
owner.__dict__[self.__class__.__name__]=self
# Execute hook
if hasattr(self, 'plugin'):
return self.plugin(owner)
def PlugOut(self):
"""
Unregister our _exported_methods from owner and detach from it.
If defined by a subclass, call self.plugout() after unplugging to execute
hook code
"""
log.info('Plugging %s __OUT__ of %s.' % (self, self._owner))
for method in self._exported_methods:
del self._owner.__dict__[method.__name__]
for method in self._old_owners_methods:
self._owner.__dict__[method.__name__]=method
# FIXME: Dispatcher workaround
if self.__class__.__name__.endswith('Dispatcher'):
del self._owner.__dict__['Dispatcher']
else:
del self._owner.__dict__[self.__class__.__name__]
# Execute hook
if hasattr(self, 'plugout'):
return self.plugout()
del self._owner
@classmethod
def get_instance(cls, *args, **kwargs):
"""
Factory Method for object creation
Use this instead of directly initializing the class in order to make
unit testing easier. For testing, this method can be patched to inject
mock objects.
"""
return cls(*args, **kwargs)

File diff suppressed because it is too large Load Diff

View File

@ -1,238 +0,0 @@
## proxy_connectors.py
## based on transports_nb.py
##
## Copyright (C) 2003-2004 Alexey "Snake" Nezhdanov
## modified by Dimitur Kirov <dkirov@gmail.com>
## modified by Tomas Karasek <tom.to.the.k@gmail.com>
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2, or (at your option)
## any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
"""
Module containing classes for proxy connecting. So far its HTTP CONNECT and
SOCKS5 proxy
Authentication to NTLM (Microsoft implementation) proxies can be next.
"""
import struct, socket, base64
import logging
log = logging.getLogger('gajim.c.x.proxy_connectors')
class ProxyConnector:
"""
Interface for proxy-connecting object - when tunnneling XMPP over proxies,
some connecting process usually has to be done before opening stream. Proxy
connectors are used right after TCP connection is estabilished
"""
def __init__(self, send_method, onreceive, old_on_receive, on_success,
on_failure, xmpp_server, proxy_creds=(None, None)):
"""
Creates proxy connector, starts connecting immediately and gives control
back to transport afterwards
:param send_method: transport send method
:param onreceive: method to set on_receive callbacks
:param old_on_receive: on_receive callback that should be set when
proxy connection was successful
:param on_success: called after proxy connection was successfully opened
:param on_failure: called when errors occured while connecting
:param xmpp_server: tuple of (hostname, port)
:param proxy_creds: tuple of (proxy_user, proxy_credentials)
"""
self.send = send_method
self.onreceive = onreceive
self.old_on_receive = old_on_receive
self.on_success = on_success
self.on_failure = on_failure
self.xmpp_server = xmpp_server
self.proxy_user, self.proxy_pass = proxy_creds
self.old_on_receive = old_on_receive
self.start_connecting()
@classmethod
def get_instance(cls, *args, **kwargs):
"""
Factory Method for object creation
Use this instead of directly initializing the class in order to make unit
testing much easier.
"""
return cls(*args, **kwargs)
def start_connecting(self):
raise NotImplementedError
def connecting_over(self):
self.onreceive(self.old_on_receive)
self.on_success()
class HTTPCONNECTConnector(ProxyConnector):
def start_connecting(self):
"""
Connect to a proxy, supply login and password to it (if were specified
while creating instance). Instruct proxy to make connection to the target
server.
"""
log.info('Proxy server contacted, performing authentification')
connector = ['CONNECT %s:%s HTTP/1.1' % self.xmpp_server,
'Proxy-Connection: Keep-Alive',
'Pragma: no-cache',
'Host: %s:%s' % self.xmpp_server,
'User-Agent: Gajim']
if self.proxy_user and self.proxy_pass:
credentials = '%s:%s' % (self.proxy_user, self.proxy_pass)
credentials = base64.encodestring(credentials).strip()
connector.append('Proxy-Authorization: Basic '+credentials)
connector.append('\r\n')
self.onreceive(self._on_headers_sent)
self.send('\r\n'.join(connector))
def _on_headers_sent(self, reply):
if reply is None:
return
self.reply = reply.replace('\r', '')
try:
proto, code, desc = reply.split('\n')[0].split(' ', 2)
except:
log.error("_on_headers_sent:", exc_info=True)
#traceback.print_exc()
self.on_failure('Invalid proxy reply')
return
if code <> '200':
log.error('Invalid proxy reply: %s %s %s' % (proto, code, desc))
self.on_failure('Invalid proxy reply')
return
if len(reply) != 2:
pass
self.connecting_over()
class SOCKS5Connector(ProxyConnector):
"""
SOCKS5 proxy connection class. Allows to use SOCKS5 proxies with
(optionally) simple authentication (only USERNAME/PASSWORD auth)
"""
def start_connecting(self):
log.info('Proxy server contacted, performing authentification')
if self.proxy_user and self.proxy_pass:
to_send = '\x05\x02\x00\x02'
else:
to_send = '\x05\x01\x00'
self.onreceive(self._on_greeting_sent)
self.send(to_send)
def _on_greeting_sent(self, reply):
if reply is None:
return
if len(reply) != 2:
self.on_failure('Invalid proxy reply')
return
if reply[0] != '\x05':
log.info('Invalid proxy reply')
self.on_failure('Invalid proxy reply')
return
if reply[1] == '\x00':
return self._on_proxy_auth('\x01\x00')
elif reply[1] == '\x02':
to_send = '\x01' + chr(len(self.proxy_user)) + self.proxy_user +\
chr(len(self.proxy_pass)) + self.proxy_pass
self.onreceive(self._on_proxy_auth)
self.send(to_send)
else:
if reply[1] == '\xff':
log.error('Authentification to proxy impossible: no acceptable '
'auth method')
self.on_failure('Authentification to proxy impossible: no '
'acceptable authentification method')
return
log.error('Invalid proxy reply')
self.on_failure('Invalid proxy reply')
return
def _on_proxy_auth(self, reply):
if reply is None:
return
if len(reply) != 2:
log.error('Invalid proxy reply')
self.on_failure('Invalid proxy reply')
return
if reply[0] != '\x01':
log.error('Invalid proxy reply')
self.on_failure('Invalid proxy reply')
return
if reply[1] != '\x00':
log.error('Authentification to proxy failed')
self.on_failure('Authentification to proxy failed')
return
log.info('Authentification successfull. Jabber server contacted.')
# Request connection
req = "\x05\x01\x00"
# If the given destination address is an IP address, we'll
# use the IPv4 address request even if remote resolving was specified.
try:
self.ipaddr = socket.inet_aton(self.xmpp_server[0])
req = req + "\x01" + self.ipaddr
except socket.error:
# Well it's not an IP number, so it's probably a DNS name.
# if self.__proxy[3]==True:
# Resolve remotely
self.ipaddr = None
req = req + "\x03" + chr(len(self.xmpp_server[0])) + self.xmpp_server[0]
# else:
# # Resolve locally
# self.ipaddr = socket.inet_aton(socket.gethostbyname(self.xmpp_server[0]))
# req = req + "\x01" + ipaddr
req = req + struct.pack(">H", self.xmpp_server[1])
self.onreceive(self._on_req_sent)
self.send(req)
def _on_req_sent(self, reply):
if reply is None:
return
if len(reply) < 10:
log.error('Invalid proxy reply')
self.on_failure('Invalid proxy reply')
return
if reply[0] != '\x05':
log.error('Invalid proxy reply')
self.on_failure('Invalid proxy reply')
return
if reply[1] != "\x00":
# Connection failed
if ord(reply[1])<9:
errors = ['general SOCKS server failure',
'connection not allowed by ruleset',
'Network unreachable',
'Host unreachable',
'Connection refused',
'TTL expired',
'Command not supported',
'Address type not supported'
]
txt = errors[ord(reply[1])-1]
else:
txt = 'Invalid proxy reply'
log.error(txt)
self.on_failure(txt)
return
# Get the bound address/port
elif reply[3] == "\x01":
begin, end = 3, 7
elif reply[3] == "\x03":
begin, end = 4, 4 + reply[4]
else:
log.error('Invalid proxy reply')
self.on_failure('Invalid proxy reply')
return
self.connecting_over()

View File

@ -1,368 +0,0 @@
## roster_nb.py
## based on roster.py
##
## Copyright (C) 2003-2005 Alexey "Snake" Nezhdanov
## modified by Dimitur Kirov <dkirov@gmail.com>
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2, or (at your option)
## any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
# $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
mass-renaming of contacts.
"""
from protocol import JID, Iq, Presence, Node, NodeProcessed, NS_MUC_USER, NS_ROSTER
from plugin import PlugIn
import logging
log = logging.getLogger('gajim.c.x.roster_nb')
class NonBlockingRoster(PlugIn):
"""
Defines a plenty of methods that will allow you to manage roster. Also
automatically track presences from remote JIDs taking into account that
every JID can have multiple resources connected. Does not currently support
'error' presences. You can also use mapping interface for access to the
internal representation of contacts in roster
"""
def __init__(self, version=None):
"""
Init internal variables
"""
PlugIn.__init__(self)
self.version = version
self._data = {}
self._set=None
self._exported_methods=[self.getRoster]
self.received_from_server = False
def Request(self, force=0):
"""
Request roster from server if it were not yet requested (or if the
'force' argument is set)
"""
if self._set is None:
self._set = 0
elif not force:
return
iq = Iq('get', NS_ROSTER)
if self.version is not None:
iq.setTagAttr('query', 'ver', self.version)
id_ = self._owner.getAnID()
iq.setID(id_)
self._owner.send(iq)
log.info('Roster requested from server')
return id_
def RosterIqHandler(self, dis, stanza):
"""
Subscription tracker. Used internally for setting items state in internal
roster representation
"""
sender = stanza.getAttr('from')
if not sender is None and not sender.bareMatch(
self._owner.User + '@' + self._owner.Server):
return
query = stanza.getTag('query')
if query:
self.received_from_server = True
self.version = stanza.getTagAttr('query', 'ver')
if self.version is None:
self.version = ''
for item in query.getTags('item'):
jid=item.getAttr('jid')
if item.getAttr('subscription')=='remove':
if self._data.has_key(jid): del self._data[jid]
# Looks like we have a workaround
# raise NodeProcessed # a MUST
log.info('Setting roster item %s...' % jid)
if not self._data.has_key(jid): self._data[jid]={}
self._data[jid]['name']=item.getAttr('name')
self._data[jid]['ask']=item.getAttr('ask')
self._data[jid]['subscription']=item.getAttr('subscription')
self._data[jid]['groups']=[]
if not self._data[jid].has_key('resources'): self._data[jid]['resources']={}
for group in item.getTags('group'):
if group.getData() not in self._data[jid]['groups']:
self._data[jid]['groups'].append(group.getData())
self._data[self._owner.User+'@'+self._owner.Server]={'resources': {}, 'name': None, 'ask': None, 'subscription': None, 'groups': None,}
self._set=1
# Looks like we have a workaround
# raise NodeProcessed # a MUST. Otherwise you'll get back an <iq type='error'/>
def PresenceHandler(self, dis, pres):
"""
Presence tracker. Used internally for setting items' resources state in
internal roster representation
"""
if pres.getTag('x', namespace=NS_MUC_USER):
return
jid=pres.getFrom()
if not jid:
# If no from attribue, it's from server
jid=self._owner.Server
jid=JID(jid)
if not self._data.has_key(jid.getStripped()): self._data[jid.getStripped()]={'name':None,'ask':None,'subscription':'none','groups':['Not in roster'],'resources':{}}
if type(self._data[jid.getStripped()]['resources'])!=type(dict()):
self._data[jid.getStripped()]['resources']={}
item=self._data[jid.getStripped()]
typ=pres.getType()
if not typ:
log.info('Setting roster item %s for resource %s...'%(jid.getStripped(), jid.getResource()))
item['resources'][jid.getResource()]=res={'show':None,'status':None,'priority':'0','timestamp':None}
if pres.getTag('show'): res['show']=pres.getShow()
if pres.getTag('status'): res['status']=pres.getStatus()
if pres.getTag('priority'): res['priority']=pres.getPriority()
if not pres.getTimestamp(): pres.setTimestamp()
res['timestamp']=pres.getTimestamp()
elif typ=='unavailable' and item['resources'].has_key(jid.getResource()): del item['resources'][jid.getResource()]
# Need to handle type='error' also
def _getItemData(self, jid, dataname):
"""
Return specific jid's representation in internal format. Used internally
"""
jid = jid[:(jid+'/').find('/')]
return self._data[jid][dataname]
def _getResourceData(self, jid, dataname):
"""
Return specific jid's resource representation in internal format. Used
internally
"""
if jid.find('/') + 1:
jid, resource = jid.split('/', 1)
if self._data[jid]['resources'].has_key(resource):
return self._data[jid]['resources'][resource][dataname]
elif self._data[jid]['resources'].keys():
lastpri = -129
for r in self._data[jid]['resources'].keys():
if int(self._data[jid]['resources'][r]['priority']) > lastpri:
resource, lastpri=r, int(self._data[jid]['resources'][r]['priority'])
return self._data[jid]['resources'][resource][dataname]
def delItem(self, jid):
"""
Delete contact 'jid' from roster
"""
self._owner.send(Iq('set', NS_ROSTER, payload=[Node('item', {'jid': jid, 'subscription': 'remove'})]))
def getAsk(self, jid):
"""
Return 'ask' value of contact 'jid'
"""
return self._getItemData(jid, 'ask')
def getGroups(self, jid):
"""
Return groups list that contact 'jid' belongs to
"""
return self._getItemData(jid, 'groups')
def getName(self, jid):
"""
Return name of contact 'jid'
"""
return self._getItemData(jid, 'name')
def getPriority(self, jid):
"""
Return priority of contact 'jid'. 'jid' should be a full (not bare) JID
"""
return self._getResourceData(jid, 'priority')
def getRawRoster(self):
"""
Return roster representation in internal format
"""
return self._data
def getRawItem(self, jid):
"""
Return roster item 'jid' representation in internal format
"""
return self._data[jid[:(jid+'/').find('/')]]
def getShow(self, jid):
"""
Return 'show' value of contact 'jid'. 'jid' should be a full (not bare)
JID
"""
return self._getResourceData(jid, 'show')
def getStatus(self, jid):
"""
Return 'status' value of contact 'jid'. 'jid' should be a full (not bare)
JID
"""
return self._getResourceData(jid, 'status')
def getSubscription(self, jid):
"""
Return 'subscription' value of contact 'jid'
"""
return self._getItemData(jid, 'subscription')
def getResources(self, jid):
"""
Return list of connected resources of contact 'jid'
"""
return self._data[jid[:(jid+'/').find('/')]]['resources'].keys()
def setItem(self, jid, name=None, groups=[]):
"""
Rename contact 'jid' and sets the groups list that it now belongs to
"""
iq = Iq('set', NS_ROSTER)
query = iq.getTag('query')
attrs = {'jid': jid}
if name:
attrs['name'] = name
item = query.setTag('item', attrs)
for group in groups:
item.addChild(node=Node('group', payload=[group]))
self._owner.send(iq)
def setItemMulti(self, items):
"""
Rename multiple contacts and sets their group lists
"""
iq = Iq('set', NS_ROSTER)
query = iq.getTag('query')
for i in items:
attrs = {'jid': i['jid']}
if i['name']:
attrs['name'] = i['name']
item = query.setTag('item', attrs)
for group in i['groups']:
item.addChild(node=Node('group', payload=[group]))
self._owner.send(iq)
def getItems(self):
"""
Return list of all [bare] JIDs that the roster is currently tracks
"""
return self._data.keys()
def keys(self):
"""
Same as getItems. Provided for the sake of dictionary interface
"""
return self._data.keys()
def __getitem__(self, item):
"""
Get the contact in the internal format. Raises KeyError if JID 'item' is
not in roster
"""
return self._data[item]
def getItem(self, item):
"""
Get the contact in the internal format (or None if JID 'item' is not in
roster)
"""
if self._data.has_key(item):
return self._data[item]
def Subscribe(self, jid):
"""
Send subscription request to JID 'jid'
"""
self._owner.send(Presence(jid, 'subscribe'))
def Unsubscribe(self, jid):
"""
Ask for removing our subscription for JID 'jid'
"""
self._owner.send(Presence(jid, 'unsubscribe'))
def Authorize(self, jid):
"""
Authorize JID 'jid'. Works only if these JID requested auth previously
"""
self._owner.send(Presence(jid, 'subscribed'))
def Unauthorize(self, jid):
"""
Unauthorise JID 'jid'. Use for declining authorisation request or for
removing existing authorization
"""
self._owner.send(Presence(jid, 'unsubscribed'))
def getRaw(self):
"""
Return the internal data representation of the roster
"""
return self._data
def setRaw(self, data):
"""
Return the internal data representation of the roster
"""
self._data = data
self._data[self._owner.User + '@' + self._owner.Server] = {
'resources': {},
'name': None,
'ask': None,
'subscription': None,
'groups': None
}
self._set = 1
def plugin(self, owner, request=1):
"""
Register presence and subscription trackers in the owner's dispatcher.
Also request roster from server if the 'request' argument is set. Used
internally
"""
self._owner.RegisterHandler('iq', self.RosterIqHandler, 'result', NS_ROSTER, makefirst = 1)
self._owner.RegisterHandler('iq', self.RosterIqHandler, 'set', NS_ROSTER)
self._owner.RegisterHandler('presence', self.PresenceHandler)
if request:
return self.Request()
def _on_roster_set(self, data):
if data:
self._owner.Dispatcher.ProcessNonBlocking(data)
if not self._set:
return
if not hasattr(self, '_owner') or not self._owner:
# Connection has been closed by receiving a <stream:error> for ex,
return
self._owner.onreceive(None)
if self.on_ready:
self.on_ready(self)
self.on_ready = None
return True
def getRoster(self, on_ready=None, force=False):
"""
Request roster from server if neccessary and returns self
"""
return_self = True
if not self._set:
self.on_ready = on_ready
self._owner.onreceive(self._on_roster_set)
return_self = False
elif on_ready:
on_ready(self)
return_self = False
if return_self or force:
return self
return None

View File

@ -1,692 +0,0 @@
## simplexml.py based on Mattew Allum's xmlstream.py
##
## Copyright (C) 2003-2005 Alexey "Snake" Nezhdanov
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2, or (at your option)
## any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
# $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. I'm personally using it in many other separate
projects. It is designed to be as standalone as possible
"""
import xml.parsers.expat
import logging
log = logging.getLogger('gajim.c.x.simplexml')
def XMLescape(txt):
"""
Return provided string with symbols & < > " replaced by their respective XML
entities
"""
# replace also FORM FEED and ESC, because they are not valid XML chars
return txt.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;").replace('"', "&quot;").replace(u'\x0C', "").replace(u'\x1B', "")
ENCODING='utf-8'
def ustr(what):
"""
Converts object "what" to unicode string using it's own __str__ method if
accessible or unicode method otherwise
"""
if isinstance(what, unicode):
return what
try:
r = what.__str__()
except AttributeError:
r = str(what)
if not isinstance(r, unicode):
return unicode(r, ENCODING)
return r
class Node(object):
"""
Node class describes syntax of separate XML Node. It have a constructor that
permits node creation from set of "namespace name", attributes and payload
of text strings and other nodes. It does not natively support building node
from text string and uses NodeBuilder class for that purpose. After
creation node can be mangled in many ways so it can be completely changed.
Also node can be serialised into string in one of two modes: default (where
the textual representation of node describes it exactly) and "fancy" - with
whitespace added to make indentation and thus make result more readable by
human.
Node class have attribute FORCE_NODE_RECREATION that is defaults to False
thus enabling fast node replication from the some other node. The drawback
of the fast way is that new node shares some info with the "original" node
that is changing the one node may influence the other. Though it is rarely
needed (in xmpppy it is never needed at all since I'm usually never using
original node after replication (and using replication only to move upwards
on the classes tree).
"""
FORCE_NODE_RECREATION = 0
def __init__(self, tag=None, attrs={}, payload=[], parent=None, nsp=None,
node_built=False, node=None):
"""
Takes "tag" argument as the name of node (prepended by namespace, if
needed and separated from it by a space), attrs dictionary as the set of
arguments, payload list as the set of textual strings and child nodes
that this node carries within itself and "parent" argument that is
another node that this one will be the child of. Also the __init__ can be
provided with "node" argument that is either a text string containing
exactly one node or another Node instance to begin with. If both "node"
and other arguments is provided then the node initially created as
replica of "node" provided and then modified to be compliant with other
arguments.
"""
if node:
if self.FORCE_NODE_RECREATION and isinstance(node, Node):
node = str(node)
if not isinstance(node, Node):
node = NodeBuilder(node, self)
node_built = True
else:
self.name, self.namespace, self.attrs, self.data, self.kids, self.parent, self.nsd = node.name, node.namespace, {}, [], [], node.parent, {}
for key in node.attrs.keys():
self.attrs[key] = node.attrs[key]
for data in node.data:
self.data.append(data)
for kid in node.kids:
self.kids.append(kid)
for k, v in node.nsd.items():
self.nsd[k] = v
else:
self.name, self.namespace, self.attrs, self.data, self.kids, self.parent, self.nsd = 'tag', '', {}, [], [], None, {}
if parent:
self.parent = parent
self.nsp_cache = {}
if nsp:
for k, v in nsp.items(): self.nsp_cache[k] = v
for attr, val in attrs.items():
if attr == 'xmlns':
self.nsd[u''] = val
elif attr.startswith('xmlns:'):
self.nsd[attr[6:]] = val
self.attrs[attr]=attrs[attr]
if tag:
if node_built:
pfx, self.name = (['']+tag.split(':'))[-2:]
self.namespace = self.lookup_nsp(pfx)
else:
if ' ' in tag:
self.namespace, self.name = tag.split()
else:
self.name = tag
if isinstance(payload, basestring): payload=[payload]
for i in payload:
if isinstance(i, Node):
self.addChild(node=i)
else:
self.data.append(ustr(i))
def lookup_nsp(self, pfx=''):
ns = self.nsd.get(pfx, None)
if ns is None:
ns = self.nsp_cache.get(pfx, None)
if ns is None:
if self.parent:
ns = self.parent.lookup_nsp(pfx)
self.nsp_cache[pfx] = ns
else:
return 'http://www.gajim.org/xmlns/undeclared'
return ns
def __str__(self, fancy=0):
"""
Method used to dump node into textual representation. If "fancy" argument
is set to True produces indented output for readability
"""
s = (fancy-1) * 2 * ' ' + "<" + self.name
if self.namespace:
if not self.parent or self.parent.namespace!=self.namespace:
if 'xmlns' not in self.attrs:
s = s + ' xmlns="%s"'%self.namespace
for key in self.attrs.keys():
val = ustr(self.attrs[key])
s = s + ' %s="%s"' % ( key, XMLescape(val) )
s = s + ">"
cnt = 0
if self.kids:
if fancy: s = s + "\n"
for a in self.kids:
if not fancy and (len(self.data)-1)>=cnt: s=s+XMLescape(self.data[cnt])
elif (len(self.data)-1)>=cnt: s=s+XMLescape(self.data[cnt].strip())
if isinstance(a, str) or isinstance(a, unicode):
s = s + a.__str__()
else:
s = s + a.__str__(fancy and fancy+1)
cnt=cnt+1
if not fancy and (len(self.data)-1) >= cnt: s = s + XMLescape(self.data[cnt])
elif (len(self.data)-1) >= cnt: s = s + XMLescape(self.data[cnt].strip())
if not self.kids and s.endswith('>'):
s=s[:-1]+' />'
if fancy: s = s + "\n"
else:
if fancy and not self.data: s = s + (fancy-1) * 2 * ' '
s = s + "</" + self.name + ">"
if fancy: s = s + "\n"
return s
def addChild(self, name=None, attrs={}, payload=[], namespace=None, node=None):
"""
If "node" argument is provided, adds it as child node. Else creates new
node from the other arguments' values and adds it as well
"""
if 'xmlns' in attrs:
raise AttributeError("Use namespace=x instead of attrs={'xmlns':x}")
if node:
newnode=node
node.parent = self
else: newnode=Node(tag=name, parent=self, attrs=attrs, payload=payload)
if namespace:
newnode.setNamespace(namespace)
self.kids.append(newnode)
return newnode
def addData(self, data):
"""
Add some CDATA to node
"""
self.data.append(ustr(data))
def clearData(self):
"""
Remove all CDATA from the node
"""
self.data = []
def delAttr(self, key):
"""
Delete an attribute "key"
"""
del self.attrs[key]
def delChild(self, node, attrs={}):
"""
Delete the "node" from the node's childs list, if "node" is an instance.
Else delete the first node that have specified name and (optionally)
attributes
"""
if not isinstance(node, Node):
node = self.getTag(node, attrs)
self.kids.remove(node)
return node
def getAttrs(self):
"""
Return all node's attributes as dictionary
"""
return self.attrs
def getAttr(self, key):
"""
Return value of specified attribute
"""
return self.attrs.get(key)
def getChildren(self):
"""
Return all node's child nodes as list
"""
return self.kids
def getData(self):
"""
Return all node CDATA as string (concatenated)
"""
return ''.join(self.data)
def getName(self):
"""
Return the name of node
"""
return self.name
def getNamespace(self):
"""
Return the namespace of node
"""
return self.namespace
def getParent(self):
"""
Returns the parent of node (if present)
"""
return self.parent
def getPayload(self):
"""
Return the payload of node i.e. list of child nodes and CDATA entries.
F.e. for "<node>text1<nodea/><nodeb/> text2</node>" will be returned
list: ['text1', <nodea instance>, <nodeb instance>, ' text2']
"""
ret = []
for i in range(len(self.kids)+len(self.data)+1):
try:
if self.data[i]:
ret.append(self.data[i])
except IndexError:
pass
try:
ret.append(self.kids[i])
except IndexError:
pass
return ret
def getTag(self, name, attrs={}, namespace=None):
"""
Filter all child nodes using specified arguments as filter. Return the
first found or None if not found
"""
return self.getTags(name, attrs, namespace, one=1)
def getTagAttr(self, tag, attr):
"""
Return attribute value of the child with specified name (or None if no
such attribute)
"""
try:
return self.getTag(tag).attrs[attr]
except:
return None
def getTagData(self, tag):
"""
Return cocatenated CDATA of the child with specified name
"""
try:
return self.getTag(tag).getData()
except Exception:
return None
def getTags(self, name, attrs={}, namespace=None, one=0):
"""
Filter all child nodes using specified arguments as filter. Returns the
list of nodes found
"""
nodes = []
for node in self.kids:
if namespace and namespace != node.getNamespace():
continue
if node.getName() == name:
for key in attrs.keys():
if key not in node.attrs or node.attrs[key]!=attrs[key]:
break
else:
nodes.append(node)
if one and nodes:
return nodes[0]
if not one:
return nodes
def iterTags(self, name, attrs={}, namespace=None):
"""
Iterate over all children using specified arguments as filter
"""
for node in self.kids:
if namespace is not None and namespace != node.getNamespace():
continue
if node.getName() == name:
for key in attrs.keys():
if key not in node.attrs or \
node.attrs[key]!=attrs[key]:
break
else:
yield node
def setAttr(self, key, val):
"""
Set attribute "key" with the value "val"
"""
self.attrs[key] = val
def setData(self, data):
"""
Set node's CDATA to provided string. Resets all previous CDATA!
"""
self.data = [ustr(data)]
def setName(self, val):
"""
Change the node name
"""
self.name = val
def setNamespace(self, namespace):
"""
Changes the node namespace
"""
self.namespace = namespace
def setParent(self, node):
"""
Set node's parent to "node". WARNING: do not checks if the parent already
present and not removes the node from the list of childs of previous
parent
"""
self.parent = node
def setPayload(self, payload, add=0):
"""
Set node payload according to the list specified. WARNING: completely
replaces all node's previous content. If you wish just to add child or
CDATA - use addData or addChild methods
"""
if isinstance(payload, basestring):
payload = [payload]
if add:
self.kids += payload
else:
self.kids = payload
def setTag(self, name, attrs={}, namespace=None):
"""
Same as getTag but if the node with specified namespace/attributes not
found, creates such node and returns it
"""
node = self.getTags(name, attrs, namespace=namespace, one=1)
if node:
return node
else:
return self.addChild(name, attrs, namespace=namespace)
def setTagAttr(self, tag, attr, val):
"""
Create new node (if not already present) with name "tag" and set it's
attribute "attr" to value "val"
"""
try:
self.getTag(tag).attrs[attr] = val
except Exception:
self.addChild(tag, attrs={attr: val})
def setTagData(self, tag, val, attrs={}):
"""
Creates new node (if not already present) with name "tag" and
(optionally) attributes "attrs" and sets it's CDATA to string "val"
"""
try:
self.getTag(tag, attrs).setData(ustr(val))
except Exception:
self.addChild(tag, attrs, payload = [ustr(val)])
def has_attr(self, key):
"""
Check if node have attribute "key"
"""
return key in self.attrs
def __getitem__(self, item):
"""
Return node's attribute "item" value
"""
return self.getAttr(item)
def __setitem__(self, item, val):
"""
Set node's attribute "item" value
"""
return self.setAttr(item, val)
def __delitem__(self, item):
"""
Delete node's attribute "item"
"""
return self.delAttr(item)
def __contains__(self, item):
"""
Check if node has attribute "item"
"""
return self.has_attr(item)
def __getattr__(self, attr):
"""
Reduce memory usage caused by T/NT classes - use memory only when needed
"""
if attr == 'T':
self.T = T(self)
return self.T
if attr == 'NT':
self.NT = NT(self)
return self.NT
raise AttributeError
class T:
"""
Auxiliary class used to quick access to node's child nodes
"""
def __init__(self, node):
self.__dict__['node'] = node
def __getattr__(self, attr):
return self.node.setTag(attr)
def __setattr__(self, attr, val):
if isinstance(val, Node):
Node.__init__(self.node.setTag(attr), node=val)
else:
return self.node.setTagData(attr, val)
def __delattr__(self, attr):
return self.node.delChild(attr)
class NT(T):
"""
Auxiliary class used to quick create node's child nodes
"""
def __getattr__(self, attr):
return self.node.addChild(attr)
def __setattr__(self, attr, val):
if isinstance(val, Node):
self.node.addChild(attr, node=val)
else:
return self.node.addChild(attr, payload=[val])
class NodeBuilder:
"""
Builds a Node class minidom from data parsed to it. This class used for two
purposes:
1. Creation an XML Node from a textual representation. F.e. reading a
config file. See an XML2Node method.
2. Handling an incoming XML stream. This is done by mangling the
__dispatch_depth parameter and redefining the dispatch method.
You do not need to use this class directly if you do not designing your own
XML handler
"""
def __init__(self, data=None, initial_node=None):
"""
Take two optional parameters: "data" and "initial_node"
By default class initialised with empty Node class instance. Though, if
"initial_node" is provided it used as "starting point". You can think
about it as of "node upgrade". "data" (if provided) feeded to parser
immidiatedly after instance init.
"""
log.debug("Preparing to handle incoming XML stream.")
self._parser = xml.parsers.expat.ParserCreate()
self._parser.StartElementHandler = self.starttag
self._parser.EndElementHandler = self.endtag
self._parser.StartNamespaceDeclHandler = self.handle_namespace_start
self._parser.CharacterDataHandler = self.handle_cdata
self._parser.buffer_text = True
self.Parse = self._parser.Parse
self.__depth = 0
self.__last_depth = 0
self.__max_depth = 0
self._dispatch_depth = 1
self._document_attrs = None
self._document_nsp = None
self._mini_dom=initial_node
self.last_is_data = 1
self._ptr=None
self.data_buffer = None
self.streamError = ''
if data:
self._parser.Parse(data, 1)
def check_data_buffer(self):
if self.data_buffer:
self._ptr.data.append(''.join(self.data_buffer))
del self.data_buffer[:]
self.data_buffer = None
def destroy(self):
"""
Method used to allow class instance to be garbage-collected
"""
self.check_data_buffer()
self._parser.StartElementHandler = None
self._parser.EndElementHandler = None
self._parser.CharacterDataHandler = None
self._parser.StartNamespaceDeclHandler = None
def starttag(self, tag, attrs):
"""
XML Parser callback. Used internally
"""
self.check_data_buffer()
self._inc_depth()
log.info("STARTTAG.. DEPTH -> %i , tag -> %s, attrs -> %s" % (self.__depth, tag, `attrs`))
if self.__depth == self._dispatch_depth:
if not self._mini_dom :
self._mini_dom = Node(tag=tag, attrs=attrs, nsp = self._document_nsp, node_built=True)
else:
Node.__init__(self._mini_dom, tag=tag, attrs=attrs, nsp = self._document_nsp, node_built=True)
self._ptr = self._mini_dom
elif self.__depth > self._dispatch_depth:
self._ptr.kids.append(Node(tag=tag, parent=self._ptr, attrs=attrs, node_built=True))
self._ptr = self._ptr.kids[-1]
if self.__depth == 1:
self._document_attrs = {}
self._document_nsp = {}
nsp, name = (['']+tag.split(':'))[-2:]
for attr, val in attrs.items():
if attr == 'xmlns':
self._document_nsp[u''] = val
elif attr.startswith('xmlns:'):
self._document_nsp[attr[6:]] = val
else:
self._document_attrs[attr] = val
ns = self._document_nsp.get(nsp, 'http://www.gajim.org/xmlns/undeclared-root')
try:
self.stream_header_received(ns, name, attrs)
except ValueError, e:
self._document_attrs = None
raise ValueError(str(e))
if not self.last_is_data and self._ptr.parent:
self._ptr.parent.data.append('')
self.last_is_data = 0
def endtag(self, tag ):
"""
XML Parser callback. Used internally
"""
log.info("DEPTH -> %i , tag -> %s" % (self.__depth, tag))
self.check_data_buffer()
if self.__depth == self._dispatch_depth:
if self._mini_dom.getName() == 'error':
children = self._mini_dom.getChildren()
if children:
self.streamError = children[0].getName()
else:
self.streamError = self._mini_dom.getData()
self.dispatch(self._mini_dom)
elif self.__depth > self._dispatch_depth:
self._ptr = self._ptr.parent
else:
log.info("Got higher than dispatch level. Stream terminated?")
self._dec_depth()
self.last_is_data = 0
if self.__depth == 0: self.stream_footer_received()
def handle_cdata(self, data):
if self.last_is_data:
if self.data_buffer:
self.data_buffer.append(data)
elif self._ptr:
self.data_buffer = [data]
self.last_is_data = 1
def handle_namespace_start(self, prefix, uri):
"""
XML Parser callback. Used internally
"""
self.check_data_buffer()
def getDom(self):
"""
Return just built Node
"""
self.check_data_buffer()
return self._mini_dom
def dispatch(self, stanza):
"""
Get called when the NodeBuilder reaches some level of depth on it's way
up with the built node as argument. Can be redefined to convert incoming
XML stanzas to program events
"""
pass
def stream_header_received(self, ns, tag, attrs):
"""
Method called when stream just opened
"""
self.check_data_buffer()
def stream_footer_received(self):
"""
Method called when stream just closed
"""
self.check_data_buffer()
def has_received_endtag(self, level=0):
"""
Return True if at least one end tag was seen (at level)
"""
return self.__depth <= level and self.__max_depth > level
def _inc_depth(self):
self.__last_depth = self.__depth
self.__depth += 1
self.__max_depth = max(self.__depth, self.__max_depth)
def _dec_depth(self):
self.__last_depth = self.__depth
self.__depth -= 1
def XML2Node(xml):
"""
Convert supplied textual string into XML node. Handy f.e. for reading
configuration file. Raises xml.parser.expat.parsererror if provided string
is not well-formed XML
"""
return NodeBuilder(xml).getDom()
def BadXML2Node(xml):
"""
Convert supplied textual string into XML node. Survives if xml data is
cutted half way round. I.e. "<html>some text <br>some more text". Will raise
xml.parser.expat.parsererror on misplaced tags though. F.e. "<b>some text
<br>some more text</b>" will not work
"""
return NodeBuilder(xml).getDom()

View File

@ -1,132 +0,0 @@
from protocol import Acks
from protocol import NS_STREAM_MGMT
import logging
log = logging.getLogger('gajim.c.x.smacks')
class Smacks():
'''
This is Smacks is the Stream Management class. It takes care of requesting
and sending acks. Also, it keeps track of the unhandled outgoing stanzas.
The dispatcher has to be able to access this class to increment the
number of handled stanzas
'''
def __init__(self, con):
self.con = con # Connection object
self.out_h = 0 # Outgoing stanzas handled
self.in_h = 0 # Incoming stanzas handled
self.uqueue = [] # Unhandled stanzas queue
self.session_id = None
self.resumption = False # If server supports resume
# Max number of stanzas in queue before making a request
self.max_queue = 5
self._owner = None
self.resuming = False
self.enabled = False # If SM is enabled
self.location = None
def set_owner(self, owner):
self._owner = owner
# Register handlers
owner.Dispatcher.RegisterNamespace(NS_STREAM_MGMT)
owner.Dispatcher.RegisterHandler('enabled', self._neg_response,
xmlns=NS_STREAM_MGMT)
owner.Dispatcher.RegisterHandler('r', self.send_ack,
xmlns=NS_STREAM_MGMT)
owner.Dispatcher.RegisterHandler('a', self.check_ack,
xmlns=NS_STREAM_MGMT)
owner.Dispatcher.RegisterHandler('resumed', self.check_ack,
xmlns=NS_STREAM_MGMT)
owner.Dispatcher.RegisterHandler('failed', self.error_handling,
xmlns=NS_STREAM_MGMT)
def _neg_response(self, disp, stanza):
r = stanza.getAttr('resume')
if r == 'true' or r == 'True' or r == '1':
self.resumption = True
self.session_id = stanza.getAttr('id')
if r == 'false' or r == 'False' or r == '0':
self.negociate(False)
l = stanza.getAttr('location')
if l:
self.location = l
def negociate(self, resume=True):
# Every time we attempt to negociate, we must erase all previous info
# about any previous session
self.uqueue = []
self.in_h = 0
self.out_h = 0
self.session_id = None
self.enabled = True
stanza = Acks()
stanza.buildEnable(resume)
self._owner.Connection.send(stanza, now=True)
def resume_request(self):
if not self.session_id:
self.resuming = False
log.error('Attempted to resume without a valid session id ')
return
resume = Acks()
resume.buildResume(self.in_h, self.session_id)
self._owner.Connection.send(resume, False)
def send_ack(self, disp, stanza):
ack = Acks()
ack.buildAnswer(self.in_h)
self._owner.Connection.send(ack, False)
def request_ack(self):
r = Acks()
r.buildRequest()
self._owner.Connection.send(r, False)
def check_ack(self, disp, stanza):
'''
Checks if the number of stanzas sent are the same as the
number of stanzas received by the server. Pops stanzas that were
handled by the server from the queue.
'''
h = int(stanza.getAttr('h'))
diff = self.out_h - h
if len(self.uqueue) < diff or diff < 0:
log.error('Server and client number of stanzas handled mismatch ')
else:
while (len(self.uqueue) > diff):
self.uqueue.pop(0)
if stanza.getName() == 'resumed':
self.enabled = True
self.resuming = True
self.con.set_oldst()
if self.uqueue != []:
for i in self.uqueue:
self._owner.Connection.send(i, False)
def error_handling(self, disp, stanza):
# If the server doesn't recognize previd, forget about resuming
# Ask for service discovery, etc..
if stanza.getTag('item-not-found'):
self.resuming = False
self.enabled = False
# we need to bind a resource
self._owner.NonBlockingBind.resuming = False
self._owner._on_auth_bind(None)
return
# Doesn't support resumption
if stanza.getTag('feature-not-implemented'):
self.negociate(False)
return
if stanza.getTag('unexpected-request'):
self.enabled = False
log.error('Gajim failed to negociate Stream Management')
return

View File

@ -1,238 +0,0 @@
# -*- coding:utf-8 -*-
## src/common/xmpp/stringprepare.py
##
## Copyright (C) 2001-2005 Twisted Matrix Laboratories
## Copyright (C) 2005-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006 Stefan Bethge <stefan AT lanpartei.de>
## Copyright (C) 2007 Jean-Marie Traissard <jim AT lapin.org>
##
## This file is part of Gajim.
##
## Gajim is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published
## by the Free Software Foundation; version 3 only.
##
## Gajim is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
##
import stringprep
import unicodedata
from encodings import idna
class ILookupTable:
"""
Interface for character lookup classes
"""
def lookup(self, c):
"""
Return whether character is in this table
"""
pass
class IMappingTable:
"""
Interface for character mapping classes
"""
def map(self, c):
"""
Return mapping for character
"""
pass
class LookupTableFromFunction:
__implements__ = ILookupTable
def __init__(self, in_table_function):
self.lookup = in_table_function
class LookupTable:
__implements__ = ILookupTable
def __init__(self, table):
self._table = table
def lookup(self, c):
return c in self._table
class MappingTableFromFunction:
__implements__ = IMappingTable
def __init__(self, map_table_function):
self.map = map_table_function
class EmptyMappingTable:
__implements__ = IMappingTable
def __init__(self, in_table_function):
self._in_table_function = in_table_function
def map(self, c):
if self._in_table_function(c):
return None
else:
return c
class Profile:
def __init__(self, mappings=[], normalize=True, prohibiteds=[],
check_unassigneds=True, check_bidi=True):
self.mappings = mappings
self.normalize = normalize
self.prohibiteds = prohibiteds
self.do_check_unassigneds = check_unassigneds
self.do_check_bidi = check_bidi
def prepare(self, string):
result = self.map(string)
if self.normalize:
result = unicodedata.normalize("NFKC", result)
self.check_prohibiteds(result)
if self.do_check_unassigneds:
self.check_unassigneds(result)
if self.do_check_bidi:
self.check_bidirectionals(result)
return result
def map(self, string):
result = []
for c in string:
result_c = c
for mapping in self.mappings:
result_c = mapping.map(c)
if result_c != c:
break
if result_c is not None:
result.append(result_c)
return u"".join(result)
def check_prohibiteds(self, string):
for c in string:
for table in self.prohibiteds:
if table.lookup(c):
raise UnicodeError, "Invalid character %s" % repr(c)
def check_unassigneds(self, string):
for c in string:
if stringprep.in_table_a1(c):
raise UnicodeError, "Unassigned code point %s" % repr(c)
def check_bidirectionals(self, string):
found_LCat = False
found_RandALCat = False
for c in string:
if stringprep.in_table_d1(c):
found_RandALCat = True
if stringprep.in_table_d2(c):
found_LCat = True
if found_LCat and found_RandALCat:
raise UnicodeError, "Violation of BIDI Requirement 2"
if found_RandALCat and not (stringprep.in_table_d1(string[0]) and
stringprep.in_table_d1(string[-1])):
raise UnicodeError, "Violation of BIDI Requirement 3"
class NamePrep:
"""
Implements preparation of internationalized domain names
This class implements preparing internationalized domain names using the
rules defined in RFC 3491, section 4 (Conversion operations).
We do not perform step 4 since we deal with unicode representations of
domain names and do not convert from or to ASCII representations using
punycode encoding. When such a conversion is needed, the L{idna} standard
library provides the C{ToUnicode()} and C{ToASCII()} functions. Note that
L{idna} itself assumes UseSTD3ASCIIRules to be false.
The following steps are performed by C{prepare()}:
* Split the domain name in labels at the dots (RFC 3490, 3.1)
* Apply nameprep proper on each label (RFC 3491)
* Enforce the restrictions on ASCII characters in host names by
assuming STD3ASCIIRules to be true. (STD 3)
* Rejoin the labels using the label separator U+002E (full stop).
"""
# Prohibited characters.
prohibiteds = [unichr(n) for n in range(0x00, 0x2c + 1) +
range(0x2e, 0x2f + 1) +
range(0x3a, 0x40 + 1) +
range(0x5b, 0x60 + 1) +
range(0x7b, 0x7f + 1) ]
def prepare(self, string):
result = []
labels = idna.dots.split(string)
if labels and len(labels[-1]) == 0:
trailing_dot = '.'
del labels[-1]
else:
trailing_dot = ''
for label in labels:
result.append(self.nameprep(label))
return ".".join(result)+trailing_dot
def check_prohibiteds(self, string):
for c in string:
if c in self.prohibiteds:
raise UnicodeError, "Invalid character %s" % repr(c)
def nameprep(self, label):
label = idna.nameprep(label)
self.check_prohibiteds(label)
if len(label) == 0:
raise UnicodeError, "Invalid empty name"
if label[0] == '-':
raise UnicodeError, "Invalid leading hyphen-minus"
if label[-1] == '-':
raise UnicodeError, "Invalid trailing hyphen-minus"
return label
C_11 = LookupTableFromFunction(stringprep.in_table_c11)
C_12 = LookupTableFromFunction(stringprep.in_table_c12)
C_21 = LookupTableFromFunction(stringprep.in_table_c21)
C_22 = LookupTableFromFunction(stringprep.in_table_c22)
C_3 = LookupTableFromFunction(stringprep.in_table_c3)
C_4 = LookupTableFromFunction(stringprep.in_table_c4)
C_5 = LookupTableFromFunction(stringprep.in_table_c5)
C_6 = LookupTableFromFunction(stringprep.in_table_c6)
C_7 = LookupTableFromFunction(stringprep.in_table_c7)
C_8 = LookupTableFromFunction(stringprep.in_table_c8)
C_9 = LookupTableFromFunction(stringprep.in_table_c9)
B_1 = EmptyMappingTable(stringprep.in_table_b1)
B_2 = MappingTableFromFunction(stringprep.map_table_b2)
nodeprep = Profile(mappings=[B_1, B_2],
prohibiteds=[C_11, C_12, C_21, C_22,
C_3, C_4, C_5, C_6, C_7, C_8, C_9,
LookupTable([u'"', u'&', u"'", u'/',
u':', u'<', u'>', u'@'])])
resourceprep = Profile(mappings=[B_1,],
prohibiteds=[C_12, C_21, C_22,
C_3, C_4, C_5, C_6, C_7, C_8, C_9])
nameprep = NamePrep()

View File

@ -1,461 +0,0 @@
## tls_nb.py
## based on transports_nb.py
##
## Copyright (C) 2003-2004 Alexey "Snake" Nezhdanov
## modified by Dimitur Kirov <dkirov@gmail.com>
## modified by Tomas Karasek <tom.to.the.k@gmail.com>
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2, or (at your option)
## any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
import socket
from plugin import PlugIn
import sys
import os
import time
import traceback
import logging
log = logging.getLogger('gajim.c.x.tls_nb')
USE_PYOPENSSL = False
PYOPENSSL = 'PYOPENSSL'
PYSTDLIB = 'PYSTDLIB'
try:
#raise ImportError("Manually disabled PyOpenSSL")
import OpenSSL.SSL
import OpenSSL.crypto
USE_PYOPENSSL = True
log.info("PyOpenSSL loaded")
except ImportError:
log.debug("Import of PyOpenSSL failed:", exc_info=True)
# FIXME: Remove these prints before release, replace with a warning dialog.
print >> sys.stderr, "=" * 79
print >> sys.stderr, "PyOpenSSL not found, falling back to Python builtin SSL objects (insecure)."
print >> sys.stderr, "=" * 79
def gattr(obj, attr, default=None):
try:
return getattr(obj, attr)
except AttributeError:
return default
class SSLWrapper:
"""
Abstract SSLWrapper base class
"""
class Error(IOError):
"""
Generic SSL Error Wrapper
"""
def __init__(self, sock=None, exc=None, errno=None, strerror=None,
peer=None):
self.parent = IOError
errno = errno or gattr(exc, 'errno') or exc[0]
strerror = strerror or gattr(exc, 'strerror') or gattr(exc, 'args')
if not isinstance(strerror, basestring):
strerror = repr(strerror)
self.sock = sock
self.exc = exc
self.peer = peer
self.exc_name = None
self.exc_args = None
self.exc_str = None
self.exc_repr = None
if self.exc is not None:
self.exc_name = str(self.exc.__class__)
self.exc_args = gattr(self.exc, 'args')
self.exc_str = str(self.exc)
self.exc_repr = repr(self.exc)
if not errno:
try:
if isinstance(exc, OpenSSL.SSL.SysCallError):
if self.exc_args[0] > 0:
errno = self.exc_args[0]
strerror = self.exc_args[1]
except: pass
self.parent.__init__(self, errno, strerror)
if self.peer is None and sock is not None:
try:
ppeer = self.sock.getpeername()
if len(ppeer) == 2 and isinstance(ppeer[0], basestring) \
and isinstance(ppeer[1], int):
self.peer = ppeer
except:
pass
def __str__(self):
s = str(self.__class__)
if self.peer:
s += " for %s:%d" % self.peer
if self.errno is not None:
s += ": [Errno: %d]" % self.errno
if self.strerror:
s += " (%s)" % self.strerror
if self.exc_name:
s += ", Caused by %s" % self.exc_name
if self.exc_str:
if self.strerror:
s += "(%s)" % self.exc_str
else: s += "(%s)" % str(self.exc_args)
return s
def __init__(self, sslobj, sock=None):
self.sslobj = sslobj
self.sock = sock
log.debug("%s.__init__ called with %s", self.__class__, sslobj)
def recv(self, data, flags=None):
"""
Receive wrapper for SSL object
We can return None out of this function to signal that no data is
available right now. Better than an exception, which differs
depending on which SSL lib we're using. Unfortunately returning ''
can indicate that the socket has been closed, so to be sure, we avoid
this by returning None.
"""
raise NotImplementedError
def send(self, data, flags=None, now=False):
"""
Send wrapper for SSL object
"""
raise NotImplementedError
class PyOpenSSLWrapper(SSLWrapper):
"""
Wrapper class for PyOpenSSL's recv() and send() methods
"""
def __init__(self, *args):
self.parent = SSLWrapper
self.parent.__init__(self, *args)
def is_numtoolarge(self, e):
''' Magic methods don't need documentation '''
t = ('asn1 encoding routines', 'a2d_ASN1_OBJECT', 'first num too large')
return (isinstance(e.args, (list, tuple)) and len(e.args) == 1 and
isinstance(e.args[0], (list, tuple)) and len(e.args[0]) == 2 and
e.args[0][0] == e.args[0][1] == t)
def recv(self, bufsize, flags=None):
retval = None
try:
if flags is None:
retval = self.sslobj.recv(bufsize)
else:
retval = self.sslobj.recv(bufsize, flags)
except (OpenSSL.SSL.WantReadError, OpenSSL.SSL.WantWriteError), e:
log.debug("Recv: Want-error: " + repr(e))
except OpenSSL.SSL.SysCallError, e:
log.debug("Recv: Got OpenSSL.SSL.SysCallError: " + repr(e),
exc_info=True)
raise SSLWrapper.Error(self.sock or self.sslobj, e)
except OpenSSL.SSL.ZeroReturnError, e:
# end-of-connection raises ZeroReturnError instead of having the
# connection's .recv() method return a zero-sized result.
raise SSLWrapper.Error(self.sock or self.sslobj, e, -1)
except OpenSSL.SSL.Error, e:
if self.is_numtoolarge(e):
# warn, but ignore this exception
log.warning("Recv: OpenSSL: asn1enc: first num too large (ignored)")
else:
log.debug("Recv: Caught OpenSSL.SSL.Error:", exc_info=True)
raise SSLWrapper.Error(self.sock or self.sslobj, e)
return retval
def send(self, data, flags=None, now=False):
try:
if flags is None:
return self.sslobj.send(data)
else:
return self.sslobj.send(data, flags)
except (OpenSSL.SSL.WantReadError, OpenSSL.SSL.WantWriteError), e:
#log.debug("Send: " + repr(e))
time.sleep(0.1) # prevent 100% CPU usage
except OpenSSL.SSL.SysCallError, e:
log.error("Send: Got OpenSSL.SSL.SysCallError: " + repr(e),
exc_info=True)
raise SSLWrapper.Error(self.sock or self.sslobj, e)
except OpenSSL.SSL.Error, e:
if self.is_numtoolarge(e):
# warn, but ignore this exception
log.warning("Send: OpenSSL: asn1enc: first num too large (ignored)")
else:
log.error("Send: Caught OpenSSL.SSL.Error:", exc_info=True)
raise SSLWrapper.Error(self.sock or self.sslobj, e)
return 0
class StdlibSSLWrapper(SSLWrapper):
"""
Wrapper class for Python socket.ssl read() and write() methods
"""
def __init__(self, *args):
self.parent = SSLWrapper
self.parent.__init__(self, *args)
def recv(self, bufsize, flags=None):
# we simply ignore flags since ssl object doesn't support it
try:
return self.sslobj.read(bufsize)
except socket.sslerror, e:
log.debug("Recv: Caught socket.sslerror: " + repr(e), exc_info=True)
if e.args[0] not in (socket.SSL_ERROR_WANT_READ, socket.SSL_ERROR_WANT_WRITE):
raise SSLWrapper.Error(self.sock or self.sslobj, e)
return None
def send(self, data, flags=None, now=False):
# we simply ignore flags since ssl object doesn't support it
try:
return self.sslobj.write(data)
except socket.sslerror, e:
log.debug("Send: Caught socket.sslerror:", exc_info=True)
if e.args[0] not in (socket.SSL_ERROR_WANT_READ, socket.SSL_ERROR_WANT_WRITE):
raise SSLWrapper.Error(self.sock or self.sslobj, e)
return 0
class NonBlockingTLS(PlugIn):
"""
TLS connection used to encrypts already estabilished tcp connection
Can be plugged into NonBlockingTCP and will make use of StdlibSSLWrapper or
PyOpenSSLWrapper.
"""
def __init__(self, cacerts, mycerts):
"""
:param cacerts: path to pem file with certificates of known XMPP servers
:param mycerts: path to pem file with certificates of user trusted servers
"""
PlugIn.__init__(self)
self.cacerts = cacerts
self.mycerts = mycerts
# from ssl.h (partial extract)
ssl_h_bits = { "SSL_ST_CONNECT": 0x1000, "SSL_ST_ACCEPT": 0x2000,
"SSL_CB_LOOP": 0x01, "SSL_CB_EXIT": 0x02,
"SSL_CB_READ": 0x04, "SSL_CB_WRITE": 0x08,
"SSL_CB_ALERT": 0x4000,
"SSL_CB_HANDSHAKE_START": 0x10, "SSL_CB_HANDSHAKE_DONE": 0x20}
def plugin(self, owner):
"""
Use to PlugIn TLS into transport and start establishing immediately.
Returns True if TLS/SSL was established correctly, otherwise False
"""
log.info('Starting TLS estabilishing')
try:
res = self._startSSL()
except Exception, e:
log.error("PlugIn: while trying _startSSL():", exc_info=True)
return False
return res
def _dumpX509(self, cert, stream=sys.stderr):
print >> stream, "Digest (SHA-1):", cert.digest("sha1")
print >> stream, "Digest (MD5):", cert.digest("md5")
print >> stream, "Serial #:", cert.get_serial_number()
print >> stream, "Version:", cert.get_version()
print >> stream, "Expired:", ("Yes" if cert.has_expired() else "No")
print >> stream, "Subject:"
self._dumpX509Name(cert.get_subject(), stream)
print >> stream, "Issuer:"
self._dumpX509Name(cert.get_issuer(), stream)
self._dumpPKey(cert.get_pubkey(), stream)
def _dumpX509Name(self, name, stream=sys.stderr):
print >> stream, "X509Name:", str(name)
def _dumpPKey(self, pkey, stream=sys.stderr):
typedict = {OpenSSL.crypto.TYPE_RSA: "RSA",
OpenSSL.crypto.TYPE_DSA: "DSA"}
print >> stream, "PKey bits:", pkey.bits()
print >> stream, "PKey type: %s (%d)" % (typedict.get(pkey.type(),
"Unknown"), pkey.type())
def _startSSL(self):
"""
Immediatedly switch socket to TLS mode. Used internally
"""
log.debug("_startSSL called")
if USE_PYOPENSSL:
result = self._startSSL_pyOpenSSL()
else:
result = self._startSSL_stdlib()
if result:
log.debug('Synchronous handshake completed')
return True
else:
return False
def _load_cert_file(self, cert_path, cert_store, logg=True):
if not os.path.isfile(cert_path):
return
try:
f = open(cert_path)
except IOError, e:
log.warning('Unable to open certificate file %s: %s' % \
(cert_path, str(e)))
return
lines = f.readlines()
i = 0
begin = -1
for line in lines:
if 'BEGIN CERTIFICATE' in line:
begin = i
elif 'END CERTIFICATE' in line and begin > -1:
cert = ''.join(lines[begin:i+2])
try:
x509cert = OpenSSL.crypto.load_certificate(
OpenSSL.crypto.FILETYPE_PEM, cert)
cert_store.add_cert(x509cert)
except OpenSSL.crypto.Error, exception_obj:
if logg:
log.warning('Unable to load a certificate from file %s: %s' %\
(cert_path, exception_obj.args[0][0][2]))
except:
log.warning('Unknown error while loading certificate from file '
'%s' % cert_path)
begin = -1
i += 1
def _startSSL_pyOpenSSL(self):
log.debug("_startSSL_pyOpenSSL called")
tcpsock = self._owner
# NonBlockingHTTPBOSH instance has no attribute _owner
if hasattr(tcpsock, '_owner') and tcpsock._owner._caller.client_cert \
and os.path.exists(tcpsock._owner._caller.client_cert):
conn = tcpsock._owner._caller
# FIXME make a checkbox for Client Cert / SSLv23 / TLSv1
# If we are going to use a client cert/key pair for authentication,
# we choose TLSv1 method.
tcpsock._sslContext = OpenSSL.SSL.Context(OpenSSL.SSL.TLSv1_METHOD)
log.debug('Using client cert and key from %s' % conn.client_cert)
try:
p12 = OpenSSL.crypto.load_pkcs12(open(conn.client_cert).read(),
conn.client_cert_passphrase)
except OpenSSL.crypto.Error, exception_obj:
log.warning('Unable to load client pkcs12 certificate from '
'file %s: %s ... Is it a valid PKCS12 cert?' % \
(conn.client_cert, exception_obj.args))
except:
log.warning('Unknown error while loading certificate from file '
'%s' % conn.client_cert)
else:
log.info('PKCS12 Client cert loaded OK')
try:
tcpsock._sslContext.use_certificate(p12.get_certificate())
tcpsock._sslContext.use_privatekey(p12.get_privatekey())
log.info('p12 cert and key loaded')
except OpenSSL.crypto.Error, exception_obj:
log.warning('Unable to extract client certificate from '
'file %s' % conn.client_cert)
except Exception, msg:
log.warning('Unknown error extracting client certificate '
'from file %s: %s' % (conn.client_cert, msg))
else:
log.info('client cert and key loaded OK')
else:
# See http://docs.python.org/dev/library/ssl.html
tcpsock._sslContext = OpenSSL.SSL.Context(OpenSSL.SSL.SSLv23_METHOD)
flags = OpenSSL.SSL.OP_NO_SSLv2
try:
flags |= OpenSSL.SSL.OP_NO_TICKET
except AttributeError, e:
# py-OpenSSL < 0.9 or old OpenSSL
flags |= 16384
tcpsock._sslContext.set_options(flags)
tcpsock.ssl_errnum = 0
tcpsock._sslContext.set_verify(OpenSSL.SSL.VERIFY_PEER,
self._ssl_verify_callback)
try:
tcpsock._sslContext.load_verify_locations(self.cacerts)
except:
log.warning('Unable to load SSL certificates from file %s' % \
os.path.abspath(self.cacerts))
store = tcpsock._sslContext.get_cert_store()
self._load_cert_file(self.mycerts, store)
if os.path.isdir('/etc/ssl/certs'):
for f in os.listdir('/etc/ssl/certs'):
# We don't logg because there is a lot a duplicated certs in this
# folder
self._load_cert_file(os.path.join('/etc/ssl/certs', f), store,
logg=False)
tcpsock._sslObj = OpenSSL.SSL.Connection(tcpsock._sslContext,
tcpsock._sock)
tcpsock._sslObj.set_connect_state() # set to client mode
wrapper = PyOpenSSLWrapper(tcpsock._sslObj)
tcpsock._recv = wrapper.recv
tcpsock._send = wrapper.send
log.debug("Initiating handshake...")
try:
tcpsock._sslObj.do_handshake()
except (OpenSSL.SSL.WantReadError, OpenSSL.SSL.WantWriteError), e:
pass
except:
log.error('Error while TLS handshake: ', exc_info=True)
return False
self._owner.ssl_lib = PYOPENSSL
return True
def _startSSL_stdlib(self):
log.debug("_startSSL_stdlib called")
tcpsock=self._owner
try:
tcpsock._sock.setblocking(True)
tcpsock._sslObj = socket.ssl(tcpsock._sock, None, None)
tcpsock._sock.setblocking(False)
tcpsock._sslIssuer = tcpsock._sslObj.issuer()
tcpsock._sslServer = tcpsock._sslObj.server()
wrapper = StdlibSSLWrapper(tcpsock._sslObj, tcpsock._sock)
tcpsock._recv = wrapper.recv
tcpsock._send = wrapper.send
except:
log.error("Exception caught in _startSSL_stdlib:", exc_info=True)
return False
self._owner.ssl_lib = PYSTDLIB
return True
def _ssl_verify_callback(self, sslconn, cert, errnum, depth, ok):
# Exceptions can't propagate up through this callback, so print them here.
try:
self._owner.ssl_fingerprint_sha1 = cert.digest('sha1')
self._owner.ssl_certificate = cert
self._owner.ssl_errnum = errnum
self._owner.ssl_cert_pem = OpenSSL.crypto.dump_certificate(
OpenSSL.crypto.FILETYPE_PEM, cert)
return True
except:
log.error("Exception caught in _ssl_info_callback:", exc_info=True)
# Make sure something is printed, even if log is disabled.
traceback.print_exc()

View File

@ -1,786 +0,0 @@
## transports_nb.py
## based on transports.py
##
## Copyright (C) 2003-2004 Alexey "Snake" Nezhdanov
## modified by Dimitur Kirov <dkirov@gmail.com>
## modified by Tomas Karasek <tom.to.the.k@gmail.com>
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2, or (at your option)
## any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
"""
Transports are objects responsible for connecting to XMPP server and putting
data to wrapped sockets in in desired form (SSL, TLS, TCP, for HTTP proxy,
for SOCKS5 proxy...)
Transports are not aware of XMPP stanzas and only responsible for low-level
connection handling.
"""
from simplexml import ustr
from plugin import PlugIn
from idlequeue import IdleObject
import proxy_connectors
import tls_nb
import socket
import errno
import time
import traceback
import base64
import urlparse
import logging
log = logging.getLogger('gajim.c.x.transports_nb')
def urisplit(uri):
"""
Function for splitting URI string to tuple (protocol, host, port, path).
e.g. urisplit('http://httpcm.jabber.org:123/webclient') returns ('http',
'httpcm.jabber.org', 123, '/webclient') return 443 as default port if proto
is https else 80
"""
splitted = urlparse.urlsplit(uri)
proto, host, path = splitted.scheme, splitted.hostname, splitted.path
try:
port = splitted.port
except ValueError:
log.warn('port cannot be extracted from BOSH URL %s, using default port' \
% uri)
port = ''
if not port:
if proto == 'https':
port = 443
else:
port = 80
return proto, host, port, path
def get_proxy_data_from_dict(proxy):
tcp_host, tcp_port, proxy_user, proxy_pass = None, None, None, None
proxy_type = proxy['type']
if proxy_type == 'bosh' and not proxy['bosh_useproxy']:
# with BOSH not over proxy we have to parse the hostname from BOSH URI
proto, tcp_host, tcp_port, path = urisplit(proxy['bosh_uri'])
else:
# with proxy!=bosh or with bosh over HTTP proxy we're connecting to proxy
# machine
tcp_host, tcp_port = proxy['host'], proxy['port']
if proxy.get('useauth', False):
proxy_user, proxy_pass = proxy['user'], proxy['pass']
return tcp_host, tcp_port, proxy_user, proxy_pass
#: timeout to connect to the server socket, it doesn't include auth
CONNECT_TIMEOUT_SECONDS = 30
#: how long to wait for a disconnect to complete
DISCONNECT_TIMEOUT_SECONDS = 5
#: size of the buffer which reads data from server
# if lower, more stanzas will be fragmented and processed twice
RECV_BUFSIZE = 32768 # 2x maximum size of ssl packet, should be plenty
# FIXME: (#2634) gajim breaks with #RECV_BUFSIZE = 16
# it's inefficient but should work. Problem is that connect machine makes wrong
# assumptions and that we only check for pending data in sockets but not in SSL
# buffer...
DATA_RECEIVED = 'DATA RECEIVED'
DATA_SENT = 'DATA SENT'
DATA_ERROR = 'DATA ERROR'
DISCONNECTED = 'DISCONNECTED'
DISCONNECTING = 'DISCONNECTING'
CONNECTING = 'CONNECTING'
PROXY_CONNECTING = 'PROXY_CONNECTING'
CONNECTED = 'CONNECTED'
STATES = (DISCONNECTED, CONNECTING, PROXY_CONNECTING, CONNECTED, DISCONNECTING)
class NonBlockingTransport(PlugIn):
"""
Abstract class representing a transport
Subclasses CAN have different constructor signature but connect method SHOULD
be the same.
"""
def __init__(self, raise_event, on_disconnect, idlequeue, estabilish_tls,
certs):
"""
Each trasport class can have different constructor but it has to have at
least all the arguments of NonBlockingTransport constructor
:param raise_event: callback for monitoring of sent and received data
:param on_disconnect: callback called on disconnection during runtime
:param idlequeue: processing idlequeue
:param estabilish_tls: boolean whether to estabilish TLS connection after
TCP connection is done
:param certs: tuple of (cacerts, mycerts) see constructor of
tls_nb.NonBlockingTLS for more details
"""
PlugIn.__init__(self)
self.raise_event = raise_event
self.on_disconnect = on_disconnect
self.on_connect = None
self.on_connect_failure = None
self.idlequeue = idlequeue
self.on_receive = None
self.server = None
self.port = None
self.conn_5tuple = None
self.set_state(DISCONNECTED)
self.estabilish_tls = estabilish_tls
self.certs = certs
# type of used ssl lib (if any) will be assigned to this member var
self.ssl_lib = None
self._exported_methods=[self.onreceive, self.set_send_timeout,
self.set_send_timeout2, self.set_timeout, self.remove_timeout,
self.start_disconnect]
# time to wait for SOME stanza to come and then send keepalive
self.sendtimeout = 0
# in case we want to something different than sending keepalives
self.on_timeout = None
self.on_timeout2 = None
def plugin(self, owner):
owner.Connection = self
def plugout(self):
self._owner.Connection = None
self._owner = None
self.disconnect(do_callback=False)
def connect(self, conn_5tuple, on_connect, on_connect_failure):
"""
Creates and connects transport to server and port defined in conn_5tuple
which should be item from list returned from getaddrinfo
:param conn_5tuple: 5-tuple returned from getaddrinfo
:param on_connect: callback called on successful connect to the server
:param on_connect_failure: callback called on failure when connecting
"""
self.on_connect = on_connect
self.on_connect_failure = on_connect_failure
self.server, self.port = conn_5tuple[4][:2]
self.conn_5tuple = conn_5tuple
def set_state(self, newstate):
assert(newstate in STATES)
self.state = newstate
def get_state(self):
return self.state
def _on_connect(self):
"""
Preceeds call of on_connect callback
"""
# data is reference to socket wrapper instance. We don't need it in client
# because
self.set_state(CONNECTED)
self.on_connect()
def _on_connect_failure(self, err_message):
"""
Preceeds call of on_connect_failure callback
"""
# In case of error while connecting we need to disconnect transport
# but we don't want to call DisconnectHandlers from client,
# thus the do_callback=False
self.disconnect(do_callback=False)
self.on_connect_failure(err_message=err_message)
def send(self, raw_data, now=False):
if self.get_state() == DISCONNECTED:
log.error('Unable to send %s \n because state is %s.' %
(raw_data, self.get_state()))
def disconnect(self, do_callback=True):
self.set_state(DISCONNECTED)
if do_callback:
# invoke callback given in __init__
self.on_disconnect()
def onreceive(self, recv_handler):
"""
Set the on_receive callback.
onreceive(None) sets callback to Dispatcher.ProcessNonBlocking which is
the default one that will decide what to do with received stanza based on
its tag name and namespace.
Do not confuse it with on_receive() method, which is the callback
itself.
"""
if not recv_handler:
if hasattr(self, '_owner') and hasattr(self._owner, 'Dispatcher'):
self.on_receive = self._owner.Dispatcher.ProcessNonBlocking
else:
log.warn('No Dispatcher plugged. Received data will not be processed')
self.on_receive = None
return
self.on_receive = recv_handler
def _tcp_connecting_started(self):
self.set_state(CONNECTING)
def read_timeout(self):
"""
Called when there's no response from server in defined timeout
"""
if self.on_timeout:
self.on_timeout()
self.renew_send_timeout()
def read_timeout2(self):
"""
called when there's no response from server in defined timeout
"""
if self.on_timeout2:
self.on_timeout2()
self.renew_send_timeout2()
def renew_send_timeout(self):
if self.on_timeout and self.sendtimeout > 0:
self.set_timeout(self.sendtimeout)
def renew_send_timeout2(self):
if self.on_timeout2 and self.sendtimeout2 > 0:
self.set_timeout2(self.sendtimeout2)
def set_timeout(self, timeout):
self.idlequeue.set_read_timeout(self.fd, timeout)
def set_timeout2(self, timeout2):
self.idlequeue.set_read_timeout(self.fd, timeout2, self.read_timeout2)
def get_fd(self):
pass
def remove_timeout(self):
self.idlequeue.remove_timeout(self.fd)
def set_send_timeout(self, timeout, on_timeout):
self.sendtimeout = timeout
if self.sendtimeout > 0:
self.on_timeout = on_timeout
else:
self.on_timeout = None
def set_send_timeout2(self, timeout2, on_timeout2):
self.sendtimeout2 = timeout2
if self.sendtimeout2 > 0:
self.on_timeout2 = on_timeout2
else:
self.on_timeout2 = None
# FIXME: where and why does this need to be called
def start_disconnect(self):
self.set_state(DISCONNECTING)
class NonBlockingTCP(NonBlockingTransport, IdleObject):
"""
Non-blocking TCP socket wrapper
It is used for simple XMPP connection. Can be connected via proxy and can
estabilish TLS connection.
"""
def __init__(self, raise_event, on_disconnect, idlequeue, estabilish_tls,
certs, proxy_dict=None):
"""
:param proxy_dict: dictionary with proxy data as loaded from config file
"""
NonBlockingTransport.__init__(self, raise_event, on_disconnect, idlequeue,
estabilish_tls, certs)
IdleObject.__init__(self)
# queue with messages to be send
self.sendqueue = []
# bytes remained from the last send message
self.sendbuff = ''
self.proxy_dict = proxy_dict
self.on_remote_disconnect = self.disconnect
# FIXME: transport should not be aware xmpp
def start_disconnect(self):
NonBlockingTransport.start_disconnect(self)
self.send('</stream:stream>', now=True)
self.disconnect()
def connect(self, conn_5tuple, on_connect, on_connect_failure):
NonBlockingTransport.connect(self, conn_5tuple, on_connect,
on_connect_failure)
log.info('NonBlockingTCP Connect :: About to connect to %s:%s' %
(self.server, self.port))
try:
self._sock = socket.socket(*conn_5tuple[:3])
except socket.error, (errnum, errstr):
self._on_connect_failure('NonBlockingTCP Connect: Error while creating\
socket: %s %s' % (errnum, errstr))
return
self._send = self._sock.send
self._recv = self._sock.recv
self.fd = self._sock.fileno()
# we want to be notified when send is possible to connected socket because
# it means the TCP connection is estabilished
self._plug_idle(writable=True, readable=False)
self.peerhost = None
# variable for errno symbol that will be found from exception raised
# from connect()
errnum = 0
errstr = str()
# set timeout for TCP connecting - if nonblocking connect() fails, pollend
# is called. If if succeeds pollout is called.
self.idlequeue.set_read_timeout(self.fd, CONNECT_TIMEOUT_SECONDS)
try:
self._sock.setblocking(False)
self._sock.connect((self.server, self.port))
except Exception, exc:
errnum, errstr = exc.args
if errnum in (errno.EINPROGRESS, errno.EALREADY, errno.EWOULDBLOCK):
# connecting in progress
log.info('After NB connect() of %s. "%s" raised => CONNECTING' %
(id(self), errstr))
self._tcp_connecting_started()
return
# if there was some other exception, call failure callback and unplug
# transport which will also remove read_timeouts for descriptor
self._on_connect_failure('Exception while connecting to %s:%s - %s %s' %
(self.server, self.port, errnum, errstr))
def _connect_to_proxy(self):
self.set_state(PROXY_CONNECTING)
if self.proxy_dict['type'] == 'socks5':
proxyclass = proxy_connectors.SOCKS5Connector
elif self.proxy_dict['type'] == 'http' :
proxyclass = proxy_connectors.HTTPCONNECTConnector
proxyclass.get_instance(
send_method=self.send,
onreceive=self.onreceive,
old_on_receive=self.on_receive,
on_success=self._on_connect,
on_failure=self._on_connect_failure,
xmpp_server=self.proxy_dict['xmpp_server'],
proxy_creds=self.proxy_dict['credentials'])
def _on_connect(self):
"""
Preceed invoking of on_connect callback. TCP connection is already
estabilished by this time
"""
if self.estabilish_tls:
self.tls_init(
on_succ = lambda: NonBlockingTransport._on_connect(self),
on_fail = lambda: self._on_connect_failure(
'error while estabilishing TLS'))
else:
NonBlockingTransport._on_connect(self)
def tls_init(self, on_succ, on_fail):
"""
Estabilishes TLS/SSL using this TCP connection by plugging a
NonBlockingTLS module
"""
cacerts, mycerts = self.certs
result = tls_nb.NonBlockingTLS.get_instance(cacerts, mycerts).PlugIn(self)
if result:
on_succ()
else:
on_fail()
def pollin(self):
"""
Called by idlequeu when receive on plugged socket is possible
"""
log.info('pollin called, state == %s' % self.get_state())
self._do_receive()
def pollout(self):
"""
Called by idlequeu when send to plugged socket is possible
"""
log.info('pollout called, state == %s' % self.get_state())
if self.get_state() == CONNECTING:
log.info('%s socket wrapper connected' % id(self))
self.idlequeue.remove_timeout(self.fd)
self._plug_idle(writable=False, readable=False)
self.peerhost = self._sock.getsockname()
if self.proxy_dict:
self._connect_to_proxy()
else:
self._on_connect()
else:
self._do_send()
def pollend(self):
"""
Called by idlequeue on TCP connection errors
"""
log.info('pollend called, state == %s' % self.get_state())
if self.get_state() == CONNECTING:
self._on_connect_failure('Error during connect to %s:%s' %
(self.server, self.port))
else:
self.disconnect()
def disconnect(self, do_callback=True):
if self.get_state() == DISCONNECTED:
return
self.set_state(DISCONNECTED)
self.idlequeue.unplug_idle(self.fd)
if 'NonBlockingTLS' in self.__dict__:
self.NonBlockingTLS.PlugOut()
try:
self._sock.shutdown(socket.SHUT_RDWR)
self._sock.close()
except socket.error, (errnum, errstr):
log.info('Error while disconnecting socket: %s' % errstr)
self.fd = -1
NonBlockingTransport.disconnect(self, do_callback)
def read_timeout(self):
log.info('read_timeout called, state == %s' % self.get_state())
if self.get_state() == CONNECTING:
# if read_timeout is called during connecting, connect() didn't end yet
# thus we have to call the tcp failure callback
self._on_connect_failure('Error during connect to %s:%s' %
(self.server, self.port))
else:
NonBlockingTransport.read_timeout(self)
def set_timeout(self, timeout):
if self.get_state() != DISCONNECTED and self.fd != -1:
NonBlockingTransport.set_timeout(self, timeout)
else:
log.warn('set_timeout: TIMEOUT NOT SET: state is %s, fd is %s' %
(self.get_state(), self.fd))
def remove_timeout(self):
if self.fd:
NonBlockingTransport.remove_timeout(self)
else:
log.warn('remove_timeout: no self.fd state is %s' % self.get_state())
def send(self, raw_data, now=False):
"""
Append raw_data to the queue of messages to be send. If supplied data is
unicode string, encode it to utf-8.
"""
NonBlockingTransport.send(self, raw_data, now)
r = self.encode_stanza(raw_data)
if now:
self.sendqueue.insert(0, r)
self._do_send()
else:
self.sendqueue.append(r)
self._plug_idle(writable=True, readable=True)
def encode_stanza(self, stanza):
"""
Encode str or unicode to utf-8
"""
if isinstance(stanza, unicode):
stanza = stanza.encode('utf-8')
elif not isinstance(stanza, str):
stanza = ustr(stanza).encode('utf-8')
return stanza
def _plug_idle(self, writable, readable):
"""
Plug file descriptor of socket to Idlequeue
Plugged socket will be watched for "send possible" or/and "recv possible"
events. pollin() callback is invoked on "recv possible", pollout() on
"send_possible".
Plugged socket will always be watched for "error" event - in that case,
pollend() is called.
"""
log.info('Plugging fd %d, W:%s, R:%s' % (self.fd, writable, readable))
self.idlequeue.plug_idle(self, writable, readable)
def _do_send(self):
"""
Called when send() to connected socket is possible. First message from
sendqueue will be sent
"""
if not self.sendbuff:
if not self.sendqueue:
log.warn('calling send on empty buffer and queue')
self._plug_idle(writable=False, readable=True)
return None
self.sendbuff = self.sendqueue.pop(0)
try:
send_count = self._send(self.sendbuff)
if send_count:
sent_data = self.sendbuff[:send_count]
self.sendbuff = self.sendbuff[send_count:]
self._plug_idle(
writable=((self.sendqueue!=[]) or (self.sendbuff!='')),
readable=True)
self.raise_event(DATA_SENT, sent_data)
except Exception:
log.error('_do_send:', exc_info=True)
traceback.print_exc()
self.disconnect()
def _do_receive(self):
"""
Reads all pending incoming data. Will call owner's disconnected() method
if appropriate
"""
received = None
errnum = 0
errstr = 'No Error Set'
try:
# get as many bites, as possible, but not more than RECV_BUFSIZE
received = self._recv(RECV_BUFSIZE)
except socket.error, (errnum, errstr):
log.info("_do_receive: got %s:" % received, exc_info=True)
except tls_nb.SSLWrapper.Error, e:
log.info("_do_receive, caught SSL error, got %s:" % received,
exc_info=True)
errnum, errstr = e.errno, e.strerror
if received == '':
errstr = 'zero bytes on recv'
if (self.ssl_lib is None and received == '') or \
(self.ssl_lib == tls_nb.PYSTDLIB and errnum == 8 ) or \
(self.ssl_lib == tls_nb.PYOPENSSL and errnum == -1 ):
# 8 in stdlib: errstr == EOF occured in violation of protocol
# -1 in pyopenssl: errstr == Unexpected EOF
log.info("Disconnected by remote server: #%s, %s" % (errnum, errstr))
self.on_remote_disconnect()
return
if errnum:
log.info("Connection to %s:%s lost: %s %s" % (self.server, self.port,
errnum, errstr), exc_info=True)
self.disconnect()
return
# this branch is for case of non-fatal SSL errors - None is returned from
# recv() but no errnum is set
if received is None:
return
# we have received some bytes, stop the timeout!
self.remove_timeout()
self.renew_send_timeout()
self.renew_send_timeout2()
# pass received data to owner
if self.on_receive:
self.raise_event(DATA_RECEIVED, received)
self._on_receive(received)
else:
# This should never happen, so we need the debug.
# (If there is no handler on receive specified, data is passed to
# Dispatcher.ProcessNonBlocking)
log.error('SOCKET %s Unhandled data received: %s' % (id(self),
received))
self.disconnect()
def _on_receive(self, data):
"""
Preceeds on_receive callback. It peels off and checks HTTP headers in
HTTP classes, in here it just calls the callback
"""
self.on_receive(data)
class NonBlockingHTTP(NonBlockingTCP):
"""
Socket wrapper that creates HTTP message out of sent data and peels-off HTTP
headers from incoming messages
"""
def __init__(self, raise_event, on_disconnect, idlequeue, estabilish_tls,
certs, on_http_request_possible, on_persistent_fallback, http_dict,
proxy_dict=None):
"""
:param on_http_request_possible: method to call when HTTP request to
socket owned by transport is possible.
:param on_persistent_fallback: callback called when server ends TCP
connection. It doesn't have to be fatal for HTTP session.
:param http_dict: dictionary with data for HTTP request and headers
"""
NonBlockingTCP.__init__(self, raise_event, on_disconnect, idlequeue,
estabilish_tls, certs, proxy_dict)
self.http_protocol, self.http_host, self.http_port, self.http_path = \
urisplit(http_dict['http_uri'])
self.http_protocol = self.http_protocol or 'http'
self.http_path = self.http_path or '/'
self.http_version = http_dict['http_version']
self.http_persistent = http_dict['http_persistent']
self.add_proxy_headers = http_dict['add_proxy_headers']
if 'proxy_user' in http_dict and 'proxy_pass' in http_dict:
self.proxy_user, self.proxy_pass = http_dict['proxy_user'], http_dict[
'proxy_pass']
else:
self.proxy_user, self.proxy_pass = None, None
# buffer for partial responses
self.recvbuff = ''
self.expected_length = 0
self.pending_requests = 0
self.on_http_request_possible = on_http_request_possible
self.last_recv_time = 0
self.close_current_connection = False
self.on_remote_disconnect = lambda: on_persistent_fallback(self)
def http_send(self, raw_data, now=False):
self.send(self.build_http_message(raw_data), now)
def _on_receive(self, data):
"""
Preceeds passing received data to owner class. Gets rid of HTTP headers
and checks them.
"""
if self.get_state() == PROXY_CONNECTING:
NonBlockingTCP._on_receive(self, data)
return
# append currently received data to HTTP msg in buffer
self.recvbuff = '%s%s' % (self.recvbuff or '', data)
statusline, headers, httpbody, buffer_rest = self.parse_http_message(
self.recvbuff)
if not (statusline and headers and httpbody):
log.debug('Received incomplete HTTP response')
return
if statusline[1] != '200':
log.error('HTTP Error: %s %s' % (statusline[1], statusline[2]))
self.disconnect()
return
self.expected_length = int(headers['Content-Length'])
if 'Connection' in headers and headers['Connection'].strip()=='close':
self.close_current_connection = True
if self.expected_length > len(httpbody):
# If we haven't received the whole HTTP mess yet, let's end the thread.
# It will be finnished from one of following recvs on plugged socket.
log.info('not enough bytes in HTTP response - %d expected, got %d' %
(self.expected_length, len(httpbody)))
else:
# First part of buffer has been extraced and is going to be handled,
# remove it from buffer
self.recvbuff = buffer_rest
# everything was received
self.expected_length = 0
if not self.http_persistent or self.close_current_connection:
# not-persistent connections disconnect after response
self.disconnect(do_callback=False)
self.close_current_connection = False
self.last_recv_time = time.time()
self.on_receive(data=httpbody, socket=self)
self.on_http_request_possible()
def build_http_message(self, httpbody, method='POST'):
"""
Builds http message with given body. Values for headers and status line
fields are taken from class variables
"""
absolute_uri = '%s://%s:%s%s' % (self.http_protocol, self.http_host,
self.http_port, self.http_path)
headers = ['%s %s %s' % (method, absolute_uri, self.http_version),
'Host: %s:%s' % (self.http_host, self.http_port),
'User-Agent: Gajim',
'Content-Type: text/xml; charset=utf-8',
'Content-Length: %s' % len(str(httpbody))]
if self.add_proxy_headers:
headers.append('Proxy-Connection: keep-alive')
headers.append('Pragma: no-cache')
if self.proxy_user and self.proxy_pass:
credentials = '%s:%s' % (self.proxy_user, self.proxy_pass)
credentials = base64.encodestring(credentials).strip()
headers.append('Proxy-Authorization: Basic %s' % credentials)
else:
headers.append('Connection: Keep-Alive')
headers.append('\r\n')
headers = '\r\n'.join(headers)
return('%s%s' % (headers, httpbody))
def parse_http_message(self, message):
"""
Split http message into a tuple:
(statusline - list of e.g. ['HTTP/1.1', '200', 'OK'],
headers - dictionary of headers e.g. {'Content-Length': '604',
'Content-Type': 'text/xml; charset=utf-8'},
httpbody - string with http body)
http_rest - what is left in the message after a full HTTP header + body
"""
splitted = message.split('\r\n\r\n')
if len(splitted) < 2:
# no complete http message. Keep filling the buffer until we find one
buffer_rest = message
return ('', '', '', buffer_rest)
else:
(header, httpbody) = splitted[:2]
header = header.replace('\r', '')
header = header.lstrip('\n')
header = header.split('\n')
statusline = header[0].split(' ', 2)
header = header[1:]
headers = {}
for dummy in header:
row = dummy.split(' ', 1)
headers[row[0][:-1]] = row[1]
body_size = headers['Content-Length']
rest_splitted = splitted[2:]
while (len(httpbody) < body_size) and rest_splitted:
# Complete httpbody until it has the announced size
httpbody = '\n\n'.join([httpbody, rest_splitted.pop(0)])
buffer_rest = "\n\n".join(rest_splitted)
return (statusline, headers, httpbody, buffer_rest)
class NonBlockingHTTPBOSH(NonBlockingHTTP):
"""
Class for BOSH HTTP connections. Slightly redefines HTTP transport by
calling bosh bodytag generating callback before putting data on wire
"""
def set_stanza_build_cb(self, build_cb):
self.build_cb = build_cb
def _do_send(self):
if self.state == PROXY_CONNECTING:
NonBlockingTCP._do_send(self)
return
if not self.sendbuff:
stanza = self.build_cb(socket=self)
stanza = self.encode_stanza(stanza)
stanza = self.build_http_message(httpbody=stanza)
self.sendbuff = stanza
NonBlockingTCP._do_send(self)

View File

@ -18,15 +18,15 @@
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
##
from common import gajim
import common.xmpp
from common.xmpp.idlequeue import IdleObject
from common.xmpp import dispatcher_nb, simplexml
from common.xmpp.plugin import *
from common.xmpp.simplexml import ustr
from common.xmpp.transports_nb import DATA_RECEIVED, DATA_SENT, DATA_ERROR
import nbxmpp
from nbxmpp.idlequeue import IdleObject
from nbxmpp import dispatcher_nb, simplexml
from nbxmpp.plugin import *
from nbxmpp.simplexml import ustr
from nbxmpp.transports_nb import DATA_RECEIVED, DATA_SENT, DATA_ERROR
from common.zeroconf import zeroconf
from common.xmpp.protocol import *
from nbxmpp.protocol import *
import socket
import errno
import sys
@ -309,24 +309,23 @@ class P2PClient(IdleObject):
self._caller.peerhost = self.Connection._sock.getsockname()
self.RegisterHandler('message', lambda conn,
data:self._caller._messageCB(self.Server, conn, data))
self.RegisterHandler('iq', self._caller._siSetCB, 'set',
common.xmpp.NS_SI)
self.RegisterHandler('iq', self._caller._siSetCB, 'set', nbxmpp.NS_SI)
self.RegisterHandler('iq', self._caller._siErrorCB, 'error',
common.xmpp.NS_SI)
nbxmpp.NS_SI)
self.RegisterHandler('iq', self._caller._siResultCB, 'result',
common.xmpp.NS_SI)
nbxmpp.NS_SI)
self.RegisterHandler('iq', self._caller._bytestreamSetCB, 'set',
common.xmpp.NS_BYTESTREAM)
nbxmpp.NS_BYTESTREAM)
self.RegisterHandler('iq', self._caller._bytestreamResultCB, 'result',
common.xmpp.NS_BYTESTREAM)
nbxmpp.NS_BYTESTREAM)
self.RegisterHandler('iq', self._caller._bytestreamErrorCB, 'error',
common.xmpp.NS_BYTESTREAM)
nbxmpp.NS_BYTESTREAM)
self.RegisterHandler('iq', self._caller._DiscoverItemsGetCB, 'get',
common.xmpp.NS_DISCO_ITEMS)
nbxmpp.NS_DISCO_ITEMS)
self.RegisterHandler('iq', self._caller._JingleCB, 'result')
self.RegisterHandler('iq', self._caller._JingleCB, 'error')
self.RegisterHandler('iq', self._caller._JingleCB, 'set',
common.xmpp.NS_JINGLE)
nbxmpp.NS_JINGLE)
class P2PConnection(IdleObject, PlugIn):
def __init__(self, sock_hash, _sock, host=None, port=None, caller=None,

View File

@ -28,7 +28,7 @@ import socket
from calendar import timegm
import common.xmpp
import nbxmpp
from common import helpers
from common import gajim
@ -111,12 +111,12 @@ connection_handlers.ConnectionHandlersBase, connection_handlers.ConnectionJingle
return
if self.commandItemsQuery(con, iq_obj):
raise common.xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
node = iq_obj.getTagAttr('query', 'node')
if node is None:
result = iq_obj.buildReply('result')
self.connection.send(result)
raise common.xmpp.NodeProcessed
if node==common.xmpp.NS_COMMANDS:
raise nbxmpp.NodeProcessed
if node==nbxmpp.NS_COMMANDS:
self.commandListQuery(con, iq_obj)
raise common.xmpp.NodeProcessed
raise nbxmpp.NodeProcessed

View File

@ -418,14 +418,14 @@ class ConnectionZeroconf(CommonConnection, ConnectionHandlersZeroconf):
# send a stanza untouched
if not self.connection:
return
if not isinstance(stanza, common.xmpp.Node):
stanza = common.xmpp.Protocol(node=stanza)
if not isinstance(stanza, nbxmpp.Node):
stanza = nbxmpp.Protocol(node=stanza)
self.connection.send(stanza)
def _event_dispatcher(self, realm, event, data):
CommonConnection._event_dispatcher(self, realm, event, data)
if realm == '':
if event == common.xmpp.transports_nb.DATA_ERROR:
if event == nbxmpp.transports_nb.DATA_ERROR:
thread_id = data[1]
frm = unicode(data[0])
session = self.get_or_create_session(frm, thread_id)

View File

@ -78,7 +78,7 @@ class DataFormWidget(gtk.Alignment, object):
def set_data_form(self, dataform):
"""
Set the data form (xmpp.DataForm) displayed in widget
Set the data form (nbxmpp.DataForm) displayed in widget
"""
assert isinstance(dataform, dataforms.DataForm)

View File

@ -59,7 +59,7 @@ import adhoc_commands
import search_window
from common import gajim
from common import xmpp
import nbxmpp
from common.exceptions import GajimGeneralException
from common import helpers
from common import ged
@ -350,7 +350,7 @@ class ServicesCache:
# NS_DISCO_ITEMS anyways.
# Allow browsing for unknown types aswell.
if (not features and not identities) or \
xmpp.NS_DISCO_ITEMS in features or xmpp.NS_BROWSE in features:
nbxmpp.NS_DISCO_ITEMS in features or nbxmpp.NS_BROWSE in features:
return ToplevelAgentBrowser
return None
@ -1502,11 +1502,11 @@ class ToplevelAgentBrowser(AgentBrowser):
def _update_actions(self, jid, node, identities, features, data):
AgentBrowser._update_actions(self, jid, node, identities, features, data)
if self.execute_button and xmpp.NS_COMMANDS in features:
if self.execute_button and nbxmpp.NS_COMMANDS in features:
self.execute_button.set_sensitive(True)
if self.search_button and xmpp.NS_SEARCH in features:
if self.search_button and nbxmpp.NS_SEARCH in features:
self.search_button.set_sensitive(True)
if self.register_button and xmpp.NS_REGISTER in features:
if self.register_button and nbxmpp.NS_REGISTER in features:
# We can register this agent
registered_transports = []
jid_list = gajim.contacts.get_jid_list(self.account)
@ -1520,13 +1520,13 @@ class ToplevelAgentBrowser(AgentBrowser):
else:
self.register_button.set_label(_('Re_gister'))
self.register_button.set_sensitive(True)
if self.join_button and xmpp.NS_MUC in features:
if self.join_button and nbxmpp.NS_MUC in features:
self.join_button.set_sensitive(True)
def _default_action(self, jid, node, identities, features, data):
if AgentBrowser._default_action(self, jid, node, identities, features, data):
return True
if xmpp.NS_REGISTER in features:
if nbxmpp.NS_REGISTER in features:
# Register if we can't browse
self.on_register_button_clicked()
return True
@ -2239,7 +2239,7 @@ class DiscussionGroupsBrowser(AgentBrowser):
# we now know subscriptions, update button states
self.update_actions()
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
def _on_pep_subscribe(self, conn, request, groupnode):
"""
@ -2255,7 +2255,7 @@ class DiscussionGroupsBrowser(AgentBrowser):
self.update_actions()
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
def _on_pep_unsubscribe(self, conn, request, groupnode):
"""
@ -2271,7 +2271,7 @@ class DiscussionGroupsBrowser(AgentBrowser):
self.update_actions()
raise xmpp.NodeProcessed
raise nbxmpp.NodeProcessed
# Fill the global agent type info dictionary
_agent_type_info = _gen_agent_type_info()

View File

@ -36,7 +36,7 @@ from common import helpers
from common.file_props import FilesProp
from common.protocol.bytestream import (is_transfer_active, is_transfer_paused,
is_transfer_stopped)
from common.xmpp.protocol import NS_JINGLE_FILE_TRANSFER
from nbxmpp.protocol import NS_JINGLE_FILE_TRANSFER
import logging
log = logging.getLogger('gajim.filetransfer_window')
@ -684,14 +684,14 @@ class FileTransfersWindow:
# Converts date-time from seconds from epoch to iso 8601
import time, datetime
ts = time.gmtime(epoch)
dt = datetime.datetime(ts.tm_year, ts.tm_mon, ts.tm_mday, ts.tm_hour,
dt = datetime.datetime(ts.tm_year, ts.tm_mon, ts.tm_mday, ts.tm_hour,
ts.tm_min, ts.tm_sec)
return dt.isoformat()
def get_send_file_props(self, account, contact, file_path, file_name,
file_desc=''):
"""
Create new file_props object and set initial file transfer
Create new file_props object and set initial file transfer
properties in it
"""
if os.path.isfile(file_path):

View File

@ -62,6 +62,12 @@ if os.name == 'nt':
new_list.insert(0, os.path.join(os.getcwd(), 'gtk', 'bin'))
os.environ['PATH'] = ';'.join(new_list)
try:
import nbxmpp
except ImportError:
print 'Gajim needs python-nbxmpp to run. Quiting...'
sys.exit()
from common import demandimport
demandimport.enable()
demandimport.ignore += ['gobject._gobject', 'libasyncns', 'i18n',

View File

@ -21,7 +21,8 @@
'''Window to create new post for discussion groups service.'''
from common import gajim, xmpp
from common import gajim
from nbxmpp import Node
import gtkgui_helpers
class GroupsPostWindow:
@ -56,7 +57,7 @@ class GroupsPostWindow:
Gather info from widgets and send it as a message
"""
# constructing item to publish... that's atom:entry element
item = xmpp.Node('entry', {'xmlns':'http://www.w3.org/2005/Atom'})
item = Node('entry', {'xmlns':'http://www.w3.org/2005/Atom'})
author = item.addChild('author')
author.addChild('name', {}, [self.from_entry.get_text()])
item.addChild('generator', {}, ['Gajim'])

View File

@ -69,8 +69,8 @@ from session import ChatControlSession
import common.sleepy
from common.xmpp import idlequeue
from common.xmpp import Hashes
from nbxmpp import idlequeue
from nbxmpp import Hashes
from common.zeroconf import connection_zeroconf
from common import resolver
from common import caps_cache

View File

@ -25,7 +25,8 @@ import message_control
from common import gajim
from common import helpers
from common.xmpp.protocol import NS_COMMANDS, NS_FILE, NS_MUC, NS_ESESSION, NS_JINGLE_FILE_TRANSFER
from nbxmpp.protocol import NS_COMMANDS, NS_FILE, NS_MUC, NS_ESESSION
from nbxmpp.protocol import NS_JINGLE_FILE_TRANSFER
def build_resources_submenu(contacts, account, action, room_jid=None,
room_account=None, cap=None):

View File

@ -24,7 +24,7 @@ import dataforms_widget
from common import dataforms
from common import gajim
from common import xmpp
import nbxmpp
def describe_features(features):
"""
@ -55,10 +55,10 @@ class FeatureNegotiationWindow:
self.window.show_all()
def on_ok_button_clicked(self, widget):
acceptance = xmpp.Message(self.jid)
acceptance = nbxmpp.Message(self.jid)
acceptance.setThread(self.session.thread_id)
feature = acceptance.NT.feature
feature.setNamespace(xmpp.NS_FEATURE)
feature.setNamespace(nbxmpp.NS_FEATURE)
form = self.data_form_widget.data_form
form.setAttr('type', 'submit')
@ -70,14 +70,14 @@ class FeatureNegotiationWindow:
self.window.destroy()
def on_cancel_button_clicked(self, widget):
rejection = xmpp.Message(self.jid)
rejection = nbxmpp.Message(self.jid)
rejection.setThread(self.session.thread_id)
feature = rejection.NT.feature
feature.setNamespace(xmpp.NS_FEATURE)
feature.setNamespace(nbxmpp.NS_FEATURE)
x = xmpp.DataForm(typ='submit')
x.addChild(node=xmpp.DataField('FORM_TYPE', value='urn:xmpp:ssn'))
x.addChild(node=xmpp.DataField('accept', value='false', typ='boolean'))
x = nbxmpp.DataForm(typ='submit')
x.addChild(node=nbxmpp.DataField('FORM_TYPE', value='urn:xmpp:ssn'))
x.addChild(node=nbxmpp.DataField('accept', value='false', typ='boolean'))
feature.addChild(node=x)

View File

@ -70,7 +70,7 @@ from common import dbus_support
if dbus_support.supported:
import dbus
from common.xmpp.protocol import NS_FILE
from nbxmpp.protocol import NS_FILE
from common.pep import MOODS, ACTIVITIES
#(icon, name, type, jid, account, editable, second pixbuf)

View File

@ -31,8 +31,6 @@ from common import ged
from common.connection_handlers_events import ChatstateReceivedEvent, \
InformationEvent
import common.xmpp
import message_control
import notify