Mercurial > libervia-backend
comparison sat/core/xmpp.py @ 2643:189e38fb11ff
core: style improvments (90 chars limit)
author | Goffi <goffi@goffi.org> |
---|---|
date | Sun, 29 Jul 2018 18:44:27 +0200 |
parents | 56f94936df1e |
children | f2cf1daa42cb |
comparison
equal
deleted
inserted
replaced
2642:755a0b8643bd | 2643:189e38fb11ff |
---|---|
52 # else, it's a deferred which fire on disconnection | 52 # else, it's a deferred which fire on disconnection |
53 self._connected = None | 53 self._connected = None |
54 self.profile = profile | 54 self.profile = profile |
55 self.host_app = host_app | 55 self.host_app = host_app |
56 self.cache = cache.Cache(host_app, profile) | 56 self.cache = cache.Cache(host_app, profile) |
57 self._mess_id_uid = {} # map from message id to uid used in history. Key: (full_jid,message_id) Value: uid | 57 self._mess_id_uid = {} # map from message id to uid used in history. |
58 # Key: (full_jid,message_id) Value: uid | |
58 self.conn_deferred = defer.Deferred() | 59 self.conn_deferred = defer.Deferred() |
59 self._progress_cb = {} # callback called when a progress is requested (key = progress id) | 60 self._progress_cb = {} # callback called when a progress is requested |
61 # (key = progress id) | |
60 self.actions = {} # used to keep track of actions for retrieval (key = action_id) | 62 self.actions = {} # used to keep track of actions for retrieval (key = action_id) |
61 | 63 |
62 ## initialisation ## | 64 ## initialisation ## |
63 | 65 |
64 @defer.inlineCallbacks | 66 @defer.inlineCallbacks |
111 | 113 |
112 @classmethod | 114 @classmethod |
113 @defer.inlineCallbacks | 115 @defer.inlineCallbacks |
114 def startConnection(cls, host, profile, max_retries): | 116 def startConnection(cls, host, profile, max_retries): |
115 """instantiate the entity and start the connection""" | 117 """instantiate the entity and start the connection""" |
116 # FIXME: reconnection doesn't seems to be handled correclty (client is deleted then recreated from scrash | 118 # FIXME: reconnection doesn't seems to be handled correclty |
117 # most of methods called here should be called once on first connection (e.g. adding subprotocols) | 119 # (client is deleted then recreated from scratch) |
118 # but client should not be deleted except if session is finished (independently of connection/deconnection | 120 # most of methods called here should be called once on first connection |
119 # | 121 # (e.g. adding subprotocols) |
122 # but client should not be deleted except if session is finished | |
123 # (independently of connection/deconnection) | |
120 try: | 124 try: |
121 port = int( | 125 port = int( |
122 host.memory.getParamA( | 126 host.memory.getParamA( |
123 C.FORCE_PORT_PARAM, "Connection", profile_key=profile | 127 C.FORCE_PORT_PARAM, "Connection", profile_key=profile |
124 ) | 128 ) |
162 | 166 |
163 yield entity.getConnectionDeferred() | 167 yield entity.getConnectionDeferred() |
164 | 168 |
165 yield defer.maybeDeferred(entity.entityConnected) | 169 yield defer.maybeDeferred(entity.entityConnected) |
166 | 170 |
167 # Call profileConnected callback for all plugins, and print error message if any of them fails | 171 # Call profileConnected callback for all plugins, |
172 # and print error message if any of them fails | |
168 conn_cb_list = [] | 173 conn_cb_list = [] |
169 for dummy, callback in plugin_conn_cb: | 174 for __, callback in plugin_conn_cb: |
170 conn_cb_list.append(defer.maybeDeferred(callback, entity)) | 175 conn_cb_list.append(defer.maybeDeferred(callback, entity)) |
171 list_d = defer.DeferredList(conn_cb_list) | 176 list_d = defer.DeferredList(conn_cb_list) |
172 | 177 |
173 def logPluginResults(results): | 178 def logPluginResults(results): |
174 all_succeed = all([success for success, result in results]) | 179 all_succeed = all([success for success, result in results]) |
191 | 196 |
192 def getConnectionDeferred(self): | 197 def getConnectionDeferred(self): |
193 """Return a deferred which fire when the client is connected""" | 198 """Return a deferred which fire when the client is connected""" |
194 return self.conn_deferred | 199 return self.conn_deferred |
195 | 200 |
196 def _disconnectionCb(self, dummy): | 201 def _disconnectionCb(self, __): |
197 self._connected = None | 202 self._connected = None |
198 | 203 |
199 def _disconnectionEb(self, failure_): | 204 def _disconnectionEb(self, failure_): |
200 log.error(_(u"Error while disconnecting: {}".format(failure_))) | 205 log.error(_(u"Error while disconnecting: {}".format(failure_))) |
201 | 206 |
217 self.streamInitialized() | 222 self.streamInitialized() |
218 self.host_app.bridge.connected( | 223 self.host_app.bridge.connected( |
219 self.profile, unicode(self.jid) | 224 self.profile, unicode(self.jid) |
220 ) # we send the signal to the clients | 225 ) # we send the signal to the clients |
221 | 226 |
222 def _finish_connection(self, dummy): | 227 def _finish_connection(self, __): |
223 self.conn_deferred.callback(None) | 228 self.conn_deferred.callback(None) |
224 | 229 |
225 def streamInitialized(self): | 230 def streamInitialized(self): |
226 """Called after _authd""" | 231 """Called after _authd""" |
227 log.debug(_(u"XML stream is initialized")) | 232 log.debug(_(u"XML stream is initialized")) |
281 self.conn_deferred.errback( | 286 self.conn_deferred.errback( |
282 error.StreamError(u"Server unexpectedly closed the connection") | 287 error.StreamError(u"Server unexpectedly closed the connection") |
283 ) | 288 ) |
284 | 289 |
285 @defer.inlineCallbacks | 290 @defer.inlineCallbacks |
286 def _cleanConnection(self, dummy): | 291 def _cleanConnection(self, __): |
287 """method called on disconnection | 292 """method called on disconnection |
288 | 293 |
289 used to call profileDisconnected* triggers | 294 used to call profileDisconnected* triggers |
290 """ | 295 """ |
291 trigger_name = "profileDisconnected" | 296 trigger_name = "profileDisconnected" |
378 | 383 |
379 @param post_xml_treatments(D): the same Deferred as in sendMessage trigger | 384 @param post_xml_treatments(D): the same Deferred as in sendMessage trigger |
380 """ | 385 """ |
381 raise NotImplementedError | 386 raise NotImplementedError |
382 | 387 |
383 def sendMessage( | 388 def sendMessage(self, to_jid, message, subject=None, mess_type="auto", extra=None, |
384 self, | 389 uid=None, no_trigger=False,): |
385 to_jid, | 390 r"""Send a message to an entity |
386 message, | |
387 subject=None, | |
388 mess_type="auto", | |
389 extra=None, | |
390 uid=None, | |
391 no_trigger=False, | |
392 ): | |
393 """Send a message to an entity | |
394 | 391 |
395 @param to_jid(jid.JID): destinee of the message | 392 @param to_jid(jid.JID): destinee of the message |
396 @param message(dict): message body, key is the language (use '' when unknown) | 393 @param message(dict): message body, key is the language (use '' when unknown) |
397 @param subject(dict): message subject, key is the language (use '' when unknown) | 394 @param subject(dict): message subject, key is the language (use '' when unknown) |
398 @param mess_type(str): one of standard message type (cf RFC 6121 §5.2.2) or: | 395 @param mess_type(str): one of standard message type (cf RFC 6121 §5.2.2) or: |
468 pre_xml_treatments, | 465 pre_xml_treatments, |
469 post_xml_treatments, | 466 post_xml_treatments, |
470 ): | 467 ): |
471 return defer.succeed(None) | 468 return defer.succeed(None) |
472 | 469 |
473 log.debug( | 470 log.debug(_(u"Sending message (type {type}, to {to})") |
474 _(u"Sending message (type {type}, to {to})").format( | 471 .format(type=data["type"], to=to_jid.full())) |
475 type=data["type"], to=to_jid.full() | 472 |
476 ) | 473 pre_xml_treatments.addCallback(lambda __: self.generateMessageXML(data)) |
477 ) | |
478 | |
479 pre_xml_treatments.addCallback(lambda dummy: self.generateMessageXML(data)) | |
480 pre_xml_treatments.chainDeferred(post_xml_treatments) | 474 pre_xml_treatments.chainDeferred(post_xml_treatments) |
481 post_xml_treatments.addCallback(self.sendMessageData) | 475 post_xml_treatments.addCallback(self.sendMessageData) |
482 if send_only: | 476 if send_only: |
483 log.debug( | 477 log.debug(_(u"Triggers, storage and echo have been inhibited by the " |
484 _( | 478 u"'send_only' parameter")) |
485 "Triggers, storage and echo have been inhibited by the 'send_only' parameter" | |
486 ) | |
487 ) | |
488 else: | 479 else: |
489 self.addPostXmlCallbacks(post_xml_treatments) | 480 self.addPostXmlCallbacks(post_xml_treatments) |
490 post_xml_treatments.addErrback(self._cancelErrorTrap) | 481 post_xml_treatments.addErrback(self._cancelErrorTrap) |
491 post_xml_treatments.addErrback(self.host_app.logErrback) | 482 post_xml_treatments.addErrback(self.host_app.logErrback) |
492 pre_xml_treatments.callback(data) | 483 pre_xml_treatments.callback(data) |
560 # XXX: DNS SRV records are checked when the host is not specified. | 551 # XXX: DNS SRV records are checked when the host is not specified. |
561 # If no SRV record is found, the host is directly extracted from the JID. | 552 # If no SRV record is found, the host is directly extracted from the JID. |
562 self.started = time.time() | 553 self.started = time.time() |
563 | 554 |
564 # Currently, we use "client/pc/Salut à Toi", but as | 555 # Currently, we use "client/pc/Salut à Toi", but as |
565 # SàT is multi-frontends and can be used on mobile devices, as a bot, with a web frontend, | 556 # SàT is multi-frontends and can be used on mobile devices, as a bot, |
566 # etc., we should implement a way to dynamically update identities through the bridge | 557 # with a web frontend, |
558 # etc., we should implement a way to dynamically update identities through the | |
559 # bridge | |
567 self.identities = [disco.DiscoIdentity(u"client", u"pc", C.APP_NAME)] | 560 self.identities = [disco.DiscoIdentity(u"client", u"pc", C.APP_NAME)] |
568 if sys.platform == "android": | 561 if sys.platform == "android": |
569 # FIXME: temporary hack as SRV is not working on android | 562 # FIXME: temporary hack as SRV is not working on android |
570 # TODO: remove this hack and fix SRV | 563 # TODO: remove this hack and fix SRV |
571 log.info(u"FIXME: Android hack, ignoring SRV") | 564 log.info(u"FIXME: Android hack, ignoring SRV") |
589 _(u"invalid data used for host: {data}").format(data=host_data) | 582 _(u"invalid data used for host: {data}").format(data=host_data) |
590 ) | 583 ) |
591 host_data = None | 584 host_data = None |
592 if host_data is not None: | 585 if host_data is not None: |
593 log.info( | 586 log.info( |
594 u"using {host}:{port} for host {host_ori} as requested in config".format( | 587 u"using {host}:{port} for host {host_ori} as requested in config" |
595 host_ori=user_jid.host, host=host, port=port | 588 .format(host_ori=user_jid.host, host=host, port=port) |
596 ) | |
597 ) | 589 ) |
598 | 590 |
599 wokkel_client.XMPPClient.__init__( | 591 wokkel_client.XMPPClient.__init__( |
600 self, user_jid, password, host or None, port or C.XMPP_C2S_PORT | 592 self, user_jid, password, host or None, port or C.XMPP_C2S_PORT |
601 ) | 593 ) |
632 # it is intended for things like end 2 end encryption. | 624 # it is intended for things like end 2 end encryption. |
633 # *DO NOT* cancel (i.e. return False) without very good reason | 625 # *DO NOT* cancel (i.e. return False) without very good reason |
634 # (out of band transmission for instance). | 626 # (out of band transmission for instance). |
635 # e2e should have a priority of 0 here, and out of band transmission | 627 # e2e should have a priority of 0 here, and out of band transmission |
636 # a lower priority | 628 # a lower priority |
637 # FIXME: trigger not used yet, can be uncommented when e2e full stanza encryption is implemented | 629 # FIXME: trigger not used yet, can be uncommented when e2e full stanza |
630 # encryption is implemented | |
638 # if not self.host_app.trigger.point("send", self, obj): | 631 # if not self.host_app.trigger.point("send", self, obj): |
639 # return | 632 # return |
640 super(SatXMPPClient, self).send(obj) | 633 super(SatXMPPClient, self).send(obj) |
641 | 634 |
642 def sendMessageData(self, mess_data): | 635 def sendMessageData(self, mess_data): |
646 The trigger can't be cancelled, it's a good place for e2e encryption which | 639 The trigger can't be cancelled, it's a good place for e2e encryption which |
647 don't handle full stanza encryption | 640 don't handle full stanza encryption |
648 @param mess_data(dict): message data as constructed by onMessage workflow | 641 @param mess_data(dict): message data as constructed by onMessage workflow |
649 @return (dict): mess_data (so it can be used in a deferred chain) | 642 @return (dict): mess_data (so it can be used in a deferred chain) |
650 """ | 643 """ |
651 # XXX: This is the last trigger before u"send" (last but one globally) for sending message. | 644 # XXX: This is the last trigger before u"send" (last but one globally) |
652 # This is intented for e2e encryption which doesn't do full stanza encryption (e.g. OTR) | 645 # for sending message. |
646 # This is intented for e2e encryption which doesn't do full stanza | |
647 # encryption (e.g. OTR) | |
653 # This trigger point can't cancel the method | 648 # This trigger point can't cancel the method |
654 self.host_app.trigger.point("sendMessageData", self, mess_data) | 649 self.host_app.trigger.point("sendMessageData", self, mess_data) |
655 self.send(mess_data[u"xml"]) | 650 self.send(mess_data[u"xml"]) |
656 return mess_data | 651 return mess_data |
657 | 652 |
673 mess_type=C.MESS_TYPE_INFO, | 668 mess_type=C.MESS_TYPE_INFO, |
674 extra={}, | 669 extra={}, |
675 profile=self.profile, | 670 profile=self.profile, |
676 ) | 671 ) |
677 | 672 |
678 def _finish_connection(self, dummy): | 673 def _finish_connection(self, __): |
679 self.roster.requestRoster() | 674 self.roster.requestRoster() |
680 self.presence.available() | 675 self.presence.available() |
681 super(SatXMPPClient, self)._finish_connection(dummy) | 676 super(SatXMPPClient, self)._finish_connection(__) |
682 | 677 |
683 | 678 |
684 class SatXMPPComponent(SatXMPPEntity, component.Component): | 679 class SatXMPPComponent(SatXMPPEntity, component.Component): |
685 """XMPP component | 680 """XMPP component |
686 | 681 |
694 "Component" | 689 "Component" |
695 ) # used for to distinguish some trigger points set in SatXMPPEntity | 690 ) # used for to distinguish some trigger points set in SatXMPPEntity |
696 is_component = True | 691 is_component = True |
697 sendHistory = ( | 692 sendHistory = ( |
698 False | 693 False |
699 ) # XXX: set to True from entry plugin to keep messages in history for received messages | 694 ) # XXX: set to True from entry plugin to keep messages in history for received |
695 # messages | |
700 | 696 |
701 def __init__( | 697 def __init__( |
702 self, | 698 self, |
703 host_app, | 699 host_app, |
704 profile, | 700 profile, |
746 @param plugins(list): list of validated plugins, will be filled by the method | 742 @param plugins(list): list of validated plugins, will be filled by the method |
747 give an empty list for first call | 743 give an empty list for first call |
748 @param required(bool): True if plugin is mandatory | 744 @param required(bool): True if plugin is mandatory |
749 for recursive calls only, should not be modified by inital caller | 745 for recursive calls only, should not be modified by inital caller |
750 @raise InternalError: one of the plugin is not handling components | 746 @raise InternalError: one of the plugin is not handling components |
751 @raise KeyError: one plugin should be present in self.host_app.plugins but it is not | 747 @raise KeyError: one plugin should be present in self.host_app.plugins but it |
748 is not | |
752 """ | 749 """ |
753 if C.PLUG_MODE_COMPONENT not in current._info[u"modes"]: | 750 if C.PLUG_MODE_COMPONENT not in current._info[u"modes"]: |
754 if not required: | 751 if not required: |
755 return | 752 return |
756 else: | 753 else: |
757 log.error( | 754 log.error( |
758 _( | 755 _( |
759 u"Plugin {current_name} is needed for {entry_name}, but it doesn't handle component mode" | 756 u"Plugin {current_name} is needed for {entry_name}, " |
757 u"but it doesn't handle component mode" | |
760 ).format( | 758 ).format( |
761 current_name=current._info[u"import_name"], | 759 current_name=current._info[u"import_name"], |
762 entry_name=self.entry_plugin._info[u"import_name"], | 760 entry_name=self.entry_plugin._info[u"import_name"], |
763 ) | 761 ) |
764 ) | 762 ) |
896 log.info(u"history is skipped as requested") | 894 log.info(u"history is skipped as requested") |
897 data[u"extra"][u"history"] = C.HISTORY_SKIP | 895 data[u"extra"][u"history"] = C.HISTORY_SKIP |
898 else: | 896 else: |
899 return self.host.memory.addToHistory(client, data) | 897 return self.host.memory.addToHistory(client, data) |
900 | 898 |
901 def bridgeSignal(self, dummy, client, data): | 899 def bridgeSignal(self, __, client, data): |
902 try: | 900 try: |
903 data["extra"]["received_timestamp"] = data["received_timestamp"] | 901 data["extra"]["received_timestamp"] = data["received_timestamp"] |
904 data["extra"]["delay_sender"] = data["delay_sender"] | 902 data["extra"]["delay_sender"] = data["delay_sender"] |
905 except KeyError: | 903 except KeyError: |
906 pass | 904 pass |
940 if not item.subscriptionTo and not item.subscriptionFrom and not item.ask: | 938 if not item.subscriptionTo and not item.subscriptionFrom and not item.ask: |
941 # XXX: current behaviour: we don't want contact in our roster list | 939 # XXX: current behaviour: we don't want contact in our roster list |
942 # if there is no presence subscription | 940 # if there is no presence subscription |
943 # may change in the future | 941 # may change in the future |
944 log.info( | 942 log.info( |
945 u"Removing contact {} from roster because there is no presence subscription".format( | 943 u"Removing contact {} from roster because there is no presence " |
944 u"subscription".format( | |
946 item.jid | 945 item.jid |
947 ) | 946 ) |
948 ) | 947 ) |
949 self.removeItem(item.entity) # FIXME: to be checked | 948 self.removeItem(item.entity) # FIXME: to be checked |
950 else: | 949 else: |
957 @param item (RosterIem): item added | 956 @param item (RosterIem): item added |
958 """ | 957 """ |
959 log.debug(u"registering item: {}".format(item.entity.full())) | 958 log.debug(u"registering item: {}".format(item.entity.full())) |
960 if item.entity.resource: | 959 if item.entity.resource: |
961 log.warning( | 960 log.warning( |
962 u"Received a roster item with a resource, this is not common but not restricted by RFC 6121, this case may be not well tested." | 961 u"Received a roster item with a resource, this is not common but not " |
962 u"restricted by RFC 6121, this case may be not well tested." | |
963 ) | 963 ) |
964 if not item.subscriptionTo: | 964 if not item.subscriptionTo: |
965 if not item.subscriptionFrom: | 965 if not item.subscriptionFrom: |
966 log.info( | 966 log.info( |
967 _(u"There's no subscription between you and [{}]!").format( | 967 _(u"There's no subscription between you and [{}]!").format( |
1042 jids_set.remove(entity) | 1042 jids_set.remove(entity) |
1043 if not jids_set: | 1043 if not jids_set: |
1044 del self._groups[group] | 1044 del self._groups[group] |
1045 except KeyError: | 1045 except KeyError: |
1046 log.warning( | 1046 log.warning( |
1047 u"there is no cache for the group [%(group)s] of the removed roster item [%(jid)s]" | 1047 u"there is no cache for the group [{group}] of the removed roster " |
1048 % {"group": group, "jid": entity} | 1048 u"item [{jid_}]".format(group=group, jid=entity) |
1049 ) | 1049 ) |
1050 | 1050 |
1051 # then we send the bridge signal | 1051 # then we send the bridge signal |
1052 self.host.bridge.contactDeleted(entity.full(), self.parent.profile) | 1052 self.host.bridge.contactDeleted(entity.full(), self.parent.profile) |
1053 | 1053 |
1137 presence_d.addCallback(lambda __: super(SatPresenceProtocol, self).send(obj)) | 1137 presence_d.addCallback(lambda __: super(SatPresenceProtocol, self).send(obj)) |
1138 | 1138 |
1139 def availableReceived(self, entity, show=None, statuses=None, priority=0): | 1139 def availableReceived(self, entity, show=None, statuses=None, priority=0): |
1140 log.debug( | 1140 log.debug( |
1141 _( | 1141 _( |
1142 u"presence update for [%(entity)s] (available, show=%(show)s statuses=%(statuses)s priority=%(priority)d)" | 1142 u"presence update for [{entity}] (available, show={show} " |
1143 u"statuses={statuses} priority={priority})" | |
1143 ) | 1144 ) |
1144 % { | 1145 .format( |
1145 "entity": entity, | 1146 entity=entity, |
1146 C.PRESENCE_SHOW: show, | 1147 show=show, |
1147 C.PRESENCE_STATUSES: statuses, | 1148 statuses=statuses, |
1148 C.PRESENCE_PRIORITY: priority, | 1149 priority=priority, |
1149 } | 1150 ) |
1150 ) | 1151 ) |
1151 | 1152 |
1152 if not statuses: | 1153 if not statuses: |
1153 statuses = {} | 1154 statuses = {} |
1154 | 1155 |
1185 "presenceReceived", entity, "unavailable", 0, statuses, self.parent.profile | 1186 "presenceReceived", entity, "unavailable", 0, statuses, self.parent.profile |
1186 ): | 1187 ): |
1187 return | 1188 return |
1188 | 1189 |
1189 # now it's time to notify frontends | 1190 # now it's time to notify frontends |
1190 # if the entity is not known yet in this session or is already unavailable, there is no need to send an unavailable signal | 1191 # if the entity is not known yet in this session or is already unavailable, |
1192 # there is no need to send an unavailable signal | |
1191 try: | 1193 try: |
1192 presence = self.host.memory.getEntityDatum( | 1194 presence = self.host.memory.getEntityDatum( |
1193 entity, "presence", self.parent.profile | 1195 entity, "presence", self.parent.profile |
1194 ) | 1196 ) |
1195 except (KeyError, exceptions.UnknownEntityError): | 1197 except (KeyError, exceptions.UnknownEntityError): |
1273 def subscribeReceived(self, entity): | 1275 def subscribeReceived(self, entity): |
1274 log.debug(_(u"subscription request from [%s]") % entity.userhost()) | 1276 log.debug(_(u"subscription request from [%s]") % entity.userhost()) |
1275 yield self.parent.roster.got_roster | 1277 yield self.parent.roster.got_roster |
1276 item = self.parent.roster.getItem(entity) | 1278 item = self.parent.roster.getItem(entity) |
1277 if item and item.subscriptionTo: | 1279 if item and item.subscriptionTo: |
1278 # We automatically accept subscription if we are already subscribed to contact presence | 1280 # We automatically accept subscription if we are already subscribed to |
1281 # contact presence | |
1279 log.debug(_("sending automatic subscription acceptance")) | 1282 log.debug(_("sending automatic subscription acceptance")) |
1280 self.subscribed(entity) | 1283 self.subscribed(entity) |
1281 else: | 1284 else: |
1282 self.host.memory.addWaitingSub( | 1285 self.host.memory.addWaitingSub( |
1283 "subscribe", entity.userhost(), self.parent.profile | 1286 "subscribe", entity.userhost(), self.parent.profile |
1312 log.debug(u"iqFallback: xml = [%s]" % (iq.toXml())) | 1315 log.debug(u"iqFallback: xml = [%s]" % (iq.toXml())) |
1313 generic.FallbackHandler.iqFallback(self, iq) | 1316 generic.FallbackHandler.iqFallback(self, iq) |
1314 | 1317 |
1315 | 1318 |
1316 class SatVersionHandler(generic.VersionHandler): | 1319 class SatVersionHandler(generic.VersionHandler): |
1320 | |
1317 def getDiscoInfo(self, requestor, target, node): | 1321 def getDiscoInfo(self, requestor, target, node): |
1318 # XXX: We need to work around wokkel's behaviour (namespace not added if there is a | 1322 # XXX: We need to work around wokkel's behaviour (namespace not added if there |
1319 # node) as it cause issues with XEP-0115 & PEP (XEP-0163): there is a node when server | 1323 # is a node) as it cause issues with XEP-0115 & PEP (XEP-0163): there is a |
1320 # ask for disco info, and not when we generate the key, so the hash is used with different | 1324 # node when server ask for disco info, and not when we generate the key, so |
1321 # disco features, and when the server (seen on ejabberd) generate its own hash for security check | 1325 # the hash is used with different disco features, and when the server (seen |
1322 # it reject our features (resulting in e.g. no notification on PEP) | 1326 # on ejabberd) generate its own hash for security check it reject our |
1327 # features (resulting in e.g. no notification on PEP) | |
1323 return generic.VersionHandler.getDiscoInfo(self, requestor, target, None) | 1328 return generic.VersionHandler.getDiscoInfo(self, requestor, target, None) |
1324 | 1329 |
1325 | 1330 |
1326 class SatIdentityHandler(XMPPHandler): | 1331 class SatIdentityHandler(XMPPHandler): |
1327 """ Manage disco Identity of SàT. | 1332 """Manage disco Identity of SàT.""" |
1328 | |
1329 """ | |
1330 | |
1331 # TODO: dynamic identity update (see docstring). Note that a XMPP entity can have several identities | |
1332 implements(iwokkel.IDisco) | 1333 implements(iwokkel.IDisco) |
1334 # TODO: dynamic identity update (see docstring). Note that a XMPP entity can have | |
1335 # several identities | |
1333 | 1336 |
1334 def getDiscoInfo(self, requestor, target, nodeIdentifier=""): | 1337 def getDiscoInfo(self, requestor, target, nodeIdentifier=""): |
1335 return self.parent.identities | 1338 return self.parent.identities |
1336 | 1339 |
1337 def getDiscoItems(self, requestor, target, nodeIdentifier=""): | 1340 def getDiscoItems(self, requestor, target, nodeIdentifier=""): |