2005-04-12 23:09:06 +02:00
|
|
|
## common/connection.py
|
2005-04-12 13:46:20 +02:00
|
|
|
##
|
|
|
|
## 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
|
2005-05-18 18:42:28 +02:00
|
|
|
import sre
|
2005-05-20 19:30:29 +02:00
|
|
|
import traceback
|
2005-04-27 20:26:31 +02:00
|
|
|
from calendar import timegm
|
2005-04-12 13:46:20 +02:00
|
|
|
|
2005-04-26 20:45:54 +02:00
|
|
|
import common.xmpp
|
2005-04-12 13:46:20 +02:00
|
|
|
|
2005-04-14 09:42:26 +02:00
|
|
|
from common import gajim
|
|
|
|
from common import GnuPG
|
2005-04-13 11:41:44 +02:00
|
|
|
USE_GPG = GnuPG.USE_GPG
|
2005-04-12 13:46:20 +02:00
|
|
|
|
|
|
|
from common import i18n
|
|
|
|
_ = i18n._
|
|
|
|
|
|
|
|
|
2005-04-30 10:48:50 +02:00
|
|
|
STATUS_LIST = ['offline', 'connecting', 'online', 'chat', 'away', 'xa', 'dnd',
|
2005-04-12 13:46:20 +02:00
|
|
|
'invisible']
|
|
|
|
|
|
|
|
distro_info = {
|
2005-04-19 15:14:41 +02:00
|
|
|
'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',
|
|
|
|
'Linux from Scratch': '/etc/lfs-release',
|
|
|
|
'Mandrake Linux': '/etc/mandrake-release',
|
|
|
|
'Slackware Linux': '/etc/slackware-release',
|
|
|
|
'Slackware Linux': '/etc/slackware-version',
|
|
|
|
'Solaris/Sparc': '/etc/release',
|
2005-05-18 19:02:46 +02:00
|
|
|
'SUSE Linux': '/etc/SuSE-release',
|
2005-04-19 15:14:41 +02:00
|
|
|
'Sun JDS': '/etc/sun-release',
|
|
|
|
'PLD Linux': '/etc/pld-release',
|
|
|
|
'Yellow Dog Linux': '/etc/yellowdog-release',
|
2005-04-12 13:46:20 +02:00
|
|
|
# many distros use the /etc/redhat-release for compatibility
|
|
|
|
# so Redhat is the last
|
2005-04-19 15:14:41 +02:00
|
|
|
'Redhat Linux': '/etc/redhat-release'
|
2005-04-12 13:46:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
def get_os_info():
|
2005-04-17 01:15:03 +02:00
|
|
|
if os.name == 'nt':
|
2005-04-19 15:14:41 +02:00
|
|
|
win_version = {
|
|
|
|
(1, 4, 0): '95',
|
|
|
|
(1, 4, 10): '98',
|
|
|
|
(1, 4, 90): 'ME',
|
|
|
|
(2, 4, 0): 'NT',
|
|
|
|
(2, 5, 0): '2000',
|
2005-04-17 01:15:03 +02:00
|
|
|
(2, 5, 1): 'XP'
|
2005-04-19 15:14:41 +02:00
|
|
|
}[ os.sys.getwindowsversion()[3],
|
|
|
|
os.sys.getwindowsversion()[0],
|
2005-04-17 01:15:03 +02:00
|
|
|
os.sys.getwindowsversion()[1] ]
|
|
|
|
return 'Windows' + ' ' + win_version
|
2005-04-26 20:45:54 +02:00
|
|
|
elif os.name == 'posix':
|
2005-04-12 13:46:20 +02:00
|
|
|
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()
|
2005-05-18 18:42:28 +02:00
|
|
|
# some distros put n/a in places so remove them
|
2005-05-20 18:46:07 +02:00
|
|
|
pattern = sre.compile(r' n/a', sre.IGNORECASE)
|
2005-05-18 18:42:28 +02:00
|
|
|
output = sre.sub(pattern, '', output)
|
2005-04-12 13:46:20 +02:00
|
|
|
return output
|
|
|
|
# lsb_release executable not available, so parse files
|
2005-04-19 15:14:41 +02:00
|
|
|
for distro_name in distro_info:
|
|
|
|
path_to_file = distro_info[distro_name]
|
2005-04-12 13:46:20 +02:00
|
|
|
if os.path.exists(path_to_file):
|
|
|
|
fd = open(path_to_file)
|
|
|
|
text = fd.read().strip()
|
|
|
|
fd.close()
|
|
|
|
if path_to_file.endswith('version'):
|
2005-04-19 15:14:41 +02:00
|
|
|
text = distro_name + ' ' + text
|
|
|
|
elif path_to_file.endswith('aurox-release'): # file doesn't have version
|
|
|
|
text = distro_name
|
|
|
|
elif path_to_file.endswith('lfs-release'): # file just has version
|
|
|
|
text = distro_name + ' ' + text
|
2005-04-12 13:46:20 +02:00
|
|
|
return text
|
2005-05-11 13:09:53 +02:00
|
|
|
return 'N/A'
|
2005-04-12 13:46:20 +02:00
|
|
|
|
2005-04-19 15:14:41 +02:00
|
|
|
class Connection:
|
|
|
|
"""Connection class"""
|
2005-04-14 11:38:08 +02:00
|
|
|
def __init__(self, name):
|
2005-04-12 13:46:20 +02:00
|
|
|
# dict of function to be calledfor each event
|
2005-05-08 22:56:11 +02:00
|
|
|
self.handlers = {'ROSTER': [], 'WARNING': [], 'ERROR': [], 'STATUS': [],
|
|
|
|
'NOTIFY': [], 'MSG': [], 'MSGERROR': [], 'MSGSENT': [] ,
|
|
|
|
'SUBSCRIBED': [], 'UNSUBSCRIBED': [], 'SUBSCRIBE': [],
|
|
|
|
'AGENT_INFO': [], 'REGISTER_AGENT_INFO': [], 'AGENT_INFO_ITEMS': [],
|
|
|
|
'AGENT_INFO_INFO': [], 'QUIT': [], 'ACC_OK': [], 'MYVCARD': [],
|
|
|
|
'OS_INFO': [], 'VCARD': [], 'GC_MSG': [], 'GC_SUBJECT': [],
|
2005-05-10 18:53:28 +02:00
|
|
|
'GC_CONFIG': [], 'BAD_PASSPHRASE': [], 'ROSTER_INFO': [],
|
|
|
|
'ERROR_ANSWER': []}
|
2005-04-12 13:46:20 +02:00
|
|
|
self.name = name
|
|
|
|
self.connected = 0 # offline
|
2005-04-26 20:45:54 +02:00
|
|
|
self.connection = None # xmpppy instance
|
2005-04-12 13:46:20 +02:00
|
|
|
self.gpg = None
|
2005-05-13 20:54:44 +02:00
|
|
|
self.status = ''
|
2005-04-12 13:46:20 +02:00
|
|
|
self.myVCardID = []
|
2005-04-14 13:06:58 +02:00
|
|
|
self.password = gajim.config.get_per('accounts', name, 'password')
|
2005-04-14 11:38:08 +02:00
|
|
|
if USE_GPG:
|
|
|
|
self.gpg = GnuPG.GnuPG()
|
|
|
|
gajim.config.set('usegpg', True)
|
|
|
|
else:
|
|
|
|
gajim.config.set('usegpg', False)
|
2005-04-12 13:46:20 +02:00
|
|
|
# END __init__
|
|
|
|
|
|
|
|
def dispatch(self, event, data):
|
|
|
|
if not event in self.handlers:
|
|
|
|
return
|
|
|
|
for handler in self.handlers[event]:
|
|
|
|
handler(self.name, data)
|
|
|
|
|
2005-04-26 20:45:54 +02:00
|
|
|
def _discover(self, ns, jid, node = None): #FIXME: this is in features.py but it is blocking
|
2005-05-23 12:46:22 +02:00
|
|
|
if not self.connection:
|
|
|
|
return
|
2005-04-26 20:45:54 +02:00
|
|
|
iq = common.xmpp.Iq(typ = 'get', to = jid, queryNS = ns)
|
|
|
|
if node:
|
|
|
|
iq.setQuerynode(node)
|
|
|
|
self.connection.send(iq)
|
|
|
|
|
|
|
|
def discoverItems(self, jid, node = None):
|
|
|
|
'''According to JEP-0030: jid is mandatory,
|
|
|
|
name, node, action is optional.'''
|
|
|
|
self._discover(common.xmpp.NS_DISCO_ITEMS, jid, node)
|
|
|
|
|
|
|
|
def discoverInfo(self, jid, node = None):
|
|
|
|
'''According to JEP-0030:
|
|
|
|
For identity: category, name is mandatory, type is optional.
|
|
|
|
For feature: var is mandatory'''
|
|
|
|
self._discover(common.xmpp.NS_DISCO_INFO, jid, node)
|
|
|
|
|
2005-04-12 13:46:20 +02:00
|
|
|
def _vCardCB(self, con, vc):
|
|
|
|
"""Called when we recieve a vCard
|
|
|
|
Parse the vCard and send it to plugins"""
|
|
|
|
vcard = {'jid': vc.getFrom().getStripped()}
|
2005-04-26 20:45:54 +02:00
|
|
|
if vc.getTag('vCard').getNamespace() == common.xmpp.NS_VCARD:
|
2005-04-12 13:46:20 +02: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())
|
|
|
|
self.dispatch('MYVCARD', vcard)
|
|
|
|
else:
|
|
|
|
self.dispatch('VCARD', vcard)
|
|
|
|
|
2005-04-26 20:45:54 +02:00
|
|
|
|
2005-04-12 13:46:20 +02:00
|
|
|
def _messageCB(self, con, msg):
|
|
|
|
"""Called when we recieve a message"""
|
2005-05-20 13:23:08 +02:00
|
|
|
msgtxt = msg.getBody()
|
2005-04-12 14:23:08 +02:00
|
|
|
mtype = msg.getType()
|
2005-04-12 13:46:20 +02:00
|
|
|
tim = msg.getTimestamp()
|
|
|
|
tim = time.strptime(tim, '%Y%m%dT%H:%M:%S')
|
2005-04-27 20:26:31 +02:00
|
|
|
tim = time.localtime(timegm(tim))
|
2005-04-26 20:45:54 +02:00
|
|
|
xtags = msg.getTags('x')
|
2005-04-12 13:46:20 +02:00
|
|
|
encTag = None
|
|
|
|
decmsg = ''
|
|
|
|
for xtag in xtags:
|
2005-04-26 20:45:54 +02:00
|
|
|
if xtag.getNamespace() == common.xmpp.NS_ENCRYPTED:
|
2005-04-12 13:46:20 +02:00
|
|
|
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
|
2005-04-12 14:23:08 +02:00
|
|
|
if mtype == 'error':
|
2005-04-12 13:46:20 +02:00
|
|
|
self.dispatch('MSGERROR', (str(msg.getFrom()), \
|
|
|
|
msg.getErrorCode(), msg.getError(), msgtxt, tim))
|
2005-04-12 14:23:08 +02:00
|
|
|
elif mtype == 'groupchat':
|
2005-04-12 13:46:20 +02:00
|
|
|
subject = msg.getSubject()
|
|
|
|
if subject:
|
|
|
|
self.dispatch('GC_SUBJECT', (str(msg.getFrom()), subject))
|
|
|
|
else:
|
2005-05-23 20:16:51 +02:00
|
|
|
if not msgtxt: # empty message
|
|
|
|
return
|
2005-04-12 13:46:20 +02:00
|
|
|
self.dispatch('GC_MSG', (str(msg.getFrom()), msgtxt, tim))
|
2005-04-16 11:36:18 +02:00
|
|
|
gajim.logger.write('gc', msgtxt, str(msg.getFrom()), tim = tim)
|
2005-04-12 13:46:20 +02:00
|
|
|
else:
|
2005-05-23 20:16:51 +02:00
|
|
|
if not msgtxt: # empty message
|
|
|
|
return
|
2005-04-16 11:36:18 +02:00
|
|
|
gajim.logger.write('incoming', msgtxt, str(msg.getFrom()), tim = tim)
|
2005-04-12 13:46:20 +02:00
|
|
|
self.dispatch('MSG', (str(msg.getFrom()), msgtxt, tim))
|
|
|
|
# END messageCB
|
|
|
|
|
|
|
|
def _presenceCB(self, con, prs):
|
|
|
|
"""Called when we recieve a presence"""
|
2005-04-26 20:45:54 +02:00
|
|
|
# if prs.getXNode(common.xmpp.NS_DELAY): return
|
2005-04-12 13:46:20 +02:00
|
|
|
who = str(prs.getFrom())
|
|
|
|
prio = prs.getPriority()
|
|
|
|
if not prio:
|
|
|
|
prio = 0
|
2005-04-12 14:23:08 +02:00
|
|
|
ptype = prs.getType()
|
|
|
|
if ptype == None: ptype = 'available'
|
|
|
|
gajim.log.debug('PresenceCB : %s' % ptype)
|
2005-04-26 20:45:54 +02:00
|
|
|
xtags = prs.getTags('x')
|
2005-04-12 13:46:20 +02:00
|
|
|
sigTag = None
|
|
|
|
keyID = ''
|
|
|
|
status = prs.getStatus()
|
|
|
|
for xtag in xtags:
|
2005-04-26 20:45:54 +02:00
|
|
|
if xtag.getNamespace() == common.xmpp.NS_SIGNED:
|
2005-04-12 13:46:20 +02:00
|
|
|
sigTag = xtag
|
|
|
|
break
|
|
|
|
if sigTag and USE_GPG:
|
|
|
|
#verify
|
|
|
|
sigmsg = sigTag.getData()
|
|
|
|
keyID = self.gpg.verify(status, sigmsg)
|
2005-04-12 14:23:08 +02:00
|
|
|
if ptype == 'available':
|
2005-04-12 13:46:20 +02:00
|
|
|
show = prs.getShow()
|
|
|
|
if not show:
|
|
|
|
show = 'online'
|
2005-04-12 14:23:08 +02:00
|
|
|
elif ptype == 'unavailable':
|
2005-04-16 11:36:18 +02:00
|
|
|
show = 'offline'
|
2005-04-12 14:23:08 +02:00
|
|
|
elif ptype == 'subscribe':
|
2005-04-12 13:46:20 +02:00
|
|
|
gajim.log.debug('subscribe request from %s' % who)
|
|
|
|
if gajim.config.get('alwaysauth') or who.find("@") <= 0:
|
|
|
|
if self.connection:
|
2005-04-26 20:45:54 +02:00
|
|
|
self.connection.send(common.xmpp.Presence(who, 'subscribed'))
|
2005-04-12 13:46:20 +02:00
|
|
|
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))
|
2005-04-12 14:23:08 +02:00
|
|
|
elif ptype == 'subscribed':
|
2005-04-12 13:46:20 +02:00
|
|
|
jid = prs.getFrom()
|
|
|
|
self.dispatch('SUBSCRIBED', (jid.getStripped(), jid.getResource()))
|
|
|
|
self.dispatch('UPDUSER', (jid.getStripped(), jid.getNode(), \
|
2005-04-14 09:42:26 +02:00
|
|
|
['General']))
|
2005-04-12 13:46:20 +02:00
|
|
|
#BE CAREFUL : no con.updateRosterItem() in a callback
|
|
|
|
gajim.log.debug('we are now subscribed to %s' % who)
|
2005-04-12 14:23:08 +02:00
|
|
|
elif ptype == 'unsubscribe':
|
2005-04-12 13:46:20 +02:00
|
|
|
gajim.log.debug('unsubscribe request from %s' % who)
|
2005-04-12 14:23:08 +02:00
|
|
|
elif ptype == 'unsubscribed':
|
2005-04-12 13:46:20 +02:00
|
|
|
gajim.log.debug('we are now unsubscribed to %s' % who)
|
|
|
|
self.dispatch('UNSUBSCRIBED', prs.getFrom().getStripped())
|
2005-04-12 14:23:08 +02:00
|
|
|
elif ptype == 'error':
|
2005-04-12 13:46:20 +02:00
|
|
|
errmsg = prs.getError()
|
|
|
|
errcode = prs.getErrorCode()
|
2005-05-11 12:05:43 +02:00
|
|
|
if errcode == '409': #conflict : Nick Conflict
|
2005-04-12 13:46:20 +02:00
|
|
|
self.dispatch('ERROR', errmsg)
|
|
|
|
else:
|
2005-05-11 17:14:43 +02:00
|
|
|
self.dispatch('ERROR_ANSWER', (prs.getFrom().getStripped(), errmsg,
|
|
|
|
errcode))
|
2005-04-16 11:36:18 +02:00
|
|
|
if ptype == 'available' or ptype == 'unavailable':
|
|
|
|
gajim.logger.write('status', status, prs.getFrom().getStripped(), show)
|
|
|
|
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()))
|
2005-04-12 13:46:20 +02:00
|
|
|
# END presenceCB
|
|
|
|
|
2005-04-26 20:45:54 +02:00
|
|
|
def _disconnectedCB(self):
|
2005-04-12 13:46:20 +02:00
|
|
|
"""Called when we are disconnected"""
|
|
|
|
gajim.log.debug('disconnectedCB')
|
|
|
|
if self.connection:
|
|
|
|
self.connected = 0
|
|
|
|
self.dispatch('STATUS', 'offline')
|
2005-04-18 11:18:50 +02:00
|
|
|
self.connection = None
|
2005-04-12 13:46:20 +02:00
|
|
|
# END disconenctedCB
|
|
|
|
|
|
|
|
def _rosterSetCB(self, con, iq_obj):
|
2005-04-20 12:21:33 +02:00
|
|
|
gajim.log.debug('rosterSetCB')
|
2005-04-26 20:45:54 +02:00
|
|
|
for item in iq_obj.getTag('query').getChildren():
|
2005-04-12 13:46:20 +02:00
|
|
|
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))
|
2005-05-11 09:55:17 +02:00
|
|
|
raise common.xmpp.NodeProcessed
|
2005-04-12 13:46:20 +02:00
|
|
|
|
|
|
|
def _BrowseResultCB(self, con, iq_obj):
|
2005-04-20 12:21:33 +02:00
|
|
|
gajim.log.debug('BrowseResultCB')
|
2005-04-12 13:46:20 +02:00
|
|
|
identities, features, items = [], [], []
|
2005-05-07 14:24:19 +02:00
|
|
|
for q in iq_obj.getChildren():
|
|
|
|
if q.getNamespace() != common.xmpp.NS_BROWSE:
|
|
|
|
continue
|
|
|
|
attr = {}
|
|
|
|
for key in q.getAttrs().keys():
|
|
|
|
attr[key.encode('utf8')] = q.getAttr(key).encode('utf8')
|
|
|
|
identities = [attr]
|
|
|
|
for node in q.getChildren():
|
|
|
|
if node.getName() == 'ns':
|
|
|
|
features.append(node.getData())
|
|
|
|
else:
|
|
|
|
infos = {}
|
|
|
|
for key in node.getAttrs().keys():
|
|
|
|
infos[key.encode('utf8')] = node.getAttr(key).encode('utf8')
|
|
|
|
infos['category'] = node.getName()
|
|
|
|
items.append(infos)
|
|
|
|
jid = str(iq_obj.getFrom())
|
|
|
|
self.dispatch('AGENT_INFO', (jid, identities, features, items))
|
2005-04-12 13:46:20 +02:00
|
|
|
|
|
|
|
def _DiscoverItemsCB(self, con, iq_obj):
|
2005-04-20 12:21:33 +02:00
|
|
|
gajim.log.debug('DiscoverItemsCB')
|
2005-04-26 20:45:54 +02:00
|
|
|
q = iq_obj.getTag('query')
|
2005-04-23 23:54:12 +02:00
|
|
|
node = q.getAttr('node')
|
|
|
|
if not node:
|
|
|
|
node = ''
|
2005-04-12 13:46:20 +02:00
|
|
|
qp = iq_obj.getQueryPayload()
|
|
|
|
items = []
|
|
|
|
if not qp:
|
|
|
|
qp = []
|
|
|
|
for i in qp:
|
|
|
|
attr = {}
|
2005-04-26 20:45:54 +02:00
|
|
|
for key in i.getAttrs():
|
|
|
|
attr[key.encode('utf8')] = i.getAttrs()[key].encode('utf8')
|
2005-04-12 13:46:20 +02:00
|
|
|
items.append(attr)
|
|
|
|
jid = str(iq_obj.getFrom())
|
2005-04-23 23:54:12 +02:00
|
|
|
self.dispatch('AGENT_INFO_ITEMS', (jid, node, items))
|
2005-04-12 13:46:20 +02:00
|
|
|
|
|
|
|
def _DiscoverInfoErrorCB(self, con, iq_obj):
|
2005-04-20 12:21:33 +02:00
|
|
|
gajim.log.debug('DiscoverInfoErrorCB')
|
2005-04-26 20:45:54 +02:00
|
|
|
iq = common.xmpp.Iq(to = iq_obj.getFrom(), typ = 'get', queryNS =\
|
|
|
|
common.xmpp.NS_AGENTS)
|
|
|
|
con.send(iq)
|
2005-04-12 13:46:20 +02:00
|
|
|
|
|
|
|
def _DiscoverInfoCB(self, con, iq_obj):
|
2005-04-20 12:21:33 +02:00
|
|
|
gajim.log.debug('DiscoverInfoCB')
|
2005-04-12 13:46:20 +02:00
|
|
|
# According to JEP-0030:
|
|
|
|
# For identity: category, name is mandatory, type is optional.
|
|
|
|
# For feature: var is mandatory
|
|
|
|
identities, features = [], []
|
2005-04-26 20:45:54 +02:00
|
|
|
q = iq_obj.getTag('query')
|
2005-04-23 23:54:12 +02:00
|
|
|
node = q.getAttr('node')
|
|
|
|
if not node:
|
|
|
|
node = ''
|
2005-04-26 20:45:54 +02:00
|
|
|
qc = iq_obj.getQueryChildren()
|
|
|
|
if not qc:
|
|
|
|
qc = []
|
|
|
|
for i in qc:
|
2005-04-12 13:46:20 +02:00
|
|
|
if i.getName() == 'identity':
|
|
|
|
attr = {}
|
2005-04-26 20:45:54 +02:00
|
|
|
for key in i.getAttrs().keys():
|
|
|
|
attr[key.encode('utf8')] = i.getAttr(key).encode('utf8')
|
2005-04-12 13:46:20 +02:00
|
|
|
identities.append(attr)
|
|
|
|
elif i.getName() == 'feature':
|
|
|
|
features.append(i.getAttr('var'))
|
|
|
|
jid = str(iq_obj.getFrom())
|
|
|
|
if not identities:
|
2005-05-07 12:57:40 +02:00
|
|
|
self.connection.send(common.xmpp.Iq(typ = 'get', queryNS = \
|
|
|
|
common.xmpp.NS_AGENTS))
|
2005-04-12 13:46:20 +02:00
|
|
|
else:
|
2005-04-24 17:47:08 +02:00
|
|
|
self.dispatch('AGENT_INFO_INFO', (jid, node, identities, features))
|
2005-04-26 20:45:54 +02:00
|
|
|
self.discoverItems(jid, node)
|
2005-04-12 13:46:20 +02:00
|
|
|
|
|
|
|
def _VersionCB(self, con, iq_obj):
|
2005-04-20 12:21:33 +02:00
|
|
|
gajim.log.debug('VersionCB')
|
2005-05-07 12:57:40 +02:00
|
|
|
iq_obj = iq_obj.buildReply('result')
|
2005-04-12 13:46:20 +02:00
|
|
|
qp = iq_obj.getTag('query')
|
2005-04-26 23:33:01 +02:00
|
|
|
qp.setTagData('name', 'Gajim')
|
|
|
|
qp.setTagData('version', gajim.version)
|
2005-04-24 02:31:48 +02:00
|
|
|
send_os = gajim.config.get('send_os_info')
|
|
|
|
if send_os:
|
2005-04-26 23:33:01 +02:00
|
|
|
qp.setTagData('os', get_os_info())
|
2005-05-07 12:57:40 +02:00
|
|
|
con.send(iq_obj)
|
2005-05-13 19:20:13 +02:00
|
|
|
raise common.xmpp.NodeProcessed
|
2005-04-12 13:46:20 +02:00
|
|
|
|
|
|
|
def _VersionResultCB(self, con, iq_obj):
|
2005-04-20 12:21:33 +02:00
|
|
|
gajim.log.debug('VersionResultCB')
|
2005-04-12 13:46:20 +02:00
|
|
|
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()
|
2005-04-25 00:58:41 +02:00
|
|
|
resource = iq_obj.getFrom().getResource()
|
|
|
|
self.dispatch('OS_INFO', (jid, resource, client_info, os_info))
|
2005-04-20 12:21:33 +02:00
|
|
|
|
|
|
|
def _MucOwnerCB(self, con, iq_obj):
|
|
|
|
gajim.log.debug('MucOwnerCB')
|
|
|
|
qp = iq_obj.getQueryPayload()
|
|
|
|
node = None
|
|
|
|
for q in qp:
|
2005-04-26 20:45:54 +02:00
|
|
|
if q.getNamespace() == common.xmpp.NS_DATA:
|
2005-04-20 12:21:33 +02:00
|
|
|
node = q
|
|
|
|
if not node:
|
|
|
|
return
|
|
|
|
# Parse the form
|
|
|
|
dic = {}
|
|
|
|
tag = node.getTag('title')
|
|
|
|
if tag:
|
|
|
|
dic['title'] = tag.getData()
|
|
|
|
tag = node.getTag('instructions')
|
|
|
|
if tag:
|
|
|
|
dic['instructions'] = tag.getData()
|
|
|
|
i = 0
|
|
|
|
for child in node.getChildren():
|
|
|
|
if child.getName() != 'field':
|
|
|
|
continue
|
|
|
|
var = child.getAttr('var')
|
|
|
|
ctype = child.getAttr('type')
|
|
|
|
label = child.getAttr('label')
|
|
|
|
if not var and ctype != 'fixed': # We must have var if type != fixed
|
|
|
|
continue
|
|
|
|
dic[i] = {}
|
|
|
|
if var:
|
|
|
|
dic[i]['var'] = var
|
|
|
|
if ctype:
|
|
|
|
dic[i]['type'] = ctype
|
|
|
|
if label:
|
|
|
|
dic[i]['label'] = label
|
|
|
|
tags = child.getTags('value')
|
|
|
|
if len(tags):
|
|
|
|
dic[i]['values'] = []
|
|
|
|
for tag in tags:
|
|
|
|
data = tag.getData()
|
|
|
|
if ctype == 'boolean':
|
2005-04-24 18:14:50 +02:00
|
|
|
if data in ['yes', 'true', 'assent', '1']:
|
2005-04-20 12:21:33 +02:00
|
|
|
data = True
|
|
|
|
else:
|
|
|
|
data = False
|
|
|
|
dic[i]['values'].append(data)
|
|
|
|
tag = child.getTag('desc')
|
|
|
|
if tag:
|
|
|
|
dic[i]['desc'] = tag.getData()
|
|
|
|
option_tags = child.getTags('option')
|
|
|
|
if len(option_tags):
|
|
|
|
dic[i]['options'] = {}
|
|
|
|
j = 0
|
|
|
|
for option_tag in option_tags:
|
|
|
|
dic[i]['options'][j] = {}
|
|
|
|
label = option_tag.getAttr('label')
|
|
|
|
if label:
|
|
|
|
dic[i]['options'][j]['label'] = label
|
|
|
|
tags = option_tag.getTags('value')
|
|
|
|
dic[i]['options'][j]['values'] = []
|
|
|
|
for tag in tags:
|
|
|
|
dic[i]['options'][j]['values'].append(tag.getData())
|
|
|
|
j += 1
|
|
|
|
i += 1
|
|
|
|
self.dispatch('GC_CONFIG', (str(iq_obj.getFrom()), dic))
|
2005-04-12 13:46:20 +02:00
|
|
|
|
2005-04-26 00:22:23 +02:00
|
|
|
def _MucErrorCB(self, con, iq_obj):
|
|
|
|
gajim.log.debug('MucErrorCB')
|
|
|
|
jid = str(iq_obj.getFrom())
|
|
|
|
errmsg = iq_obj.getError()
|
|
|
|
errcode = iq_obj.getErrorCode()
|
|
|
|
self.dispatch('MSGERROR', (jid, errcode, errmsg))
|
|
|
|
|
2005-05-08 19:00:41 +02:00
|
|
|
def _getRosterCB(self, con, iq_obj):
|
|
|
|
roster = self.connection.getRoster().getRaw()
|
|
|
|
if not roster :
|
|
|
|
roster = {}
|
|
|
|
name = gajim.config.get_per('accounts', self.name, 'name')
|
|
|
|
hostname = gajim.config.get_per('accounts', self.name, 'hostname')
|
|
|
|
if roster.has_key(name + '@' + hostname):
|
|
|
|
del roster[name + '@' + hostname]
|
|
|
|
self.dispatch('ROSTER', roster)
|
|
|
|
|
2005-05-10 18:53:28 +02:00
|
|
|
def _ErrorCB(self, con, iq_obj):
|
|
|
|
errmsg = iq_obj.getError()
|
|
|
|
errcode = iq_obj.getErrorCode()
|
|
|
|
jid_from = str(iq_obj.getFrom())
|
|
|
|
self.dispatch('ERROR_ANSWER', (jid_from, errmsg, errcode))
|
|
|
|
|
2005-04-12 13:46:20 +02:00
|
|
|
def connect(self):
|
2005-05-21 03:28:18 +02:00
|
|
|
"""Connect and authenticate to the Jabber server"""
|
2005-04-14 13:06:58 +02:00
|
|
|
name = gajim.config.get_per('accounts', self.name, 'name')
|
2005-04-12 13:46:20 +02:00
|
|
|
hostname = gajim.config.get_per('accounts', self.name, 'hostname')
|
|
|
|
resource = gajim.config.get_per('accounts', self.name, 'resource')
|
2005-05-09 21:52:43 +02:00
|
|
|
usetls = gajim.config.get_per('accounts', self.name, 'usetls')
|
2005-04-12 13:46:20 +02:00
|
|
|
|
|
|
|
#create connexion if it doesn't already existe
|
2005-04-14 13:06:58 +02:00
|
|
|
if self.connection:
|
|
|
|
return self.connection
|
2005-04-18 11:18:50 +02:00
|
|
|
self.connected = 1
|
2005-04-14 13:06:58 +02:00
|
|
|
if gajim.config.get_per('accounts', self.name, 'use_proxy'):
|
2005-05-10 17:38:16 +02:00
|
|
|
proxy = {'host': gajim.config.get_per('accounts', self.name,
|
2005-04-14 13:06:58 +02:00
|
|
|
'proxyhost')}
|
2005-05-10 17:38:16 +02:00
|
|
|
proxy['port'] = gajim.config.get_per('accounts', self.name,
|
2005-04-14 13:06:58 +02:00
|
|
|
'proxyport')
|
2005-05-10 17:38:16 +02:00
|
|
|
proxy['user'] = gajim.config.get_per('accounts', self.name,
|
|
|
|
'proxyuser')
|
|
|
|
proxy['password'] = gajim.config.get_per('accounts', self.name,
|
|
|
|
'proxypass')
|
2005-04-14 13:06:58 +02:00
|
|
|
else:
|
|
|
|
proxy = None
|
2005-05-03 18:26:30 +02:00
|
|
|
if gajim.config.get('verbose'):
|
2005-05-08 19:00:41 +02:00
|
|
|
con = common.xmpp.Client(hostname)
|
2005-04-14 13:06:58 +02:00
|
|
|
else:
|
2005-05-03 10:06:59 +02:00
|
|
|
con = common.xmpp.Client(hostname, debug = [])
|
2005-04-14 13:06:58 +02:00
|
|
|
#debug = [common.jabber.DBG_ALWAYS], log = sys.stderr, \
|
|
|
|
#connection=common.xmlstream.TCP_SSL, port=5223, proxy = proxy)
|
2005-05-23 11:53:05 +02:00
|
|
|
common.xmpp.dispatcher.DefaultTimeout = 45
|
2005-05-20 12:49:46 +02:00
|
|
|
con.UnregisterDisconnectHandler(con.DisconnectHandler)
|
2005-04-26 20:45:54 +02:00
|
|
|
con.RegisterDisconnectHandler(self._disconnectedCB)
|
2005-04-12 13:46:20 +02:00
|
|
|
try:
|
2005-05-11 18:37:01 +02:00
|
|
|
c = con.connect(proxy=proxy, tls=usetls) #FIXME: blocking
|
2005-04-12 13:46:20 +02:00
|
|
|
except:
|
2005-05-11 18:37:01 +02:00
|
|
|
c = None
|
|
|
|
if not c:
|
2005-04-14 13:06:58 +02:00
|
|
|
gajim.log.debug('Couldn\'t connect to %s' % hostname)
|
2005-05-18 16:05:54 +02:00
|
|
|
self.connected = 0
|
2005-04-12 13:46:20 +02:00
|
|
|
self.dispatch('STATUS', 'offline')
|
2005-05-11 18:37:01 +02:00
|
|
|
self.dispatch('ERROR', _('Couldn\'t connect to %s') % hostname)
|
2005-04-14 13:06:58 +02:00
|
|
|
return None
|
2005-04-12 13:46:20 +02:00
|
|
|
|
2005-04-26 20:45:54 +02:00
|
|
|
con.RegisterHandler('message', self._messageCB)
|
|
|
|
con.RegisterHandler('presence', self._presenceCB)
|
|
|
|
con.RegisterHandler('iq', self._vCardCB, 'result',\
|
|
|
|
common.xmpp.NS_VCARD)
|
|
|
|
con.RegisterHandler('iq', self._rosterSetCB, 'set',\
|
|
|
|
common.xmpp.NS_ROSTER)
|
|
|
|
con.RegisterHandler('iq', self._BrowseResultCB, 'result',\
|
|
|
|
common.xmpp.NS_BROWSE)
|
|
|
|
con.RegisterHandler('iq', self._DiscoverItemsCB, 'result',\
|
|
|
|
common.xmpp.NS_DISCO_ITEMS)
|
|
|
|
con.RegisterHandler('iq', self._DiscoverInfoCB, 'result',\
|
|
|
|
common.xmpp.NS_DISCO_INFO)
|
|
|
|
con.RegisterHandler('iq', self._DiscoverInfoErrorCB, 'error',\
|
|
|
|
common.xmpp.NS_DISCO_INFO)
|
|
|
|
con.RegisterHandler('iq', self._VersionCB, 'get',\
|
|
|
|
common.xmpp.NS_VERSION)
|
|
|
|
con.RegisterHandler('iq', self._VersionResultCB, 'result',\
|
|
|
|
common.xmpp.NS_VERSION)
|
|
|
|
con.RegisterHandler('iq', self._MucOwnerCB, 'result',\
|
|
|
|
common.xmpp.NS_MUC_OWNER)
|
2005-05-08 19:00:41 +02:00
|
|
|
con.RegisterHandler('iq', self._getRosterCB, 'result',\
|
|
|
|
common.xmpp.NS_ROSTER)
|
2005-05-10 18:53:28 +02:00
|
|
|
con.RegisterHandler('iq', self._ErrorCB, 'error')
|
2005-04-26 20:45:54 +02:00
|
|
|
|
2005-04-12 13:46:20 +02:00
|
|
|
gajim.log.debug('Connected to server')
|
|
|
|
|
2005-05-11 18:37:01 +02:00
|
|
|
try:
|
2005-05-24 20:19:53 +02:00
|
|
|
auth = con.auth(name, self.password, resource,
|
|
|
|
not gajim.config.get_per('accounts', self.name, 'force_nonSASL')) #FIXME: blocking
|
2005-05-11 18:37:01 +02:00
|
|
|
except IOError: #probably a timeout
|
2005-05-18 16:05:54 +02:00
|
|
|
self.connected = 0
|
2005-05-11 18:37:01 +02:00
|
|
|
self.dispatch('STATUS', 'offline')
|
|
|
|
self.dispatch('ERROR', _('Couldn\'t connect to %s') % hostname)
|
|
|
|
return None
|
|
|
|
if auth:
|
2005-05-08 19:00:41 +02:00
|
|
|
con.initRoster()
|
2005-04-12 13:46:20 +02:00
|
|
|
self.connected = 2
|
2005-04-14 13:06:58 +02:00
|
|
|
return con
|
2005-04-12 13:46:20 +02:00
|
|
|
else:
|
2005-05-21 03:28:18 +02:00
|
|
|
gajim.log.debug('Couldn\'t authenticate to %s' % hostname)
|
2005-05-18 16:05:54 +02:00
|
|
|
self.connected = 0
|
2005-04-12 13:46:20 +02:00
|
|
|
self.dispatch('STATUS', 'offline')
|
2005-05-21 03:28:18 +02:00
|
|
|
self.dispatch('ERROR', _('Authentication failed with %s, check your login and password') % hostname)
|
2005-04-14 13:06:58 +02:00
|
|
|
return None
|
2005-04-12 13:46:20 +02:00
|
|
|
# END connect
|
|
|
|
|
2005-04-14 09:58:54 +02:00
|
|
|
def register_handler(self, event, function):
|
2005-04-12 13:46:20 +02:00
|
|
|
if event in self.handlers:
|
|
|
|
self.handlers[event].append(function)
|
|
|
|
|
2005-04-14 09:58:54 +02:00
|
|
|
def unregister_handler(self, event, function):
|
2005-04-12 13:46:20 +02:00
|
|
|
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')
|
|
|
|
return
|
|
|
|
|
|
|
|
def ask_roster(self):
|
|
|
|
roster = {}
|
|
|
|
if self.connection:
|
|
|
|
roster = self.connection.getRoster().getRaw()
|
|
|
|
return roster
|
|
|
|
|
2005-05-13 20:54:44 +02:00
|
|
|
def change_status(self, show, msg):
|
|
|
|
if not show in STATUS_LIST:
|
2005-04-12 13:46:20 +02:00
|
|
|
return -1
|
|
|
|
signed = ''
|
|
|
|
keyID = gajim.config.get_per('accounts', self.name, 'keyid')
|
|
|
|
if keyID and USE_GPG:
|
2005-05-20 17:32:05 +02:00
|
|
|
if not msg:
|
|
|
|
msg = show
|
2005-04-12 13:46:20 +02:00
|
|
|
signed = self.gpg.sign(msg, keyID)
|
|
|
|
if signed == 'BAD_PASSPHRASE':
|
|
|
|
signed = ''
|
|
|
|
if self.connected < 2:
|
|
|
|
self.dispatch('BAD_PASSPHRASE', ())
|
2005-05-20 17:32:05 +02:00
|
|
|
self.status = msg
|
2005-05-19 19:50:19 +02:00
|
|
|
if show != 'offline' and not self.connected:
|
2005-04-14 13:06:58 +02:00
|
|
|
self.connection = self.connect()
|
2005-04-12 13:46:20 +02:00
|
|
|
if self.connected == 2:
|
2005-05-13 20:54:44 +02:00
|
|
|
self.connected = STATUS_LIST.index(show)
|
2005-04-12 13:46:20 +02:00
|
|
|
#send our presence
|
2005-04-12 14:23:08 +02:00
|
|
|
ptype = 'available'
|
2005-05-13 20:54:44 +02:00
|
|
|
if show == 'invisible':
|
2005-04-12 14:23:08 +02:00
|
|
|
ptype = 'invisible'
|
2005-04-17 13:49:39 +02:00
|
|
|
prio = str(gajim.config.get_per('accounts', self.name, 'priority'))
|
2005-05-20 17:32:05 +02:00
|
|
|
p = common.xmpp.Presence(typ = ptype, priority = prio, show = show)
|
|
|
|
if msg:
|
|
|
|
p.setStatus(msg)
|
2005-04-26 20:45:54 +02:00
|
|
|
if signed:
|
2005-04-26 23:33:01 +02:00
|
|
|
p.setTag(common.xmpp.NS_SIGNED + ' x').setData(signed)
|
2005-04-26 20:45:54 +02:00
|
|
|
|
|
|
|
self.connection.send(p)
|
2005-05-13 20:54:44 +02:00
|
|
|
self.dispatch('STATUS', show)
|
2005-04-12 13:46:20 +02:00
|
|
|
#ask our VCard
|
2005-04-26 20:45:54 +02:00
|
|
|
iq = common.xmpp.Iq('get')
|
|
|
|
iq.setTag(common.xmpp.NS_VCARD + ' vCard')
|
2005-04-14 13:06:58 +02:00
|
|
|
self.connection.send(iq)
|
2005-04-26 20:45:54 +02:00
|
|
|
self.myVCardID.append(iq.getID())
|
2005-05-19 19:50:19 +02:00
|
|
|
elif show == 'offline' and self.connected:
|
2005-04-12 13:46:20 +02:00
|
|
|
self.connected = 0
|
2005-05-04 21:20:02 +02:00
|
|
|
if self.connection:
|
2005-05-20 17:32:05 +02:00
|
|
|
p = common.xmpp.Presence(typ = 'unavailable')
|
|
|
|
if msg:
|
|
|
|
p.setStatus(msg)
|
|
|
|
self.connection.send(p)
|
2005-05-04 21:20:02 +02:00
|
|
|
self.connection.disconnect()
|
2005-04-12 13:46:20 +02:00
|
|
|
self.dispatch('STATUS', 'offline')
|
2005-04-18 11:18:50 +02:00
|
|
|
self.connection = None
|
2005-05-13 20:54:44 +02:00
|
|
|
elif show != 'offline' and self.connected:
|
|
|
|
self.connected = STATUS_LIST.index(show)
|
2005-04-12 14:23:08 +02:00
|
|
|
ptype = 'available'
|
2005-05-13 20:54:44 +02:00
|
|
|
if show == 'invisible':
|
2005-04-12 14:23:08 +02:00
|
|
|
ptype = 'invisible'
|
2005-04-17 13:49:39 +02:00
|
|
|
prio = str(gajim.config.get_per('accounts', self.name, 'priority'))
|
2005-05-20 17:32:05 +02:00
|
|
|
p = common.xmpp.Presence(typ = ptype, priority = prio, show = show)
|
|
|
|
if msg:
|
|
|
|
p.setStatus(msg)
|
|
|
|
if signed:
|
|
|
|
p.setTag(common.xmpp.NS_SIGNED + ' x').setData(signed)
|
2005-04-26 20:45:54 +02:00
|
|
|
self.connection.send(p)
|
2005-05-13 20:54:44 +02:00
|
|
|
self.dispatch('STATUS', show)
|
2005-04-12 13:46:20 +02:00
|
|
|
|
2005-04-14 19:07:55 +02:00
|
|
|
def send_message(self, jid, msg, keyID):
|
2005-04-14 09:42:26 +02:00
|
|
|
if not self.connection:
|
2005-04-12 13:46:20 +02:00
|
|
|
return
|
|
|
|
msgtxt = msg
|
|
|
|
msgenc = ''
|
|
|
|
if keyID and USE_GPG:
|
|
|
|
#encrypt
|
|
|
|
msgenc = self.gpg.encrypt(msg, keyID)
|
|
|
|
if msgenc: msgtxt = _('[this message is encrypted]')
|
2005-04-26 20:45:54 +02:00
|
|
|
msg_iq = common.xmpp.Message(to = jid, body = msgtxt, typ = 'chat')
|
2005-04-12 13:46:20 +02:00
|
|
|
if msgenc:
|
2005-04-26 20:45:54 +02:00
|
|
|
msg_iq.setTag(common.xmpp.NS_ENCRYPTED + ' x').setData(msgenc)
|
2005-04-12 13:46:20 +02:00
|
|
|
self.connection.send(msg_iq)
|
2005-04-16 11:36:18 +02:00
|
|
|
gajim.logger.write('outgoing', msg, jid)
|
2005-04-12 13:46:20 +02:00
|
|
|
self.dispatch('MSGSENT', (jid, msg, keyID))
|
|
|
|
|
2005-04-14 09:42:26 +02:00
|
|
|
def request_subscription(self, jid, msg):
|
2005-04-12 13:46:20 +02:00
|
|
|
if not self.connection:
|
|
|
|
return
|
|
|
|
gajim.log.debug('subscription request for %s' % jid)
|
2005-04-26 20:45:54 +02:00
|
|
|
pres = common.xmpp.Presence(jid, 'subscribe')
|
2005-04-12 13:46:20 +02:00
|
|
|
if not msg:
|
|
|
|
msg = _('I would like to add you to my roster.')
|
|
|
|
pres.setStatus(msg)
|
|
|
|
self.connection.send(pres)
|
|
|
|
|
2005-04-14 09:42:26 +02:00
|
|
|
def send_authorization(self, jid):
|
2005-04-12 13:46:20 +02:00
|
|
|
if not self.connection:
|
|
|
|
return
|
2005-04-26 20:45:54 +02:00
|
|
|
self.connection.send(common.xmpp.Presence(jid, 'subscribed'))
|
2005-04-12 13:46:20 +02:00
|
|
|
|
2005-04-14 09:42:26 +02:00
|
|
|
def refuse_authorization(self, jid):
|
2005-04-12 13:46:20 +02:00
|
|
|
if not self.connection:
|
|
|
|
return
|
2005-04-26 20:45:54 +02:00
|
|
|
self.connection.send(common.xmpp.Presence(jid, 'unsubscribed'))
|
2005-04-12 13:46:20 +02:00
|
|
|
|
|
|
|
def unsubscribe(self, jid):
|
|
|
|
if not self.connection:
|
|
|
|
return
|
|
|
|
delauth = gajim.config.get('delauth')
|
|
|
|
delroster = gajim.config.get('delroster')
|
|
|
|
if delauth:
|
2005-04-26 20:45:54 +02:00
|
|
|
self.connection.getRoster().Unsubscribe(jid)
|
2005-04-12 13:46:20 +02:00
|
|
|
if delroster:
|
2005-04-26 20:45:54 +02:00
|
|
|
self.connection.getRoster().delItem(jid)
|
2005-04-12 13:46:20 +02:00
|
|
|
|
2005-05-11 11:08:06 +02:00
|
|
|
def _continue_unsubscribe(self, con, iq_obj, agent):
|
|
|
|
self.connection.getRoster().delItem(agent)
|
2005-04-12 13:46:20 +02:00
|
|
|
self.dispatch('AGENT_REMOVED', agent)
|
|
|
|
|
2005-05-08 19:33:08 +02:00
|
|
|
def unsubscribe_agent(self, agent):
|
|
|
|
if not self.connection:
|
|
|
|
return
|
2005-05-11 11:08:06 +02:00
|
|
|
iq = common.xmpp.Iq('set', common.xmpp.NS_REGISTER, to = agent)
|
|
|
|
iq.getTag('query').setTag('remove')
|
|
|
|
self.connection.SendAndCallForResponse(iq, self._continue_unsubscribe,
|
2005-05-08 19:33:08 +02:00
|
|
|
{'agent': agent})
|
|
|
|
return
|
|
|
|
|
2005-04-12 13:46:20 +02:00
|
|
|
def update_user(self, jid, name, groups):
|
|
|
|
if self.connection:
|
2005-04-30 10:48:50 +02:00
|
|
|
self.connection.getRoster().setItem(jid = jid, name = name,
|
2005-04-26 20:45:54 +02:00
|
|
|
groups = groups)
|
2005-04-12 13:46:20 +02:00
|
|
|
|
2005-04-23 23:54:12 +02:00
|
|
|
def request_agents(self, jid, node):
|
2005-04-12 13:46:20 +02:00
|
|
|
if self.connection:
|
2005-05-07 12:57:40 +02:00
|
|
|
self.connection.send(common.xmpp.Iq(to = jid, typ = 'get',
|
|
|
|
queryNS = common.xmpp.NS_BROWSE))
|
2005-04-26 20:45:54 +02:00
|
|
|
self.discoverInfo(jid, node)
|
2005-04-12 13:46:20 +02:00
|
|
|
|
2005-05-08 22:56:11 +02:00
|
|
|
def _receive_register_agent_info(self, con, iq_obj, agent):
|
|
|
|
if not common.xmpp.isResultNode(iq_obj):
|
|
|
|
return
|
|
|
|
iq = common.xmpp.Iq('get', common.xmpp.NS_REGISTER, to = agent)
|
|
|
|
df = iq_obj.getTag('query', namespace = common.xmpp.NS_REGISTER).\
|
|
|
|
getTag('x', namespace = common.xmpp.NS_DATA)
|
|
|
|
if df:
|
|
|
|
df = common.xmpp.DataForm(node = df)
|
|
|
|
self.dispatch('REGISTER_AGENT_INFO', (agent, df.asDict()))
|
|
|
|
return
|
|
|
|
df = common.xmpp.DataForm(typ = 'form')
|
|
|
|
for i in iq_obj.getQueryPayload():
|
|
|
|
if type(i) != type(iq):
|
|
|
|
pass
|
|
|
|
elif i.getName() == 'instructions':
|
|
|
|
df.addInstructions(i.getData())
|
|
|
|
else:
|
|
|
|
df.setField(i.getName()).setValue(i.getData())
|
|
|
|
self.dispatch('REGISTER_AGENT_INFO', (agent, df.asDict()))
|
|
|
|
return
|
|
|
|
|
|
|
|
def request_register_agent_info(self, agent):
|
2005-04-12 13:46:20 +02:00
|
|
|
if not self.connection:
|
|
|
|
return None
|
2005-05-08 22:56:11 +02:00
|
|
|
iq = common.xmpp.Iq('get', common.xmpp.NS_REGISTER, to = agent)
|
|
|
|
self.connection.SendAndCallForResponse(iq,
|
|
|
|
self._receive_register_agent_info, {'agent': agent})
|
|
|
|
return
|
2005-04-26 20:45:54 +02:00
|
|
|
|
|
|
|
def register_agent(self, agent, info):
|
2005-04-12 13:46:20 +02:00
|
|
|
if not self.connection:
|
|
|
|
return
|
2005-04-26 20:45:54 +02:00
|
|
|
common.xmpp.features.register(self.connection, agent, info) # FIXME: Blocking
|
2005-04-12 13:46:20 +02:00
|
|
|
|
2005-05-10 11:20:35 +02:00
|
|
|
def new_account(self, name, config):
|
2005-04-12 13:46:20 +02:00
|
|
|
# If a connection already exist we cannot create a new account
|
|
|
|
if self.connection:
|
|
|
|
return
|
2005-05-10 11:20:35 +02:00
|
|
|
if config['use_proxy']:
|
2005-05-10 17:38:16 +02:00
|
|
|
proxy = {'host': config['proxyhost'], 'port': config['proxyport'],
|
|
|
|
'user': config['proxyuser'], 'password': config['proxypass']}
|
2005-04-12 13:46:20 +02:00
|
|
|
else:
|
|
|
|
proxy = None
|
2005-05-10 11:20:35 +02:00
|
|
|
c = common.xmpp.Client(server = config['hostname'], debug = [])
|
2005-05-09 12:34:47 +02:00
|
|
|
try:
|
|
|
|
c.connect(proxy = proxy)
|
|
|
|
except:
|
2005-05-10 11:20:35 +02:00
|
|
|
gajim.log.debug('Couldn\'t connect to %s' % config['hostname'])
|
|
|
|
self.dispatch('ERROR', _('Couldn\'t connect to ') + config['hostname'])
|
2005-05-09 12:34:47 +02:00
|
|
|
return 0
|
2005-04-12 13:46:20 +02:00
|
|
|
else:
|
2005-05-18 14:02:27 +02:00
|
|
|
gajim.log.debug('Connected to server')
|
2005-05-10 11:20:35 +02:00
|
|
|
req = common.xmpp.features.getRegInfo(c, config['hostname']).asDict() # FIXME! This blocks!
|
|
|
|
req['username'] = config['name']
|
|
|
|
req['password'] = config['password']
|
|
|
|
if not common.xmpp.features.register(c, config['hostname'], req): #FIXME: error
|
2005-05-09 12:34:47 +02:00
|
|
|
self.dispatch('ERROR', _('Error: ') + c.lastErr)
|
2005-04-12 13:46:20 +02:00
|
|
|
else:
|
2005-05-09 12:34:47 +02:00
|
|
|
self.name = name
|
|
|
|
self.connected = 0
|
2005-05-10 11:20:35 +02:00
|
|
|
self.password = config['password']
|
2005-05-09 12:34:47 +02:00
|
|
|
if USE_GPG:
|
|
|
|
self.gpg = GnuPG.GnuPG()
|
|
|
|
gajim.config.set('usegpg', True)
|
|
|
|
else:
|
|
|
|
gajim.config.set('usegpg', False)
|
2005-05-10 11:20:35 +02:00
|
|
|
gajim.connections[name] = self
|
|
|
|
self.dispatch('ACC_OK', (name, config))
|
2005-04-12 13:46:20 +02:00
|
|
|
|
|
|
|
def account_changed(self, new_name):
|
|
|
|
self.name = new_name
|
|
|
|
|
|
|
|
def request_os_info(self, jid, resource):
|
|
|
|
if not self.connection:
|
|
|
|
return
|
2005-04-26 20:45:54 +02:00
|
|
|
iq = common.xmpp.Iq(to=jid + '/' + resource, typ = 'get', queryNS =\
|
|
|
|
common.xmpp.NS_VERSION)
|
2005-04-12 13:46:20 +02:00
|
|
|
self.connection.send(iq)
|
|
|
|
|
|
|
|
def request_vcard(self, jid):
|
|
|
|
if not self.connection:
|
|
|
|
return
|
2005-04-26 20:45:54 +02:00
|
|
|
iq = common.xmpp.Iq(to = jid, typ = 'get')
|
|
|
|
iq.setTag(common.xmpp.NS_VCARD + ' vCard')
|
2005-04-12 13:46:20 +02:00
|
|
|
self.connection.send(iq)
|
|
|
|
#('VCARD', {entry1: data, entry2: {entry21: data, ...}, ...})
|
|
|
|
|
|
|
|
def send_vcard(self, vcard):
|
|
|
|
if not self.connection:
|
|
|
|
return
|
2005-04-26 20:45:54 +02:00
|
|
|
iq = common.xmpp.Iq(typ = 'set')
|
|
|
|
iq2 = iq.setTag(common.xmpp.NS_VCARD + ' vCard')
|
2005-04-12 13:46:20 +02:00
|
|
|
for i in vcard.keys():
|
|
|
|
if i != 'jid':
|
|
|
|
if type(vcard[i]) == type({}):
|
2005-04-26 20:45:54 +02:00
|
|
|
iq3 = iq2.addChild(i)
|
2005-04-12 13:46:20 +02:00
|
|
|
for j in vcard[i].keys():
|
2005-04-26 20:45:54 +02:00
|
|
|
iq3.addChild(j).setData(vcard[i][j])
|
2005-04-12 13:46:20 +02:00
|
|
|
else:
|
2005-04-26 20:45:54 +02:00
|
|
|
iq2.addChild(i).setData(vcard[i])
|
2005-04-12 13:46:20 +02:00
|
|
|
self.connection.send(iq)
|
|
|
|
|
2005-04-12 14:23:08 +02:00
|
|
|
def send_agent_status(self, agent, ptype):
|
2005-04-12 13:46:20 +02:00
|
|
|
if not self.connection:
|
|
|
|
return
|
2005-04-12 14:23:08 +02:00
|
|
|
if not ptype:
|
|
|
|
ptype = 'available';
|
2005-04-26 20:45:54 +02:00
|
|
|
p = common.xmpp.Presence(to = agent, typ = ptype)
|
2005-04-12 13:46:20 +02:00
|
|
|
self.connection.send(p)
|
|
|
|
|
2005-04-18 14:17:43 +02:00
|
|
|
def join_gc(self, nick, room, server, password):
|
2005-04-12 13:46:20 +02:00
|
|
|
if not self.connection:
|
|
|
|
return
|
2005-05-13 20:54:44 +02:00
|
|
|
p = common.xmpp.Presence(to = '%s@%s/%s' % (room, server, nick),
|
|
|
|
show = STATUS_LIST[self.connected], status = self.status)
|
2005-05-18 11:18:29 +02:00
|
|
|
t = p.setTag(common.xmpp.NS_MUC + ' x')
|
|
|
|
if password:
|
|
|
|
t.setTagData('password', password)
|
2005-04-12 13:46:20 +02:00
|
|
|
self.connection.send(p)
|
|
|
|
|
|
|
|
def send_gc_message(self, jid, msg):
|
|
|
|
if not self.connection:
|
|
|
|
return
|
2005-04-26 20:45:54 +02:00
|
|
|
msg_iq = common.xmpp.Message(jid, msg, typ = 'groupchat')
|
2005-04-12 13:46:20 +02:00
|
|
|
self.connection.send(msg_iq)
|
|
|
|
self.dispatch('MSGSENT', (jid, msg))
|
|
|
|
|
|
|
|
def send_gc_subject(self, jid, subject):
|
|
|
|
if not self.connection:
|
|
|
|
return
|
2005-04-26 20:45:54 +02:00
|
|
|
msg_iq = common.xmpp.Message(jid,typ = 'groupchat', subject = subject)
|
2005-04-12 13:46:20 +02:00
|
|
|
self.connection.send(msg_iq)
|
|
|
|
|
2005-04-20 12:21:33 +02:00
|
|
|
def request_gc_config(self, room_jid):
|
2005-04-26 20:45:54 +02:00
|
|
|
iq = common.xmpp.Iq(typ = 'get', queryNS = common.xmpp.NS_MUC_OWNER,\
|
|
|
|
to = room_jid)
|
2005-04-20 12:21:33 +02:00
|
|
|
self.connection.send(iq)
|
|
|
|
|
2005-04-12 13:46:20 +02:00
|
|
|
def send_gc_status(self, nick, jid, show, status):
|
|
|
|
if not self.connection:
|
|
|
|
return
|
|
|
|
if show == 'offline':
|
2005-04-12 14:23:08 +02:00
|
|
|
ptype = 'unavailable'
|
2005-04-12 13:46:20 +02:00
|
|
|
show = None
|
|
|
|
else:
|
2005-04-12 14:23:08 +02:00
|
|
|
ptype = 'available'
|
2005-04-26 20:45:54 +02:00
|
|
|
self.connection.send(common.xmpp.Presence(to = '%s/%s' % (jid, nick), \
|
|
|
|
typ = ptype, show = show, status = status))
|
2005-04-12 13:46:20 +02:00
|
|
|
|
|
|
|
def gc_set_role(self, room_jid, nick, role):
|
|
|
|
if not self.connection:
|
|
|
|
return
|
2005-04-26 20:45:54 +02:00
|
|
|
iq = common.xmpp.Iq(typ = 'set', to = room_jid, queryNS =\
|
|
|
|
common.xmpp.NS_MUC_ADMIN)
|
|
|
|
item = iq.getTag('query').setTag('item')
|
|
|
|
item.setAttr('nick', nick)
|
|
|
|
item.setAttr('role', role)
|
2005-04-12 13:46:20 +02:00
|
|
|
self.connection.send(iq)
|
|
|
|
|
|
|
|
def gc_set_affiliation(self, room_jid, jid, affiliation):
|
|
|
|
if not self.connection:
|
|
|
|
return
|
2005-04-26 20:45:54 +02:00
|
|
|
iq = common.xmpp.Iq(typ = 'set', to = room_jid, queryNS =\
|
|
|
|
common.xmpp.NS_MUC_ADMIN)
|
|
|
|
item = iq.getTag('query').setTag('item')
|
|
|
|
item.setAttr('jid', jid)
|
|
|
|
item.setAttr('affiliation', affiliation)
|
2005-04-12 13:46:20 +02:00
|
|
|
self.connection.send(iq)
|
|
|
|
|
2005-04-20 12:21:33 +02:00
|
|
|
def send_gc_config(self, room_jid, config):
|
2005-04-26 20:45:54 +02:00
|
|
|
iq = common.xmpp.Iq(typ = 'set', to = room_jid, queryNS =\
|
|
|
|
common.xmpp.NS_MUC_OWNER)
|
|
|
|
query = iq.getTag('query')
|
|
|
|
x = query.setTag(common.xmpp.NS_DATA + ' x', attrs = {'type': 'submit'}) # FIXME: should really use XData class
|
2005-04-20 12:21:33 +02:00
|
|
|
i = 0
|
|
|
|
while config.has_key(i):
|
2005-04-25 11:30:24 +02:00
|
|
|
if not config[i].has_key('type'):
|
|
|
|
i += 1
|
|
|
|
continue
|
|
|
|
if config[i]['type'] == 'fixed':
|
|
|
|
i += 1
|
|
|
|
continue
|
2005-04-28 00:14:28 +02:00
|
|
|
tag = x.addChild('field')
|
2005-04-20 12:21:33 +02:00
|
|
|
if config[i].has_key('var'):
|
2005-04-26 20:45:54 +02:00
|
|
|
tag.setAttr('var', config[i]['var'])
|
2005-04-20 12:21:33 +02:00
|
|
|
if config[i].has_key('values'):
|
|
|
|
for val in config[i]['values']:
|
|
|
|
if val == False:
|
2005-04-25 11:30:24 +02:00
|
|
|
val = '0'
|
2005-04-20 12:21:33 +02:00
|
|
|
elif val == True:
|
2005-04-25 11:30:24 +02:00
|
|
|
val = '1'
|
2005-04-26 20:45:54 +02:00
|
|
|
tag.setTagData('value', val)
|
2005-04-20 12:21:33 +02:00
|
|
|
i += 1
|
|
|
|
self.connection.send(iq)
|
|
|
|
|
2005-04-12 13:46:20 +02:00
|
|
|
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')
|
2005-04-26 20:45:54 +02:00
|
|
|
iq = common.xmpp.Iq(typ = 'set', to = hostname)
|
|
|
|
q = iq.setTag(common.xmpp.NS_REGISTER + ' query')
|
|
|
|
q.setTagData('username',username)
|
|
|
|
q.setTagData('password',password)
|
2005-04-12 13:46:20 +02:00
|
|
|
self.connection.send(iq)
|
|
|
|
|
2005-04-20 14:23:41 +02:00
|
|
|
def unregister_account(self):
|
|
|
|
if self.connected == 0:
|
|
|
|
self.connection = self.connect()
|
|
|
|
if self.connected > 1:
|
|
|
|
hostname = gajim.config.get_per('accounts', self.name, 'hostname')
|
2005-04-26 20:45:54 +02:00
|
|
|
iq = common.xmpp.Iq(typ = 'set', to = hostname)
|
|
|
|
q = iq.setTag(common.xmpp.NS_REGISTER + ' query').setTag('remove')
|
2005-04-20 14:23:41 +02:00
|
|
|
self.connection.send(iq)
|
2005-04-20 00:29:38 +02:00
|
|
|
|
2005-04-18 11:18:50 +02:00
|
|
|
def process(self, timeout):
|
2005-04-12 13:46:20 +02:00
|
|
|
if not self.connection:
|
|
|
|
return
|
|
|
|
if self.connected:
|
2005-05-18 15:42:12 +02:00
|
|
|
try:
|
|
|
|
self.connection.Process(timeout)
|
2005-05-18 20:57:54 +02:00
|
|
|
except:
|
2005-05-20 19:30:29 +02:00
|
|
|
gajim.log.debug('error appeared while processing xmpp:')
|
|
|
|
traceback.print_exc()
|
2005-05-18 15:42:12 +02:00
|
|
|
self.connected = 0
|
|
|
|
self.dispatch('STATUS', 'offline')
|
2005-05-23 12:46:22 +02:00
|
|
|
if not self.connection:
|
|
|
|
return
|
2005-05-18 15:42:12 +02:00
|
|
|
try:
|
|
|
|
self.connection.disconnect()
|
|
|
|
except:
|
2005-05-20 19:30:29 +02:00
|
|
|
gajim.log.debug('error appeared while processing xmpp:')
|
|
|
|
traceback.print_exc()
|
2005-05-18 15:42:12 +02:00
|
|
|
self.connection = None
|
2005-04-12 13:46:20 +02:00
|
|
|
# END GajimCore
|