changeset 1076fc9700f5 in /home/hg/repos/gajim

details:http://hg.gajim.org/gajim?cmd=changeset;node=1076fc9700f5
description: merge elghinn's branch (roster versioning) to trunk. Fixes #4661, 
#3190

diffstat:

 src/common/check_paths.py         |   16 ++++
 src/common/config.py              |    1 +
 src/common/connection.py          |    5 +
 src/common/connection_handlers.py |   38 ++++++++-
 src/common/logger.py              |  137 ++++++++++++++++++++++++++++++++++
 src/common/optparser.py           |   37 +++++++++
 src/common/xmpp/client_nb.py      |    8 +-
 src/common/xmpp/roster_nb.py      |   35 ++++++--
 src/config.py                     |    1 +
 src/gajim.py                      |    2 +
 10 files changed, 263 insertions(+), 17 deletions(-)

diffs (truncated from 497 to 300 lines):

diff -r a736d5846aab -r 1076fc9700f5 src/common/check_paths.py
--- a/src/common/check_paths.py Thu Jul 09 19:06:08 2009 +0200
+++ b/src/common/check_paths.py Fri Jul 10 15:05:01 2009 +0200
@@ -96,6 +96,22 @@
                        jid_id INTEGER PRIMARY KEY UNIQUE,
                        time INTEGER
                );
