Swtich from old to new caps API.

Now we do:

contact.supports(feauture) instead of gajim.capscache.is_supported(contact, feature)
This commit is contained in:
Stephan Erb 2009-10-27 22:41:39 +01:00
parent c7ff97703f
commit 33fe53ff7d
9 changed files with 84 additions and 109 deletions

View File

@ -1333,9 +1333,7 @@ class ChatControl(ChatControlBase):
def update_toolbar(self):
# Formatting
if gajim.capscache.is_supported(self.contact, NS_XHTML_IM) \
and not gajim.capscache.is_supported(self.contact, 'notexistant') \
and not self.gpg_is_active:
if self.contact.supports(NS_XHTML_IM) and not self.gpg_is_active:
self._formattings_button.set_sensitive(True)
else:
self._formattings_button.set_sensitive(False)
@ -1348,12 +1346,11 @@ class ChatControl(ChatControlBase):
self._add_to_roster_button.hide()
# Send file
if gajim.capscache.is_supported(self.contact, NS_FILE) and \
self.contact.resource:
if self.contact.supports(NS_FILE) and self.contact.resource:
self._send_file_button.set_sensitive(True)
else:
self._send_file_button.set_sensitive(False)
if not gajim.capscache.is_supported(self.contact, NS_FILE):
if not self.contact.supports(NS_FILE):
self._send_file_button.set_tooltip_text(_(
"This contact does not support file transfer."))
else:
@ -1362,7 +1359,7 @@ class ChatControl(ChatControlBase):
"her a file."))
# Convert to GC
if gajim.capscache.is_supported(self.contact, NS_MUC):
if self.contact.supports(NS_MUC):
self._convert_to_gc_button.set_sensitive(True)
else:
self._convert_to_gc_button.set_sensitive(False)
@ -1828,9 +1825,7 @@ class ChatControl(ChatControlBase):
def _on_sent(id_, contact, message, encrypted, xhtml):
# XXX: Once we have fallback to disco, remove notexistant check
if gajim.capscache.is_supported(contact, NS_RECEIPTS) \
and not gajim.capscache.is_supported(contact,
'notexistant') and gajim.config.get_per('accounts',
if contact.supports(NS_RECEIPTS) and gajim.config.get_per('accounts',
self.account, 'request_receipt'):
xep0184_id = id_
else:
@ -2137,10 +2132,7 @@ class ChatControl(ChatControlBase):
toggle_gpg_menuitem.set_active(self.gpg_is_active)
# disable esessions if we or the other client don't support them
# XXX: Once we have fallback to disco, remove notexistant check
if not gajim.HAVE_PYCRYPTO or \
not gajim.capscache.is_supported(contact, NS_ESESSION) or \
gajim.capscache.is_supported(contact, 'notexistant') or \
if not gajim.HAVE_PYCRYPTO or not contact.supports(NS_ESESSION) or \
not gajim.config.get_per('accounts', self.account, 'enable_esessions'):
toggle_e2e_menuitem.set_sensitive(False)
else:
@ -2152,13 +2144,13 @@ class ChatControl(ChatControlBase):
add_to_roster_menuitem.show()
# check if it's possible to send a file
if gajim.capscache.is_supported(contact, NS_FILE):
if contact.supports(NS_FILE):
send_file_menuitem.set_sensitive(True)
else:
send_file_menuitem.set_sensitive(False)
# check if it's possible to convert to groupchat
if gajim.capscache.is_supported(contact, NS_MUC):
if contact.supports(NS_MUC):
convert_to_gc_menuitem.set_sensitive(True)
else:
convert_to_gc_menuitem.set_sensitive(False)
@ -2471,12 +2463,8 @@ class ChatControl(ChatControlBase):
want_e2e = not e2e_is_active and not self.gpg_is_active \
and e2e_pref
# XXX: Once we have fallback to disco, remove notexistant check
if want_e2e and not self.no_autonegotiation \
and gajim.HAVE_PYCRYPTO \
and gajim.capscache.is_supported(self.contact,
NS_ESESSION) and not gajim.capscache.is_supported(
self.contact, 'notexistant'):
and gajim.HAVE_PYCRYPTO and self.contact.supports(NS_ESESSION):
self.begin_e2e_negotiation()
else:
self.send_chatstate('active', self.contact)

View File

@ -65,8 +65,14 @@ class AbstractClientCaps(object):
def _lookup_in_cache(self, caps_cache):
''' To be implemented by subclassess '''
raise NotImplementedError()
def get_hash_validation_strategy(self):
return self._is_hash_valid
def _is_hash_valid(self, identities, features, dataforms):
raise NotImplementedError()
class ClientCaps(AbstractClientCaps):
''' The current XEP-115 implementation '''
@ -81,6 +87,11 @@ class ClientCaps(AbstractClientCaps):
def _discover(self, connection, jid):
connection.discoverInfo(jid, '%s#%s' % (self._node, self._hash))
def _is_hash_valid(self, identities, features, dataforms):
computed_hash = helpers.compute_caps_hash(identities, features,
dataforms=dataforms, hash_method=self._hash_method)
return computed_hash == self._hash
class OldClientCaps(AbstractClientCaps):
''' Old XEP-115 implemtation. Kept around for background competability. '''
@ -94,6 +105,8 @@ class OldClientCaps(AbstractClientCaps):
def _discover(self, connection, jid):
connection.discoverInfo(jid)
def _is_hash_valid(self, identities, features, dataforms):
return True
class NullClientCaps(AbstractClientCaps):
'''
@ -112,6 +125,8 @@ class NullClientCaps(AbstractClientCaps):
def _discover(self, connection, jid):
pass
def _is_hash_valid(self, identities, features, dataforms):
return False
class CapsCache(object):
'''
@ -238,11 +253,17 @@ class CapsCache(object):
gajim.capscache = CapsCache(gajim.logger)
class ConnectionCaps(object):
''' This class highly depends on that it is a part of Connection class. '''
'''
This class highly depends on that it is a part of Connection class.
'''
def _capsPresenceCB(self, con, presence):
''' Handle incoming presence stanzas... This is a callback
for xmpp registered in connection_handlers.py'''
'''
Handle incoming presence stanzas... This is a callback for xmpp
registered in connection_handlers.py
'''
# we will put these into proper Contact object and ask
# for disco... so that disco will learn how to interpret
@ -264,64 +285,47 @@ class ConnectionCaps(object):
# into Contacts
return
# get the caps element
caps = presence.getTag('c')
if not caps:
contact.caps_node = None
contact.caps_hash = None
contact.caps_hash_method = None
return
caps_tag = presence.getTag('c')
if not caps_tag:
# presence did not contain caps_tag
client_caps = NullClientCaps()
else:
hash_method, node, caps_hash = caps_tag['hash'], caps_tag['node'], caps_tag['ver']
hash_method, node, hash_ = caps['hash'], caps['node'], caps['ver']
if node is None or caps_hash is None:
# improper caps in stanza, ignore client capabilities.
client_caps = NullClientCaps()
elif hash_method is None:
client_caps = OldClientCaps(caps_hash, node)
else:
client_caps = ClientCaps(caps_hash, node, hash_method)
gajim.capscache.query_client_of_jid_if_unknown(self, jid, client_caps)
contact.client_caps = client_caps
if hash_method is None and node and hash_:
# Old XEP-115 implentation
hash_method = 'old'
if hash_method is None or node is None or hash_ is None:
# improper caps in stanza, ignoring
contact.caps_node = None
contact.caps_hash = None
contact.hash_method = None
return
# start disco query...
gajim.capscache.preload(self, jid, node, hash_method, hash_)
# overwriting old data
contact.caps_node = node
contact.caps_hash_method = hash_method
contact.caps_hash = hash_
if pm_ctrl:
pm_ctrl.update_contact()
def _capsDiscoCB(self, jid, node, identities, features, dataforms):
def _capsDiscoCB(self, jid, node, identities, features, dataforms):
contact = gajim.contacts.get_contact_from_full_jid(self.name, jid)
if not contact:
room_jid, nick = gajim.get_room_and_nick_from_fjid(jid)
contact = gajim.contacts.get_gc_contact(self.name, room_jid, nick)
if contact is None:
return
if not contact.caps_node:
return # we didn't asked for that?
if contact.caps_hash_method != 'old':
computed_hash = helpers.compute_caps_hash(identities, features,
dataforms=dataforms, hash_method=contact.caps_hash_method)
if computed_hash != contact.caps_hash:
# wrong hash, forget it
contact.caps_node = ''
contact.caps_hash_method = ''
contact.caps_hash = ''
return
# if we don't have this info already...
caps = gajim.capscache[(contact.caps_hash_method, contact.caps_hash)]
else:
# if we don't have this info already...
caps = gajim.capscache[(contact.caps_hash_method, contact.caps_node + \
'#' + contact.caps_hash)]
if caps.queried == 2:
return
caps.update(identities, features)
lookup = contact.client_caps.get_cache_lookup_strategy()
cache_item = lookup(gajim.capscache)
if cache_item.queried == 2:
return
else:
validate = contact.client_caps.get_hash_validation_strategy()
hash_is_valid = validate(identities, features, dataforms)
if hash_is_valid:
cache_item.update(identities, features)
else:
contact.client_caps = NullClientCaps()
# vim: se ts=3:

View File

@ -1303,10 +1303,7 @@ class Connection(ConnectionHandlers):
# remove notexistant check
if ((composing_xep == 'XEP-0085' or not composing_xep) \
and composing_xep != 'asked_once') or \
(gajim.capscache.is_supported(contact,
common.xmpp.NS_CHATSTATES) and \
not gajim.capscache.is_supported(contact,
'notexistant')):
contact.supports(common.xmpp.NS_CHATSTATES):
# XEP-0085
msg_iq.setTag(chatstate, namespace=common.xmpp.NS_CHATSTATES)
if composing_xep in ('XEP-0022', 'asked_once') or \
@ -1332,8 +1329,7 @@ class Connection(ConnectionHandlers):
# XEP-0184
if msgtxt and gajim.config.get_per('accounts', self.name,
'request_receipt') and gajim.capscache.is_supported(contact,
common.xmpp.NS_RECEIPTS):
'request_receipt') and contact.supports(common.xmpp.NS_RECEIPTS):
msg_iq.setTag('request', namespace=common.xmpp.NS_RECEIPTS)
if session:

