use NEC to handle agent info / items events

This commit is contained in:
Yann Leboulanger 2010-11-29 12:53:50 +01:00
parent bfea5e1392
commit 6a2651ebd5
8 changed files with 246 additions and 201 deletions

View File

@ -3044,8 +3044,6 @@ class ChatControl(ChatControlBase):
if obj.session != self.session:
return
obj.printed_in_chat = True
details = _('Unable to decrypt message from %s\nIt may have been '
'tampered with.') % obj.fjid
self.print_conversation_line(details, 'status', '', obj.timestamp)

View File

@ -714,11 +714,17 @@ class Connection(CommonConnection, ConnectionHandlers):
self.secret_hmac = str(random.random())[2:]
gajim.ged.register_event_handler('privacy-list-received', ged.CORE,
self._nec_privacy_list_received)
gajim.ged.register_event_handler('agent-info-error-received', ged.CORE,
self._nec_agent_info_error_received)
gajim.ged.register_event_handler('agent-info-received', ged.CORE,
self._nec_agent_info_received)
# END __init__
def __del__(self):
gajim.ged.remove_event_handler('privacy-list-received', ged.CORE,
self._nec_privacy_list_received)
gajim.ged.remove_event_handler('agent-info-error-received', ged.CORE,
self._nec_agent_info_error_received)
def get_config_values_or_default(self):
if gajim.config.get_per('accounts', self.name, 'keep_alives_enabled'):
@ -1594,6 +1600,83 @@ class Connection(CommonConnection, ConnectionHandlers):
self.awaiting_answers[id_] = (PRIVACY_ARRIVED, )
self.connection.send(iq)
def _nec_agent_info_error_received(self, obj):
if obj.conn.name != self.name:
return
if obj.id_[:6] == 'Gajim_':
if not self.privacy_rules_requested:
self.privacy_rules_requested = True
self._request_privacy()
def _nec_agent_info_received(self, obj):
if obj.conn.name != self.name:
return
is_muc = False
transport_type = ''
for identity in obj.identities:
if 'category' in identity and identity['category'] in ('gateway',
'headline') and 'type' in identity:
transport_type = identity['type']
if 'category' in identity and identity['category'] == 'conference' \
and 'type' in identity and identity['type'] == 'text':
is_muc = True
if transport_type and obj.fjid not in gajim.transport_type:
gajim.transport_type[obj.fjid] = transport_type
gajim.logger.save_transport_type(obj.fjid, transport_type)
if obj.id_[:6] == 'Gajim_':
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:
gajim.gmail_domains.append(obj.fjid)
self.request_gmail_notifications()
if common.xmpp.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:
self.vcard_supported = True
if common.xmpp.NS_PUBSUB in obj.features:
self.pubsub_supported = True
if common.xmpp.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:
self.archiving_supported = True
if common.xmpp.NS_ARCHIVE_AUTO in obj.features:
self.archive_auto_supported = True
if common.xmpp.NS_ARCHIVE_MANAGE in obj.features:
self.archive_manage_supported = True
if common.xmpp.NS_ARCHIVE_MANUAL in obj.features:
self.archive_manual_supported = True
if common.xmpp.NS_ARCHIVE_PREF in obj.features:
self.archive_pref_supported = True
if common.xmpp.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)
gajim.proxy65_manager.resolve(obj.fjid, self.connection,
our_fjid, self.name)
if common.xmpp.NS_MUC in obj.features and is_muc:
type_ = transport_type or 'jabber'
self.muc_jid[type_] = obj.fjid
if transport_type:
if transport_type in self.available_transports:
self.available_transports[transport_type].append(obj.fjid)
else:
self.available_transports[transport_type] = [obj.fjid]
if not self.privacy_rules_requested:
self.privacy_rules_requested = True
self._request_privacy()
def send_custom_status(self, show, msg, jid):
if not show in gajim.SHOW_LIST:
return -1

View File

