From 77e53f7488d930598e63b2d195e8e5cce7456348 Mon Sep 17 00:00:00 2001 From: Stefan Bethge <stefan@lanpartei.de> Date: Mon, 29 May 2006 19:57:39 +0000 Subject: [PATCH] trying to show contacts on the roster --- src/common/client_zeroconf.py | 12 + src/common/connection.py | 1 + src/common/connection_handlers_zeroconf.py | 1505 +------------------- src/common/connection_zeroconf.py | 432 +----- src/common/roster_zeroconf.py | 37 + src/common/zeroconf.py | 39 +- 6 files changed, 117 insertions(+), 1909 deletions(-) create mode 100644 src/common/client_zeroconf.py create mode 100644 src/common/roster_zeroconf.py diff --git a/src/common/client_zeroconf.py b/src/common/client_zeroconf.py new file mode 100644 index 0000000000..f4b98aab98 --- /dev/null +++ b/src/common/client_zeroconf.py @@ -0,0 +1,12 @@ + +from common import roster_zeroconf + +class ClientZeroconf: + def __init__(self, zeroconf): + self.roster = roster_zeroconf.Roster(zeroconf) + + def getRoster(self): + return self.roster.getRoster() + + def send(self, str): + pass diff --git a/src/common/connection.py b/src/common/connection.py index 850317ce81..a361b1b597 100644 --- a/src/common/connection.py +++ b/src/common/connection.py @@ -54,6 +54,7 @@ class Connection(ConnectionHandlers): self.connection = None # xmpppy ClientCommon instance # this property is used to prevent double connections self.last_connection = None # last ClientCommon instance + self.is_zeroconf = False self.gpg = None self.status = '' self.old_show = '' diff --git a/src/common/connection_handlers_zeroconf.py b/src/common/connection_handlers_zeroconf.py index 1a82dc682c..a912a0846b 100644 --- a/src/common/connection_handlers_zeroconf.py +++ b/src/common/connection_handlers_zeroconf.py @@ -51,702 +51,6 @@ except: gajim.log.debug(_('Unable to load idle module')) HAS_IDLE = False -class ConnectionBytestream: - def __init__(self): - self.files_props = {} - - def is_transfer_stoped(self, file_props): - if file_props.has_key('error') and file_props['error'] != 0: - return True - if file_props.has_key('completed') and file_props['completed']: - return True - if file_props.has_key('connected') and file_props['connected'] == False: - return True - if not file_props.has_key('stopped') or not file_props['stopped']: - return False - return True - - def send_success_connect_reply(self, streamhost): - ''' send reply to the initiator of FT that we - made a connection - ''' - if streamhost is None: - return None - iq = common.xmpp.Iq(to = streamhost['initiator'], typ = 'result', - frm = streamhost['target']) - iq.setAttr('id', streamhost['id']) - query = iq.setTag('query') - query.setNamespace(common.xmpp.NS_BYTESTREAM) - stream_tag = query.setTag('streamhost-used') - stream_tag.setAttr('jid', streamhost['jid']) - self.connection.send(iq) - - def remove_transfers_for_contact(self, contact): - ''' stop all active transfer for contact ''' - for file_props in self.files_props.values(): - if self.is_transfer_stoped(file_props): - continue - receiver_jid = unicode(file_props['receiver']).split('/')[0] - if contact.jid == receiver_jid: - file_props['error'] = -5 - self.remove_transfer(file_props) - self.dispatch('FILE_REQUEST_ERROR', (contact.jid, file_props)) - sender_jid = unicode(file_props['sender']).split('/')[0] - if contact.jid == sender_jid: - file_props['error'] = -3 - self.remove_transfer(file_props) - - def remove_all_transfers(self): - ''' stops and removes all active connections from the socks5 pool ''' - for file_props in self.files_props.values(): - self.remove_transfer(file_props, remove_from_list = False) - del(self.files_props) - self.files_props = {} - - def remove_transfer(self, file_props, remove_from_list = True): - if file_props is None: - return - self.disconnect_transfer(file_props) - sid = file_props['sid'] - gajim.socks5queue.remove_file_props(self.name, sid) - - if remove_from_list: - if self.files_props.has_key('sid'): - del(self.files_props['sid']) - - def disconnect_transfer(self, file_props): - if file_props is None: - return - if file_props.has_key('hash'): - gajim.socks5queue.remove_sender(file_props['hash']) - - if file_props.has_key('streamhosts'): - for host in file_props['streamhosts']: - if host.has_key('idx') and host['idx'] > 0: - gajim.socks5queue.remove_receiver(host['idx']) - gajim.socks5queue.remove_sender(host['idx']) - - def send_socks5_info(self, file_props, fast = True, receiver = None, - sender = None): - ''' send iq for the present streamhosts and proxies ''' - if type(self.peerhost) != tuple: - return - port = gajim.config.get('file_transfers_port') - ft_override_host_to_send = gajim.config.get('ft_override_host_to_send') - cfg_proxies = gajim.config.get_per('accounts', self.name, - 'file_transfer_proxies') - if receiver is None: - receiver = file_props['receiver'] - if sender is None: - sender = file_props['sender'] - proxyhosts = [] - if fast and cfg_proxies: - proxies = map(lambda e:e.strip(), cfg_proxies.split(',')) - default = gajim.proxy65_manager.get_default_for_name(self.name) - if default: - # add/move default proxy at top of the others - if proxies.__contains__(default): - proxies.remove(default) - proxies.insert(0, default) - - for proxy in proxies: - (host, _port, jid) = gajim.proxy65_manager.get_proxy(proxy, self.name) - if host is None: - continue - host_dict={ - 'state': 0, - 'target': unicode(receiver), - 'id': file_props['sid'], - 'sid': file_props['sid'], - 'initiator': proxy, - 'host': host, - 'port': unicode(_port), - 'jid': jid - } - proxyhosts.append(host_dict) - sha_str = helpers.get_auth_sha(file_props['sid'], sender, - receiver) - file_props['sha_str'] = sha_str - if not ft_override_host_to_send: - ft_override_host_to_send = self.peerhost[0] - ft_override_host_to_send = socket.gethostbyname(ft_override_host_to_send) - listener = gajim.socks5queue.start_listener(self.peerhost[0], port, - sha_str, self._result_socks5_sid, file_props['sid']) - if listener == None: - file_props['error'] = -5 - self.dispatch('FILE_REQUEST_ERROR', (unicode(receiver), file_props)) - self._connect_error(unicode(receiver), file_props['sid'], - file_props['sid'], code = 406) - return - - iq = common.xmpp.Protocol(name = 'iq', to = unicode(receiver), - typ = 'set') - file_props['request-id'] = 'id_' + file_props['sid'] - iq.setID(file_props['request-id']) - query = iq.setTag('query') - query.setNamespace(common.xmpp.NS_BYTESTREAM) - query.setAttr('mode', 'tcp') - query.setAttr('sid', file_props['sid']) - streamhost = query.setTag('streamhost') - streamhost.setAttr('port', unicode(port)) - streamhost.setAttr('host', ft_override_host_to_send) - streamhost.setAttr('jid', sender) - if fast and proxyhosts != [] and gajim.config.get_per('accounts', - self.name, 'use_ft_proxies'): - file_props['proxy_receiver'] = unicode(receiver) - file_props['proxy_sender'] = unicode(sender) - file_props['proxyhosts'] = proxyhosts - for proxyhost in proxyhosts: - streamhost = common.xmpp.Node(tag = 'streamhost') - query.addChild(node=streamhost) - streamhost.setAttr('port', proxyhost['port']) - streamhost.setAttr('host', proxyhost['host']) - streamhost.setAttr('jid', proxyhost['jid']) - - # don't add the proxy child tag for streamhosts, which are proxies - # proxy = streamhost.setTag('proxy') - # proxy.setNamespace(common.xmpp.NS_STREAM) - self.connection.send(iq) - - def send_file_rejection(self, file_props): - ''' informs sender that we refuse to download the file ''' - # user response to ConfirmationDialog may come after we've disconneted - if not self.connection or self.connected < 2: - return - iq = common.xmpp.Protocol(name = 'iq', - to = unicode(file_props['sender']), typ = 'error') - iq.setAttr('id', file_props['request-id']) - err = common.xmpp.ErrorNode(code = '406', typ = 'auth', name = - 'not-acceptable') - iq.addChild(node=err) - self.connection.send(iq) - - def send_file_approval(self, file_props): - ''' send iq, confirming that we want to download the file ''' - # user response to ConfirmationDialog may come after we've disconneted - if not self.connection or self.connected < 2: - return - iq = common.xmpp.Protocol(name = 'iq', - to = unicode(file_props['sender']), typ = 'result') - iq.setAttr('id', file_props['request-id']) - si = iq.setTag('si') - si.setNamespace(common.xmpp.NS_SI) - if file_props.has_key('offset') and file_props['offset']: - file_tag = si.setTag('file') - file_tag.setNamespace(common.xmpp.NS_FILE) - range_tag = file_tag.setTag('range') - range_tag.setAttr('offset', file_props['offset']) - feature = si.setTag('feature') - feature.setNamespace(common.xmpp.NS_FEATURE) - _feature = common.xmpp.DataForm(typ='submit') - feature.addChild(node=_feature) - field = _feature.setField('stream-method') - field.delAttr('type') - field.setValue(common.xmpp.NS_BYTESTREAM) - self.connection.send(iq) - - def send_file_request(self, file_props): - ''' send iq for new FT request ''' - if not self.connection or self.connected < 2: - return - our_jid = gajim.get_jid_from_account(self.name) - resource = self.server_resource - frm = our_jid + '/' + resource - file_props['sender'] = frm - fjid = file_props['receiver'].jid + '/' + file_props['receiver'].resource - iq = common.xmpp.Protocol(name = 'iq', to = fjid, - typ = 'set') - iq.setID(file_props['sid']) - self.files_props[file_props['sid']] = file_props - si = iq.setTag('si') - si.setNamespace(common.xmpp.NS_SI) - si.setAttr('profile', common.xmpp.NS_FILE) - si.setAttr('id', file_props['sid']) - file_tag = si.setTag('file') - file_tag.setNamespace(common.xmpp.NS_FILE) - file_tag.setAttr('name', file_props['name']) - file_tag.setAttr('size', file_props['size']) - desc = file_tag.setTag('desc') - if file_props.has_key('desc'): - desc.setData(file_props['desc']) - file_tag.setTag('range') - feature = si.setTag('feature') - feature.setNamespace(common.xmpp.NS_FEATURE) - _feature = common.xmpp.DataForm(typ='form') - feature.addChild(node=_feature) - field = _feature.setField('stream-method') - field.setAttr('type', 'list-single') - field.addOption(common.xmpp.NS_BYTESTREAM) - self.connection.send(iq) - - def _result_socks5_sid(self, sid, hash_id): - ''' store the result of sha message from auth. ''' - if not self.files_props.has_key(sid): - return - file_props = self.files_props[sid] - file_props['hash'] = hash_id - return - - def _connect_error(self, to, _id, sid, code = 404): - ''' cb, when there is an error establishing BS connection, or - when connection is rejected''' - msg_dict = { - 404: 'Could not connect to given hosts', - 405: 'Cancel', - 406: 'Not acceptable', - } - msg = msg_dict[code] - iq = None - iq = common.xmpp.Protocol(name = 'iq', to = to, - typ = 'error') - iq.setAttr('id', _id) - err = iq.setTag('error') - err.setAttr('code', unicode(code)) - err.setData(msg) - self.connection.send(iq) - if code == 404: - file_props = gajim.socks5queue.get_file_props(self.name, sid) - if file_props is not None: - self.disconnect_transfer(file_props) - file_props['error'] = -3 - self.dispatch('FILE_REQUEST_ERROR', (to, file_props)) - - def _proxy_auth_ok(self, proxy): - '''cb, called after authentication to proxy server ''' - file_props = self.files_props[proxy['sid']] - iq = common.xmpp.Protocol(name = 'iq', to = proxy['initiator'], - typ = 'set') - auth_id = "au_" + proxy['sid'] - iq.setID(auth_id) - query = iq.setTag('query') - query.setNamespace(common.xmpp.NS_BYTESTREAM) - query.setAttr('sid', proxy['sid']) - activate = query.setTag('activate') - activate.setData(file_props['proxy_receiver']) - iq.setID(auth_id) - self.connection.send(iq) - - # register xmpppy handlers for bytestream and FT stanzas - def _bytestreamErrorCB(self, con, iq_obj): - gajim.log.debug('_bytestreamErrorCB') - id = unicode(iq_obj.getAttr('id')) - frm = helpers.get_full_jid_from_iq(iq_obj) - query = iq_obj.getTag('query') - gajim.proxy65_manager.error_cb(frm, query) - jid = helpers.get_jid_from_iq(iq_obj) - id = id[3:] - if not self.files_props.has_key(id): - return - file_props = self.files_props[id] - file_props['error'] = -4 - self.dispatch('FILE_REQUEST_ERROR', (jid, file_props)) - raise common.xmpp.NodeProcessed - - def _bytestreamSetCB(self, con, iq_obj): - gajim.log.debug('_bytestreamSetCB') - target = unicode(iq_obj.getAttr('to')) - id = unicode(iq_obj.getAttr('id')) - query = iq_obj.getTag('query') - sid = unicode(query.getAttr('sid')) - file_props = gajim.socks5queue.get_file_props( - self.name, sid) - streamhosts=[] - for item in query.getChildren(): - if item.getName() == 'streamhost': - host_dict={ - 'state': 0, - 'target': target, - 'id': id, - 'sid': sid, - 'initiator': helpers.get_full_jid_from_iq(iq_obj) - } - for attr in item.getAttrs(): - host_dict[attr] = item.getAttr(attr) - streamhosts.append(host_dict) - if file_props is None: - if self.files_props.has_key(sid): - file_props = self.files_props[sid] - file_props['fast'] = streamhosts - if file_props['type'] == 's': # FIXME: remove fast xmlns - # only psi do this - - if file_props.has_key('streamhosts'): - file_props['streamhosts'].extend(streamhosts) - else: - file_props['streamhosts'] = streamhosts - if not gajim.socks5queue.get_file_props(self.name, sid): - gajim.socks5queue.add_file_props(self.name, file_props) - gajim.socks5queue.connect_to_hosts(self.name, sid, - self.send_success_connect_reply, None) - raise common.xmpp.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 common.xmpp.NodeProcessed - - def _ResultCB(self, con, iq_obj): - gajim.log.debug('_ResultCB') - # if we want to respect jep-0065 we have to check for proxy - # activation result in any result iq - real_id = unicode(iq_obj.getAttr('id')) - if real_id[:3] != 'au_': - return - frm = helpers.get_full_jid_from_iq(iq_obj) - id = real_id[3:] - if self.files_props.has_key(id): - file_props = self.files_props[id] - if file_props['streamhost-used']: - for host in file_props['proxyhosts']: - if host['initiator'] == frm and host.has_key('idx'): - gajim.socks5queue.activate_proxy(host['idx']) - raise common.xmpp.NodeProcessed - - def _bytestreamResultCB(self, con, iq_obj): - gajim.log.debug('_bytestreamResultCB') - frm = helpers.get_full_jid_from_iq(iq_obj) - real_id = unicode(iq_obj.getAttr('id')) - query = iq_obj.getTag('query') - gajim.proxy65_manager.resolve_result(frm, query) - - try: - streamhost = query.getTag('streamhost-used') - except: # this bytestream result is not what we need - pass - id = real_id[3:] - if self.files_props.has_key(id): - file_props = self.files_props[id] - else: - raise common.xmpp.NodeProcessed - if streamhost is None: - # proxy approves the activate query - if real_id[:3] == 'au_': - id = real_id[3:] - if not file_props.has_key('streamhost-used') or \ - file_props['streamhost-used'] is False: - raise common.xmpp.NodeProcessed - if not file_props.has_key('proxyhosts'): - raise common.xmpp.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 common.xmpp.NodeProcessed - jid = streamhost.getAttr('jid') - if file_props.has_key('streamhost-used') and \ - file_props['streamhost-used'] is True: - raise common.xmpp.NodeProcessed - - if real_id[:3] == 'au_': - gajim.socks5queue.send_file(file_props, self.name) - raise common.xmpp.NodeProcessed - - proxy = None - if file_props.has_key('proxyhosts'): - for proxyhost in file_props['proxyhosts']: - if proxyhost['jid'] == jid: - proxy = proxyhost - - if proxy != None: - file_props['streamhost-used'] = True - if not file_props.has_key('streamhosts'): - file_props['streamhosts'] = [] - file_props['streamhosts'].append(proxy) - file_props['is_a_proxy'] = True - receiver = socks5.Socks5Receiver(gajim.idlequeue, proxy, file_props['sid'], file_props) - gajim.socks5queue.add_receiver(self.name, receiver) - proxy['idx'] = receiver.queue_idx - gajim.socks5queue.on_success = self._proxy_auth_ok - raise common.xmpp.NodeProcessed - - else: - gajim.socks5queue.send_file(file_props, self.name) - if file_props.has_key('fast'): - fasts = file_props['fast'] - if len(fasts) > 0: - self._connect_error(frm, fasts[0]['id'], file_props['sid'], - code = 406) - - raise common.xmpp.NodeProcessed - - def _siResultCB(self, con, iq_obj): - gajim.log.debug('_siResultCB') - id = iq_obj.getAttr('id') - if not self.files_props.has_key(id): - # no such jid - return - file_props = self.files_props[id] - if file_props is None: - # file properties for jid is none - return - if file_props.has_key('request-id'): - # we have already sent streamhosts info - return - file_props['receiver'] = helpers.get_full_jid_from_iq(iq_obj) - si = iq_obj.getTag('si') - file_tag = si.getTag('file') - range_tag = None - if file_tag: - range_tag = file_tag.getTag('range') - if range_tag: - offset = range_tag.getAttr('offset') - if offset: - file_props['offset'] = int(offset) - length = range_tag.getAttr('length') - if length: - file_props['length'] = int(length) - feature = si.setTag('feature') - if feature.getNamespace() != common.xmpp.NS_FEATURE: - return - form_tag = feature.getTag('x') - form = common.xmpp.DataForm(node=form_tag) - field = form.getField('stream-method') - if field.getValue() != common.xmpp.NS_BYTESTREAM: - return - self.send_socks5_info(file_props, fast = True) - raise common.xmpp.NodeProcessed - - def _siSetCB(self, con, iq_obj): - gajim.log.debug('_siSetCB') - jid = helpers.get_jid_from_iq(iq_obj) - si = iq_obj.getTag('si') - profile = si.getAttr('profile') - mime_type = si.getAttr('mime-type') - if profile != common.xmpp.NS_FILE: - return - file_tag = si.getTag('file') - file_props = {'type': 'r'} - for attribute in file_tag.getAttrs(): - if attribute in ('name', 'size', 'hash', 'date'): - val = file_tag.getAttr(attribute) - if val is None: - continue - file_props[attribute] = val - file_desc_tag = file_tag.getTag('desc') - if file_desc_tag is not None: - file_props['desc'] = file_desc_tag.getData() - - if mime_type is not None: - file_props['mime-type'] = mime_type - our_jid = gajim.get_jid_from_account(self.name) - resource = self.server_resource - file_props['receiver'] = our_jid + '/' + resource - file_props['sender'] = helpers.get_full_jid_from_iq(iq_obj) - file_props['request-id'] = unicode(iq_obj.getAttr('id')) - file_props['sid'] = unicode(si.getAttr('id')) - gajim.socks5queue.add_file_props(self.name, file_props) - self.dispatch('FILE_REQUEST', (jid, file_props)) - raise common.xmpp.NodeProcessed - - def _siErrorCB(self, con, iq_obj): - gajim.log.debug('_siErrorCB') - si = iq_obj.getTag('si') - profile = si.getAttr('profile') - if profile != common.xmpp.NS_FILE: - return - id = iq_obj.getAttr('id') - if not self.files_props.has_key(id): - # no such jid - return - file_props = self.files_props[id] - if file_props is None: - # file properties for jid is none - return - jid = helpers.get_jid_from_iq(iq_obj) - file_props['error'] = -3 - self.dispatch('FILE_REQUEST_ERROR', (jid, file_props)) - raise common.xmpp.NodeProcessed - -class ConnectionDisco: - ''' hold xmpppy handlers and public methods for discover services''' - def discoverItems(self, jid, node = None, id_prefix = None): - '''According to JEP-0030: jid is mandatory, - name, node, action is optional.''' - self._discover(common.xmpp.NS_DISCO_ITEMS, jid, node, id_prefix) - - def discoverInfo(self, jid, node = None, id_prefix = None): - '''According to JEP-0030: - 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) - - def request_register_agent_info(self, agent): - if not self.connection: - return None - iq=common.xmpp.Iq('get', common.xmpp.NS_REGISTER, to=agent) - id = self.connection.getAnID() - iq.setID(id) - # Wait the answer during 30 secondes - self.awaiting_timeouts[gajim.idlequeue.current_time() + 30] = (id, - _('Registration information for transport %s has not arrived in time' % \ - agent)) - self.connection.SendAndCallForResponse(iq, self._ReceivedRegInfo, - {'agent': agent}) - - def build_data_from_dict(self, query, config): - x = query.setTag(common.xmpp.NS_DATA + ' x', attrs = {'type': 'submit'}) - i = 0 - while config.has_key(i): - if not config[i].has_key('type'): - i += 1 - continue - if config[i]['type'] == 'fixed': - i += 1 - continue - tag = x.addChild('field') - if config[i].has_key('var'): - tag.setAttr('var', config[i]['var']) - if config[i].has_key('values'): - for val in config[i]['values']: - if val == False: - val = '0' - elif val == True: - val = '1' - # Force to create a new child - tag.addChild('value').addData(val) - i += 1 - - def register_agent(self, agent, info, is_form = False): - if not self.connection: - return - if is_form: - iq = common.xmpp.Iq('set', common.xmpp.NS_REGISTER, to = agent) - query = iq.getTag('query') - self.build_data_from_dict(query, info) - self.connection.send(iq) - else: - # fixed: blocking - common.xmpp.features_nb.register(self.connection, agent, info, None) - - - def _discover(self, ns, jid, node = None, id_prefix = None): - if not self.connection: - return - iq = common.xmpp.Iq(typ = 'get', to = jid, queryNS = ns) - if id_prefix: - id = self.connection.getAnID() - iq.setID('%s%s' % (id_prefix, id)) - if node: - iq.setQuerynode(node) - self.connection.send(iq) - - def _ReceivedRegInfo(self, con, resp, agent): - common.xmpp.features_nb._ReceivedRegInfo(con, resp, agent) - self._IqCB(con, resp) - - def _discoGetCB(self, con, iq_obj): - ''' get disco info ''' - 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.setAttr('id', id) - query = iq.setTag('query') - # bytestream transfers - feature = common.xmpp.Node('feature') - feature.setAttr('var', common.xmpp.NS_BYTESTREAM) - query.addChild(node=feature) - # si methods - feature = common.xmpp.Node('feature') - feature.setAttr('var', common.xmpp.NS_SI) - query.addChild(node=feature) - # filetransfers transfers - feature = common.xmpp.Node('feature') - feature.setAttr('var', common.xmpp.NS_FILE) - query.addChild(node=feature) - - self.connection.send(iq) - raise common.xmpp.NodeProcessed - - def _DiscoverItemsErrorCB(self, con, iq_obj): - gajim.log.debug('DiscoverItemsErrorCB') - jid = helpers.get_full_jid_from_iq(iq_obj) - self.dispatch('AGENT_ERROR_ITEMS', (jid)) - - def _DiscoverItemsCB(self, con, iq_obj): - gajim.log.debug('DiscoverItemsCB') - q = iq_obj.getTag('query') - node = q.getAttr('node') - if not node: - node = '' - qp = iq_obj.getQueryPayload() - items = [] - if not qp: - qp = [] - for i in qp: - # CDATA payload is not processed, only nodes - if not isinstance(i, common.xmpp.simplexml.Node): - continue - attr = {} - for key in i.getAttrs(): - attr[key] = i.getAttrs()[key] - items.append(attr) - jid = helpers.get_full_jid_from_iq(iq_obj) - hostname = gajim.config.get_per('accounts', self.name, - 'hostname') - id = iq_obj.getID() - if jid == hostname and id[0] == 'p': - for item in items: - self.discoverInfo(item['jid'], id_prefix='p') - else: - self.dispatch('AGENT_INFO_ITEMS', (jid, node, items)) - - def _DiscoverInfoGetCB(self, con, iq_obj): - gajim.log.debug('DiscoverInfoGetCB') - iq = iq_obj.buildReply('result') - q = iq.getTag('query') - q.addChild('identity', attrs = {'type': 'pc', - 'category': 'client', - 'name': 'Gajim'}) - q.addChild('feature', attrs = {'var': common.xmpp.NS_BYTESTREAM}) - q.addChild('feature', attrs = {'var': common.xmpp.NS_SI}) - q.addChild('feature', attrs = {'var': common.xmpp.NS_FILE}) - q.addChild('feature', attrs = {'var': common.xmpp.NS_MUC}) - self.connection.send(iq) - raise common.xmpp.NodeProcessed - - def _DiscoverInfoErrorCB(self, con, iq_obj): - gajim.log.debug('DiscoverInfoErrorCB') - jid = helpers.get_full_jid_from_iq(iq_obj) - self.dispatch('AGENT_ERROR_INFO', (jid)) - - def _DiscoverInfoCB(self, con, iq_obj): - gajim.log.debug('DiscoverInfoCB') - # According to JEP-0030: - # For identity: category, type is mandatory, name is optional. - # For feature: var is mandatory - identities, features, data = [], [], [] - q = iq_obj.getTag('query') - node = q.getAttr('node') - if not node: - node = '' - qc = iq_obj.getQueryChildren() - if not qc: - qc = [] - for i in qc: - if i.getName() == 'identity': - attr = {} - for key in i.getAttrs().keys(): - attr[key] = i.getAttr(key) - identities.append(attr) - elif i.getName() == 'feature': - features.append(i.getAttr('var')) - elif i.getName() == 'x' and i.getAttr('xmlns') == common.xmpp.NS_DATA: - data.append(common.xmpp.DataForm(node=i)) - jid = helpers.get_full_jid_from_iq(iq_obj) - id = iq_obj.getID() - if not identities: # ejabberd doesn't send identities when we browse online users - #FIXME: see http://www.jabber.ru/bugzilla/show_bug.cgi?id=225 - identities = [{'category': 'server', 'type': 'im', 'name': node}] - if id[0] == 'p': - if features.__contains__(common.xmpp.NS_BYTESTREAM): - gajim.proxy65_manager.resolve(jid, self.connection, self.name) - self.dispatch('AGENT_INFO_INFO', (jid, node, identities, - features, data)) - class ConnectionVcard: def __init__(self): self.vcard_sha = None @@ -754,23 +58,30 @@ class ConnectionVcard: self.room_jids = [] # list of gc jids so that vcard are saved in a folder def add_sha(self, p, send_caps = True): + ''' c = p.setTag('x', namespace = common.xmpp.NS_VCARD_UPDATE) if self.vcard_sha is not None: c.setTagData('photo', self.vcard_sha) if send_caps: return self.add_caps(p) return p + ''' + pass def add_caps(self, p): - ''' advertise our capabilities in presence stanza (jep-0115)''' + ''' + # advertise our capabilities in presence stanza (jep-0115) c = p.setTag('c', namespace = common.xmpp.NS_CAPS) c.setAttr('node', 'http://gajim.org/caps') c.setAttr('ext', 'ftrans') c.setAttr('ver', gajim.version) return p + ''' + pass def node_to_dict(self, node): dict = {} + ''' for info in node.getChildren(): name = info.getName() if name in ('ADR', 'TEL', 'EMAIL'): # we can have several @@ -786,6 +97,7 @@ class ConnectionVcard: dict[name] = {} for c in info.getChildren(): dict[name][c.getName()] = c.getData() + ''' return dict def save_vcard_to_hd(self, full_jid, card): @@ -844,6 +156,7 @@ class ConnectionVcard: to a fake jid, like in private messages in groupchat''' if not self.connection: return + ''' iq = common.xmpp.Iq(typ = 'get') if jid: iq.setTo(jid) @@ -858,10 +171,13 @@ class ConnectionVcard: self.room_jids.append(room_jid) self.connection.send(iq) #('VCARD', {entry1: data, entry2: {entry21: data, ...}, ...}) - + ''' + pass + def send_vcard(self, vcard): if not self.connection: return + ''' iq = common.xmpp.Iq(typ = 'set') iq2 = iq.setTag(common.xmpp.NS_VCARD + ' vCard') for i in vcard: @@ -894,156 +210,12 @@ class ConnectionVcard: iq2.getTag('PHOTO').setTagData('SHA', avatar_sha) self.awaiting_answers[id] = (VCARD_PUBLISHED, iq2) - - def _IqCB(self, con, iq_obj): - id = iq_obj.getID() - - # Check if we were waiting a timeout for this id - found_tim = None - for tim in self.awaiting_timeouts: - if id == self.awaiting_timeouts[tim][0]: - found_tim = tim - break - if found_tim: - del self.awaiting_timeouts[found_tim] - - if id not in self.awaiting_answers: - return - if self.awaiting_answers[id][0] == VCARD_PUBLISHED: - if iq_obj.getType() == 'result': - vcard_iq = self.awaiting_answers[id][1] - # Save vcard to HD - if vcard_iq.getTag('PHOTO') and vcard_iq.getTag('PHOTO').getTag('SHA'): - new_sha = vcard_iq.getTag('PHOTO').getTagData('SHA') - else: - new_sha = '' - - # Save it to file - our_jid = gajim.get_jid_from_account(self.name) - self.save_vcard_to_hd(our_jid, vcard_iq) - - # Send new presence if sha changed and we are not invisible - if self.vcard_sha != new_sha and STATUS_LIST[self.connected] != \ - 'invisible': - self.vcard_sha = new_sha - sshow = helpers.get_xmpp_show(STATUS_LIST[self.connected]) - prio = unicode(gajim.config.get_per('accounts', self.name, - 'priority')) - p = common.xmpp.Presence(typ = None, priority = prio, - show = sshow, status = self.status) - p = self.add_sha(p) - self.connection.send(p) - self.dispatch('VCARD_PUBLISHED', ()) - elif iq_obj.getType() == 'error': - self.dispatch('VCARD_NOT_PUBLISHED', ()) - elif self.awaiting_answers[id][0] == VCARD_ARRIVED: - # If vcard is empty, we send to the interface an empty vcard so that - # it knows it arrived - if not iq_obj.getTag('vCard'): - jid = self.awaiting_answers[id][1] - our_jid = gajim.get_jid_from_account(self.name) - if jid and jid != our_jid: - # Write an empty file - self.save_vcard_to_hd(jid, '') - self.dispatch('VCARD', {'jid': jid}) - elif jid == our_jid: - self.dispatch('MYVCARD', {'jid': jid}) - elif self.awaiting_answers[id][0] == AGENT_REMOVED: - jid = self.awaiting_answers[id][1] - self.dispatch('AGENT_REMOVED', jid) - del self.awaiting_answers[id] - - def _vCardCB(self, con, vc): - '''Called when we receive a vCard - Parse the vCard and send it to plugins''' - if not vc.getTag('vCard'): - return - frm_iq = vc.getFrom() - our_jid = gajim.get_jid_from_account(self.name) - resource = '' - if frm_iq: - who = helpers.get_full_jid_from_iq(vc) - frm, resource = gajim.get_room_and_nick_from_fjid(who) - else: - who = frm = our_jid - if vc.getTag('vCard').getNamespace() == common.xmpp.NS_VCARD: - card = vc.getChildren()[0] - vcard = self.node_to_dict(card) - photo_decoded = None - if vcard.has_key('PHOTO') and isinstance(vcard['PHOTO'], dict) and \ - vcard['PHOTO'].has_key('BINVAL'): - photo = vcard['PHOTO']['BINVAL'] - try: - photo_decoded = base64.decodestring(photo) - avatar_sha = sha.sha(photo_decoded).hexdigest() - except: - avatar_sha = '' - else: - avatar_sha = '' - - if avatar_sha: - card.getTag('PHOTO').setTagData('SHA', avatar_sha) - - # Save it to file - self.save_vcard_to_hd(who, card) - # Save the decoded avatar to a separate file too, and generate files for dbus notifications - puny_jid = helpers.sanitize_filename(frm) - puny_nick = None - begin_path = os.path.join(gajim.AVATAR_PATH, puny_jid) - if frm in self.room_jids: - puny_nick = helpers.sanitize_filename(resource) - # create folder if needed - if not os.path.isdir(begin_path): - os.mkdir(begin_path, 0700) - begin_path = os.path.join(begin_path, puny_nick) - if photo_decoded: - avatar_file = begin_path + '_notif_size_colored.png' - if frm == our_jid and avatar_sha != self.vcard_sha: - gajim.interface.save_avatar_files(frm, photo_decoded, puny_nick) - elif frm != our_jid and (not os.path.exists(avatar_file) or \ - not self.vcard_shas.has_key(frm) or \ - avatar_sha != self.vcard_shas[frm]): - gajim.interface.save_avatar_files(frm, photo_decoded, puny_nick) - else: - for ext in ('.jpeg', '.png', '_notif_size_bw.png', - '_notif_size_colored.png'): - path = begin_path + ext - if os.path.isfile(path): - os.remove(path) - - if frm != our_jid: - if avatar_sha: - self.vcard_shas[frm] = avatar_sha - elif self.vcard_shas.has_key(frm): - del self.vcard_shas[frm] - - vcard['jid'] = frm - vcard['resource'] = resource - if frm == our_jid: - self.dispatch('MYVCARD', vcard) - # we re-send our presence with sha if has changed and if we are - # not invisible - if self.vcard_sha == avatar_sha: - return - self.vcard_sha = avatar_sha - if STATUS_LIST[self.connected] == 'invisible': - return - sshow = helpers.get_xmpp_show(STATUS_LIST[self.connected]) - prio = unicode(gajim.config.get_per('accounts', self.name, - 'priority')) - p = common.xmpp.Presence(typ = None, priority = prio, show = sshow, - status = self.status) - p = self.add_sha(p) - self.connection.send(p) - else: - self.dispatch('VCARD', vcard) - - -# TODO: remove bytestream and disco, vcard maybe later used? -class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco): + ''' + pass + +class ConnectionHandlersZeroconf(ConnectionVcard): def __init__(self): ConnectionVcard.__init__(self) - ConnectionBytestream.__init__(self) # List of IDs we are waiting answers for {id: (type_of_request, data), } self.awaiting_answers = {} # List of IDs that will produce a timeout is answer doesn't arrive @@ -1065,466 +237,6 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco) iq.setError('not-authorized', 401) self.connection.send(iq) - def _HttpAuthCB(self, con, iq_obj): - gajim.log.debug('HttpAuthCB') - opt = gajim.config.get_per('accounts', self.name, 'http_auth') - if opt in ('yes', 'no'): - self.build_http_auth_answer(iq_obj, opt) - else: - id = iq_obj.getTagAttr('confirm', 'id') - method = iq_obj.getTagAttr('confirm', 'method') - url = iq_obj.getTagAttr('confirm', 'url') - self.dispatch('HTTP_AUTH', (method, url, id, iq_obj)); - raise common.xmpp.NodeProcessed - - def _ErrorCB(self, con, iq_obj): - errmsg = iq_obj.getError() - errcode = iq_obj.getErrorCode() - jid_from = helpers.get_full_jid_from_iq(iq_obj) - id = unicode(iq_obj.getID()) - self.dispatch('ERROR_ANSWER', (id, jid_from, errmsg, errcode)) - - def _PrivateCB(self, con, iq_obj): - ''' - Private Data (JEP 048 and 049) - ''' - gajim.log.debug('PrivateCB') - query = iq_obj.getTag('query') - storage = query.getTag('storage') - if storage: - ns = storage.getNamespace() - if ns == 'storage:bookmarks': - # Bookmarked URLs and Conferences - # http://www.jabber.org/jeps/jep-0048.html - confs = storage.getTags('conference') - for conf in confs: - autojoin_val = conf.getAttr('autojoin') - if autojoin_val is None: # not there (it's optional) - autojoin_val = False - print_status = conf.getTagData('print_status') - if not print_status: - print_status = conf.getTagData('show_status') - bm = {'name': conf.getAttr('name'), - 'jid': conf.getAttr('jid'), - 'autojoin': autojoin_val, - 'password': conf.getTagData('password'), - 'nick': conf.getTagData('nick'), - 'print_status': print_status} - - self.bookmarks.append(bm) - self.dispatch('BOOKMARKS', self.bookmarks) - - elif ns == 'storage:metacontacts': - # Metacontact tags - # http://www.jabber.org/jeps/jep-XXXX.html - meta_list = {} - metas = storage.getTags('meta') - for meta in metas: - jid = meta.getAttr('jid') - tag = meta.getAttr('tag') - data = {'jid': jid} - order = meta.getAttr('order') - if order != None: - data['order'] = order - if meta_list.has_key(tag): - meta_list[tag].append(data) - else: - meta_list[tag] = [data] - self.dispatch('METACONTACTS', meta_list) - # We can now continue connection by requesting the roster - self.connection.initRoster() - - elif ns == 'gajim:prefs': - # Preferences data - # http://www.jabber.org/jeps/jep-0049.html - #TODO: implement this - pass - - def _PrivateErrorCB(self, con, iq_obj): - gajim.log.debug('PrivateErrorCB') - query = iq_obj.getTag('query') - storage_tag = query.getTag('storage') - if storage_tag: - ns = storage_tag.getNamespace() - if ns == 'storage:metacontacts': - # Private XML Storage (JEP49) is not supported by server - # Continue connecting - self.connection.initRoster() - - def _rosterSetCB(self, con, iq_obj): - gajim.log.debug('rosterSetCB') - for item in iq_obj.getTag('query').getChildren(): - jid = helpers.parse_jid(item.getAttr('jid')) - name = item.getAttr('name') - sub = item.getAttr('subscription') - ask = item.getAttr('ask') - groups = [] - for group in item.getTags('group'): - groups.append(group.getData()) - self.dispatch('ROSTER_INFO', (jid, name, sub, ask, groups)) - raise common.xmpp.NodeProcessed - - def _VersionCB(self, con, iq_obj): - gajim.log.debug('VersionCB') - iq_obj = iq_obj.buildReply('result') - qp = iq_obj.getTag('query') - qp.setTagData('name', 'Gajim') - qp.setTagData('version', gajim.version) - send_os = gajim.config.get('send_os_info') - if send_os: - qp.setTagData('os', helpers.get_os_info()) - self.connection.send(iq_obj) - raise common.xmpp.NodeProcessed - - def _LastCB(self, con, iq_obj): - gajim.log.debug('IdleCB') - iq_obj = iq_obj.buildReply('result') - qp = iq_obj.getTag('query') - if not HAS_IDLE: - qp.attrs['seconds'] = '0'; - else: - qp.attrs['seconds'] = idle.getIdleSec() - - self.connection.send(iq_obj) - raise common.xmpp.NodeProcessed - - def _LastResultCB(self, con, iq_obj): - gajim.log.debug('LastResultCB') - qp = iq_obj.getTag('query') - seconds = qp.getAttr('seconds') - status = qp.getData() - try: - seconds = int(seconds) - except: - return - who = helpers.get_full_jid_from_iq(iq_obj) - jid_stripped, resource = gajim.get_room_and_nick_from_fjid(who) - self.dispatch('LAST_STATUS_TIME', (jid_stripped, resource, seconds, status)) - - def _VersionResultCB(self, con, iq_obj): - gajim.log.debug('VersionResultCB') - client_info = '' - os_info = '' - qp = iq_obj.getTag('query') - if qp.getTag('name'): - client_info += qp.getTag('name').getData() - if qp.getTag('version'): - client_info += ' ' + qp.getTag('version').getData() - if qp.getTag('os'): - os_info += qp.getTag('os').getData() - who = helpers.get_full_jid_from_iq(iq_obj) - jid_stripped, resource = gajim.get_room_and_nick_from_fjid(who) - self.dispatch('OS_INFO', (jid_stripped, resource, client_info, os_info)) - - - def _gMailNewMailCB(self, con, gm): - '''Called when we get notified of new mail messages in gmail account''' - if not gm.getTag('new-mail'): - return - if gm.getTag('new-mail').getNamespace() == common.xmpp.NS_GMAILNOTIFY: - # we'll now ask the server for the exact number of new messages - jid = gajim.get_jid_from_account(self.name) - gajim.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.setAttr('id', '13') - query = iq.setTag('query') - query.setNamespace(common.xmpp.NS_GMAILNOTIFY) - self.connection.send(iq) - raise common.xmpp.NodeProcessed - - def _gMailQueryCB(self, con, gm): - '''Called when we receive results from Querying the server for mail messages in gmail account''' - if not gm.getTag('mailbox'): - return - if gm.getTag('mailbox').getNamespace() == common.xmpp.NS_GMAILNOTIFY: - newmsgs = gm.getTag('mailbox').getAttr('total-matched') - if newmsgs != '0': - # there are new messages - jid = gajim.get_jid_from_account(self.name) - gajim.log.debug(('You have %s new gmail e-mails on %s.') % (newmsgs, jid)) - self.dispatch('GMAIL_NOTIFY', (jid, newmsgs)) - raise common.xmpp.NodeProcessed - - def _messageCB(self, con, msg): - '''Called when we receive a message''' - msgtxt = msg.getBody() - mtype = msg.getType() - subject = msg.getSubject() # if not there, it's None - tim = msg.getTimestamp() - tim = time.strptime(tim, '%Y%m%dT%H:%M:%S') - tim = time.localtime(timegm(tim)) - frm = helpers.get_full_jid_from_iq(msg) - jid = helpers.get_jid_from_iq(msg) - no_log_for = gajim.config.get_per('accounts', self.name, - 'no_log_for').split() - encrypted = False - chatstate = None - encTag = msg.getTag('x', namespace = common.xmpp.NS_ENCRYPTED) - decmsg = '' - # invitations - invite = None - if not encTag: - invite = msg.getTag('x', namespace = common.xmpp.NS_MUC_USER) - if invite and not invite.getTag('invite'): - invite = None - delayed = msg.getTag('x', namespace = common.xmpp.NS_DELAY) != None - msg_id = None - composing_jep = None - # FIXME: Msn transport (CMSN1.2.1 and PyMSN0.10) do NOT RECOMMENDED - # invitation - # stanza (MUC JEP) remove in 2007, as we do not do NOT RECOMMENDED - xtags = msg.getTags('x') - for xtag in xtags: - if xtag.getNamespace() == common.xmpp.NS_CONFERENCE and not invite: - room_jid = xtag.getAttr('jid') - self.dispatch('GC_INVITATION', (room_jid, frm, '', None)) - return - # chatstates - look for chatstate tags in a message if not delayed - if not delayed: - composing_jep = False - children = msg.getChildren() - for child in children: - if child.getNamespace() == 'http://jabber.org/protocol/chatstates': - chatstate = child.getName() - composing_jep = 'JEP-0085' - break - # No JEP-0085 support, fallback to JEP-0022 - if not chatstate: - chatstate_child = msg.getTag('x', namespace = common.xmpp.NS_EVENT) - if chatstate_child: - chatstate = 'active' - composing_jep = 'JEP-0022' - if not msgtxt and chatstate_child.getTag('composing'): - chatstate = 'composing' - - if encTag and GnuPG.USE_GPG: - #decrypt - encmsg = encTag.getData() - - keyID = gajim.config.get_per('accounts', self.name, 'keyid') - if keyID: - decmsg = self.gpg.decrypt(encmsg, keyID) - if decmsg: - msgtxt = decmsg - encrypted = True - if mtype == 'error': - error_msg = msg.getError() - if not error_msg: - error_msg = msgtxt - msgtxt = None - if self.name not in no_log_for: - gajim.logger.write('error', frm, error_msg, tim = tim, - subject = subject) - self.dispatch('MSGERROR', (frm, msg.getErrorCode(), error_msg, msgtxt, - tim)) - elif mtype == 'groupchat': - if subject: - self.dispatch('GC_SUBJECT', (frm, subject, msgtxt)) - else: - if not msg.getTag('body'): #no <body> - return - # Ignore message from room in which we are not - if not self.last_history_line.has_key(jid): - return - self.dispatch('GC_MSG', (frm, msgtxt, tim)) - if self.name not in no_log_for and jid in self.last_history_line \ - and not int(float(time.mktime(tim))) <= \ - self.last_history_line[jid] and msgtxt: - gajim.logger.write('gc_msg', frm, msgtxt, tim = tim) - elif mtype == 'chat': # it's type 'chat' - if not msg.getTag('body') and chatstate is None: #no <body> - return - if msg.getTag('body') and self.name not in no_log_for and jid not in\ - no_log_for and msgtxt: - msg_id = gajim.logger.write('chat_msg_recv', frm, msgtxt, tim = tim, - subject = subject) - self.dispatch('MSG', (frm, msgtxt, tim, encrypted, mtype, subject, - chatstate, msg_id, composing_jep)) - else: # it's single message - if self.name not in no_log_for and jid not in no_log_for and msgtxt: - gajim.logger.write('single_msg_recv', frm, msgtxt, tim = tim, - subject = subject) - if invite is not None: - item = invite.getTag('invite') - jid_from = item.getAttr('from') - reason = item.getTagData('reason') - item = invite.getTag('password') - password = invite.getTagData('password') - self.dispatch('GC_INVITATION',(frm, jid_from, reason, password)) - else: - self.dispatch('MSG', (frm, msgtxt, tim, encrypted, 'normal', - subject, chatstate, msg_id, composing_jep)) - # END messageCB - - def _presenceCB(self, con, prs): - '''Called when we receive a presence''' - ptype = prs.getType() - if ptype == 'available': - ptype = None - gajim.log.debug('PresenceCB: %s' % ptype) - who = helpers.get_full_jid_from_iq(prs) - jid_stripped, resource = gajim.get_room_and_nick_from_fjid(who) - timestamp = None - is_gc = False # is it a GC presence ? - sigTag = None - avatar_sha = None - transport_auto_auth = False - xtags = prs.getTags('x') - for x in xtags: - if x.getNamespace().startswith(common.xmpp.NS_MUC): - is_gc = True - if x.getNamespace() == common.xmpp.NS_SIGNED: - sigTag = x - if x.getNamespace() == common.xmpp.NS_VCARD_UPDATE: - avatar_sha = x.getTagData('photo') - if x.getNamespace() == common.xmpp.NS_DELAY: - # JEP-0091 - tim = prs.getTimestamp() - tim = time.strptime(tim, '%Y%m%dT%H:%M:%S') - timestamp = time.localtime(timegm(tim)) - if x.getNamespace() == 'http://delx.cjb.net/protocol/roster-subsync': - # see http://trac.gajim.org/ticket/326 - agent = gajim.get_server_from_jid(jid_stripped) - if self.connection.getRoster().getItem(agent): # to be sure it's a transport contact - transport_auto_auth = True - - no_log_for = gajim.config.get_per('accounts', self.name, - 'no_log_for').split() - status = prs.getStatus() - show = prs.getShow() - if not show in STATUS_LIST: - show = '' # We ignore unknown show - if not ptype and not show: - show = 'online' - elif ptype == 'unavailable': - show = 'offline' - - prio = prs.getPriority() - try: - prio = int(prio) - except: - prio = 0 - keyID = '' - if sigTag and GnuPG.USE_GPG: - #verify - sigmsg = sigTag.getData() - keyID = self.gpg.verify(status, sigmsg) - - if is_gc: - if ptype == 'error': - errmsg = prs.getError() - errcode = prs.getErrorCode() - if errcode == '502': # Internal Timeout: - self.dispatch('NOTIFY', (jid_stripped, 'error', errmsg, resource, - prio, keyID, timestamp)) - elif errcode == '401': # password required to join - self.dispatch('ERROR', (_('Unable to join room'), - _('A password is required to join this room.'))) - elif errcode == '403': # we are banned - self.dispatch('ERROR', (_('Unable to join room'), - _('You are banned from this room.'))) - elif errcode == '404': # room does not exist - self.dispatch('ERROR', (_('Unable to join room'), - _('Such room does not exist.'))) - elif errcode == '405': - self.dispatch('ERROR', (_('Unable to join room'), - _('Room creation is restricted.'))) - elif errcode == '406': - self.dispatch('ERROR', (_('Unable to join room'), - _('Your registered nickname must be used.'))) - elif errcode == '407': - self.dispatch('ERROR', (_('Unable to join room'), - _('You are not in the members list.'))) - elif errcode == '409': # nick conflict - # the jid_from in this case is FAKE JID: room_jid/nick - # resource holds the bad nick so propose a new one - proposed_nickname = resource + \ - gajim.config.get('gc_proposed_nick_char') - room_jid = gajim.get_room_from_fjid(who) - self.dispatch('ASK_NEW_NICK', (room_jid, _('Unable to join room'), - _('Your desired nickname is in use or registered by another occupant.\nPlease specify another nickname below:'), proposed_nickname)) - else: # print in the window the error - self.dispatch('ERROR_ANSWER', ('', jid_stripped, - errmsg, errcode)) - if not ptype or ptype == 'unavailable': - if gajim.config.get('log_contact_status_changes') and self.name\ - not in no_log_for and jid_stripped not in no_log_for: - gajim.logger.write('gcstatus', who, status, show) - if avatar_sha: - if self.vcard_shas.has_key(who): - if avatar_sha != self.vcard_shas[who]: - # avatar has been updated - self.request_vcard(who, True) - else: - self.vcard_shas[who] = avatar_sha - self.dispatch('GC_NOTIFY', (jid_stripped, show, status, resource, - prs.getRole(), prs.getAffiliation(), prs.getJid(), - prs.getReason(), prs.getActor(), prs.getStatusCode(), - prs.getNewNick())) - return - - if ptype == 'subscribe': - gajim.log.debug('subscribe request from %s' % who) - if gajim.config.get('alwaysauth') or who.find("@") <= 0 or \ - jid_stripped in self.jids_for_auto_auth or transport_auto_auth: - if self.connection: - p = common.xmpp.Presence(who, 'subscribed') - p = self.add_sha(p) - self.connection.send(p) - if who.find("@") <= 0 or transport_auto_auth: - self.dispatch('NOTIFY', (jid_stripped, 'offline', 'offline', - resource, prio, keyID, timestamp)) - if transport_auto_auth: - self.automatically_added.append(jid_stripped) - self.request_subscription(jid_stripped) - else: - if not status: - status = _('I would like to add you to my roster.') - self.dispatch('SUBSCRIBE', (who, status)) - elif ptype == 'subscribed': - if jid_stripped in self.automatically_added: - self.automatically_added.remove(jid_stripped) - else: - self.dispatch('SUBSCRIBED', (jid_stripped, resource)) - # BE CAREFUL: no con.updateRosterItem() in a callback - gajim.log.debug(_('we are now subscribed to %s') % who) - elif ptype == 'unsubscribe': - gajim.log.debug(_('unsubscribe request from %s') % who) - elif ptype == 'unsubscribed': - gajim.log.debug(_('we are now unsubscribed from %s') % who) - self.dispatch('UNSUBSCRIBED', jid_stripped) - elif ptype == 'error': - errmsg = prs.getError() - errcode = prs.getErrorCode() - if errcode == '502': # Internal Timeout: - self.dispatch('NOTIFY', (jid_stripped, 'error', errmsg, resource, - prio, keyID, timestamp)) - else: # print in the window the error - self.dispatch('ERROR_ANSWER', ('', jid_stripped, - errmsg, errcode)) - - if avatar_sha and ptype != 'error': - if not self.vcard_shas.has_key(jid_stripped): - cached_vcard = self.get_cached_vcard(jid_stripped) - if cached_vcard and cached_vcard.has_key('PHOTO') and \ - cached_vcard['PHOTO'].has_key('SHA'): - self.vcard_shas[jid_stripped] = cached_vcard['PHOTO']['SHA'] - else: - self.vcard_shas[jid_stripped] = '' - if avatar_sha != self.vcard_shas[jid_stripped]: - # avatar has been updated - self.request_vcard(jid_stripped) - if not ptype or ptype == 'unavailable': - if gajim.config.get('log_contact_status_changes') and self.name\ - not in no_log_for and jid_stripped not in no_log_for: - gajim.logger.write('status', jid_stripped, status, show) - self.dispatch('NOTIFY', (jid_stripped, show, status, resource, prio, - keyID, timestamp)) - # END presenceCB - def _StanzaArrivedCB(self, con, obj): - self.last_io = gajim.idlequeue.current_time() - - def parse_data_form(self, node): dic = {} tag = node.getTag('title') @@ -1583,63 +295,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco) i += 1 return dic - def _MucOwnerCB(self, con, iq_obj): - gajim.log.debug('MucOwnerCB') - qp = iq_obj.getQueryPayload() - node = None - for q in qp: - if q.getNamespace() == common.xmpp.NS_DATA: - node = q - if not node: - return - dic = self.parse_data_form(node) - self.dispatch('GC_CONFIG', (helpers.get_full_jid_from_iq(iq_obj), dic)) - - def _MucAdminCB(self, con, iq_obj): - gajim.log.debug('MucAdminCB') - items = iq_obj.getTag('query', namespace = common.xmpp.NS_MUC_ADMIN).getTags('item') - list = {} - affiliation = '' - for item in items: - if item.has_attr('jid') and item.has_attr('affiliation'): - jid = item.getAttr('jid') - affiliation = item.getAttr('affiliation') - list[jid] = {'affiliation': affiliation} - if item.has_attr('nick'): - list[jid]['nick'] = item.getAttr('nick') - if item.has_attr('role'): - list[jid]['role'] = item.getAttr('role') - reason = item.getTagData('reason') - if reason: - list[jid]['reason'] = reason - - self.dispatch('GC_AFFILIATION', (helpers.get_full_jid_from_iq(iq_obj), - affiliation, list)) - def _MucErrorCB(self, con, iq_obj): - gajim.log.debug('MucErrorCB') - jid = helpers.get_full_jid_from_iq(iq_obj) - errmsg = iq_obj.getError() - errcode = iq_obj.getErrorCode() - self.dispatch('MSGERROR', (jid, errcode, errmsg)) - - def _getRosterCB(self, con, iq_obj): - if not self.connection: - return - self.connection.getRoster(self._on_roster_set) - if gajim.config.get_per('accounts', self.name, 'use_ft_proxies'): - self.discover_ft_proxies() - - def discover_ft_proxies(self): - cfg_proxies = gajim.config.get_per('accounts', self.name, - 'file_transfer_proxies') - if cfg_proxies: - proxies = map(lambda e:e.strip(), cfg_proxies.split(',')) - for proxy in proxies: - gajim.proxy65_manager.resolve(proxy, self.connection) - self.discoverItems(gajim.config.get_per('accounts', self.name, - 'hostname'), id_prefix='p') - def _on_roster_set(self, roster): raw_roster = roster.getRaw() roster = {} @@ -1651,131 +307,16 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco) print >> sys.stderr, _('JID %s is not RFC compliant. It will not be added to your roster. Use roster management tools such as http://jru.jabberstudio.org/ to remove it') % jid else: infos = raw_roster[jid] + if jid != our_jid and (not infos['subscription'] or infos['subscription'] == \ 'none') and (not infos['ask'] or infos['ask'] == 'none') and not infos['name'] \ and not infos['groups']: # remove this useless item, it won't be shown in roster anyway - self.connection.getRoster().delItem(jid) + #self.connection.getRoster().delItem(jid) + pass elif jid != our_jid: # don't add our jid roster[j] = raw_roster[jid] + self.dispatch('ROSTER', roster) - - # continue connection - if self.connected > 1 and self.continue_connect_info: - show = self.continue_connect_info[0] - msg = self.continue_connect_info[1] - signed = self.continue_connect_info[2] - self.connected = STATUS_LIST.index(show) - sshow = helpers.get_xmpp_show(show) - # send our presence - if show == 'invisible': - self.send_invisible_presence(msg, signed, True) - return - prio = unicode(gajim.config.get_per('accounts', self.name, - 'priority')) - vcard = self.get_cached_vcard(jid) - if vcard and vcard.has_key('PHOTO') and vcard['PHOTO'].has_key('SHA'): - self.vcard_sha = vcard['PHOTO']['SHA'] - p = common.xmpp.Presence(typ = None, priority = prio, show = sshow) - p = self.add_sha(p) - if msg: - p.setStatus(msg) - if signed: - p.setTag(common.xmpp.NS_SIGNED + ' x').setData(signed) - - if self.connection: - self.connection.send(p) - self.dispatch('STATUS', show) - # ask our VCard - self.request_vcard(None) - - # Get bookmarks from private namespace - self.get_bookmarks() - - # If it's a gmail account, - # inform the server that we want e-mail notifications - if gajim.get_server_from_jid(our_jid) == 'gmail.com': - gajim.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.setAttr('id', 'MailNotify') - query = iq.setTag('usersetting') - query.setNamespace(common.xmpp.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.setAttr('id', '13') - query = iq.setTag('query') - query.setNamespace(common.xmpp.NS_GMAILNOTIFY) - self.connection.send(iq) - - #Inform GUI we just signed in - self.dispatch('SIGNED_IN', ()) - self.continue_connect_info = None - - def _register_handlers(self, con, con_type): - # try to find another way to register handlers in each class - # that defines handlers - con.RegisterHandler('message', self._messageCB) - con.RegisterHandler('presence', self._presenceCB) - 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._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) - con.RegisterHandler('iq', self._bytestreamSetCB, 'set', - common.xmpp.NS_BYTESTREAM) - con.RegisterHandler('iq', self._bytestreamResultCB, 'result', - common.xmpp.NS_BYTESTREAM) - con.RegisterHandler('iq', self._bytestreamErrorCB, 'error', - common.xmpp.NS_BYTESTREAM) - con.RegisterHandler('iq', self._DiscoverItemsCB, 'result', - common.xmpp.NS_DISCO_ITEMS) - con.RegisterHandler('iq', self._DiscoverItemsErrorCB, 'error', - common.xmpp.NS_DISCO_ITEMS) - con.RegisterHandler('iq', self._DiscoverInfoCB, 'result', - common.xmpp.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._LastCB, 'get', - common.xmpp.NS_LAST) - con.RegisterHandler('iq', self._LastResultCB, 'result', - common.xmpp.NS_LAST) - con.RegisterHandler('iq', self._VersionResultCB, 'result', - common.xmpp.NS_VERSION) - con.RegisterHandler('iq', self._MucOwnerCB, 'result', - common.xmpp.NS_MUC_OWNER) - con.RegisterHandler('iq', self._MucAdminCB, 'result', - common.xmpp.NS_MUC_ADMIN) - con.RegisterHandler('iq', self._getRosterCB, 'result', - common.xmpp.NS_ROSTER) - con.RegisterHandler('iq', self._PrivateCB, 'result', - common.xmpp.NS_PRIVATE) - con.RegisterHandler('iq', self._PrivateErrorCB, 'error', - common.xmpp.NS_PRIVATE) - con.RegisterHandler('iq', self._HttpAuthCB, 'get', - common.xmpp.NS_HTTP_AUTH) - con.RegisterHandler('iq', self._gMailNewMailCB, 'set', - common.xmpp.NS_GMAILNOTIFY) - con.RegisterHandler('iq', self._gMailQueryCB, 'result', - common.xmpp.NS_GMAILNOTIFY) - con.RegisterHandler('iq', self._DiscoverInfoGetCB, 'get', - common.xmpp.NS_DISCO_INFO) - con.RegisterHandler('iq', self._ErrorCB, 'error') - con.RegisterHandler('iq', self._IqCB) - con.RegisterHandler('iq', self._StanzaArrivedCB) - con.RegisterHandler('iq', self._ResultCB, 'result') - con.RegisterHandler('presence', self._StanzaArrivedCB) - con.RegisterHandler('message', self._StanzaArrivedCB) +# self.dispatch('SIGNED_IN', ()) diff --git a/src/common/connection_zeroconf.py b/src/common/connection_zeroconf.py index 0d31f201f6..e5728793ce 100644 --- a/src/common/connection_zeroconf.py +++ b/src/common/connection_zeroconf.py @@ -34,12 +34,12 @@ import signal if os.name != 'nt': signal.signal(signal.SIGPIPE, signal.SIG_DFL) -# import common.xmpp from common import helpers from common import gajim from common import GnuPG from common import zeroconf from common import connection_handlers_zeroconf +from common import client_zeroconf from connection_handlers_zeroconf import * USE_GPG = GnuPG.USE_GPG @@ -55,10 +55,10 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf): self.zeroconf = zeroconf.Zeroconf() self.connected = 0 # offline self.connection = None # dummy connection variable - # this property is used to prevent double connections # self.last_connection = None # last ClientCommon instance self.gpg = None + self.is_zeroconf = True self.status = '' self.old_show = '' # increase/decrease default timeout for server responses @@ -119,8 +119,7 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf): gajim.log.debug('reconnect') - # TODO: no gpg for now, add some day - # signed = self.get_signed_msg(self.status) + signed = self.get_signed_msg(self.status) # We are doing disconnect at so many places, better use one function in all @@ -133,103 +132,6 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf): self.last_connection = None self.connection = None self.zeroconf.disconnect() - - ''' - def _disconnectedReconnCB(self): - # Called when we are disconnected - gajim.log.debug('disconnectedReconnCB') - if self.connected > 1: - # we cannot change our status to offline or connectiong - # after we auth to server - self.old_show = STATUS_LIST[self.connected] - self.connected = 0 - self.dispatch('STATUS', 'offline') - if not self.on_purpose: - self.disconnect() - if gajim.config.get_per('accounts', self.name, 'autoreconnect') \ - and self.retrycount <= 10: - self.connected = 1 - self.dispatch('STATUS', 'connecting') - self.time_to_reconnect = 10 - # this check has moved from _reconnect method - if self.retrycount > 5: - self.time_to_reconnect = 20 - else: - self.time_to_reconnect = 10 - gajim.idlequeue.set_alarm(self._reconnect_alarm, - self.time_to_reconnect) - elif self.on_connect_failure: - self.on_connect_failure() - self.on_connect_failure = None - else: - # show error dialog - self._connection_lost() - else: - self.disconnect() - self.on_purpose = False - # END disconenctedReconnCB - ''' - - ''' - def _connection_lost(self): - self.disconnect(on_purpose = False) - self.dispatch('STATUS', 'offline') - self.dispatch('ERROR', - (_('Connection with account "%s" has been lost') % self.name, - _('To continue sending and receiving messages, you will need to reconnect.'))) - ''' - ''' - def _event_dispatcher(self, realm, event, data): - if realm == common.xmpp.NS_REGISTER: - if event == common.xmpp.features_nb.REGISTER_DATA_RECEIVED: - # data is (agent, DataFrom, is_form) - if self.new_account_info and\ - self.new_account_info['hostname'] == data[0]: - #it's a new account - if not data[1]: # wrong answer - print self.connection.lastErr - self.dispatch('ACC_NOT_OK', ( - _('Transport %s answered wrongly to register request.') % \ - data[0])) - return - req = data[1].asDict() - req['username'] = self.new_account_info['name'] - req['password'] = self.new_account_info['password'] - def _on_register_result(result): - if not common.xmpp.isResultNode(result): - self.dispatch('ACC_NOT_OK', (result.getError())) - return - self.connected = 0 - self.password = self.new_account_info['password'] - if USE_GPG: - self.gpg = GnuPG.GnuPG() - gajim.config.set('usegpg', True) - else: - gajim.config.set('usegpg', False) - gajim.connections[self.name] = self - self.dispatch('ACC_OK', (self.new_account_info)) - self.new_account_info = None - self.connection = None - common.xmpp.features_nb.register(self.connection, data[0], - req, _on_register_result) - return - if not data[1]: # wrong answer - self.dispatch('ERROR', (_('Invalid answer'), - _('Transport %s answered wrongly to register request.') % \ - data[0])) - return - is_form = data[2] - if is_form: - conf = self.parse_data_form(data[1]) - else: - conf = data[1].asDict() - self.dispatch('REGISTER_AGENT_INFO', (data[0], conf, is_form)) - elif realm == '': - if event == common.xmpp.transports.DATA_RECEIVED: - self.dispatch('STANZA_ARRIVED', unicode(data, errors = 'ignore')) - elif event == common.xmpp.transports.DATA_SENT: - self.dispatch('STANZA_SENT', unicode(data)) - ''' def select_next_host(self, hosts): hosts_best_prio = [] @@ -254,279 +156,12 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf): min_w = h['weight'] return h - - def connect(self, data = None, show = 'online'): - - if self.connection: - return self.connection, '' - - self.zeroconf.connect() - self.connection = 1 - self.connected = STATUS_LIST.index(show) - - ''' Start a connection to the Jabber server. - Returns connection, and connection type ('tls', 'ssl', 'tcp', '') - data MUST contain name, hostname, resource, usessl, proxy, - use_custom_host, custom_host (if use_custom_host), custom_port (if - use_custom_host), ''' - - ''' - if self.connection: - return self.connection, '' - - if data: - name = data['name'] - hostname = data['hostname'] - resource = data['resource'] - usessl = data['usessl'] - self.try_connecting_for_foo_secs = 45 - p = data['proxy'] - use_srv = True - use_custom = data['use_custom_host'] - if use_custom: - custom_h = data['custom_host'] - custom_p = data['custom_port'] - else: - name = gajim.config.get_per('accounts', self.name, 'name') - hostname = gajim.config.get_per('accounts', self.name, 'hostname') - resource = gajim.config.get_per('accounts', self.name, 'resource') - usessl = gajim.config.get_per('accounts', self.name, 'usessl') - self.try_connecting_for_foo_secs = gajim.config.get_per('accounts', - self.name, 'try_connecting_for_foo_secs') - p = gajim.config.get_per('accounts', self.name, 'proxy') - use_srv = gajim.config.get_per('accounts', self.name, 'use_srv') - use_custom = gajim.config.get_per('accounts', self.name, - 'use_custom_host') - custom_h = gajim.config.get_per('accounts', self.name, 'custom_host') - custom_p = gajim.config.get_per('accounts', self.name, 'custom_port') - - #create connection if it doesn't already exist - self.connected = 1 - if p and p in gajim.config.get_per('proxies'): - proxy = {'host': gajim.config.get_per('proxies', p, 'host')} - proxy['port'] = gajim.config.get_per('proxies', p, 'port') - proxy['user'] = gajim.config.get_per('proxies', p, 'user') - proxy['password'] = gajim.config.get_per('proxies', p, 'pass') - else: - proxy = None - - h = hostname - p = 5222 - # autodetect [for SSL in 5223/443 and for TLS if broadcasted] - secur = None - if usessl: - p = 5223 - secur = 1 # 1 means force SSL no matter what the port will be - use_srv = False # wants ssl? disable srv lookup - if use_custom: - h = custom_h - p = custom_p - use_srv = False - - hosts = [] - # SRV resolver - self._proxy = proxy - self._secure = secur - self._hosts = [ {'host': h, 'port': p, 'prio': 10, 'weight': 10} ] - self._hostname = hostname - if use_srv: - # add request for srv query to the resolve, on result '_on_resolve' will be called - gajim.resolver.resolve('_xmpp-client._tcp.' + h.encode('utf-8'), self._on_resolve) - else: - self._on_resolve('', []) - ''' - ''' - def _on_resolve(self, host, result_array): - # SRV query returned at least one valid result, we put it in hosts dict - if len(result_array) != 0: - self._hosts = [i for i in result_array] - self.connect_to_next_host() - ''' - ''' - def connect_to_next_host(self, retry = False): - - if len(self._hosts): - if self.last_connection: - self.last_connection.socket.disconnect() - self.last_connection = None - self.connection = None - if gajim.verbose: - con = common.xmpp.NonBlockingClient(self._hostname, caller = self, - on_connect = self.on_connect_success, - on_connect_failure = self.connect_to_next_host) - else: - con = common.xmpp.NonBlockingClient(self._hostname, debug = [], caller = self, - on_connect = self.on_connect_success, - on_connect_failure = self.connect_to_next_host) - self.last_connection = con - # increase default timeout for server responses - common.xmpp.dispatcher_nb.DEFAULT_TIMEOUT_SECONDS = self.try_connecting_for_foo_secs - con.set_idlequeue(gajim.idlequeue) - host = self.select_next_host(self._hosts) - self._current_host = host - self._hosts.remove(host) - con.connect((host['host'], host['port']), proxy = self._proxy, - secure = self._secure) - return - else: - if not retry or self.retrycount > 10: - self.retrycount = 0 - self.time_to_reconnect = None - if self.on_connect_failure: - self.on_connect_failure() - self.on_connect_failure = None - else: - # shown error dialog - self._connection_lost() - else: - # try reconnect if connection has failed before auth to server - self._disconnectedReconnCB() - ''' - ''' - def _connect_failure(self, con_type = None): - if not con_type: - # we are not retrying, and not conecting - if not self.retrycount and self.connected != 0: - self.disconnect(on_purpose = True) - self.dispatch('STATUS', 'offline') - self.dispatch('ERROR', (_('Could not connect to "%s"') % self._hostname, - _('Check your connection or try again later.'))) - ''' - ''' - def _connect_success(self, con, con_type): - if not self.connected: # We went offline during connecting process - # FIXME - not possible, maybe it was when we used threads - return - self.hosts = [] - if not con_type: - gajim.log.debug('Could not connect to %s:%s' % (self._current_host['host'], - self._current_host['port'])) - self.connected_hostname = self._current_host['host'] - self.on_connect_failure = None - con.RegisterDisconnectHandler(self._disconnectedReconnCB) - gajim.log.debug(_('Connected to server %s:%s with %s') % (self._current_host['host'], - self._current_host['port'], con_type)) - # Ask metacontacts before roster - self.get_metacontacts() - self._register_handlers(con, con_type) - return True - ''' - ''' - def _register_handlers(self, con, con_type): - self.peerhost = con.get_peerhost() - # notify the gui about con_type - self.dispatch('CON_TYPE', con_type) - ConnectionHandlers._register_handlers(self, con, con_type) - name = gajim.config.get_per('accounts', self.name, 'name') - hostname = gajim.config.get_per('accounts', self.name, 'hostname') - resource = gajim.config.get_per('accounts', self.name, 'resource') - self.connection = con - con.auth(name, self.password, resource, 1, self.__on_auth) - ''' - ''' - def __on_auth(self, con, auth): - if not con: - self.disconnect(on_purpose = True) - self.dispatch('STATUS', 'offline') - self.dispatch('ERROR', (_('Could not connect to "%s"') % self._hostname, - _('Check your connection or try again later'))) - if self.on_connect_auth: - self.on_connect_auth(None) - self.on_connect_auth = None - return - if not self.connected: # We went offline during connecting process - if self.on_connect_auth: - self.on_connect_auth(None) - self.on_connect_auth = None - return - if hasattr(con, 'Resource'): - self.server_resource = con.Resource - if auth: - self.last_io = gajim.idlequeue.current_time() - self.connected = 2 - if self.on_connect_auth: - self.on_connect_auth(con) - self.on_connect_auth = None - else: - # Forget password if needed - if not gajim.config.get_per('accounts', self.name, 'savepass'): - self.password = None - gajim.log.debug("Couldn't authenticate to %s" % self._hostname) - self.disconnect(on_purpose = True) - self.dispatch('STATUS', 'offline') - self.dispatch('ERROR', (_('Authentication failed with "%s"') % self._hostname, - _('Please check your login and password for correctness.'))) - if self.on_connect_auth: - self.on_connect_auth(None) - self.on_connect_auth = None - # END connect - ''' - def quit(self, kill_core): if kill_core and self.connected > 1: self.disconnect(on_purpose = True) - ''' - #invisible == no service announced( privacy rule? ) - def build_privacy_rule(self, name, action): - #Build a Privacy rule stanza for invisibility - iq = common.xmpp.Iq('set', common.xmpp.NS_PRIVACY, xmlns = '') - l = iq.getTag('query').setTag('list', {'name': name}) - i = l.setTag('item', {'action': action, 'order': '1'}) - i.setTag('presence-out') - return iq - ''' - - ''' - def activate_privacy_rule(self, name): - activate a privacy rule - iq = common.xmpp.Iq('set', common.xmpp.NS_PRIVACY, xmlns = '') - iq.getTag('query').setTag('active', {'name': name}) - self.connection.send(iq) - ''' - ''' - def send_invisible_presence(self, msg, signed, initial = False): - # try to set the privacy rule - iq = self.build_privacy_rule('invisible', 'deny') - self.connection.SendAndCallForResponse(iq, self._continue_invisible, - {'msg': msg, 'signed': signed, 'initial': initial}) - ''' - ''' - def _continue_invisible(self, con, iq_obj, msg, signed, initial): - ptype = '' - show = '' - # FIXME: JEP 126 need some modifications (see http://lists.jabber.ru/pipermail/ejabberd/2005-July/001252.html). So I disable it for the moment - if 1 or iq_obj.getType() == 'error': #server doesn't support privacy lists - # We use the old way which is not xmpp complient - ptype = 'invisible' - show = 'invisible' - else: - # active the privacy rule - self.privacy_rules_supported = True - self.activate_privacy_rule('invisible') - prio = unicode(gajim.config.get_per('accounts', self.name, 'priority')) - p = common.xmpp.Presence(typ = ptype, priority = prio, show = show) - p = self.add_sha(p, ptype != 'unavailable') - if msg: - p.setStatus(msg) - if signed: - p.setTag(common.xmpp.NS_SIGNED + ' x').setData(signed) - self.connection.send(p) - self.dispatch('STATUS', 'invisible') - if initial: - #ask our VCard - self.request_vcard(None) - - #Get bookmarks from private namespace - self.get_bookmarks() - - #Inform GUI we just signed in - self.dispatch('SIGNED_IN', ()) - ''' - - def test_gpg_passphrase(self, password): self.gpg.passphrase = password keyID = gajim.config.get_per('accounts', self.name, 'keyid') @@ -553,45 +188,27 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf): self.dispatch('BAD_PASSPHRASE', ()) return signed - - def connect_and_auth(self): - ''' - self.on_connect_success = self._connect_success - self.on_connect_failure = self._connect_failure - self.connect() - ''' - - pass + def connect(self, data = None, show = 'online'): + if self.connection: + return self.connection, '' + self.zeroconf.connect() + self.connection = client_zeroconf.ClientZeroconf(self.zeroconf) + self.connected = STATUS_LIST.index(show) + def connect_and_init(self, show, msg, signed): - ''' self.continue_connect_info = [show, msg, signed] - self.on_connect_auth = self._init_roster - self.connect_and_auth() - ''' - + self.zeroconf.txt['status'] = show self.zeroconf.txt['msg'] = msg self.connect('',show) - def _init_roster(self, con): - ''' - self.connection = con - if self.connection: - con.set_send_timeout(self.keepalives, self.send_keepalive) - self.connection.onreceive(None) - # Ask metacontacts before roster - self.get_metacontacts() - ''' - - pass - def change_status(self, show, msg, sync = False, auto = False): print "change_status: show: %s msg: %s" % (show, msg) if not show in STATUS_LIST: return -1 - # connect + # 'connect' if show != 'offline' and not self.connected: print "connect in change_status" self.on_purpose = False @@ -601,11 +218,13 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf): else: self.connected = STATUS_LIST.index(show) - # disconnect + # 'disconnect' elif show == 'offline' and self.connected: print "disconnect in change_status" self.connected = 0 - self._on_disconnected() + self.dispatch('STATUS', 'offline') + self.disconnect() + #self._on_disconnected() # update status elif show != 'offline' and self.connected: @@ -625,10 +244,12 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf): self.zeroconf.update_txt(txt) self.dispatch('STATUS', show) + ''' def _on_disconnected(self): self.dispatch('STATUS', 'offline') self.disconnect() - + ''' + def get_status(self): return STATUS_LIST[self.connected] @@ -1198,21 +819,8 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf): pass def send_keepalive(self): - ''' # nothing received for the last foo seconds (60 secs by default) if self.connection: self.connection.send(' ') - ''' - pass - - def _reconnect_alarm(self): - ''' - if self.time_to_reconnect: - if self.connected < 2: - self._reconnect() - else: - self.time_to_reconnect = None - ''' - pass -# END Connection +# END ConnectionZeroconf diff --git a/src/common/roster_zeroconf.py b/src/common/roster_zeroconf.py new file mode 100644 index 0000000000..9e2befc484 --- /dev/null +++ b/src/common/roster_zeroconf.py @@ -0,0 +1,37 @@ +from common import zeroconf + +class Roster: + def __init__(self, zeroconf): + self._data = {} + self.zeroconf = zeroconf # our zeroconf instance + + def getRoster(self): + print 'getRoster in Roster' + self._data = self.zeroconf.get_contacts() + return self + + def getItem(self, jid): + print 'getItem(%s) in Roster' % jid + if self._data.has_key(jid): + return self._data[jid] + + def __getitem__(self,item): + print '__getitem__ in Roster' + return self._data[item] + + def getRaw(self): + return self._data + + def getResources(self, jid): + print 'getResources(%s) in Roster' % jid +# return self + + ''' + getRaw() + delItem(jid) + getItem(jid) + getResources(jid) + getStatus(jid) + getPriority(jid) + getShow(jid) + ''' diff --git a/src/common/zeroconf.py b/src/common/zeroconf.py index 0389f09262..091982e07c 100755 --- a/src/common/zeroconf.py +++ b/src/common/zeroconf.py @@ -34,11 +34,13 @@ class Zeroconf: print "Found service '%s' in domain '%s' on %i.%i." % (name, domain, interface, protocol) #synchronous resolving - self.server.ResolveService( int(interface), int(protocol), name, stype, domain, avahi.PROTO_UNSPEC, dbus.UInt32(0), reply_handler=self.service_resolved_callback, error_handler=self.print_error_callback) + self.server.ResolveService( int(interface), int(protocol), name, stype, \ + domain, avahi.PROTO_UNSPEC, dbus.UInt32(0), \ + reply_handler=self.service_resolved_callback, error_handler=self.print_error_callback) def remove_service_callback(self, interface, protocol, name, stype, domain, flags): print "Service '%s' in domain '%s' on %i.%i disappeared." % (name, domain, interface, protocol) - del self.contacts[(interface, name, domain)] + del self.contacts[(name, stype, domain, interface)] def new_service_type(self, interface, protocol, stype, domain, flags): # Are we already browsing this domain for this type? @@ -59,11 +61,26 @@ class Zeroconf: if domain != "local": self.browse_domain(interface, protocol, domain) + def txt_array_to_dict(self,t): + l = {} + + for s in t: + str = avahi.byte_array_to_string(s) + poseq = str.find('=') + l[str[:poseq]] = str[poseq+1:] + return l + def service_resolved_callback(self, interface, protocol, name, stype, domain, host, aprotocol, address, port, txt, flags): print "Service data for service '%s' in domain '%s' on %i.%i:" % (name, domain, interface, protocol) print "\tHost %s (%s), port %i, TXT data: %s" % (host, address, port, str(avahi.txt_array_to_string_array(txt))) - - self.contacts[(interface, name, domain)] = (interface, name, protocol, domain, host, address, port, txt) + + # add domain to stay unique + if domain != 'local': + add_domain = '%'+domain + else: + add_domain = '' + + self.contacts[name+add_domain+'@'+host] = (name, stype, domain, interface, protocol, host, address, port, txt) def service_added_callback(self): @@ -191,8 +208,8 @@ class Zeroconf: # END Zeroconf ''' -def main(): - +# how to use... + zeroconf = Zeroconf() zeroconf.connect() zeroconf.txt[('1st')] = 'foo' @@ -201,15 +218,7 @@ def main(): # updating after announcing txt = {} - txt['status'] = 'avail' # out of avail/away/dnd + txt['status'] = 'avail' txt['msg'] = 'Here I am' zeroconf.update_txt(txt) - - try: - gobject.MainLoop().run() - except KeyboardInterrupt, k: - pass - -if __name__ == "__main__": - main() ''' -- GitLab