Newer
Older
exec python -OOt "$0" ${1+"$@"}
## Contributors for this file:

nicfit
committed
## - Travis Shirk <travis@pobox.com>
## Copyright (C) 2003-2004 Yann Le Boulanger <asterix@lagaule.org>
## Vincent Hanquez <tab@snarc.org>
## Copyright (C) 2005 Yann Le Boulanger <asterix@lagaule.org>
## Vincent Hanquez <tab@snarc.org>
## Nikos Kouremenos <nkour@jabber.org>
## Dimitur Kirov <dkirov@gmail.com>
## Travis Shirk <travis@pobox.com>
## Norman Rasmussen <norman@rasmussen.co.za>
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published
## by the Free Software Foundation; version 2 only.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
from common import exceptions
if os.name == 'posix': # dl module is Unix Only
try: # rename the process name to gajim
import dl
libc = dl.open('/lib/libc.so.6')
libc.call('prctl', 15, 'gajim\0', 0, 0, 0)
except:
pass
try:
import gtk
except RuntimeError, msg:
if str(msg) == 'could not open display':
print >> sys.stderr, _('Gajim needs Xserver to run. Quiting...')
pritext = ''
pritext = _('Gajim needs PyGTK 2.6 or above')
sectext = _('Gajim needs PyGTK 2.6 or above to run. Quiting...')
try:
import gtk.glade # check if user has libglade (in pygtk and in gtk)
except ImportError:
pritext = _('GTK+ runtime is missing libglade support')
if os.name == 'nt':
sectext = _('Please remove your current GTK+ runtime and install the latest stable version from %s') % 'http://gladewin32.sourceforge.net'
sectext = _('Please make sure that GTK+ and PyGTK have libglade support in your system.')
try:
from common import check_paths
except exceptions.PysqliteNotAvailable, e:
sectext = str(e)
if os.name == 'nt':
try:
import winsound # windows-only built-in module for playing wav
import win32api
import win32con
except:
pritext = _('Gajim needs pywin32 to run')
sectext = _('Please make sure that Pywin32 is installed on your system. You can get it at %s') % 'http://sourceforge.net/project/showfiles.php?group_id=78018'
if pritext:
dlg = gtk.MessageDialog(None,
gtk.DIALOG_DESTROY_WITH_PARENT | gtk.DIALOG_MODAL,
gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, message_format = pritext)
dlg.format_secondary_text(sectext)
dlg.run()
dlg.destroy()
sys.exit()
path = os.getcwd()
if '.svn' in os.listdir(path) or '_svn' in os.listdir(path):
# import gtkexcepthook only for those that run svn
# those than run with --verbose run from terminal so no need to care
# about those
import gtkexcepthook
del path
import signal
import getopt
import time

Yann Leboulanger
committed
import math
import gtkgui_helpers
import notify
from common.xmpp import idlequeue
from common import nslookup
from common import proxy65_manager
from common import socks5
from common import helpers
from common import optparser
profile = ''
try:
opts, args = getopt.getopt(sys.argv[1:], 'hvp:', ['help', 'verbose',
'profile=', 'sm-config-prefix=', 'sm-client-id='])
except getopt.error, msg:
print msg
print 'for help use --help'
sys.exit(2)
for o, a in opts:
elif o in ('-v', '--verbose'):
gajim.verbose = True
elif o in ('-p', '--profile'): # gajim --profile name
profile = a

Yann Leboulanger
committed
pid_filename = os.path.expanduser('~/.gajim/gajim')

nkour
committed
config_filename = os.path.expanduser('~/.gajim/config')
if os.name == 'nt':
try:
# Documents and Settings\[User Name]\Application Data\Gajim\logs
config_filename = os.environ['appdata'] + '/Gajim/config'

Yann Leboulanger
committed
pid_filename = os.environ['appdata'] + '/Gajim/gajim'

nkour
committed
except KeyError:

Yann Leboulanger
committed
pid_filename = 'gajim'

nkour
committed
if profile:

Yann Leboulanger
committed
pid_filename += '.%s' % profile
pid_filename += '.pid'

Yann Leboulanger
committed
if os.path.exists(pid_filename):
path_to_file = os.path.join(gajim.DATA_DIR, 'pixmaps/gajim.png')
pix = gtk.gdk.pixbuf_new_from_file(path_to_file)
gtk.window_set_default_icon(pix) # set the icon to all newly opened wind

Yann Leboulanger
committed
pritext = _('Gajim is already running')
sectext = _('Another instance of Gajim seems to be running\nRun anyway?')
dialog = dialogs.YesNoDialog(pritext, sectext)
if dialog.get_response() != gtk.RESPONSE_YES:
sys.exit(3)
if os.path.exists(pid_filename):
os.remove(pid_filename)

