From 3d4c7bf547f7b70fed35bb413e21cfbfc9462e3f Mon Sep 17 00:00:00 2001 From: Yann Leboulanger Date: Sun, 3 Jun 2007 14:00:09 +0000 Subject: [PATCH] [elghinn] fix entity time support (xep 90 and 202) --- src/common/connection.py | 8 ++-- src/common/connection_handlers.py | 80 +++++++++++++++++-------------- src/common/xmpp/protocol.py | 66 ++++++++++++------------- 3 files changed, 80 insertions(+), 74 deletions(-) diff --git a/src/common/connection.py b/src/common/connection.py index 00a17a54e..4910c3937 100644 --- a/src/common/connection.py +++ b/src/common/connection.py @@ -566,14 +566,14 @@ class Connection(ConnectionHandlers): iq = common.xmpp.Iq('get', to = pingTo.get_full_jid()) iq.addChild(name = 'ping', namespace = common.xmpp.NS_PING) def _on_response(resp): - timePong = time.time() + timePong = time_time() if not common.xmpp.isResultNode(resp): self.dispatch('PING_ERROR', (pingTo)) return timeDiff = round(timePong - timePing,2) self.dispatch('PING_REPLY', (pingTo, timeDiff)) self.dispatch('PING_SENT', (pingTo)) - timePing = time.time() + timePing = time_time() self.connection.SendAndCallForResponse(iq, _on_response) def get_active_default_lists(self): @@ -850,7 +850,7 @@ class Connection(ConnectionHandlers): ' ([This message is *encrypted* (See :JEP:`27`])' else: # Encryption failed, do not send message - tim = time.localtime() + tim = localtime() self.dispatch('MSGNOTSENT', (jid, error, msgtxt, tim)) return 3 if msgtxt and not xhtml and gajim.config.get( @@ -1264,7 +1264,7 @@ class Connection(ConnectionHandlers): self.connection.send(p) # Save the time we quit to avoid duplicate logs AND be faster than # get that date from DB - self.last_history_line[jid] = time.time() + self.last_history_line[jid] = time_time() def gc_set_role(self, room_jid, nick, role, reason = ''): '''role is for all the life of the room so it's based on nick''' diff --git a/src/common/connection_handlers.py b/src/common/connection_handlers.py index 4f8ae386e..6fa1bc894 100644 --- a/src/common/connection_handlers.py +++ b/src/common/connection_handlers.py @@ -18,13 +18,13 @@ ## import os -import time import base64 import sha import socket import sys -from time import localtime, strftime, gmtime +from time import (altzone, daylight, gmtime, localtime, mktime, strftime, + strptime, time as time_time, timezone, tzname) from calendar import timegm import socks5 @@ -412,7 +412,7 @@ class ConnectionBytestream: def _ResultCB(self, con, iq_obj): gajim.log.debug('_ResultCB') - # if we want to respect jep-0065 we have to check for proxy + # if we want to respect xep-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_': @@ -586,12 +586,12 @@ class ConnectionBytestream: 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, + '''According to XEP-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: + '''According to XEP-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) @@ -738,6 +738,9 @@ class ConnectionDisco: if (node is None or extension == 'xhtml') and not gajim.config.get('ignore_incoming_xhtml'): q.addChild('feature', attrs = {'var': common.xmpp.NS_XHTML_IM}) + if node is None: + q.addChild('feature', attrs = {'var': common.xmpp.NS_TIME_REVISED}) + if q.getChildren(): self.connection.send(iq) raise common.xmpp.NodeProcessed @@ -749,7 +752,7 @@ class ConnectionDisco: def _DiscoverInfoCB(self, con, iq_obj): gajim.log.debug('DiscoverInfoCB') - # According to JEP-0030: + # According to XEP-0030: # For identity: category, type is mandatory, name is optional. # For feature: var is mandatory identities, features, data = [], [], [] @@ -822,7 +825,7 @@ class ConnectionVcard: return p def add_caps(self, p): - ''' advertise our capabilities in presence stanza (jep-0115)''' + ''' advertise our capabilities in presence stanza (xep-0115)''' c = p.setTag('c', namespace = common.xmpp.NS_CAPS) c.setAttr('node', 'http://gajim.org/caps') ext = [] @@ -1034,7 +1037,7 @@ class ConnectionVcard: elif self.awaiting_answers[id][0] == METACONTACTS_ARRIVED: if iq_obj.getType() == 'result': # Metacontact tags - # http://www.jabber.org/jeps/jep-XXXX.html + # http://www.xmpp.org/extensions/xep-0209.html meta_list = {} query = iq_obj.getTag('query') storage = query.getTag('storage') @@ -1212,7 +1215,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, def _PrivateCB(self, con, iq_obj): ''' - Private Data (JEP 048 and 049) + Private Data (XEP 048 and 049) ''' gajim.log.debug('PrivateCB') query = iq_obj.getTag('query') @@ -1221,7 +1224,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, ns = storage.getNamespace() if ns == 'storage:bookmarks': # Bookmarked URLs and Conferences - # http://www.jabber.org/jeps/jep-0048.html + # http://www.xmpp.org/extensions/xep-0048.html confs = storage.getTags('conference') for conf in confs: autojoin_val = conf.getAttr('autojoin') @@ -1242,7 +1245,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, elif ns == 'gajim:prefs': # Preferences data - # http://www.jabber.org/jeps/jep-0049.html + # http://www.xmpp.org/extensions/xep-0049.html #TODO: implement this pass elif ns == 'storage:rosternotes': @@ -1262,7 +1265,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, ns = storage_tag.getNamespace() if ns == 'storage:metacontacts': self.metacontacts_supported = False - # Private XML Storage (JEP49) is not supported by server + # Private XML Storage (XEP49) is not supported by server # Continue connecting self.connection.initRoster() @@ -1335,18 +1338,21 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, gajim.log.debug('TimeCB') iq_obj = iq_obj.buildReply('result') qp = iq_obj.getTag('query') - qp.setTagData('utc', strftime("%Y%m%dT%T", gmtime())) - qp.setTagData('tz', strftime("%Z", gmtime())) - qp.setTagData('display', strftime("%c", localtime())) + qp.setTagData('utc', strftime('%Y%m%dT%T', gmtime())) + qp.setTagData('tz', tzname[daylight]) + qp.setTagData('display', strftime('%c', localtime())) self.connection.send(iq_obj) raise common.xmpp.NodeProcessed def _TimeRevisedCB(self, con, iq_obj): gajim.log.debug('TimeRevisedCB') iq_obj = iq_obj.buildReply('result') - qp = iq_obj.setTag('time') - qp.setTagData('utc', strftime("%Y-%m-%dT%TZ", gmtime())) - qp.setTagData('tzo', "%+03d:00"% (-time.timezone/(60*60))) + qp = iq_obj.setTag('time', + namespace=common.xmpp.NS_TIME_REVISED) + qp.setTagData('utc', strftime('%Y-%m-%dT%TZ', gmtime())) + zone = -(timezone, altzone)[daylight] / 60 + tzo = (zone / 60, abs(zone % 60)) + qp.setTagData('tzo', '%+03d:%02d' % (tzo)) self.connection.send(iq_obj) raise common.xmpp.NodeProcessed @@ -1408,8 +1414,8 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, 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)) + tim = strptime(tim, '%Y%m%dT%H:%M:%S') + tim = 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, @@ -1429,10 +1435,10 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, invite = None delayed = msg.getTag('x', namespace = common.xmpp.NS_DELAY) != None msg_id = None - composing_jep = None + composing_xep = 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 + # stanza (MUC XEP) 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: @@ -1441,22 +1447,22 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, return # chatstates - look for chatstate tags in a message if not delayed if not delayed: - composing_jep = False + composing_xep = False children = msg.getChildren() for child in children: if child.getNamespace() == 'http://jabber.org/protocol/chatstates': chatstate = child.getName() - composing_jep = 'JEP-0085' + composing_xep = 'XEP-0085' break - # No JEP-0085 support, fallback to JEP-0022 + # No XEP-0085 support, fallback to XEP-0022 if not chatstate: chatstate_child = msg.getTag('x', namespace = common.xmpp.NS_EVENT) if chatstate_child: chatstate = 'active' - composing_jep = 'JEP-0022' + composing_xep = 'XEP-0022' if not msgtxt and chatstate_child.getTag('composing'): chatstate = 'composing' - # JEP-0172 User Nickname + # XEP-0172 User Nickname user_nick = msg.getTagData('nick') if not user_nick: user_nick = '' @@ -1495,7 +1501,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, if not self.last_history_line.has_key(jid): return self.dispatch('GC_MSG', (frm, msgtxt, tim, has_timestamp, msghtml)) - if self.name not in no_log_for and not int(float(time.mktime(tim)))\ + if self.name not in no_log_for and not int(float(mktime(tim)))\ <= self.last_history_line[jid] and msgtxt: gajim.logger.write('gc_msg', frm, msgtxt, tim = tim) return @@ -1523,7 +1529,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, if treat_as: mtype = treat_as self.dispatch('MSG', (frm, msgtxt, tim, encrypted, mtype, - subject, chatstate, msg_id, composing_jep, user_nick, msghtml)) + subject, chatstate, msg_id, composing_xep, user_nick, msghtml)) # END messageCB def _pubsubEventCB(self, con, msg): @@ -1578,7 +1584,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, sigTag = None ns_muc_user_x = None avatar_sha = None - # JEP-0172 User Nickname + # XEP-0172 User Nickname user_nick = prs.getTagData('nick') if not user_nick: user_nick = '' @@ -1597,10 +1603,10 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, avatar_sha = x.getTagData('photo') contact_nickname = x.getTagData('nickname') elif namespace == common.xmpp.NS_DELAY: - # JEP-0091 + # XEP-0091 tim = prs.getTimestamp() - tim = time.strptime(tim, '%Y%m%dT%H:%M:%S') - timestamp = time.localtime(timegm(tim)) + tim = strptime(tim, '%Y%m%dT%H:%M:%S') + timestamp = localtime(timegm(tim)) elif namespace == 'http://delx.cjb.net/protocol/roster-subsync': # see http://trac.gajim.org/ticket/326 agent = gajim.get_server_from_jid(jid_stripped) @@ -1732,10 +1738,10 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, # detect a subscription loop if not self.subscribed_events.has_key(jid_stripped): self.subscribed_events[jid_stripped] = [] - self.subscribed_events[jid_stripped].append(time.time()) + self.subscribed_events[jid_stripped].append(time_time()) block = False if len(self.subscribed_events[jid_stripped]) > 5: - if time.time() - self.subscribed_events[jid_stripped][0] < 5: + if time_time() - self.subscribed_events[jid_stripped][0] < 5: block = True self.subscribed_events[jid_stripped] = self.subscribed_events[jid_stripped][1:] if block: @@ -1752,10 +1758,10 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, # detect a unsubscription loop if not self.subscribed_events.has_key(jid_stripped): self.subscribed_events[jid_stripped] = [] - self.subscribed_events[jid_stripped].append(time.time()) + self.subscribed_events[jid_stripped].append(time_time()) block = False if len(self.subscribed_events[jid_stripped]) > 5: - if time.time() - self.subscribed_events[jid_stripped][0] < 5: + if time_time() - self.subscribed_events[jid_stripped][0] < 5: block = True self.subscribed_events[jid_stripped] = self.subscribed_events[jid_stripped][1:] if block: diff --git a/src/common/xmpp/protocol.py b/src/common/xmpp/protocol.py index 6267e201a..0b549bd5b 100644 --- a/src/common/xmpp/protocol.py +++ b/src/common/xmpp/protocol.py @@ -21,71 +21,71 @@ xmpp-related data structures. from simplexml import Node,NodeBuilder,ustr import time -NS_ACTIVITY ='http://jabber.org/protocol/activity' # JEP-0108 -NS_ADDRESS ='http://jabber.org/protocol/address' # JEP-0033 +NS_ACTIVITY ='http://jabber.org/protocol/activity' # XEP-0108 +NS_ADDRESS ='http://jabber.org/protocol/address' # XEP-0033 NS_AGENTS ='jabber:iq:agents' NS_AMP ='http://jabber.org/protocol/amp' NS_AMP_ERRORS =NS_AMP+'#errors' NS_AUTH ='jabber:iq:auth' NS_BIND ='urn:ietf:params:xml:ns:xmpp-bind' NS_BROWSE ='jabber:iq:browse' -NS_BYTESTREAM ='http://jabber.org/protocol/bytestreams' # JEP-0065 -NS_CAPS ='http://jabber.org/protocol/caps' # JEP-0115 -NS_CHATSTATES ='http://jabber.org/protocol/chatstates' # JEP-0085 +NS_BYTESTREAM ='http://jabber.org/protocol/bytestreams' # XEP-0065 +NS_CAPS ='http://jabber.org/protocol/caps' # XEP-0115 +NS_CHATSTATES ='http://jabber.org/protocol/chatstates' # XEP-0085 NS_CLIENT ='jabber:client' NS_COMMANDS ='http://jabber.org/protocol/commands' NS_COMPONENT_ACCEPT='jabber:component:accept' NS_COMPONENT_1 ='http://jabberd.jabberstudio.org/ns/component/1.0' -NS_COMPRESS ='http://jabber.org/protocol/compress' # JEP-0138 +NS_COMPRESS ='http://jabber.org/protocol/compress' # XEP-0138 NS_CONFERENCE ='jabber:x:conference' -NS_DATA ='jabber:x:data' # JEP-0004 +NS_DATA ='jabber:x:data' # XEP-0004 NS_DELAY ='jabber:x:delay' NS_DIALBACK ='jabber:server:dialback' NS_DISCO ='http://jabber.org/protocol/disco' NS_DISCO_INFO =NS_DISCO+'#info' NS_DISCO_ITEMS =NS_DISCO+'#items' -NS_ENCRYPTED ='jabber:x:encrypted' # JEP-0027 -NS_EVENT ='jabber:x:event' # JEP-0022 +NS_ENCRYPTED ='jabber:x:encrypted' # XEP-0027 +NS_EVENT ='jabber:x:event' # XEP-0022 NS_FEATURE ='http://jabber.org/protocol/feature-neg' -NS_FILE ='http://jabber.org/protocol/si/profile/file-transfer' # JEP-0096 -NS_GEOLOC ='http://jabber.org/protocol/geoloc' # JEP-0080 +NS_FILE ='http://jabber.org/protocol/si/profile/file-transfer' # XEP-0096 +NS_GEOLOC ='http://jabber.org/protocol/geoloc' # XEP-0080 NS_GROUPCHAT ='gc-1.0' -NS_HTTP_AUTH ='http://jabber.org/protocol/http-auth' # JEP-0070 -NS_HTTP_BIND ='http://jabber.org/protocol/httpbind' # JEP-0124 +NS_HTTP_AUTH ='http://jabber.org/protocol/http-auth' # XEP-0070 +NS_HTTP_BIND ='http://jabber.org/protocol/httpbind' # XEP-0124 NS_IBB ='http://jabber.org/protocol/ibb' NS_INVISIBLE ='presence-invisible' # Jabberd2 NS_IQ ='iq' # Jabberd2 NS_LAST ='jabber:iq:last' NS_MESSAGE ='message' # Jabberd2 -NS_MOOD ='http://jabber.org/protocol/mood' # JEP-0107 +NS_MOOD ='http://jabber.org/protocol/mood' # XEP-0107 NS_MUC ='http://jabber.org/protocol/muc' NS_MUC_USER =NS_MUC+'#user' NS_MUC_ADMIN =NS_MUC+'#admin' NS_MUC_OWNER =NS_MUC+'#owner' -NS_NICK ='http://jabber.org/protocol/nick' # JEP-0172 -NS_OFFLINE ='http://www.jabber.org/jeps/jep-0030.html' # JEP-0013 -NS_PHYSLOC ='http://jabber.org/protocol/physloc' # JEP-0112 +NS_NICK ='http://jabber.org/protocol/nick' # XEP-0172 +NS_OFFLINE ='http://www.jabber.org/jeps/jep-0030.html' # XEP-0013 +NS_PHYSLOC ='http://jabber.org/protocol/physloc' # XEP-0112 NS_PRESENCE ='presence' # Jabberd2 NS_PRIVACY ='jabber:iq:privacy' NS_PRIVATE ='jabber:iq:private' -NS_PROFILE ='http://jabber.org/protocol/profile' # JEP-0154 -NS_PUBSUB ='http://jabber.org/protocol/pubsub' # JEP-0060 +NS_PROFILE ='http://jabber.org/protocol/profile' # XEP-0154 +NS_PUBSUB ='http://jabber.org/protocol/pubsub' # XEP-0060 NS_REGISTER ='jabber:iq:register' NS_ROSTER ='jabber:iq:roster' -NS_ROSTERX ='http://jabber.org/protocol/rosterx' # JEP-0144 -NS_RPC ='jabber:iq:rpc' # JEP-0009 +NS_ROSTERX ='http://jabber.org/protocol/rosterx' # XEP-0144 +NS_RPC ='jabber:iq:rpc' # XEP-0009 NS_SASL ='urn:ietf:params:xml:ns:xmpp-sasl' NS_SEARCH ='jabber:iq:search' NS_SERVER ='jabber:server' NS_SESSION ='urn:ietf:params:xml:ns:xmpp-session' -NS_SI ='http://jabber.org/protocol/si' # JEP-0096 -NS_SI_PUB ='http://jabber.org/protocol/sipub' # JEP-0137 -NS_SIGNED ='jabber:x:signed' # JEP-0027 +NS_SI ='http://jabber.org/protocol/si' # XEP-0096 +NS_SI_PUB ='http://jabber.org/protocol/sipub' # XEP-0137 +NS_SIGNED ='jabber:x:signed' # XEP-0027 NS_STANZAS ='urn:ietf:params:xml:ns:xmpp-stanzas' NS_STREAM ='http://affinix.com/jabber/stream' NS_STREAMS ='http://etherx.jabber.org/streams' -NS_TIME ='jabber:iq:time' # JEP-0900 -NS_TIME_REVISED ='http://www.xmpp.org/extensions/xep-0202.html#ns' # JEP-0202 +NS_TIME ='jabber:iq:time' # XEP-0900 +NS_TIME_REVISED ='urn:xmpp:time' # XEP-0202 NS_TLS ='urn:ietf:params:xml:ns:xmpp-tls' NS_VACATION ='http://jabber.org/protocol/vacation' NS_VCARD ='vcard-temp' @@ -94,11 +94,11 @@ NS_GTALKSETTING ='google:setting' NS_VCARD_UPDATE =NS_VCARD+':x:update' NS_VERSION ='jabber:iq:version' NS_PING ='urn:xmpp:ping' # XEP-0199 -NS_WAITINGLIST ='http://jabber.org/protocol/waitinglist' # JEP-0130 -NS_XHTML_IM ='http://jabber.org/protocol/xhtml-im' # JEP-0071 +NS_WAITINGLIST ='http://jabber.org/protocol/waitinglist' # XEP-0130 +NS_XHTML_IM ='http://jabber.org/protocol/xhtml-im' # XEP-0071 NS_XHTML = 'http://www.w3.org/1999/xhtml' # " -NS_DATA_LAYOUT ='http://jabber.org/protocol/xdata-layout' # JEP-0141 -NS_DATA_VALIDATE='http://jabber.org/protocol/xdata-validate' # JEP-0122 +NS_DATA_LAYOUT ='http://jabber.org/protocol/xdata-layout' # XEP-0141 +NS_DATA_VALIDATE='http://jabber.org/protocol/xdata-validate' # XEP-0122 NS_XMPP_STREAMS ='urn:ietf:params:xml:ns:xmpp-streams' xmpp_stream_error_conditions=""" @@ -422,7 +422,7 @@ class Message(Protocol): self.setTagData('body',val) def setXHTML(self,val,xmllang=None): - """ Sets the xhtml text of the message (JEP-0071). + """ Sets the xhtml text of the message (XEP-0071). The parameter is the "inner html" to the body.""" try: if xmllang: @@ -590,7 +590,7 @@ class Error(Protocol): class DataField(Node): """ This class is used in the DataForm class to describe the single data item. - If you are working with jabber:x:data (JEP-0004, JEP-0068, JEP-0122) + If you are working with jabber:x:data (XEP-0004, XEP-0068, XEP-0122) then you will need to work with instances of this class. """ def __init__(self,name=None,value=None,typ=None,required=0,desc=None,options=[],node=None): """ Create new data field of specified name,value and type. @@ -667,7 +667,7 @@ class DataField(Node): class DataForm(Node): """ DataForm class. Used for manipulating dataforms in XMPP. - Relevant JEPs: 0004, 0068, 0122. + Relevant XEPs: 0004, 0068, 0122. Can be used in disco, pub-sub and many other applications.""" def __init__(self, typ=None, data=[], title=None, node=None): """