# HG changeset patch # User Goffi # Date 1306607301 -7200 # Node ID ca3a041fed30f556c91211545a70c9bcf12aa10c # Parent e6047415868d0aca0b22eadf281756cea315a687 core: fixed several subscription scheme issues + removed most of profile_key default value in core.sat_main and core.xmmp (source of bugs) + contact update diff -r e6047415868d -r ca3a041fed30 src/core/sat_main.py --- a/src/core/sat_main.py Sat May 28 20:24:02 2011 +0200 +++ b/src/core/sat_main.py Sat May 28 20:28:21 2011 +0200 @@ -34,6 +34,7 @@ from twisted.internet import reactor from wokkel import compat +from wokkel.xmppim import RosterItem from sat.bridge.DBus import DBusBridge import logging @@ -128,6 +129,7 @@ self.bridge.register("setPresence", self.setPresence) self.bridge.register("subscription", self.subscription) self.bridge.register("addContact", self.addContact) + self.bridge.register("updateContact", self.updateContact) self.bridge.register("delContact", self.delContact) self.bridge.register("isConnected", self.isConnected) self.bridge.register("launchAction", self.launchAction) @@ -235,7 +237,7 @@ current.startService() - def disconnect(self, profile_key='@DEFAULT@'): + def disconnect(self, profile_key): """disconnect from jabber server""" if (not self.isConnected(profile_key)): info(_("not connected !")) @@ -322,7 +324,7 @@ else: self.actionResult(action_id, "SUPPRESS", {}) - def submitForm(self, action, target, fields, profile_key='@DEFAULT@'): + def submitForm(self, action, target, fields, profile_key): """submit a form @param target: target jid where we are submitting @param fields: list of tuples (name, value) @@ -351,12 +353,12 @@ ## Client management ## - def setParam(self, name, value, category, profile_key='@DEFAULT@'): + def setParam(self, name, value, category, profile_key): """set wanted paramater and notice observers""" info (_("setting param: %(name)s=%(value)s in category %(category)s") % {'name':name, 'value':value, 'category':category}) self.memory.setParam(name, value, category, profile_key) - def isConnected(self, profile_key='@DEFAULT@'): + def isConnected(self, profile_key): """Return connection status of profile @param profile_key: key_word or profile name to determine profile name @return True if connected @@ -369,7 +371,7 @@ return False return self.profiles[profile].isConnected() - def launchAction(self, type, data, profile_key='@DEFAULT@'): + def launchAction(self, type, data, profile_key): """Launch a specific action asked by client @param type: action type (button) @param data: needed data to launch the action @@ -429,7 +431,7 @@ int(priority), statuses, profile) - def subscription(self, subs_type, raw_jid, profile_key='@DEFAULT@'): + def subscription(self, subs_type, raw_jid, profile_key): """Called to manage subscription @param subs_type: subsciption type (cf RFC 3921) @param raw_jid: unicode entity's jid @@ -442,17 +444,12 @@ self.profiles[profile].presence.subscribe(to_jid) elif subs_type=="subscribed": self.profiles[profile].presence.subscribed(to_jid) - contact = self.memory.getContact(to_jid) - if not contact or not bool(contact['to']): #we automatically subscribe to 'to' presence - debug(_('sending automatic "to" subscription request')) - self.subscription('subscribe', to_jid.userhost()) elif subs_type=="unsubscribe": self.profiles[profile].presence.unsubscribe(to_jid) elif subs_type=="unsubscribed": self.profiles[profile].presence.unsubscribed(to_jid) - - def addContact(self, to, profile_key='@DEFAULT@'): + def addContact(self, to, profile_key): """Add a contact in roster list""" profile = self.memory.getProfileName(profile_key) assert(profile) @@ -460,7 +457,18 @@ #self.profiles[profile].roster.addItem(to_jid) XXX: disabled (cf http://wokkel.ik.nu/ticket/56)) self.profiles[profile].presence.subscribe(to_jid) - def delContact(self, to, profile_key='@DEFAULT@'): + def updateContact(self, to, name, groups, profile_key): + """update a contact in roster list""" + profile = self.memory.getProfileName(profile_key) + assert(profile) + to_jid = jid.JID(to) + groups = set(groups) + roster_item = RosterItem(to_jid) + roster_item.name = name or None + roster_item.groups = set(groups) + self.profiles[profile].roster.updateItem(roster_item) + + def delContact(self, to, profile_key): """Remove contact from roster list""" profile = self.memory.getProfileName(profile_key) assert(profile) diff -r e6047415868d -r ca3a041fed30 src/core/xmpp.py --- a/src/core/xmpp.py Sat May 28 20:24:02 2011 +0200 +++ b/src/core/xmpp.py Sat May 28 20:28:21 2011 +0200 @@ -139,6 +139,22 @@ #xmppim.RosterClientProtocol.addItem(self, to) #TODO: check IQ result""" + def updateItem(self, roster_item): + """ + Update an item of the contact list. + + @param roster_item: item to update + """ + iq = compat.IQ(self.xmlstream, 'set') + iq.addElement((xmppim.NS_ROSTER, 'query')) + item = iq.query.addElement('item') + item['jid'] = roster_item.jid.userhost() + if roster_item.name: + item['name'] = roster_item.name + for group in roster_item.groups: + item.addElement('group', content=group) + return iq.send() + def onRosterSet(self, item): """Called when a new/update roster item is received""" #TODO: send a signal to frontends @@ -206,25 +222,44 @@ statuses[None] = statuses['default'] del statuses['default'] xmppim.PresenceClientProtocol.available(self, entity, show, statuses, priority) - + + def subscribed(self, entity): + xmppim.PresenceClientProtocol.subscribed(self, entity) + self.host.memory.delWaitingSub(entity.userhost(), self.parent.profile) + contact = self.host.memory.getContact(entity, self.parent.profile) + if not contact or contact[0]['to'] == 'False': #we automatically subscribe to 'to' presence + debug(_('sending automatic "from" subscription request')) + self.subscribe(entity) + + def unsubscribed(self, entity): + xmppim.PresenceClientProtocol.unsubscribed(self, entity) + self.host.memory.delWaitingSub(entity.userhost(), self.parent.profile) + def subscribedReceived(self, entity): debug (_("subscription approved for [%s]") % entity.userhost()) - self.host.memory.delWaitingSub(entity.userhost(), self.parent.profile) self.host.bridge.subscribe('subscribed', entity.userhost(), self.parent.profile) def unsubscribedReceived(self, entity): debug (_("unsubscription confirmed for [%s]") % entity.userhost()) - self.host.memory.delWaitingSub(entity.userhost(), self.parent.profile) self.host.bridge.subscribe('unsubscribed', entity.userhost(), self.parent.profile) def subscribeReceived(self, entity): - debug (_("subscription request for [%s]") % entity.userhost()) - self.host.memory.addWaitingSub('subscribe', entity.userhost(), self.parent.profile) - self.host.bridge.subscribe('subscribe', entity.userhost(), self.parent.profile) + debug (_("subscription request from [%s]") % entity.userhost()) + contact = self.host.memory.getContact(entity, self.parent.profile) + if contact and contact[0]['to'] == 'True': + #We automatically accept subscription if we are already subscribed to contact presence + debug(_('sending automatic subscription acceptance')) + self.subscribed(entity) + else: + self.host.memory.addWaitingSub('subscribe', entity.userhost(), self.parent.profile) + self.host.bridge.subscribe('subscribe', entity.userhost(), self.parent.profile) def unsubscribeReceived(self, entity): debug (_("unsubscription asked for [%s]") % entity.userhost()) - self.host.memory.addWaitingSub('unsubscribe', entity.userhost(), self.parent.profile) + contact = self.host.memory.getContact(entity, self.parent.profile) + if contact and contact[0]['from'] == 'True': #we automatically remove contact + debug(_('automatic contact deletion')) + self.host.delContact(entity.userhost(), self.parent.profile) self.host.bridge.subscribe('unsubscribe', entity.userhost(), self.parent.profile) class SatDiscoProtocol(disco.DiscoClientProtocol): diff -r e6047415868d -r ca3a041fed30 src/tools/memory.py --- a/src/tools/memory.py Sat May 28 20:24:02 2011 +0200 +++ b/src/tools/memory.py Sat May 28 20:28:21 2011 +0200 @@ -291,7 +291,7 @@ return prof_xml - def getParamsUI(self, profile_key='@DEFAULT@'): + def getParamsUI(self, profile_key): """Return a SàT XMLUI for parameters, with given profile""" profile = self.getProfileName(profile_key) if not profile: @@ -300,7 +300,7 @@ param_xml = self.getParams(profile) return paramsXml2xmlUI(param_xml) - def getParams(self, profile_key='@DEFAULT@'): + def getParams(self, profile_key): """Construct xml for asked profile Take params xml as skeleton""" profile = self.getProfileName(profile_key) @@ -313,7 +313,7 @@ return return_xml - def getParamsForCategory(self, category, profile_key='@DEFAULT@'): + def getParamsForCategory(self, category, profile_key): """Return node's xml for selected category""" #TODO: manage category of general type (without existant profile) profile = self.getProfileName(profile_key) @@ -359,7 +359,7 @@ categories.append(cat.getAttribute("name")) return categories - def setParam(self, name, value, category, profile_key='@DEFAULT@'): + def setParam(self, name, value, category, profile_key): """Set a parameter, return None if the parameter is not in param xml""" profile = self.getProfileName(profile_key) if not profile: @@ -573,7 +573,7 @@ else: return list(entities)[0] if entities else None - def hasServerFeature(self, feature, profile_key='@DEFAULT@'): + def hasServerFeature(self, feature, profile_key): """Tell if the server of the profile has the required feature""" profile = self.getProfileName(profile_key) if not profile: @@ -583,7 +583,7 @@ return feature in self.server_features[profile] - def addContact(self, contact_jid, attributes, groups, profile_key='@DEFAULT@'): + def addContact(self, contact_jid, attributes, groups, profile_key): debug("Memory addContact: %s",contact_jid.userhost()) profile = self.getProfileName(profile_key) if not profile: @@ -595,7 +595,7 @@ self.contacts[profile] = {} self.contacts[profile][contact_jid.userhost()]=[attributes, groups] - def delContact(self, contact_jid, profile_key='@DEFAULT@'): + def delContact(self, contact_jid, profile_key): debug("Memory delContact: %s",contact_jid.userhost()) profile = self.getProfileName(profile_key) if not profile: @@ -604,17 +604,15 @@ if self.contacts.has_key(profile) and self.contacts[profile].has_key(contact_jid.userhost()): del self.contacts[profile][contact_jid.userhost()] - def getContact(self, contact_jid, profile_key='@DEFAULT@'): + def getContact(self, contact_jid, profile_key): profile = self.getProfileName(profile_key) if not profile: error(_('Asking a contact for a non-existant profile')) return None if self.contacts.has_key(profile) and self.contacts[profile].has_key(contact_jid.userhost()): - self.contacts[profile][contact_jid.userhost()] - else: - return None + return self.contacts[profile][contact_jid.userhost()] - def getContacts(self, profile_key='@DEFAULT@'): + def getContacts(self, profile_key): """Return list of contacts for given profile @param profile_key: profile key @return list of [contact, attr, groups]""" @@ -630,7 +628,7 @@ ret.append([contact, attr, groups ]) return ret - def addPresenceStatus(self, contact_jid, show, priority, statuses, profile_key='@DEFAULT@'): + def addPresenceStatus(self, contact_jid, show, priority, statuses, profile_key): profile = self.getProfileName(profile_key) if not profile: error(_('Trying to add presence status to a non-existant profile')) @@ -657,7 +655,7 @@ if self.subscriptions.has_key(profile) and self.subscriptions[profile].has_key(contact_jid): del self.subscriptions[profile][contact_jid] - def getWaitingSub(self, profile_key='@DEFAULT@'): + def getWaitingSub(self, profile_key): """Called to get a list of currently waiting subscription requests""" profile = self.getProfileName(profile_key) if not profile: @@ -668,7 +666,7 @@ return self.subscriptions[profile] - def getPresenceStatus(self, profile_key='@DEFAULT@'): + def getPresenceStatus(self, profile_key): profile = self.getProfileName(profile_key) if not profile: error(_('Asking contacts for a non-existant profile')) @@ -678,22 +676,22 @@ debug ("Memory getPresenceStatus (%s)", self.presenceStatus[profile]) return self.presenceStatus[profile] - def getParamA(self, name, category, attr="value", profile_key="@DEFAULT@"): + def getParamA(self, name, category, attr="value", profile_key='@DEFAULT@'): return self.params.getParamA(name, category, attr, profile_key) - def getParamsUI(self, profile_key='@DEFAULT@'): + def getParamsUI(self, profile_key): return self.params.getParamsUI(profile_key) - def getParams(self, profile_key='@DEFAULT@'): + def getParams(self, profile_key): return self.params.getParams(profile_key) - def getParamsForCategory(self, category, profile_key='@DEFAULT@'): + def getParamsForCategory(self, category, profile_key): return self.params.getParamsForCategory(category, profile_key) def getParamsCategories(self): return self.params.getParamsCategories() - def setParam(self, name, value, category, profile_key='@DEFAULT@'): + def setParam(self, name, value, category, profile_key): return self.params.setParam(name, value, category, profile_key) def importParams(self, xml):