@ -203,42 +203,13 @@ class ConnectionDisco:
def _DiscoverItemsErrorCB(self, con, iq_obj):
log.debug('DiscoverItemsErrorCB')
jid = helpers.get_full_jid_from_iq(iq_obj)
self.dispatch('AGENT_ERROR_ITEMS', (jid))
gajim.nec.push_incoming_event(AgentItemsErrorReceivedEvent(None,
conn=self, stanza=iq_obj))
def _DiscoverItemsCB(self, con, iq_obj):
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]
if 'jid' not in attr:
continue
try:
attr['jid'] = helpers.parse_jid(attr['jid'])
except common.helpers.InvalidFormat:
# jid is not conform
continue
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_[:6] == 'Gajim_':
for item in items:
self.discoverInfo(item['jid'], id_prefix='Gajim_')
else:
self.dispatch('AGENT_INFO_ITEMS', (jid, node, items))
gajim.nec.push_incoming_event(AgentItemsReceivedEvent(None, conn=self,
stanza=iq_obj))
def _DiscoverItemsGetCB(self, con, iq_obj):
log.debug('DiscoverItemsGetCB')
@ -291,117 +262,15 @@ class ConnectionDisco:
def _DiscoverInfoErrorCB(self, con, iq_obj):
log.debug('DiscoverInfoErrorCB')
jid = helpers.get_full_jid_from_iq(iq_obj)
id_ = iq_obj.getID()
if id_[:6] == 'Gajim_':
if not self.privacy_rules_requested:
self.privacy_rules_requested = True
self._request_privacy()
self.dispatch('AGENT_ERROR_INFO', (jid))
gajim.nec.push_incoming_event(AgentInfoErrorReceivedEvent(None,
conn=self, stanza=iq_obj))
def _DiscoverInfoCB(self, con, iq_obj):
log.debug('DiscoverInfoCB')
if not self.connection or self.connected < 2:
return
# According to XEP-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 = []
is_muc = False
transport_type = ''
for i in qc:
if i.getName() == 'identity':
attr = {}
for key in i.getAttrs().keys():
attr[key] = i.getAttr(key)
if 'category' in attr and attr['category'] in ('gateway',
'headline') and 'type' in attr:
transport_type = attr['type']
if 'category' in attr and attr['category'] == 'conference' and \
'type' in attr and attr['type'] == 'text':
is_muc = True
identities.append(attr)
elif i.getName() == 'feature':
var = i.getAttr('var')
if var:
features.append(var)
elif i.getName() == 'x' and i.getNamespace() == common.xmpp.NS_DATA:
data.append(common.xmpp.DataForm(node=i))
jid = helpers.get_full_jid_from_iq(iq_obj)
if transport_type and jid not in gajim.transport_type:
gajim.transport_type[jid] = transport_type
gajim.logger.save_transport_type(jid, transport_type)
id_ = iq_obj.getID()
if id_ is None:
log.warn('Invalid IQ received without an ID. Ignoring it: %s' % \
iq_obj)
return
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_[:6] == 'Gajim_':
if jid == gajim.config.get_per('accounts', self.name, 'hostname'):
if features.__contains__(common.xmpp.NS_GMAILNOTIFY):
gajim.gmail_domains.append(jid)
self.request_gmail_notifications()
if features.__contains__(common.xmpp.NS_SECLABEL):
self.seclabel_supported = True
for identity in identities:
if identity['category'] == 'pubsub' and identity.get(
'type') == 'pep':
self.pep_supported = True
break
if features.__contains__(common.xmpp.NS_VCARD):
self.vcard_supported = True
if features.__contains__(common.xmpp.NS_PUBSUB):
self.pubsub_supported = True
if features.__contains__(
common.xmpp.NS_PUBSUB_PUBLISH_OPTIONS):
self.pubsub_publish_options_supported = True
else:
# Remove stored bookmarks accessible to everyone.
our_jid = gajim.get_jid_from_account(self.name)
self.send_pb_purge(our_jid, 'storage:bookmarks')
self.send_pb_delete(our_jid, 'storage:bookmarks')
if features.__contains__(common.xmpp.NS_ARCHIVE):
self.archiving_supported = True
if features.__contains__(common.xmpp.NS_ARCHIVE_AUTO):
self.archive_auto_supported = True
if features.__contains__(common.xmpp.NS_ARCHIVE_MANAGE):
self.archive_manage_supported = True
if features.__contains__(common.xmpp.NS_ARCHIVE_MANUAL):
self.archive_manual_supported = True
if features.__contains__(common.xmpp.NS_ARCHIVE_PREF):
self.archive_pref_supported = True
if features.__contains__(common.xmpp.NS_BYTESTREAM) and \
gajim.config.get_per('accounts', self.name, 'use_ft_proxies'):
our_jid = helpers.parse_jid(gajim.get_jid_from_account(
self.name) + '/' + self.server_resource)
gajim.proxy65_manager.resolve(jid, self.connection, our_jid,
self.name)
if features.__contains__(common.xmpp.NS_MUC) and is_muc:
type_ = transport_type or 'jabber'
self.muc_jid[type_] = jid
if transport_type:
if transport_type in self.available_transports:
self.available_transports[transport_type].append(jid)
else:
self.available_transports[transport_type] = [jid]
if not self.privacy_rules_requested:
self.privacy_rules_requested = True
self._request_privacy()
self.dispatch('AGENT_INFO_INFO', (jid, node, identities, features,
data))
self._capsDiscoCB(jid, node, identities, features, data)
gajim.nec.push_incoming_event(AgentInfoReceivedEvent(None, conn=self,
stanza=iq_obj))
class ConnectionVcard:
def __init__(self):