Yann Leboulanger
committed
# Create .gajim dir
pid_dir = os.path.dirname(pid_filename)
if not os.path.exists(pid_dir):
check_paths.create_path(pid_dir)
# Create pid file

Yann Leboulanger
committed
f = open(pid_filename, 'a')
f.close()
def on_exit():
# delete pid file on normal exit
if os.path.exists(pid_filename):
os.remove(pid_filename)
import atexit
atexit.register(on_exit)

nkour
committed
parser = optparser.OptionsParser(config_filename)
import roster_window
import systray
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
class GlibIdleQueue(idlequeue.IdleQueue):
'''
Extends IdleQueue to use glib io_add_wath, instead of select/poll
In another, `non gui' implementation of Gajim IdleQueue can be used safetly.
'''
def init_idle(self):
''' this method is called at the end of class constructor.
Creates a dict, which maps file/pipe/sock descriptor to glib event id'''
self.events = {}
if gtk.pygtk_version >= (2, 8, 0):
# time() is already called in glib, we just get the last value
# overrides IdleQueue.current_time()
self.current_time = lambda: gobject.get_current_time()
def add_idle(self, fd, flags):
''' this method is called when we plug a new idle object.
Start listening for events from fd
'''
res = gobject.io_add_watch(fd, flags, self.process_events,
priority=gobject.PRIORITY_LOW)
# store the id of the watch, so that we can remove it on unplug
self.events[fd] = res
def remove_idle(self, fd):
''' this method is called when we unplug a new idle object.
Stop listening for events from fd
'''
gobject.source_remove(self.events[fd])
del(self.events[fd])
def process(self):
self.check_time_events()
class Interface:

Yann Leboulanger
committed
def handle_event_roster(self, account, data):
self.roster.fill_contacts_and_groups_dicts(data, account)
self.roster.add_account_contacts(account)
self.roster.fire_up_unread_messages_events(account)

nkour
committed
if self.remote_ctrl:
self.remote_ctrl.raise_signal('Roster', (account, data))

Yann Leboulanger
committed
def handle_event_warning(self, unused, data):
#('WARNING', account, (title_text, section_text))

Yann Leboulanger
committed
dialogs.WarningDialog(data[0], data[1])

Yann Leboulanger
committed
def handle_event_error(self, unused, data):
#('ERROR', account, (title_text, section_text))

Yann Leboulanger
committed
dialogs.ErrorDialog(data[0], data[1])
def handle_event_information(self, unused, data):
#('INFORMATION', account, (title_text, section_text))
dialogs.InformationDialog(data[0], data[1])
def handle_event_ask_new_nick(self, account, data):
#('ASK_NEW_NICK', account, (room_jid, title_text, prompt_text, proposed_nick))

nkour
committed
room_jid = data[0]
title = data[1]
prompt = data[2]
proposed_nick = data[3]

Yann Leboulanger
committed
gc_control = self.msg_win_mgr.get_control(room_jid, account)
if gc_control: # user may close the window before we are here
gc_control.show_change_nick_input_dialog(title, prompt, proposed_nick)
def handle_event_http_auth(self, account, data):

nicfit
committed
#('HTTP_AUTH', account, (method, url, transaction_id, iq_obj))

Yann Leboulanger
committed
def response(widget, account, iq_obj, answer):
self.dialog.destroy()
gajim.connections[account].build_http_auth_answer(iq_obj, answer)
self.dialog = dialogs.YesNoDialog(_('HTTP (%s) Authorization for %s (id: %s)') \
% (data[0], data[1], data[2]), _('Do you accept this request?'),
on_response_yes = (response, account, data[3], 'yes'),
on_response_no = (response, account, data[3], 'no'))
def handle_event_error_answer(self, account, array):

Yann Leboulanger
committed
#('ERROR_ANSWER', account, (id, jid_from, errmsg, errcode))
id, jid_from, errmsg, errcode = array
if unicode(errcode) in ('403', '406') and id:
ft = self.instances['file_transfers']
sid = id
if len(id) > 3 and id[2] == '_':
sid = id[3:]
if ft.files_props['s'].has_key(sid):
file_props = ft.files_props['s'][sid]
file_props['error'] = -4
self.handle_event_file_request_error(account,

Yann Leboulanger
committed
(jid_from, file_props, errmsg))
conn = gajim.connections[account]
conn.disconnect_transfer(file_props)
return
elif unicode(errcode) == '404':
sid = id
if len(id) > 3 and id[2] == '_':
sid = id[3:]
if conn.files_props.has_key(sid):
file_props = conn.files_props[sid]
self.handle_event_file_send_error(account,
(jid_from, file_props))
conn.disconnect_transfer(file_props)
return

