2008-08-15 19:31:51 +02:00
# -*- coding:utf-8 -*-
2008-08-15 05:20:23 +02:00
## src/common/connection_handlers.py
2006-03-19 15:54:00 +01:00
##
2008-08-15 05:20:23 +02:00
## Copyright (C) 2006 Dimitur Kirov <dkirov AT gmail.com>
2008-08-15 19:31:51 +02:00
## Junglecow J <junglecow AT gmail.com>
2008-08-15 05:20:23 +02:00
## Copyright (C) 2006-2007 Tomasz Melcer <liori AT exroot.org>
## Travis Shirk <travis AT pobox.com>
## Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2006-2008 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2007 Julien Pivotto <roidelapluie AT gmail.com>
## Copyright (C) 2007-2008 Brendan Taylor <whateley AT gmail.com>
## Jean-Marie Traissard <jim AT lapin.org>
## Stephan Erb <steve-e AT h3c.de>
## Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org>
2006-03-19 15:54:00 +01:00
##
2007-12-12 09:44:46 +01:00
## This file is part of Gajim.
##
## Gajim is free software; you can redistribute it and/or modify
2006-03-19 15:54:00 +01:00
## it under the terms of the GNU General Public License as published
2007-12-12 09:44:46 +01:00
## by the Free Software Foundation; version 3 only.
2006-03-19 15:54:00 +01:00
##
2007-12-12 09:44:46 +01:00
## Gajim is distributed in the hope that it will be useful,
2006-03-19 15:54:00 +01:00
## but WITHOUT ANY WARRANTY; without even the implied warranty of
2008-08-15 05:20:23 +02:00
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2006-03-19 15:54:00 +01:00
## GNU General Public License for more details.
##
2007-12-12 09:44:46 +01:00
## You should have received a copy of the GNU General Public License
2008-08-15 05:20:23 +02:00
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
2007-12-12 09:44:46 +01:00
##
2006-03-19 15:54:00 +01:00
import os
2006-03-21 16:57:44 +01:00
import base64
2006-03-22 17:36:56 +01:00
import sha
2006-03-19 15:54:00 +01:00
import socket
2006-04-11 20:36:09 +02:00
import sys
2006-03-19 15:54:00 +01:00
2007-08-09 17:39:18 +02:00
from time import ( altzone , daylight , gmtime , localtime , mktime , strftime ,
2007-12-12 09:44:46 +01:00
time as time_time , timezone , tzname )
2006-03-19 15:54:00 +01:00
from calendar import timegm
import socks5
import common . xmpp
from common import helpers
from common import gajim
2006-07-21 15:52:36 +02:00
from common import atom
2007-03-26 00:16:48 +02:00
from common import pep
2007-08-09 17:39:18 +02:00
from common import exceptions
2006-07-17 15:40:25 +02:00
from common . commands import ConnectionCommands
2006-08-20 12:18:20 +02:00
from common . pubsub import ConnectionPubSub
2007-08-09 17:39:18 +02:00
from common . caps import ConnectionCaps
2006-03-19 15:54:00 +01:00
2007-08-10 22:18:32 +02:00
from common import dbus_support
if dbus_support . supported :
import dbus
from music_track_listener import MusicTrackListener
2008-04-11 05:52:45 +02:00
from session import ChatControlSession
2007-12-12 09:44:46 +01:00
2008-06-03 01:26:40 +02:00
gajim . default_session_type = ChatControlSession
2006-03-19 15:54:00 +01:00
STATUS_LIST = [ ' offline ' , ' connecting ' , ' online ' , ' chat ' , ' away ' , ' xa ' , ' dnd ' ,
2006-12-20 21:40:08 +01:00
' invisible ' , ' error ' ]
2006-03-19 15:54:00 +01:00
# kind of events we can wait for an answer
VCARD_PUBLISHED = ' vcard_published '
VCARD_ARRIVED = ' vcard_arrived '
2006-05-01 20:29:12 +02:00
AGENT_REMOVED = ' agent_removed '
2006-09-13 18:47:58 +02:00
METACONTACTS_ARRIVED = ' metacontacts_arrived '
2006-11-18 21:52:28 +01:00
PRIVACY_ARRIVED = ' privacy_arrived '
2008-02-15 23:55:21 +01:00
PEP_CONFIG = ' pep_config '
2006-03-19 15:54:00 +01:00
HAS_IDLE = True
try :
2006-11-18 21:52:28 +01:00
import idle
2006-03-19 15:54:00 +01:00
except :
2006-11-18 21:52:28 +01:00
gajim . log . debug ( _ ( ' Unable to load idle module ' ) )
HAS_IDLE = False
2006-03-19 15:54:00 +01:00
class ConnectionBytestream :
def __init__ ( self ) :
self . files_props = { }
2007-12-12 09:44:46 +01:00
def is_transfer_stopped ( self , file_props ) :
2006-03-23 01:11:50 +01:00
if file_props . has_key ( ' error ' ) and file_props [ ' error ' ] != 0 :
return True
if file_props . has_key ( ' completed ' ) and file_props [ ' completed ' ] :
return True
if file_props . has_key ( ' connected ' ) and file_props [ ' connected ' ] == False :
return True
if not file_props . has_key ( ' stopped ' ) or not file_props [ ' stopped ' ] :
return False
return True
2008-05-17 04:23:46 +02:00
2006-03-19 15:54:00 +01:00
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
iq = common . xmpp . Iq ( to = streamhost [ ' initiator ' ] , typ = ' result ' ,
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 . connection . send ( iq )
2008-05-17 04:23:46 +02:00
2006-03-22 00:43:26 +01:00
def remove_transfers_for_contact ( self , contact ) :
''' stop all active transfer for contact '''
for file_props in self . files_props . values ( ) :
2007-12-12 09:44:46 +01:00
if self . is_transfer_stopped ( file_props ) :
2006-03-23 01:11:50 +01:00
continue
2006-03-22 00:43:26 +01:00
receiver_jid = unicode ( file_props [ ' receiver ' ] ) . split ( ' / ' ) [ 0 ]
if contact . jid == receiver_jid :
file_props [ ' error ' ] = - 5
self . remove_transfer ( file_props )
2006-11-18 21:52:28 +01:00
self . dispatch ( ' FILE_REQUEST_ERROR ' , ( contact . jid , file_props , ' ' ) )
2006-03-22 00:43:26 +01:00
sender_jid = unicode ( file_props [ ' sender ' ] ) . split ( ' / ' ) [ 0 ]
if contact . jid == sender_jid :
file_props [ ' error ' ] = - 3
self . remove_transfer ( file_props )
2008-05-17 04:23:46 +02:00
2006-03-19 15:54:00 +01: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 = { }
2008-05-17 04:23:46 +02:00
2006-03-19 15:54:00 +01:00
def remove_transfer ( self , file_props , remove_from_list = True ) :
if file_props is None :
return
self . disconnect_transfer ( file_props )
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 ' ] )
2008-05-17 04:23:46 +02:00
2006-03-19 15:54:00 +01:00
def disconnect_transfer ( self , file_props ) :
if file_props is None :
return
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 . has_key ( ' idx ' ) and host [ ' idx ' ] > 0 :
gajim . socks5queue . remove_receiver ( host [ ' idx ' ] )
gajim . socks5queue . remove_sender ( host [ ' idx ' ] )
2008-05-17 04:23:46 +02:00
2006-03-19 15:54:00 +01:00
def send_socks5_info ( self , file_props , fast = True , receiver = None ,
sender = None ) :
''' send iq for the present streamhosts and proxies '''
if type ( self . peerhost ) != tuple :
return
port = gajim . config . get ( ' file_transfers_port ' )
2007-01-28 20:11:39 +01:00
ft_add_hosts_to_send = gajim . config . get ( ' ft_add_hosts_to_send ' )
2006-03-19 15:54:00 +01:00
cfg_proxies = gajim . config . get_per ( ' accounts ' , self . name ,
' file_transfer_proxies ' )
if receiver is None :
receiver = file_props [ ' receiver ' ]
if sender is None :
sender = file_props [ ' sender ' ]
proxyhosts = [ ]
if fast and cfg_proxies :
proxies = map ( lambda e : e . strip ( ) , cfg_proxies . split ( ' , ' ) )
2006-03-21 00:17:36 +01:00
default = gajim . proxy65_manager . get_default_for_name ( self . name )
if default :
# add/move default proxy at top of the others
if proxies . __contains__ ( default ) :
proxies . remove ( default )
proxies . insert ( 0 , default )
2008-05-17 04:23:46 +02:00
2006-03-19 15:54:00 +01:00
for proxy in proxies :
2006-03-21 00:17:36 +01:00
( host , _port , jid ) = gajim . proxy65_manager . get_proxy ( proxy , self . name )
2006-03-19 15:54:00 +01:00
if host is None :
continue
host_dict = {
' state ' : 0 ,
' target ' : unicode ( receiver ) ,
' id ' : file_props [ ' sid ' ] ,
' sid ' : file_props [ ' sid ' ] ,
' initiator ' : proxy ,
' host ' : host ,
' port ' : unicode ( _port ) ,
' jid ' : jid
}
proxyhosts . append ( host_dict )
sha_str = helpers . get_auth_sha ( file_props [ ' sid ' ] , sender ,
receiver )
file_props [ ' sha_str ' ] = sha_str
2007-01-28 20:11:39 +01:00
ft_add_hosts = [ ]
if ft_add_hosts_to_send :
ft_add_hosts_to_send = map ( lambda e : e . strip ( ) ,
ft_add_hosts_to_send . split ( ' , ' ) )
for ft_host in ft_add_hosts_to_send :
2007-12-27 19:58:07 +01:00
ft_add_hosts . append ( ft_host )
2006-11-18 21:52:28 +01:00
listener = gajim . socks5queue . start_listener ( port ,
2006-03-19 15:54:00 +01:00
sha_str , self . _result_socks5_sid , file_props [ ' sid ' ] )
2008-04-18 02:02:56 +02:00
if listener is None :
2006-03-19 15:54:00 +01:00
file_props [ ' error ' ] = - 5
2006-11-18 21:52:28 +01:00
self . dispatch ( ' FILE_REQUEST_ERROR ' , ( unicode ( receiver ) , file_props ,
' ' ) )
2006-03-19 15:54:00 +01:00
self . _connect_error ( unicode ( receiver ) , file_props [ ' sid ' ] ,
file_props [ ' sid ' ] , code = 406 )
return
iq = common . xmpp . Protocol ( name = ' iq ' , to = unicode ( receiver ) ,
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 ' ] )
2007-01-28 20:11:39 +01:00
for ft_host in ft_add_hosts :
# The streamhost, if set
ostreamhost = common . xmpp . Node ( tag = ' streamhost ' )
query . addChild ( node = ostreamhost )
ostreamhost . setAttr ( ' port ' , unicode ( port ) )
ostreamhost . setAttr ( ' host ' , ft_host )
ostreamhost . setAttr ( ' jid ' , sender )
2007-12-12 09:44:46 +01:00
try :
thehost = self . peerhost [ 0 ]
streamhost = common . xmpp . Node ( tag = ' streamhost ' ) # My IP
query . addChild ( node = streamhost )
streamhost . setAttr ( ' port ' , unicode ( port ) )
streamhost . setAttr ( ' host ' , thehost )
streamhost . setAttr ( ' jid ' , sender )
except socket . gaierror :
self . dispatch ( ' ERROR ' , ( _ ( ' Wrong host ' ) ,
_ ( ' Invalid local address? :-O ' ) ) )
2007-01-28 20:11:39 +01:00
2006-03-27 10:28:05 +02:00
if fast and proxyhosts != [ ] and gajim . config . get_per ( ' accounts ' ,
self . name , ' use_ft_proxies ' ) :
2006-03-19 15:54:00 +01:00
file_props [ ' proxy_receiver ' ] = unicode ( receiver )
file_props [ ' proxy_sender ' ] = unicode ( 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 ' ] )
# don't add the proxy child tag for streamhosts, which are proxies
# proxy = streamhost.setTag('proxy')
# proxy.setNamespace(common.xmpp.NS_STREAM)
self . connection . send ( iq )
def send_file_rejection ( self , file_props ) :
''' informs sender that we refuse to download the file '''
2006-04-08 18:40:43 +02:00
# user response to ConfirmationDialog may come after we've disconneted
if not self . connection or self . connected < 2 :
return
2006-03-19 15:54:00 +01:00
iq = common . xmpp . Protocol ( name = ' iq ' ,
to = unicode ( file_props [ ' sender ' ] ) , typ = ' error ' )
iq . setAttr ( ' id ' , file_props [ ' request-id ' ] )
2006-11-18 21:52:28 +01:00
err = common . xmpp . ErrorNode ( code = ' 403 ' , typ = ' cancel ' , name =
' forbidden ' , text = ' Offer Declined ' )
2006-03-19 15:54:00 +01:00
iq . addChild ( node = err )
self . connection . send ( iq )
def send_file_approval ( self , file_props ) :
''' send iq, confirming that we want to download the file '''
2006-04-08 18:40:43 +02:00
# user response to ConfirmationDialog may come after we've disconneted
if not self . connection or self . connected < 2 :
return
2006-03-19 15:54:00 +01:00
iq = common . xmpp . Protocol ( name = ' iq ' ,
to = unicode ( file_props [ ' sender ' ] ) , typ = ' result ' )
iq . setAttr ( ' id ' , file_props [ ' request-id ' ] )
si = iq . setTag ( ' si ' )
si . setNamespace ( common . xmpp . NS_SI )
if file_props . has_key ( ' offset ' ) and file_props [ ' offset ' ] :
2006-04-04 10:31:36 +02:00
file_tag = si . setTag ( ' file ' )
file_tag . setNamespace ( common . xmpp . NS_FILE )
2006-03-19 15:54:00 +01:00
range_tag = file_tag . setTag ( ' range ' )
range_tag . setAttr ( ' offset ' , file_props [ ' offset ' ] )
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 ( common . xmpp . NS_BYTESTREAM )
self . connection . send ( iq )
def send_file_request ( self , file_props ) :
''' send iq for new FT request '''
2006-04-13 20:00:04 +02:00
if not self . connection or self . connected < 2 :
return
2006-03-19 15:54:00 +01:00
our_jid = gajim . get_jid_from_account ( self . name )
resource = self . server_resource
frm = our_jid + ' / ' + 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 ( common . xmpp . NS_BYTESTREAM )
self . connection . send ( iq )
2008-05-17 04:23:46 +02:00
2006-03-19 15:54:00 +01:00
def _result_socks5_sid ( self , sid , hash_id ) :
''' store the result of sha message from auth. '''
if not self . files_props . has_key ( sid ) :
return
file_props = self . files_props [ sid ]
file_props [ ' hash ' ] = hash_id
return
2008-05-17 04:23:46 +02:00
2006-03-19 15:54:00 +01:00
def _connect_error ( self , to , _id , sid , code = 404 ) :
''' cb, when there is an error establishing BS connection, or
when connection is rejected '''
msg_dict = {
404 : ' Could not connect to given hosts ' ,
405 : ' Cancel ' ,
406 : ' Not acceptable ' ,
}
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 ' , unicode ( code ) )
err . setData ( msg )
self . connection . send ( iq )
if code == 404 :
file_props = gajim . socks5queue . get_file_props ( self . name , sid )
if file_props is not None :
self . disconnect_transfer ( file_props )
file_props [ ' error ' ] = - 3
2006-11-18 21:52:28 +01:00
self . dispatch ( ' FILE_REQUEST_ERROR ' , ( to , file_props , msg ) )
2006-03-19 15:54:00 +01:00
def _proxy_auth_ok ( self , proxy ) :
''' cb, called after authentication to proxy server '''
file_props = self . files_props [ proxy [ ' sid ' ] ]
iq = common . xmpp . Protocol ( name = ' iq ' , to = proxy [ ' initiator ' ] ,
typ = ' set ' )
auth_id = " au_ " + proxy [ ' sid ' ]
iq . setID ( auth_id )
query = iq . setTag ( ' query ' )
query . setNamespace ( common . xmpp . NS_BYTESTREAM )
2007-12-12 09:44:46 +01:00
query . setAttr ( ' sid ' , proxy [ ' sid ' ] )
2006-03-19 15:54:00 +01:00
activate = query . setTag ( ' activate ' )
activate . setData ( file_props [ ' proxy_receiver ' ] )
iq . setID ( auth_id )
self . connection . send ( iq )
2008-05-17 04:23:46 +02:00
2006-03-19 15:54:00 +01:00
# register xmpppy handlers for bytestream and FT stanzas
def _bytestreamErrorCB ( self , con , iq_obj ) :
gajim . log . debug ( ' _bytestreamErrorCB ' )
id = unicode ( iq_obj . getAttr ( ' id ' ) )
2006-03-20 22:24:10 +01:00
frm = helpers . get_full_jid_from_iq ( iq_obj )
2006-03-19 15:54:00 +01:00
query = iq_obj . getTag ( ' query ' )
2006-03-20 22:24:10 +01:00
gajim . proxy65_manager . error_cb ( frm , query )
2006-03-19 15:54:00 +01:00
jid = helpers . get_jid_from_iq ( iq_obj )
id = id [ 3 : ]
if not self . files_props . has_key ( id ) :
return
file_props = self . files_props [ id ]
file_props [ ' error ' ] = - 4
2006-11-18 21:52:28 +01:00
self . dispatch ( ' FILE_REQUEST_ERROR ' , ( jid , file_props , ' ' ) )
2006-03-19 15:54:00 +01:00
raise common . xmpp . NodeProcessed
2008-05-17 04:23:46 +02:00
2006-03-19 15:54:00 +01:00
def _bytestreamSetCB ( self , con , iq_obj ) :
gajim . log . debug ( ' _bytestreamSetCB ' )
target = unicode ( iq_obj . getAttr ( ' to ' ) )
id = unicode ( iq_obj . getAttr ( ' id ' ) )
query = iq_obj . getTag ( ' query ' )
sid = unicode ( query . getAttr ( ' sid ' ) )
file_props = gajim . socks5queue . get_file_props (
self . name , sid )
streamhosts = [ ]
for item in query . getChildren ( ) :
if item . getName ( ) == ' streamhost ' :
host_dict = {
' state ' : 0 ,
' target ' : target ,
' id ' : id ,
' sid ' : sid ,
' initiator ' : helpers . get_full_jid_from_iq ( iq_obj )
}
for attr in item . getAttrs ( ) :
host_dict [ attr ] = item . getAttr ( attr )
streamhosts . append ( host_dict )
if file_props is None :
if self . files_props . has_key ( sid ) :
file_props = self . files_props [ sid ]
file_props [ ' fast ' ] = streamhosts
if file_props [ ' type ' ] == ' s ' : # FIXME: remove fast xmlns
# 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 )
raise common . xmpp . NodeProcessed
file_props [ ' streamhosts ' ] = streamhosts
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
2006-04-12 00:23:51 +02:00
def _ResultCB ( self , con , iq_obj ) :
gajim . log . debug ( ' _ResultCB ' )
2007-08-09 17:39:18 +02:00
# if we want to respect xep-0065 we have to check for proxy
2006-04-12 00:23:51 +02:00
# activation result in any result iq
real_id = unicode ( iq_obj . getAttr ( ' id ' ) )
2008-02-08 00:53:02 +01:00
if real_id == self . awaiting_xmpp_ping_id :
self . awaiting_xmpp_ping_id = None
return
2008-04-21 22:39:55 +02:00
if not real_id . startswith ( ' au_ ' ) :
2008-02-08 08:58:23 +01:00
return
2006-04-12 00:23:51 +02:00
frm = helpers . get_full_jid_from_iq ( iq_obj )
id = real_id [ 3 : ]
if self . files_props . has_key ( id ) :
file_props = self . files_props [ id ]
if file_props [ ' streamhost-used ' ] :
for host in file_props [ ' proxyhosts ' ] :
2006-04-13 20:00:04 +02:00
if host [ ' initiator ' ] == frm and host . has_key ( ' idx ' ) :
2006-04-12 00:23:51 +02:00
gajim . socks5queue . activate_proxy ( host [ ' idx ' ] )
raise common . xmpp . NodeProcessed
2008-05-17 04:23:46 +02:00
2006-03-19 15:54:00 +01:00
def _bytestreamResultCB ( self , con , iq_obj ) :
gajim . log . debug ( ' _bytestreamResultCB ' )
frm = helpers . get_full_jid_from_iq ( iq_obj )
real_id = unicode ( iq_obj . getAttr ( ' id ' ) )
query = iq_obj . getTag ( ' query ' )
2006-03-19 21:43:30 +01:00
gajim . proxy65_manager . resolve_result ( frm , query )
2008-05-17 04:23:46 +02:00
2006-03-19 15:54:00 +01:00
try :
2007-12-12 09:44:46 +01:00
streamhost = query . getTag ( ' streamhost-used ' )
2006-03-19 15:54:00 +01:00
except : # this bytestream result is not what we need
pass
id = real_id [ 3 : ]
if self . files_props . has_key ( id ) :
file_props = self . files_props [ id ]
else :
raise common . xmpp . NodeProcessed
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 \
unicode ( query . getAttr ( ' sid ' ) ) == file_props [ ' sid ' ] :
gajim . socks5queue . activate_proxy ( host [ ' idx ' ] )
break
raise common . xmpp . NodeProcessed
jid = streamhost . getAttr ( ' jid ' )
if file_props . has_key ( ' streamhost-used ' ) and \
file_props [ ' streamhost-used ' ] is True :
raise common . xmpp . NodeProcessed
if real_id [ : 3 ] == ' au_ ' :
2007-12-12 09:44:46 +01:00
if file . has_key ( ' stopped ' ) and file_props [ ' stopped ' ] :
self . remove_transfer ( file_props )
else :
gajim . socks5queue . send_file ( file_props , self . name )
2006-03-19 15:54:00 +01:00
raise common . xmpp . NodeProcessed
proxy = None
if file_props . has_key ( ' proxyhosts ' ) :
for proxyhost in file_props [ ' proxyhosts ' ] :
if proxyhost [ ' jid ' ] == jid :
proxy = proxyhost
2008-04-18 02:26:07 +02:00
if proxy is not None :
2006-03-19 15:54:00 +01:00
file_props [ ' streamhost-used ' ] = True
if not file_props . has_key ( ' streamhosts ' ) :
file_props [ ' streamhosts ' ] = [ ]
file_props [ ' streamhosts ' ] . append ( proxy )
file_props [ ' is_a_proxy ' ] = True
receiver = socks5 . Socks5Receiver ( gajim . idlequeue , 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
else :
2007-12-12 09:44:46 +01:00
if file_props . has_key ( ' stopped ' ) and file_props [ ' stopped ' ] :
self . remove_transfer ( file_props )
else :
gajim . socks5queue . send_file ( file_props , self . name )
2006-03-19 15:54:00 +01:00
if file_props . has_key ( ' fast ' ) :
fasts = file_props [ ' fast ' ]
if len ( fasts ) > 0 :
self . _connect_error ( frm , fasts [ 0 ] [ ' id ' ] , file_props [ ' sid ' ] ,
code = 406 )
2008-05-17 04:23:46 +02:00
2006-03-19 15:54:00 +01:00
raise common . xmpp . NodeProcessed
2008-05-17 04:23:46 +02:00
2006-03-19 15:54:00 +01:00
def _siResultCB ( self , con , iq_obj ) :
gajim . log . debug ( ' _siResultCB ' )
id = iq_obj . getAttr ( ' id ' )
if not self . files_props . has_key ( id ) :
# no such jid
return
file_props = self . files_props [ id ]
if file_props is None :
# file properties for jid is none
return
2006-04-13 20:00:04 +02:00
if file_props . has_key ( ' request-id ' ) :
# we have already sent streamhosts info
return
2006-03-19 15:54:00 +01:00
file_props [ ' receiver ' ] = helpers . get_full_jid_from_iq ( iq_obj )
si = iq_obj . getTag ( ' si ' )
file_tag = si . getTag ( ' file ' )
range_tag = None
if file_tag :
range_tag = file_tag . getTag ( ' range ' )
if range_tag :
offset = range_tag . getAttr ( ' offset ' )
if offset :
file_props [ ' offset ' ] = int ( offset )
length = range_tag . getAttr ( ' length ' )
if length :
file_props [ ' length ' ] = int ( length )
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
self . send_socks5_info ( file_props , fast = True )
raise common . xmpp . NodeProcessed
2008-05-17 04:23:46 +02:00
2006-03-19 15:54:00 +01:00
def _siSetCB ( self , con , iq_obj ) :
gajim . log . debug ( ' _siSetCB ' )
jid = helpers . get_jid_from_iq ( iq_obj )
si = iq_obj . getTag ( ' si ' )
profile = si . getAttr ( ' profile ' )
mime_type = si . getAttr ( ' mime-type ' )
if profile != common . xmpp . NS_FILE :
return
file_tag = si . getTag ( ' file ' )
file_props = { ' type ' : ' r ' }
for attribute in file_tag . getAttrs ( ) :
if attribute in ( ' name ' , ' size ' , ' hash ' , ' date ' ) :
val = file_tag . getAttr ( attribute )
if val is None :
continue
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
our_jid = gajim . get_jid_from_account ( self . name )
resource = self . server_resource
file_props [ ' receiver ' ] = our_jid + ' / ' + resource
file_props [ ' sender ' ] = helpers . get_full_jid_from_iq ( iq_obj )
file_props [ ' request-id ' ] = unicode ( iq_obj . getAttr ( ' id ' ) )
file_props [ ' sid ' ] = unicode ( si . getAttr ( ' id ' ) )
2007-08-09 17:39:18 +02:00
file_props [ ' transfered_size ' ] = [ ]
2006-03-19 15:54:00 +01:00
gajim . socks5queue . add_file_props ( self . name , file_props )
self . dispatch ( ' FILE_REQUEST ' , ( jid , file_props ) )
raise common . xmpp . NodeProcessed
def _siErrorCB ( self , con , iq_obj ) :
gajim . log . debug ( ' _siErrorCB ' )
si = iq_obj . getTag ( ' si ' )
profile = si . getAttr ( ' profile ' )
if profile != common . xmpp . NS_FILE :
return
id = iq_obj . getAttr ( ' id ' )
if not self . files_props . has_key ( id ) :
# no such jid
return
file_props = self . files_props [ id ]
if file_props is None :
# file properties for jid is none
return
jid = helpers . get_jid_from_iq ( iq_obj )
file_props [ ' error ' ] = - 3
2006-11-18 21:52:28 +01:00
self . dispatch ( ' FILE_REQUEST_ERROR ' , ( jid , file_props , ' ' ) )
2006-03-19 15:54:00 +01:00
raise common . xmpp . NodeProcessed
class ConnectionDisco :
''' hold xmpppy handlers and public methods for discover services '''
2006-03-21 00:17:36 +01:00
def discoverItems ( self , jid , node = None , id_prefix = None ) :
2007-08-09 17:39:18 +02:00
''' According to XEP-0030: jid is mandatory,
2006-03-19 15:54:00 +01:00
name , node , action is optional . '''
2006-03-21 00:17:36 +01:00
self . _discover ( common . xmpp . NS_DISCO_ITEMS , jid , node , id_prefix )
2006-03-19 15:54:00 +01:00
2006-03-21 00:17:36 +01:00
def discoverInfo ( self , jid , node = None , id_prefix = None ) :
2007-08-09 17:39:18 +02:00
''' According to XEP-0030:
2006-03-19 15:54:00 +01:00
For identity : category , type is mandatory , name is optional .
For feature : var is mandatory '''
2006-03-21 00:17:36 +01:00
self . _discover ( common . xmpp . NS_DISCO_INFO , jid , node , id_prefix )
2008-05-17 04:23:46 +02:00
2006-03-19 15:54:00 +01:00
def request_register_agent_info ( self , agent ) :
if not self . connection :
return None
iq = common . xmpp . Iq ( ' get ' , common . xmpp . NS_REGISTER , to = agent )
id = self . connection . getAnID ( )
iq . setID ( id )
# Wait the answer during 30 secondes
self . awaiting_timeouts [ gajim . idlequeue . current_time ( ) + 30 ] = ( id ,
2006-09-13 18:47:58 +02:00
_ ( ' Registration information for transport %s has not arrived in time ' ) % \
agent )
2006-03-19 15:54:00 +01:00
self . connection . SendAndCallForResponse ( iq , self . _ReceivedRegInfo ,
{ ' agent ' : agent } )
2007-02-15 10:18:24 +01:00
2006-03-19 15:54:00 +01:00
def register_agent ( self , agent , info , is_form = False ) :
if not self . connection :
return
if is_form :
iq = common . xmpp . Iq ( ' set ' , common . xmpp . NS_REGISTER , to = agent )
query = iq . getTag ( ' query ' )
2007-02-15 10:18:24 +01:00
info . setAttr ( ' type ' , ' submit ' )
query . addChild ( node = info )
2006-03-19 15:54:00 +01:00
self . connection . send ( iq )
else :
# fixed: blocking
common . xmpp . features_nb . register ( self . connection , agent , info , None )
2008-05-17 04:23:46 +02:00
2006-03-21 00:17:36 +01:00
def _discover ( self , ns , jid , node = None , id_prefix = None ) :
2006-03-19 15:54:00 +01:00
if not self . connection :
return
iq = common . xmpp . Iq ( typ = ' get ' , to = jid , queryNS = ns )
2006-03-21 00:17:36 +01:00
if id_prefix :
id = self . connection . getAnID ( )
iq . setID ( ' %s %s ' % ( id_prefix , id ) )
2006-03-19 15:54:00 +01:00
if node :
iq . setQuerynode ( node )
self . connection . send ( iq )
2008-05-17 04:23:46 +02:00
2006-03-19 15:54:00 +01:00
def _ReceivedRegInfo ( self , con , resp , agent ) :
common . xmpp . features_nb . _ReceivedRegInfo ( con , resp , agent )
self . _IqCB ( con , resp )
2008-05-17 04:23:46 +02:00
2006-03-19 15:54:00 +01:00
def _discoGetCB ( self , con , iq_obj ) :
''' get disco info '''
frm = helpers . get_full_jid_from_iq ( iq_obj )
to = unicode ( iq_obj . getAttr ( ' to ' ) )
id = unicode ( iq_obj . getAttr ( ' id ' ) )
iq = common . xmpp . Iq ( to = frm , typ = ' result ' , queryNS = \
common . xmpp . NS_DISCO , frm = to )
iq . setAttr ( ' id ' , id )
query = iq . setTag ( ' query ' )
2008-04-21 00:58:47 +02:00
query . setAttr ( ' node ' , ' http://gajim.org# ' + gajim . version . split ( ' - ' ,
2007-12-12 09:44:46 +01:00
1 ) [ 0 ] )
2008-02-08 00:53:02 +01:00
for f in ( common . xmpp . NS_BYTESTREAM , common . xmpp . NS_SI ,
common . xmpp . NS_FILE , common . xmpp . NS_COMMANDS ) :
2007-03-08 09:57:20 +01:00
feature = common . xmpp . Node ( ' feature ' )
feature . setAttr ( ' var ' , f )
query . addChild ( node = feature )
2008-05-17 04:23:46 +02:00
2006-03-19 15:54:00 +01:00
self . connection . send ( iq )
raise common . xmpp . NodeProcessed
2008-05-17 04:23:46 +02:00
2006-03-19 15:54:00 +01:00
def _DiscoverItemsErrorCB ( self , con , iq_obj ) :
gajim . log . debug ( ' DiscoverItemsErrorCB ' )
jid = helpers . get_full_jid_from_iq ( iq_obj )
self . dispatch ( ' AGENT_ERROR_ITEMS ' , ( jid ) )
def _DiscoverItemsCB ( self , con , iq_obj ) :
gajim . log . debug ( ' DiscoverItemsCB ' )
q = iq_obj . getTag ( ' query ' )
node = q . getAttr ( ' node ' )
if not node :
node = ' '
qp = iq_obj . getQueryPayload ( )
items = [ ]
if not qp :
qp = [ ]
for i in qp :
# CDATA payload is not processed, only nodes
if not isinstance ( i , common . xmpp . simplexml . Node ) :
continue
attr = { }
for key in i . getAttrs ( ) :
attr [ key ] = i . getAttrs ( ) [ key ]
2006-11-18 21:52:28 +01:00
if ' jid ' not in attr :
continue
try :
helpers . parse_jid ( attr [ ' jid ' ] )
except common . helpers . InvalidFormat :
# jid is not conform
continue
2006-03-19 15:54:00 +01:00
items . append ( attr )
jid = helpers . get_full_jid_from_iq ( iq_obj )
2008-05-17 04:23:46 +02:00
hostname = gajim . config . get_per ( ' accounts ' , self . name ,
2006-03-21 00:17:36 +01:00
' hostname ' )
id = iq_obj . getID ( )
if jid == hostname and id [ 0 ] == ' p ' :
for item in items :
self . discoverInfo ( item [ ' jid ' ] , id_prefix = ' p ' )
else :
self . dispatch ( ' AGENT_INFO_ITEMS ' , ( jid , node , items ) )
2006-03-19 15:54:00 +01:00
2006-07-15 15:27:57 +02:00
def _DiscoverItemsGetCB ( self , con , iq_obj ) :
gajim . log . debug ( ' DiscoverItemsGetCB ' )
2008-07-28 14:17:33 +02:00
if not self . connection :
return
2007-12-12 09:44:46 +01:00
if self . commandItemsQuery ( con , iq_obj ) :
raise common . xmpp . NodeProcessed
2006-07-15 15:27:57 +02:00
node = iq_obj . getTagAttr ( ' query ' , ' node ' )
2007-12-12 09:44:46 +01:00
if node is None :
2007-08-09 17:39:18 +02:00
result = iq_obj . buildReply ( ' result ' )
self . connection . send ( result )
raise common . xmpp . NodeProcessed
2006-07-15 15:27:57 +02:00
if node == common . xmpp . NS_COMMANDS :
self . commandListQuery ( con , iq_obj )
raise common . xmpp . NodeProcessed
2006-03-19 15:54:00 +01:00
def _DiscoverInfoGetCB ( self , con , iq_obj ) :
2008-07-29 09:36:44 +02:00
if not self . connection :
return
2006-03-19 15:54:00 +01:00
gajim . log . debug ( ' DiscoverInfoGetCB ' )
2006-07-15 15:27:57 +02:00
q = iq_obj . getTag ( ' query ' )
node = q . getAttr ( ' node ' )
2007-12-12 09:44:46 +01:00
if self . commandInfoQuery ( con , iq_obj ) :
2006-11-20 20:34:11 +01:00
raise common . xmpp . NodeProcessed
2008-05-17 04:23:46 +02:00
2006-12-02 18:02:53 +01:00
else :
2006-07-15 15:27:57 +02:00
iq = iq_obj . buildReply ( ' result ' )
q = iq . getTag ( ' query ' )
2007-03-08 09:57:20 +01:00
if node :
q . setAttr ( ' node ' , node )
2008-04-21 00:58:47 +02:00
q . addChild ( ' identity ' , attrs = gajim . gajim_identity )
2006-12-02 18:02:53 +01:00
extension = None
if node and node . find ( ' # ' ) != - 1 :
extension = node [ node . index ( ' # ' ) + 1 : ]
2008-05-27 12:24:29 +02:00
client_version = ' http://gajim.org# ' + gajim . caps_hash [ self . name ]
2006-12-02 18:02:53 +01:00
2007-03-08 09:57:20 +01:00
if node in ( None , client_version ) :
2008-04-21 00:58:47 +02:00
for f in gajim . gajim_common_features :
q . addChild ( ' feature ' , attrs = { ' var ' : f } )
2008-05-27 12:24:29 +02:00
for f in gajim . gajim_optional_features [ self . name ] :
2008-04-21 00:58:47 +02:00
q . addChild ( ' feature ' , attrs = { ' var ' : f } )
2007-08-09 17:39:18 +02:00
2006-12-02 18:02:53 +01:00
if q . getChildren ( ) :
self . connection . send ( iq )
raise common . xmpp . NodeProcessed
2006-03-19 15:54:00 +01:00
def _DiscoverInfoErrorCB ( self , con , iq_obj ) :
gajim . log . debug ( ' DiscoverInfoErrorCB ' )
jid = helpers . get_full_jid_from_iq ( iq_obj )
self . dispatch ( ' AGENT_ERROR_INFO ' , ( jid ) )
def _DiscoverInfoCB ( self , con , iq_obj ) :
gajim . log . debug ( ' DiscoverInfoCB ' )
2007-08-09 17:39:18 +02:00
# According to XEP-0030:
2006-03-19 15:54:00 +01:00
# For identity: category, type is mandatory, name is optional.
# For feature: var is mandatory
identities , features , data = [ ] , [ ] , [ ]
q = iq_obj . getTag ( ' query ' )
node = q . getAttr ( ' node ' )
if not node :
node = ' '
qc = iq_obj . getQueryChildren ( )
if not qc :
qc = [ ]
2006-09-13 18:47:58 +02:00
is_muc = False
transport_type = ' '
2006-03-19 15:54:00 +01:00
for i in qc :
if i . getName ( ) == ' identity ' :
attr = { }
for key in i . getAttrs ( ) . keys ( ) :
attr [ key ] = i . getAttr ( key )
2007-08-09 17:39:18 +02:00
if attr . has_key ( ' category ' ) and \
2007-12-12 09:44:46 +01:00
attr [ ' category ' ] in ( ' gateway ' , ' headline ' ) and \
attr . has_key ( ' type ' ) :
2006-09-13 18:47:58 +02:00
transport_type = attr [ ' type ' ]
2007-08-09 17:39:18 +02:00
if attr . has_key ( ' category ' ) and \
2007-12-12 09:44:46 +01:00
attr [ ' category ' ] == ' conference ' and \
attr . has_key ( ' type ' ) and attr [ ' type ' ] == ' text ' :
2006-09-13 18:47:58 +02:00
is_muc = True
2006-03-19 15:54:00 +01:00
identities . append ( attr )
elif i . getName ( ) == ' feature ' :
features . append ( i . getAttr ( ' var ' ) )
2006-09-13 18:47:58 +02:00
elif i . getName ( ) == ' x ' and i . getNamespace ( ) == common . xmpp . NS_DATA :
2006-03-19 15:54:00 +01:00
data . append ( common . xmpp . DataForm ( node = i ) )
jid = helpers . get_full_jid_from_iq ( iq_obj )
2006-09-13 18:47:58 +02:00
if transport_type and jid not in gajim . transport_type :
gajim . transport_type [ jid ] = transport_type
gajim . logger . save_transport_type ( jid , transport_type )
2006-03-21 00:17:36 +01:00
id = iq_obj . getID ( )
2006-03-25 01:46:42 +01:00
if not identities : # ejabberd doesn't send identities when we browse online users
#FIXME: see http://www.jabber.ru/bugzilla/show_bug.cgi?id=225
identities = [ { ' category ' : ' server ' , ' type ' : ' im ' , ' name ' : node } ]
if id [ 0 ] == ' p ' :
2007-03-30 21:16:44 +02:00
if jid == gajim . config . get_per ( ' accounts ' , self . name , ' hostname ' ) :
2007-08-09 17:39:18 +02:00
if features . __contains__ ( common . xmpp . NS_GMAILNOTIFY ) :
gajim . gmail_domains . append ( jid )
self . request_gmail_notifications ( )
2007-03-30 21:16:44 +02:00
for identity in identities :
2008-04-23 01:52:04 +02:00
if identity [ ' category ' ] == ' pubsub ' and identity . get ( ' type ' ) == \
2007-03-30 21:16:44 +02:00
' pep ' :
self . pep_supported = True
2007-12-15 13:15:10 +01:00
if dbus_support . supported :
listener = MusicTrackListener . get ( )
track = listener . get_playing_track ( )
2008-05-30 23:43:53 +02:00
if gajim . config . get_per ( ' accounts ' , self . name ,
' publish_tune ' ) :
2008-05-15 21:52:04 +02:00
gajim . interface . roster . music_track_changed ( listener ,
2007-12-15 13:15:10 +01:00
track , self . name )
2007-03-30 21:16:44 +02:00
break
2006-03-25 01:46:42 +01:00
if features . __contains__ ( common . xmpp . NS_BYTESTREAM ) :
gajim . proxy65_manager . resolve ( jid , self . connection , self . name )
2006-09-13 18:47:58 +02:00
if features . __contains__ ( common . xmpp . NS_MUC ) and is_muc :
type_ = transport_type or ' jabber '
self . muc_jid [ type_ ] = jid
if transport_type :
if self . available_transports . has_key ( transport_type ) :
self . available_transports [ transport_type ] . append ( jid )
else :
self . available_transports [ transport_type ] = [ jid ]
2007-08-09 17:39:18 +02:00
2006-03-25 01:46:42 +01:00
self . dispatch ( ' AGENT_INFO_INFO ' , ( jid , node , identities ,
features , data ) )
2007-08-09 17:39:18 +02:00
self . _capsDiscoCB ( jid , node , identities , features , data )
2006-03-19 15:54:00 +01:00
class ConnectionVcard :
def __init__ ( self ) :
self . vcard_sha = None
self . vcard_shas = { } # sha of contacts
self . room_jids = [ ] # list of gc jids so that vcard are saved in a folder
2007-08-09 17:39:18 +02:00
2006-05-01 16:15:28 +02:00
def add_sha ( self , p , send_caps = True ) :
2006-03-19 15:54:00 +01:00
c = p . setTag ( ' x ' , namespace = common . xmpp . NS_VCARD_UPDATE )
if self . vcard_sha is not None :
c . setTagData ( ' photo ' , self . vcard_sha )
2006-05-01 16:15:28 +02:00
if send_caps :
return self . add_caps ( p )
return p
2008-05-17 04:23:46 +02:00
2006-05-01 16:15:28 +02:00
def add_caps ( self , p ) :
2007-08-09 17:39:18 +02:00
''' advertise our capabilities in presence stanza (xep-0115) '''
2006-05-01 16:15:28 +02:00
c = p . setTag ( ' c ' , namespace = common . xmpp . NS_CAPS )
2008-04-21 00:58:47 +02:00
c . setAttr ( ' hash ' , ' sha-1 ' )
c . setAttr ( ' node ' , ' http://gajim.org ' )
2008-05-27 12:24:29 +02:00
c . setAttr ( ' ver ' , gajim . caps_hash [ self . name ] )
2006-03-19 15:54:00 +01:00
return p
2008-05-17 04:23:46 +02:00
2006-03-19 15:54:00 +01:00
def node_to_dict ( self , node ) :
dict = { }
for info in node . getChildren ( ) :
name = info . getName ( )
if name in ( ' ADR ' , ' TEL ' , ' EMAIL ' ) : # we can have several
if not dict . has_key ( name ) :
dict [ name ] = [ ]
entry = { }
for c in info . getChildren ( ) :
2007-02-04 19:57:25 +01:00
entry [ c . getName ( ) ] = c . getData ( )
2006-03-19 15:54:00 +01:00
dict [ name ] . append ( entry )
elif info . getChildren ( ) == [ ] :
dict [ name ] = info . getData ( )
else :
dict [ name ] = { }
for c in info . getChildren ( ) :
2007-02-04 19:57:25 +01:00
dict [ name ] [ c . getName ( ) ] = c . getData ( )
2006-03-19 15:54:00 +01:00
return dict
def save_vcard_to_hd ( self , full_jid , card ) :
jid , nick = gajim . get_room_and_nick_from_fjid ( full_jid )
2006-03-26 13:46:04 +02:00
puny_jid = helpers . sanitize_filename ( jid )
2006-03-19 15:54:00 +01:00
path = os . path . join ( gajim . VCARD_PATH , puny_jid )
2006-04-26 10:11:16 +02:00
if jid in self . room_jids or os . path . isdir ( path ) :
2006-11-18 21:52:28 +01:00
if not nick :
return
2006-03-19 15:54:00 +01:00
# remove room_jid file if needed
if os . path . isfile ( path ) :
os . remove ( path )
# create folder if needed
if not os . path . isdir ( path ) :
os . mkdir ( path , 0700 )
2006-03-26 13:46:04 +02:00
puny_nick = helpers . sanitize_filename ( nick )
2006-03-19 15:54:00 +01:00
path_to_file = os . path . join ( gajim . VCARD_PATH , puny_jid , puny_nick )
else :
path_to_file = path
2007-08-09 17:39:18 +02:00
try :
fil = open ( path_to_file , ' w ' )
fil . write ( str ( card ) )
fil . close ( )
except IOError , e :
self . dispatch ( ' ERROR ' , ( _ ( ' Disk Write Error ' ) , str ( e ) ) )
2008-05-17 04:23:46 +02:00
2006-03-19 15:54:00 +01:00
def get_cached_vcard ( self , fjid , is_fake_jid = False ) :
''' return the vcard as a dict
return { } if vcard was too old
return None if we don ' t have cached vcard ' ' '
jid , nick = gajim . get_room_and_nick_from_fjid ( fjid )
2006-03-26 13:46:04 +02:00
puny_jid = helpers . sanitize_filename ( jid )
2006-03-19 15:54:00 +01:00
if is_fake_jid :
2006-03-26 13:46:04 +02:00
puny_nick = helpers . sanitize_filename ( nick )
2006-03-19 15:54:00 +01:00
path_to_file = os . path . join ( gajim . VCARD_PATH , puny_jid , puny_nick )
else :
path_to_file = os . path . join ( gajim . VCARD_PATH , puny_jid )
if not os . path . isfile ( path_to_file ) :
return None
# We have the vcard cached
f = open ( path_to_file )
c = f . read ( )
f . close ( )
2007-01-12 11:10:01 +01:00
try :
card = common . xmpp . Node ( node = c )
except :
# We are unable to parse it. Remove it
os . remove ( path_to_file )
return None
2006-03-19 15:54:00 +01:00
vcard = self . node_to_dict ( card )
if vcard . has_key ( ' PHOTO ' ) :
if not isinstance ( vcard [ ' PHOTO ' ] , dict ) :
del vcard [ ' PHOTO ' ]
2008-05-17 04:23:46 +02:00
elif vcard [ ' PHOTO ' ] . has_key ( ' SHA ' ) :
cached_sha = vcard [ ' PHOTO ' ] [ ' SHA ' ]
if self . vcard_shas . has_key ( jid ) and self . vcard_shas [ jid ] != \
cached_sha :
# user change his vcard so don't use the cached one
return { }
2006-03-19 15:54:00 +01:00
vcard [ ' jid ' ] = jid
vcard [ ' resource ' ] = gajim . get_resource_from_jid ( fjid )
return vcard
2007-06-03 12:04:20 +02:00
def request_vcard ( self , jid = None , groupchat_jid = None ) :
''' request the VCARD. If groupchat_jid is not nul, it means we request a vcard
to a fake jid , like in private messages in groupchat . jid can be the
real jid of the contact , but we want to consider it comes from a fake jid '''
2006-03-19 15:54:00 +01:00
if not self . connection :
return
iq = common . xmpp . Iq ( typ = ' get ' )
if jid :
iq . setTo ( jid )
iq . setTag ( common . xmpp . NS_VCARD + ' vCard ' )
id = self . connection . getAnID ( )
iq . setID ( id )
2006-09-13 18:47:58 +02:00
j = jid
if not j :
j = gajim . get_jid_from_account ( self . name )
2007-06-03 12:04:20 +02:00
self . awaiting_answers [ id ] = ( VCARD_ARRIVED , j , groupchat_jid )
if groupchat_jid :
room_jid , nick = gajim . get_room_and_nick_from_fjid ( groupchat_jid )
2006-03-19 15:54:00 +01:00
if not room_jid in self . room_jids :
self . room_jids . append ( room_jid )
2007-06-03 12:04:20 +02:00
self . groupchat_jids [ id ] = groupchat_jid
2006-03-19 15:54:00 +01:00
self . connection . send ( iq )
def send_vcard ( self , vcard ) :
if not self . connection :
return
iq = common . xmpp . Iq ( typ = ' set ' )
iq2 = iq . setTag ( common . xmpp . NS_VCARD + ' vCard ' )
for i in vcard :
if i == ' jid ' :
continue
if isinstance ( vcard [ i ] , dict ) :
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 ] )
else :
iq2 . addChild ( i ) . setData ( vcard [ i ] )
id = self . connection . getAnID ( )
iq . setID ( id )
self . connection . send ( iq )
2006-11-28 16:40:08 +01:00
our_jid = gajim . get_jid_from_account ( self . name )
2006-03-19 15:54:00 +01:00
# Add the sha of the avatar
if vcard . has_key ( ' PHOTO ' ) and isinstance ( vcard [ ' PHOTO ' ] , dict ) and \
vcard [ ' PHOTO ' ] . has_key ( ' BINVAL ' ) :
photo = vcard [ ' PHOTO ' ] [ ' BINVAL ' ]
photo_decoded = base64 . decodestring ( photo )
2006-04-11 20:28:31 +02:00
gajim . interface . save_avatar_files ( our_jid , photo_decoded )
2006-03-19 15:54:00 +01:00
avatar_sha = sha . sha ( photo_decoded ) . hexdigest ( )
iq2 . getTag ( ' PHOTO ' ) . setTagData ( ' SHA ' , avatar_sha )
2006-11-28 16:40:08 +01:00
else :
gajim . interface . remove_avatar_files ( our_jid )
2006-03-19 15:54:00 +01:00
self . awaiting_answers [ id ] = ( VCARD_PUBLISHED , iq2 )
2008-05-03 02:10:17 +02:00
2006-03-19 15:54:00 +01:00
def _IqCB ( self , con , iq_obj ) :
id = iq_obj . getID ( )
# Check if we were waiting a timeout for this id
found_tim = None
for tim in self . awaiting_timeouts :
if id == self . awaiting_timeouts [ tim ] [ 0 ] :
found_tim = tim
break
if found_tim :
del self . awaiting_timeouts [ found_tim ]
if id not in self . awaiting_answers :
return
if self . awaiting_answers [ id ] [ 0 ] == VCARD_PUBLISHED :
if iq_obj . getType ( ) == ' result ' :
vcard_iq = self . awaiting_answers [ id ] [ 1 ]
# Save vcard to HD
if vcard_iq . getTag ( ' PHOTO ' ) and vcard_iq . getTag ( ' PHOTO ' ) . getTag ( ' SHA ' ) :
new_sha = vcard_iq . getTag ( ' PHOTO ' ) . getTagData ( ' SHA ' )
else :
new_sha = ' '
# Save it to file
our_jid = gajim . get_jid_from_account ( self . name )
self . save_vcard_to_hd ( our_jid , vcard_iq )
# Send new presence if sha changed and we are not invisible
if self . vcard_sha != new_sha and STATUS_LIST [ self . connected ] != \
' invisible ' :
self . vcard_sha = new_sha
sshow = helpers . get_xmpp_show ( STATUS_LIST [ self . connected ] )
2006-11-18 21:52:28 +01:00
p = common . xmpp . Presence ( typ = None , priority = self . priority ,
2006-03-19 15:54:00 +01:00
show = sshow , status = self . status )
p = self . add_sha ( p )
self . connection . send ( p )
2006-04-12 14:55:06 +02:00
self . dispatch ( ' VCARD_PUBLISHED ' , ( ) )
2006-03-19 15:54:00 +01:00
elif iq_obj . getType ( ) == ' error ' :
self . dispatch ( ' VCARD_NOT_PUBLISHED ' , ( ) )
elif self . awaiting_answers [ id ] [ 0 ] == VCARD_ARRIVED :
# If vcard is empty, we send to the interface an empty vcard so that
# it knows it arrived
2006-09-13 18:47:58 +02:00
jid = self . awaiting_answers [ id ] [ 1 ]
2007-06-03 12:04:20 +02:00
groupchat_jid = self . awaiting_answers [ id ] [ 2 ]
frm = jid
if groupchat_jid :
# We do as if it comes from the fake_jid
frm = groupchat_jid
2006-09-13 18:47:58 +02:00
our_jid = gajim . get_jid_from_account ( self . name )
if iq_obj . getType ( ) == ' error ' and jid == our_jid :
# our server doesn't support vcard
2008-05-03 02:10:17 +02:00
gajim . log . debug ( ' xxx error xxx ' )
2006-09-13 18:47:58 +02:00
self . vcard_supported = False
if not iq_obj . getTag ( ' vCard ' ) or iq_obj . getType ( ) == ' error ' :
2007-06-03 12:04:20 +02:00
if frm and frm != our_jid :
2006-03-19 15:54:00 +01:00
# Write an empty file
2007-06-03 12:04:20 +02:00
self . save_vcard_to_hd ( frm , ' ' )
2008-04-09 23:30:12 +02:00
jid , resource = gajim . get_room_and_nick_from_fjid ( frm )
self . dispatch ( ' VCARD ' , { ' jid ' : jid , ' resource ' : resource } )
2007-06-03 12:04:20 +02:00
elif frm == our_jid :
self . dispatch ( ' MYVCARD ' , { ' jid ' : frm } )
2006-05-01 20:29:12 +02:00
elif self . awaiting_answers [ id ] [ 0 ] == AGENT_REMOVED :
jid = self . awaiting_answers [ id ] [ 1 ]
self . dispatch ( ' AGENT_REMOVED ' , jid )
2006-09-13 18:47:58 +02:00
elif self . awaiting_answers [ id ] [ 0 ] == METACONTACTS_ARRIVED :
if iq_obj . getType ( ) == ' result ' :
# Metacontact tags
2007-08-09 17:39:18 +02:00
# http://www.xmpp.org/extensions/xep-0209.html
2006-09-13 18:47:58 +02:00
meta_list = { }
query = iq_obj . getTag ( ' query ' )
storage = query . getTag ( ' storage ' )
metas = storage . getTags ( ' meta ' )
for meta in metas :
jid = meta . getAttr ( ' jid ' )
tag = meta . getAttr ( ' tag ' )
data = { ' jid ' : jid }
order = meta . getAttr ( ' order ' )
2007-12-12 09:44:46 +01:00
try :
order = int ( order )
except :
order = 0
2008-04-18 02:26:07 +02:00
if order is not None :
2006-09-13 18:47:58 +02:00
data [ ' order ' ] = order
if meta_list . has_key ( tag ) :
meta_list [ tag ] . append ( data )
else :
meta_list [ tag ] = [ data ]
self . dispatch ( ' METACONTACTS ' , meta_list )
2006-11-18 21:52:28 +01:00
else :
2007-12-12 09:44:46 +01:00
if iq_obj . getErrorCode ( ) not in ( ' 403 ' , ' 406 ' , ' 404 ' ) :
self . private_storage_supported = False
2006-09-13 18:47:58 +02:00
# We can now continue connection by requesting the roster
self . connection . initRoster ( )
2006-11-18 21:52:28 +01:00
elif self . awaiting_answers [ id ] [ 0 ] == PRIVACY_ARRIVED :
if iq_obj . getType ( ) != ' error ' :
self . privacy_rules_supported = True
2007-06-03 12:04:20 +02:00
self . get_privacy_list ( ' block ' )
2008-06-25 11:25:43 +02:00
elif self . continue_connect_info :
if self . continue_connect_info [ 0 ] == ' invisible ' :
# Trying to login as invisible but privacy list not supported
self . disconnect ( on_purpose = True )
self . dispatch ( ' STATUS ' , ' offline ' )
self . dispatch ( ' ERROR ' , ( _ ( ' Invisibility not supported ' ) ,
_ ( ' Account %s doesn \' t support invisibility. ' ) % self . name ) )
return
2006-11-18 21:52:28 +01:00
# Ask metacontacts before roster
self . get_metacontacts ( )
2008-02-15 23:55:21 +01:00
elif self . awaiting_answers [ id ] [ 0 ] == PEP_CONFIG :
2007-06-03 12:30:34 +02:00
conf = iq_obj . getTag ( ' pubsub ' ) . getTag ( ' configure ' )
node = conf . getAttr ( ' node ' )
form_tag = conf . getTag ( ' x ' , namespace = common . xmpp . NS_DATA )
2007-12-13 21:44:30 +01:00
if form_tag :
form = common . dataforms . ExtendForm ( node = form_tag )
2008-02-15 23:55:21 +01:00
self . dispatch ( ' PEP_CONFIG ' , ( node , form ) )
2006-09-13 18:47:58 +02:00
2006-03-19 15:54:00 +01:00
del self . awaiting_answers [ id ]
2007-01-31 12:31:07 +01:00
2006-03-19 15:54:00 +01:00
def _vCardCB ( self , con , vc ) :
''' Called when we receive a vCard
Parse the vCard and send it to plugins '''
if not vc . getTag ( ' vCard ' ) :
return
2007-01-31 12:31:07 +01:00
if not vc . getTag ( ' vCard ' ) . getNamespace ( ) == common . xmpp . NS_VCARD :
return
2007-06-03 12:04:20 +02:00
id = vc . getID ( )
2006-03-19 15:54:00 +01:00
frm_iq = vc . getFrom ( )
our_jid = gajim . get_jid_from_account ( self . name )
resource = ' '
2007-06-03 12:04:20 +02:00
if id in self . groupchat_jids :
who = self . groupchat_jids [ id ]
frm , resource = gajim . get_room_and_nick_from_fjid ( who )
del self . groupchat_jids [ id ]
elif frm_iq :
2006-03-19 15:54:00 +01:00
who = helpers . get_full_jid_from_iq ( vc )
frm , resource = gajim . get_room_and_nick_from_fjid ( who )
else :
who = frm = our_jid
2007-01-31 12:31:07 +01:00
card = vc . getChildren ( ) [ 0 ]
vcard = self . node_to_dict ( card )
photo_decoded = None
if vcard . has_key ( ' PHOTO ' ) and isinstance ( vcard [ ' PHOTO ' ] , dict ) and \
vcard [ ' PHOTO ' ] . has_key ( ' BINVAL ' ) :
photo = vcard [ ' PHOTO ' ] [ ' BINVAL ' ]
try :
photo_decoded = base64 . decodestring ( photo )
avatar_sha = sha . sha ( photo_decoded ) . hexdigest ( )
except :
2006-03-19 15:54:00 +01:00
avatar_sha = ' '
2007-01-31 12:31:07 +01:00
else :
avatar_sha = ' '
if avatar_sha :
card . getTag ( ' PHOTO ' ) . setTagData ( ' SHA ' , avatar_sha )
# Save it to file
self . save_vcard_to_hd ( who , card )
# Save the decoded avatar to a separate file too, and generate files for dbus notifications
puny_jid = helpers . sanitize_filename ( frm )
puny_nick = None
begin_path = os . path . join ( gajim . AVATAR_PATH , puny_jid )
2007-02-04 00:56:40 +01:00
frm_jid = frm
2007-01-31 12:31:07 +01:00
if frm in self . room_jids :
puny_nick = helpers . sanitize_filename ( resource )
# create folder if needed
if not os . path . isdir ( begin_path ) :
os . mkdir ( begin_path , 0700 )
begin_path = os . path . join ( begin_path , puny_nick )
2007-02-04 00:56:40 +01:00
frm_jid + = ' / ' + resource
2007-01-31 12:31:07 +01:00
if photo_decoded :
avatar_file = begin_path + ' _notif_size_colored.png '
2007-02-04 00:56:40 +01:00
if frm_jid == our_jid and avatar_sha != self . vcard_sha :
2007-01-31 12:31:07 +01:00
gajim . interface . save_avatar_files ( frm , photo_decoded , puny_nick )
2007-02-04 00:56:40 +01:00
elif frm_jid != our_jid and ( not os . path . exists ( avatar_file ) or \
not self . vcard_shas . has_key ( frm_jid ) or \
avatar_sha != self . vcard_shas [ frm_jid ] ) :
2007-01-31 12:31:07 +01:00
gajim . interface . save_avatar_files ( frm , photo_decoded , puny_nick )
2007-02-04 00:56:40 +01:00
if avatar_sha :
self . vcard_shas [ frm_jid ] = avatar_sha
elif self . vcard_shas . has_key ( frm ) :
del self . vcard_shas [ frm ]
2007-01-31 12:31:07 +01:00
else :
for ext in ( ' .jpeg ' , ' .png ' , ' _notif_size_bw.png ' ,
' _notif_size_colored.png ' ) :
path = begin_path + ext
if os . path . isfile ( path ) :
os . remove ( path )
2006-03-19 15:54:00 +01:00
2007-01-31 12:31:07 +01:00
vcard [ ' jid ' ] = frm
vcard [ ' resource ' ] = resource
2007-02-04 00:56:40 +01:00
if frm_jid == our_jid :
2007-01-31 12:31:07 +01:00
self . dispatch ( ' MYVCARD ' , vcard )
# we re-send our presence with sha if has changed and if we are
# not invisible
if self . vcard_sha == avatar_sha :
return
self . vcard_sha = avatar_sha
if STATUS_LIST [ self . connected ] == ' invisible ' :
return
sshow = helpers . get_xmpp_show ( STATUS_LIST [ self . connected ] )
p = common . xmpp . Presence ( typ = None , priority = self . priority ,
show = sshow , status = self . status )
p = self . add_sha ( p )
self . connection . send ( p )
else :
2007-06-03 12:04:20 +02:00
#('VCARD', {entry1: data, entry2: {entry21: data, ...}, ...})
2007-01-31 12:31:07 +01:00
self . dispatch ( ' VCARD ' , vcard )
2006-03-19 15:54:00 +01:00
2008-05-17 04:23:46 +02:00
# basic connection handlers used here and in zeroconf
class ConnectionHandlersBase :
2006-03-19 15:54:00 +01:00
def __init__ ( self ) :
# List of IDs we are waiting answers for {id: (type_of_request, data), }
self . awaiting_answers = { }
# List of IDs that will produce a timeout is answer doesn't arrive
# {time_of_the_timeout: (id, message to send to gui), }
2006-04-29 11:44:47 +02:00
self . awaiting_timeouts = { }
# keep the jids we auto added (transports contacts) to not send the
# SUBSCRIBED event to gui
2006-04-18 16:30:00 +02:00
self . automatically_added = [ ]
2008-05-17 04:23:46 +02:00
# keep track of sessions this connection has with other JIDs
self . sessions = { }
2008-07-26 07:28:15 +02:00
def get_sessions ( self , jid ) :
''' get all sessions for the given full jid '''
2008-05-17 04:23:46 +02:00
if not gajim . interface . is_pm_contact ( jid , self . name ) :
jid = gajim . get_jid_without_resource ( jid )
2008-07-26 07:28:15 +02:00
try :
return self . sessions [ jid ] . values ( )
except KeyError :
return [ ]
def get_or_create_session ( self , fjid , thread_id ) :
''' returns an existing session between this connection and ' jid ' , returns a
new one if none exist . '''
pm = True
jid = fjid
if not gajim . interface . is_pm_contact ( fjid , self . name ) :
pm = False
jid = gajim . get_jid_without_resource ( fjid )
2008-05-17 04:23:46 +02:00
session = self . find_session ( jid , thread_id )
if session :
return session
if pm :
2008-07-26 07:28:15 +02:00
return self . make_new_session ( fjid , thread_id , type = ' pm ' )
2008-05-17 04:23:46 +02:00
else :
2008-07-26 07:28:15 +02:00
return self . make_new_session ( fjid , thread_id )
2008-05-17 04:23:46 +02:00
def find_session ( self , jid , thread_id ) :
try :
if not thread_id :
return self . find_null_session ( jid )
else :
return self . sessions [ jid ] [ thread_id ]
except KeyError :
return None
def terminate_sessions ( self ) :
''' send termination messages and delete all active sessions '''
for jid in self . sessions :
for thread_id in self . sessions [ jid ] :
self . sessions [ jid ] [ thread_id ] . terminate ( )
self . sessions = { }
def delete_session ( self , jid , thread_id ) :
2008-05-24 01:27:08 +02:00
if not jid in self . sessions :
jid = gajim . get_jid_without_resource ( jid )
2008-05-17 04:23:46 +02:00
2008-05-24 01:27:08 +02:00
del self . sessions [ jid ] [ thread_id ]
if not self . sessions [ jid ] :
del self . sessions [ jid ]
2008-05-17 04:23:46 +02:00
def find_null_session ( self , jid ) :
''' finds all of the sessions between us and a remote jid in which we
haven ' t received a thread_id yet and returns the session that we last
sent a message to . '''
sessions = self . sessions [ jid ] . values ( )
# sessions that we haven't received a thread ID in
idless = filter ( lambda s : not s . received_thread_id , sessions )
2008-06-03 01:26:40 +02:00
# filter out everything except the default session type
p = lambda s : isinstance ( s , gajim . default_session_type )
chat_sessions = filter ( p , idless )
2008-05-17 04:23:46 +02:00
if chat_sessions :
# return the session that we last sent a message in
chat_sessions . sort ( key = lambda s : s . last_send )
return chat_sessions [ - 1 ]
else :
return None
2008-06-03 01:26:40 +02:00
def find_controlless_session ( self , jid ) :
''' find an active session that doesn ' t have a control attached '''
try :
sessions = self . sessions [ jid ] . values ( )
# filter out everything except the default session type
p = lambda s : isinstance ( s , gajim . default_session_type )
chat_sessions = filter ( p , sessions )
orphaned = filter ( lambda s : not s . control , chat_sessions )
return orphaned [ 0 ]
2008-06-10 04:58:17 +02:00
except ( KeyError , IndexError ) :
2008-06-03 01:26:40 +02:00
return None
2008-05-24 01:26:53 +02:00
def make_new_session ( self , jid , thread_id = None , type = ' chat ' , cls = None ) :
if not cls :
2008-06-03 01:26:40 +02:00
cls = gajim . default_session_type
2008-05-17 04:23:46 +02:00
2008-07-26 07:28:15 +02:00
sess = cls ( self , common . xmpp . JID ( jid ) , thread_id , type )
2008-05-17 04:23:46 +02:00
# determine if this session is a pm session
2008-07-26 07:28:15 +02:00
# if not, discard the resource so that all sessions are stored bare
2008-05-17 04:23:46 +02:00
if not type == ' pm ' :
jid = gajim . get_jid_without_resource ( jid )
if not jid in self . sessions :
self . sessions [ jid ] = { }
self . sessions [ jid ] [ sess . thread_id ] = sess
return sess
class ConnectionHandlers ( ConnectionVcard , ConnectionBytestream , ConnectionDisco , ConnectionCommands , ConnectionPubSub , ConnectionCaps , ConnectionHandlersBase ) :
def __init__ ( self ) :
ConnectionVcard . __init__ ( self )
ConnectionBytestream . __init__ ( self )
ConnectionCommands . __init__ ( self )
ConnectionPubSub . __init__ ( self )
ConnectionHandlersBase . __init__ ( self )
self . gmail_url = None
2007-12-12 09:44:46 +01:00
# keep the latest subscribed event for each jid to prevent loop when we
2008-05-17 04:23:46 +02:00
# acknowledge presences
2006-09-13 18:47:58 +02:00
self . subscribed_events = { }
2008-02-05 15:50:21 +01:00
# IDs of jabber:iq:last requests
self . last_ids = [ ]
# IDs of jabber:iq:version requests
self . version_ids = [ ]
2008-02-08 00:53:02 +01:00
# ID of urn:xmpp:ping requests
self . awaiting_xmpp_ping_id = None
2007-12-12 09:44:46 +01:00
2006-03-19 15:54:00 +01:00
try :
idle . init ( )
except :
HAS_IDLE = False
2007-12-12 09:44:46 +01:00
2008-06-03 16:15:57 +02:00
self . gmail_last_tid = None
self . gmail_last_time = None
2006-03-19 15:54:00 +01:00
def build_http_auth_answer ( self , iq_obj , answer ) :
if answer == ' yes ' :
2006-11-18 21:52:28 +01:00
self . connection . send ( iq_obj . buildReply ( ' result ' ) )
2006-03-19 15:54:00 +01:00
elif answer == ' no ' :
2006-11-18 21:52:28 +01:00
err = common . xmpp . Error ( iq_obj ,
common . xmpp . protocol . ERR_NOT_AUTHORIZED )
self . connection . send ( err )
2008-05-17 04:23:46 +02:00
2006-03-19 15:54:00 +01:00
def _HttpAuthCB ( self , con , iq_obj ) :
gajim . log . debug ( ' HttpAuthCB ' )
opt = gajim . config . get_per ( ' accounts ' , self . name , ' http_auth ' )
if opt in ( ' yes ' , ' no ' ) :
self . build_http_auth_answer ( iq_obj , opt )
else :
id = iq_obj . getTagAttr ( ' confirm ' , ' id ' )
method = iq_obj . getTagAttr ( ' confirm ' , ' method ' )
url = iq_obj . getTagAttr ( ' confirm ' , ' url ' )
2007-06-03 12:04:20 +02:00
msg = iq_obj . getTagData ( ' body ' ) # In case it's a message with a body
self . dispatch ( ' HTTP_AUTH ' , ( method , url , id , iq_obj , msg ) ) ;
2006-03-19 15:54:00 +01:00
raise common . xmpp . NodeProcessed
def _ErrorCB ( self , con , iq_obj ) :
2006-11-18 21:52:28 +01:00
gajim . log . debug ( ' ErrorCB ' )
2008-02-05 15:50:21 +01:00
jid_from = helpers . get_full_jid_from_iq ( iq_obj )
jid_stripped , resource = gajim . get_room_and_nick_from_fjid ( jid_from )
id = unicode ( iq_obj . getID ( ) )
if id in self . version_ids :
2006-11-18 21:52:28 +01:00
self . dispatch ( ' OS_INFO ' , ( jid_stripped , resource , ' ' , ' ' ) )
2008-02-05 15:50:21 +01:00
self . version_ids . remove ( id )
return
if id in self . last_ids :
self . dispatch ( ' LAST_STATUS_TIME ' , ( jid_stripped , resource , - 1 , ' ' ) )
self . last_ids . remove ( id )
2006-11-18 21:52:28 +01:00
return
2008-02-08 00:53:02 +01:00
if id == self . awaiting_xmpp_ping_id :
self . awaiting_xmpp_ping_id = None
2006-11-18 21:52:28 +01:00
errmsg = iq_obj . getErrorMsg ( )
2006-03-19 15:54:00 +01:00
errcode = iq_obj . getErrorCode ( )
self . dispatch ( ' ERROR_ANSWER ' , ( id , jid_from , errmsg , errcode ) )
2008-05-02 04:32:28 +02:00
2006-03-19 15:54:00 +01:00
def _PrivateCB ( self , con , iq_obj ) :
'''
2007-08-09 17:39:18 +02:00
Private Data ( XEP 048 and 049 )
2006-03-19 15:54:00 +01:00
'''
gajim . log . debug ( ' PrivateCB ' )
query = iq_obj . getTag ( ' query ' )
storage = query . getTag ( ' storage ' )
if storage :
ns = storage . getNamespace ( )
if ns == ' storage:bookmarks ' :
# Bookmarked URLs and Conferences
2007-08-09 17:39:18 +02:00
# http://www.xmpp.org/extensions/xep-0048.html
2006-03-19 15:54:00 +01:00
confs = storage . getTags ( ' conference ' )
for conf in confs :
autojoin_val = conf . getAttr ( ' autojoin ' )
if autojoin_val is None : # not there (it's optional)
autojoin_val = False
2007-08-09 17:39:18 +02:00
minimize_val = conf . getAttr ( ' minimize ' )
if minimize_val is None : # not there (it's optional)
minimize_val = False
2006-05-10 18:25:57 +02:00
print_status = conf . getTagData ( ' print_status ' )
if not print_status :
print_status = conf . getTagData ( ' show_status ' )
2006-03-19 15:54:00 +01:00
bm = { ' name ' : conf . getAttr ( ' name ' ) ,
' jid ' : conf . getAttr ( ' jid ' ) ,
' autojoin ' : autojoin_val ,
2007-08-09 17:39:18 +02:00
' minimize ' : minimize_val ,
2006-03-19 15:54:00 +01:00
' password ' : conf . getTagData ( ' password ' ) ,
2006-05-07 23:44:57 +02:00
' nick ' : conf . getTagData ( ' nick ' ) ,
2006-05-10 18:25:57 +02:00
' print_status ' : print_status }
2006-03-19 15:54:00 +01:00
self . bookmarks . append ( bm )
self . dispatch ( ' BOOKMARKS ' , self . bookmarks )
elif ns == ' gajim:prefs ' :
# Preferences data
2007-08-09 17:39:18 +02:00
# http://www.xmpp.org/extensions/xep-0049.html
2006-03-19 15:54:00 +01:00
#TODO: implement this
pass
2006-11-18 21:52:28 +01:00
elif ns == ' storage:rosternotes ' :
# Annotations
# http://www.xmpp.org/extensions/xep-0145.html
notes = storage . getTags ( ' note ' )
for note in notes :
jid = note . getAttr ( ' jid ' )
annotation = note . getData ( )
self . annotations [ jid ] = annotation
2006-03-19 15:54:00 +01:00
def _rosterSetCB ( self , con , iq_obj ) :
gajim . log . debug ( ' rosterSetCB ' )
for item in iq_obj . getTag ( ' query ' ) . getChildren ( ) :
2007-12-12 09:44:46 +01:00
jid = helpers . parse_jid ( item . getAttr ( ' jid ' ) )
2006-03-19 15:54:00 +01:00
name = item . getAttr ( ' name ' )
2007-12-12 09:44:46 +01:00
sub = item . getAttr ( ' subscription ' )
ask = item . getAttr ( ' ask ' )
2006-03-19 15:54:00 +01:00
groups = [ ]
for group in item . getTags ( ' group ' ) :
groups . append ( group . getData ( ) )
self . dispatch ( ' ROSTER_INFO ' , ( jid , name , sub , ask , groups ) )
raise common . xmpp . NodeProcessed
def _VersionCB ( self , con , iq_obj ) :
2008-08-01 12:27:38 +02:00
if not self . connection :
return
2006-03-19 15:54:00 +01:00
gajim . log . debug ( ' VersionCB ' )
iq_obj = iq_obj . buildReply ( ' result ' )
qp = iq_obj . getTag ( ' query ' )
qp . setTagData ( ' name ' , ' Gajim ' )
qp . setTagData ( ' version ' , gajim . version )
send_os = gajim . config . get ( ' send_os_info ' )
if send_os :
qp . setTagData ( ' os ' , helpers . get_os_info ( ) )
self . connection . send ( iq_obj )
raise common . xmpp . NodeProcessed
2008-02-08 00:53:02 +01:00
2006-03-19 15:54:00 +01:00
def _LastCB ( self , con , iq_obj ) :
2008-08-26 12:07:53 +02:00
if not self . connection :
return
2008-02-08 00:53:02 +01:00
gajim . log . debug ( ' LastCB ' )
2006-03-19 15:54:00 +01:00
iq_obj = iq_obj . buildReply ( ' result ' )
qp = iq_obj . getTag ( ' query ' )
if not HAS_IDLE :
qp . attrs [ ' seconds ' ] = ' 0 ' ;
else :
qp . attrs [ ' seconds ' ] = idle . getIdleSec ( )
self . connection . send ( iq_obj )
raise common . xmpp . NodeProcessed
2008-02-08 00:53:02 +01:00
2006-03-19 15:54:00 +01:00
def _LastResultCB ( self , con , iq_obj ) :
gajim . log . debug ( ' LastResultCB ' )
qp = iq_obj . getTag ( ' query ' )
seconds = qp . getAttr ( ' seconds ' )
status = qp . getData ( )
try :
seconds = int ( seconds )
except :
return
2007-08-09 17:39:18 +02:00
id = iq_obj . getID ( )
if id in self . groupchat_jids :
who = self . groupchat_jids [ id ]
del self . groupchat_jids [ id ]
else :
who = helpers . get_full_jid_from_iq ( iq_obj )
2008-02-05 15:50:21 +01:00
if id in self . last_ids :
self . last_ids . remove ( id )
2006-03-19 15:54:00 +01:00
jid_stripped , resource = gajim . get_room_and_nick_from_fjid ( who )
self . dispatch ( ' LAST_STATUS_TIME ' , ( jid_stripped , resource , seconds , status ) )
2008-02-08 00:53:02 +01:00
2006-03-19 15:54:00 +01:00
def _VersionResultCB ( self , con , iq_obj ) :
gajim . log . debug ( ' VersionResultCB ' )
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 ( )
2007-08-09 17:39:18 +02:00
id = iq_obj . getID ( )
if id in self . groupchat_jids :
who = self . groupchat_jids [ id ]
del self . groupchat_jids [ id ]
else :
who = helpers . get_full_jid_from_iq ( iq_obj )
2006-03-19 15:54:00 +01:00
jid_stripped , resource = gajim . get_room_and_nick_from_fjid ( who )
2008-02-05 15:50:21 +01:00
if id in self . version_ids :
self . version_ids . remove ( id )
2006-03-19 15:54:00 +01:00
self . dispatch ( ' OS_INFO ' , ( jid_stripped , resource , client_info , os_info ) )
2006-09-13 18:47:58 +02:00
def _TimeCB ( self , con , iq_obj ) :
gajim . log . debug ( ' TimeCB ' )
iq_obj = iq_obj . buildReply ( ' result ' )
qp = iq_obj . getTag ( ' query ' )
2007-08-09 17:39:18 +02:00
qp . setTagData ( ' utc ' , strftime ( ' % Y % m %d T % T ' , gmtime ( ) ) )
2007-12-13 09:37:20 +01:00
qp . setTagData ( ' tz ' , helpers . decode_string ( tzname [ daylight ] ) )
2007-12-12 09:44:46 +01:00
qp . setTagData ( ' display ' , helpers . decode_string ( strftime ( ' %c ' ,
localtime ( ) ) ) )
2006-09-13 18:47:58 +02:00
self . connection . send ( iq_obj )
raise common . xmpp . NodeProcessed
2006-12-28 17:27:41 +01:00
def _TimeRevisedCB ( self , con , iq_obj ) :
gajim . log . debug ( ' TimeRevisedCB ' )
iq_obj = iq_obj . buildReply ( ' result ' )
2007-08-09 17:39:18 +02:00
qp = iq_obj . setTag ( ' time ' ,
2007-12-12 09:44:46 +01:00
namespace = common . xmpp . NS_TIME_REVISED )
2007-08-09 17:39:18 +02:00
qp . setTagData ( ' utc ' , strftime ( ' % Y- % m- %d T % TZ ' , gmtime ( ) ) )
zone = - ( timezone , altzone ) [ daylight ] / 60
tzo = ( zone / 60 , abs ( zone % 60 ) )
qp . setTagData ( ' tzo ' , ' %+03d : %02d ' % ( tzo ) )
2006-12-28 17:27:41 +01:00
self . connection . send ( iq_obj )
raise common . xmpp . NodeProcessed
2006-03-19 15:54:00 +01:00
def _gMailNewMailCB ( self , con , gm ) :
''' Called when we get notified of new mail messages in gmail account '''
if not gm . getTag ( ' new-mail ' ) :
return
if gm . getTag ( ' new-mail ' ) . getNamespace ( ) == common . xmpp . NS_GMAILNOTIFY :
# we'll now ask the server for the exact number of new messages
jid = gajim . get_jid_from_account ( self . name )
gajim . log . debug ( ' Got notification of new gmail e-mail on %s . Asking the server for more info. ' % jid )
iq = common . xmpp . Iq ( typ = ' get ' )
2008-06-03 16:15:57 +02:00
iq . setID ( self . connection . getAnID ( ) )
2006-03-19 15:54:00 +01:00
query = iq . setTag ( ' query ' )
query . setNamespace ( common . xmpp . NS_GMAILNOTIFY )
2008-06-03 16:15:57 +02:00
# we want only be notified about newer mails
if self . gmail_last_tid :
query . setAttr ( ' newer-than-tid ' , self . gmail_last_tid )
if self . gmail_last_time :
query . setAttr ( ' newer-than-time ' , self . gmail_last_time )
2006-03-19 15:54:00 +01:00
self . connection . send ( iq )
raise common . xmpp . NodeProcessed
def _gMailQueryCB ( self , con , gm ) :
''' Called when we receive results from Querying the server for mail messages in gmail account '''
if not gm . getTag ( ' mailbox ' ) :
return
2007-08-09 17:39:18 +02:00
self . gmail_url = gm . getTag ( ' mailbox ' ) . getAttr ( ' url ' )
2006-03-19 15:54:00 +01:00
if gm . getTag ( ' mailbox ' ) . getNamespace ( ) == common . xmpp . NS_GMAILNOTIFY :
newmsgs = gm . getTag ( ' mailbox ' ) . getAttr ( ' total-matched ' )
if newmsgs != ' 0 ' :
# there are new messages
2006-07-17 21:30:53 +02:00
gmail_messages_list = [ ]
if gm . getTag ( ' mailbox ' ) . getTag ( ' mail-thread-info ' ) :
gmail_messages = gm . getTag ( ' mailbox ' ) . getTags ( ' mail-thread-info ' )
for gmessage in gmail_messages :
2008-06-03 16:15:57 +02:00
unread_senders = [ ]
for sender in gmessage . getTag ( ' senders ' ) . getTags ( ' sender ' ) :
if sender . getAttr ( ' unread ' ) != ' 1 ' :
continue
if sender . getAttr ( ' name ' ) :
unread_senders . append ( sender . getAttr ( ' name ' ) + ' < ' + \
sender . getAttr ( ' address ' ) + ' > ' )
else :
unread_senders . append ( sender . getAttr ( ' address ' ) )
if not unread_senders :
2006-11-18 21:52:28 +01:00
continue
2006-07-17 21:30:53 +02:00
gmail_subject = gmessage . getTag ( ' subject ' ) . getData ( )
gmail_snippet = gmessage . getTag ( ' snippet ' ) . getData ( )
2008-06-03 16:15:57 +02:00
tid = int ( gmessage . getAttr ( ' tid ' ) )
if not self . gmail_last_tid or tid > self . gmail_last_tid :
self . gmail_last_tid = tid
2006-07-17 21:30:53 +02:00
gmail_messages_list . append ( { \
2008-06-03 16:15:57 +02:00
' From ' : unread_senders , \
2006-07-17 21:30:53 +02:00
' Subject ' : gmail_subject , \
2008-06-03 16:15:57 +02:00
' Snippet ' : gmail_snippet , \
' url ' : gmessage . getAttr ( ' url ' ) , \
' participation ' : gmessage . getAttr ( ' participation ' ) , \
' messages ' : gmessage . getAttr ( ' messages ' ) , \
' date ' : gmessage . getAttr ( ' date ' ) } )
self . gmail_last_time = int ( gm . getTag ( ' mailbox ' ) . getAttr (
' result-time ' ) )
2006-03-19 15:54:00 +01:00
jid = gajim . get_jid_from_account ( self . name )
gajim . log . debug ( ( ' You have %s new gmail e-mails on %s . ' ) % ( newmsgs , jid ) )
2006-07-17 21:30:53 +02:00
self . dispatch ( ' GMAIL_NOTIFY ' , ( jid , newmsgs , gmail_messages_list ) )
2006-03-19 15:54:00 +01:00
raise common . xmpp . NodeProcessed
def _messageCB ( self , con , msg ) :
''' Called when we receive a message '''
2008-05-13 03:59:10 +02:00
gajim . log . debug ( ' MessageCB ' )
2007-12-12 09:44:46 +01:00
frm = helpers . get_full_jid_from_iq ( msg )
2008-05-18 19:35:00 +02:00
# check if the message is pubsub#event
if msg . getTag ( ' event ' ) is not None :
2008-07-11 14:34:43 +02:00
if msg . getTag ( ' error ' ) is None :
self . _pubsubEventCB ( con , msg )
2008-05-18 19:35:00 +02:00
return
# check if the message is a XEP-0070 confirmation request
if msg . getTag ( ' confirm ' , namespace = common . xmpp . NS_HTTP_AUTH ) :
self . _HttpAuthCB ( con , msg )
return
# invitations
invite = None
encTag = msg . getTag ( ' x ' , namespace = common . xmpp . NS_ENCRYPTED )
if not encTag :
invite = msg . getTag ( ' x ' , namespace = common . xmpp . NS_MUC_USER )
if invite and not invite . getTag ( ' invite ' ) :
invite = None
# FIXME: Msn transport (CMSN1.2.1 and PyMSN0.10) do NOT RECOMMENDED
# invitation
# stanza (MUC XEP) remove in 2007, as we do not do NOT RECOMMENDED
xtags = msg . getTags ( ' x ' )
for xtag in xtags :
if xtag . getNamespace ( ) == common . xmpp . NS_CONFERENCE and not invite :
room_jid = xtag . getAttr ( ' jid ' )
is_continued = False
if xtag . getTag ( ' continue ' ) :
is_continued = True
self . dispatch ( ' GC_INVITATION ' , ( room_jid , frm , ' ' , None ,
is_continued ) )
return
2007-12-12 09:44:46 +01:00
mtype = msg . getType ( )
thread_id = msg . getThread ( )
if not mtype :
mtype = ' normal '
2006-03-19 15:54:00 +01:00
msgtxt = msg . getBody ( )
2008-04-07 00:21:46 +02:00
2006-03-19 15:54:00 +01:00
jid = helpers . get_jid_from_iq ( msg )
2008-04-07 00:21:46 +02:00
2008-05-24 01:26:53 +02:00
encrypted = False
2008-05-24 01:27:08 +02:00
xep_200_encrypted = msg . getTag ( ' c ' , namespace = common . xmpp . NS_STANZA_CRYPTO )
2008-06-24 03:17:02 +02:00
2008-06-03 03:13:30 +02:00
if mtype != ' groupchat ' :
2008-05-24 01:26:53 +02:00
session = self . get_or_create_session ( frm , thread_id )
if thread_id and not session . received_thread_id :
session . received_thread_id = True
2008-05-25 23:28:32 +02:00
session . last_receive = time_time ( )
2008-05-24 01:26:53 +02:00
# check if the message is a XEP-0020 feature negotiation request
if msg . getTag ( ' feature ' , namespace = common . xmpp . NS_FEATURE ) :
if gajim . HAVE_PYCRYPTO :
2008-06-21 21:12:47 +02:00
feature = msg . getTag ( name = ' feature ' , namespace = common . xmpp . NS_FEATURE )
form = common . xmpp . DataForm ( node = feature . getTag ( ' x ' ) )
if form [ ' FORM_TYPE ' ] == ' urn:xmpp:ssn ' :
session . handle_negotiation ( form )
else :
reply = msg . buildReply ( )
reply . setType ( ' error ' )
reply . addChild ( feature )
err = common . xmpp . ErrorNode ( ' service-unavailable ' , typ = ' cancel ' )
reply . addChild ( node = err )
con . send ( reply )
raise common . xmpp . NodeProcessed
2008-05-24 01:26:53 +02:00
return
2008-06-21 21:12:47 +02:00
2008-05-24 01:26:53 +02:00
if msg . getTag ( ' init ' , namespace = common . xmpp . NS_ESESSION_INIT ) :
2008-06-21 21:12:47 +02:00
init = msg . getTag ( name = ' init ' , namespace = common . xmpp . NS_ESESSION_INIT )
form = common . xmpp . DataForm ( node = init . getTag ( ' x ' ) )
session . handle_negotiation ( form )
raise common . xmpp . NodeProcessed
2008-05-24 01:26:53 +02:00
tim = msg . getTimestamp ( )
tim = helpers . datetime_tuple ( tim )
tim = localtime ( timegm ( tim ) )
2008-05-24 01:27:08 +02:00
if xep_200_encrypted :
2008-05-24 01:26:53 +02:00
encrypted = True
try :
msg = session . decrypt_stanza ( msg )
2008-05-24 01:27:08 +02:00
msgtxt = msg . getBody ( )
2008-05-24 01:26:53 +02:00
except :
self . dispatch ( ' FAILED_DECRYPT ' , ( frm , tim , session ) )
2008-07-14 02:25:53 +02:00
# Receipt requested
# TODO: We shouldn't answer if we're invisible!
contact = gajim . contacts . get_contact ( self . name ,
common . gajim . get_room_and_nick_from_fjid ( frm ) [ 0 ] )
if msg . getTag ( ' request ' , namespace = common . xmpp . NS_RECEIPTS ) \
and gajim . config . get_per ( ' accounts ' , self . name ,
' answer_receipts ' ) and contact and contact . sub \
not in ( u ' to ' , u ' none ' ) :
receipt = common . xmpp . Message ( to = jid , typ = ' chat ' )
receipt . setID ( msg . getID ( ) )
receipt . setTag ( ' received ' ,
namespace = ' urn:xmpp:receipts ' )
if thread_id :
receipt . setThread ( thread_id )
con . send ( receipt )
2008-07-18 22:24:34 +02:00
# We got our message's receipt
if msg . getTag ( ' received ' , namespace = common . xmpp . NS_RECEIPTS ) \
and session . control and gajim . config . get_per ( ' accounts ' ,
self . name , ' request_receipt ' ) :
session . control . conv_textview . hide_xep0184_warning (
msg . getID ( ) )
2008-05-24 01:26:53 +02:00
addressTag = msg . getTag ( ' addresses ' , namespace = common . xmpp . NS_ADDRESS )
2007-08-09 17:39:18 +02:00
# Be sure it comes from one of our resource, else ignore address element
if addressTag and jid == gajim . get_jid_from_account ( self . name ) :
address = addressTag . getTag ( ' address ' , attrs = { ' type ' : ' ofrom ' } )
if address :
frm = address . getAttr ( ' jid ' )
jid = gajim . get_jid_without_resource ( frm )
2008-04-07 00:21:46 +02:00
2007-12-28 19:49:28 +01:00
if encTag and self . USE_GPG :
2006-03-19 15:54:00 +01:00
encmsg = encTag . getData ( )
2007-12-12 09:44:46 +01:00
2006-03-19 15:54:00 +01:00
keyID = gajim . config . get_per ( ' accounts ' , self . name , ' keyid ' )
if keyID :
decmsg = self . gpg . decrypt ( encmsg , keyID )
2007-12-12 09:44:46 +01:00
# \x00 chars are not allowed in C (so in GTK)
2008-04-07 00:21:46 +02:00
msgtxt = decmsg . replace ( ' \x00 ' , ' ' )
encrypted = True
2006-03-19 15:54:00 +01:00
if mtype == ' error ' :
2008-05-24 01:27:08 +02:00
self . dispatch_error_message ( msg , msgtxt , session , frm , tim )
2006-03-19 15:54:00 +01:00
elif mtype == ' groupchat ' :
2008-05-24 01:27:08 +02:00
self . dispatch_gc_message ( msg , frm , msgtxt , jid , tim )
2008-04-07 00:21:46 +02:00
elif invite is not None :
self . dispatch_invite_message ( invite , frm )
2008-04-11 05:52:45 +02:00
else :
2008-04-15 07:32:45 +02:00
if isinstance ( session , ChatControlSession ) :
2008-05-24 01:27:08 +02:00
session . received ( frm , msgtxt , tim , encrypted , msg )
2006-03-19 15:54:00 +01:00
else :
2008-04-15 07:32:45 +02:00
session . received ( msg )
2008-05-11 15:17:28 +02:00
# END messageCB
2008-05-11 03:19:59 +02:00
2008-04-07 00:21:46 +02:00
# process and dispatch an error message
2008-05-24 01:27:08 +02:00
def dispatch_error_message ( self , msg , msgtxt , session , frm , tim ) :
2008-05-13 03:59:10 +02:00
error_msg = msg . getErrorMsg ( )
2008-04-07 00:21:46 +02:00
if not error_msg :
error_msg = msgtxt
msgtxt = None
2008-05-24 01:27:08 +02:00
subject = msg . getSubject ( )
2008-04-07 00:21:46 +02:00
if session . is_loggable ( ) :
try :
2008-05-13 03:59:10 +02:00
gajim . logger . write ( ' error ' , frm , error_msg , tim = tim ,
subject = subject )
2008-04-07 00:21:46 +02:00
except exceptions . PysqliteOperationalError , e :
self . dispatch ( ' ERROR ' , ( _ ( ' Disk Write Error ' ) , str ( e ) ) )
2008-05-13 03:59:10 +02:00
self . dispatch ( ' MSGERROR ' , ( frm , msg . getErrorCode ( ) , error_msg , msgtxt ,
tim , session ) )
2008-04-07 00:21:46 +02:00
# process and dispatch a groupchat message
2008-05-24 01:27:08 +02:00
def dispatch_gc_message ( self , msg , frm , msgtxt , jid , tim ) :
2008-04-07 00:21:46 +02:00
has_timestamp = bool ( msg . timestamp )
2008-05-24 01:27:08 +02:00
subject = msg . getSubject ( )
2008-05-13 03:59:10 +02:00
if subject is not None :
2008-04-07 00:21:46 +02:00
self . dispatch ( ' GC_SUBJECT ' , ( frm , subject , msgtxt , has_timestamp ) )
2008-05-13 03:59:10 +02:00
return
2008-04-07 00:21:46 +02:00
2008-05-13 03:59:10 +02:00
statusCode = msg . getStatusCode ( )
2008-04-07 00:21:46 +02:00
2008-05-13 03:59:10 +02:00
if not msg . getTag ( ' body ' ) : # no <body>
# It could be a config change. See
# http://www.xmpp.org/extensions/xep-0045.html#roomconfig-notify
if msg . getTag ( ' x ' ) :
if statusCode != [ ] :
self . dispatch ( ' GC_CONFIG_CHANGE ' , ( jid , statusCode ) )
return
2008-04-07 00:21:46 +02:00
2008-05-13 03:59:10 +02:00
# Ignore message from room in which we are not
if not self . last_history_time . has_key ( jid ) :
return
2008-04-07 00:21:46 +02:00
2008-05-13 03:59:10 +02:00
self . dispatch ( ' GC_MSG ' , ( frm , msgtxt , tim , has_timestamp , msg . getXHTML ( ) ,
statusCode ) )
2008-04-07 00:21:46 +02:00
2008-05-13 03:59:10 +02:00
no_log_for = gajim . config . get_per ( ' accounts ' , self . name , ' no_log_for ' )
2008-04-07 00:21:46 +02:00
2008-05-13 03:59:10 +02:00
if not no_log_for :
no_log_for = ' '
no_log_for = no_log_for . split ( )
tim_int = int ( float ( mktime ( tim ) ) )
if self . name not in no_log_for and jid not in no_log_for and not \
tim_int < = self . last_history_time [ jid ] and msgtxt and frm . find ( ' / ' ) > = 0 :
# if frm.find('/') < 0, it means message comes from room itself
# usually it hold description and can be send at each connection
# so don't store it in logs
try :
gajim . logger . write ( ' gc_msg ' , frm , msgtxt , tim = tim )
except exceptions . PysqliteOperationalError , e :
self . dispatch ( ' ERROR ' , ( _ ( ' Disk Write Error ' ) , str ( e ) ) )
2008-04-07 00:21:46 +02:00
2008-04-11 05:52:45 +02:00
def dispatch_invite_message ( self , invite , frm ) :
2008-04-07 00:21:46 +02:00
item = invite . getTag ( ' invite ' )
jid_from = item . getAttr ( ' from ' )
reason = item . getTagData ( ' reason ' )
item = invite . getTag ( ' password ' )
password = invite . getTagData ( ' password ' )
is_continued = False
if invite . getTag ( ' invite ' ) . getTag ( ' continue ' ) :
is_continued = True
self . dispatch ( ' GC_INVITATION ' , ( frm , jid_from , reason , password ,
is_continued ) )
2006-07-21 15:52:36 +02:00
def _pubsubEventCB ( self , con , msg ) :
''' Called when we receive <message/> with pubsub event. '''
# TODO: Logging? (actually services where logging would be useful, should
# TODO: allow to access archives remotely...)
2007-03-29 21:40:50 +02:00
jid = helpers . get_full_jid_from_iq ( msg )
2006-07-21 15:52:36 +02:00
event = msg . getTag ( ' event ' )
2007-03-26 00:16:48 +02:00
# XEP-0107: User Mood
2007-03-28 23:18:16 +02:00
items = event . getTag ( ' items ' , { ' node ' : common . xmpp . NS_MOOD } )
2007-03-26 00:16:48 +02:00
if items : pep . user_mood ( items , self . name , jid )
# XEP-0118: User Tune
2007-03-28 23:18:16 +02:00
items = event . getTag ( ' items ' , { ' node ' : common . xmpp . NS_TUNE } )
2007-03-26 00:16:48 +02:00
if items : pep . user_tune ( items , self . name , jid )
# XEP-0080: User Geolocation
2007-03-28 23:18:16 +02:00
items = event . getTag ( ' items ' , { ' node ' : common . xmpp . NS_GEOLOC } )
2007-03-26 00:16:48 +02:00
if items : pep . user_geoloc ( items , self . name , jid )
2007-03-28 23:18:16 +02:00
# XEP-0108: User Activity
items = event . getTag ( ' items ' , { ' node ' : common . xmpp . NS_ACTIVITY } )
if items : pep . user_activity ( items , self . name , jid )
2008-05-05 23:55:59 +02:00
# XEP-0172: User Nickname
items = event . getTag ( ' items ' , { ' node ' : common . xmpp . NS_NICK } )
if items : pep . user_nickname ( items , self . name , jid )
2007-03-26 00:16:48 +02:00
2006-07-21 15:52:36 +02:00
items = event . getTag ( ' items ' )
if items is None : return
for item in items . getTags ( ' item ' ) :
2007-08-09 17:39:18 +02:00
entry = item . getTag ( ' entry ' )
if entry is not None :
# for each entry in feed (there shouldn't be more than one,
# but to be sure...
self . dispatch ( ' ATOM_ENTRY ' , ( atom . OldEntry ( node = entry ) , ) )
2006-07-21 15:52:36 +02:00
continue
# unknown type... probably user has another client who understands that event
raise common . xmpp . NodeProcessed
2006-03-19 15:54:00 +01:00
def _presenceCB ( self , con , prs ) :
''' Called when we receive a presence '''
ptype = prs . getType ( )
if ptype == ' available ' :
ptype = None
2007-06-03 12:04:20 +02:00
rfc_types = ( ' unavailable ' , ' error ' , ' subscribe ' , ' subscribed ' , ' unsubscribe ' , ' unsubscribed ' )
if ptype and not ptype in rfc_types :
ptype = None
2006-03-19 15:54:00 +01:00
gajim . log . debug ( ' PresenceCB: %s ' % ptype )
2006-09-13 18:47:58 +02:00
try :
who = helpers . get_full_jid_from_iq ( prs )
except :
if prs . getTag ( ' error ' ) . getTag ( ' jid-malformed ' ) :
2007-12-12 09:44:46 +01:00
# wrong jid, we probably tried to change our nick in a room to a non
# valid one
2006-09-13 18:47:58 +02:00
who = str ( prs . getFrom ( ) )
jid_stripped , resource = gajim . get_room_and_nick_from_fjid ( who )
2006-11-18 21:52:28 +01:00
self . dispatch ( ' GC_MSG ' , ( jid_stripped ,
2007-12-12 09:44:46 +01:00
_ ( ' Nickname not allowed: %s ' ) % resource , None , False , None , [ ] ) )
2006-09-13 18:47:58 +02:00
return
2006-04-18 16:30:00 +02:00
jid_stripped , resource = gajim . get_room_and_nick_from_fjid ( who )
2006-04-01 20:16:06 +02:00
timestamp = None
2006-03-19 15:54:00 +01:00
is_gc = False # is it a GC presence ?
sigTag = None
2007-03-11 21:14:53 +01:00
ns_muc_user_x = None
2006-04-29 11:44:47 +02:00
avatar_sha = None
2007-08-09 17:39:18 +02:00
# XEP-0172 User Nickname
2006-09-13 18:47:58 +02:00
user_nick = prs . getTagData ( ' nick ' )
if not user_nick :
user_nick = ' '
2007-06-03 12:04:20 +02:00
contact_nickname = None
2006-04-18 16:30:00 +02:00
transport_auto_auth = False
2006-03-19 15:54:00 +01:00
xtags = prs . getTags ( ' x ' )
for x in xtags :
2006-06-01 17:23:38 +02:00
namespace = x . getNamespace ( )
if namespace . startswith ( common . xmpp . NS_MUC ) :
2006-03-19 15:54:00 +01:00
is_gc = True
2007-03-11 21:14:53 +01:00
if namespace == common . xmpp . NS_MUC_USER and x . getTag ( ' destroy ' ) :
ns_muc_user_x = x
elif namespace == common . xmpp . NS_SIGNED :
2006-03-19 15:54:00 +01:00
sigTag = x
2007-03-11 21:14:53 +01:00
elif namespace == common . xmpp . NS_VCARD_UPDATE :
2006-03-19 15:54:00 +01:00
avatar_sha = x . getTagData ( ' photo ' )
2007-06-03 12:04:20 +02:00
contact_nickname = x . getTagData ( ' nickname ' )
2007-03-11 21:14:53 +01:00
elif namespace == common . xmpp . NS_DELAY :
2007-08-09 17:39:18 +02:00
# XEP-0091
2006-04-01 20:16:06 +02:00
tim = prs . getTimestamp ( )
2007-08-09 17:39:18 +02:00
tim = helpers . datetime_tuple ( tim )
timestamp = localtime ( timegm ( tim ) )
2007-03-11 21:14:53 +01:00
elif namespace == ' http://delx.cjb.net/protocol/roster-subsync ' :
2006-04-29 11:44:47 +02:00
# see http://trac.gajim.org/ticket/326
agent = gajim . get_server_from_jid ( jid_stripped )
if self . connection . getRoster ( ) . getItem ( agent ) : # to be sure it's a transport contact
2006-04-18 16:30:00 +02:00
transport_auto_auth = True
2006-03-19 15:54:00 +01:00
2006-04-20 14:46:51 +02:00
no_log_for = gajim . config . get_per ( ' accounts ' , self . name ,
' no_log_for ' ) . split ( )
2006-09-13 18:47:58 +02:00
status = prs . getStatus ( ) or ' '
2006-03-19 15:54:00 +01:00
show = prs . getShow ( )
if not show in STATUS_LIST :
show = ' ' # We ignore unknown show
if not ptype and not show :
show = ' online '
elif ptype == ' unavailable ' :
show = ' offline '
prio = prs . getPriority ( )
try :
prio = int ( prio )
except :
prio = 0
keyID = ' '
2008-08-11 17:30:24 +02:00
if sigTag and self . USE_GPG and ptype != ' error ' :
# error presences contain our own signature
2007-12-12 09:44:46 +01:00
# verify
2006-03-19 15:54:00 +01:00
sigmsg = sigTag . getData ( )
keyID = self . gpg . verify ( status , sigmsg )
if is_gc :
if ptype == ' error ' :
errmsg = prs . getError ( )
errcode = prs . getErrorCode ( )
2007-08-09 17:39:18 +02:00
room_jid , nick = gajim . get_room_and_nick_from_fjid ( who )
2006-03-19 15:54:00 +01:00
if errcode == ' 502 ' : # Internal Timeout:
self . dispatch ( ' NOTIFY ' , ( jid_stripped , ' error ' , errmsg , resource ,
2007-06-03 12:04:20 +02:00
prio , keyID , timestamp , None ) )
2006-03-19 15:54:00 +01:00
elif errcode == ' 401 ' : # password required to join
2007-08-09 17:39:18 +02:00
self . dispatch ( ' GC_PASSWORD_REQUIRED ' , ( room_jid , nick ) )
2006-03-19 15:54:00 +01:00
elif errcode == ' 403 ' : # we are banned
2006-11-18 21:52:28 +01:00
self . dispatch ( ' ERROR ' , ( _ ( ' Unable to join group chat ' ) ,
2007-08-09 17:39:18 +02:00
_ ( ' You are banned from group chat %s . ' ) % room_jid ) )
2006-11-18 21:52:28 +01:00
elif errcode == ' 404 ' : # group chat does not exist
self . dispatch ( ' ERROR ' , ( _ ( ' Unable to join group chat ' ) ,
2007-08-09 17:39:18 +02:00
_ ( ' Group chat %s does not exist. ' ) % room_jid ) )
2006-03-19 15:54:00 +01:00
elif errcode == ' 405 ' :
2006-11-18 21:52:28 +01:00
self . dispatch ( ' ERROR ' , ( _ ( ' Unable to join group chat ' ) ,
_ ( ' Group chat creation is restricted. ' ) ) )
2006-03-19 15:54:00 +01:00
elif errcode == ' 406 ' :
2006-11-18 21:52:28 +01:00
self . dispatch ( ' ERROR ' , ( _ ( ' Unable to join group chat ' ) ,
2007-08-09 17:39:18 +02:00
_ ( ' Your registered nickname must be used in group chat %s . ' ) \
% room_jid ) )
2006-03-19 15:54:00 +01:00
elif errcode == ' 407 ' :
2006-11-18 21:52:28 +01:00
self . dispatch ( ' ERROR ' , ( _ ( ' Unable to join group chat ' ) ,
2007-08-09 17:39:18 +02:00
_ ( ' You are not in the members list in groupchat %s . ' ) % \
room_jid ) )
2006-03-19 15:54:00 +01:00
elif errcode == ' 409 ' : # nick conflict
# the jid_from in this case is FAKE JID: room_jid/nick
# resource holds the bad nick so propose a new one
proposed_nickname = resource + \
gajim . config . get ( ' gc_proposed_nick_char ' )
room_jid = gajim . get_room_from_fjid ( who )
2006-11-18 21:52:28 +01:00
self . dispatch ( ' ASK_NEW_NICK ' , ( room_jid , _ ( ' Unable to join group chat ' ) ,
2007-08-09 17:39:18 +02:00
_ ( ' Your desired nickname in group chat %s is in use or registered by another occupant. \n Please specify another nickname below: ' ) % room_jid , proposed_nickname ) )
2006-03-19 15:54:00 +01:00
else : # print in the window the error
self . dispatch ( ' ERROR_ANSWER ' , ( ' ' , jid_stripped ,
errmsg , errcode ) )
if not ptype or ptype == ' unavailable ' :
if gajim . config . get ( ' log_contact_status_changes ' ) and self . name \
2007-01-31 12:31:07 +01:00
not in no_log_for and jid_stripped not in no_log_for :
2007-06-03 12:04:20 +02:00
gc_c = gajim . contacts . get_gc_contact ( self . name , jid_stripped ,
resource )
2006-09-13 18:47:58 +02:00
st = status or ' '
if gc_c :
jid = gc_c . jid
else :
jid = prs . getJid ( )
if jid :
# we know real jid, save it in db
st + = ' ( %s ) ' % jid
2007-08-09 17:39:18 +02:00
try :
gajim . logger . write ( ' gcstatus ' , who , st , show )
except exceptions . PysqliteOperationalError , e :
self . dispatch ( ' ERROR ' , ( _ ( ' Disk Write Error ' ) , str ( e ) ) )
2006-11-28 17:41:31 +01:00
if avatar_sha or avatar_sha == ' ' :
if avatar_sha == ' ' :
# contact has no avatar
puny_nick = helpers . sanitize_filename ( resource )
gajim . interface . remove_avatar_files ( jid_stripped , puny_nick )
2007-06-03 12:04:20 +02:00
# if it's a gc presence, don't ask vcard here. We may ask it to
# real jid in gui part.
2007-03-11 21:14:53 +01:00
if ns_muc_user_x :
# Room has been destroyed. see
# http://www.xmpp.org/extensions/xep-0045.html#destroyroom
reason = _ ( ' Room has been destroyed ' )
destroy = ns_muc_user_x . getTag ( ' destroy ' )
r = destroy . getTagData ( ' reason ' )
if r :
reason + = ' ( %s ) ' % r
jid = destroy . getAttr ( ' jid ' )
if jid :
reason + = ' \n ' + _ ( ' You can join this room instead: %s ' ) % jid
2007-08-09 17:39:18 +02:00
statusCode = [ ' destroyed ' ]
2007-03-11 21:14:53 +01:00
else :
reason = prs . getReason ( )
statusCode = prs . getStatusCode ( )
2006-03-19 15:54:00 +01:00
self . dispatch ( ' GC_NOTIFY ' , ( jid_stripped , show , status , resource ,
prs . getRole ( ) , prs . getAffiliation ( ) , prs . getJid ( ) ,
2007-06-03 12:04:20 +02:00
reason , prs . getActor ( ) , statusCode , prs . getNewNick ( ) ,
avatar_sha ) )
2006-03-19 15:54:00 +01:00
return
if ptype == ' subscribe ' :
gajim . log . debug ( ' subscribe request from %s ' % who )
if gajim . config . get ( ' alwaysauth ' ) or who . find ( " @ " ) < = 0 or \
2006-04-19 12:06:59 +02:00
jid_stripped in self . jids_for_auto_auth or transport_auto_auth :
2006-03-19 15:54:00 +01:00
if self . connection :
p = common . xmpp . Presence ( who , ' subscribed ' )
p = self . add_sha ( p )
self . connection . send ( p )
2006-04-19 12:06:59 +02:00
if who . find ( " @ " ) < = 0 or transport_auto_auth :
2006-04-01 20:16:06 +02:00
self . dispatch ( ' NOTIFY ' , ( jid_stripped , ' offline ' , ' offline ' ,
2007-06-03 12:04:20 +02:00
resource , prio , keyID , timestamp , None ) )
2006-04-19 12:06:59 +02:00
if transport_auto_auth :
self . automatically_added . append ( jid_stripped )
2006-06-01 17:23:38 +02:00
self . request_subscription ( jid_stripped , name = user_nick )
2006-03-19 15:54:00 +01:00
else :
if not status :
status = _ ( ' I would like to add you to my roster. ' )
2007-12-12 09:44:46 +01:00
self . dispatch ( ' SUBSCRIBE ' , ( jid_stripped , status , user_nick ) )
2006-04-19 12:06:59 +02:00
elif ptype == ' subscribed ' :
if jid_stripped in self . automatically_added :
self . automatically_added . remove ( jid_stripped )
2006-04-18 16:30:00 +02:00
else :
2006-09-13 18:47:58 +02:00
# detect a subscription loop
if not self . subscribed_events . has_key ( jid_stripped ) :
self . subscribed_events [ jid_stripped ] = [ ]
2007-08-09 17:39:18 +02:00
self . subscribed_events [ jid_stripped ] . append ( time_time ( ) )
2006-09-13 18:47:58 +02:00
block = False
if len ( self . subscribed_events [ jid_stripped ] ) > 5 :
2007-08-09 17:39:18 +02:00
if time_time ( ) - self . subscribed_events [ jid_stripped ] [ 0 ] < 5 :
2006-09-13 18:47:58 +02:00
block = True
self . subscribed_events [ jid_stripped ] = self . subscribed_events [ jid_stripped ] [ 1 : ]
if block :
gajim . config . set_per ( ' account ' , self . name ,
' dont_ack_subscription ' , True )
else :
self . dispatch ( ' SUBSCRIBED ' , ( jid_stripped , resource ) )
2006-03-19 15:54:00 +01:00
# BE CAREFUL: no con.updateRosterItem() in a callback
gajim . log . debug ( _ ( ' we are now subscribed to %s ' ) % who )
elif ptype == ' unsubscribe ' :
gajim . log . debug ( _ ( ' unsubscribe request from %s ' ) % who )
elif ptype == ' unsubscribed ' :
gajim . log . debug ( _ ( ' we are now unsubscribed from %s ' ) % who )
2006-09-13 18:47:58 +02:00
# detect a unsubscription loop
if not self . subscribed_events . has_key ( jid_stripped ) :
self . subscribed_events [ jid_stripped ] = [ ]
2007-08-09 17:39:18 +02:00
self . subscribed_events [ jid_stripped ] . append ( time_time ( ) )
2006-09-13 18:47:58 +02:00
block = False
if len ( self . subscribed_events [ jid_stripped ] ) > 5 :
2007-08-09 17:39:18 +02:00
if time_time ( ) - self . subscribed_events [ jid_stripped ] [ 0 ] < 5 :
2006-09-13 18:47:58 +02:00
block = True
self . subscribed_events [ jid_stripped ] = self . subscribed_events [ jid_stripped ] [ 1 : ]
if block :
gajim . config . set_per ( ' account ' , self . name , ' dont_ack_subscription ' ,
True )
else :
self . dispatch ( ' UNSUBSCRIBED ' , jid_stripped )
2006-03-19 15:54:00 +01:00
elif ptype == ' error ' :
errmsg = prs . getError ( )
errcode = prs . getErrorCode ( )
2008-08-03 21:11:03 +02:00
if errcode != ' 502 ' : # Internal Timeout:
# print in the window the error
2006-03-19 15:54:00 +01:00
self . dispatch ( ' ERROR_ANSWER ' , ( ' ' , jid_stripped ,
errmsg , errcode ) )
2008-08-03 21:11:03 +02:00
self . dispatch ( ' NOTIFY ' , ( jid_stripped , ' error ' , errmsg , resource , prio ,
keyID , timestamp , None ) )
2006-03-19 15:54:00 +01:00
2008-06-10 04:58:17 +02:00
if ptype == ' unavailable ' and jid_stripped in self . sessions :
# automatically terminate sessions that they haven't sent a thread ID in
for sess in self . sessions [ jid_stripped ] . values ( ) :
if not sess . received_thread_id :
sess . terminate ( )
del self . sessions [ jid_stripped ] [ sess . thread_id ]
2006-03-19 15:54:00 +01:00
if avatar_sha and ptype != ' error ' :
2006-04-19 17:16:51 +02:00
if not self . vcard_shas . has_key ( jid_stripped ) :
cached_vcard = self . get_cached_vcard ( jid_stripped )
if cached_vcard and cached_vcard . has_key ( ' PHOTO ' ) and \
cached_vcard [ ' PHOTO ' ] . has_key ( ' SHA ' ) :
self . vcard_shas [ jid_stripped ] = cached_vcard [ ' PHOTO ' ] [ ' SHA ' ]
else :
self . vcard_shas [ jid_stripped ] = ' '
if avatar_sha != self . vcard_shas [ jid_stripped ] :
# avatar has been updated
self . request_vcard ( jid_stripped )
2006-03-19 15:54:00 +01:00
if not ptype or ptype == ' unavailable ' :
2007-08-09 17:39:18 +02:00
if gajim . config . get ( ' log_contact_status_changes ' ) and self . name \
not in no_log_for and jid_stripped not in no_log_for :
try :
gajim . logger . write ( ' status ' , jid_stripped , status , show )
except exceptions . PysqliteOperationalError , e :
self . dispatch ( ' ERROR ' , ( _ ( ' Disk Write Error ' ) , str ( e ) ) )
2007-12-12 09:44:46 +01:00
our_jid = gajim . get_jid_from_account ( self . name )
if jid_stripped == our_jid and resource == self . server_resource :
# We got our own presence
self . dispatch ( ' STATUS ' , show )
else :
self . dispatch ( ' NOTIFY ' , ( jid_stripped , show , status , resource , prio ,
keyID , timestamp , contact_nickname ) )
2006-03-19 15:54:00 +01:00
# END presenceCB
2007-02-15 10:18:24 +01:00
2006-03-19 15:54:00 +01:00
def _StanzaArrivedCB ( self , con , obj ) :
self . last_io = gajim . idlequeue . current_time ( )
def _MucOwnerCB ( self , con , iq_obj ) :
gajim . log . debug ( ' MucOwnerCB ' )
qp = iq_obj . getQueryPayload ( )
node = None
for q in qp :
if q . getNamespace ( ) == common . xmpp . NS_DATA :
node = q
if not node :
return
2007-02-14 17:48:25 +01:00
self . dispatch ( ' GC_CONFIG ' , ( helpers . get_full_jid_from_iq ( iq_obj ) , node ) )
2006-03-19 15:54:00 +01:00
def _MucAdminCB ( self , con , iq_obj ) :
gajim . log . debug ( ' MucAdminCB ' )
items = iq_obj . getTag ( ' query ' , namespace = common . xmpp . NS_MUC_ADMIN ) . getTags ( ' item ' )
2008-05-05 05:18:09 +02:00
users_dict = { }
2006-03-19 15:54:00 +01:00
for item in items :
if item . has_attr ( ' jid ' ) and item . has_attr ( ' affiliation ' ) :
jid = item . getAttr ( ' jid ' )
affiliation = item . getAttr ( ' affiliation ' )
2008-05-05 05:18:09 +02:00
users_dict [ jid ] = { ' affiliation ' : affiliation }
2006-03-19 15:54:00 +01:00
if item . has_attr ( ' nick ' ) :
2008-05-05 05:18:09 +02:00
users_dict [ jid ] [ ' nick ' ] = item . getAttr ( ' nick ' )
2006-03-19 15:54:00 +01:00
if item . has_attr ( ' role ' ) :
2008-05-05 05:18:09 +02:00
users_dict [ jid ] [ ' role ' ] = item . getAttr ( ' role ' )
2006-03-19 15:54:00 +01:00
reason = item . getTagData ( ' reason ' )
if reason :
2008-05-05 05:18:09 +02:00
users_dict [ jid ] [ ' reason ' ] = reason
2006-03-19 15:54:00 +01:00
self . dispatch ( ' GC_AFFILIATION ' , ( helpers . get_full_jid_from_iq ( iq_obj ) ,
2008-05-05 05:18:09 +02:00
users_dict ) )
2006-03-19 15:54:00 +01:00
def _MucErrorCB ( self , con , iq_obj ) :
gajim . log . debug ( ' MucErrorCB ' )
jid = helpers . get_full_jid_from_iq ( iq_obj )
errmsg = iq_obj . getError ( )
errcode = iq_obj . getErrorCode ( )
self . dispatch ( ' MSGERROR ' , ( jid , errcode , errmsg ) )
2007-01-27 11:19:53 +01:00
def _IqPingCB ( self , con , iq_obj ) :
gajim . log . debug ( ' IqPingCB ' )
iq_obj = iq_obj . buildReply ( ' result ' )
self . connection . send ( iq_obj )
raise common . xmpp . NodeProcessed
2008-06-25 09:35:35 +02:00
def _PrivacySetCB ( self , con , iq_obj ) :
'''
Privacy lists ( XEP 016 )
A list has been set
'''
gajim . log . debug ( ' PrivacySetCB ' )
result = iq_obj . buildReply ( ' result ' )
q = result . getTag ( ' query ' )
if q :
result . delChild ( q )
self . connection . send ( result )
raise common . xmpp . NodeProcessed
2006-03-19 15:54:00 +01:00
def _getRosterCB ( self , con , iq_obj ) :
if not self . connection :
return
self . connection . getRoster ( self . _on_roster_set )
2007-08-09 17:39:18 +02:00
self . discoverItems ( gajim . config . get_per ( ' accounts ' , self . name ,
' hostname ' ) , id_prefix = ' p ' )
self . discoverInfo ( gajim . config . get_per ( ' accounts ' , self . name ,
' hostname ' ) , id_prefix = ' p ' )
2006-03-27 10:28:05 +02:00
if gajim . config . get_per ( ' accounts ' , self . name , ' use_ft_proxies ' ) :
self . discover_ft_proxies ( )
def discover_ft_proxies ( self ) :
2006-03-19 21:43:30 +01:00
cfg_proxies = gajim . config . get_per ( ' accounts ' , self . name ,
2006-03-27 10:28:05 +02:00
' file_transfer_proxies ' )
2006-03-19 21:43:30 +01:00
if cfg_proxies :
proxies = map ( lambda e : e . strip ( ) , cfg_proxies . split ( ' , ' ) )
for proxy in proxies :
gajim . proxy65_manager . resolve ( proxy , self . connection )
2006-03-19 15:54:00 +01:00
def _on_roster_set ( self , roster ) :
raw_roster = roster . getRaw ( )
roster = { }
2006-04-10 10:24:55 +02:00
our_jid = helpers . parse_jid ( gajim . get_jid_from_account ( self . name ) )
2007-12-27 18:06:30 +01:00
if self . connected > 1 and self . continue_connect_info :
msg = self . continue_connect_info [ 1 ]
sign_msg = self . continue_connect_info [ 2 ]
signed = ' '
send_first_presence = True
if sign_msg :
signed = self . get_signed_presence ( msg , self . _send_first_presence )
if signed is None :
self . dispatch ( ' GPG_PASSWORD_REQUIRED ' ,
( self . _send_first_presence , ) )
# _send_first_presence will be called when user enter passphrase
send_first_presence = False
if send_first_presence :
self . _send_first_presence ( signed )
2006-03-19 15:54:00 +01:00
for jid in raw_roster :
try :
j = helpers . parse_jid ( jid )
except :
print >> sys . stderr , _ ( ' JID %s is not RFC compliant. It will not be added to your roster. Use roster management tools such as http://jru.jabberstudio.org/ to remove it ' ) % jid
else :
2006-04-10 10:24:55 +02:00
infos = raw_roster [ jid ]
2006-09-13 18:47:58 +02:00
if jid != our_jid and ( not infos [ ' subscription ' ] or \
infos [ ' subscription ' ] == ' none ' ) and ( not infos [ ' ask ' ] or \
infos [ ' ask ' ] == ' none ' ) and not infos [ ' name ' ] and \
not infos [ ' groups ' ] :
2006-04-10 10:24:55 +02:00
# remove this useless item, it won't be shown in roster anyway
self . connection . getRoster ( ) . delItem ( jid )
elif jid != our_jid : # don't add our jid
roster [ j ] = raw_roster [ jid ]
2006-09-13 18:47:58 +02:00
if gajim . jid_is_transport ( jid ) and \
not gajim . get_transport_name_from_jid ( jid ) :
# we can't determine which iconset to use
self . discoverInfo ( jid )
2006-03-19 15:54:00 +01:00
self . dispatch ( ' ROSTER ' , roster )
2007-12-12 09:44:46 +01:00
def _send_first_presence ( self , signed = ' ' ) :
show = self . continue_connect_info [ 0 ]
msg = self . continue_connect_info [ 1 ]
sign_msg = self . continue_connect_info [ 2 ]
if sign_msg and not signed :
signed = self . get_signed_presence ( msg )
if signed is None :
self . dispatch ( ' ERROR ' , ( _ ( ' OpenPGP passphrase was not given ' ) ,
#%s is the account name here
_ ( ' You will be connected to %s without OpenPGP. ' ) % self . name ) )
2007-12-30 00:28:27 +01:00
self . USE_GPG = False
2007-12-12 09:44:46 +01:00
signed = ' '
self . connected = STATUS_LIST . index ( show )
sshow = helpers . get_xmpp_show ( show )
# send our presence
if show == ' invisible ' :
self . send_invisible_presence ( msg , signed , True )
return
priority = gajim . get_priority ( self . name , sshow )
our_jid = helpers . parse_jid ( gajim . get_jid_from_account ( self . name ) )
vcard = self . get_cached_vcard ( our_jid )
if vcard and vcard . has_key ( ' PHOTO ' ) and vcard [ ' PHOTO ' ] . has_key ( ' SHA ' ) :
self . vcard_sha = vcard [ ' PHOTO ' ] [ ' SHA ' ]
p = common . xmpp . Presence ( typ = None , priority = priority , show = sshow )
p = self . add_sha ( p )
if msg :
p . setStatus ( msg )
if signed :
p . setTag ( common . xmpp . NS_SIGNED + ' x ' ) . setData ( signed )
if self . connection :
self . connection . send ( p )
self . priority = priority
self . dispatch ( ' STATUS ' , show )
# ask our VCard
self . request_vcard ( None )
# Get bookmarks from private namespace
self . get_bookmarks ( )
# Get annotations from private namespace
self . get_annotations ( )
# Inform GUI we just signed in
self . dispatch ( ' SIGNED_IN ' , ( ) )
2006-03-19 15:54:00 +01:00
self . continue_connect_info = None
2007-08-09 17:39:18 +02:00
def request_gmail_notifications ( self ) :
# It's a gmail account,
# inform the server that we want e-mail notifications
our_jid = helpers . parse_jid ( gajim . get_jid_from_account ( self . name ) )
gajim . log . debug ( ( ' %s is a gmail account. Setting option '
' to get e-mail notifications on the server. ' ) % ( our_jid ) )
iq = common . xmpp . Iq ( typ = ' set ' , to = our_jid )
iq . setAttr ( ' id ' , ' MailNotify ' )
query = iq . setTag ( ' usersetting ' )
query . setNamespace ( common . xmpp . NS_GTALKSETTING )
query = query . setTag ( ' mailnotifications ' )
query . setAttr ( ' value ' , ' true ' )
self . connection . send ( iq )
# Ask how many messages there are now
iq = common . xmpp . Iq ( typ = ' get ' )
iq . setID ( self . connection . getAnID ( ) )
query = iq . setTag ( ' query ' )
query . setNamespace ( common . xmpp . NS_GMAILNOTIFY )
self . connection . send ( iq )
2007-06-03 12:04:20 +02:00
def _search_fields_received ( self , con , iq_obj ) :
jid = jid = helpers . get_jid_from_iq ( iq_obj )
tag = iq_obj . getTag ( ' query ' , namespace = common . xmpp . NS_SEARCH )
if not tag :
self . dispatch ( ' SEARCH_FORM ' , ( jid , None , False ) )
return
df = tag . getTag ( ' x ' , namespace = common . xmpp . NS_DATA )
if df :
self . dispatch ( ' SEARCH_FORM ' , ( jid , df , True ) )
return
df = { }
for i in iq_obj . getQueryPayload ( ) :
df [ i . getName ( ) ] = i . getData ( )
self . dispatch ( ' SEARCH_FORM ' , ( jid , df , False ) )
def _StreamCB ( self , con , obj ) :
if obj . getTag ( ' conflict ' ) :
# disconnected because of a resource conflict
self . dispatch ( ' RESOURCE_CONFLICT ' , ( ) )
2006-03-19 15:54:00 +01:00
def _register_handlers ( self , con , con_type ) :
2008-05-13 03:59:10 +02:00
# try to find another way to register handlers in each class
2006-03-19 15:54:00 +01:00
# that defines handlers
con . RegisterHandler ( ' message ' , self . _messageCB )
con . RegisterHandler ( ' presence ' , self . _presenceCB )
2007-08-09 17:39:18 +02:00
con . RegisterHandler ( ' presence ' , self . _capsPresenceCB )
2006-03-19 15:54:00 +01:00
con . RegisterHandler ( ' iq ' , self . _vCardCB , ' result ' ,
common . xmpp . NS_VCARD )
con . RegisterHandler ( ' iq ' , self . _rosterSetCB , ' set ' ,
common . xmpp . NS_ROSTER )
con . RegisterHandler ( ' iq ' , self . _siSetCB , ' set ' ,
common . xmpp . NS_SI )
con . RegisterHandler ( ' iq ' , self . _siErrorCB , ' error ' ,
common . xmpp . NS_SI )
con . RegisterHandler ( ' iq ' , self . _siResultCB , ' result ' ,
common . xmpp . NS_SI )
con . RegisterHandler ( ' iq ' , self . _discoGetCB , ' get ' ,
common . xmpp . NS_DISCO )
con . RegisterHandler ( ' iq ' , self . _bytestreamSetCB , ' set ' ,
common . xmpp . NS_BYTESTREAM )
con . RegisterHandler ( ' iq ' , self . _bytestreamResultCB , ' result ' ,
common . xmpp . NS_BYTESTREAM )
con . RegisterHandler ( ' iq ' , self . _bytestreamErrorCB , ' error ' ,
common . xmpp . NS_BYTESTREAM )
con . RegisterHandler ( ' iq ' , self . _DiscoverItemsCB , ' result ' ,
common . xmpp . NS_DISCO_ITEMS )
con . RegisterHandler ( ' iq ' , self . _DiscoverItemsErrorCB , ' error ' ,
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 )
2006-09-13 18:47:58 +02:00
con . RegisterHandler ( ' iq ' , self . _TimeCB , ' get ' ,
common . xmpp . NS_TIME )
2006-12-28 17:27:41 +01:00
con . RegisterHandler ( ' iq ' , self . _TimeRevisedCB , ' get ' ,
common . xmpp . NS_TIME_REVISED )
2006-03-19 15:54:00 +01:00
con . RegisterHandler ( ' iq ' , self . _LastCB , ' get ' ,
common . xmpp . NS_LAST )
con . RegisterHandler ( ' iq ' , self . _LastResultCB , ' result ' ,
common . xmpp . NS_LAST )
con . RegisterHandler ( ' iq ' , self . _VersionResultCB , ' result ' ,
common . xmpp . NS_VERSION )
con . RegisterHandler ( ' iq ' , self . _MucOwnerCB , ' result ' ,
common . xmpp . NS_MUC_OWNER )
con . RegisterHandler ( ' iq ' , self . _MucAdminCB , ' result ' ,
common . xmpp . NS_MUC_ADMIN )
con . RegisterHandler ( ' iq ' , self . _getRosterCB , ' result ' ,
common . xmpp . NS_ROSTER )
con . RegisterHandler ( ' iq ' , self . _PrivateCB , ' result ' ,
common . xmpp . NS_PRIVATE )
con . RegisterHandler ( ' iq ' , self . _HttpAuthCB , ' get ' ,
common . xmpp . NS_HTTP_AUTH )
2006-07-15 15:27:57 +02:00
con . RegisterHandler ( ' iq ' , self . _CommandExecuteCB , ' set ' ,
common . xmpp . NS_COMMANDS )
2006-03-19 15:54:00 +01:00
con . RegisterHandler ( ' iq ' , self . _gMailNewMailCB , ' set ' ,
common . xmpp . NS_GMAILNOTIFY )
con . RegisterHandler ( ' iq ' , self . _gMailQueryCB , ' result ' ,
common . xmpp . NS_GMAILNOTIFY )
con . RegisterHandler ( ' iq ' , self . _DiscoverInfoGetCB , ' get ' ,
common . xmpp . NS_DISCO_INFO )
2006-07-15 15:27:57 +02:00
con . RegisterHandler ( ' iq ' , self . _DiscoverItemsGetCB , ' get ' ,
common . xmpp . NS_DISCO_ITEMS )
2007-01-27 11:19:53 +01:00
con . RegisterHandler ( ' iq ' , self . _IqPingCB , ' get ' ,
common . xmpp . NS_PING )
2007-06-03 12:04:20 +02:00
con . RegisterHandler ( ' iq ' , self . _search_fields_received , ' result ' ,
common . xmpp . NS_SEARCH )
2008-06-25 09:35:35 +02:00
con . RegisterHandler ( ' iq ' , self . _PrivacySetCB , ' set ' ,
common . xmpp . NS_PRIVACY )
2006-08-20 12:18:20 +02:00
con . RegisterHandler ( ' iq ' , self . _PubSubCB , ' result ' )
2006-03-19 15:54:00 +01:00
con . RegisterHandler ( ' iq ' , self . _ErrorCB , ' error ' )
con . RegisterHandler ( ' iq ' , self . _IqCB )
con . RegisterHandler ( ' iq ' , self . _StanzaArrivedCB )
2006-04-12 00:23:51 +02:00
con . RegisterHandler ( ' iq ' , self . _ResultCB , ' result ' )
2006-03-19 15:54:00 +01:00
con . RegisterHandler ( ' presence ' , self . _StanzaArrivedCB )
2006-03-19 15:59:17 +01:00
con . RegisterHandler ( ' message ' , self . _StanzaArrivedCB )
2007-06-03 12:04:20 +02:00
con . RegisterHandler ( ' unknown ' , self . _StreamCB , ' urn:ietf:params:xml:ns:xmpp-streams ' , xmlns = ' http://etherx.jabber.org/streams ' )
2008-07-29 21:49:31 +02:00
2008-08-01 12:27:38 +02:00
# vim: se ts=3: