diff --git a/core/core.py b/core/core.py index df500d0b4..20a4e8aeb 100644 --- a/core/core.py +++ b/core/core.py @@ -22,6 +22,7 @@ import sys, os, time, string, logging import common.hub, common.optparser import common.jabber import socket, select, pickle +import GnuPGInterface from common import i18n @@ -47,6 +48,142 @@ def XMLunescape(txt): txt = txt.replace("&", "&") return txt +class MyGnuPG(GnuPGInterface.GnuPG): + def __init__(self): + GnuPGInterface.GnuPG.__init__(self) + self.setup_my_options() + + def setup_my_options(self): + self.options.armor = 1 + self.options.meta_interactive = 0 + self.options.extra_args.append('--no-secmem-warning') + + def _read_response(self, child_stdout): + # Internal method: reads all the output from GPG, taking notice + # only of lines that begin with the magic [GNUPG:] prefix. + # (See doc/DETAILS in the GPG distribution for info on GPG's + # output when --status-fd is specified.) + # + # Returns a dictionary, mapping GPG's keywords to the arguments + # for that keyword. + + resp = {} + while 1: + line = child_stdout.readline() + if line == "": break + line = string.rstrip( line ) + if line[0:9] == '[GNUPG:] ': + # Chop off the prefix + line = line[9:] + L = string.split(line, None, 1) + keyword = L[0] + if len(L) > 1: + resp[ keyword ] = L[1] + else: + resp[ keyword ] = "" + return resp + + def encrypt(self, string, recipients): + self.options.recipients = recipients # a list! + + proc = self.run(['--encrypt'], create_fhs=['stdin', 'stdout']) + proc.handles['stdin'].write(string) + proc.handles['stdin'].close() + + output = proc.handles['stdout'].read() + proc.handles['stdout'].close() + + try: proc.wait() + except IOError: pass + return self.stripHeaderFooter(output) + + def decrypt(self, string, keyID): + proc = self.run(['--decrypt', '-q', '-u %s'%keyID], create_fhs=['stdin', 'stdout', 'status']) + enc = self.addHeaderFooter(string, 'MESSAGE') + proc.handles['stdin'].write(enc) + proc.handles['stdin'].close() + + output = proc.handles['stdout'].read() + proc.handles['stdout'].close() + + resp = proc.handles['status'].read() + proc.handles['status'].close() + + try: proc.wait() + except IOError: pass + return output + + def sign(self, string, keyID): + proc = self.run(['-b', '-u %s'%keyID], create_fhs=['stdin', 'stdout', 'status', 'stderr']) + proc.handles['stdin'].write(string) + proc.handles['stdin'].close() + + output = proc.handles['stdout'].read() + proc.handles['stdout'].close() + proc.handles['stderr'].close() + + stat = proc.handles['status'] + resp = self._read_response(stat) + proc.handles['status'].close() + + try: proc.wait() + except IOError: pass + if resp.has_key('BAD_PASSPHRASE'): + return 'BAD_PASSPHRASE' + elif resp.has_key('GOOD_PASSPHRASE'): + return self.stripHeaderFooter(output) + + def verify(self, str, sign): + file = open('gpg_data', 'w+r') + os.remove('gpg_data') + fd = file.fileno() + file.write(str) + file.seek(0) + + proc = self.run(['--verify', '--enable-special-filenames', '-', '-&%s'%fd], create_fhs=['stdin', 'status', 'stderr']) + + file.close + sign = self.addHeaderFooter(sign, 'SIGNATURE') + proc.handles['stdin'].write(sign) + proc.handles['stdin'].close() + proc.handles['stderr'].close() + + stat = proc.handles['status'] + resp = self._read_response(stat) + proc.handles['status'].close() + + try: proc.wait() + except IOError: pass + + keyid = '' + if resp.has_key('GOODSIG'): + keyid = string.split(resp['GOODSIG'])[0] + return keyid + + def stripHeaderFooter(self, data): + """Remove header and footer from data""" + lines = string.split(data, '\n') + while lines[0] != '': + lines.remove(lines[0]) + while lines[0] == '': + lines.remove(lines[0]) + i = 0 + for line in lines: + if line: + if line[0] == '-': break + i = i+1 + line = string.join(lines[0:i], '\n') + return line + + def addHeaderFooter(self, data, type): + """Add header and footer from data""" + out = "-----BEGIN PGP %s-----\n" % type + out = out + "Version: PGP\n" + out = out + "\n" + out = out + data + "\n" + out = out + "-----END PGP %s-----\n" % type + return out + class GajimCore: """Core""" def __init__(self, mode='client'): @@ -65,9 +202,11 @@ class GajimCore: self.connected = {} #connexions {con: name, ...} self.connexions = {} + self.gpg = {} for a in self.accounts: self.connected[a] = 0 #0:offline, 1:online, 2:away, #3:xa, 4:dnd, 5:invisible + self.gpg[a] = MyGnuPG() self.myVCardID = [] self.loadPlugins(self.cfgParser.tab['Core']['modules']) else: @@ -158,7 +297,7 @@ class GajimCore: def vCardCB(self, con, vc): """Called when we recieve a vCard Parse the vCard and send it to plugins""" - vcard = {'jid': vc.getFrom().getBasic()} + vcard = {'jid': vc.getFrom().getStripped()} if vc._getTag('vCard') == common.jabber.NS_VCARD: card = vc.getChildren()[0] for info in card.getChildren(): @@ -179,16 +318,33 @@ class GajimCore: typ = msg.getType() tim = msg.getTimestamp() tim = time.strptime(tim, "%Y%m%dT%H:%M:%S") + msgtxt = msg.getBody() + xtags = msg.getXNodes() + encTag = None + decmsg = '' + for xtag in xtags: + if xtag.getNamespace() == common.jabber.NS_XENCRYPTED: + encTag = xtag + break + if encTag: + #decrypt + encmsg = encTag.getData() + keyID = '' + if self.cfgParser.tab[self.connexions[con]].has_key("keyid"): + keyID = self.cfgParser.tab[self.connexions[con]]["keyid"] + if keyID: + decmsg = self.gpg[self.connexions[con]].decrypt(encmsg, keyID) + if decmsg: + msgtxt = decmsg if typ == 'error': self.hub.sendPlugin('MSGERROR', self.connexions[con], \ - (str(msg.getFrom()), msg.getErrorCode(), msg.getError(), \ - msg.getBody(), tim)) + (str(msg.getFrom()), msg.getErrorCode(), msg.getError(), msgtxt, tim)) elif typ == 'groupchat': self.hub.sendPlugin('GC_MSG', self.connexions[con], \ - (str(msg.getFrom()), msg.getBody(), tim)) + (str(msg.getFrom()), msgtxt, tim)) else: self.hub.sendPlugin('MSG', self.connexions[con], \ - (str(msg.getFrom()), msg.getBody(), tim)) + (str(msg.getFrom()), msgtxt, tim)) # END messageCB def presenceCB(self, con, prs): @@ -200,19 +356,31 @@ class GajimCore: typ = prs.getType() if typ == None: typ = 'available' log.debug("PresenceCB : %s" % typ) + xtags = prs.getXNodes() + sigTag = None + keyID = '' + status = prs.getStatus() + for xtag in xtags: + if xtag.getNamespace() == common.jabber.NS_XSIGNED: + sigTag = xtag + break + if sigTag: + #verify + sigmsg = sigTag.getData() + keyID = self.gpg[self.connexions[con]].verify(status, sigmsg) if typ == 'available': show = prs.getShow() if not show: show = 'online' self.hub.sendPlugin('NOTIFY', self.connexions[con], \ - (prs.getFrom().getBasic(), show, prs.getStatus(), \ - prs.getFrom().getResource(), prio, prs.getRole(), \ + (prs.getFrom().getStripped(), show, status, \ + prs.getFrom().getResource(), prio, keyID, prs.getRole(), \ prs.getAffiliation(), prs.getJid(), prs.getReason(), \ prs.getActor(), prs.getStatusCode())) elif typ == 'unavailable': self.hub.sendPlugin('NOTIFY', self.connexions[con], \ - (prs.getFrom().getBasic(), 'offline', prs.getStatus(), \ - prs.getFrom().getResource(), prio, prs.getRole(), \ + (prs.getFrom().getStripped(), 'offline', status, \ + prs.getFrom().getResource(), prio, keyID, prs.getRole(), \ prs.getAffiliation(), prs.getJid(), prs.getReason(), \ prs.getActor(), prs.getStatusCode())) elif typ == 'subscribe': @@ -222,20 +390,20 @@ class GajimCore: con.send(common.jabber.Presence(who, 'subscribed')) if string.find(who, "@") <= 0: self.hub.sendPlugin('NOTIFY', self.connexions[con], \ - (prs.getFrom().getBasic(), 'offline', 'offline', \ - prs.getFrom().getResource(), prio, None, None, None, None, \ - None, None)) + (prs.getFrom().getStripped(), 'offline', 'offline', \ + prs.getFrom().getResource(), prio, keyID, None, None, None, \ + None, None, None)) else: - txt = prs.getStatus() - if not txt: - txt = _("I would like to add you to my roster.") - self.hub.sendPlugin('SUBSCRIBE', self.connexions[con], (who, txt)) + if not status: + status = _("I would like to add you to my roster.") + self.hub.sendPlugin('SUBSCRIBE', self.connexions[con], (who, \ + status)) elif typ == 'subscribed': jid = prs.getFrom() self.hub.sendPlugin('SUBSCRIBED', self.connexions[con],\ - (jid.getBasic(), jid.getNode(), jid.getResource())) + (jid.getStripped(), jid.getNode(), jid.getResource())) self.hub.queueIn.put(('UPDUSER', self.connexions[con], \ - (jid.getBasic(), jid.getNode(), ['general']))) + (jid.getStripped(), jid.getNode(), ['general']))) #BE CAREFUL : no con.updateRosterItem() in a callback log.debug("we are now subscribed to %s" % who) elif typ == 'unsubscribe': @@ -243,7 +411,7 @@ class GajimCore: elif typ == 'unsubscribed': log.debug("we are now unsubscribed to %s" % who) self.hub.sendPlugin('UNSUBSCRIBED', self.connexions[con], \ - prs.getFrom().getBasic()) + prs.getFrom().getStripped()) elif typ == 'error': errmsg = prs.getError() errcode = prs.getErrorCode() @@ -273,9 +441,9 @@ class GajimCore: self.hub.sendPlugin('WARNING', None, errmsg) else: self.hub.sendPlugin('NOTIFY', self.connexions[con], \ - (prs.getFrom().getBasic(), 'error', errmsg, \ - prs.getFrom().getResource(), prio, None, None, None, None, None,\ - None)) + (prs.getFrom().getStripped(), 'error', errmsg, \ + prs.getFrom().getResource(), prio, keyID, None, None, None, \ + None, None, None)) # END presenceCB def disconnectedCB(self, con): @@ -463,6 +631,16 @@ class GajimCore: #('STATUS', account, (status, msg)) elif ev[0] == 'STATUS': activ = 1 + signed = '' + keyID = '' + if self.cfgParser.tab[ev[1]].has_key("keyid"): + keyID = self.cfgParser.tab[ev[1]]["keyid"] + if keyID: + signed = self.gpg[ev[1]].sign(ev[2][0], keyID) + if signed == 'BAD_PASSPHRASE': + signed = '' + if self.connected[ev[1]] == 0: + self.hub.sendPlugin('BAD_PASSPHRASE', ev[1], ()) if self.cfgParser.tab[ev[1]].has_key('active'): activ = self.cfgParser.tab[ev[1]]['active'] if (ev[2][0] != 'offline') and (self.connected[ev[1]] == 0) and \ @@ -479,7 +657,7 @@ class GajimCore: prio = 0 if self.cfgParser.tab[ev[1]].has_key('priority'): prio = str(self.cfgParser.tab[ev[1]]['priority']) - con.sendPresence(typ, prio, ev[2][0], ev[2][1]) + con.sendPresence(typ, prio, ev[2][0], ev[2][1], signed) self.hub.sendPlugin('STATUS', ev[1], ev[2][0]) #ask our VCard iq = common.jabber.Iq(type="get") @@ -502,12 +680,20 @@ class GajimCore: prio = 0 if self.cfgParser.tab[ev[1]].has_key('priority'): prio = str(self.cfgParser.tab[ev[1]]['priority']) - con.sendPresence(typ, prio, ev[2][0], ev[2][1]) + con.sendPresence(typ, prio, ev[2][0], ev[2][1], signed) self.hub.sendPlugin('STATUS', ev[1], ev[2][0]) - #('MSG', account, (jid, msg)) + #('MSG', account, (jid, msg, keyID)) elif ev[0] == 'MSG': - msg = common.jabber.Message(ev[2][0], ev[2][1]) + msgtxt = ev[2][1] + msgenc = '' + if ev[2][2]: + #encrypt + msgenc = self.gpg[ev[1]].encrypt(ev[2][1], [ev[2][2]]) + if msgenc: msgtxt = '[this message is encrypted]' + msg = common.jabber.Message(ev[2][0], msgtxt) msg.setType('chat') + if msgenc: + msg.setX(common.jabber.NS_XENCRYPTED).insertData(msgenc) con.send(msg) self.hub.sendPlugin('MSGSENT', ev[1], ev[2]) #('SUB', account, (jid, txt)) @@ -678,6 +864,9 @@ class GajimCore: else: con.send(common.jabber.Presence('%s/%s' % (ev[2][1], ev[2][0]), \ 'available', show=ev[2][2], status = ev[2][3])) + #('PASSPHRASE', account, passphrase) + elif ev[0] == 'PASSPHRASE': + self.gpg[ev[1]].passphrase = ev[2] else: log.debug(_("Unknown Command %s") % ev[0]) if self.mode == 'server': diff --git a/plugins/gtkgui/dialogs.py b/plugins/gtkgui/dialogs.py index 997ca13ff..edbb12094 100644 --- a/plugins/gtkgui/dialogs.py +++ b/plugins/gtkgui/dialogs.py @@ -183,7 +183,28 @@ class infoUser_Window: self.xml.signal_connect('on_remove_clicked', self.on_remove) self.xml.signal_connect('on_entry_new_key_press_event', \ self.on_new_key_pressed) - + +class passphrase_Window: + """Class for Passphrase Window""" + def run(self): + """Wait for Ok button to be pressed and return passphrase""" + rep = self.xml.get_widget("Passphrase").run() + if rep == gtk.RESPONSE_OK: + msg = self.entry.get_text() + else: + msg = -1 + self.xml.get_widget("Passphrase").destroy() + return msg + + def on_key_pressed(self, widget, event): + if event.keyval == gtk.keysyms.Return: + self.xml.get_widget("Passphrase").response(gtk.RESPONSE_OK) + + def __init__(self): + self.xml = gtk.glade.XML(GTKGUI_GLADE, 'Passphrase', APP) + self.entry = self.xml.get_widget("entry") + self.xml.signal_connect('on_Passphrase_key_press_event', \ + self.on_key_pressed) class awayMsg_Window: """Class for Away Message Window""" diff --git a/plugins/gtkgui/gtkgui.glade b/plugins/gtkgui/gtkgui.glade index 7c78a66dc..f27ead55a 100644 --- a/plugins/gtkgui/gtkgui.glade +++ b/plugins/gtkgui/gtkgui.glade @@ -536,6 +536,34 @@ + + + True + True + GTK_RELIEF_NONE + False + False + False + + + + True + gtk-dialog-authentication + 4 + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + True @@ -7752,4 +7780,123 @@ when NOT online + + True + Passphrase + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + gtk-cancel + True + GTK_RELIEF_NORMAL + True + -6 + + + + + + True + True + True + True + gtk-ok + True + GTK_RELIEF_NORMAL + True + -5 + + + + + 0 + False + True + GTK_PACK_END + + + + + + True + False + 0 + + + + True + Enter your passphrase + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 5 + False + False + + + + + + True + True + True + True + False + 0 + + True + * + False + + + 0 + False + False + + + + + 0 + True + True + + + + + + diff --git a/plugins/gtkgui/gtkgui.py b/plugins/gtkgui/gtkgui.py index 2d2c0c887..3390f6015 100644 --- a/plugins/gtkgui/gtkgui.py +++ b/plugins/gtkgui/gtkgui.py @@ -163,7 +163,8 @@ class user: self.sub = '' self.resource = '' self.priority = 0 - elif len(args) == 8: + self.keyID = '' + elif len(args) == 9: self.jid = args[0] self.name = args[1] self.groups = args[2] @@ -172,6 +173,7 @@ class user: self.sub = args[5] self.resource = args[6] self.priority = args[7] + self.keyID = args[8] else: raise TypeError, _('bad arguments') @@ -248,7 +250,10 @@ class message_Window: end_iter = txt_buffer.get_end_iter() txt = txt_buffer.get_text(start_iter, end_iter, 0) if txt != '': - self.plugin.send('MSG', self.account, (self.user.jid, txt)) + keyID = '' + if self.xml.get_widget('toggle_gpg').get_active(): + keyID = self.keyID + self.plugin.send('MSG', self.account, (self.user.jid, txt, keyID)) txt_buffer.set_text('', -1) self.print_conversation(txt, self.user.jid) widget.grab_focus() @@ -275,6 +280,7 @@ class message_Window: self.user = user self.plugin = plugin self.account = account + self.keyID = self.user.keyID self.xml = gtk.glade.XML(GTKGUI_GLADE, 'Chat', APP) self.window = self.xml.get_widget('Chat') self.window.set_title('Chat with ' + user.name + " (" + account + ")") @@ -287,6 +293,8 @@ class message_Window: self.xml.get_widget('button_contact').set_label(user.name + ' <'\ + user.jid + '>') self.xml.get_widget('button_contact').set_resize_mode(gtk.RESIZE_QUEUE) + if not self.keyID: + self.xml.get_widget('toggle_gpg').set_sensitive(False) message = self.xml.get_widget('message') message.grab_focus() conversation = self.xml.get_widget('conversation') @@ -419,7 +427,6 @@ class gc: start_iter = txt_buffer.get_start_iter() end_iter = txt_buffer.get_end_iter() txt = txt_buffer.get_text(start_iter, end_iter, 0) - print self.jid if txt != '': self.plugin.send('GC_MSG', self.account, (self.jid, txt)) txt_buffer.set_text('', -1) @@ -878,7 +885,7 @@ class roster_Window: model.append(None, (self.pixbufs[status], account, 'account', account,\ FALSE)) - def add_user_to_roster(self, jid, account): + def add_user_to_roster(self, jid, account, keyID): """Add a user to the roster and add groups if they aren't in roster""" showOffline = self.plugin.config['showoffline'] if not self.contacts[account].has_key(jid): @@ -1009,7 +1016,8 @@ class roster_Window: for acct in self.contacts.keys(): self.add_account_to_roster(acct) for jid in self.contacts[acct].keys(): - self.add_user_to_roster(jid, acct) + #TODO: get the good keyID + self.add_user_to_roster(jid, acct, '') def mklists(self, array, account): """fill self.contacts and self.groups""" @@ -1038,7 +1046,7 @@ class roster_Window: show = 'offline' user1 = user(ji, name, array[jid]['groups'], show, \ - array[jid]['status'], array[jid]['sub'], resource, 0) + array[jid]['status'], array[jid]['sub'], resource, 0, '') #when we draw the roster, we can't have twice the same user with # 2 resources self.contacts[account][ji] = [user1] @@ -1067,13 +1075,14 @@ class roster_Window: iters = [] else: if not self.get_user_iter(user.jid, account): - self.add_user_to_roster(user.jid, account) + self.add_user_to_roster(user.jid, account, user.keyID) self.redraw_jid(user.jid, account) users = self.contacts[account][user.jid] for u in users: if u.resource == user.resource: u.show = show u.status = status + u.keyID = user.keyID break #Print status in chat window if self.plugin.windows[account]['chats'].has_key(user.jid): @@ -1299,9 +1308,9 @@ class roster_Window: self.plugin.send('SUB', account, (jid, txt)) if not self.contacts[account].has_key(jid): user1 = user(jid, jid, ['general'], 'requested', \ - 'requested', 'sub', '', 0) + 'requested', 'sub', '', 0, '') self.contacts[account][jid] = [user1] - self.add_user_to_roster(jid, account) + self.add_user_to_roster(jid, account, '') def on_treeview_event(self, widget, event): """popup user's group's or agent menu""" @@ -1345,20 +1354,35 @@ class roster_Window: self.remove_user(u, account) del self.contacts[account][u.jid] - def change_status(self, widget, account, status): - if status != 'online' and status != 'offline': - w = awayMsg_Window() - txt = w.run() - if txt != -1: - self.plugin.send('STATUS', account, (status, txt)) - else: - txt = status - self.plugin.send('STATUS', account, (status, txt)) + def send_status(self, account, status, txt): + if status != 'offline': + keyid = None + if self.plugin.accounts[account].has_key("keyid"): + keyid = self.plugin.accounts[account]["keyid"] + if keyid and not self.plugin.connected[account]: + passphrase = '' + #TODO: ask passphrase + w = passphrase_Window() + passphrase = w.run() + if passphrase == -1: + passphrase = '' + self.plugin.send('PASSPHRASE', account, passphrase) + self.plugin.send('STATUS', account, (status, txt)) if status == 'online': self.plugin.sleeper_state[account] = 1 else: self.plugin.sleeper_state[account] = 0 + def change_status(self, widget, account, status): + if status != 'online' and status != 'offline': + w = awayMsg_Window() + txt = w.run() + if txt == -1: + return + else: + txt = status + self.send_status(account, status, txt) + def on_optionmenu_changed(self, widget): """When we change our status""" optionmenu = self.xml.get_widget('optionmenu') @@ -1377,11 +1401,7 @@ class roster_Window: warning_Window(_("You must setup an account before connecting to jabber network.")) return for acct in accounts: - self.plugin.send('STATUS', acct, (status, txt)) - if status == 'online': - self.plugin.sleeper_state[acct] = 1 - else: - self.plugin.sleeper_state[acct] = 0 + self.send_status(acct, status, txt) def set_optionmenu(self): #table to change index in plugin.connected to index in optionmenu @@ -1423,9 +1443,9 @@ class roster_Window: """when we receive a message""" if not self.contacts[account].has_key(jid): user1 = user(jid, jid, ['not in list'], \ - 'not in list', 'not in list', 'none', '', 0) + 'not in list', 'not in list', 'none', '', 0, '') self.contacts[account][jid] = [user1] - self.add_user_to_roster(jid, account) + self.add_user_to_roster(jid, account, '') iters = self.get_user_iter(jid, account) if iters: path = self.tree.get_model().get_path(iters[0]) @@ -1445,7 +1465,7 @@ class roster_Window: # tim = time.strftime("[%H:%M:%S]") self.plugin.queues[account][jid].put((msg, tim)) if not path: - self.add_user_to_roster(jid, account) + self.add_user_to_roster(jid, account, '') iters = self.get_user_iter(jid, account) path = self.tree.get_model().get_path(iters[0]) self.tree.expand_row(path[0:1], FALSE) @@ -1747,7 +1767,8 @@ class roster_Window: parent_i = model.iter_parent(iter_source) if model.iter_n_children(parent_i) == 1: #this was the only child model.remove(parent_i) - self.add_user_to_roster(data, account) + #TODO: get the good keyID + self.add_user_to_roster(data, account, '') if context.action == gtk.gdk.ACTION_MOVE: context.finish(True, True, etime) return @@ -2060,9 +2081,10 @@ class plugin: self.roster.on_status_changed(account, status) def handle_event_notify(self, account, array): - #('NOTIFY', account, (jid, status, message, resource, priority, role, \ - #affiliation, real_jid, reason, actor, statusCode)) + #('NOTIFY', account, (jid, status, message, resource, priority, keyID, + # role, affiliation, real_jid, reason, actor, statusCode)) jid = string.split(array[0], '/')[0] + keyID = array[5] resource = array[3] if not resource: resource = '' @@ -2088,12 +2110,13 @@ class plugin: luser[0].show != 'offline')) and not string.find(jid, "@") <= 0: user1 = user(user1.jid, user1.name, user1.groups, \ user1.show, user1.status, user1.sub, user1.resource, \ - user1.priority) + user1.priority, user1.keyID) luser.append(user1) user1.resource = resource user1.show = array[1] user1.status = array[2] user1.priority = priority + user1.keyID = keyID if string.find(jid, "@") <= 0: #It must be an agent if self.roster.contacts[account].has_key(ji): @@ -2105,8 +2128,8 @@ class plugin: elif self.windows[account]['gc'].has_key(ji): #it is a groupchat presence self.windows[account]['gc'][ji].chg_user_status(resource, array[1],\ - array[2], array[5], array[6], array[7], array[8], array[9], \ - array[10], account) + array[2], array[6], array[7], array[8], array[9], array[10], \ + array[11], account) def handle_event_msg(self, account, array): #('MSG', account, (user, msg, time)) @@ -2137,9 +2160,9 @@ class plugin: self.roster.redraw_jid(u.jid, account) else: user1 = user(jid, jid, ['general'], 'online', \ - 'online', 'to', array[2], 0) + 'online', 'to', array[2], 0, '') self.roster.contacts[account][jid] = [user1] - self.roster.add_user_to_roster(jid, account) + self.roster.add_user_to_roster(jid, account, '') warning_Window(_("You are now authorized by %s") % jid) def handle_event_unsubscribed(self, account, jid):