View File

@ -2460,9 +2460,8 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
if not sess.received_thread_id:
contact = gajim.contacts.get_contact(self.name, jid)
session_supported = gajim.capscache.is_supported(contact,
common.xmpp.NS_SSN) or gajim.capscache.is_supported(
contact, common.xmpp.NS_ESESSION)
session_supported = contact.supports(common.xmpp.NS_SSN) or \
contact.supports(common.xmpp.NS_ESESSION)
if session_supported:
sess.terminate()
del self.sessions[jid][sess.thread_id]

View File

@ -53,7 +53,7 @@ class Contact(object):
self.keyID = keyID
# Entity Capabilities
self._client_caps = client_caps or NullClientCaps()
self.client_caps = client_caps or NullClientCaps()
self._caps_cache = caps_cache or common.gajim.capscache
# please read xep-85 http://www.xmpp.org/extensions/xep-0085.html
@ -147,8 +147,8 @@ class Contact(object):
return self._client_supports(requested_feature)
def _client_supports(self, requested_feature):
lookup_item = self._client_caps.get_cache_lookup_strategy()
cache_item = lookup_item(self._caps_cache)
lookup = self.client_caps.get_cache_lookup_strategy()
cache_item = lookup(self._caps_cache)
supported_features = cache_item.features
if requested_feature in supported_features:
@ -160,11 +160,6 @@ class Contact(object):
else:
return False
def set_supported_client_caps(self, client_caps):
''' Set an EntityCapabilities object '''
self._client_caps = client_caps
class GC_Contact:
'''Information concerning each groupchat contact'''
def __init__(self, room_jid='', name='', show='', status='', role='',
@ -180,7 +175,7 @@ class GC_Contact:
self.resource = resource
# Entity Capabilities
self._client_caps = NullClientCaps()
self.client_caps = NullClientCaps()
self._caps_cache = common.gajim.capscache
self.our_chatstate = our_chatstate
@ -204,7 +199,7 @@ class GC_Contact:
return self._client_supports(requested_feature)
def _client_supports(self, requested_feature):
lookup_item = self._client_caps.get_cache_lookup_strategy()
lookup_item = self.client_caps.get_cache_lookup_strategy()
cache_item = lookup_item(self._caps_cache)
supported_features = cache_item.features
@ -217,10 +212,6 @@ class GC_Contact:
else:
return False
def set_supported_client_caps(self, client_caps):
''' Set an EntityCapabilities object '''
self._client_caps = client_caps
class Contacts:
'''Information concerning all contacts and groupchat contacts'''
def __init__(self):
@ -276,7 +267,7 @@ class Contacts:
groups=contact.groups, show=contact.show, status=contact.status,
sub=contact.sub, ask=contact.ask, resource=contact.resource,
priority=contact.priority, keyID=contact.keyID,
client_caps=contact._client_caps, caps_cache=contact._caps_cache,
client_caps=contact.client_caps, caps_cache=contact._caps_cache,
our_chatstate=contact.our_chatstate,
chatstate=contact.chatstate, last_status_time=contact.last_status_time)
@ -647,7 +638,7 @@ class Contacts:
jid = gc_contact.get_full_jid()
return Contact(jid=jid, resource=gc_contact.resource,
name=gc_contact.name, groups=[], show=gc_contact.show,
status=gc_contact.status, sub='none', client_caps=gc_contact._client_caps,
status=gc_contact.status, sub='none', client_caps=gc_contact.client_caps,
caps_cache=gc_contact._caps_cache)
def create_gc_contact(self, room_jid='', name='', show='', status='',

View File

@ -223,7 +223,7 @@ class EncryptedStanzaSession(StanzaSession):
def _is_buggy_gajim(self):
c = self._get_contact()
if gajim.capscache.is_supported(c, xmpp.NS_ROSTERX):
if c.supports(xmpp.NS_ROSTERX):
return False
return True

View File

@ -4060,7 +4060,7 @@ class RosterWindow:
return
c_dest = gajim.contacts.get_contact_with_highest_priority(account_dest,
jid_dest)
if not gajim.capscache.is_supported(c_dest, NS_FILE):
if not c_dest.supports(NS_FILE):
return
uri = data.strip()
uri_splitted = uri.split() # we may have more than one file dropped
@ -5411,7 +5411,7 @@ class RosterWindow:
start_chat_menuitem.connect('activate',
self.on_roster_treeview_row_activated, tree_path)
if gajim.capscache.is_supported(contact, NS_FILE):
if contact.supports(NS_FILE):
send_file_menuitem.set_sensitive(True)
send_file_menuitem.connect('activate',
self.on_send_file_menuitem_activate, contact, account)
@ -5584,7 +5584,7 @@ class RosterWindow:
else: # one resource
start_chat_menuitem.connect('activate',
gajim.interface.on_open_chat_window, contact, account)
if gajim.capscache.is_supported(contact, NS_COMMANDS):
if contact.supports(NS_COMMANDS):
execute_command_menuitem.set_sensitive(True)
execute_command_menuitem.connect('activate', self.on_execute_command,
contact, account, contact.resource)
@ -5598,7 +5598,7 @@ class RosterWindow:
# our_jid_other_resource = contact.resource
# Else this var is useless but harmless in next connect calls
if gajim.capscache.is_supported(contact, NS_FILE):
if contact.supports(NS_FILE):
send_file_menuitem.set_sensitive(True)
send_file_menuitem.connect('activate',
self.on_send_file_menuitem_activate, contact, account)
@ -6026,8 +6026,7 @@ class RosterWindow:
item.connect('activate', action, [(c, account)], c.resource)
else: # start_chat, execute_command, send_file
item.connect('activate', action, c, account, c.resource)
if cap and \
not gajim.capscache.is_supported(c, cap):
if cap and not c.suppors(cap):
item.set_sensitive(False)
return sub_menu
@ -6062,7 +6061,7 @@ class RosterWindow:
if len(contact_list) > 1: # several resources
invite_to_new_room_menuitem.set_submenu(self.build_resources_submenu(
contact_list, account, self.on_invite_to_new_room, cap=NS_MUC))
elif len(list_) == 1 and gajim.capscache.is_supported(contact, NS_MUC):
elif len(list_) == 1 and contact.supports(NS_MUC):
invite_menuitem.set_sensitive(True)
# use resource if it's self contact
if contact.jid == gajim.get_jid_from_account(account):

View File

@ -118,8 +118,7 @@ class TestClientCaps(CommonCapsTest):
"http://gajim.org#m3P2WeXPMGVH2tZPe7yITnfY0Dw=")
def test_client_supports(self):
contact = Contact(caps_cache=self.cc)
contact.set_supported_client_caps(self.client_caps)
contact = Contact(caps_cache=self.cc, client_caps=self.client_caps)
self.assertTrue(contact.supports(NS_PING),
msg="Assume supported, if we don't have caps")

View File

@ -24,8 +24,7 @@ class TestCommonContact(unittest.TestCase):
self.assertTrue(self.contact.supports(NS_MUC),
msg="Must not backtrace on simple check for supported feature")
client_caps = NullClientCaps()
self.contact.set_supported_client_caps(client_caps)
self.contact.client_caps = NullClientCaps()
self.assertTrue(self.contact.supports(NS_MUC),
msg="Must not backtrace on simple check for supported feature")