From 51003f471221c139afc7653f18ba727ea79929d0 Mon Sep 17 00:00:00 2001 From: Yann Leboulanger <asterix@lagaule.org> Date: Tue, 12 Apr 2005 11:46:20 +0000 Subject: [PATCH] remove the old plugin system new connection and GnuPG class --- Core/GnuPG.py | 194 +++++++ Core/connection.py | 746 +++++++++++++++++++++++++++ Core/core.py | 1226 -------------------------------------------- common/hub.py | 104 ---- common/plugin.py | 36 -- common/thread.py | 40 -- 6 files changed, 940 insertions(+), 1406 deletions(-) create mode 100644 Core/GnuPG.py create mode 100644 Core/connection.py delete mode 100644 Core/core.py delete mode 100644 common/hub.py delete mode 100644 common/plugin.py delete mode 100644 common/thread.py diff --git a/Core/GnuPG.py b/Core/GnuPG.py new file mode 100644 index 0000000000..c637f7154d --- /dev/null +++ b/Core/GnuPG.py @@ -0,0 +1,194 @@ +## Core/GnuPG.py +## +## Gajim Team: +## - Yann Le Boulanger <asterix@lagaule.org> +## - Vincent Hanquez <tab@snarc.org> +## - Nikos Kouremenos <nkour@jabber.org> +## +## Copyright (C) 2003-2005 Gajim Team +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published +## by the Free Software Foundation; version 2 only. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## + +from tempfile import * + +USE_GPG = 1 + +try: + import GnuPGInterface +except: + USE_GPG = 0 + +class GnuPG(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') + # Nolith's patch - prevent crashs on non fully-trusted keys + self.options.extra_args.append('--always-trust') + + 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 = line.rstrip() + if line[0:9] == '[GNUPG:] ': + # Chop off the prefix + line = line[9:] + L = line.split(None, 1) + keyword = L[0] + if len(L) > 1: + resp[ keyword ] = L[1] + else: + resp[ keyword ] = "" + return resp + + def encrypt(self, str, recipients): + if not USE_GPG: + return str + self.options.recipients = recipients # a list! + + proc = self.run(['--encrypt'], create_fhs=['stdin', 'stdout']) + proc.handles['stdin'].write(str) + 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, str, keyID): + if not USE_GPG: + return str + proc = self.run(['--decrypt', '-q', '-u %s'%keyID], create_fhs=['stdin', 'stdout', 'status']) + enc = self._addHeaderFooter(str, '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, str, keyID): + if not USE_GPG: + return str + proc = self.run(['-b', '-u %s'%keyID], create_fhs=['stdin', 'stdout', 'status', 'stderr']) + proc.handles['stdin'].write(str) + 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): + if not USE_GPG: + return str + if not str: + return '' + file = TemporaryFile(prefix='gajim') + 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 = resp['GOODSIG'].split()[0] + elif resp.has_key('BADSIG'): + keyid = resp['BADSIG'].split()[0] + return keyid + + def get_secret_keys(self): + if not USE_GPG: + return + proc = self.run(['--with-colons', '--list-secret-keys'], \ + create_fhs=['stdout']) + output = proc.handles['stdout'].read() + proc.handles['stdout'].close() + + keys = {} + lines = output.split('\n') + for line in lines: + sline = line.split(':') + if sline[0] == 'sec': + keys[sline[4][8:]] = sline[9] + return keys + try: proc.wait() + except IOError: pass + + def _stripHeaderFooter(self, data): + """Remove header and footer from data""" + lines = data.split('\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 = '\n'.join(lines[0:i]) + 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 diff --git a/Core/connection.py b/Core/connection.py new file mode 100644 index 0000000000..a794b9d587 --- /dev/null +++ b/Core/connection.py @@ -0,0 +1,746 @@ +## Core/connection.py +## +## Gajim Team: +## - Yann Le Boulanger <asterix@lagaule.org> +## - Vincent Hanquez <tab@snarc.org> +## - Nikos Kouremenos <nkour@jabber.org> +## +## Copyright (C) 2003-2005 Gajim Team +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published +## by the Free Software Foundation; version 2 only. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## + +import sys +import os +import time + +import common.jabber + +from Core import GnuPG + +from common import i18n +_ = i18n._ + + +STATUS_LIST = ['offline', 'connecting', 'online', 'away', 'xa', 'dnd', \ + 'invisible'] + +distro_info = { + 'Arch Linux': '/etc/arch-release',\ + 'Aurox Linux': '/etc/aurox-release',\ + 'Conectiva Linux': '/etc/conectiva-release',\ + 'Debian GNU/Linux': '/etc/debian_release',\ + 'Debian GNU/Linux': '/etc/debian_version',\ + 'Fedora Linux': '/etc/fedora-release',\ + 'Gentoo Linux': '/etc/gentoo-release',\ + 'Mandrake Linux': '/etc/mandrake-release',\ + 'Slackware Linux': '/etc/slackware-release',\ + 'Slackware Linux': '/etc/slackware-version',\ + 'Solaris/Sparc': '/etc/release',\ + 'Sun JDS': '/etc/sun-release',\ + 'Novell SUSE Linux': '/etc/SuSE-release',\ + 'PLD Linux': '/etc/pld-release',\ + 'SUSE Linux': '/etc/SuSE-release',\ + 'Yellow Dog Linux': '/etc/yellowdog-release',\ + # many distros use the /etc/redhat-release for compatibility + # so Redhat is the last + 'Redhat Linux': '/etc/redhat-release'\ +} + +def get_os_info(): + if os.name =='nt': + return 'windows' + elif os.name =='posix': + executable = 'lsb_release' + params = ' --id --codename --release --short' + for path in os.environ['PATH'].split(':'): + full_path_to_executable = os.path.join(path, executable) + if os.path.exists(full_path_to_executable): + command = executable + params + child_stdin, child_stdout = os.popen2(command) + output = child_stdout.readline().strip() + child_stdout.close() + child_stdin.close() + return output + # lsb_release executable not available, so parse files + for distro in distro_info: + path_to_file = distro_info[distro] + if os.path.exists(path_to_file): + fd = open(path_to_file) + text = fd.read().strip() + fd.close() + if path_to_file.endswith('version'): + text = distro + ' ' + text + return text + return '' + +class connection: + """connection""" + def __init__(self, name = None): + # dict of function to be calledfor each event + self.handlers = {'ROSTER': [], 'WARNING': [], 'ERROR': [], 'STATUS': [], \ + 'NOTIFY': [], 'MSG': [], 'MSGERROR': [], 'SUBSCRIBED': [], \ + 'UNSUBSCRIBED': [], 'SUBSCRIBE': [], 'AGENTS': [], 'AGENT_INFO': [], \ + 'AGENT_INFO_ITEMS': [], 'AGENT_INFO_INFO': [], 'REG_AGENT_INFO': [], \ + 'QUIT': [], 'ACC_OK': [], 'CONFIG': [], 'MYVCARD': [], 'OS_INFO': [], \ + 'VCARD': [], 'LOG_NB_LINE': [], 'LOG_LINE': [], 'VISUAL': [], \ + 'GC_MSG': [], 'GC_SUBJECT': [], 'BAD_PASSPHRASE': [], \ + 'GPG_SECRETE_KEYS': [], 'ROSTER_INFO': [], 'MSGSENT': []} + self.name = name + self.connected = 0 # offline + self.connection = None # Jabber.py instance + self.gpg = None + self.myVCardID = [] + if name: + self.password = gajim.config.get_per('accounts', name, 'hostname') + if USE_GPG: + self.gpg = GnuPG.GnuPG() + # END __init__ + + def dispatch(self, event, data): + if not event in self.handlers: + return + for handler in self.handlers[event]: + handler(self.name, data) + + def _vCardCB(self, con, vc): + """Called when we recieve a vCard + Parse the vCard and send it to plugins""" + vcard = {'jid': vc.getFrom().getStripped()} + if vc._getTag('vCard') == common.jabber.NS_VCARD: + card = vc.getChildren()[0] + for info in card.getChildren(): + if info.getChildren() == []: + vcard[info.getName()] = info.getData() + else: + vcard[info.getName()] = {} + for c in info.getChildren(): + vcard[info.getName()][c.getName()] = c.getData() + if vc.getID() in self.myVCardID: + self.myVCardID.remove(vc.getID()) + self.dispatch('MYVCARD', vcard) + else: + self.dispatch('VCARD', vcard) + + def _messageCB(self, con, msg): + """Called when we recieve a message""" + 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 and USE_GPG: + #decrypt + encmsg = encTag.getData() + + keyID = gajim.config.get_per('accounts', self.name, 'keyid') + if keyID: + decmsg = self.gpg.decrypt(encmsg, keyID) + if decmsg: + msgtxt = decmsg + if typ == 'error': + self.dispatch('MSGERROR', (str(msg.getFrom()), \ + msg.getErrorCode(), msg.getError(), msgtxt, tim)) + elif typ == 'groupchat': + subject = msg.getSubject() + if subject: + self.dispatch('GC_SUBJECT', (str(msg.getFrom()), subject)) + else: + self.dispatch('GC_MSG', (str(msg.getFrom()), msgtxt, tim)) + else: + self.dispatch('MSG', (str(msg.getFrom()), msgtxt, tim)) + # END messageCB + + def _presenceCB(self, con, prs): + """Called when we recieve a presence""" +# if prs.getXNode(common.jabber.NS_DELAY): return + who = str(prs.getFrom()) + prio = prs.getPriority() + if not prio: + prio = 0 + typ = prs.getType() + if typ == None: typ = 'available' + gajim.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 and USE_GPG: + #verify + sigmsg = sigTag.getData() + keyID = self.gpg.verify(status, sigmsg) + if typ == 'available': + show = prs.getShow() + if not show: + show = 'online' + self.dispatch('NOTIFY', (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.dispatch('NOTIFY', (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': + gajim.log.debug('subscribe request from %s' % who) + if gajim.config.get('alwaysauth') or who.find("@") <= 0: + if self.connection: + self.connection.send(common.jabber.Presence(who, 'subscribed')) + if who.find("@") <= 0: + self.dispatch('NOTIFY', (prs.getFrom().getStripped(), \ + 'offline', 'offline', prs.getFrom().getResource(), prio, \ + keyID, None, None, None, None, None, None)) + else: + if not status: + status = _('I would like to add you to my roster.') + self.dispatch('SUBSCRIBE', (who, status)) + elif typ == 'subscribed': + jid = prs.getFrom() + self.dispatch('SUBSCRIBED', (jid.getStripped(), jid.getResource())) + self.dispatch('UPDUSER', (jid.getStripped(), jid.getNode(), \ + ['General']))) + #BE CAREFUL : no con.updateRosterItem() in a callback + gajim.log.debug('we are now subscribed to %s' % who) + elif typ == 'unsubscribe': + gajim.log.debug('unsubscribe request from %s' % who) + elif typ == 'unsubscribed': + gajim.log.debug('we are now unsubscribed to %s' % who) + self.dispatch('UNSUBSCRIBED', prs.getFrom().getStripped()) + elif typ == 'error': + errmsg = prs.getError() + errcode = prs.getErrorCode() + if errcode == '400': #Bad Request: JID Malformed or Private message when not allowed + pass + elif errcode == '401': #No Password Provided + pass + elif errcode == '403': #forbidden : User is Banned + # Unauthorized Subject Change + # Attempt by Mere Member to Invite Others to a Members-Only Room + # Configuration Access to Non-Owner + # Attempt by Non-Owner to Modify Owner List + # Attempt by Non-Owner to Modify Admin List + # Destroy Request Submitted by Non-Owner + pass + elif errcode == '404': #item not found : Room Does Not Exist + pass + elif errcode == '405': #Not allowed : Attempt to Kick Moderator, Admin, or Owner + # Attempt to Ban an Admin or Owner + # Attempt to Revoke Voice from an Admin, Owner, or User with a Higher Affiliation + # Attempt to Revoke Moderator Privileges from an Admin or Owner + pass + elif errcode == '407': #registration required : User Is Not on Member List + # + pass + elif errcode == '409': #conflict : Nick Conflict + self.dispatch('ERROR', errmsg) + else: + self.dispatch('NOTIFY', (prs.getFrom().getStripped(), 'error', \ + errmsg, prs.getFrom().getResource(), prio, keyID, None, None, \ + None, None, None, None)) + # END presenceCB + + def _disconnectedCB(self, con): + """Called when we are disconnected""" + gajim.log.debug('disconnectedCB') + if self.connection: + self.connected = 0 + self.dispatch('STATUS', 'offline') + # END disconenctedCB + + def _rosterSetCB(self, con, iq_obj): + for item in iq_obj.getQueryNode().getChildren(): + jid = item.getAttr('jid') + name = item.getAttr('name') + sub = item.getAttr('subscription') + ask = item.getAttr('ask') + groups = [] + for group in item.getTags('group'): + groups.append(group.getData()) + self.dispatch('ROSTER_INFO', (jid, name, sub, ask, groups)) + + def _BrowseResultCB(self, con, iq_obj): + identities, features, items = [], [], [] + q = iq_obj.getTag('service') + if not q: + return identities, features, items + attr = {} + for key in q.attrs: + attr[key.encode('utf8')] = q.attrs[key].encode('utf8') + identities = [attr] + for node in q.kids: + if node.getName() == 'ns': + features.append(node.getData()) + else: + infos = {} + for key in node.attrs: + infos[key.encode('utf8')] = node.attrs[key].encode('utf8') + infos['category'] = node.getName() + items.append(infos) + jid = str(iq_obj.getFrom()) + self.dispatch('AGENT_INFO', (jid, identities, features, items)) + + def _DiscoverItemsCB(self, con, iq_obj): + qp = iq_obj.getQueryPayload() + items = [] + if not qp: + qp = [] + for i in qp: + attr = {} + for key in i.attrs: + attr[key.encode('utf8')] = i.attrs[key].encode('utf8') + items.append(attr) + jid = str(iq_obj.getFrom()) + self.dispatch('AGENT_INFO_ITEMS', (jid, items)) + + def _DiscoverInfoErrorCB(self, con, iq_obj): + jid = str(iq_obj.getFrom()) + con.browseAgents(jid) + + def _DiscoverInfoCB(self, con, iq_obj): + # According to JEP-0030: + # For identity: category, name is mandatory, type is optional. + # For feature: var is mandatory + identities, features = [], [] + qp = iq_obj.getQueryPayload() + if not qp: + qp = [] + for i in qp: + if i.getName() == 'identity': + attr = {} + for key in i.attrs: + attr[key.encode('utf8')] = i.attrs[key].encode('utf8') + identities.append(attr) + elif i.getName() == 'feature': + features.append(i.getAttr('var')) + jid = str(iq_obj.getFrom()) + if not identities: + self.connection.browseAgents(jid) + else: + self.dispatch('AGENT_INFO_INFO', (jid, identities, features)) + self.connection.discoverItems(jid) + + def _VersionCB(self, con, iq_obj): + f = iq_obj.getFrom() + iq_obj.setFrom(iq_obj.getTo()) + iq_obj.setTo(f) + iq_obj.setType('result') + qp = iq_obj.getTag('query') + qp.insertTag('name').insertData('Gajim') + qp.insertTag('version').insertData(version.version) + no_send_os = gajim.config.get('do_not_send_os_info') + if not no_send_os: + qp.insertTag('os').insertData(get_os_info()) + self.connection.send(iq_obj) + + def _VersionResultCB(self, con, iq_obj): + client_info = '' + os_info = '' + qp = iq_obj.getTag('query') + if qp.getTag('name'): + client_info += qp.getTag('name').getData() + if qp.getTag('version'): + client_info += ' ' + qp.getTag('version').getData() + if qp.getTag('os'): + os_info += qp.getTag('os').getData() + jid = iq_obj.getFrom().getStripped() + self.dispatch('OS_INFO', (jid, client_info, os_info)) + + def connect(self): + """Connect and authentificate to the Jabber server""" + self.connected = 1 + hostname = gajim.config.get_per('accounts', self.name, 'hostname') + resource = gajim.config.get_per('accounts', self.name, 'resource') + + #create connexion if it doesn't already existe + if not self.connection: + if gajim.config.get_per('accounts', self.name, 'use_proxy') + proxy = {'host': gajim.config.get_per('accounts', self.name, \ + 'proxyhost') + proxy['port'] = gajim.config.get_per('accounts', self.name, \ + 'proxyport') + else: + proxy = None + if gajim.log: + self.connection = common.jabber.Client(host = hostname, debug = [],\ + log = sys.stderr, connection=common.xmlstream.TCP, port=5222, \ + proxy = proxy) + else: + con = common.jabber.Client(host = hostname, debug = [], log = None,\ + connection=common.xmlstream.TCP, port=5222, proxy = proxy) + #debug = [common.jabber.DBG_ALWAYS], log = sys.stderr, \ + #connection=common.xmlstream.TCP_SSL, port=5223, proxy = proxy) + self.connection.setDisconnectHandler(self.disconnectedCB) + self.connection.registerHandler('message', self.messageCB) + self.connection.registerHandler('presence', self.presenceCB) + self.connection.registerHandler('iq',self.vCardCB,'result') + self.connection.registerHandler('iq',self.rosterSetCB,'set', \ + common.jabber.NS_ROSTER) + self.connection.registerHandler('iq',self.BrowseResultCB,'result', \ + common.jabber.NS_BROWSE) + self.connection.registerHandler('iq',self.DiscoverItemsCB,'result', \ + common.jabber.NS_P_DISC_ITEMS) + self.connection.registerHandler('iq',self.DiscoverInfoCB,'result', \ + common.jabber.NS_P_DISC_INFO) + self.connection.registerHandler('iq',self.DiscoverInfoErrorCB,'error',\ + common.jabber.NS_P_DISC_INFO) + self.connection.registerHandler('iq',self.VersionCB,'get', \ + common.jabber.NS_VERSION) + self.connection.registerHandler('iq',self.VersionResultCB,'result', \ + common.jabber.NS_VERSION) + try: + self.connection.connect() + except: + gajim.log.debug("Couldn't connect to %s %s" % (hostname, e)) + self.dispatch('STATUS', 'offline') + self.dispatch('ERROR', _('Couldn\'t connect to %s') \ + % hostname) + self.connected = 0 + return -1 + + gajim.log.debug('Connected to server') + + if self.connection.auth(self.name, self.password, resource): + self.connection.requestRoster() + roster = self.connection.getRoster().getRaw() + if not roster : + roster = {} + self.dispatch('ROSTER', (0, roster)) + self.connected = 2 + return 0 + else: + log.debug('Couldn\'t authentificate to %s' % hostname) + self.dispatch('STATUS', 'offline') + self.dispatch('ERROR', _('Authentification failed with %s, check your login and password') % hostname) + self.connected = 0 + return -1 +# END connect + + def register_handler(self, event, funtion): + if event in self.handlers: + self.handlers[event].append(function) + + def unregister_handler(self, event, funtion): + if event in self.handlers: + if function in self.handlers[event]: + self.handlers[event].remove(function) + + def quit(self, kill_core): + if kill_core: + if self.connected > 1: + self.connected = 0 + self.connection.disconnect('Disconnected') + self.dispatch('QUIT', ()) + return + + def ask_roster(self): + roster = {} + if self.connection: + roster = self.connection.getRoster().getRaw() + return roster + + def change_status(self, status, msg): + if not status in STATUS_LIST: + return -1 + if not msg: + msg = status + signed = '' + keyID = gajim.config.get_per('accounts', self.name, 'keyid') + if keyID and USE_GPG: + signed = self.gpg.sign(msg, keyID) + if signed == 'BAD_PASSPHRASE': + signed = '' + if self.connected < 2: + self.dispatch('BAD_PASSPHRASE', ()) + if (status != 'offline') and (self.connected == 0): + self.connect() + if self.connected == 2: + self.connected = STATUS_LIST.index(status) + #send our presence + typ = 'available' + if status == 'invisible': + typ = 'invisible' + prio = gajim.config.get_per('accounts', self.name, 'priority') + self.connection.sendPresence(typ, prio, status, msg, signed) + self.dispatch('STATUS', status) + #ask our VCard + iq = common.jabber.Iq(type='get') + iq._setTag('vCard', common.jabber.NS_VCARD) + id = con.getAnID() + iq.setID(id) + con.send(iq) + self.myVCardID.append(id) + elif (status == 'offline') and self.connected: + self.connected = 0 + self.connection.disconnect(msg) + self.dispatch('STATUS', 'offline') + elif status != 'offline' and self.connected: + self.connected = STATUS_LIST.index(status) + typ = 'available' + if status == 'invisible': + typ = 'invisible' + prio = gajim.config.get_per('accounts', self.name, 'priority') + self.connection.sendPresence(typ, prio, status, msg, signed) + self.dispatch('STATUS', status) + + def send_message(jid, msg, keyID) + if inot self.connection: + return + msgtxt = msg + msgenc = '' + if keyID and USE_GPG: + #encrypt + msgenc = self.gpg.encrypt(msg, keyID) + if msgenc: msgtxt = _('[this message is encrypted]') + msg_iq = common.jabber.Message(to = jid, body = msgtxt, type = 'chat') + if msgenc: + msg_iq.setX(common.jabber.NS_XENCRYPTED).insertData(msgenc) + self.connection.send(msg_iq) + self.dispatch('MSGSENT', (jid, msg, keyID)) + + def request_subscription(self, jid, msg) + if not self.connection: + return + gajim.log.debug('subscription request for %s' % jid) + pres = common.jabber.Presence(jid, 'subscribe') + if not msg: + msg = _('I would like to add you to my roster.') + pres.setStatus(msg) + self.connection.send(pres) + + def send_authorization(self, jid) + if not self.connection: + return + self.connection.send(common.jabber.Presence(jid, 'subscribed')) + + def refuse_authorization(self, jid) + if not self.connection: + return + self.connection.send(common.jabber.Presence(jid, 'unsubscribed')) + + def unsubscribe(self, jid): + if not self.connection: + return + delauth = gajim.config.get('delauth') + delroster = gajim.config.get('delroster') + if delauth: + self.connection.send(common.jabber.Presence(jid, 'unsubscribe')) + if delroster: + self.connection.removeRosterItem(jid) + + def unsubscribe_agent(self, agent): + if not self.connection: + return + self.connection.removeRosterItem(agent) + self.connection.requestRegInfo(agent) + agent_info = self.connection.getRegInfo() + if not agent_info: + return + key = agent_info['key'] + iq = common.jabber.Iq(to=agent, type='set') + q = iq.setQuery(common.jabber.NS_REGISTER) + q.insertTag('remove') + q.insertTag('key').insertData(key) + id = self.connection.getAnID() + iq.setID(id) + self.connection.send(iq) + self.dispatch('AGENT_REMOVED', agent) + + def update_user(self, jid, name, groups): + if self.connection: + self.connection.updateRosterItem(jid=jid, name=name, groups=groups) + + def request_agents(self, jid): + if self.connection: + self.connection.discoverInfo(jid) + + def ask_register_agent_info(self, agent): + if not self.connection: + return None + self.connection.requestRegInfo(agent) + agent_info = self.connection.getRegInfo() + return agent_info + + def register_agent(self, info): + if not self.connection: + return + self.connection.sendRegInfo(info) + + def new_account(self, hostname, login, password, name, resource, prio, \ + use_proxy, proxyhost, proxyport): + # If a connection already exist we cannot create a new account + if self.connection: + return + if use_proxy: + proxy = {'host': proxyhost, 'port': proxyport} + else: + proxy = None + c = common.jabber.Client(host = hostname, debug = [], \ + log = None, proxy = proxy) + try: + c.connect() + except: + gajim.log.debug('Couldn\'t connect to %s' % hostname) + self.dispatch('ERROR', _('Couldn\'t connect to ') + hostname) + return 0 + else: + gajim.log.debug(_('Connected to server')) + c.requestRegInfo() + req = c.getRegInfo() + c.setRegInfo( 'username', login) + c.setRegInfo( 'password', password) + if not c.sendRegInfo(): + self.dispatch('ERROR', _('Error: ') + c.lastErr) + else: + self.name = name + self.connected = 0 + self.password = '' + if USE_GPG: + self.gpg = Core.GnuPG() + self.dispatch('ACC_OK', (hostname, login, password, name, \ + resource, prio, use_proxy, proxyhost, proxyport)) + + def account_changed(self, new_name): + self.name = new_name + + def request_os_info(self, jid, resource): + if not self.connection: + return + iq = common.jabber.Iq(to=jid + '/' + resource, type = 'get', \ + query = common.jabber.NS_VERSION) + iq.setID(self.connection.getAnID()) + self.connection.send(iq) + + def request_vcard(self, jid): + if not self.connection: + return + iq = common.jabber.Iq(to = jid, type = 'get') + iq._setTag('vCard', common.jabber.NS_VCARD) + iq.setID(self.connection.getAnID()) + self.connection.send(iq) + #('VCARD', {entry1: data, entry2: {entry21: data, ...}, ...}) + + def send_vcard(self, vcard): + if not self.connection: + return + iq = common.jabber.Iq(type = 'set') + iq.setID(self.connection.getAnID()) + iq2 = iq._setTag('vCard', common.jabber.NS_VCARD) + for i in vcard.keys(): + if i != 'jid': + if type(vcard[i]) == type({}): + iq3 = iq2.insertTag(i) + for j in vcard[i].keys(): + iq3.insertTag(j).putData(vcard[i][j]) + else: + iq2.insertTag(i).putData(vcard[i]) + self.connection.send(iq) + + def send_agent_status(self, agent, typ): + if not self.connection: + return + if not typ: + typ = 'available'; + p = common.jabber.Presence(to = agent, type = typ) + self.connection.send(p) + + def join_gc(self, nick, room, server, passwd): + if not self.connection: + return + p = common.jabber.Presence(to = '%s@%s/%s' % (room, server, password)) + self.connection.send(p) + + def send_gc_message(self, jid, msg): + if not self.connection: + return + msg_iq = common.jabber.Message(jid, msg) + msg_iq.setType('groupchat') + self.connection.send(msg_iq) + self.dispatch('MSGSENT', (jid, msg)) + + def send_gc_subject(self, jid, subject): + if not self.connection: + return + msg_iq = common.jabber.Message(jid) + msg_iq.setType('groupchat') + msg_iq.setSubject(subject) + self.connection.send(msg_iq) + + def send_gc_status(self, nick, jid, show, status): + if not self.connection: + return + if show == 'offline': + typ = 'unavailable' + show = None + else: + typ = 'available' + self.connection.send(common.jabber.Presence(to = '%s/%s' % (jid, nick), \ + type = typ, show = show, status = status)) + + def gc_set_role(self, room_jid, nick, role): + if not self.connection: + return + iq = common.jabber.Iq(type = 'set', to = room_jid) + item = iq.setQuery(common.jabber.NS_P_MUC_ADMIN).insertTag('item') + item.putAttr('nick', nick) + item.putAttr('role', role) + id = self.connection.getAnID() + iq.setID(id) + self.connection.send(iq) + + def gc_set_affiliation(self, room_jid, jid, affiliation): + if not self.connection: + return + iq = common.jabber.Iq(type = 'set', to = room_jid) + item = iq.setQuery(common.jabber.NS_P_MUC_ADMIN).insertTag('item') + item.putAttr('jid', jid) + item.putAttr('affiliation', affiliation) + id = self.connection.getAnID() + iq.setID(id) + self.connection.send(iq) + + def gpg_passphrase(self, passphrase): + if USE_GPG: + self.gpg.passphrase = passphrase + + def ask_gpg_secrete_keys(self): + if USE_GPG: + keys = self.gpg.get_secret_keys() + return keys + return None + + def change_password(self, password, username): + if not self.connection: + return + hostname = gajim.config.get_per('accounts', self.name, 'hostname') + iq = common.jabber.Iq(type = 'set', to = hostname) + q = iq.setQuery(common.jabber.NS_REGISTER) + q.insertTag('username').insertData(username) + q.insertTag('password').insertData(password) + id = self.connection.getAnID() + iq.setID(id) + self.connection.send(iq) + + def process(self): + if not self.connection: + return + if self.connected: + self.connection.process(1) +# END GajimCore diff --git a/Core/core.py b/Core/core.py deleted file mode 100644 index 50cae4baaf..0000000000 --- a/Core/core.py +++ /dev/null @@ -1,1226 +0,0 @@ -## core/core.py -## -## Gajim Team: -## - Yann Le Boulanger <asterix@lagaule.org> -## - Vincent Hanquez <tab@snarc.org> -## - Nikos Kouremenos <nkour@jabber.org> -## -## Copyright (C) 2003-2005 Gajim Team -## -## This program is free software; you can redistribute it and/or modify -## it under the terms of the GNU General Public License as published -## by the Free Software Foundation; version 2 only. -## -## This program is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License for more details. -## - -import sys -import os -import time -import logging - -import common.hub -import common.optparser -import common.jabber -import socket -import select -import pickle -import version -from tempfile import * - -from common import i18n -_ = i18n._ - -log = logging.getLogger('core.core') -log.setLevel(logging.DEBUG) - -CONFPATH = "~/.gajim/config" -LOGPATH = os.path.expanduser("~/.gajim/logs/") - -distro_info = { - 'Arch Linux': '/etc/arch-release',\ - 'Aurox Linux': '/etc/aurox-release',\ - 'Conectiva Linux': '/etc/conectiva-release',\ - 'Debian GNU/Linux': '/etc/debian_release',\ - 'Debian GNU/Linux': '/etc/debian_version',\ - 'Fedora Linux': '/etc/fedora-release',\ - 'Gentoo Linux': '/etc/gentoo-release',\ - 'Mandrake Linux': '/etc/mandrake-release',\ - 'Slackware Linux': '/etc/slackware-release',\ - 'Slackware Linux': '/etc/slackware-version',\ - 'Solaris/Sparc': '/etc/release',\ - 'Sun JDS': '/etc/sun-release',\ - 'Novell SUSE Linux': '/etc/SuSE-release',\ - 'PLD Linux': '/etc/pld-release',\ - 'SUSE Linux': '/etc/SuSE-release',\ - 'Yellow Dog Linux': '/etc/yellowdog-release',\ - # many distros use the /etc/redhat-release for compatibility - # so Redhat is the last - 'Redhat Linux': '/etc/redhat-release'\ -} - -def get_os_info(): - if os.name =='nt': - return 'windows' - elif os.name =='posix': - executable = 'lsb_release' - params = ' --id --codename --release --short' - for path in os.environ['PATH'].split(':'): - full_path_to_executable = os.path.join(path, executable) - if os.path.exists(full_path_to_executable): - command = executable + params - child_stdin, child_stdout = os.popen2(command) - output = child_stdout.readline().strip() - child_stdout.close() - child_stdin.close() - return output - # lsb_release executable not available, so parse files - for distro in distro_info: - path_to_file = distro_info[distro] - if os.path.exists(path_to_file): - fd = open(path_to_file) - text = fd.read().strip() - fd.close() - if path_to_file.endswith('version'): - text = distro + ' ' + text - return text - return '' - -def XMLescape(txt): - "Escape XML entities" - txt = txt.replace("&", "&") - txt = txt.replace("<", "<") - txt = txt.replace(">", ">") - return txt - -def XMLunescape(txt): - "Unescape XML entities" - txt = txt.replace(">", ">") - txt = txt.replace("<", "<") - txt = txt.replace("&", "&") - return txt - -USE_GPG = 1 -try: - import GnuPGInterface -except: - USE_GPG = 0 -else: - 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') - # Nolith's patch - prevent crashs on non fully-trusted keys - self.options.extra_args.append('--always-trust') - - 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 = line.rstrip() - if line[0:9] == '[GNUPG:] ': - # Chop off the prefix - line = line[9:] - L = line.split(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): - if not str: - return '' - file = TemporaryFile(prefix='gajim') - 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 = resp['GOODSIG'].split()[0] - elif resp.has_key('BADSIG'): - keyid = resp['BADSIG'].split()[0] - return keyid - - def get_secret_keys(self): - proc = self.run(['--with-colons', '--list-secret-keys'], \ - create_fhs=['stdout']) - output = proc.handles['stdout'].read() - proc.handles['stdout'].close() - - keys = {} - lines = output.split('\n') - for line in lines: - sline = line.split(':') - if sline[0] == 'sec': - keys[sline[4][8:]] = sline[9] - return keys - try: proc.wait() - except IOError: pass - - def stripHeaderFooter(self, data): - """Remove header and footer from data""" - lines = data.split('\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 = '\n'.join(lines[0:i]) - 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'): - self.mode = mode - self.log = 0 - self.init_cfg_file() - if mode == 'client': - self.data = '' - self.connect_core() - self.hub = common.hub.GajimHub() - if self.log: - log.setLevel(logging.DEBUG) - else: - log.setLevel(None) - if mode == 'server': - self.connected = {} - #connections {con: name, ...} - self.connections = {} - self.gpg = {} - self.passwords = {} - if USE_GPG: - self.gpg_common = MyGnuPG() - for a in self.accounts: - self.connected[a] = 0 #0:offline, 1:online, 2:away, - #3:xa, 4:dnd, 5:invisible - if self.cfgParser.tab[a].has_key("password"): - self.passwords[a] = self.cfgParser.tab[a]["password"] - else: - self.passwords[a] = ' ' - if USE_GPG: - self.gpg[a] = MyGnuPG() - self.myVCardID = [] - self.loadPlugins(self.cfgParser.tab['Core']['modules']) - else: - self.loadPlugins(self.cfgParser.tab['Core_client']['modules']) - # END __init__ - - def loadPlugins(self, moduleStr): - """Load defaults plugins : plugins in 'modules' option of Core section - in ConfFile and register them to the hub""" - if moduleStr: - mods = moduleStr.split(' ') - - for mod in mods: - try: - modObj = self.hub.newPlugin(mod) - except: - print _("The plugin %s cannot be launched" % mod) - if not modObj: - print _("The plugin %s is already launched" % mod) - return - modObj.load() - # END loadPLugins - - def connect_core(self): - self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.socket.connect((self.cfgParser.tab['Core_client']['host'], \ - self.cfgParser.tab['Core_client']['port'])) - # END connect_core - - def init_cfg_file(self): - """Initialize configuration file""" - if self.mode == 'server': - default_tab = {'Profile': {'accounts': '', 'log': 0}, 'Core': \ - {'delauth': 1, 'alwaysauth': 0, 'modules': 'logger gtkgui', \ - 'delroster': 1}} - else: - default_tab = {'Profile': {'log': 0}, 'Core_client': {'host': \ - 'localhost', 'port': 8255, 'modules': 'gtkgui'}} - fname = os.path.expanduser(CONFPATH) - reps = fname.split('/') - path = '' - while len(reps) > 1: - path = path + reps[0] + '/' - del reps[0] - try: - os.stat(os.path.expanduser(path)) - except OSError: - try: - os.mkdir(os.path.expanduser(path)) - except: - print _("Can't create %s") % path - sys.exit - try: - os.stat(fname) - except: - print _("creating %s") % fname - fic = open(fname, "w") - import stat - os.chmod(fname, stat.S_IRUSR | stat.S_IWUSR) - fic.close() - self.cfgParser = common.optparser.OptionsParser(CONFPATH) - for part in default_tab.keys(): - if not self.cfgParser.tab.has_key(part): - self.cfgParser.tab[part] = {} - for option in default_tab[part].keys(): - if not self.cfgParser.tab[part].has_key(option): - self.cfgParser.tab[part][option] = default_tab[part][option] - self.parse() - # END init_cfg_file - - def parse(self): - """Parse configuratoin file and create self.accounts""" - self.cfgParser.parseCfgFile() - if self.cfgParser.tab.has_key('Profile'): - if self.cfgParser.tab['Profile'].has_key('log'): - self.log = self.cfgParser.tab['Profile']['log'] - if self.mode == 'server': - self.accounts = {} - if self.cfgParser.tab['Profile'].has_key('accounts'): - accts = self.cfgParser.tab['Profile']['accounts'].split(' ') - if accts == ['']: - accts = [] - for a in accts: - self.accounts[a] = self.cfgParser.tab[a] - - def vCardCB(self, con, vc): - """Called when we recieve a vCard - Parse the vCard and send it to plugins""" - vcard = {'jid': vc.getFrom().getStripped()} - if vc._getTag('vCard') == common.jabber.NS_VCARD: - card = vc.getChildren()[0] - for info in card.getChildren(): - if info.getChildren() == []: - vcard[info.getName()] = info.getData() - else: - vcard[info.getName()] = {} - for c in info.getChildren(): - vcard[info.getName()][c.getName()] = c.getData() - if vc.getID() in self.myVCardID: - self.myVCardID.remove(vc.getID()) - self.hub.sendPlugin('MYVCARD', self.connections[con], vcard) - else: - self.hub.sendPlugin('VCARD', self.connections[con], vcard) - - def messageCB(self, con, msg): - """Called when we recieve a message""" - 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 and USE_GPG: - #decrypt - encmsg = encTag.getData() - keyID = '' - if self.cfgParser.tab[self.connections[con]].has_key("keyid"): - keyID = self.cfgParser.tab[self.connections[con]]["keyid"] - if keyID: - decmsg = self.gpg[self.connections[con]].decrypt(encmsg, keyID) - if decmsg: - msgtxt = decmsg - if typ == 'error': - self.hub.sendPlugin('MSGERROR', self.connections[con], \ - (str(msg.getFrom()), msg.getErrorCode(), msg.getError(), msgtxt, tim)) - elif typ == 'groupchat': - subject = msg.getSubject() - if subject: - self.hub.sendPlugin('GC_SUBJECT', self.connections[con], \ - (str(msg.getFrom()), subject)) - else: - self.hub.sendPlugin('GC_MSG', self.connections[con], \ - (str(msg.getFrom()), msgtxt, tim)) - else: - self.hub.sendPlugin('MSG', self.connections[con], \ - (str(msg.getFrom()), msgtxt, tim)) - # END messageCB - - def presenceCB(self, con, prs): - """Called when we recieve a presence""" -# if prs.getXNode(common.jabber.NS_DELAY): return - who = str(prs.getFrom()) - prio = prs.getPriority() - if not prio: - prio = 0 - 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 and USE_GPG: - #verify - sigmsg = sigTag.getData() - keyID = self.gpg[self.connections[con]].verify(status, sigmsg) - if typ == 'available': - show = prs.getShow() - if not show: - show = 'online' - self.hub.sendPlugin('NOTIFY', self.connections[con], \ - (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.connections[con], \ - (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': - log.debug("subscribe request from %s" % who) - if self.cfgParser.Core['alwaysauth'] == 1 or \ - who.find("@") <= 0: - if con: - con.send(common.jabber.Presence(who, 'subscribed')) - if who.find("@") <= 0: - self.hub.sendPlugin('NOTIFY', self.connections[con], \ - (prs.getFrom().getStripped(), 'offline', 'offline', \ - prs.getFrom().getResource(), prio, keyID, None, None, None, \ - None, None, None)) - else: - if not status: - status = _("I would like to add you to my roster.") - self.hub.sendPlugin('SUBSCRIBE', self.connections[con], (who, \ - status)) - elif typ == 'subscribed': - jid = prs.getFrom() - self.hub.sendPlugin('SUBSCRIBED', self.connections[con],\ - (jid.getStripped(), jid.getResource())) - self.hub.queueIn.put(('UPDUSER', self.connections[con], \ - (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': - log.debug("unsubscribe request from %s" % who) - elif typ == 'unsubscribed': - log.debug("we are now unsubscribed to %s" % who) - self.hub.sendPlugin('UNSUBSCRIBED', self.connections[con], \ - prs.getFrom().getStripped()) - elif typ == 'error': - errmsg = prs.getError() - errcode = prs.getErrorCode() - if errcode == '400': #Bad Request: JID Malformed or Private message when not allowed - pass - elif errcode == '401': #No Password Provided - pass - elif errcode == '403': #forbidden : User is Banned - # Unauthorized Subject Change - # Attempt by Mere Member to Invite Others to a Members-Only Room - # Configuration Access to Non-Owner - # Attempt by Non-Owner to Modify Owner List - # Attempt by Non-Owner to Modify Admin List - # Destroy Request Submitted by Non-Owner - pass - elif errcode == '404': #item not found : Room Does Not Exist - pass - elif errcode == '405': #Not allowed : Attempt to Kick Moderator, Admin, or Owner - # Attempt to Ban an Admin or Owner - # Attempt to Revoke Voice from an Admin, Owner, or User with a Higher Affiliation - # Attempt to Revoke Moderator Privileges from an Admin or Owner - pass - elif errcode == '407': #registration required : User Is Not on Member List - # - pass - elif errcode == '409': #conflict : Nick Conflict - self.hub.sendPlugin('ERROR', None, errmsg) - else: - self.hub.sendPlugin('NOTIFY', self.connections[con], \ - (prs.getFrom().getStripped(), 'error', errmsg, \ - prs.getFrom().getResource(), prio, keyID, None, None, None, \ - None, None, None)) - # END presenceCB - - def disconnectedCB(self, con): - """Called when we are disconnected""" - log.debug("disconnectedCB") - if self.connections.has_key(con): - self.connected[self.connections[con]] = 0 - self.hub.sendPlugin('STATUS', self.connections[con], 'offline') - # END disconenctedCB - - def rosterSetCB(self, con, iq_obj): - for item in iq_obj.getQueryNode().getChildren(): - jid = item.getAttr('jid') - name = item.getAttr('name') - sub = item.getAttr('subscription') - ask = item.getAttr('ask') - groups = [] - for group in item.getTags("group"): - groups.append(group.getData()) - self.hub.sendPlugin('ROSTER_INFO', self.connections[con], (jid, name, sub, ask, groups)) - - def BrowseResultCB(self, con, iq_obj): - identities, features, items = [], [], [] - q = iq_obj.getTag('service') - if not q: - return identities, features, items - attr = {} - for key in q.attrs: - attr[key.encode('utf8')] = q.attrs[key].encode('utf8') - identities = [attr] - for node in q.kids: - if node.getName() == 'ns': - features.append(node.getData()) - else: - infos = {} - for key in node.attrs: - infos[key.encode('utf8')] = node.attrs[key].encode('utf8') - infos['category'] = node.getName() - items.append(infos) - jid = str(iq_obj.getFrom()) - self.hub.sendPlugin('AGENT_INFO', self.connections[con], \ - (jid, identities, features, items)) - - def DiscoverItemsCB(self, con, iq_obj): - qp = iq_obj.getQueryPayload() - items = [] - if not qp: - qp = [] - for i in qp: - attr = {} - for key in i.attrs: - attr[key.encode('utf8')] = i.attrs[key].encode('utf8') - items.append(attr) - jid = str(iq_obj.getFrom()) - self.hub.sendPlugin('AGENT_INFO_ITEMS', self.connections[con],\ - (jid, items)) - - def DiscoverInfoErrorCB(self, con, iq_obj): - jid = str(iq_obj.getFrom()) - con.browseAgents(jid) - - def DiscoverInfoCB(self, con, iq_obj): - # According to JEP-0030: - # For identity: category, name is mandatory, type is optional. - # For feature: var is mandatory - identities, features = [], [] - qp = iq_obj.getQueryPayload() - if not qp: - qp = [] - for i in qp: - if i.getName() == 'identity': - attr = {} - for key in i.attrs: - attr[key.encode('utf8')] = i.attrs[key].encode('utf8') - identities.append(attr) - elif i.getName() == 'feature': - features.append(i.getAttr('var')) - jid = str(iq_obj.getFrom()) - if not identities: - con.browseAgents(jid) - else: - self.hub.sendPlugin('AGENT_INFO_INFO', self.connections[con],\ - (jid, identities, features)) - con.discoverItems(jid) - - def VersionCB(self, con, iq_obj): - f = iq_obj.getFrom() - iq_obj.setFrom(iq_obj.getTo()) - iq_obj.setTo(f) - iq_obj.setType('result') - qp = iq_obj.getTag('query') - qp.insertTag('name').insertData('Gajim') - qp.insertTag('version').insertData(version.version) - no_send_os = True - if self.cfgParser.tab['GtkGui'].has_key('do_not_send_os_info'): - no_send_os = self.cfgParser.tab['GtkGui']['do_not_send_os_info'] - if not no_send_os: - qp.insertTag('os').insertData(get_os_info()) - con.send(iq_obj) - - def VersionResultCB(self, con, iq_obj): - client_info = '' - os_info = '' - qp = iq_obj.getTag('query') - if qp.getTag('name'): - client_info += qp.getTag('name').getData() - if qp.getTag('version'): - client_info += ' ' + qp.getTag('version').getData() - if qp.getTag('os'): - os_info += qp.getTag('os').getData() - jid = iq_obj.getFrom().getStripped() - self.hub.sendPlugin('OS_INFO', self.connections[con],\ - (jid, client_info, os_info)) - - def connect(self, account): - """Connect and authentificate to the Jabber server""" - hostname = self.cfgParser.tab[account]['hostname'] - name = self.cfgParser.tab[account]["name"] - password = self.passwords[account] - if not self.cfgParser.tab[account].has_key('resource'): - if not self.cfgParser.tab[account].has_key('ressource'): - resource = 'Gajim' - else: - resource = self.cfgParser.tab[account]['ressource'] - self.cfgParser.tab[account]['resource'] = resource - del self.cfgParser.tab[account]['ressource'] - else: - resource = self.cfgParser.tab[account]['resource'] - - #create connexion if it doesn't already existe - con = None - for conn in self.connections: - if self.connections[conn] == account: - con = conn - if not con: - if self.cfgParser.tab[account]["use_proxy"]: - proxy = {"host":self.cfgParser.tab[account]["proxyhost"]} - proxy["port"] = self.cfgParser.tab[account]["proxyport"] - else: - proxy = None - if self.log: - con = common.jabber.Client(host = hostname, debug = [], \ - log = sys.stderr, connection=common.xmlstream.TCP, port=5222, \ - proxy = proxy) - else: - con = common.jabber.Client(host = hostname, debug = [], log = None,\ - connection=common.xmlstream.TCP, port=5222, proxy = proxy) - #debug = [common.jabber.DBG_ALWAYS], log = sys.stderr, \ - #connection=common.xmlstream.TCP_SSL, port=5223, proxy = proxy) - con.setDisconnectHandler(self.disconnectedCB) - con.registerHandler('message', self.messageCB) - con.registerHandler('presence', self.presenceCB) - con.registerHandler('iq',self.vCardCB,'result')#common.jabber.NS_VCARD) - con.registerHandler('iq',self.rosterSetCB,'set', \ - common.jabber.NS_ROSTER) - con.registerHandler('iq',self.BrowseResultCB,'result', \ - common.jabber.NS_BROWSE) - con.registerHandler('iq',self.DiscoverItemsCB,'result', \ - common.jabber.NS_P_DISC_ITEMS) - con.registerHandler('iq',self.DiscoverInfoCB,'result', \ - common.jabber.NS_P_DISC_INFO) - con.registerHandler('iq',self.DiscoverInfoErrorCB,'error', \ - common.jabber.NS_P_DISC_INFO) - con.registerHandler('iq',self.VersionCB,'get', \ - common.jabber.NS_VERSION) - con.registerHandler('iq',self.VersionResultCB,'result', \ - common.jabber.NS_VERSION) - try: - con.connect() - except IOError, e: - log.debug("Couldn't connect to %s %s" % (hostname, e)) - self.hub.sendPlugin('STATUS', account, 'offline') - self.hub.sendPlugin('ERROR', None, _("Couldn't connect to %s") \ - % hostname) - return 0 - except common.xmlstream.socket.error, e: - log.debug("Couldn't connect to %s %s" % (hostname, e)) - self.hub.sendPlugin('STATUS', account, 'offline') - self.hub.sendPlugin('ERROR', None, _("Couldn't connect to %s: %s") \ - % (hostname, e)) - return 0 - except common.xmlstream.error, e: - log.debug("Couldn't connect to %s %s" % (hostname, e)) - self.hub.sendPlugin('STATUS', account, 'offline') - self.hub.sendPlugin('ERROR', None, _("Couldn't connect to %s: %s") \ - % (hostname, e)) - return 0 -# except: -# print sys.exc_info()[1] - else: - log.debug("Connected to server") - - #BUG in jabberpy library : if hostname is wrong : "boucle" - if con.auth(name, password, resource): - self.connections[con] = account - con.requestRoster() - roster = con.getRoster().getRaw() - if not roster : - roster = {} - self.hub.sendPlugin('ROSTER', account, (0, roster)) - self.connected[account] = 1 - return con - else: - log.debug("Couldn't authentificate to %s" % hostname) - self.hub.sendPlugin('STATUS', account, 'offline') - self.hub.sendPlugin('ERROR', None, \ - _("Authentification failed with %s, check your login and password") % hostname) - return 0 - # END connect - - def send_to_socket(self, ev, sock): - evp = pickle.dumps(ev) - sock.send('<'+XMLescape(evp)+'>') - - def unparse_socket(self): - list_ev = [] - while self.data: - deb = self.data.find('<') - if deb == -1: - break - end = self.data.find('>', deb) - if end == -1: - break - list_ev.append(pickle.loads(self.data[deb+1:end])) - self.data = self.data[end+1:] - return list_ev - - def request_infos(self, account, con, jid): - if con: - con.discoverInfo(jid) - - def read_queue(self): - while self.hub.queueIn.empty() == 0: - ev = self.hub.queueIn.get() - if self.mode == 'client': - #('REG_MESSAGE', module, list_message) - if ev[0] == 'REG_MESSAGE': - for msg in ev[2]: - self.hub.register(ev[1], msg) -# ready_to_read, ready_to_write, in_error = select.select( -# [], [self.socket], []) - self.send_to_socket(ev, self.socket) - return 0 - if ev[1] and (ev[1] in self.connections.values()): - for con in self.connections.keys(): - if ev[1] == self.connections[con]: - break - else: - con = None - #('QUIT', None, (plugin, kill_core ?)) kill core : 0 or 1 - if ev[0] == 'QUIT': - self.hub.unregister(ev[2][0]) - if ev[2][1]: - for con in self.connections.keys(): - if self.connected[self.connections[con]]: - self.connected[self.connections[con]] = 0 - con.disconnect('Disconnected') - self.hub.sendPlugin('QUIT', None, ()) - return 1 - #('ASK_ROSTER', account, queue_for_response) - elif ev[0] == 'ASK_ROSTER': - roster = {} - if con: - roster = con.getRoster().getRaw() - self.hub.sendPlugin('ROSTER', ev[1], (self.connected[ev[1]], \ - roster), ev[2]) - #('ASK_CONFIG', account, (who_ask, section, default_config)) - elif ev[0] == 'ASK_CONFIG': - if ev[2][1] == 'accounts': - self.hub.sendPlugin('CONFIG', None, (ev[2][0], self.accounts)) - else: - if self.cfgParser.tab.has_key(ev[2][1]): - config = self.cfgParser.__getattr__(ev[2][1]) - for item in ev[2][2].keys(): - if not config.has_key(item): - config[item] = ev[2][2][item] - else: - config = ev[2][2] - self.cfgParser.tab[ev[2][1]] = config - self.cfgParser.writeCfgFile() - config['usegpg'] = USE_GPG - self.hub.sendPlugin('CONFIG', None, (ev[2][0], config)) - #('CONFIG', account, (section, config, who_sent)) - elif ev[0] == 'CONFIG': - if ev[2][0] == 'accounts': - #Remove all old accounts - accts = self.cfgParser.tab['Profile']['accounts'].split(' ') - if accts == ['']: - accts = [] - for a in accts: - del self.cfgParser.tab[a] - #Write all new accounts - accts = ev[2][1].keys() - self.cfgParser.tab['Profile']['accounts'] = \ - ' '.join(accts) - for a in accts: - self.cfgParser.tab[a] = ev[2][1][a] - if not a in self.connected.keys(): - self.connected[a] = 0 - if not self.gpg.has_key(a) and USE_GPG: - self.gpg[a] = MyGnuPG() - if not self.passwords.keys(): - self.passwords[a] = '' - else: - self.cfgParser.tab[ev[2][0]] = ev[2][1] - if ev[2][0] != ev[2][2]: - self.hub.sendPlugin('CONFIG', None, (ev[2][0], ev[2][1])) - self.cfgParser.writeCfgFile() - #('STATUS', account, (status, msg)) - elif ev[0] == 'STATUS': - msg = ev[2][1] - if not msg: - msg = ev[2][0] - signed = '' - keyID = '' - if self.cfgParser.tab[ev[1]].has_key('keyid'): - keyID = self.cfgParser.tab[ev[1]]['keyid'] - if keyID and USE_GPG: - signed = self.gpg[ev[1]].sign(msg, keyID) - if signed == 'BAD_PASSPHRASE': - signed = '' - if self.connected[ev[1]] == 0: - self.hub.sendPlugin('BAD_PASSPHRASE', ev[1], ()) - if (ev[2][0] != 'offline') and (self.connected[ev[1]] == 0): - con = self.connect(ev[1]) - if self.connected[ev[1]]: - statuss = ['offline', 'online', 'away', 'xa', 'dnd', \ - 'invisible'] - self.connected[ev[1]] = statuss.index(ev[2][0]) - #send our presence - typ = 'available' - if ev[2][0] == 'invisible': - typ = 'invisible' - 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], msg, signed) - self.hub.sendPlugin('STATUS', ev[1], ev[2][0]) - #ask our VCard - iq = common.jabber.Iq(type="get") - iq._setTag('vCard', common.jabber.NS_VCARD) - id = con.getAnID() - iq.setID(id) - con.send(iq) - self.myVCardID.append(id) - elif (ev[2][0] == 'offline') and (self.connected[ev[1]]): - self.connected[ev[1]] = 0 - con.disconnect(msg) - self.hub.sendPlugin('STATUS', ev[1], 'offline') - elif ev[2][0] != 'offline' and self.connected[ev[1]]: - statuss = ['offline', 'online', 'away', 'xa', 'dnd', \ - 'invisible'] - self.connected[ev[1]] = statuss.index(ev[2][0]) - typ = 'available' - if ev[2][0] == 'invisible': - typ = 'invisible' - 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], msg, signed) - self.hub.sendPlugin('STATUS', ev[1], ev[2][0]) - #('MSG', account, (jid, msg, keyID)) - elif ev[0] == 'MSG': - if con: - msgtxt = ev[2][1] - msgenc = '' - if ev[2][2] and USE_GPG: - #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)) - elif ev[0] == 'SUB': - if con: - log.debug('subscription request for %s' % ev[2][0]) - pres = common.jabber.Presence(ev[2][0], 'subscribe') - if ev[2][1]: - pres.setStatus(ev[2][1]) - else: - pres.setStatus(_("I would like to add you to my roster.")) - con.send(pres) - #('REQ', account, jid) - elif ev[0] == 'AUTH': - if con: - con.send(common.jabber.Presence(ev[2], 'subscribed')) - #('DENY', account, jid) - elif ev[0] == 'DENY': - if con: - con.send(common.jabber.Presence(ev[2], 'unsubscribed')) - #('UNSUB', account, jid) - elif ev[0] == 'UNSUB': - if con: - delauth = 1 - if self.cfgParser.Core.has_key('delauth'): - delauth = self.cfgParser.Core['delauth'] - delroster = 1 - if self.cfgParser.Core.has_key('delroster'): - delroster = self.cfgParser.Core['delroster'] - if delauth: - con.send(common.jabber.Presence(ev[2], 'unsubscribe')) - if delroster: - con.removeRosterItem(ev[2]) - #('UNSUB_AGENT', account, agent) - elif ev[0] == 'UNSUB_AGENT': - if con: - con.removeRosterItem(ev[2]) - con.requestRegInfo(ev[2]) - agent_info = con.getRegInfo() - if not agent_info: - return - key = agent_info['key'] - iq = common.jabber.Iq(to=ev[2], type="set") - q = iq.setQuery(common.jabber.NS_REGISTER) - q.insertTag('remove') - q.insertTag('key').insertData(key) - id = con.getAnID() - iq.setID(id) - con.send(iq) - self.hub.sendPlugin('AGENT_REMOVED', ev[1], ev[2]) - #('UPDUSER', account, (jid, name, groups)) - elif ev[0] == 'UPDUSER': - if con: - con.updateRosterItem(jid=ev[2][0], name=ev[2][1], \ - groups=ev[2][2]) - #('REQ_AGENTS', account, jid) - elif ev[0] == 'REQ_AGENTS': - self.request_infos(ev[1], con, ev[2]) - #('REG_AGENT_INFO', account, agent) - elif ev[0] == 'REG_AGENT_INFO': - if con: - con.requestRegInfo(ev[2]) - agent_info = con.getRegInfo() - self.hub.sendPlugin('REG_AGENT_INFO', ev[1], (ev[2], agent_info)) - #('REG_AGENT', account, infos) - elif ev[0] == 'REG_AGENT': - if con: - con.sendRegInfo(ev[2]) - #('NEW_ACC', (hostname, login, password, name, resource, prio, \ - # use_proxy, proxyhost, proxyport)) - elif ev[0] == 'NEW_ACC': - if ev[2][6]: - proxy = {'host': ev[2][7], 'port': ev[2][8]} - else: - proxy = None - c = common.jabber.Client(host = ev[2][0], debug = [], \ - log = None, proxy = proxy) - try: - c.connect() - except: - log.debug("Couldn't connect to %s" % ev[2][0]) - self.hub.sendPlugin('ERROR', None, \ - _('Couldn\'t connect to ')+ev[2][0]) - return 0 - else: - log.debug("Connected to server") - c.requestRegInfo() - req = c.getRegInfo() - c.setRegInfo( 'username', ev[2][1]) - c.setRegInfo( 'password', ev[2][2]) - if not c.sendRegInfo(): - self.hub.sendPlugin('ERROR', None, _('Error: ')+c.lastErr) - else: - self.connected[ev[2][3]] = 0 - self.passwords[ev[2][3]] = '' - if USE_GPG: - self.gpg[ev[2][3]] = MyGnuPG() - self.hub.sendPlugin('ACC_OK', ev[1], ev[2]) - #('ACC_CHG', old_account, new_account) - elif ev[0] == 'ACC_CHG': - self.connected[ev[2]] = self.connected[ev[1]] - self.passwords[ev[2]] = self.passwords[ev[1]] - del self.connected[ev[1]] - del self.passwords[ev[1]] - if USE_GPG: - self.gpg[ev[2]] = self.gpg[ev[1]] - del self.gpg[ev[1]] - if con: - self.connections[con] = ev[2] - #('ASK_OS_INFO', account, (jid, resource)) - elif ev[0] == 'ASK_OS_INFO': - if con: - iq = common.jabber.Iq(to=ev[2][0]+'/'+ev[2][1], type="get", \ - query=common.jabber.NS_VERSION) - iq.setID(con.getAnID()) - con.send(iq) - #('ASK_VCARD', account, jid) - elif ev[0] == 'ASK_VCARD': - if con: - iq = common.jabber.Iq(to=ev[2], type="get") - iq._setTag('vCard', common.jabber.NS_VCARD) - iq.setID(con.getAnID()) - con.send(iq) - #('VCARD', {entry1: data, entry2: {entry21: data, ...}, ...}) - elif ev[0] == 'VCARD': - if con: - iq = common.jabber.Iq(type="set") - iq.setID(con.getAnID()) - iq2 = iq._setTag('vCard', common.jabber.NS_VCARD) - for i in ev[2].keys(): - if i != 'jid': - if type(ev[2][i]) == type({}): - iq3 = iq2.insertTag(i) - for j in ev[2][i].keys(): - iq3.insertTag(j).putData(ev[2][i][j]) - else: - iq2.insertTag(i).putData(ev[2][i]) - con.send(iq) - #('AGENT_LOGGING', account, (agent, typ)) - elif ev[0] == 'AGENT_LOGGING': - if con: - t = ev[2][1]; - if not t: - t='available'; - p = common.jabber.Presence(to=ev[2][0], type=t) - con.send(p) - #('LOG_NB_LINE', account, jid) - elif ev[0] == 'LOG_NB_LINE': - fic = open(LOGPATH + ev[2], "r") - nb = 0 - while (fic.readline()): - nb = nb+1 - fic.close() - self.hub.sendPlugin('LOG_NB_LINE', ev[1], (ev[2], nb)) - #('LOG_GET_RANGE', account, (jid, line_begin, line_end)) - elif ev[0] == 'LOG_GET_RANGE': - fic = open(LOGPATH + ev[2][0], "r") - nb = 0 - while (nb < ev[2][1] and fic.readline()): - nb = nb+1 - while nb < ev[2][2]: - line = fic.readline() - nb = nb+1 - if line: - lineSplited = line.split(':') - if len(lineSplited) > 2: - self.hub.sendPlugin('LOG_LINE', ev[1], (ev[2][0], nb, \ - lineSplited[0], lineSplited[1], lineSplited[2:])) - fic.close() - #('REG_MESSAGE', module, list_message) - elif ev[0] == 'REG_MESSAGE': - for msg in ev[2]: - self.hub.register(ev[1], msg) - elif ev[0] == 'EXEC_PLUGIN': - self.loadPlugins(ev[2]) - #('GC_JOIN', account, (nick, room, server, passwd)) - elif ev[0] == 'GC_JOIN': - if con: - p = common.jabber.Presence(to='%s@%s/%s' % (ev[2][1], ev[2][2], \ - ev[2][0])) - con.send(p) - #('GC_MSG', account, (jid, msg)) - elif ev[0] == 'GC_MSG': - if con: - msg = common.jabber.Message(ev[2][0], ev[2][1]) - msg.setType('groupchat') - con.send(msg) - self.hub.sendPlugin('MSGSENT', ev[1], ev[2]) - #('GC_SUBJECT', account, (jid, subject)) - elif ev[0] == 'GC_SUBJECT': - if con: - msg = common.jabber.Message(ev[2][0]) - msg.setType('groupchat') - msg.setSubject(ev[2][1]) - con.send(msg) - #('GC_STATUS', account, (nick, jid, show, status)) - elif ev[0] == 'GC_STATUS': - if con: - if ev[2][2] == 'offline': - con.send(common.jabber.Presence(to = '%s/%s' % (ev[2][1], \ - ev[2][0]), type = 'unavailable', status = ev[2][3])) - else: - con.send(common.jabber.Presence(to = '%s/%s' % (ev[2][1], \ - ev[2][0]), type = 'available', show = ev[2][2], status = \ - ev[2][3])) - #('GC_SET_ROLE', account, (room_jid, nick, role)) - elif ev[0] == 'GC_SET_ROLE': - if con: - iq = common.jabber.Iq(type='set', to=ev[2][0]) - item = iq.setQuery(common.jabber.NS_P_MUC_ADMIN).\ - insertTag('item') - item.putAttr('nick', ev[2][1]) - item.putAttr('role', ev[2][2]) - id = con.getAnID() - iq.setID(id) - con.send(iq) - #('GC_SET_AFFILIATION', account, (room_jid, jid, affiliation)) - elif ev[0] == 'GC_SET_AFFILIATION': - if con: - iq = common.jabber.Iq(type='set', to=ev[2][0]) - item = iq.setQuery(common.jabber.NS_P_MUC_ADMIN).\ - insertTag('item') - item.putAttr('jid', ev[2][1]) - item.putAttr('affiliation', ev[2][2]) - id = con.getAnID() - iq.setID(id) - con.send(iq) - #('GPGPASSPHRASE', account, passphrase) - elif ev[0] == 'GPGPASSPHRASE': - if USE_GPG: - self.gpg[ev[1]].passphrase = ev[2] - elif ev[0] == 'GPG_SECRETE_KEYS': - if USE_GPG: - keys = self.gpg_common.get_secret_keys() - self.hub.sendPlugin('GPG_SECRETE_KEYS', ev[1], keys) - elif ev[0] == 'PASSPHRASE': - self.passwords[ev[1]] = ev[2] - #('CHANGE_PASSWORD', account, (new_password, username)) - elif ev[0] == 'CHANGE_PASSWORD': - if con: - hostname = self.cfgParser.tab[ev[1]]['hostname'] - iq = common.jabber.Iq(type='set', to=hostname) - q = iq.setQuery(common.jabber.NS_REGISTER) - q.insertTag('username').insertData(ev[2][1]) - q.insertTag('password').insertData(ev[2][0]) - id = con.getAnID() - iq.setID(id) - con.send(iq) - else: - log.debug(_("Unknown Command %s") % ev[0]) - if self.mode == 'server': - for con in self.connections: - if self.connected[self.connections[con]]: - con.process(1) - #remove connexion that have been broken - for acc in self.connected: - if self.connected[acc]: - break - for con in self.connections: - if self.connections[con] == acc: - del self.connections[con] - break - - time.sleep(0.1) - return 0 - - # END read_queue - - def read_socket(self): - ready_to_read, ready_to_write, in_error = select.select( - [self.socket], [], [], 0.1) - for sock in ready_to_read: - self.data += sock.recv(1024) - if not self.data: - continue - while len(self.data) == 1024: - self.data += sock.recv(1024) - list_ev = self.unparse_socket() - for ev in list_ev: - self.hub.sendPlugin(ev[0], ev[1], ev[2]) - if ev[0] == 'QUIT': - sock.close() - return 1 - return 0 - # END read_socket - - - def mainLoop(self): - """Main Loop : Read the incomming queue to execute commands comming from - plugins and process Jabber""" - end = 0 - while not end: - end = self.read_queue() - if self.mode == 'client': - end = self.read_socket() - # END main -# END GajimCore - -def start(mode='server'): - """Start the Core""" - gc = GajimCore(mode) - try: - gc.mainLoop() - except KeyboardInterrupt: - print _("Keyboard Interrupt : Bye!") - gc.hub.sendPlugin('QUIT', None, ()) - return 0 -# except: -# print "Erreur survenue" -# gc.hub.sendPlugin('QUIT', ()) -# END start diff --git a/common/hub.py b/common/hub.py deleted file mode 100644 index c0178b1f94..0000000000 --- a/common/hub.py +++ /dev/null @@ -1,104 +0,0 @@ -## common/hub.py -## -## Gajim Team: -## - Yann Le Boulanger <asterix@lagaule.org> -## - Vincent Hanquez <tab@snarc.org> -## -## Copyright (C) 2003-2005 Gajim Team -## -## This program is free software; you can redistribute it and/or modify -## it under the terms of the GNU General Public License as published -## by the Free Software Foundation; version 2 only. -## -## This program is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License for more details. -## - -import Queue -import common.plugin -import common.thread - -""" Hub definitions """ - -class GajimHub: - def __init__(self): - self.queues = {} - # {event1:[queue1, queue2]} - self.events = {} - self.queueIn = self.newQueue('in', 100) - self.saveQueue = Queue.Queue(100) - self.events_to_store = ['WARNING', 'MSG', 'MSGERROR', 'SUBSCRIBED', 'UNSUBSCRIBED', 'SUBSCRIBE'] - self.queue_to_send = None - # END __init__ - - def newQueue(self, name, size): - """ Creates a new queue """ - qu = Queue.Queue(size) - self.queues[name] = qu - return qu - # END newQueue - - def newPlugin(self, name): - """Creates a new Plugin """ - if name in self.queues.keys(): - return 0 - qu = self.newQueue(name, 100) - pl = common.plugin.GajimPlugin(name, qu, self.queueIn) - return pl - # END newPlugin - - def register(self, name, event): - """ Records a plugin from an event """ - if not self.queues.has_key(name): - return - qu = self.queues[name] - if event == 'VISUAL' and not self.saveQueue.empty(): - # we save the queue in whitch we must send saved events - # after the roster is sent - self.queue_to_send = qu - if self.events.has_key(event): - if not qu in self.events[event]: - self.events[event].append(qu) - else : - self.events[event] = [qu] - # END register - - def unregisterEvents(self, name, event): - """ Records a plugin from an event """ - if not self.queues.has_key(name): - return - qu = self.queues[name] - if self.events.has_key(event) : - if qu in self.events[event]: - self.events[event].remove(qu) - # END register - - def unregister(self, name): - if not self.queues.has_key(name): - return - qu = self.queues[name] - for event in self.events: - if qu in self.events[event]: - self.events[event].remove(qu) - del self.queues[name] - # END unregister - - def sendPlugin(self, event, con, data, qu=None): - """ Sends an event to registered plugins""" - if self.events.has_key(event): - if event in self.events_to_store and len(self.events['VISUAL']) == 0: - # Save event if no visual plugin is registered - self.saveQueue.put((event, con, data)) - for queue in self.events[event]: - if qu == None or qu == queue: - queue.put((event, con, data)) - if event == 'ROSTER' and self.queue_to_send in self.events[event]: - # send saved events - while not self.saveQueue.empty(): - ev = self.saveQueue.get() - self.queue_to_send.put(ev) - self.queue_to_send = None - # END sendPlugin -# END GajimHub diff --git a/common/plugin.py b/common/plugin.py deleted file mode 100644 index e7a8a3c220..0000000000 --- a/common/plugin.py +++ /dev/null @@ -1,36 +0,0 @@ -## common/plugin.py -## -## Gajim Team: -## - Yann Le Boulanger <asterix@lagaule.org> -## - Vincent Hanquez <tab@snarc.org> -## -## Copyright (C) 2003-2005 Gajim Team -## -## This program is free software; you can redistribute it and/or modify -## it under the terms of the GNU General Public License as published -## by the Free Software Foundation; version 2 only. -## -## This program is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License for more details. -## - -import common.thread - -""" Plugin definitions """ - -class GajimPlugin: - def __init__(self, name, queueIn, queueOut): - """ queueIn is a queue to interact from the hub to the plugin """ - self.name = name - self.queueIn = queueIn - self.queueOut= queueOut - # END __init__ - - def load(self): - thr = common.thread.GajimThread(self.name, self.queueIn, self.queueOut) -# thr.setDaemon(1) - thr.start() - # END load -# END GajimPlugin diff --git a/common/thread.py b/common/thread.py deleted file mode 100644 index 1bc680e541..0000000000 --- a/common/thread.py +++ /dev/null @@ -1,40 +0,0 @@ -## common/thread.py -## -## Gajim Team: -## - Yann Le Boulanger <asterix@lagaule.org> -## - Vincent Hanquez <tab@snarc.org> -## -## Copyright (C) 2003-2005 Gajim Team -## -## This program is free software; you can redistribute it and/or modify -## it under the terms of the GNU General Public License as published -## by the Free Software Foundation; version 2 only. -## -## This program is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License for more details. -## - -import threading -import socket -import time -import sys -from common import i18n -_ = i18n._ - -class GajimThread(threading.Thread): - def __init__(self, name = None, queueIn = None, queueOut = None): - self.queueIn = queueIn - self.queueOut = queueOut - threading.Thread.__init__(self, target = self.run, name = name) - # END __init__ - - def run(self): - mod = compile('import plugins.%s' % self.getName(), self.getName(), 'exec') - res = eval(mod) - mod = compile('plugins.%s.%s.plugin(self.queueIn, self.queueOut)' - % (self.getName(), self.getName()), self.getName(), 'exec') - res = eval(mod) - # END run -# END GajimThread -- GitLab