View File

@ -1572,7 +1572,6 @@ class FailedDecryptEvent(nec.NetworkIncomingEvent):
self.fjid = self.msg_obj.fjid
self.timestamp = self.msg_obj.timestamp
self.session = self.msg_obj.session
self.printed_in_chat = False
return True
class SignedInEvent(nec.NetworkIncomingEvent):
@ -1582,3 +1581,100 @@ class SignedInEvent(nec.NetworkIncomingEvent):
class RegisterAgentInfoReceivedEvent(nec.NetworkIncomingEvent):
name = 'register-agent-info-received'
base_network_events = []
class AgentItemsReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
name = 'agent-items-received'
base_network_events = []
def generate(self):
q = self.stanza.getTag('query')
self.node = q.getAttr('node')
if not self.node:
self.node = ''
qp = self.stanza.getQueryPayload()
self.items = []
if not qp:
qp = []
for i in qp:
# CDATA payload is not processed, only nodes
if not isinstance(i, xmpp.simplexml.Node):
continue
attr = {}
for key in i.getAttrs():
attr[key] = i.getAttrs()[key]
if 'jid' not in attr:
continue
try:
attr['jid'] = helpers.parse_jid(attr['jid'])
except helpers.InvalidFormat:
# jid is not conform
continue
self.items.append(attr)
self.get_jid_resource()
hostname = gajim.config.get_per('accounts', self.conn.name, 'hostname')
self.get_id()
if self.fjid == hostname and self.id_[:6] == 'Gajim_':
for item in self.items:
self.conn.discoverInfo(item['jid'], id_prefix='Gajim_')
else:
return True
class AgentItemsErrorReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
name = 'agent-items-error-received'
base_network_events = []
def generate(self):
self.get_jid_resource()
return True
class AgentInfoReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
name = 'agent-info-received'
base_network_events = []
def generate(self):
self.get_id()
if self.id_ is None:
log.warn('Invalid IQ received without an ID. Ignoring it: %s' % \
self.stanza)
return
# According to XEP-0030:
# For identity: category, type is mandatory, name is optional.
# For feature: var is mandatory
self.identities, self.features, self.data = [], [], []
q = self.stanza.getTag('query')
self.node = q.getAttr('node')
if not self.node:
self.node = ''
qc = self.stanza.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)
self.identities.append(attr)
elif i.getName() == 'feature':
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))
if not self.identities:
# ejabberd doesn't send identities when we browse online users
# see http://www.jabber.ru/bugzilla/show_bug.cgi?id=225
self.identities = [{'category': 'server', 'type': 'im',
'name': node}]
self.get_jid_resource()
return True
class AgentInfoErrorReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
name = 'agent-info-error-received'
base_network_events = []
def generate(self):
self.get_jid_resource()
self.get_id()
return True

View File

@ -43,6 +43,8 @@ class ConnectionCaps(object):
gajim.nec.register_incoming_event(CapsReceivedEvent)
gajim.ged.register_event_handler('caps-presence-received', ged.GUI1,
self._nec_caps_presence_received)
gajim.ged.register_event_handler('agent-info-received', ged.GUI1,
self._nec_agent_info_received)
def caps_change_account_name(self, new_name):
self._account = new_name
@ -70,14 +72,14 @@ class ConnectionCaps(object):
contact = gajim.contacts.get_gc_contact(self._account, room_jid, nick)
return contact
def _capsDiscoCB(self, jid, node, identities, features, dataforms):
def _nec_agent_info_received(self, obj):
"""
XMMPPY callback to update our caps cache with queried information after
callback to update our caps cache with queried information after
we have retrieved an unknown caps hash and issued a disco
"""
contact = self._get_contact_or_gc_contact_for_jid(jid)
contact = self._get_contact_or_gc_contact_for_jid(obj.fjid)
if not contact:
log.info("Received Disco from unknown contact %s" % jid)
log.info('Received Disco from unknown contact %s' % obj.fjid)
return
lookup = contact.client_caps.get_cache_lookup_strategy()
@ -89,18 +91,17 @@ class ConnectionCaps(object):
return
else:
validate = contact.client_caps.get_hash_validation_strategy()
hash_is_valid = validate(identities, features, dataforms)
hash_is_valid = validate(obj.identities, obj.features, obj.data)
if hash_is_valid:
cache_item.set_and_store(identities, features)
cache_item.set_and_store(obj.identities, obj.features)
else:
node = caps_hash = hash_method = None
contact.client_caps = self._create_suitable_client_caps(node,
caps_hash, hash_method)
log.info("Computed and retrieved caps hash differ." +
"Ignoring caps of contact %s" % contact.get_full_jid())
contact.client_caps = self._create_suitable_client_caps(
obj.node, caps_hash, hash_method)
log.info('Computed and retrieved caps hash differ.' +
'Ignoring caps of contact %s' % contact.get_full_jid())
j, r = gajim.get_room_and_nick_from_fjid(jid)
gajim.nec.push_incoming_event(CapsDiscoReceivedEvent(None,
conn=self, fjid=jid, jid=j, resource=r,
conn=self, fjid=obj.fjid, jid=obj.jid, resource=obj.resource,
client_caps=contact.client_caps))