Yann Leboulanger
committed
ctrl = self.msg_win_mgr.get_control(jid_from, account)
if ctrl and ctrl.type_id == message_control.TYPE_GC:
ctrl.print_conversation('Error %s: %s' % (array[2], array[1]))
def handle_event_con_type(self, account, con_type):
# ('CON_TYPE', account, con_type) which can be 'ssl', 'tls', 'tcp'

Yann Leboulanger
committed
gajim.con_types[account] = con_type
self.roster.draw_account(account)

Yann Leboulanger
committed
def handle_event_connection_lost(self, account, array):
# ('CONNECTION_LOST', account, [title, text])
path = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events',
'connection_lost.png')
path = gtkgui_helpers.get_path_to_generic_or_avatar(path)
notify.popup(_('Connection Failed'), account, account,
'connection_failed', path, array[0], array[1])
def unblock_signed_in_notifications(self, account):
gajim.block_signed_in_notifications[account] = False
def handle_event_status(self, account, status): # OUR status
model = self.roster.status_combobox.get_model()
if status == 'offline':

Yann Leboulanger
committed
if gajim.get_number_of_connected_accounts() == 0:
model[self.roster.status_message_menuitem_iter][3] = False
gajim.block_signed_in_notifications[account] = True
# 30 seconds after we change our status to sth else than offline
# we stop blocking notifications of any kind
# this prevents from getting the roster items as 'just signed in'
# contacts. 30 seconds should be enough time
gobject.timeout_add(30000, self.unblock_signed_in_notifications, account)
# sensitivity for this menuitem
model[self.roster.status_message_menuitem_iter][3] = True
# Inform all controls for this account of the connection state change
for ctrl in self.msg_win_mgr.get_controls():
if ctrl.account == account:
if status == 'offline':
ctrl.got_disconnected()
else:
# Other code rejoins all GCs, so we don't do it here
if not ctrl.type_id == message_control.TYPE_GC:
ctrl.got_connected()
ctrl.parent_win.redraw_tab(ctrl)
self.roster.on_status_changed(account, status)

Yann Leboulanger
committed
if account in self.show_vcard_when_connect:
self.edit_own_details(account)

nkour
committed
if self.remote_ctrl:
self.remote_ctrl.raise_signal('AccountPresence', (status, account))
def edit_own_details(self, account):
jid = gajim.get_jid_from_account(account)
if not self.instances[account].has_key('profile'):
self.instances[account]['profile'] = \
profile_window.ProfileWindow(account)
gajim.connections[account].request_vcard(jid)
def handle_event_notify(self, account, array):
# 'NOTIFY' (account, (jid, status, status message, resource, priority,
# keyID, timestamp))
# if we're here it means contact changed show
statuss = ['offline', 'error', 'online', 'chat', 'away', 'xa', 'dnd',
'invisible']
status_message = array[2]
jid = array[0].split('/')[0]
attached_keys = gajim.config.get_per('accounts', account,
'attached_gpg_keys').split()
if jid in attached_keys:
keyID = attached_keys[attached_keys.index(jid) + 1]
resource = array[3]
if not resource:
resource = ''
priority = array[4]
if gajim.jid_is_transport(jid):
# It must be an agent
ji = jid.replace('@', '')
jid_list = gajim.contacts.get_jid_list(account)

Yann Leboulanger
committed
if ji in jid_list or jid == gajim.get_jid_from_account(account):
lcontact = gajim.contacts.get_contacts_from_jid(account, ji)
contact1 = None
for c in lcontact:
if c.resource == resource:
contact1 = c
if contact1:
if contact1.show in statuss:
old_show = statuss.index(contact1.show)
if old_show == new_show and contact1.status == status_message and \
contact1.priority == priority: # no change

Yann Leboulanger
committed
return
contact1 = gajim.contacts.get_first_contact_from_jid(account, ji)

Yann Leboulanger
committed
if not contact1:

Yann Leboulanger
committed
# presence of another resource of our jid
if resource == gajim.connections[account].server_resource:
return
contact1 = gajim.contacts.create_contact(jid = ji,
name = gajim.nicks[account], groups = [],
show = array[1], status = status_message, sub = 'both',
ask = 'none', priority = priority, keyID = keyID,
resource = resource)
old_show = 0
gajim.contacts.add_contact(account, contact1)
lcontact.append(contact1)
self.roster.add_self_contact(account)

Yann Leboulanger
committed
elif contact1.show in statuss:
old_show = statuss.index(contact1.show)
if (resources != [''] and (len(lcontact) != 1 or
lcontact[0].show != 'offline')) and jid.find('@') > 0:
contact1 = gajim.contacts.copy_contact(contact1)
lcontact.append(contact1)
contact1.resource = resource
if contact1.jid.find('@') > 0 and len(lcontact) == 1: # It's not an agent
if not contact1.jid in gajim.newly_added[account]:
gajim.newly_added[account].append(contact1.jid)
if contact1.jid in gajim.to_be_removed[account]:
gajim.to_be_removed[account].remove(contact1.jid)
gobject.timeout_add(5000, self.roster.remove_newly_added,
contact1.jid, account)
elif old_show > 1 and new_show == 0 and gajim.connections[account].\
connected > 1:
if not contact1.jid in gajim.to_be_removed[account]:
gajim.to_be_removed[account].append(contact1.jid)
if contact1.jid in gajim.newly_added[account]:
gajim.newly_added[account].remove(contact1.jid)
self.roster.draw_contact(contact1.jid, account)

Yann Leboulanger
committed
gobject.timeout_add(5000, self.roster.really_remove_contact,
contact1, account)
contact1.show = array[1]
contact1.status = status_message
contact1.priority = priority
contact1.keyID = keyID
timestamp = array[6]
if timestamp:
contact1.last_status_time = timestamp
elif not gajim.block_signed_in_notifications[account]:
# We're connected since more that 30 seconds

Yann Leboulanger
committed
contact1.last_status_time = time.localtime()
if gajim.jid_is_transport(jid):
# It must be an agent
# Update existing iter
self.roster.draw_contact(ji, account)

Yann Leboulanger
committed
# transport just signed in/out, don't show popup notifications
# for 30s
account_ji = account + '/' + ji
gajim.block_signed_in_notifications[account_ji] = True
gobject.timeout_add(30000, self.unblock_signed_in_notifications,
account_ji)

Yann Leboulanger
committed
locations = (self.instances, self.instances[account])
for location in locations:
if location.has_key('add_contact'):
if old_show == 0 and new_show > 1:
location['add_contact'].transport_signed_in(jid)
break
elif old_show > 1 and new_show == 0:
location['add_contact'].transport_signed_out(jid)
break
# reset chatstate if needed:
# (when contact signs out or has errors)
if array[1] in ('offline', 'error'):

Yann Leboulanger
committed
contact1.our_chatstate = contact1.chatstate = \
contact1.composing_jep = None
gajim.connections[account].remove_transfers_for_contact(contact1)
self.roster.chg_contact_status(contact1, array[1], status_message,
account)
if old_show < 2 and new_show > 1:
notify.notify('contact_connected', jid, account, status_message)

