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>
2005-07-30 12:59:15 +02:00
## - Dimitur Kirov <dkirov@gmail.com>
2005-04-12 13:46:20 +02:00
##
## 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
2005-08-07 23:42:32 +02:00
import sha
2005-04-12 13:46:20 +02:00
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-06-28 21:03:00 +02:00
import threading
2005-07-30 12:19:52 +02:00
import select
2005-07-30 12:59:15 +02:00
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-05-27 07:56:17 +02:00
from common import helpers
2005-04-14 09:42:26 +02:00
from common import gajim
from common import GnuPG
2005-08-02 00:58:14 +02:00
import socks5
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-06-04 22:54:21 +02:00
' Source Mage ' : ' /etc/sourcemage_version ' ,
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 '
2005-08-09 13:34:16 +02:00
full_path_to_executable = helpers . is_in_path ( executable , return_abs_path = True )
if 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 ( )
# some distros put n/a in places so remove them
pattern = sre . compile ( r ' n/a ' , sre . IGNORECASE )
output = sre . sub ( pattern , ' ' , output )
return output
2005-04-12 13:46:20 +02:00
# 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 )
2005-06-04 23:52:49 +02:00
text = fd . readline ( ) . strip ( ) #get only first line
2005-04-12 13:46:20 +02:00
fd . close ( )
if path_to_file . endswith ( ' version ' ) :
2005-06-04 22:54:21 +02:00
# sourcemage_version has all the info we need
2005-06-06 02:11:48 +02:00
if not os . path . basename ( path_to_file ) . startswith ( ' sourcemage ' ) :
2005-06-04 22:54:21 +02:00
text = distro_name + ' ' + text
2005-06-29 10:28:12 +02:00
elif path_to_file . endswith ( ' aurox-release ' ) :
# file doesn't have version
2005-04-19 15:14:41 +02:00
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
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-08-07 23:42:32 +02:00
self . vcard_sha = None
2005-05-13 20:54:44 +02:00
self . status = ' '
2005-07-07 22:45:24 +02:00
self . new_account_info = None
2005-06-07 20:21:36 +02:00
self . bookmarks = [ ]
2005-05-27 14:07:20 +02:00
self . on_purpose = False
2005-06-26 01:25:17 +02:00
self . last_incoming = time . time ( )
self . keep_alive_sent = False
2005-06-29 10:28:12 +02:00
self . to_be_sent = [ ]
self . last_sent = [ ]
2005-08-03 16:04:54 +02:00
self . files_props = { }
2005-04-14 13:06:58 +02:00
self . password = gajim . config . get_per ( ' accounts ' , name , ' password ' )
2005-07-22 18:36:20 +02:00
self . privacy_rules_supported = False
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__
2005-08-09 20:45:16 +02:00
def put_event ( self , ev ) :
gajim . events_for_ui [ self . name ] . append ( ev )
2005-06-07 09:40:15 +02:00
def dispatch ( self , event , data ) :
2005-06-29 14:57:46 +02:00
''' always passes account name as first param '''
2005-08-09 20:45:16 +02:00
gajim . mutex_events_for_ui . lock ( self . put_event , [ event , data ] )
gajim . mutex_events_for_ui . unlock ( )
2005-04-12 13:46:20 +02:00
2005-08-07 23:42:32 +02:00
def add_sha ( self , p ) :
c = p . setTag ( ' x ' , namespace = common . xmpp . NS_VCARD_UPDATE )
if self . vcard_sha is not None :
c . setTagData ( ' photo ' , self . vcard_sha )
return p
2005-05-31 15:53:22 +02:00
# this is in features.py but it is blocking
def _discover ( self , ns , jid , node = None ) :
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 )
2005-07-04 23:30:00 +02:00
self . to_be_sent . append ( iq )
2005-04-26 20:45:54 +02:00
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 ) :
2005-06-07 03:10:24 +02:00
""" Called when we receive a vCard
2005-04-12 13:46:20 +02:00
Parse the vCard and send it to plugins """
2005-06-26 21:40:57 +02:00
frm_iq = vc . getFrom ( )
2005-08-08 15:34:48 +02:00
name = gajim . config . get_per ( ' accounts ' , self . name , ' name ' )
hostname = gajim . config . get_per ( ' accounts ' , self . name , ' hostname ' )
our_jid = name + ' @ ' + hostname
2005-06-26 21:40:57 +02:00
resource = ' '
if frm_iq :
frm = frm_iq . getStripped ( )
resource = frm_iq . getResource ( )
2005-05-24 21:18:32 +02:00
else :
2005-08-08 15:34:48 +02:00
frm = our_jid
2005-06-26 21:40:57 +02:00
vcard = { ' jid ' : frm , ' resource ' : resource }
2005-06-20 22:58:57 +02:00
if not vc . getTag ( ' vCard ' ) :
return
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 ( ) :
2005-06-07 10:50:47 +02:00
name = info . getName ( )
if name in [ ' ADR ' , ' TEL ' , ' EMAIL ' ] : # we can have several
if not vcard . has_key ( name ) :
vcard [ name ] = [ ]
entry = { }
for c in info . getChildren ( ) :
entry [ c . getName ( ) ] = c . getData ( )
vcard [ name ] . append ( entry )
elif info . getChildren ( ) == [ ] :
vcard [ name ] = info . getData ( )
2005-04-12 13:46:20 +02:00
else :
2005-06-07 10:50:47 +02:00
vcard [ name ] = { }
2005-04-12 13:46:20 +02:00
for c in info . getChildren ( ) :
2005-06-07 10:50:47 +02:00
vcard [ name ] [ c . getName ( ) ] = c . getData ( )
2005-08-08 15:34:48 +02:00
if frm == our_jid :
2005-08-07 23:42:32 +02:00
if vcard . has_key ( ' PHOTO ' ) and type ( vcard [ ' PHOTO ' ] ) == type ( { } ) and \
vcard [ ' PHOTO ' ] . has_key ( ' BINVAL ' ) :
photo = vcard [ ' PHOTO ' ] [ ' BINVAL ' ]
self . vcard_sha = sha . sha ( photo ) . hexdigest ( )
else :
self . vcard_sha = ' '
2005-04-12 13:46:20 +02:00
self . dispatch ( ' MYVCARD ' , vcard )
2005-08-07 23:42:32 +02:00
#we re-send our presence with sha
sshow = STATUS_LIST [ self . connected ]
2005-08-08 14:23:51 +02:00
p = common . xmpp . Presence ( typ = None , show = sshow ,
status = self . status )
2005-08-07 23:42:32 +02:00
p = self . add_sha ( p )
self . to_be_sent . append ( p )
2005-04-12 13:46:20 +02:00
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 ) :
2005-06-07 03:10:24 +02:00
""" Called when we receive 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-07-05 23:44:01 +02:00
subject = msg . getSubject ( ) # if not there, it's None
2005-04-12 13:46:20 +02:00
tim = msg . getTimestamp ( )
tim = time . strptime ( tim , ' % Y % m %d T % H: % M: % S ' )
2005-04-27 20:26:31 +02:00
tim = time . localtime ( timegm ( tim ) )
2005-05-30 12:41:55 +02:00
encrypted = False
2005-07-21 16:56:39 +02:00
chatstate = None
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
2005-07-19 16:38:58 +02:00
# chatstates - look for chatstate tags in a message
children = msg . getChildren ( )
for child in children :
if child . getNamespace ( ) == ' http://jabber.org/protocol/chatstates ' :
2005-07-21 16:56:39 +02:00
chatstate = child . getName ( )
2005-07-19 16:38:58 +02:00
break
2005-04-12 13:46:20 +02:00
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-05-30 12:41:55 +02:00
encrypted = True
2005-04-12 14:23:08 +02:00
if mtype == ' error ' :
2005-06-29 14:57:46 +02:00
self . dispatch ( ' MSGERROR ' , ( str ( msg . getFrom ( ) ) ,
2005-04-12 13:46:20 +02:00
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
if subject :
self . dispatch ( ' GC_SUBJECT ' , ( str ( msg . getFrom ( ) ) , subject ) )
else :
2005-06-07 13:05:58 +02:00
if not msg . getTag ( ' body ' ) : #no <body>
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-07-05 23:35:37 +02:00
elif mtype == ' normal ' : # it's single message
log_msgtxt = msgtxt
if subject :
log_msgtxt = _ ( ' Subject: %s \n %s ' ) % ( subject , msgtxt )
gajim . logger . write ( ' incoming ' , log_msgtxt , str ( msg . getFrom ( ) ) ,
tim = tim )
self . dispatch ( ' MSG ' , ( str ( msg . getFrom ( ) ) , msgtxt , tim , encrypted ,
2005-07-19 16:38:58 +02:00
mtype , subject , None ) )
2005-07-05 23:35:37 +02:00
else : # it's type 'chat'
2005-07-21 16:56:39 +02:00
if not msg . getTag ( ' body ' ) and chatstate is None : #no <body>
2005-06-07 13:05:58 +02:00
return
2005-07-05 23:35:37 +02:00
log_msgtxt = msgtxt
if subject :
log_msgtxt = _ ( ' Subject: %s \n %s ' ) % ( subject , msgtxt )
2005-07-22 22:27:24 +02:00
if msg . getTag ( ' body ' ) :
gajim . logger . write ( ' incoming ' , log_msgtxt , str ( msg . getFrom ( ) ) ,
tim = tim )
2005-07-05 23:35:37 +02:00
self . dispatch ( ' MSG ' , ( str ( msg . getFrom ( ) ) , msgtxt , tim , encrypted ,
2005-07-21 16:56:39 +02:00
mtype , subject , chatstate ) )
2005-04-12 13:46:20 +02:00
# END messageCB
def _presenceCB ( self , con , prs ) :
2005-06-07 03:10:24 +02:00
""" Called when we receive a presence """
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 ( )
2005-06-04 00:49:07 +02:00
if ptype == ' available ' : ptype = None
2005-07-07 19:20:43 +02:00
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-06-23 20:27:14 +02:00
show = prs . getShow ( )
if not show in STATUS_LIST :
show = ' ' # We ignore unknown show
if not ptype and 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-08-07 23:42:32 +02:00
p = common . xmpp . Presence ( who , ' subscribed ' )
p = self . add_sha ( p )
self . to_be_sent . append ( p )
2005-04-12 13:46:20 +02:00
if who . find ( " @ " ) < = 0 :
2005-06-29 10:28:12 +02:00
self . dispatch ( ' NOTIFY ' ,
( prs . getFrom ( ) . getStripped ( ) . encode ( ' utf8 ' ) , ' offline ' ,
' offline ' , prs . getFrom ( ) . getResource ( ) . encode ( ' utf8 ' ) , prio ,
2005-04-12 13:46:20 +02:00
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 ( )
2005-06-29 10:28:12 +02:00
self . dispatch ( ' SUBSCRIBED ' , ( jid . getStripped ( ) . encode ( ' utf8 ' ) ,
jid . getResource ( ) . encode ( ' utf8 ' ) ) )
2005-07-07 19:20:43 +02:00
#BE CAREFUL: no con.updateRosterItem() in a callback
2005-08-02 00:58:14 +02:00
gajim . log . debug ( _ ( ' we are now subscribed to %s ' ) % who )
2005-04-12 14:23:08 +02:00
elif ptype == ' unsubscribe ' :
2005-07-24 22:00:38 +02:00
gajim . log . debug ( _ ( ' unsubscribe request from %s ' ) % who )
2005-04-12 14:23:08 +02:00
elif ptype == ' unsubscribed ' :
2005-08-02 00:58:14 +02:00
gajim . log . debug ( _ ( ' we are now unsubscribed from %s ' ) % who )
2005-04-12 13:46:20 +02:00
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-07-07 19:20:43 +02:00
if errcode == ' 409 ' : #conflict: Nick Conflict
2005-06-07 09:40:15 +02:00
self . dispatch ( ' ERROR ' , ( errmsg , ' ' ) )
2005-05-24 23:32:52 +02:00
elif errcode == ' 502 ' : # Internal Timeout:
2005-06-04 02:37:49 +02:00
self . dispatch ( ' NOTIFY ' , ( prs . getFrom ( ) . getStripped ( ) . encode ( ' utf8 ' ) ,
2005-06-20 09:50:50 +02:00
' error ' , errmsg , prs . getFrom ( ) . getResource ( ) . encode ( ' utf8 ' ) ,
prio , keyID , prs . getRole ( ) , prs . getAffiliation ( ) , prs . getJid ( ) ,
prs . getReason ( ) , prs . getActor ( ) , prs . getStatusCode ( ) ,
prs . getNewNick ( ) ) )
2005-04-12 13:46:20 +02:00
else :
2005-08-09 17:28:32 +02:00
self . dispatch ( ' ERROR_ANSWER ' , ( ' ' , prs . getFrom ( ) . getStripped ( ) ,
errmsg , errcode ) )
2005-06-04 00:49:07 +02:00
if not ptype or ptype == ' unavailable ' :
2005-06-04 02:37:49 +02:00
jid = prs . getFrom ( )
2005-06-13 16:46:08 +02:00
gajim . logger . write ( ' status ' , status , str ( jid ) . encode ( ' utf8 ' ) , show )
2005-06-04 02:37:49 +02:00
account = prs . getFrom ( ) . getStripped ( ) . encode ( ' utf8 ' )
resource = prs . getFrom ( ) . getResource ( ) . encode ( ' utf8 ' )
self . dispatch ( ' NOTIFY ' , ( account , show , status ,
resource , prio , keyID , prs . getRole ( ) ,
2005-05-24 23:32:52 +02:00
prs . getAffiliation ( ) , prs . getJid ( ) , prs . getReason ( ) ,
2005-06-19 00:09:31 +02:00
prs . getActor ( ) , prs . getStatusCode ( ) , prs . getNewNick ( ) ) )
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 ' )
2005-05-27 14:07:20 +02:00
if not self . connection :
return
self . connected = 0
self . dispatch ( ' STATUS ' , ' offline ' )
self . connection = None
if not self . on_purpose :
2005-06-07 03:17:38 +02:00
self . dispatch ( ' ERROR ' ,
2005-06-07 09:40:15 +02:00
( _ ( ' Connection with account " %s " has been lost ' ) % self . name ,
_ ( ' To continue sending and receiving messages, you will need to reconnect. ' ) ) )
2005-05-27 14:07:20 +02:00
self . on_purpose = False
2005-08-06 18:31:41 +02:00
2005-04-12 13:46:20 +02:00
# END disconenctedCB
2005-08-06 18:31:41 +02:00
def _bytestreamErrorCB ( self , con , iq_obj ) :
gajim . log . debug ( ' _bytestreamErrorCB ' )
frm = str ( iq_obj . getFrom ( ) )
id = str ( iq_obj . getAttr ( ' id ' ) )
query = iq_obj . getTag ( ' query ' )
streamhost = query . getTag ( ' streamhost ' )
jid = iq_obj . getFrom ( ) . getStripped ( ) . encode ( ' utf8 ' )
id = id [ 3 : ]
if not self . files_props . has_key ( id ) :
return
file_props = self . files_props [ id ]
self . dispatch ( ' FILE_REQUEST_ERROR ' , ( jid , file_props ) )
raise common . xmpp . NodeProcessed
2005-07-30 12:19:52 +02:00
def _bytestreamSetCB ( self , con , iq_obj ) :
gajim . log . debug ( ' _bytestreamSetCB ' )
target = str ( iq_obj . getAttr ( ' to ' ) )
id = str ( iq_obj . getAttr ( ' id ' ) )
query = iq_obj . getTag ( ' query ' )
sid = str ( query . getAttr ( ' sid ' ) )
2005-08-02 00:45:29 +02:00
file_props = gajim . socks5queue . get_file_props (
self . name , sid )
2005-07-30 12:19:52 +02:00
streamhosts = [ ]
for item in query . getChildren ( ) :
if item . getName ( ) == ' streamhost ' :
2005-08-06 18:31:41 +02:00
host_dict = {
2005-08-06 22:18:44 +02:00
' state ' : 0 ,
' target ' : target ,
' id ' : id ,
2005-08-07 15:24:21 +02:00
' sid ' : sid ,
2005-08-06 22:18:44 +02:00
' initiator ' : str ( iq_obj . getFrom ( ) )
2005-08-06 18:31:41 +02:00
}
2005-07-30 12:19:52 +02:00
for attr in item . getAttrs ( ) :
val = item . getAttr ( attr )
if type ( val ) == unicode :
val = val . encode ( ' utf-8 ' )
if type ( attr ) == unicode :
attr = attr . encode ( ' utf-8 ' )
host_dict [ attr ] = val
streamhosts . append ( host_dict )
2005-08-06 18:31:41 +02:00
if file_props is None :
if self . files_props . has_key ( sid ) :
file_props = self . files_props [ sid ]
file_props [ ' fast ' ] = streamhosts
2005-08-07 14:05:36 +02:00
if file_props [ ' type ' ] == ' s ' :
# only psi do this
if file_props . has_key ( ' streamhosts ' ) :
file_props [ ' streamhosts ' ] . extend ( streamhosts )
else :
file_props [ ' streamhosts ' ] = streamhosts
if not gajim . socks5queue . get_file_props ( self . name , sid ) :
gajim . socks5queue . add_file_props ( self . name , file_props )
gajim . socks5queue . connect_to_hosts ( self . name , sid ,
self . send_success_connect_reply , None )
2005-08-06 18:31:41 +02:00
raise common . xmpp . NodeProcessed
fast = None
try :
fast = query . getTag ( ' fast ' )
except Exception , e :
pass
if fast is not None :
2005-08-06 22:18:44 +02:00
if fast . getNamespace ( ) == common . xmpp . NS_STREAM :
self . send_socks5_info ( file_props , fast = False ,
2005-08-06 18:31:41 +02:00
receiver = file_props [ ' sender ' ] , sender = file_props [ ' receiver ' ] )
self . files_props [ sid ] = file_props
file_props [ ' streamhosts ' ] = streamhosts
conn_err = False
if file_props [ ' type ' ] == ' r ' :
gajim . socks5queue . connect_to_hosts ( self . name , sid ,
self . send_success_connect_reply , self . _connect_error )
raise common . xmpp . NodeProcessed
def send_success_connect_reply ( self , streamhost ) :
''' send reply to the initiator of FT that we
made a connection
'''
if streamhost is None :
return None
2005-08-06 22:18:44 +02:00
iq = common . xmpp . Iq ( to = streamhost [ ' initiator ' ] , typ = ' result ' ,
2005-08-06 18:31:41 +02:00
frm = streamhost [ ' target ' ] )
iq . setAttr ( ' id ' , streamhost [ ' id ' ] )
query = iq . setTag ( ' query ' )
query . setNamespace ( common . xmpp . NS_BYTESTREAM )
stream_tag = query . setTag ( ' streamhost-used ' )
stream_tag . setAttr ( ' jid ' , streamhost [ ' jid ' ] )
self . to_be_sent . append ( iq )
2005-08-07 20:43:53 +02:00
2005-08-06 18:31:41 +02:00
def _connect_error ( self , to , id , code = 404 ) :
msg_dict = {
2005-08-06 22:18:44 +02:00
404 : ' Could not connect to given hosts ' ,
405 : ' Cancel ' ,
406 : ' Not acceptable ' ,
2005-08-06 18:31:41 +02:00
}
msg = msg_dict [ code ]
iq = None
iq = common . xmpp . Protocol ( name = ' iq ' , to = to ,
typ = ' error ' )
iq . setAttr ( ' id ' , id )
err = iq . setTag ( ' error ' )
err . setAttr ( ' code ' , str ( code ) )
err . setData ( msg )
self . to_be_sent . append ( iq )
2005-08-03 16:04:54 +02:00
def _bytestreamResultCB ( self , con , iq_obj ) :
gajim . log . debug ( ' _bytestreamResultCB ' )
frm = str ( iq_obj . getFrom ( ) )
2005-08-06 18:31:41 +02:00
real_id = str ( iq_obj . getAttr ( ' id ' ) )
2005-08-03 16:04:54 +02:00
query = iq_obj . getTag ( ' query ' )
2005-08-06 22:18:44 +02:00
streamhost = None
try :
streamhost = query . getTag ( ' streamhost ' )
except :
pass
if streamhost is not None : # this is a result for proxy request
2005-08-06 23:40:01 +02:00
jid = None
try :
jid = streamhost . getAttr ( ' jid ' )
except :
raise common . xmpp . NodeProcessed
2005-08-06 18:31:41 +02:00
proxyhosts = [ ]
for item in query . getChildren ( ) :
if item . getName ( ) == ' streamhost ' :
2005-08-06 22:18:44 +02:00
host = item . getAttr ( ' host ' )
port = item . getAttr ( ' port ' )
jid = item . getAttr ( ' jid ' )
conf = gajim . config
2005-08-09 16:53:33 +02:00
conf . add_per ( ' ft_proxies65_cache ' , jid )
conf . set_per ( ' ft_proxies65_cache ' , jid , ' host ' , str ( host ) )
conf . set_per ( ' ft_proxies65_cache ' , jid , ' port ' , int ( port ) )
conf . set_per ( ' ft_proxies65_cache ' , jid , ' jid ' , str ( jid ) )
2005-08-06 22:18:44 +02:00
raise common . xmpp . NodeProcessed
try :
streamhost = query . getTag ( ' streamhost-used ' )
except : # this bytestream result is not what we need
2005-08-06 23:40:01 +02:00
pass
2005-08-06 22:18:44 +02:00
id = real_id [ 3 : ]
if self . files_props . has_key ( id ) :
file_props = self . files_props [ id ]
else :
raise common . xmpp . NodeProcessed
2005-08-10 17:59:55 +02:00
if streamhost is None :
# proxy approves the activate query
if real_id [ : 3 ] == ' au_ ' :
id = real_id [ 3 : ]
if not file_props . has_key ( ' streamhost-used ' ) or \
file_props [ ' streamhost-used ' ] is False :
raise common . xmpp . NodeProcessed
if not file_props . has_key ( ' proxyhosts ' ) :
raise common . xmpp . NodeProcessed
for host in file_props [ ' proxyhosts ' ] :
if host [ ' initiator ' ] == frm and \
str ( query . getAttr ( ' sid ' ) ) == file_props [ ' sid ' ] :
gajim . socks5queue . activate_proxy ( host [ ' idx ' ] )
break
raise common . xmpp . NodeProcessed
jid = streamhost . getAttr ( ' jid ' )
2005-08-09 13:38:11 +02:00
if file_props . has_key ( ' streamhost-used ' ) and \
file_props [ ' streamhost-used ' ] is True :
raise common . xmpp . NodeProcessed
if real_id [ : 3 ] == ' au_ ' :
gajim . socks5queue . send_file ( file_props , self . name )
raise common . xmpp . NodeProcessed
2005-08-06 18:31:41 +02:00
proxy = None
if file_props . has_key ( ' proxyhosts ' ) :
for proxyhost in file_props [ ' proxyhosts ' ] :
if proxyhost [ ' jid ' ] == jid :
proxy = proxyhost
2005-08-06 22:18:44 +02:00
2005-08-06 18:31:41 +02:00
if proxy != None :
2005-08-09 13:38:11 +02:00
file_props [ ' streamhost-used ' ] = True
2005-08-06 18:31:41 +02:00
if not file_props . has_key ( ' streamhosts ' ) :
2005-08-09 13:38:11 +02:00
file_props [ ' streamhosts ' ] = [ ]
2005-08-06 18:31:41 +02:00
file_props [ ' streamhosts ' ] . append ( proxy )
file_props [ ' is_a_proxy ' ] = True
receiver = socks5 . Socks5Receiver ( proxy , file_props [ ' sid ' ] , file_props )
gajim . socks5queue . add_receiver ( self . name , receiver )
proxy [ ' idx ' ] = receiver . queue_idx
gajim . socks5queue . on_success = self . proxy_auth_ok
raise common . xmpp . NodeProcessed
2005-08-09 13:38:11 +02:00
else :
2005-08-06 18:31:41 +02:00
gajim . socks5queue . send_file ( file_props , self . name )
if file_props . has_key ( ' fast ' ) :
fasts = file_props [ ' fast ' ]
if len ( fasts ) > 0 :
self . _connect_error ( str ( iq_obj . getFrom ( ) ) , fasts [ 0 ] [ ' id ' ] ,
code = 406 )
2005-08-09 13:38:11 +02:00
2005-08-03 16:04:54 +02:00
raise common . xmpp . NodeProcessed
2005-08-06 18:31:41 +02:00
2005-08-10 17:59:55 +02:00
def remove_all_transfers ( self ) :
''' stops and removes all active connections from the socks5 pool '''
for file_props in self . files_props . values ( ) :
self . remove_transfer ( file_props , remove_from_list = False )
del ( self . files_props )
self . files_props = { }
def remove_transfer ( self , file_props , remove_from_list = True ) :
if file_props . has_key ( ' hash ' ) :
gajim . socks5queue . remove_sender ( file_props [ ' hash ' ] )
if file_props . has_key ( ' streamhosts ' ) :
for host in file_props [ ' streamhosts ' ] :
if host [ ' idx ' ] > 0 :
gajim . socks5queue . remove_receiver ( host [ ' idx ' ] )
gajim . socks5queue . remove_sender ( host [ ' idx ' ] )
sid = file_props [ ' sid ' ]
gajim . socks5queue . remove_file_props ( self . name , sid )
if remove_from_list :
if self . files_props . has_key ( ' sid ' ) :
del ( self . files_props [ ' sid ' ] )
def disconnect_transfer ( self , file_props ) :
if file_props . has_key ( ' hash ' ) :
gajim . socks5queue . remove_sender ( file_props [ ' hash ' ] )
if file_props . has_key ( ' streamhosts ' ) :
for host in file_props [ ' streamhosts ' ] :
if host [ ' idx ' ] > 0 :
gajim . socks5queue . remove_receiver ( host [ ' idx ' ] )
gajim . socks5queue . remove_sender ( host [ ' idx ' ] )
2005-08-06 18:31:41 +02:00
def proxy_auth_ok ( self , proxy ) :
2005-08-07 15:24:21 +02:00
''' cb, called after authentication to proxy server '''
file_props = self . files_props [ proxy [ ' sid ' ] ]
2005-08-06 18:31:41 +02:00
iq = common . xmpp . Protocol ( name = ' iq ' , to = proxy [ ' initiator ' ] ,
typ = ' set ' )
2005-08-07 15:26:03 +02:00
auth_id = " au_ " + proxy [ ' sid ' ]
2005-08-06 18:31:41 +02:00
iq . setID ( auth_id )
query = iq . setTag ( ' query ' )
query . setNamespace ( common . xmpp . NS_BYTESTREAM )
2005-08-07 15:26:03 +02:00
query . setAttr ( ' sid ' , proxy [ ' sid ' ] )
2005-08-06 18:31:41 +02:00
activate = query . setTag ( ' activate ' )
activate . setData ( file_props [ ' proxy_receiver ' ] )
iq . setID ( auth_id )
self . to_be_sent . append ( iq )
2005-08-03 16:04:54 +02:00
2005-07-30 17:06:35 +02:00
def _discoGetCB ( self , con , iq_obj ) :
''' get disco info '''
frm = str ( iq_obj . getFrom ( ) )
to = str ( iq_obj . getAttr ( ' to ' ) )
id = str ( iq_obj . getAttr ( ' id ' ) )
iq = common . xmpp . Iq ( to = frm , typ = ' result ' , queryNS = \
common . xmpp . NS_DISCO , frm = to )
iq . setAttr ( ' id ' , id )
2005-08-01 17:00:27 +02:00
query = iq . setTag ( ' query ' )
2005-07-30 17:06:35 +02:00
# bytestream transfers
feature = common . xmpp . Node ( ' feature ' )
2005-08-01 17:00:27 +02:00
feature . setAttr ( ' var ' , common . xmpp . NS_BYTESTREAM )
query . addChild ( node = feature )
# si methods
feature = common . xmpp . Node ( ' feature ' )
feature . setAttr ( ' var ' , common . xmpp . NS_SI )
query . addChild ( node = feature )
2005-07-30 17:06:35 +02:00
# filetransfers transfers
2005-08-01 17:00:27 +02:00
feature = common . xmpp . Node ( ' feature ' )
feature . setAttr ( ' var ' , common . xmpp . NS_FILE )
query . addChild ( node = feature )
2005-07-30 17:06:35 +02:00
self . to_be_sent . append ( iq )
raise common . xmpp . NodeProcessed
2005-08-03 16:04:54 +02:00
def _siResultCB ( self , con , iq_obj ) :
gajim . log . debug ( ' _siResultCB ' )
id = iq_obj . getAttr ( ' id ' )
if not self . files_props . has_key ( id ) :
2005-08-04 13:18:26 +02:00
# no such jid
2005-08-03 16:04:54 +02:00
return
file_props = self . files_props [ id ]
if file_props is None :
2005-08-04 13:18:26 +02:00
# file properties for jid is none
2005-08-03 16:04:54 +02:00
return
file_props [ ' receiver ' ] = str ( iq_obj . getFrom ( ) )
jid = iq_obj . getFrom ( ) . getStripped ( ) . encode ( ' utf8 ' )
si = iq_obj . getTag ( ' si ' )
feature = si . setTag ( ' feature ' )
if feature . getNamespace ( ) != common . xmpp . NS_FEATURE :
return
form_tag = feature . getTag ( ' x ' )
form = common . xmpp . DataForm ( node = form_tag )
field = form . getField ( ' stream-method ' )
if field . getValue ( ) != common . xmpp . NS_BYTESTREAM :
return
2005-08-06 18:31:41 +02:00
self . send_socks5_info ( file_props , fast = True )
2005-08-03 16:04:54 +02:00
raise common . xmpp . NodeProcessed
def _get_sha ( self , sid , initiator , target ) :
import sha
return sha . new ( " %s %s %s " % ( sid , initiator , target ) ) . hexdigest ( )
2005-07-30 12:19:52 +02:00
2005-08-03 16:04:54 +02:00
def result_socks5_sid ( self , sid , hash_id ) :
2005-08-06 18:31:41 +02:00
''' store the result of sha message from auth '''
2005-08-03 16:04:54 +02:00
if not self . files_props . has_key ( sid ) :
return
file_props = self . files_props [ sid ]
file_props [ ' hash ' ] = hash_id
return
2005-08-06 22:18:44 +02:00
def get_cached_proxies ( self , proxy ) :
''' get cached entries for proxy and request the cache again '''
2005-08-09 16:53:33 +02:00
host = gajim . config . get_per ( ' ft_proxies65_cache ' , proxy , ' host ' )
port = gajim . config . get_per ( ' ft_proxies65_cache ' , proxy , ' port ' )
jid = gajim . config . get_per ( ' ft_proxies65_cache ' , proxy , ' jid ' )
2005-08-06 22:18:44 +02:00
iq = common . xmpp . Protocol ( name = ' iq ' , to = proxy , typ = ' get ' )
query = iq . setTag ( ' query ' )
query . setNamespace ( common . xmpp . NS_BYTESTREAM )
2005-08-07 14:05:36 +02:00
# FIXME bad logic - this should be somewhere else!
# this line should be put somewhere else
# self.to_be_sent.append(iq)
2005-08-06 22:18:44 +02:00
# ensure that we don;t return empty vars
if None not in ( host , port , jid ) or ' ' not in ( host , port , jid ) :
return ( host , port , jid )
return ( None , None , None )
2005-08-06 18:31:41 +02:00
def send_socks5_info ( self , file_props , fast = True , receiver = None ,
sender = None ) :
2005-08-06 22:18:44 +02:00
''' send iq for the present streamhosts and proxies '''
2005-08-03 16:04:54 +02:00
if type ( self . peerhost ) != tuple :
return
2005-08-03 23:10:59 +02:00
port = gajim . config . get ( ' file_transfers_port ' )
2005-08-06 18:31:41 +02:00
proxy = gajim . config . get_per ( ' accounts ' , self . name , ' file_transfers_proxy ' )
2005-08-06 22:18:44 +02:00
2005-08-06 18:31:41 +02:00
if receiver is None :
receiver = file_props [ ' receiver ' ]
if sender is None :
sender = file_props [ ' sender ' ]
2005-08-06 22:18:44 +02:00
proxyhosts = [ ]
2005-08-07 14:05:36 +02:00
if fast and proxy :
2005-08-06 22:18:44 +02:00
proxies = map ( lambda e : e . strip ( ) , proxy . split ( ' , ' ) )
for proxy in proxies :
( host , _port , jid ) = self . get_cached_proxies ( proxy )
if host is None :
continue
host_dict = {
' state ' : 0 ,
' target ' : str ( receiver ) ,
2005-08-06 22:50:47 +02:00
' id ' : file_props [ ' sid ' ] ,
2005-08-07 15:24:21 +02:00
' sid ' : file_props [ ' sid ' ] ,
2005-08-06 22:18:44 +02:00
' initiator ' : proxy ,
' host ' : host ,
' port ' : str ( _port ) ,
' jid ' : jid
}
proxyhosts . append ( host_dict )
2005-08-06 18:31:41 +02:00
sha_str = self . _get_sha ( file_props [ ' sid ' ] , sender ,
receiver )
2005-08-03 16:04:54 +02:00
file_props [ ' sha_str ' ] = sha_str
listener = gajim . socks5queue . start_listener ( self . peerhost [ 0 ] , port ,
sha_str , self . result_socks5_sid , file_props [ ' sid ' ] )
if listener == None :
2005-08-06 23:40:01 +02:00
# FIXME - raise error dialog that address is in use
2005-08-03 16:04:54 +02:00
return
2005-08-06 18:31:41 +02:00
iq = common . xmpp . Protocol ( name = ' iq ' , to = str ( receiver ) ,
2005-08-03 16:04:54 +02:00
typ = ' set ' )
file_props [ ' request-id ' ] = ' id_ ' + file_props [ ' sid ' ]
iq . setID ( file_props [ ' request-id ' ] )
query = iq . setTag ( ' query ' )
query . setNamespace ( common . xmpp . NS_BYTESTREAM )
query . setAttr ( ' mode ' , ' tcp ' )
query . setAttr ( ' sid ' , file_props [ ' sid ' ] )
streamhost = query . setTag ( ' streamhost ' )
streamhost . setAttr ( ' port ' , str ( port ) )
streamhost . setAttr ( ' host ' , self . peerhost [ 0 ] )
2005-08-06 18:31:41 +02:00
streamhost . setAttr ( ' jid ' , sender )
2005-08-06 23:43:04 +02:00
if fast and proxyhosts != [ ] :
2005-08-06 22:18:44 +02:00
file_props [ ' proxy_receiver ' ] = str ( receiver )
file_props [ ' proxy_sender ' ] = str ( sender )
file_props [ ' proxyhosts ' ] = proxyhosts
for proxyhost in proxyhosts :
streamhost = common . xmpp . Node ( tag = ' streamhost ' )
query . addChild ( node = streamhost )
streamhost . setAttr ( ' port ' , proxyhost [ ' port ' ] )
streamhost . setAttr ( ' host ' , proxyhost [ ' host ' ] )
streamhost . setAttr ( ' jid ' , proxyhost [ ' jid ' ] )
proxy = streamhost . setTag ( ' proxy ' )
proxy . setNamespace ( common . xmpp . NS_STREAM )
2005-08-06 18:31:41 +02:00
if fast :
fast_tag = query . setTag ( ' fast ' )
fast_tag . setNamespace ( common . xmpp . NS_STREAM )
2005-08-03 16:04:54 +02:00
self . to_be_sent . append ( iq )
2005-07-30 12:19:52 +02:00
def _siSetCB ( self , con , iq_obj ) :
gajim . log . debug ( ' _siSetCB ' )
jid = iq_obj . getFrom ( ) . getStripped ( ) . encode ( ' utf8 ' )
si = iq_obj . getTag ( ' si ' )
profile = si . getAttr ( ' profile ' )
mime_type = si . getAttr ( ' mime-type ' )
2005-07-30 17:30:38 +02:00
if profile != common . xmpp . NS_FILE :
2005-07-30 12:19:52 +02:00
return
feature = si . getTag ( ' feature ' )
file_tag = si . getTag ( ' file ' )
2005-08-06 22:18:44 +02:00
file_props = { ' type ' : ' r ' }
2005-07-30 12:19:52 +02:00
for attribute in file_tag . getAttrs ( ) :
attribute = attribute . encode ( ' utf-8 ' )
if attribute in [ ' name ' , ' size ' , ' hash ' , ' date ' ] :
val = file_tag . getAttr ( attribute )
if val is None :
continue
if type ( val ) is unicode :
val = val . encode ( ' utf-8 ' )
file_props [ attribute ] = val
file_desc_tag = file_tag . getTag ( ' desc ' )
if file_desc_tag is not None :
file_props [ ' desc ' ] = file_desc_tag . getData ( )
if mime_type is not None :
file_props [ ' mime-type ' ] = mime_type
2005-08-06 18:31:41 +02:00
name = gajim . config . get_per ( ' accounts ' , self . name , ' name ' )
hostname = gajim . config . get_per ( ' accounts ' , self . name , ' hostname ' )
resource = gajim . config . get_per ( ' accounts ' , self . name , ' resource ' )
file_props [ ' receiver ' ] = name + ' @ ' + hostname + ' / ' + resource
2005-07-30 12:19:52 +02:00
file_props [ ' sender ' ] = iq_obj . getFrom ( )
file_props [ ' request-id ' ] = str ( iq_obj . getAttr ( ' id ' ) )
file_props [ ' sid ' ] = str ( si . getAttr ( ' id ' ) )
2005-08-02 00:45:29 +02:00
gajim . socks5queue . add_file_props ( self . name , file_props )
2005-07-30 12:19:52 +02:00
self . dispatch ( ' FILE_REQUEST ' , ( jid , file_props ) )
raise common . xmpp . NodeProcessed
2005-07-30 16:13:45 +02:00
def send_file_rejection ( self , file_props ) :
''' informs sender that we refuse to download the file '''
2005-08-03 16:04:54 +02:00
iq = common . xmpp . Protocol ( name = ' iq ' , to = str ( file_props [ ' sender ' ] ) ,
2005-07-30 16:13:45 +02:00
typ = ' error ' )
iq . setAttr ( ' id ' , file_props [ ' request-id ' ] )
err = common . xmpp . ErrorNode ( code = ' 406 ' , typ = ' auth ' , name = ' not-acceptable ' )
iq . addChild ( node = err )
self . to_be_sent . append ( iq )
2005-07-30 12:19:52 +02:00
def send_file_approval ( self , file_props ) :
2005-07-30 16:13:45 +02:00
''' comfirm that we want to download the file '''
2005-08-03 16:04:54 +02:00
iq = common . xmpp . Protocol ( name = ' iq ' , to = str ( file_props [ ' sender ' ] ) ,
2005-07-30 12:19:52 +02:00
typ = ' result ' )
iq . setAttr ( ' id ' , file_props [ ' request-id ' ] )
si = iq . setTag ( ' si ' )
si . setNamespace ( common . xmpp . NS_SI )
file_tag = si . setTag ( ' file ' )
file_tag . setNamespace ( common . xmpp . NS_FILE )
feature = si . setTag ( ' feature ' )
feature . setNamespace ( common . xmpp . NS_FEATURE )
_feature = common . xmpp . DataForm ( typ = ' submit ' )
feature . addChild ( node = _feature )
field = _feature . setField ( ' stream-method ' )
field . delAttr ( ' type ' )
field . setValue ( ' http://jabber.org/protocol/bytestreams ' )
self . to_be_sent . append ( iq )
2005-08-03 16:04:54 +02:00
def send_file_request ( self , file_props ) :
name = gajim . config . get_per ( ' accounts ' , self . name , ' name ' )
hostname = gajim . config . get_per ( ' accounts ' , self . name , ' hostname ' )
resource = gajim . config . get_per ( ' accounts ' , self . name , ' resource ' )
frm = name + ' @ ' + hostname + ' / ' + resource
file_props [ ' sender ' ] = frm
fjid = file_props [ ' receiver ' ] . jid + ' / ' + file_props [ ' receiver ' ] . resource
iq = common . xmpp . Protocol ( name = ' iq ' , to = fjid ,
typ = ' set ' )
iq . setID ( file_props [ ' sid ' ] )
self . files_props [ file_props [ ' sid ' ] ] = file_props
si = iq . setTag ( ' si ' )
si . setNamespace ( common . xmpp . NS_SI )
si . setAttr ( ' profile ' , common . xmpp . NS_FILE )
si . setAttr ( ' id ' , file_props [ ' sid ' ] )
file_tag = si . setTag ( ' file ' )
file_tag . setNamespace ( common . xmpp . NS_FILE )
file_tag . setAttr ( ' name ' , file_props [ ' name ' ] )
file_tag . setAttr ( ' size ' , file_props [ ' size ' ] )
desc = file_tag . setTag ( ' desc ' )
if file_props . has_key ( ' desc ' ) :
desc . setData ( file_props [ ' desc ' ] )
file_tag . setTag ( ' range ' )
feature = si . setTag ( ' feature ' )
feature . setNamespace ( common . xmpp . NS_FEATURE )
_feature = common . xmpp . DataForm ( typ = ' form ' )
feature . addChild ( node = _feature )
field = _feature . setField ( ' stream-method ' )
field . setAttr ( ' type ' , ' list-single ' )
field . addOption ( ' http://jabber.org/protocol/bytestreams ' )
self . to_be_sent . append ( iq )
2005-04-12 13:46:20 +02:00
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-06-04 02:37:49 +02:00
jid = item . getAttr ( ' jid ' ) . encode ( ' utf8 ' )
2005-04-12 13:46:20 +02:00
name = item . getAttr ( ' name ' )
2005-06-04 02:37:49 +02:00
if name :
name = name . encode ( ' utf8 ' )
sub = item . getAttr ( ' subscription ' ) . encode ( ' utf8 ' )
2005-04-12 13:46:20 +02:00
ask = item . getAttr ( ' ask ' )
2005-06-04 02:37:49 +02:00
if ask :
ask = ask . encode ( ' utf8 ' )
2005-04-12 13:46:20 +02:00
groups = [ ]
for group in item . getTags ( ' group ' ) :
2005-06-04 02:37:49 +02:00
groups . append ( group . getData ( ) . encode ( ' utf8 ' ) )
2005-04-12 13:46:20 +02:00
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 )
2005-07-04 23:30:00 +02:00
self . to_be_sent . append ( 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-07-04 23:30:00 +02:00
self . to_be_sent . append ( common . xmpp . Iq ( typ = ' get ' , queryNS = \
2005-05-07 12:57:40 +02:00
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-07-04 23:30:00 +02:00
self . to_be_sent . append ( 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 ) :
2005-06-10 13:26:37 +02:00
if not self . connection :
return
2005-05-08 19:00:41 +02:00
roster = self . connection . getRoster ( ) . getRaw ( )
2005-07-07 19:20:43 +02:00
if not roster :
2005-05-08 19:00:41 +02:00
roster = { }
2005-06-04 02:37:49 +02:00
else :
for i in roster . keys ( ) :
props = roster [ i ]
if props . has_key ( ' name ' ) and props [ ' name ' ] :
2005-06-29 10:28:12 +02:00
props [ ' name ' ] = props [ ' name ' ] . encode ( ' utf8 ' )
2005-06-04 02:37:49 +02:00
if props . has_key ( ' groups ' ) and props [ ' groups ' ] :
2005-06-29 10:28:12 +02:00
props [ ' groups ' ] = map ( lambda e : e . encode ( ' utf8 ' ) , props [ ' groups ' ] )
2005-06-04 02:37:49 +02:00
if props . has_key ( ' resources ' ) and props [ ' resources ' ] :
2005-06-29 10:28:12 +02:00
props [ ' resources ' ] = map ( lambda e : e . encode ( ' utf8 ' ) ,
props [ ' resources ' ] )
2005-06-04 02:37:49 +02:00
del roster [ i ]
roster [ i . encode ( ' utf8 ' ) ] = props
2005-05-08 19:00:41 +02:00
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-06-07 20:21:36 +02:00
def _PrivateCB ( self , con , iq_obj ) :
2005-06-11 19:21:30 +02:00
'''
2005-06-07 20:21:36 +02:00
Private Data ( JEP 048 and 049 )
2005-06-11 19:21:30 +02:00
'''
gajim . log . debug ( ' PrivateCB ' )
storage = iq_obj . getTag ( ' query ' ) . getTag ( ' storage ' )
2005-06-07 20:21:36 +02:00
try :
ns = storage . getNamespace ( )
except AttributeError :
#Its a result for a 'set' Iq, so we don't do anything here
2005-06-11 19:21:30 +02:00
return
2005-06-07 20:21:36 +02:00
2005-06-11 19:21:30 +02:00
if ns == ' storage:bookmarks ' :
2005-06-07 20:21:36 +02:00
#Bookmarked URLs and Conferences
#http://www.jabber.org/jeps/jep-0048.html
2005-06-11 19:21:30 +02:00
confs = storage . getTags ( ' conference ' )
urls = storage . getTags ( ' url ' )
2005-06-07 20:21:36 +02:00
for conf in confs :
2005-06-11 19:21:30 +02:00
bm = { ' name ' : conf . getAttr ( ' name ' ) ,
' jid ' : conf . getAttr ( ' jid ' ) ,
' autojoin ' : conf . getAttr ( ' autojoin ' ) ,
' password ' : conf . getTagData ( ' password ' ) ,
' nick ' : conf . getTagData ( ' nick ' ) }
2005-06-07 20:21:36 +02:00
2005-06-09 22:35:44 +02:00
self . bookmarks . append ( bm )
2005-06-11 19:21:30 +02:00
self . dispatch ( ' BOOKMARKS ' , self . bookmarks )
elif ns == ' gajim:prefs ' :
2005-06-07 20:21:36 +02:00
#Preferences data
#http://www.jabber.org/jeps/jep-0049.html
#TODO: implement this
2005-08-05 15:29:39 +02:00
pass
def build_http_auth_answer ( self , iq_obj , answer ) :
if answer == ' yes ' :
iq = iq_obj . buildReply ( ' result ' )
elif answer == ' no ' :
iq = iq_obj . buildReply ( ' error ' )
iq . setError ( ' not-authorized ' , 401 )
self . to_be_sent . append ( iq )
def _HttpAuthCB ( self , con , iq_obj ) :
2005-08-06 12:11:02 +02:00
gajim . log . debug ( ' HttpAuthCB ' )
2005-08-05 15:29:39 +02:00
opt = gajim . config . get_per ( ' accounts ' , self . name , ' http_auth ' )
if opt in [ ' yes ' , ' no ' ] :
self . build_http_auth_answer ( iq_obj , opt )
else :
method = iq_obj . getTagAttr ( ' confirm ' , ' method ' )
url = iq_obj . getTagAttr ( ' confirm ' , ' url ' )
self . dispatch ( ' HTTP_AUTH ' , ( method , url , iq_obj ) ) ;
raise common . xmpp . NodeProcessed
2005-06-07 20:21:36 +02:00
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 ( ) )
2005-08-03 18:21:23 +02:00
id = str ( iq_obj . getID ( ) )
self . dispatch ( ' ERROR_ANSWER ' , ( id , jid_from , errmsg , errcode ) )
2005-06-22 16:54:02 +02:00
def _StanzaArrivedCB ( self , con , obj ) :
2005-06-26 01:25:17 +02:00
self . last_incoming = time . time ( )
self . keep_alive_sent = False
2005-05-10 18:53:28 +02:00
2005-06-14 12:29:36 +02:00
def _event_dispatcher ( self , realm , event , data ) :
if realm == common . xmpp . NS_REGISTER :
if event == common . xmpp . features . REGISTER_DATA_RECEIVED :
# data is (agent, DataFrom)
2005-07-20 22:00:57 +02:00
if self . new_account_info and \
self . new_account_info [ ' hostname ' ] == data [ 0 ] :
2005-07-07 22:45:24 +02:00
#it's a new account
req = data [ 1 ] . asDict ( )
req [ ' username ' ] = self . new_account_info [ ' name ' ]
req [ ' password ' ] = self . new_account_info [ ' password ' ]
2005-07-20 22:00:57 +02:00
if not common . xmpp . features . register ( self . connection , data [ 0 ] ,
req ) :
2005-07-07 22:45:24 +02:00
self . dispatch ( ' ERROR ' , ( _ ( ' Error: ' ) , self . connection . lastErr ) )
return
self . connected = 0
self . password = self . new_account_info [ ' password ' ]
if USE_GPG :
self . gpg = GnuPG . GnuPG ( )
gajim . config . set ( ' usegpg ' , True )
else :
gajim . config . set ( ' usegpg ' , False )
gajim . connections [ self . name ] = self
2005-07-18 23:16:31 +02:00
self . dispatch ( ' ACC_OK ' , ( self . name , self . new_account_info ) )
2005-07-07 22:45:24 +02:00
self . new_account_info = None
return
2005-06-14 12:29:36 +02:00
self . dispatch ( ' REGISTER_AGENT_INFO ' , ( data [ 0 ] , data [ 1 ] . asDict ( ) ) )
2005-08-06 01:43:28 +02:00
elif realm == ' ' :
if event == common . xmpp . transports . DATA_RECEIVED :
self . dispatch ( ' STANZA_ARRIVED ' , str ( data ) )
elif event == common . xmpp . transports . DATA_SENT :
self . dispatch ( ' STANZA_SENT ' , str ( data ) )
2005-06-14 12:29:36 +02:00
2005-04-12 13:46:20 +02:00
def connect ( self ) :
2005-06-29 14:57:46 +02:00
""" Connect and authenticate to the Jabber server
Returns connection , and connection type ( ' tls ' , ' ssl ' , ' tcp ' , ' ' ) """
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-30 13:01:08 +02:00
usessl = gajim . config . get_per ( ' accounts ' , self . name , ' usessl ' )
2005-06-26 01:25:17 +02:00
try_connecting_for_foo_secs = gajim . config . get_per ( ' accounts ' , self . name ,
' try_connecting_for_foo_secs ' )
2005-04-12 13:46:20 +02:00
2005-05-26 15:35:58 +02:00
#create connection if it doesn't already exist
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-06-08 17:48:53 +02:00
p = gajim . config . get_per ( ' accounts ' , self . name , ' proxy ' )
2005-07-04 09:28:42 +02:00
if p and p in gajim . config . get_per ( ' proxies ' ) :
2005-06-08 17:48:53 +02:00
proxy = { ' host ' : gajim . config . get_per ( ' proxies ' , p , ' host ' ) }
proxy [ ' port ' ] = gajim . config . get_per ( ' proxies ' , p , ' port ' )
proxy [ ' user ' ] = gajim . config . get_per ( ' proxies ' , p , ' user ' )
proxy [ ' password ' ] = gajim . config . get_per ( ' proxies ' , p , ' pass ' )
2005-04-14 13:06:58 +02:00
else :
proxy = None
2005-05-28 20:20:27 +02:00
if gajim . 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-06-26 01:25:17 +02:00
common . xmpp . dispatcher . DefaultTimeout = try_connecting_for_foo_secs
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-06-13 23:16:41 +02:00
2005-06-14 12:26:01 +02:00
h = hostname
p = 5222
2005-08-05 01:29:41 +02:00
# autodetect [for SSL in 5223/443 and for TLS if broadcasted]
secur = None
2005-06-14 12:26:01 +02:00
if usessl :
p = 5223
2005-06-18 13:37:29 +02:00
secur = 1 #1 means force SSL no matter what the port will be
2005-06-14 12:26:01 +02:00
if gajim . config . get_per ( ' accounts ' , self . name , ' use_custom_host ' ) :
h = gajim . config . get_per ( ' accounts ' , self . name , ' custom_host ' )
p = gajim . config . get_per ( ' accounts ' , self . name , ' custom_port ' )
2005-06-18 13:37:29 +02:00
con_type = con . connect ( ( h , p ) , proxy = proxy , secure = secur ) #FIXME: blocking
2005-08-02 00:45:29 +02:00
self . peerhost = con . get_peerhost ( )
2005-05-26 15:35:58 +02:00
if not con_type :
2005-05-30 16:08:48 +02:00
gajim . log . debug ( " Couldn ' t connect to %s " % self . name )
2005-05-18 16:05:54 +02:00
self . connected = 0
2005-04-12 13:46:20 +02:00
self . dispatch ( ' STATUS ' , ' offline ' )
2005-06-07 09:40:15 +02:00
self . dispatch ( ' ERROR ' , ( _ ( ' Could not connect to " %s " ' ) % self . name ,
2005-06-13 14:35:53 +02:00
_ ( ' Check your connection or try again later ' ) ) )
2005-06-29 17:09:10 +02:00
return None
2005-06-29 17:06:05 +02:00
2005-07-25 09:52:04 +02:00
gajim . log . debug ( _ ( ' Connected to server with %s ' ) , con_type )
2005-06-29 17:06:05 +02:00
2005-08-09 19:21:35 +02:00
# notify the gui about con_type
self . dispatch ( ' CON_TYPE ' , con_type )
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 )
2005-05-27 18:43:38 +02:00
con . RegisterHandler ( ' iq ' , self . _vCardCB , ' result ' ,
2005-04-26 20:45:54 +02:00
common . xmpp . NS_VCARD )
2005-05-27 18:43:38 +02:00
con . RegisterHandler ( ' iq ' , self . _rosterSetCB , ' set ' ,
2005-04-26 20:45:54 +02:00
common . xmpp . NS_ROSTER )
2005-07-30 12:19:52 +02:00
con . RegisterHandler ( ' iq ' , self . _siSetCB , ' set ' ,
common . xmpp . NS_SI )
2005-08-03 16:04:54 +02:00
con . RegisterHandler ( ' iq ' , self . _siResultCB , ' result ' ,
common . xmpp . NS_SI )
2005-07-30 17:06:35 +02:00
con . RegisterHandler ( ' iq ' , self . _discoGetCB , ' get ' ,
common . xmpp . NS_DISCO )
2005-07-30 12:19:52 +02:00
con . RegisterHandler ( ' iq ' , self . _bytestreamSetCB , ' set ' ,
common . xmpp . NS_BYTESTREAM )
2005-08-03 16:04:54 +02:00
con . RegisterHandler ( ' iq ' , self . _bytestreamResultCB , ' result ' ,
common . xmpp . NS_BYTESTREAM )
2005-08-06 18:31:41 +02:00
con . RegisterHandler ( ' iq ' , self . _bytestreamErrorCB , ' error ' ,
common . xmpp . NS_BYTESTREAM )
2005-05-27 18:43:38 +02:00
con . RegisterHandler ( ' iq ' , self . _BrowseResultCB , ' result ' ,
2005-04-26 20:45:54 +02:00
common . xmpp . NS_BROWSE )
2005-05-27 18:43:38 +02:00
con . RegisterHandler ( ' iq ' , self . _DiscoverItemsCB , ' result ' ,
2005-04-26 20:45:54 +02:00
common . xmpp . NS_DISCO_ITEMS )
2005-05-27 18:43:38 +02:00
con . RegisterHandler ( ' iq ' , self . _DiscoverInfoCB , ' result ' ,
2005-04-26 20:45:54 +02:00
common . xmpp . NS_DISCO_INFO )
2005-05-27 18:43:38 +02:00
con . RegisterHandler ( ' iq ' , self . _DiscoverInfoErrorCB , ' error ' ,
2005-04-26 20:45:54 +02:00
common . xmpp . NS_DISCO_INFO )
2005-05-27 18:43:38 +02:00
con . RegisterHandler ( ' iq ' , self . _VersionCB , ' get ' ,
2005-04-26 20:45:54 +02:00
common . xmpp . NS_VERSION )
2005-05-27 18:43:38 +02:00
con . RegisterHandler ( ' iq ' , self . _VersionResultCB , ' result ' ,
2005-04-26 20:45:54 +02:00
common . xmpp . NS_VERSION )
2005-05-27 18:43:38 +02:00
con . RegisterHandler ( ' iq ' , self . _MucOwnerCB , ' result ' ,
2005-04-26 20:45:54 +02:00
common . xmpp . NS_MUC_OWNER )
2005-05-27 18:43:38 +02:00
con . RegisterHandler ( ' iq ' , self . _getRosterCB , ' result ' ,
2005-05-08 19:00:41 +02:00
common . xmpp . NS_ROSTER )
2005-06-07 20:21:36 +02:00
con . RegisterHandler ( ' iq ' , self . _PrivateCB , ' result ' ,
common . xmpp . NS_PRIVATE )
2005-08-05 15:29:39 +02:00
con . RegisterHandler ( ' iq ' , self . _HttpAuthCB , ' get ' ,
common . xmpp . NS_HTTP_AUTH )
2005-05-10 18:53:28 +02:00
con . RegisterHandler ( ' iq ' , self . _ErrorCB , ' error ' )
2005-06-22 16:54:02 +02:00
con . RegisterHandler ( ' iq ' , self . _StanzaArrivedCB )
con . RegisterHandler ( ' presence ' , self . _StanzaArrivedCB )
con . RegisterHandler ( ' message ' , self . _StanzaArrivedCB )
2005-06-14 12:29:36 +02:00
con . RegisterEventHandler ( self . _event_dispatcher )
2005-04-26 20:45:54 +02:00
2005-05-11 18:37:01 +02:00
try :
2005-05-31 15:53:22 +02:00
#FIXME: blocking
2005-06-01 14:33:29 +02:00
auth = con . auth ( name , self . password , resource , 1 )
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 ' )
2005-06-07 09:40:15 +02:00
self . dispatch ( ' ERROR ' , ( _ ( ' Could not connect to " %s " ' ) % self . name ,
2005-06-13 14:35:53 +02:00
_ ( ' Check your connection or try again later ' ) ) )
2005-06-29 17:09:10 +02:00
return None
2005-05-11 18:37:01 +02:00
if auth :
2005-05-08 19:00:41 +02:00
con . initRoster ( )
2005-06-30 18:57:42 +02:00
self . last_incoming = time . time ( )
2005-04-12 13:46:20 +02:00
self . connected = 2
2005-06-29 17:09:10 +02:00
return con # return connection
2005-04-12 13:46:20 +02:00
else :
2005-05-30 16:08:48 +02:00
gajim . log . debug ( " Couldn ' t authenticate to %s " % self . name )
2005-05-18 16:05:54 +02:00
self . connected = 0
2005-04-12 13:46:20 +02:00
self . dispatch ( ' STATUS ' , ' offline ' )
2005-08-09 17:28:32 +02:00
self . dispatch ( ' ERROR ' , ( _ ( ' Authentication failed with " %s " ' ) % self . name ,
2005-06-10 01:08:28 +02:00
_ ( ' Please check your login and password for correctness. ' ) ) )
2005-06-29 17:09:10 +02:00
return None
2005-05-31 15:53:22 +02:00
# END connect
2005-04-12 13:46:20 +02:00
def quit ( self , kill_core ) :
if kill_core :
if self . connected > 1 :
self . connected = 0
2005-07-03 14:36:13 +02:00
self . connection . disconnect ( )
2005-04-12 13:46:20 +02:00
return
def ask_roster ( self ) :
roster = { }
if self . connection :
roster = self . connection . getRoster ( ) . getRaw ( )
return roster
2005-07-22 18:36:20 +02:00
def build_privacy_rule ( self , name , action ) :
''' Build a Privacy rule stanza for invisibility '''
iq = common . xmpp . Iq ( ' set ' , common . xmpp . NS_PRIVACY , xmlns = ' ' )
l = iq . getTag ( ' query ' ) . setTag ( ' list ' , { ' name ' : name } )
i = l . setTag ( ' item ' , { ' action ' : action , ' order ' : ' 1 ' } )
i . setTag ( ' presence-out ' )
return iq
def activate_privacy_rule ( self , name ) :
''' activate a privacy rule '''
iq = common . xmpp . Iq ( ' set ' , common . xmpp . NS_PRIVACY , xmlns = ' ' )
iq . getTag ( ' query ' ) . setTag ( ' active ' , { ' name ' : name } )
self . connection . send ( iq )
def send_invisible_presence ( self , msg , signed , initial = False ) :
# try to set the privacy rule
iq = self . build_privacy_rule ( ' invisible ' , ' deny ' )
self . connection . SendAndCallForResponse ( iq , self . _continue_invisible ,
{ ' msg ' : msg , ' signed ' : signed , ' initial ' : initial } )
2005-04-12 13:46:20 +02:00
2005-07-22 18:36:20 +02:00
def _continue_invisible ( self , con , iq_obj , msg , signed , initial ) :
ptype = ' '
show = ' '
# FIXME: JEP 126 need some modifications (see http://lists.jabber.ru/pipermail/ejabberd/2005-July/001252.html). So I disable it for the moment
if 1 or iq_obj . getType ( ) == ' error ' : #server doesn't support privacy lists
# We use the old way which is not xmpp complient
ptype = ' invisible '
show = ' invisible '
else :
# active the privacy rule
self . privacy_rules_supported = True
self . activate_privacy_rule ( ' invisible ' )
prio = str ( gajim . config . get_per ( ' accounts ' , self . name , ' priority ' ) )
p = common . xmpp . Presence ( typ = ptype , priority = prio , show = show )
2005-08-07 23:42:32 +02:00
p = self . add_sha ( p )
2005-07-22 18:36:20 +02:00
if msg :
p . setStatus ( msg )
if signed :
p . setTag ( common . xmpp . NS_SIGNED + ' x ' ) . setData ( signed )
self . connection . send ( p )
2005-08-09 19:21:35 +02:00
self . dispatch ( ' STATUS ' , ' invisible ' )
2005-07-22 18:36:20 +02:00
if initial :
#ask our VCard
2005-08-08 15:34:48 +02:00
self . request_vcard ( None )
2005-07-22 18:36:20 +02:00
#Get bookmarks from private namespace
self . get_bookmarks ( )
2005-07-30 12:19:52 +02:00
2005-06-28 21:03:00 +02:00
def change_status ( self , show , msg , sync = False ) :
if sync :
self . change_status2 ( show , msg )
else :
t = threading . Thread ( target = self . change_status2 , args = ( show , msg ) )
t . start ( )
def change_status2 ( self , show , msg ) :
2005-05-13 20:54:44 +02:00
if not show in STATUS_LIST :
2005-04-12 13:46:20 +02:00
return - 1
2005-06-04 16:27:09 +02:00
sshow = show # show to be send
if show == ' online ' :
sshow = None
2005-04-12 13:46:20 +02:00
signed = ' '
2005-08-01 20:19:36 +02:00
if not msg :
lowered_uf_status_msg = helpers . get_uf_show ( show ) . lower ( )
msg = _ ( " I ' m %s " ) % lowered_uf_status_msg
2005-04-12 13:46:20 +02:00
keyID = gajim . config . get_per ( ' accounts ' , self . name , ' keyid ' )
if keyID and USE_GPG :
2005-07-23 13:44:54 +02:00
if self . connected < 2 and self . gpg . passphrase is None :
2005-06-29 10:28:12 +02:00
# We didn't set a passphrase
2005-08-09 19:21:35 +02:00
self . dispatch ( ' ERROR ' , ( _ ( ' OpenPGP Key was not given ' ) ,
_ ( ' You will be connected to %s without OpenPGP. ' ) % self . name ) )
2005-08-01 20:19:36 +02:00
else :
2005-06-18 18:57:57 +02:00
signed = self . gpg . sign ( msg , keyID )
if signed == ' BAD_PASSPHRASE ' :
signed = ' '
if self . connected < 2 :
2005-08-09 19:21:35 +02:00
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-06-29 17:09:10 +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-05-13 20:54:44 +02:00
if show == ' invisible ' :
2005-07-22 18:36:20 +02:00
self . send_invisible_presence ( msg , signed , True )
return
2005-04-17 13:49:39 +02:00
prio = str ( gajim . config . get_per ( ' accounts ' , self . name , ' priority ' ) )
2005-08-07 23:42:32 +02:00
p = common . xmpp . Presence ( typ = None , priority = prio , show = sshow )
p = self . add_sha ( p )
2005-05-20 17:32:05 +02:00
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
2005-07-15 22:04:02 +02:00
if self . connection :
self . connection . send ( p )
2005-08-09 19:21:35 +02:00
self . dispatch ( ' STATUS ' , show )
2005-04-12 13:46:20 +02:00
#ask our VCard
2005-08-08 15:34:48 +02:00
self . request_vcard ( None )
2005-06-07 20:21:36 +02:00
#Get bookmarks from private namespace
self . get_bookmarks ( )
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-27 14:07:20 +02:00
self . on_purpose = True
2005-05-20 17:32:05 +02:00
p = common . xmpp . Presence ( typ = ' unavailable ' )
2005-08-07 23:42:32 +02:00
p = self . add_sha ( p )
2005-05-20 17:32:05 +02:00
if msg :
p . setStatus ( msg )
2005-08-10 17:59:55 +02:00
self . remove_all_transfers ( )
2005-07-15 22:04:02 +02:00
if self . connection :
self . connection . send ( p )
2005-05-31 18:47:05 +02:00
try :
self . connection . disconnect ( )
except :
pass
2005-08-09 19:21:35 +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 :
2005-07-22 18:36:20 +02:00
was_invisible = self . connected == STATUS_LIST . index ( ' invisible ' )
2005-05-13 20:54:44 +02:00
self . connected = STATUS_LIST . index ( show )
if show == ' invisible ' :
2005-07-22 18:36:20 +02:00
self . send_invisible_presence ( msg , signed )
return
if was_invisible and self . privacy_rules_supported :
iq = self . build_privacy_rule ( ' visible ' , ' allow ' )
self . connection . send ( iq )
self . activate_privacy_rule ( ' visible ' )
2005-04-17 13:49:39 +02:00
prio = str ( gajim . config . get_per ( ' accounts ' , self . name , ' priority ' ) )
2005-08-07 23:42:32 +02:00
p = common . xmpp . Presence ( typ = None , priority = prio , show = sshow )
p = self . add_sha ( p )
2005-05-20 17:32:05 +02:00
if msg :
p . setStatus ( msg )
if signed :
p . setTag ( common . xmpp . NS_SIGNED + ' x ' ) . setData ( signed )
2005-07-16 19:12:11 +02:00
if self . connection :
2005-07-15 22:04:02 +02:00
self . connection . send ( p )
2005-08-09 19:21:35 +02:00
self . dispatch ( ' STATUS ' , show )
2005-04-12 13:46:20 +02:00
2005-08-06 14:33:20 +02:00
def send_motd ( self , jid , subject = ' ' , msg = ' ' ) :
if not self . connection :
return
msg_iq = common . xmpp . Message ( to = jid , body = msg , subject = subject )
self . to_be_sent . append ( msg_iq )
2005-07-19 16:38:58 +02:00
def send_message ( self , jid , msg , keyID , type = ' chat ' , subject = ' ' , chatstate = None ) :
2005-04-14 09:42:26 +02:00
if not self . connection :
2005-04-12 13:46:20 +02:00
return
2005-07-19 16:38:58 +02:00
if not msg and chatstate is None :
2005-06-21 22:04:23 +02:00
return
2005-04-12 13:46:20 +02:00
msgtxt = msg
msgenc = ' '
if keyID and USE_GPG :
#encrypt
2005-05-27 16:16:34 +02:00
msgenc = self . gpg . encrypt ( msg , [ keyID ] )
2005-07-04 18:27:26 +02:00
if msgenc :
2005-07-06 14:13:54 +02:00
msgtxt = ' [This message is encrypted] '
lang = os . getenv ( ' LANG ' )
if lang is not None or lang != ' en ' : # we're not english
msgtxt = _ ( ' [This message is encrypted] ' ) + \
' ([This message is encrypted]) ' # one in locale and one en
2005-07-02 17:49:25 +02:00
if type == ' chat ' :
msg_iq = common . xmpp . Message ( to = jid , body = msgtxt , typ = type )
else :
if subject :
msg_iq = common . xmpp . Message ( to = jid , body = msgtxt ,
typ = ' normal ' , subject = subject )
else :
msg_iq = common . xmpp . Message ( to = jid , body = msgtxt ,
typ = ' normal ' )
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-07-19 16:38:58 +02:00
# chatstates - if peer supports jep85, send chatstates
# please note that the only valid tag inside a message containing a <body> tag is the active event
2005-07-21 17:23:18 +02:00
if chatstate is not None :
2005-07-22 02:34:08 +02:00
msg_iq . setTag ( chatstate , { } ,
namespace = ' http://jabber.org/protocol/chatstates ' )
2005-07-19 16:38:58 +02:00
2005-07-04 23:30:00 +02:00
self . to_be_sent . append ( msg_iq )
2005-07-23 13:54:01 +02:00
if msg :
gajim . logger . write ( ' outgoing ' , msg , jid )
2005-04-12 13:46:20 +02:00
self . dispatch ( ' MSGSENT ' , ( jid , msg , keyID ) )
2005-07-04 23:30:00 +02:00
def send_stanza ( self , stanza ) :
''' send a stanza untouched '''
if not self . connection :
return
self . to_be_sent . append ( stanza )
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-08-07 23:42:32 +02:00
p = common . xmpp . Presence ( jid , ' subscribe ' )
p = self . add_sha ( p )
2005-04-12 13:46:20 +02:00
if not msg :
msg = _ ( ' I would like to add you to my roster. ' )
2005-08-07 23:42:32 +02:00
p . setStatus ( msg )
self . to_be_sent . append ( p )
2005-04-12 13:46:20 +02:00
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-08-07 23:42:32 +02:00
p = common . xmpp . Presence ( jid , ' subscribed ' )
p = self . add_sha ( p )
self . to_be_sent . append ( p )
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-08-07 23:42:32 +02:00
p = common . xmpp . Presence ( jid , ' unsubscribed ' )
p = self . add_sha ( p )
self . to_be_sent . append ( p )
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
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-07-19 16:38:58 +02:00
def update_contact ( self , jid , name , groups ) :
2005-04-12 13:46:20 +02:00
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-07-04 23:30:00 +02:00
self . to_be_sent . append ( common . xmpp . Iq ( to = jid , typ = ' get ' ,
2005-05-07 12:57:40 +02:00
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 request_register_agent_info ( self , agent ) :
2005-04-12 13:46:20 +02:00
if not self . connection :
return None
2005-07-07 22:45:24 +02:00
common . xmpp . features . getRegInfo ( self . connection , agent , sync = False )
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-05-31 15:53:22 +02:00
# FIXME: Blocking
common . xmpp . features . register ( self . connection , agent , info )
2005-04-12 13:46:20 +02:00
2005-07-07 22:45:24 +02:00
def new_account ( self , name , config , sync = False ) :
if sync :
self . new_account2 ( name , config )
else :
t = threading . Thread ( target = self . new_account2 , args = ( name , config ) )
t . start ( )
def new_account2 ( 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-06-08 17:48:53 +02:00
p = config [ ' proxy ' ]
2005-07-04 09:28:42 +02:00
if p and p in gajim . config . get_per ( ' proxies ' ) :
2005-06-08 17:48:53 +02:00
proxy = { ' host ' : gajim . config . get_per ( ' proxies ' , p , ' host ' ) }
proxy [ ' port ' ] = gajim . config . get_per ( ' proxies ' , p , ' port ' )
proxy [ ' user ' ] = gajim . config . get_per ( ' proxies ' , p , ' user ' )
proxy [ ' password ' ] = gajim . config . get_per ( ' proxies ' , p , ' pass ' )
2005-04-12 13:46:20 +02:00
else :
proxy = None
2005-05-31 15:53:22 +02:00
if gajim . verbose :
c = common . xmpp . Client ( server = config [ ' hostname ' ] )
else :
c = common . xmpp . Client ( server = config [ ' hostname ' ] , debug = [ ] )
common . xmpp . dispatcher . DefaultTimeout = 45
c . UnregisterDisconnectHandler ( c . DisconnectHandler )
c . RegisterDisconnectHandler ( self . _disconnectedCB )
2005-06-21 16:24:15 +02:00
h = config [ ' hostname ' ]
2005-06-14 12:26:01 +02:00
p = 5222
2005-06-18 13:37:29 +02:00
usessl = None
if usessl : #FIXME: we cannot create an account if we want ssl connection to create it
2005-06-14 12:26:01 +02:00
p = 5223
if config [ ' use_custom_host ' ] :
h = config [ ' custom_host ' ]
p = config [ ' custom_port ' ]
2005-06-18 13:37:29 +02:00
secur = None # autodetect [for SSL in 5223/443 and for TLS if broadcasted]
if usessl :
secur = 1 #1 means force SSL no matter what the port is
con_type = c . connect ( ( h , p ) , proxy = proxy , secure = secur ) #FIXME: blocking
2005-05-26 15:35:58 +02:00
if not con_type :
2005-05-30 16:08:48 +02:00
gajim . log . debug ( " Couldn ' t connect to %s " % name )
2005-06-07 09:40:15 +02:00
self . dispatch ( ' ERROR ' , ( _ ( ' Could not connect to " %s " ' ) % name ,
2005-06-14 12:26:01 +02:00
_ ( ' Check your connection or try again later. ' ) ) )
2005-05-26 15:35:58 +02:00
return False
2005-07-24 22:00:38 +02:00
gajim . log . debug ( _ ( ' Connected to server with %s ' ) , con_type )
2005-06-29 14:57:46 +02:00
2005-07-07 22:45:24 +02:00
c . RegisterEventHandler ( self . _event_dispatcher )
self . new_account_info = config
self . connection = c
2005-05-31 15:53:22 +02:00
self . name = name
2005-07-07 22:45:24 +02:00
common . xmpp . features . getRegInfo ( c , config [ ' hostname ' ] )
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-07-03 01:07:26 +02:00
to_whom_jid = jid
2005-07-03 01:03:11 +02:00
if resource :
2005-07-03 01:07:26 +02:00
to_whom_jid + = ' / ' + resource
2005-07-03 01:03:11 +02:00
iq = common . xmpp . Iq ( to = to_whom_jid , typ = ' get ' , queryNS = \
2005-04-26 20:45:54 +02:00
common . xmpp . NS_VERSION )
2005-07-04 23:30:00 +02:00
self . to_be_sent . append ( iq )
2005-04-12 13:46:20 +02:00
2005-05-24 21:18:32 +02:00
def request_vcard ( self , jid = None ) :
''' request the VCARD and return the iq '''
2005-04-12 13:46:20 +02:00
if not self . connection :
return
2005-05-24 21:18:32 +02:00
iq = common . xmpp . Iq ( typ = ' get ' )
if jid :
iq . setTo ( jid )
2005-04-26 20:45:54 +02:00
iq . setTag ( common . xmpp . NS_VCARD + ' vCard ' )
2005-07-04 23:30:00 +02:00
self . to_be_sent . append ( iq )
2005-04-12 13:46:20 +02:00
#('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-06-07 10:50:47 +02:00
for i in vcard :
2005-06-06 17:29:27 +02:00
if i == ' jid ' :
continue
if type ( vcard [ i ] ) == type ( { } ) :
2005-06-07 10:50:47 +02:00
iq3 = iq2 . addChild ( i )
for j in vcard [ i ] :
iq3 . addChild ( j ) . setData ( vcard [ i ] [ j ] )
elif type ( vcard [ i ] ) == type ( [ ] ) :
for j in vcard [ i ] :
iq3 = iq2 . addChild ( i )
for k in j :
iq3 . addChild ( k ) . setData ( j [ k ] )
2005-06-06 17:29:27 +02:00
else :
iq2 . addChild ( i ) . setData ( vcard [ i ] )
2005-07-04 23:30:00 +02:00
self . to_be_sent . append ( iq )
2005-04-12 13:46:20 +02:00
2005-06-07 20:21:36 +02:00
def get_settings ( self ) :
''' Get Gajim settings as described in JEP 0049 '''
if not self . connection :
return
iq = common . xmpp . Iq ( typ = ' get ' )
iq2 = iq . addChild ( name = ' query ' , namespace = ' jabber:iq:private ' )
iq3 = iq2 . addChild ( name = ' gajim ' , namespace = ' gajim:prefs ' )
2005-07-04 23:30:00 +02:00
self . to_be_sent . append ( iq )
2005-06-07 20:21:36 +02:00
def get_bookmarks ( self ) :
''' Get Bookmarks from storage as described in JEP 0048 '''
2005-06-11 16:14:50 +02:00
self . bookmarks = [ ] #avoid multiple bookmarks when re-connecting
2005-06-07 20:21:36 +02:00
if not self . connection :
return
iq = common . xmpp . Iq ( typ = ' get ' )
iq2 = iq . addChild ( name = " query " , namespace = " jabber:iq:private " )
iq3 = iq2 . addChild ( name = " storage " , namespace = " storage:bookmarks " )
2005-07-04 23:30:00 +02:00
self . to_be_sent . append ( iq )
2005-06-07 20:21:36 +02:00
def store_bookmarks ( self ) :
''' Send bookmarks to the storage namespace '''
2005-06-10 17:45:09 +02:00
if not self . connection :
return
2005-06-07 20:21:36 +02:00
iq = common . xmpp . Iq ( typ = ' set ' )
2005-07-04 23:30:00 +02:00
iq2 = iq . addChild ( name = ' query ' , namespace = ' jabber:iq:private ' )
iq3 = iq2 . addChild ( name = ' storage ' , namespace = ' storage:bookmarks ' )
2005-06-07 20:21:36 +02:00
for bm in self . bookmarks :
2005-07-04 23:30:00 +02:00
iq4 = iq3 . addChild ( name = " conference " )
iq4 . setAttr ( ' jid ' , bm [ ' jid ' ] )
iq4 . setAttr ( ' autojoin ' , bm [ ' autojoin ' ] )
iq4 . setAttr ( ' name ' , bm [ ' name ' ] )
iq5 = iq4 . setTagData ( ' nick ' , bm [ ' nick ' ] )
iq5 = iq4 . setTagData ( ' password ' , bm [ ' password ' ] )
self . to_be_sent . append ( iq )
2005-06-07 20:21:36 +02:00
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-26 20:45:54 +02:00
p = common . xmpp . Presence ( to = agent , typ = ptype )
2005-08-07 23:42:32 +02:00
p = self . add_sha ( p )
2005-07-04 23:30:00 +02:00
self . to_be_sent . append ( p )
2005-04-12 13:46:20 +02:00
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-06-04 16:27:09 +02:00
show = STATUS_LIST [ self . connected ]
ptype = None
if show == ' online ' :
show = None
2005-05-13 20:54:44 +02:00
p = common . xmpp . Presence ( to = ' %s @ %s / %s ' % ( room , server , nick ) ,
2005-06-04 16:27:09 +02:00
show = show , status = self . status )
2005-08-07 23:42:32 +02:00
p = self . add_sha ( p )
2005-05-18 11:18:29 +02:00
t = p . setTag ( common . xmpp . NS_MUC + ' x ' )
if password :
t . setTagData ( ' password ' , password )
2005-07-04 23:30:00 +02:00
self . to_be_sent . append ( p )
2005-04-12 13:46:20 +02:00
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-07-04 23:30:00 +02:00
self . to_be_sent . append ( msg_iq )
2005-04-12 13:46:20 +02:00
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-07-04 23:30:00 +02:00
self . to_be_sent . append ( msg_iq )
2005-04-12 13:46:20 +02:00
2005-04-20 12:21:33 +02:00
def request_gc_config ( self , room_jid ) :
2005-05-27 18:43:38 +02:00
iq = common . xmpp . Iq ( typ = ' get ' , queryNS = common . xmpp . NS_MUC_OWNER ,
2005-04-26 20:45:54 +02:00
to = room_jid )
2005-07-04 23:30:00 +02:00
self . to_be_sent . append ( iq )
2005-06-29 10:28:12 +02:00
2005-06-19 01:44:33 +02:00
def change_gc_nick ( self , room_jid , nick ) :
2005-06-19 00:09:31 +02:00
if not self . connection :
return
2005-08-07 23:42:32 +02:00
p = common . xmpp . Presence ( to = ' %s / %s ' % ( room_jid , nick ) )
p = self . add_sha ( p )
self . to_be_sent . append ( p )
2005-04-20 12:21:33 +02:00
2005-04-12 13:46:20 +02:00
def send_gc_status ( self , nick , jid , show , status ) :
if not self . connection :
return
2005-06-04 00:49:07 +02:00
ptype = None
2005-04-12 13:46:20 +02:00
if show == ' offline ' :
2005-04-12 14:23:08 +02:00
ptype = ' unavailable '
2005-04-12 13:46:20 +02:00
show = None
2005-06-04 16:27:09 +02:00
if show == ' online ' :
show = None
2005-08-07 23:42:32 +02:00
p = common . xmpp . Presence ( to = ' %s / %s ' % ( jid , nick ) , typ = ptype ,
show = show , status = status )
p = self . add_sha ( p )
self . to_be_sent . append ( p )
2005-04-12 13:46:20 +02:00
2005-07-02 20:33:51 +02:00
def gc_set_role ( self , room_jid , nick , role , reason = ' ' ) :
2005-07-19 16:38:58 +02:00
''' role is for all the life of the room so it ' s based on nick '''
2005-04-12 13:46:20 +02:00
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-07-02 20:33:51 +02:00
if reason :
item . addChild ( name = ' reason ' , payload = reason )
2005-07-04 23:30:00 +02:00
self . to_be_sent . append ( iq )
2005-04-12 13:46:20 +02:00
2005-07-02 20:33:51 +02:00
def gc_set_affiliation ( self , room_jid , jid , affiliation , reason = ' ' ) :
2005-07-19 16:38:58 +02:00
''' affiliation is for all the life of the room so it ' s based on jid '''
2005-04-12 13:46:20 +02:00
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-07-02 20:33:51 +02:00
if reason :
item . addChild ( name = ' reason ' , payload = reason )
2005-07-04 23:30:00 +02:00
self . to_be_sent . append ( iq )
2005-04-12 13:46:20 +02:00
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 ' )
2005-05-31 15:53:22 +02:00
# FIXME: should really use XData class
x = query . setTag ( common . xmpp . NS_DATA + ' x ' , attrs = { ' type ' : ' submit ' } )
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
2005-07-04 23:30:00 +02:00
self . to_be_sent . append ( iq )
2005-04-20 12:21:33 +02:00
2005-04-12 13:46:20 +02:00
def gpg_passphrase ( self , passphrase ) :
if USE_GPG :
self . gpg . passphrase = passphrase
2005-05-29 23:34:01 +02:00
def ask_gpg_keys ( self ) :
if USE_GPG :
keys = self . gpg . get_keys ( )
return keys
return None
2005-04-12 13:46:20 +02:00
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-07-04 23:30:00 +02:00
self . to_be_sent . append ( iq )
2005-04-12 13:46:20 +02:00
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-07-04 23:30:00 +02:00
self . to_be_sent . append ( iq )
2005-04-20 00:29:38 +02:00
2005-06-26 01:25:17 +02:00
def send_keepalive ( self ) :
# we received nothing for the last foo seconds (60 secs by default)
hostname = gajim . config . get_per ( ' accounts ' , self . name ,
' hostname ' )
iq = common . xmpp . Iq ( ' get ' , common . xmpp . NS_LAST , to = hostname )
2005-07-04 23:30:00 +02:00
self . to_be_sent . append ( iq )
2005-06-26 01:25:17 +02:00
self . keep_alive_sent = True
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-06-29 10:28:12 +02:00
now = time . time ( )
l = [ ]
for t in self . last_sent :
if ( now - t ) < 1 :
l . append ( t )
self . last_sent = l
t_limit = time . time ( ) + timeout
while time . time ( ) < t_limit and len ( self . to_be_sent ) and \
len ( self . last_sent ) < gajim . config . get_per ( ' accounts ' ,
self . name , ' max_stanza_per_sec ' ) :
2005-07-30 12:19:52 +02:00
tosend = self . to_be_sent . pop ( 0 )
self . connection . send ( tosend )
2005-06-29 10:28:12 +02:00
self . last_sent . append ( time . time ( ) )
2005-05-18 15:42:12 +02:00
try :
2005-06-26 01:25:17 +02:00
if gajim . config . get_per ( ' accounts ' , self . name ,
' keep_alives_enabled ' ) : # do we want keepalives?
keep_alive_every_foo_secs = gajim . config . get_per ( ' accounts ' ,
self . name , ' keep_alive_every_foo_secs ' )
2005-06-29 10:28:12 +02:00
#should we send keepalive?
if time . time ( ) > ( self . last_incoming + \
keep_alive_every_foo_secs ) and not self . keep_alive_sent :
2005-06-26 01:25:17 +02:00
self . send_keepalive ( )
2005-06-29 10:28:12 +02:00
2005-06-26 11:19:37 +02:00
# did the server reply to the keepalive? if no disconnect
2005-07-24 21:56:47 +02:00
keep_alive_disconnect_after_foo_secs = gajim . config . get_per (
' accounts ' , self . name ,
' keep_alive_disconnect_after_foo_secs ' ) # 2 mins by default
2005-06-29 10:28:12 +02:00
if time . time ( ) > ( self . last_incoming + \
2005-07-24 21:56:47 +02:00
keep_alive_disconnect_after_foo_secs ) :
2005-06-26 11:19:37 +02:00
self . connection . disconnect ( ) # disconnect if no answer
2005-08-04 12:56:47 +02:00
pritext = _ ( ' Gajim disconnected you from %s ' ) % self . name
2005-08-08 23:11:59 +02:00
sectext = _ ( ' %s seconds have passed and server did not reply to our keep-alive. If you believe such disconnection should not have happend, you can disable sending keep-alive packets by modifying this account. ' ) % str ( keep_alive_disconnect_after_foo_secs )
2005-08-04 22:33:00 +02:00
self . dispatch ( ' ERROR ' , ( pritext , sectext ) )
2005-06-26 11:19:37 +02:00
return
2005-07-03 14:42:53 +02:00
if self . connection :
self . connection . Process ( timeout )
2005-05-18 20:57:54 +02:00
except :
2005-07-24 22:00:38 +02:00
gajim . log . debug ( _ ( ' error appeared while processing xmpp: ' ) )
2005-05-20 19:30:29 +02:00
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-07-24 22:00:38 +02:00
gajim . log . debug ( _ ( ' error appeared while processing xmpp: ' ) )
2005-05-20 19:30:29 +02:00
traceback . print_exc ( )
2005-05-18 15:42:12 +02:00
self . connection = None
2005-05-31 15:53:22 +02:00
# END Connection