| 98 | | ciself.node = node |
| 99 | | ciself.version = version |
| 100 | | ciself.features = set() |
| 101 | | ciself.ext = ext |
| 102 | | ciself.exts = {} |
| 103 | | |
| 104 | | # set of tuples: (category, type, name) |
| 105 | | # (dictionaries are not hashable, so cannot be in sets) |
| 106 | | ciself.identities = set() |
| | 99 | ciself.hash_method = hash_method |
| | 100 | ciself.hash = hash |
| | 101 | |
| | 102 | @property |
| | 103 | def features(): |
| | 104 | def fget(self): |
| | 105 | return self.getAttr('features') |
| | 106 | def fset(self, value): |
| | 107 | list_ = [] |
| | 108 | for feature in value: |
| | 109 | list_.append(self.__names.setdefault(feature, feature)) |
| | 110 | self.setAttr('features', list_) |
| | 111 | |
| | 112 | @property |
| | 113 | def identities(): |
| | 114 | def fget(self): |
| | 115 | return self.getAttr('identities') |
| | 116 | def fset(self, value): |
| | 117 | list_ = [] |
| | 118 | for identity in value: |
| | 119 | list_.append(self.__names.setdefault(identity, identity)) |
| | 120 | self.setAttr('identities', list_) |
| 115 | | class CacheQuery(object): |
| 116 | | def __init__(cqself, proxied): |
| 117 | | cqself.proxied=proxied |
| 118 | | |
| 119 | | def __getattr__(cqself, obj): |
| 120 | | if obj!='exts': return getattr(cqself.proxied[0], obj) |
| 121 | | return set(chain(ci.features for ci in cqself.proxied)) |
| 122 | | |
| 123 | | def __getitem__(ciself, exts): |
| 124 | | if not exts: # (), [], None, False, whatever |
| 125 | | return ciself |
| 126 | | if isinstance(exts, basestring): |
| 127 | | exts=(exts,) |
| 128 | | if len(exts)==1: |
| 129 | | ext=exts[0] |
| 130 | | if ext in ciself.exts: |
| 131 | | return ciself.exts[ext] |
| 132 | | x=CacheItem(ciself.node, ciself.version, ext) |
| 133 | | ciself.exts[ext]=x |
| 134 | | return x |
| 135 | | proxied = [ciself] |
| 136 | | proxied.extend(ciself[(e,)] for e in exts) |
| 137 | | return ciself.CacheQuery(proxied) |
| 138 | | |
| 150 | | gajimnode = 'http://gajim.org/caps' |
| 151 | | |
| 152 | | gajimcaps=self[(gajimnode, '0.11.1')] |
| 153 | | gajimcaps.category='client' |
| 154 | | gajimcaps.type='pc' |
| 155 | | gajimcaps.features=set((xmpp.NS_BYTESTREAM, xmpp.NS_SI, |
| 156 | | xmpp.NS_FILE, xmpp.NS_MUC, xmpp.NS_COMMANDS, |
| 157 | | xmpp.NS_DISCO_INFO, xmpp.NS_PING, xmpp.NS_TIME_REVISED)) |
| 158 | | gajimcaps['cstates'].features=set((xmpp.NS_CHATSTATES,)) |
| 159 | | gajimcaps['xhtml'].features=set((xmpp.NS_XHTML_IM,)) |
| 160 | | |
| 161 | | # TODO: older gajim versions |
| | 139 | |
| | 140 | gajimcaps = self[('sha-1', gajim.caps_hash)] |
| | 141 | gajimcaps.identities = [gajim.gajim_identity] |
| | 142 | gajimcaps.features = gajim.gajim_common_features + \ |
| | 143 | gajim.gajim_optional_features |
| 169 | | for node, ver, ext, identities, features in self.logger.iter_caps_data(): |
| 170 | | x=self[(node, ver, ext)] |
| 171 | | x.identities=identities |
| 172 | | x.features=features |
| 173 | | x.queried=2 |
| | 151 | for hash_method, hash, identities, features in \ |
| | 152 | self.logger.iter_caps_data(): |
| | 153 | x = self[(hash_method, hash)] |
| | 154 | x.identities = identities |
| | 155 | x.features = features |
| | 156 | x.queried = 2 |
| 176 | | node_version = caps[:2] |
| 177 | | if node_version in self.__cache: |
| 178 | | return self.__cache[node_version][caps[2]] |
| 179 | | node, version = self.__names.setdefault(caps[0], caps[0]), caps[1] |
| 180 | | x=self.__CacheItem(node, version) |
| 181 | | self.__cache[(node, version)]=x |
| | 159 | if caps in self.__cache: |
| | 160 | return self.__cache[caps] |
| | 161 | hash_method, hash = caps[0], caps[1] |
| | 162 | x = self.__CacheItem(hash_method, hash) |
| | 163 | self.__cache[(hash_method, hash)] = x |
| 213 | | caps=presence.getTag('c') |
| 214 | | if not caps: return |
| 215 | | |
| 216 | | node, ver=caps['node'], caps['ver'] |
| 217 | | if node is None or ver is None: |
| | 187 | caps = presence.getTag('c') |
| | 188 | if not caps: |
| | 189 | return |
| | 190 | |
| | 191 | hash_method, node, hash = caps['hash'], caps['node'], caps['ver'] |
| | 192 | if hash_method is None or node is None or hash is None: |
| 248 | | contact=gajim.contacts.get_contact_from_full_jid(self.name, jid) |
| 249 | | if not contact: return |
| 250 | | if not contact.caps_node: return # we didn't asked for that? |
| 251 | | if not node.startswith(contact.caps_node+'#'): return |
| 252 | | node, ext = node.split('#', 1) |
| 253 | | if ext==contact.caps_ver: # this can be also version (like '0.9') |
| 254 | | exts=None |
| 255 | | else: |
| 256 | | exts=(ext,) |
| | 217 | contact = gajim.contacts.get_contact_from_full_jid(self.name, jid) |
| | 218 | if not contact: |
| | 219 | return |
| | 220 | if not contact.caps_node: |
| | 221 | return # we didn't asked for that? |
| | 222 | if not node.startswith(contact.caps_node + '#'): |
| | 223 | return |
| | 224 | node, hash = node.split('#', 1) |
| | 225 | computed_hash = helpers.compute_caps_hash(identities, features, |
| | 226 | contact.caps_hash_method) |
| | 227 | if computed_hash != hash: |
| | 228 | # wrong hash, forget it |
| | 229 | contact.caps_node = '' |
| | 230 | contact.caps_hash_method = '' |
| | 231 | contact.caps_hash = '' |
| | 232 | return |