nkour
committed
if self.remote_ctrl:
self.remote_ctrl.raise_signal('ContactPresence',

Yann Leboulanger
committed
elif old_show > 1 and new_show < 2:
notify.notify('contact_disconnected', jid, account, status_message)

nkour
committed
if self.remote_ctrl:
self.remote_ctrl.raise_signal('ContactAbsence', (account, array))
# FIXME: stop non active file transfers
elif new_show > 1: # Status change (not connected/disconnected or error (<1))
notify.notify('status_change', jid, account, [new_show,
status_message])
# FIXME: Msn transport (CMSN1.2.1 and PyMSN0.10) doesn't follow the JEP
# remove in 2007
# It's maybe a GC_NOTIFY (specialy for MSN gc)
self.handle_event_gc_notify(account, (jid, array[1], status_message,
array[3], None, None, None, None, None, None, None))
def handle_event_msg(self, account, array):

nkour
committed
# 'MSG' (account, (jid, msg, time, encrypted, msg_type, subject,
# chatstate, msg_id, composing_jep, user_nick)) user_nick is JEP-0172

nkour
committed
full_jid_with_resource = array[0]
jid = gajim.get_jid_without_resource(full_jid_with_resource)
resource = gajim.get_resource_from_jid(full_jid_with_resource)

Yann Leboulanger
committed

nkour
committed
message = array[1]
msg_type = array[4]

Yann Leboulanger
committed
msg_id = array[7]

Yann Leboulanger
committed
composing_jep = array[8]
if gajim.jid_is_transport(jid):
jid = jid.replace('@', '')
groupchat_control = self.msg_win_mgr.get_control(jid, account)
pm = False
if groupchat_control and groupchat_control.type_id == \
message_control.TYPE_GC:
# It's a Private message
pm = True
chat_control = None
jid_of_control = full_jid_with_resource

Yann Leboulanger
committed
highest_contact = gajim.contacts.get_contact_with_highest_priority(
account, jid)
# Look for a chat control that has the given resource, or default to one
# without resource
ctrl = self.msg_win_mgr.get_control(full_jid_with_resource, account)
if ctrl:
chat_control = ctrl
elif not pm and (not highest_contact or not highest_contact.resource):

Yann Leboulanger
committed
# unknow contact or offline message
jid_of_control = jid
chat_control = self.msg_win_mgr.get_control(jid, account)
elif highest_contact and resource != highest_contact.resource:

Yann Leboulanger
committed
jid_of_control = full_jid_with_resource
chat_control = None

Yann Leboulanger
committed
jid_of_control = jid
chat_control = self.msg_win_mgr.get_control(jid, account)
# Handle chat states

Yann Leboulanger
committed
contact = gajim.contacts.get_contact(account, jid, resource)
if contact and isinstance(contact, list):

Yann Leboulanger
committed
contact = contact[0]
if contact:
contact.composing_jep = composing_jep

Yann Leboulanger
committed
if chat_control and chat_control.type_id == message_control.TYPE_CHAT:
if chatstate is not None:
# other peer sent us reply, so he supports jep85 or jep22
contact.chatstate = chatstate
if contact.our_chatstate == 'ask': # we were jep85 disco?
contact.our_chatstate = 'active' # no more
chat_control.handle_incoming_chatstate()
elif contact.chatstate != 'active':
# got no valid jep85 answer, peer does not support it
contact.chatstate = False
elif chatstate == 'active':
# Brand new message, incoming.
contact.our_chatstate = chatstate
contact.chatstate = chatstate

Yann Leboulanger
committed
if msg_id: # Do not overwrite an existing msg_id with None
contact.msg_id = msg_id
# THIS MUST BE AFTER chatstates handling
# AND BEFORE playsound (else we here sounding on chatstates!)

nkour
committed
if not message: # empty message text
return

jimpp
committed
if gajim.config.get('ignore_unknown_contacts') and \
not gajim.contacts.get_contact(account, jid) and not pm:
return

Yann Leboulanger
committed
advanced_notif_num = notify.get_advanced_notification('message_received',
account, contact)

jimpp
committed
# Is it a first or next message received ?

Yann Leboulanger
committed
first = False

Yann Leboulanger
committed
if not chat_control and not gajim.events.get_events(account,
jid_of_control, ['chat']):

Yann Leboulanger
committed
# It's a first message and not a Private Message
first = True

nkour
committed
if pm:

jimpp
committed
nickname = resource
msg_type = 'pm'
groupchat_control.on_private_message(nickname, message, array[2])
else:
# array: (jid, msg, time, encrypted, msg_type, subject)
self.roster.on_message(jid, message, array[2], account, array[3],

Yann Leboulanger
committed
msg_type, subject, resource, msg_id, array[9], advanced_notif_num)

jimpp
committed
nickname = gajim.get_name_from_jid(account, jid)
# Check and do wanted notifications
msg = message
if subject:
msg = _('Subject: %s') % subject + '\n' + msg
notify.notify('new_message', jid, account, [msg_type, first, nickname,

Yann Leboulanger
committed
msg], advanced_notif_num)

jimpp
committed

nkour
committed
if self.remote_ctrl:
self.remote_ctrl.raise_signal('NewMessage', (account, array))
def handle_event_msgerror(self, account, array):

nkour
committed
#'MSGERROR' (account, (jid, error_code, error_msg, msg, time))
full_jid_with_resource = array[0]
jids = full_jid_with_resource.split('/', 1)

Yann Leboulanger
committed
gcs = self.msg_win_mgr.get_controls(message_control.TYPE_GC)
for gc_control in gcs:
if jid == gc_control.contact.jid:
if len(jids) > 1: # it's a pm
nick = jids[1]

nkour
committed
if not self.msg_win_mgr.get_control(full_jid_with_resource, account):
tv = gc_control.list_treeview
model = tv.get_model()
i = gc_control.get_contact_iter(nick)
if i:
show = model[i][3]
else:
show = 'offline'
gc_c = gajim.contacts.create_gc_contact(room_jid = jid,
name = nick, show = show)
c = gajim.contacts.contact_from_gc_contact(gc_c)

nkour
committed
ctrl = self.msg_win_mgr.get_control(full_jid_with_resource, account)
gc_control.print_conversation('Error %s: %s' % (array[1], array[2]))
if gc_control.parent_win.get_active_jid() == jid:
gc_control.set_subject(gc_control.subject)
if gajim.jid_is_transport(jid):
jid = jid.replace('@', '')
msg = array[2]
if array[3]:
msg = _('error while sending %s ( %s )') % (array[3], msg)
self.roster.on_message(jid, msg, array[4], account, \
msg_type='error')
def handle_event_msgsent(self, account, array):
msg = array[1]
# do not play sound when standalone chatstate message (eg no msg)
if msg and gajim.config.get_per('soundevents', 'message_sent', 'enabled'):
helpers.play_sound('message_sent')
def handle_event_subscribe(self, account, array):
#('SUBSCRIBE', account, (jid, text, user_nick)) user_nick is JEP-0172
dialogs.SubscriptionRequestWindow(array[0], array[1], account, array[2])

nkour
committed
if self.remote_ctrl:
self.remote_ctrl.raise_signal('Subscribe', (account, array))
def handle_event_subscribed(self, account, array):
#('SUBSCRIBED', account, (jid, resource))
if jid in gajim.contacts.get_jid_list(account):
c = gajim.contacts.get_first_contact_from_jid(account, jid)
c.resource = array[1]
self.roster.remove_contact(c, account)
if _('Not in Roster') in c.groups:
c.groups.remove(_('Not in Roster'))
self.roster.add_contact_to_roster(c.jid, account)
keyID = ''
attached_keys = gajim.config.get_per('accounts', account,
'attached_gpg_keys').split()
if jid in attached_keys:
keyID = attached_keys[attached_keys.index(jid) + 1]
name = jid.split('@', 1)[0]
name = name.split('%', 1)[0]
contact1 = gajim.contacts.create_contact(jid = jid, name = name,
groups = [], show = 'online', status = 'online',
ask = 'to', resource = array[1], keyID = keyID)
gajim.contacts.add_contact(account, contact1)
self.roster.add_contact_to_roster(jid, account)

nkour
committed
dialogs.InformationDialog(_('Authorization accepted'),
_('The contact "%s" has authorized you to see his or her status.')
if not gajim.config.get_per('accounts', account, 'dont_ack_subscription'):
gajim.connections[account].ack_subscribed(jid)

nkour
committed
if self.remote_ctrl:
self.remote_ctrl.raise_signal('Subscribed', (account, array))
def handle_event_unsubscribed(self, account, jid):
dialogs.InformationDialog(_('Contact "%s" removed subscription from you') % jid,
# FIXME: Per RFC 3921, we can "deny" ack as well, but the GUI does not show deny
gajim.connections[account].ack_unsubscribed(jid)

nkour
committed
if self.remote_ctrl:
self.remote_ctrl.raise_signal('Unsubscribed', (account, jid))
def handle_event_agent_info_error(self, account, agent):
#('AGENT_ERROR_INFO', account, (agent))
try:
gajim.connections[account].services_cache.agent_info_error(agent)
except AttributeError:
return
def handle_event_agent_items_error(self, account, agent):
#('AGENT_ERROR_INFO', account, (agent))
try:
gajim.connections[account].services_cache.agent_items_error(agent)
except AttributeError:
return

Yann Leboulanger
committed
def handle_event_agent_removed(self, account, agent):
# remove transport's contacts from treeview
jid_list = gajim.contacts.get_jid_list(account)
for jid in jid_list:
if jid.endswith('@' + agent):
c = gajim.contacts.get_first_contact_from_jid(account, jid)
gajim.log.debug(
'Removing contact %s due to unregistered transport %s'\
% (jid, agent))
gajim.connections[account].unsubscribe(c.jid)
# Transport contacts can't have 2 resources
if c.jid in gajim.to_be_removed[account]:
# This way we'll really remove it
gajim.to_be_removed[account].remove(c.jid)
gajim.contacts.remove_jid(account, c.jid)
self.roster.remove_contact(c, account)
def handle_event_register_agent_info(self, account, array):
#('REGISTER_AGENT_INFO', account, (agent, infos, is_form))
if array[1].has_key('instructions'):

Yann Leboulanger
committed
config.ServiceRegistrationWindow(array[0], array[1], account,
dialogs.ErrorDialog(_('Contact with "%s" cannot be established')\
% array[0], _('Check your connection or try again later.'))

Yann Leboulanger
committed
def handle_event_agent_info_items(self, account, array):
#('AGENT_INFO_ITEMS', account, (agent, node, items))
try:
gajim.connections[account].services_cache.agent_items(array[0],
array[1], array[2])
except AttributeError:
return

Yann Leboulanger
committed
def handle_event_agent_info_info(self, account, array):
#('AGENT_INFO_INFO', account, (agent, node, identities, features, data))
try:
gajim.connections[account].services_cache.agent_info(array[0],
array[1], array[2], array[3], array[4])
except AttributeError:
return

Yann Leboulanger
committed
def handle_event_acc_ok(self, account, array):
#('ACC_OK', account, (config))
if self.instances.has_key('account_creation_wizard'):
self.instances['account_creation_wizard'].acc_is_ok(array)

nkour
committed
if self.remote_ctrl:
self.remote_ctrl.raise_signal('NewAccount', (account, array))
def handle_event_acc_not_ok(self, account, array):
#('ACC_NOT_OK', account, (reason))
if self.instances.has_key('account_creation_wizard'):
self.instances['account_creation_wizard'].acc_is_not_ok(array)
def handle_event_quit(self, p1, p2):

Yann Leboulanger
committed
self.roster.quit_gtkgui_interface()
def handle_event_myvcard(self, account, array):
if array.has_key('NICKNAME'):
nick = array['NICKNAME']

Yann Leboulanger
committed
gajim.nicks[account] = nick
if self.instances[account].has_key('profile'):
win = self.instances[account]['profile']

Yann Leboulanger
committed
win.set_values(array)
if account in self.show_vcard_when_connect:
self.show_vcard_when_connect.remove(account)
def handle_event_vcard(self, account, vcard):
'''vcard holds the vcard data'''
jid = vcard['jid']

Yann Leboulanger
committed
resource = ''
if vcard.has_key('resource'):
resource = vcard['resource']
# vcard window
if self.instances[account]['infos'].has_key(jid):
win = self.instances[account]['infos'][jid]

Yann Leboulanger
committed
elif resource and self.instances[account]['infos'].has_key(
jid + '/' + resource):
win = self.instances[account]['infos'][jid + '/' + resource]

Yann Leboulanger
committed
if win:
# show avatar in chat

Yann Leboulanger
committed
if resource and self.msg_win_mgr.has_window(
jid + '/' + resource, account):

Yann Leboulanger
committed
win = self.msg_win_mgr.get_window(jid + '/' + resource,
account)
ctrl = win.get_control(jid + '/' + resource, account)

Yann Leboulanger
committed
elif self.msg_win_mgr.has_window(jid, account):
win = self.msg_win_mgr.get_window(jid, account)
ctrl = win.get_control(jid, account)
if win and ctrl.type_id != message_control.TYPE_GC:
ctrl.show_avatar()

Yann Leboulanger
committed
# Show avatar in roster or gc_roster

Yann Leboulanger
committed
gc_ctrl = self.msg_win_mgr.get_control(jid, account)
if gc_ctrl and gc_ctrl.type_id == message_control.TYPE_GC:

Yann Leboulanger
committed
gc_ctrl.draw_avatar(resource)
else:
self.roster.draw_avatar(jid, account)

nkour
committed
if self.remote_ctrl:
self.remote_ctrl.raise_signal('VcardInfo', (account, vcard))

Yann Leboulanger
committed
def handle_event_last_status_time(self, account, array):
# ('LAST_STATUS_TIME', account, (jid, resource, seconds, status))
win = None
if self.instances[account]['infos'].has_key(array[0]):
win = self.instances[account]['infos'][array[0]]
elif self.instances[account]['infos'].has_key(array[0] + '/' + array[1]):
win = self.instances[account]['infos'][array[0] + '/' + array[1]]
if win:
c = gajim.contacts.get_contact(account, array[0], array[1])
# c is a list when no resource is given. it probably means that contact
# is offline, so only on Contact instance
if isinstance(c, list) and len(c):

Yann Leboulanger
committed
c = c[0]

Yann Leboulanger
committed
if c: # c can be none if it's a gc contact
c.last_status_time = time.localtime(time.time() - array[2])
if array[3]:
c.status = array[3]
win.set_last_status_time()

Yann Leboulanger
committed
if self.remote_ctrl:
self.remote_ctrl.raise_signal('LastStatusTime', (account, array))
def handle_event_os_info(self, account, array):

Yann Leboulanger
committed
#'OS_INFO' (account, (jid, resource, client_info, os_info))
if self.instances[account]['infos'].has_key(array[0]):
win = self.instances[account]['infos'][array[0]]
elif self.instances[account]['infos'].has_key(array[0] + '/' + array[1]):
win = self.instances[account]['infos'][array[0] + '/' + array[1]]
if win:
win.set_os_info(array[1], array[2], array[3])

nkour
committed
if self.remote_ctrl:
self.remote_ctrl.raise_signal('OsInfo', (account, array))
def handle_event_gc_notify(self, account, array):

nkour
committed
#'GC_NOTIFY' (account, (room_jid, show, status, nick,
# role, affiliation, jid, reason, actor, statusCode, newNick))
nick = array[3]
if not nick:
return
room_jid = array[0]
fjid = room_jid + '/' + nick
show = array[1]
status = array[2]
# Get the window and control for the updated status, this may be a PrivateChatControl

Yann Leboulanger
committed
control = self.msg_win_mgr.get_control(room_jid, account)
if control:
control.chg_contact_status(nick, show, status, array[4], array[5], array[6],
array[7], array[8], array[9], array[10])
# print status in chat window and update status/GPG image
if self.msg_win_mgr.has_window(fjid, account):
ctrl = self.msg_win_mgr.get_control(fjid, account)
contact = ctrl.contact
contact.show = show
contact.status = status
ctrl.update_ui()
uf_show = helpers.get_uf_show(show)
ctrl.print_conversation(_('%s is now %s (%s)') % (nick, uf_show, status),
'status')

jimpp
committed
ctrl.parent_win.redraw_tab(ctrl)
if self.remote_ctrl:
self.remote_ctrl.raise_signal('GCPresence', (account, array))
def handle_event_gc_msg(self, account, array):
# ('GC_MSG', account, (jid, msg, time, has_timestamp))

Yann Leboulanger
committed
room_jid = jids[0]

Yann Leboulanger
committed
gc_control = self.msg_win_mgr.get_control(room_jid, account)

Yann Leboulanger
committed
# message from server
nick = ''

Yann Leboulanger
committed
# message from someone
nick = jids[1]
gc_control.on_message(nick, array[1], array[2], array[3])

nkour
committed
if self.remote_ctrl:
self.remote_ctrl.raise_signal('GCMessage', (account, array))
def handle_event_gc_subject(self, account, array):
#('GC_SUBJECT', account, (jid, subject, body))

Yann Leboulanger
committed
gc_control = self.msg_win_mgr.get_control(jid, account)
# We can receive a subject with a body that contains "X has set the subject to Y" ...
if array[2]:
gc_control.print_conversation(array[2])
# ... Or the message comes from the occupant who set the subject
elif len(jids) > 1:
gc_control.print_conversation('%s has set the subject to %s' % (jids[1], array[1]))
def handle_event_gc_config(self, account, array):
#('GC_CONFIG', account, (jid, config)) config is a dict
room_jid = array[0].split('/')[0]
if room_jid in gajim.automatic_rooms[account]:
# use default configuration
gajim.connections[account].send_gc_config(room_jid, array[1])
# invite contacts
if gajim.automatic_rooms[account][room_jid].has_key('invities'):
for jid in gajim.automatic_rooms[account][room_jid]['invities']:
gajim.connections[account].send_invite(room_jid, jid)
del gajim.automatic_rooms[account][room_jid]
elif not self.instances[account]['gc_config'].has_key(room_jid):
self.instances[account]['gc_config'][room_jid] = \
config.GroupchatConfigWindow(account, room_jid, array[1])

Yann Leboulanger
committed
def handle_event_gc_affiliation(self, account, array):
#('GC_AFFILIATION', account, (room_jid, affiliation, list)) list is list
room_jid = array[0]
if self.instances[account]['gc_config'].has_key(room_jid):

Yann Leboulanger
committed
self.instances[account]['gc_config'][room_jid].\
affiliation_list_received(array[1], array[2])

Yann Leboulanger
committed
def handle_event_gc_invitation(self, account, array):
#('GC_INVITATION', (room_jid, jid_from, reason, password))

Yann Leboulanger
committed
jid = gajim.get_jid_without_resource(array[1])
room_jid = array[0]
if helpers.allow_popup_window(account) or not self.systray_enabled:

Yann Leboulanger
committed
dialogs.InvitationReceivedDialog(account, room_jid, jid, array[3],
array[2])
return
self.add_event(account, jid, 'gc-invitation', (room_jid, array[2],
array[3]))

Yann Leboulanger
committed
if helpers.allow_showing_notification(account, 'notify_on_new_message'):

Yann Leboulanger
committed
path = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events',
'gc_invitation.png')
path = gtkgui_helpers.get_path_to_generic_or_avatar(path)
event_type = _('Groupchat Invitation')
notify.popup(event_type, jid, account, 'gc-invitation', path,
event_type, room_jid)

Yann Leboulanger
committed
def handle_event_bad_passphrase(self, account, array):
use_gpg_agent = gajim.config.get('use_gpg_agent')
if use_gpg_agent:
return
keyID = gajim.config.get_per('accounts', account, 'keyid')
self.roster.forget_gpg_passphrase(keyID)
dialogs.WarningDialog(_('Your passphrase is incorrect'),

Yann Leboulanger
committed
_('You are currently connected without your OpenPGP key.'))

Yann Leboulanger
committed
def handle_event_roster_info(self, account, array):
#('ROSTER_INFO', account, (jid, name, sub, ask, groups))
jid = array[0]

Yann Leboulanger
committed
name = array[1]
sub = array[2]
ask = array[3]
groups = array[4]
contacts = gajim.contacts.get_contacts_from_jid(account, jid)
# contact removes us.

Yann Leboulanger
committed
if (not sub or sub == 'none') and (not ask or ask == 'none') and \
not name and not groups:
if contacts:
c = contacts[0]
self.roster.remove_contact(c, account)
gajim.contacts.remove_jid(account, jid)

Yann Leboulanger
committed
if gajim.events.get_events(account, c.jid):
keyID = ''
attached_keys = gajim.config.get_per('accounts', account,
'attached_gpg_keys').split()
if jid in attached_keys:
keyID = attached_keys[attached_keys.index(jid) + 1]
contact = gajim.contacts.create_contact(jid = c.jid,