+
+               CREATE TABLE IF NOT EXISTS roster_entry(
+                       account_jid_id INTEGER,
+                       jid_id INTEGER,
+                       name TEXT,
+                       subscription INTEGER,
+                       ask BOOLEAN,
+                       PRIMARY KEY (account_jid_id, jid_id)
+               );
+
+               CREATE TABLE IF NOT EXISTS roster_group(
+                       account_jid_id INTEGER,
+                       jid_id INTEGER,
+                       group_name TEXT,
+                       PRIMARY KEY (account_jid_id, jid_id, group_name)
+               );
                '''
                )
 
diff -r a736d5846aab -r 1076fc9700f5 src/common/config.py
--- a/src/common/config.py      Thu Jul 09 19:06:08 2009 +0200
+++ b/src/common/config.py      Fri Jul 10 15:05:01 2009 +0200
@@ -336,6 +336,7 @@
                        'ignore_unknown_contacts': [ opt_bool, False ],
                        'send_os_info': [ opt_bool, True ],
                        'log_encrypted_sessions': [opt_bool, True, _('When 
negotiating an encrypted session, should Gajim assume you want your messages to 
be logged?')],
+                       'roster_version': [opt_str, ''],
                }, {}),
                'statusmsg': ({
                        'message': [ opt_str, '' ],
diff -r a736d5846aab -r 1076fc9700f5 src/common/connection.py
--- a/src/common/connection.py  Thu Jul 09 19:06:08 2009 +0200
+++ b/src/common/connection.py  Fri Jul 10 15:05:01 2009 +0200
@@ -1970,6 +1970,11 @@
 
                self.connection.SendAndCallForResponse(iq, _on_response)
 
+       def load_roster_from_db(self):
+               roster = 
gajim.logger.get_roster(gajim.get_jid_from_account(self.name))
+               self.dispatch('ROSTER', roster)
+
+
 # END Connection
 
 # vim: se ts=3:
diff -r a736d5846aab -r 1076fc9700f5 src/common/connection_handlers.py
--- a/src/common/connection_handlers.py Thu Jul 09 19:06:08 2009 +0200
+++ b/src/common/connection_handlers.py Fri Jul 10 15:05:01 2009 +0200
@@ -65,6 +65,7 @@
 VCARD_ARRIVED = 'vcard_arrived'
 AGENT_REMOVED = 'agent_removed'
 METACONTACTS_ARRIVED = 'metacontacts_arrived'
+ROSTER_ARRIVED = 'roster_arrived'
 PRIVACY_ARRIVED = 'privacy_arrived'
 PEP_CONFIG = 'pep_config'
 HAS_IDLE = True
@@ -1172,7 +1173,18 @@
                                if iq_obj.getErrorCode() not in ('403', '406', 
'404'):
                                        self.private_storage_supported = False
                        # We can now continue connection by requesting the 
roster
-                       self.connection.initRoster()
+                       version = gajim.config.get_per('accounts', self.name,
+                               'roster_version')
+                       iq_id = self.connection.initRoster(version=version)
+                       self.awaiting_answers[iq_id] = (ROSTER_ARRIVED, )
+               elif self.awaiting_answers[id_][0] == ROSTER_ARRIVED:
+                       if iq_obj.getType() == 'result':
+                               if not iq_obj.getTag('query'):
+                                       account_jid = 
gajim.get_jid_from_account(self.name)
+                                       roster_data = 
gajim.logger.get_roster(account_jid)
+                                       roster = 
self.connection.getRoster(force=True)
+                                       roster.setRaw(roster_data)
+                               self._getRoster()
                elif self.awaiting_answers[id_][0] == PRIVACY_ARRIVED:
                        if iq_obj.getType() != 'error':
                                self.privacy_rules_supported = True
@@ -1556,6 +1568,7 @@
 
        def _rosterSetCB(self, con, iq_obj):
                log.debug('rosterSetCB')
+               version = iq_obj.getTagAttr('query', 'ver')
                for item in iq_obj.getTag('query').getChildren():
                        try:
                                jid = helpers.parse_jid(item.getAttr('jid'))
@@ -1569,6 +1582,12 @@
                        for group in item.getTags('group'):
                                groups.append(group.getData())
                        self.dispatch('ROSTER_INFO', (jid, name, sub, ask, 
groups))
+                       account_jid = gajim.get_jid_from_account(self.name)
+                       gajim.logger.add_or_update_contact(account_jid, jid, 
name, sub, ask,
+                               groups)
+                       if version:
+                               gajim.config.set_per('accounts', self.name, 
'roster_version',
+                                       version)
                if not self.connection or self.connected < 2:
                        raise common.xmpp.NodeProcessed
                reply = common.xmpp.Iq(typ='result', attrs={'id': 
iq_obj.getID()},
@@ -2484,7 +2503,7 @@
                self.connection.send(result)
                raise common.xmpp.NodeProcessed
 
-       def _getRosterCB(self, con, iq_obj):
+       def _getRoster(self):
                log.debug('getRosterCB')
                if not self.connection:
                        return
@@ -2507,6 +2526,8 @@
                                gajim.proxy65_manager.resolve(proxy, 
self.connection, our_jid)
 
        def _on_roster_set(self, roster):
+               roster_version = roster.version
+               received_from_server = roster.received_from_server
                raw_roster = roster.getRaw()
                roster = {}
                our_jid = 
helpers.parse_jid(gajim.get_jid_from_account(self.name))
@@ -2545,7 +2566,16 @@
                                                # we can't determine which 
iconset to use
                                                self.discoverInfo(jid)
 
-               self.dispatch('ROSTER', roster)
+               gajim.logger.replace_roster(self.name, roster_version, roster)
+               if received_from_server:
+                       for contact in gajim.contacts.iter_contacts(self.name):
+                               if not contact.is_groupchat() and contact.jid 
not in roster:
+                                       self.dispatch('ROSTER_INFO', (self.name,
+                                               (contact.jid, None, None, None, 
())))
+                       for jid in roster:
+                               self.dispatch('ROSTER_INFO', (jid, 
roster[jid]['name'],
+                                       roster[jid]['subscription'], 
roster[jid]['ask'],
+                                       roster[jid]['groups']))
 
        def _send_first_presence(self, signed = ''):
                show = self.continue_connect_info[0]
@@ -2689,8 +2719,6 @@
                        common.xmpp.NS_MUC_OWNER)
                con.RegisterHandler('iq', self._MucAdminCB, 'result',
                        common.xmpp.NS_MUC_ADMIN)
-               con.RegisterHandler('iq', self._getRosterCB, 'result',
-                       common.xmpp.NS_ROSTER)
                con.RegisterHandler('iq', self._PrivateCB, 'result',
                        common.xmpp.NS_PRIVATE)
                con.RegisterHandler('iq', self._HttpAuthCB, 'get',
diff -r a736d5846aab -r 1076fc9700f5 src/common/logger.py
--- a/src/common/logger.py      Thu Jul 09 19:06:08 2009 +0200
+++ b/src/common/logger.py      Fri Jul 10 15:05:01 2009 +0200
@@ -92,6 +92,13 @@
                        self.TYPE_MRIM,
                ) = range(14)
 
+               (
+                       self.SUBSCRIPTION_NONE,
+                       self.SUBSCRIPTION_TO,
+                       self.SUBSCRIPTION_FROM,
+                       self.SUBSCRIPTION_BOTH,
+               ) = range(4)
+
 constants = Constants()
 
 class Logger:
@@ -331,6 +338,28 @@
                if type_id == constants.TYPE_MRIM:
                        return 'mrim'
 
+       def convert_human_subscription_values_to_db_api_values(self, sub):
+               '''converts from string style to constant ints for db'''
+               if sub == 'none':
+                       return constants.SUBSCRIPTION_NONE
+               if sub == 'to':
+                       return constants.SUBSCRIPTION_TO
+               if sub == 'from':
+                       return constants.SUBSCRIPTION_FROM
+               if sub == 'both':
+                       return constants.SUBSCRIPTION_BOTH
+
+       def convert_db_api_values_to_human_subscription_values(self, sub):
+               '''converts from constant ints for db to string style'''
+               if sub == constants.SUBSCRIPTION_NONE:
+                       return 'none'
+               if sub == constants.SUBSCRIPTION_TO:
+                       return 'to'
+               if sub == constants.SUBSCRIPTION_FROM:
+                       return 'from'
+               if sub == constants.SUBSCRIPTION_BOTH:
+                       return 'both'
+
        def commit_to_db(self, values, write_unread = False):
                sql = 'INSERT INTO logs (jid_id, contact_name, time, kind, 
show, message, subject) VALUES (?, ?, ?, ?, ?, ?, ?)'
                try:
@@ -799,4 +828,112 @@
                except sqlite.OperationalError, e:
                        print >> sys.stderr, str(e)
 
+       def replace_roster(self, account_name, roster_version, roster):
+               ''' Replace current roster in DB by a new one.
+               accout_name is the name of the account to change
+               roster_version is the version of the new roster
+               roster is the new version '''
+               gajim.config.set_per('accounts', account_name, 
'roster_version', '')
+               account_jid = gajim.get_jid_from_account(account_name)
+               account_jid_id = self.get_jid_id(account_jid)
+
+               # Delete old roster
+               sql = 'DELETE FROM roster_entry WHERE account_jid_id = %d' % (
+                       account_jid_id)
+               sql = 'DELETE FROM roster_group WHERE account_jid_id = %d' % (
+                       account_jid_id)
+
+               # Fill roster tables with the new roster
+               for jid in roster:
+                       self.add_or_update_contact(account_jid, jid, 
roster[jid]['name'],
+                               roster[jid]['subscription'], roster[jid]['ask'],
+                               roster[jid]['groups'])
+               gajim.config.set_per('accounts', account_name, 'roster_version',
+                       roster_version)
+
+       def del_contact(self, account_jid, jid):
+               ''' Remove jid from account_jid roster. '''
+               try:
+                       account_jid_id = self.get_jid_id(account_jid)
+                       jid_id = self.get_jid_id(jid)
+               except exceptions.PysqliteOperationalError, e:
+                       raise exceptions.PysqliteOperationalError(str(e))
+               sql = 'DELETE FROM roster_group WHERE account_jid_id=%d AND 
jid_id=%d' % (account_jid_id, jid_id)
+               self.cur.execute(sql)
+               sql = 'DELETE FROM roster_entry WHERE account_jid_id=%d AND 
jid_id=%d' % (account_jid_id, jid_id)
+               self.simple_commit(sql)
+
+       def add_or_update_contact(self, account_jid, jid, name, sub, ask, 
groups):
+               ''' Add or update a contact from account_jid roster. '''
+               if sub == 'remove':
+                       self.del_contact(account_jid, jid)
+                       return
+
+               try:
+                       account_jid_id = self.get_jid_id(account_jid)
+                       jid_id = self.get_jid_id(jid)
+               except exceptions.PysqliteOperationalError, e:
+                       raise exceptions.PysqliteOperationalError(str(e))
+
+               # Update groups information
+               # First we delete all previous groups information
+               sql = 'DELETE FROM roster_group WHERE account_jid_id=%d AND 
jid_id=%d' % (account_jid_id, jid_id)
+               self.cur.execute(sql)
+               # Then we add all new groups information
+               for group in groups:
+                       sql = 'INSERT INTO roster_group VALUES("%d", "%d", 
"%s")' % (
+                               account_jid_id, jid_id, group)
+                       self.cur.execute(sql)
+
+               if name is None:
+                       name = ''
+
+               sql = 'REPLACE INTO roster_entry VALUES("%d", "%d", "%s", "%s", 
"%d")'\
+                       % (account_jid_id, jid_id, name,
+                       
self.convert_human_subscription_values_to_db_api_values(sub),
+                       bool(ask))
+               self.simple_commit(sql)
+
+       def get_roster(self, account_jid):
+               ''' Return the accound_jid roster in NonBlockingRoster format. 
'''
+               data = {}
+               account_jid_id = self.get_jid_id(account_jid)
+
+               # First we fill data with roster_entry informations
+               self.cur.execute('SELECT j.jid, re.jid_id, re.name, 
re.subscription, re.ask FROM roster_entry re, jids j WHERE 
re.account_jid_id="%(account_jid_id)s" AND j.jid_id=re.jid_id' % 
{'account_jid_id': account_jid_id})
+               for jid, jid_id, name, subscription, ask in self.cur:
+                       data[jid] = {}
+                       if name:
+                               data[jid]['name'] = name
+                       else:
+                               data[jid]['name'] = None
+                       data[jid]['subscription'] = 
self.convert_db_api_values_to_human_subscription_values(subscription)
+                       data[jid]['groups'] = []
+                       data[jid]['resources'] = {}
+                       if ask:
+                               data[jid]['ask'] = 'subscribe'
+                       else:
+                               data[jid]['ask'] = None
+                       data[jid]['id'] = jid_id
+
+               # Then we add group for roster entries
+               for jid in data:
+                       self.cur.execute('SELECT group_name FROM roster_group 
WHERE account_jid_id="%(account_jid_id)s" AND jid_id="%(jid_id)s"' % 
{'account_jid_id': account_jid_id, 'jid_id': data[jid]['id']})
+                       for (group_name,) in self.cur:
+                               data[jid]['groups'].append(group_name)
+                       del data[jid]['id']
+
+               return data
+
+       def remove_roster(self, account_jid):
+               account_jid_id = self.get_jid_id(account_jid)
+
+               sql = 'DELETE FROM roster_group WHERE account_jid_id=%d' % (
_______________________________________________
Commits mailing list
[email protected]
http://lists.gajim.org/cgi-bin/listinfo/commits

Reply via email to