View File

@ -3943,6 +3943,8 @@ class ManagePEPServicesWindow:
gajim.ged.register_event_handler('pep-config-received', ged.GUI1,
self._nec_pep_config_received)
gajim.ged.register_event_handler('agent-items-received', ged.GUI1,
self._nec_agent_items_received)
self.window.show_all()
@ -3951,6 +3953,8 @@ class ManagePEPServicesWindow:
del gajim.interface.instances[self.account]['pep_services']
gajim.ged.remove_event_handler('pep-config-received', ged.GUI1,
self._nec_pep_config_received)
gajim.ged.remove_event_handler('agent-items-received', ged.GUI1,
self._nec_agent_items_received)
def on_close_button_clicked(self, widget):
self.window.destroy()
@ -3975,9 +3979,9 @@ class ManagePEPServicesWindow:
our_jid = gajim.get_jid_from_account(self.account)
gajim.connections[self.account].discoverItems(our_jid)
def items_received(self, items):
def _nec_agent_items_received(self, obj):
our_jid = gajim.get_jid_from_account(self.account)
for item in items:
for item in obj.items:
if 'jid' in item and item['jid'] == our_jid and 'node' in item:
self.treestore.append([item['node']])
@ -4028,6 +4032,9 @@ class ManagePEPServicesWindow:
window.set_title(title)
window.show_all()
def _nec_agent_items_received(self, obj):
pass
class ManageSoundsWindow:
def __init__(self):
self.xml = gtkgui_helpers.get_gtk_builder('manage_sounds_window.ui')

View File

