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