gajim-plural/Core/core.py

1066 lines
33 KiB
Python
Raw Normal View History

2003-10-22 22:23:45 +02:00
## core/core.py
##
## Gajim Team:
## - Yann Le Boulanger <asterix@lagaule.org>
2004-06-18 11:25:15 +02:00
## - Vincent Hanquez <tab@snarc.org>
## - Nikos Kouremenos <nkour@jabber.org>
2003-10-22 22:23:45 +02:00
##
## Copyright (C) 2003-2005 Gajim Team
2003-10-22 22:23:45 +02:00
##
## 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
2003-11-30 16:50:23 +01:00
import common.hub
import common.optparser
2003-10-22 22:23:45 +02:00
import common.jabber
import socket
import select
import pickle
2004-12-20 22:07:50 +01:00
from tempfile import *
2003-10-22 22:23:45 +02:00
2004-05-17 01:47:14 +02:00
from common import i18n
_ = i18n._
2003-10-22 22:23:45 +02:00
log = logging.getLogger('core.core')
log.setLevel(logging.DEBUG)
2003-11-30 16:50:23 +01:00
2004-01-18 23:56:28 +01:00
CONFPATH = "~/.gajim/config"
LOGPATH = os.path.expanduser("~/.gajim/logs/")
2003-10-22 22:23:45 +02:00
def XMLescape(txt):
"Escape XML entities"
txt = txt.replace("&", "&amp;")
txt = txt.replace("<", "&lt;")
txt = txt.replace(">", "&gt;")
return txt
def XMLunescape(txt):
"Unescape XML entities"
txt = txt.replace("&gt;", ">")
txt = txt.replace("&lt;", "<")
txt = txt.replace("&amp;", "&")
return txt
2004-10-16 11:37:32 +02:00
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')
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()
2004-10-16 11:37:32 +02:00
if line[0:9] == '[GNUPG:] ':
# Chop off the prefix
line = line[9:]
L = line.split(None, 1)
2004-10-16 11:37:32 +02:00
keyword = L[0]
if len(L) > 1:
resp[ keyword ] = L[1]
else:
resp[ keyword ] = ""
return resp
2004-10-07 16:43:59 +02:00
2004-10-16 11:37:32 +02:00
def encrypt(self, string, recipients):
self.options.recipients = recipients # a list!
2004-10-07 16:43:59 +02:00
2004-10-16 11:37:32 +02:00
proc = self.run(['--encrypt'], create_fhs=['stdin', 'stdout'])
proc.handles['stdin'].write(string)
proc.handles['stdin'].close()
2004-10-07 16:43:59 +02:00
2004-10-16 11:37:32 +02:00
output = proc.handles['stdout'].read()
proc.handles['stdout'].close()
2004-10-07 16:43:59 +02:00
2004-10-16 11:37:32 +02:00
try: proc.wait()
except IOError: pass
return self.stripHeaderFooter(output)
2004-10-07 16:43:59 +02:00
2004-10-16 11:37:32 +02:00
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()
2004-10-07 16:43:59 +02:00
2004-10-16 11:37:32 +02:00
output = proc.handles['stdout'].read()
proc.handles['stdout'].close()
2004-10-07 16:43:59 +02:00
2004-10-16 11:37:32 +02:00
resp = proc.handles['status'].read()
proc.handles['status'].close()
2004-10-07 16:43:59 +02:00
2004-10-16 11:37:32 +02:00
try: proc.wait()
except IOError: pass
return output
2004-10-07 16:43:59 +02:00
2004-10-16 11:37:32 +02:00
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):
2005-01-15 12:04:53 +01:00
if not str:
return ''
2004-12-20 22:07:50 +01:00
file = TemporaryFile(prefix='gajim')
2004-10-16 11:37:32 +02:00
fd = file.fileno()
file.write(str)
file.seek(0)
2004-10-07 16:43:59 +02:00
2004-10-16 11:37:32 +02:00
proc = self.run(['--verify', '--enable-special-filenames', '-', '-&%s'%fd], create_fhs=['stdin', 'status', 'stderr'])
file.close()
2004-10-16 11:37:32 +02:00
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]
2004-10-16 11:37:32 +02:00
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')
2004-10-16 11:37:32 +02:00
for line in lines:
sline = line.split(':')
2004-10-16 11:37:32 +02:00
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')
2004-10-16 11:37:32 +02:00
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])
2004-10-16 11:37:32 +02:00
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
2004-10-07 16:43:59 +02:00
2003-10-22 22:23:45 +02:00
class GajimCore:
2004-01-17 16:38:29 +01:00
"""Core"""
def __init__(self, mode='client'):
self.mode = mode
self.log = 0
2004-02-25 01:33:06 +01:00
self.init_cfg_file()
if mode == 'client':
self.data = ''
self.connect_core()
2003-10-22 22:23:45 +02:00
self.hub = common.hub.GajimHub()
if self.log:
log.setLevel(logging.DEBUG)
else:
log.setLevel(None)
if mode == 'server':
self.connected = {}
2005-03-07 18:01:56 +01:00
#connections {con: name, ...}
self.connections = {}
2004-10-07 16:43:59 +02:00
self.gpg = {}
self.passwords = {}
2004-10-16 11:37:32 +02:00
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] = ' '
2004-10-16 11:37:32 +02:00
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'])
2003-10-22 22:23:45 +02:00
# 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:
2004-09-06 17:30:44 +02:00
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
2004-02-25 01:33:06 +01:00
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'}}
2004-02-25 01:33:06 +01:00
fname = os.path.expanduser(CONFPATH)
reps = fname.split('/')
2004-02-25 01:33:06 +01:00
path = ''
while len(reps) > 1:
2004-10-21 17:11:29 +02:00
path = path + reps[0] + '/'
2004-02-25 01:33:06 +01:00
del reps[0]
try:
os.stat(os.path.expanduser(path))
except OSError:
try:
os.mkdir(os.path.expanduser(path))
except:
2004-05-17 01:47:14 +02:00
print _("Can't create %s") % path
2004-02-25 01:33:06 +01:00
sys.exit
try:
os.stat(fname)
except:
2004-05-17 01:47:14 +02:00
print _("creating %s") % fname
2004-02-25 01:33:06 +01:00
fic = open(fname, "w")
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]
2005-02-27 00:16:42 +01:00
self.parse()
2004-02-25 01:33:06 +01:00
# 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'):
2005-03-06 02:12:28 +01:00
accts = self.cfgParser.tab['Profile']['accounts'].split(' ')
if accts == ['']:
accts = []
for a in accts:
self.accounts[a] = self.cfgParser.tab[a]
2004-02-18 22:03:45 +01:00
def vCardCB(self, con, vc):
"""Called when we recieve a vCard
Parse the vCard and send it to plugins"""
2004-10-07 16:43:59 +02:00
vcard = {'jid': vc.getFrom().getStripped()}
if vc._getTag('vCard') == common.jabber.NS_VCARD:
2004-02-18 22:03:45 +01:00
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())
2005-03-07 18:01:56 +01:00
self.hub.sendPlugin('MYVCARD', self.connections[con], vcard)
else:
2005-03-07 18:01:56 +01:00
self.hub.sendPlugin('VCARD', self.connections[con], vcard)
2004-02-18 22:03:45 +01:00
2003-10-22 22:23:45 +02:00
def messageCB(self, con, msg):
2004-01-17 16:38:29 +01:00
"""Called when we recieve a message"""
typ = msg.getType()
tim = msg.getTimestamp()
tim = time.strptime(tim, "%Y%m%dT%H:%M:%S")
2004-10-07 16:43:59 +02:00
msgtxt = msg.getBody()
xtags = msg.getXNodes()
encTag = None
decmsg = ''
for xtag in xtags:
if xtag.getNamespace() == common.jabber.NS_XENCRYPTED:
encTag = xtag
break
2004-10-16 11:37:32 +02:00
if encTag and USE_GPG:
2004-10-07 16:43:59 +02:00
#decrypt
encmsg = encTag.getData()
keyID = ''
2005-03-07 18:01:56 +01:00
if self.cfgParser.tab[self.connections[con]].has_key("keyid"):
keyID = self.cfgParser.tab[self.connections[con]]["keyid"]
2004-10-07 16:43:59 +02:00
if keyID:
2005-03-07 18:01:56 +01:00
decmsg = self.gpg[self.connections[con]].decrypt(encmsg, keyID)
2004-10-07 16:43:59 +02:00
if decmsg:
msgtxt = decmsg
if typ == 'error':
2005-03-07 18:01:56 +01:00
self.hub.sendPlugin('MSGERROR', self.connections[con], \
2004-10-07 16:43:59 +02:00
(str(msg.getFrom()), msg.getErrorCode(), msg.getError(), msgtxt, tim))
elif typ == 'groupchat':
2005-03-04 22:27:45 +01:00
subject = msg.getSubject()
if subject:
2005-03-07 18:01:56 +01:00
self.hub.sendPlugin('GC_SUBJECT', self.connections[con], \
2005-03-04 22:27:45 +01:00
(str(msg.getFrom()), subject))
else:
2005-03-07 18:01:56 +01:00
self.hub.sendPlugin('GC_MSG', self.connections[con], \
2005-03-04 22:27:45 +01:00
(str(msg.getFrom()), msgtxt, tim))
2004-07-08 21:46:24 +02:00
else:
2005-03-07 18:01:56 +01:00
self.hub.sendPlugin('MSG', self.connections[con], \
2004-10-07 16:43:59 +02:00
(str(msg.getFrom()), msgtxt, tim))
2003-10-22 22:23:45 +02:00
# END messageCB
def presenceCB(self, con, prs):
2004-01-17 16:38:29 +01:00
"""Called when we recieve a presence"""
# if prs.getXNode(common.jabber.NS_DELAY): return
2003-10-22 22:23:45 +02:00
who = str(prs.getFrom())
prio = prs.getPriority()
if not prio:
prio = 0
2004-08-02 11:11:50 +02:00
typ = prs.getType()
if typ == None: typ = 'available'
log.debug("PresenceCB : %s" % typ)
2004-10-07 16:43:59 +02:00
xtags = prs.getXNodes()
sigTag = None
keyID = ''
status = prs.getStatus()
for xtag in xtags:
if xtag.getNamespace() == common.jabber.NS_XSIGNED:
sigTag = xtag
break
2004-10-16 11:37:32 +02:00
if sigTag and USE_GPG:
2004-10-07 16:43:59 +02:00
#verify
sigmsg = sigTag.getData()
2005-03-07 18:01:56 +01:00
keyID = self.gpg[self.connections[con]].verify(status, sigmsg)
2004-08-02 11:11:50 +02:00
if typ == 'available':
show = prs.getShow()
if not show:
2003-10-22 22:23:45 +02:00
show = 'online'
2005-03-07 18:01:56 +01:00
self.hub.sendPlugin('NOTIFY', self.connections[con], \
2004-10-07 16:43:59 +02:00
(prs.getFrom().getStripped(), show, status, \
prs.getFrom().getResource(), prio, keyID, prs.getRole(), \
prs.getAffiliation(), prs.getJid(), prs.getReason(), \
prs.getActor(), prs.getStatusCode()))
2004-08-02 11:11:50 +02:00
elif typ == 'unavailable':
2005-03-07 18:01:56 +01:00
self.hub.sendPlugin('NOTIFY', self.connections[con], \
2004-10-07 16:43:59 +02:00
(prs.getFrom().getStripped(), 'offline', status, \
prs.getFrom().getResource(), prio, keyID, prs.getRole(), \
prs.getAffiliation(), prs.getJid(), prs.getReason(), \
prs.getActor(), prs.getStatusCode()))
2004-08-02 11:11:50 +02:00
elif typ == 'subscribe':
2003-10-27 17:30:37 +01:00
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:
2005-03-07 18:01:56 +01:00
self.hub.sendPlugin('NOTIFY', self.connections[con], \
2004-10-07 16:43:59 +02:00
(prs.getFrom().getStripped(), 'offline', 'offline', \
prs.getFrom().getResource(), prio, keyID, None, None, None, \
None, None, None))
else:
2004-10-07 16:43:59 +02:00
if not status:
status = _("I would like to add you to my roster.")
2005-03-07 18:01:56 +01:00
self.hub.sendPlugin('SUBSCRIBE', self.connections[con], (who, \
2004-10-07 16:43:59 +02:00
status))
2004-08-02 11:11:50 +02:00
elif typ == 'subscribed':
jid = prs.getFrom()
2005-03-07 18:01:56 +01:00
self.hub.sendPlugin('SUBSCRIBED', self.connections[con],\
(jid.getStripped(), jid.getResource()))
2005-03-07 18:01:56 +01:00
self.hub.queueIn.put(('UPDUSER', self.connections[con], \
2004-10-07 16:43:59 +02:00
(jid.getStripped(), jid.getNode(), ['general'])))
2004-03-16 16:39:36 +01:00
#BE CAREFUL : no con.updateRosterItem() in a callback
2003-10-27 17:30:37 +01:00
log.debug("we are now subscribed to %s" % who)
2004-08-02 11:11:50 +02:00
elif typ == 'unsubscribe':
2003-10-27 17:30:37 +01:00
log.debug("unsubscribe request from %s" % who)
2004-08-02 11:11:50 +02:00
elif typ == 'unsubscribed':
2003-10-27 17:30:37 +01:00
log.debug("we are now unsubscribed to %s" % who)
2005-03-07 18:01:56 +01:00
self.hub.sendPlugin('UNSUBSCRIBED', self.connections[con], \
2004-10-07 16:43:59 +02:00
prs.getFrom().getStripped())
2004-08-02 11:11:50 +02:00
elif typ == 'error':
2004-09-06 17:30:44 +02:00
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('WARNING', None, errmsg)
else:
2005-03-07 18:01:56 +01:00
self.hub.sendPlugin('NOTIFY', self.connections[con], \
2004-10-07 16:43:59 +02:00
(prs.getFrom().getStripped(), 'error', errmsg, \
prs.getFrom().getResource(), prio, keyID, None, None, None, \
None, None, None))
2003-10-22 22:23:45 +02:00
# END presenceCB
def disconnectedCB(self, con):
2004-01-17 16:38:29 +01:00
"""Called when we are disconnected"""
2003-10-22 22:23:45 +02:00
log.debug("disconnectedCB")
2005-03-07 18:01:56 +01:00
if self.connections.has_key(con):
self.connected[self.connections[con]] = 0
self.hub.sendPlugin('STATUS', self.connections[con], 'offline')
2003-10-22 22:23:45 +02:00
# 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())
2005-03-07 18:01:56 +01:00
self.hub.sendPlugin('ROSTER_INFO', self.connections[con], (jid, name, sub, ask, groups))
2003-11-30 23:40:24 +01:00
def connect(self, account):
2004-01-17 16:38:29 +01:00
"""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
2005-03-07 18:01:56 +01:00
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)
2003-10-22 22:23:45 +02:00
try:
2004-03-16 16:39:36 +01:00
con.connect()
2003-10-22 22:23:45 +02:00
except IOError, e:
log.debug("Couldn't connect to %s %s" % (hostname, e))
2004-03-16 16:39:36 +01:00
self.hub.sendPlugin('STATUS', account, 'offline')
2004-05-17 01:47:14 +02:00
self.hub.sendPlugin('WARNING', None, _("Couldn't connect to %s") \
2004-03-16 16:39:36 +01:00
% hostname)
return 0
2004-02-17 19:06:18 +01:00
except common.xmlstream.socket.error, e:
2004-01-17 16:38:29 +01:00
log.debug("Couldn't connect to %s %s" % (hostname, e))
2004-03-16 16:39:36 +01:00
self.hub.sendPlugin('STATUS', account, 'offline')
2004-05-17 01:47:14 +02:00
self.hub.sendPlugin('WARNING', None, _("Couldn't connect to %s : %s") \
2004-03-16 16:39:36 +01:00
% (hostname, e))
2004-01-17 16:38:29 +01:00
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('WARNING', None, _("Couldn't connect to %s : %s") \
% (hostname, e))
return 0
2004-10-16 11:37:32 +02:00
# except:
# print sys.exc_info()[1]
2003-10-22 22:23:45 +02:00
else:
log.debug("Connected to server")
#BUG in jabberpy library : if hostname is wrong : "boucle"
2005-03-09 17:48:21 +01:00
if con.auth(name, password, resource):
2005-03-07 18:01:56 +01:00
self.connections[con] = account
2004-03-16 16:39:36 +01:00
con.requestRoster()
roster = con.getRoster().getRaw()
2003-11-02 22:39:40 +01:00
if not roster :
roster = {}
self.hub.sendPlugin('ROSTER', account, (0, roster))
2004-03-16 16:39:36 +01:00
self.connected[account] = 1
2004-03-16 19:53:49 +01:00
return con
2003-10-22 22:23:45 +02:00
else:
log.debug("Couldn't authentificate to %s" % hostname)
2004-03-16 16:39:36 +01:00
self.hub.sendPlugin('STATUS', account, 'offline')
self.hub.sendPlugin('WARNING', None, \
2004-05-17 01:47:14 +02:00
_("Authentification failed with %s, check your login and password") % hostname)
return 0
2003-10-22 22:23:45 +02:00
# 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):
identities, features = con.discoverInfo(jid)
if not identities:
2004-10-16 11:37:32 +02:00
identities, features, items = con.browseAgents(jid)
else:
items = con.discoverItems(jid)
self.hub.sendPlugin('AGENT_INFO', account, (jid, identities, features, items))
for item in items:
self.request_infos(account, con, item['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
2005-03-07 18:01:56 +01:00
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]:
2005-03-07 18:01:56 +01:00
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))
2004-03-22 14:09:59 +01:00
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:
2004-10-16 11:37:32 +02:00
config = ev[2][2]
self.cfgParser.tab[ev[2][1]] = config
self.cfgParser.writeCfgFile()
2004-10-16 11:37:32 +02:00
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
2005-03-06 02:12:28 +01:00
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
2004-10-16 11:37:32 +02:00
if not self.gpg.has_key(a) and USE_GPG:
self.gpg[a] = MyGnuPG()
if not self.passwords.keys():
2004-11-23 15:14:58 +01:00
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]
2004-10-07 16:43:59 +02:00
signed = ''
keyID = ''
if self.cfgParser.tab[ev[1]].has_key('keyid'):
keyID = self.cfgParser.tab[ev[1]]['keyid']
2004-10-16 11:37:32 +02:00
if keyID and USE_GPG:
2004-10-11 18:28:12 +02:00
signed = self.gpg[ev[1]].sign(msg, keyID)
2004-10-07 16:43:59 +02:00
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
2004-08-02 11:11:50 +02:00
typ = 'available'
2004-05-31 20:12:57 +02:00
if ev[2][0] == 'invisible':
2004-08-02 11:11:50 +02:00
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)
2004-03-16 16:39:36 +01:00
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])
2004-08-02 11:11:50 +02:00
typ = 'available'
if ev[2][0] == 'invisible':
2004-08-02 11:11:50 +02:00
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])
2004-10-07 16:43:59 +02:00
#('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, ())
elif ev[0] == 'REQ_AGENTS':
2004-10-16 14:19:46 +02:00
config = self.cfgParser.__getattr__(ev[1])
self.request_infos(ev[1], con, config['hostname'])
#('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])
2005-03-09 17:48:21 +01:00
#('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 IOError, e:
log.debug("Couldn't connect to %s %s" % (hostname, e))
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('WARNING', 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]]
2004-10-16 11:37:32 +02:00
if USE_GPG:
self.gpg[ev[2]] = self.gpg[ev[1]]
del self.gpg[ev[1]]
if con:
2005-03-07 18:01:56 +01:00
self.connections[con] = ev[2]
#('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)
2004-08-02 11:11:50 +02:00
#('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])
2005-03-04 22:27:45 +01:00
#('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':
2004-10-16 11:37:32 +02:00
if USE_GPG:
self.gpg[ev[1]].passphrase = ev[2]
elif ev[0] == 'GPG_SECRETE_KEYS':
2004-10-16 11:37:32 +02:00
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]
2005-03-04 14:10:00 +01:00
#('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)
2004-03-16 16:39:36 +01:00
else:
log.debug(_("Unknown Command %s") % ev[0])
if self.mode == 'server':
2005-03-07 18:01:56 +01:00
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
2005-03-07 18:01:56 +01:00
for con in self.connections:
if self.connections[con] == acc:
del self.connections[con]
break
2003-10-22 22:23:45 +02:00
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
2003-10-22 22:23:45 +02:00
2003-11-30 16:50:23 +01:00
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
2003-11-30 16:50:23 +01:00
def start(mode='server'):
2004-01-17 16:38:29 +01:00
"""Start the Core"""
gc = GajimCore(mode)
2004-01-17 16:38:29 +01:00
try:
gc.mainLoop()
except KeyboardInterrupt:
2004-05-17 01:47:14 +02:00
print _("Keyboard Interrupt : Bye!")
2004-03-16 16:39:36 +01:00
gc.hub.sendPlugin('QUIT', None, ())
2004-01-17 16:38:29 +01:00
return 0
2004-02-17 19:06:18 +01:00
# except:
# print "Erreur survenue"
# gc.hub.sendPlugin('QUIT', ())
2003-11-30 16:50:23 +01:00
# END start