@ -255,24 +255,24 @@ class ServicesCache:
self._info = CacheDictionary(0, getrefresh = False)
self._subscriptions = CacheDictionary(5, getrefresh=False)
self._cbs = {}
gajim.ged.register_event_handler('AGENT_ERROR_INFO', ged.CORE,
self.agent_info_error)
gajim.ged.register_event_handler('AGENT_ERROR_ITEMS', ged.CORE,
self.agent_items_error)
gajim.ged.register_event_handler('AGENT_INFO_ITEMS', ged.CORE,
self.agent_items)
gajim.ged.register_event_handler('AGENT_INFO_INFO', ged.CORE,
self.agent_info)
gajim.ged.register_event_handler('agent-items-received', ged.GUI1,
self._nec_agent_items_received)
gajim.ged.register_event_handler('agent-items-error-received', ged.GUI1,
self._nec_agent_items_error_received)
gajim.ged.register_event_handler('agent-info-received', ged.GUI1,
self._nec_agent_info_received)
gajim.ged.register_event_handler('agent-info-error-received', ged.GUI1,
self._nec_agent_info_error_received)
def __del__(self):
gajim.ged.remove_event_handler('AGENT_ERROR_INFO', ged.CORE,
self.agent_info_error)
gajim.ged.remove_event_handler('AGENT_ERROR_ITEMS', ged.CORE,
self.agent_items_error)
gajim.ged.remove_event_handler('AGENT_INFO_ITEMS', ged.CORE,
self.agent_items)
gajim.ged.remove_event_handler('AGENT_INFO_INFO', ged.CORE,
self.agent_info)
gajim.ged.remove_event_handler('agent-items-received', ged.GUI1,
self._nec_agent_items_received)
gajim.ged.remove_event_handler('agent-items-error-received', ged.GUI1,
self._nec_agent_items_error_received)
gajim.ged.remove_event_handler('agent-info-received', ged.GUI1,
self._nec_agent_info_received)
gajim.ged.remove_event_handler('agent-info-error-received', ged.GUI1,
self._nec_agent_info_error_received)
def cleanup(self):
self._items.cleanup()
@ -402,86 +402,86 @@ class ServicesCache:
self._cbs[cbkey] = [cb]
gajim.connections[self.account].discoverItems(jid, node)
def agent_info(self, account, array):
def _nec_agent_info_received(self, obj):
"""
Callback for when we receive an agent's info
array is (agent, node, identities, features, data)
"""
# We receive events from all accounts from GED
if account != self.account:
if obj.conn.name != self.account:
return
jid, node, identities, features, data = array
addr = get_agent_address(jid, node)
addr = get_agent_address(obj.fjid, obj.node)
# Store in cache
self._info[addr] = (identities, features, data)
self._info[addr] = (obj.identities, obj.features, obj.data)
# Call callbacks
cbkey = ('info', addr)
if cbkey in self._cbs:
for cb in self._cbs[cbkey]:
cb(jid, node, identities, features, data)
cb(obj.fjid, obj.node, obj.identities, obj.features, obj.data)
# clean_closure may have beaten us to it
if cbkey in self._cbs:
del self._cbs[cbkey]
def agent_items(self, account, array):
def _nec_agent_items_received(self, obj):
"""
Callback for when we receive an agent's items
array is (agent, node, items)
"""
# We receive events from all accounts from GED
if account != self.account:
if obj.conn.name != self.account:
return
jid, node, items = array
addr = get_agent_address(jid, node)
addr = get_agent_address(obj.fjid, obj.node)
# Store in cache
self._items[addr] = items
self._items[addr] = obj.items
# Call callbacks
cbkey = ('items', addr)
if cbkey in self._cbs:
for cb in self._cbs[cbkey]:
cb(jid, node, items)
cb(obj.fjid, obj.node, obj.items)
# clean_closure may have beaten us to it
if cbkey in self._cbs:
del self._cbs[cbkey]
def agent_info_error(self, account, jid):
def _nec_agent_info_error_received(self, obj):
"""
Callback for when a query fails. Even after the browse and agents
namespaces
"""
# We receive events from all accounts from GED
if account != self.account:
if obj.conn.name != self.account:
return
addr = get_agent_address(jid)
addr = get_agent_address(obj.fjid)
# Call callbacks
cbkey = ('info', addr)
if cbkey in self._cbs:
for cb in self._cbs[cbkey]:
cb(jid, '', 0, 0, 0)
cb(obj.fjid, '', 0, 0, 0)
# clean_closure may have beaten us to it
if cbkey in self._cbs:
del self._cbs[cbkey]
def agent_items_error(self, account, jid):
def _nec_agent_items_error_received(self, obj):
"""
Callback for when a query fails. Even after the browse and agents
namespaces
"""
# We receive events from all accounts from GED
if account != self.account:
if obj.conn.name != self.account:
return
addr = get_agent_address(jid)
addr = get_agent_address(obj.fjid)
# Call callbacks
cbkey = ('items', addr)
if cbkey in self._cbs:
for cb in self._cbs[cbkey]:
cb(jid, '', 0)
cb(obj.fjid, '', 0)
# clean_closure may have beaten us to it
if cbkey in self._cbs:
del self._cbs[cbkey]

View File

@ -556,14 +556,6 @@ class Interface:
dialogs.ErrorDialog(_('Contact with "%s" cannot be established') % \
obj.agent, _('Check your connection or try again later.'))
def handle_event_agent_info_items(self, account, array):
#('AGENT_INFO_ITEMS', account, (agent, node, items))
our_jid = gajim.get_jid_from_account(account)
if 'pep_services' in gajim.interface.instances[account] and \
array[0] == our_jid:
gajim.interface.instances[account]['pep_services'].items_received(
array[2])
def handle_event_vcard(self, obj):
# ('VCARD', account, data)
'''vcard holds the vcard data'''
@ -1388,7 +1380,6 @@ class Interface:
'DB_ERROR': [self.handle_event_db_error],
'INFORMATION': [self.handle_event_information],
'MSGERROR': [self.handle_event_msgerror],
'AGENT_INFO_ITEMS': [self.handle_event_agent_info_items],
'FILE_REQUEST': [self.handle_event_file_request],
'FILE_REQUEST_ERROR': [self.handle_event_file_request_error],
'FILE_SEND_ERROR': [self.handle_event_file_send_error],