Skip to content
Snippets Groups Projects
gajim.py 12.3 KiB
Newer Older
roidelapluie's avatar
roidelapluie committed
# -*- coding:utf-8 -*-
roidelapluie's avatar
roidelapluie committed
## src/common/gajim.py
Yann Leboulanger's avatar
Yann Leboulanger committed
##
roidelapluie's avatar
roidelapluie committed
## Copyright (C) 2003-2008 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2005-2006 Dimitur Kirov <dkirov AT gmail.com>
##                         Travis Shirk <travis AT pobox.com>
##                         Nikos Kouremenos <kourem AT gmail.com>
roidelapluie's avatar
roidelapluie committed
## Copyright (C) 2006 Junglecow J <junglecow AT gmail.com>
roidelapluie's avatar
roidelapluie committed
##                    Stefan Bethge <stefan AT lanpartei.de>
## Copyright (C) 2006-2008 Jean-Marie Traissard <jim AT lapin.org>
## Copyright (C) 2007-2008 Brendan Taylor <whateley AT gmail.com>
##                         Stephan Erb <steve-e AT h3c.de>
## Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org>
Yann Leboulanger's avatar
Yann Leboulanger committed
##
Yann Leboulanger's avatar
Yann Leboulanger committed
## This file is part of Gajim.
##
## Gajim is free software; you can redistribute it and/or modify
Yann Leboulanger's avatar
Yann Leboulanger committed
## it under the terms of the GNU General Public License as published
Yann Leboulanger's avatar
Yann Leboulanger committed
## by the Free Software Foundation; version 3 only.
Yann Leboulanger's avatar
Yann Leboulanger committed
##
Yann Leboulanger's avatar
Yann Leboulanger committed
## Gajim is distributed in the hope that it will be useful,
Yann Leboulanger's avatar
Yann Leboulanger committed
## but WITHOUT ANY WARRANTY; without even the implied warranty of
roidelapluie's avatar
roidelapluie committed
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Yann Leboulanger's avatar
Yann Leboulanger committed
## GNU General Public License for more details.
##
Yann Leboulanger's avatar
Yann Leboulanger committed
## You should have received a copy of the GNU General Public License
roidelapluie's avatar
roidelapluie committed
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
Yann Leboulanger's avatar
Yann Leboulanger committed
##
Yann Leboulanger's avatar
Yann Leboulanger committed

Yann Leboulanger's avatar
Yann Leboulanger committed
import logging
from contacts import Contacts
sb's avatar
sb committed
from events import Events
Yann Leboulanger's avatar
Yann Leboulanger committed

dkirov's avatar
dkirov committed
try:
	import defs
except ImportError:
	print >> sys.stderr, '''defs.py is missing!

If you start gajim from svn:
 * Make sure you have GNU autotools installed.
   This includes the following packages:
    automake >= 1.8
    autoconf >= 2.59
    intltool-0.35
    libtool
 * Run
    $ sh autogen.sh
 * Optionally, install gajim
    $ make
    $ sudo make install

**** Note for translators ****
 You can get the latest string updates, by running:
    $ cd po/
    $ make update-po

'''
dkirov's avatar
dkirov committed
	sys.exit(1)
interface = None # The actual interface (the gtk one for the moment)
thread_interface = None # Interface to run a thread and then a callback
version = config.get('version')
dkirov's avatar
dkirov committed
connections = {} # 'account name': 'account (connection.Connection) instance'
ipython_window = None
log = logging.getLogger('gajim')
import logger
logger = logger.Logger() # init the logger
import configpaths
gajimpaths = configpaths.gajimpaths
nkour's avatar
nkour committed

LOGPATH = gajimpaths['LOG'] # deprecated
VCARD_PATH = gajimpaths['VCARD']
AVATAR_PATH = gajimpaths['AVATAR']
MY_EMOTS_PATH = gajimpaths['MY_EMOTS']
MY_ICONSETS_PATH = gajimpaths['MY_ICONSETS']
js's avatar
js committed
MY_MOOD_ICONSETS_PATH = gajimpaths['MY_MOOD_ICONSETS']
js's avatar
js committed
MY_ACTIVITY_ICONSETS_PATH = gajimpaths['MY_ACTIVITY_ICONSETS']
Yann Leboulanger's avatar
Yann Leboulanger committed
MY_CACERTS =  gajimpaths['MY_CACERTS']
TMP = gajimpaths['TMP']
DATA_DIR = gajimpaths['DATA']
HOME_DIR = gajimpaths['HOME']
try:
	LANG = locale.getdefaultlocale()[0] # en_US, fr_FR, el_GR etc..
except (ValueError, locale.Error):
	# unknown locale, use en is better than fail
	LANG = None
	LANG = 'en'
else:
	LANG = LANG[:2] # en, fr, el etc..
os_info = None # used to cache os information

sb's avatar
sb committed
gmail_domains = ['gmail.com', 'googlemail.com']

transport_type = {} # list the type of transport

last_message_time = {} # list of time of the latest incomming message
							# {acct1: {jid1: time1, jid2: time2}, }
encrypted_chats = {} # list of encrypted chats {acct1: [jid1, jid2], ..}
contacts = Contacts()
Yann Leboulanger's avatar
Yann Leboulanger committed
gc_connected = {} # tell if we are connected to the room or not {acct: {room_jid: True}}
gc_passwords = {} # list of the pass required to enter a room {room_jid: password}
sb's avatar
sb committed
automatic_rooms = {} # list of rooms that must be automaticaly configured and for which we have a list of invities {account: {room_jid: {'invities': []}}}
groups = {} # list of groups
newly_added = {} # list of contacts that has just signed in
to_be_removed = {} # list of contacts that has just signed out
sb's avatar
sb committed
events = Events()

nicks = {} # list of our nick names in each account
# should we block 'contact signed in' notifications for this account?
# this is only for the first 30 seconds after we change our show
# to something else than offline
sb's avatar
sb committed
# can also contain account/transport_jid to block notifications for contacts
# from this transport
block_signed_in_notifications = {}
con_types = {} # type of each connection (ssl, tls, tcp, ...)

sleeper_state = {} # whether we pass auto away / xa or not
#'off': don't use sleeper for this account
#'online': online and use sleeper
#'autoaway': autoaway and use sleeper
#'autoxa': autoxa and use sleeper
# jid of transport contacts for which we need to ask avatar when transport will
# be online
transport_avatar = {} # {transport_jid: [jid_list]}

Piotr Gaczkowski's avatar
Piotr Gaczkowski committed
# Is Gnome configured to activate on single click ?
single_click = False
nkour's avatar
nkour committed
SHOW_LIST = ['offline', 'connecting', 'online', 'chat', 'away', 'xa', 'dnd',
junglecow's avatar
junglecow committed
	'invisible', 'error']
# zeroconf account name
ZEROCONF_ACC_NAME = 'Local'
Yann Leboulanger's avatar
Yann Leboulanger committed
HAVE_PYCRYPTO = True
try:
	import Crypto
except ImportError:
	HAVE_PYCRYPTO = False

HAVE_PYSEXY = True
try:
	import sexy
except ImportError:
	HAVE_PYSEXY = False

	import GnuPGInterface
	from os import system
	if system('gpg -h >/dev/null 2>&1'):
import latex
HAVE_LATEX = latex.check_for_latex_support()
gajim_identity = {'type': 'pc', 'category': 'client', 'name': 'Gajim'}
gajim_common_features = [xmpp.NS_BYTESTREAM, xmpp.NS_SI, xmpp.NS_FILE,
	xmpp.NS_MUC, xmpp.NS_MUC_USER, xmpp.NS_MUC_ADMIN, xmpp.NS_MUC_OWNER,
	xmpp.NS_MUC_CONFIG, xmpp.NS_COMMANDS, xmpp.NS_DISCO_INFO, 'ipv6',
	'jabber:iq:gateway', xmpp.NS_LAST, xmpp.NS_PRIVACY, xmpp.NS_PRIVATE,
	xmpp.NS_REGISTER, xmpp.NS_VERSION, xmpp.NS_DATA, xmpp.NS_ENCRYPTED, 'msglog',
	'sslc2s', 'stringprep', xmpp.NS_PING, xmpp.NS_TIME_REVISED, xmpp.NS_SSN,
Yann Leboulanger's avatar
Yann Leboulanger committed
	xmpp.NS_MOOD, xmpp.NS_ACTIVITY, xmpp.NS_NICK]
# Optional features gajim supports per account
gajim_optional_features = {}

# Capabilities hash per account
caps_hash = {}
def get_nick_from_jid(jid):
	pos = jid.find('@')
	return jid[:pos]

def get_server_from_jid(jid):
nkour's avatar
nkour committed
	pos = jid.find('@') + 1 # after @
def get_nick_from_fjid(jid):
	# fake jid is the jid for a contact in a room
	# gaim@conference.jabber.no/nick/nick-continued
sb's avatar
sb committed
def get_name_and_server_from_jid(jid):
	name = get_nick_from_jid(jid)
	server = get_server_from_jid(jid)
sb's avatar
sb committed
	return name, server
def get_room_and_nick_from_fjid(jid):
	# fake jid is the jid for a contact in a room
	# gaim@conference.jabber.no/nick/nick-continued
	# return ('gaim@conference.jabber.no', 'nick/nick-continued')
	l = jid.split('/', 1)

def get_real_jid_from_fjid(account, fjid):
	room_jid, nick = get_room_and_nick_from_fjid(fjid)
	if not nick: # It's not a fake_jid, it is a real jid
Yann Leboulanger's avatar
Yann Leboulanger committed
		return fjid # we return the real jid
	if interface.msg_win_mgr.get_gc_control(room_jid, account):
		# It's a pm, so if we have real jid it's in contact.jid
nicfit's avatar
nicfit committed
		gc_contact = contacts.get_gc_contact(account, room_jid, nick)
		if not gc_contact:
nicfit's avatar
nicfit committed
		# gc_contact.jid is None when it's not a real jid (we don't know real jid)
		real_jid = gc_contact.jid
def get_room_from_fjid(jid):
	return get_room_and_nick_from_fjid(jid)[0]
def get_contact_name_from_jid(account, jid):
nicfit's avatar
nicfit committed
	c = contacts.get_first_contact_from_jid(account, jid)
	return c.name
nkour's avatar
nkour committed
def get_jid_without_resource(jid):
	return jid.split('/')[0]

def construct_fjid(room_jid, nick):
	''' nick is in utf8 (taken from treeview); room_jid is in unicode'''
	# fake jid is the jid for a contact in a room
	# gaim@conference.jabber.org/nick
	if isinstance(nick, str):
		nick = unicode(nick, 'utf-8')
	return room_jid + '/' + nick
	jids = jid.split('/', 1)
	if len(jids) > 1:
		return jids[1] # abc@doremi.org/res/res-continued
	else:
		return ''

# [15:34:28] <asterix> we should add contact.fake_jid I think
# [15:34:46] <asterix> so if we know real jid, it wil be in contact.jid, or we look in contact.fake_jid
# [15:32:54] <asterix> they can have resource if we know the real jid
# [15:33:07] <asterix> and that resource is in contact.resource

def get_number_of_accounts():
	'''returns the number of ALL accounts'''
	return len(connections.keys())
def get_number_of_connected_accounts(accounts_list = None):
	'''returns the number of CONNECTED accounts
	you can optionally pass an accounts_list
	and if you do those will be checked, else all will be checked'''
	connected_accounts = 0
	if accounts_list is None:
		accounts = connections.keys()
	else:
		accounts = accounts_list
dkirov's avatar
dkirov committed
	for account in accounts:
		if account_is_connected(account):
			connected_accounts = connected_accounts + 1
	return connected_accounts

dkirov's avatar
dkirov committed
def account_is_connected(account):
	if account not in connections:
		return False
	if connections[account].connected > 1: # 0 is offline, 1 is connecting
		return True
	else:
		return False

def account_is_disconnected(account):
	return not account_is_connected(account)

def zeroconf_is_connected():
	return account_is_connected(ZEROCONF_ACC_NAME) and \
		config.get_per('accounts', ZEROCONF_ACC_NAME, 'is_zeroconf')

dkirov's avatar
dkirov committed
def get_number_of_securely_connected_accounts():
	'''returns the number of the accounts that are SSL/TLS connected'''
	num_of_secured = 0
	for account in connections.keys():
dkirov's avatar
dkirov committed
		if account_is_securely_connected(account):
			num_of_secured += 1
	return num_of_secured

def account_is_securely_connected(account):
	if account_is_connected(account) and \
	account in con_types and con_types[account] in ('tls', 'ssl'):
dkirov's avatar
dkirov committed
		return True
	else:
		return False

nkour's avatar
nkour committed
def get_transport_name_from_jid(jid, use_config_setting = True):
	'''returns 'aim', 'gg', 'irc' etc
	if JID is not from transport returns None'''
	#FIXME: jid can be None! one TB I saw had this problem:
	# in the code block # it is a groupchat presence in handle_event_notify
	# jid was None. Yann why?
	if not jid or (use_config_setting and not config.get('use_transports_iconsets')):
nkour's avatar
nkour committed
		return
sb's avatar
sb committed

sb's avatar
sb committed
	if host in transport_type:
		return transport_type[host]

	# host is now f.e. icq.foo.org or just icq (sometimes on hacky transports)
	host_splitted = host.split('.')
	if len(host_splitted) != 0:
		# now we support both 'icq.' and 'icq' but not icqsucks.org
		host = host_splitted[0]

	if host in ('aim', 'irc', 'icq', 'msn', 'sms', 'tlen', 'weather', 'yahoo',
	'mrim'):
		return host
sb's avatar
sb committed
		return 'gadu-gadu'
	elif host == 'jit':
		return 'icq'
nkour's avatar
nkour committed
	else:
		return None
nkour's avatar
nkour committed

def jid_is_transport(jid):
	# if not '@' or '@' starts the jid then it is transport
	if jid.find('@') <= 0:
		return True
Yann Leboulanger's avatar
Yann Leboulanger committed
	return False

def get_jid_from_account(account_name):
nkour's avatar
nkour committed
	'''return the jid we use in the given account'''
	name = config.get_per('accounts', account_name, 'name')
nkour's avatar
nkour committed
	hostname = config.get_per('accounts', account_name, 'hostname')
	jid = name + '@' + hostname
	return jid
nkour's avatar
nkour committed
def get_our_jids():
	'''returns a list of the jids we use in our accounts'''
	our_jids = list()
	for account in contacts.get_accounts():
		our_jids.append(get_jid_from_account(account))
	return our_jids

def get_hostname_from_account(account_name, use_srv = False):
	'''returns hostname (if custom hostname is used, that is returned)'''
	if use_srv and connections[account_name].connected_hostname:
		return connections[account_name].connected_hostname
	if config.get_per('accounts', account_name, 'use_custom_host'):
		return config.get_per('accounts', account_name, 'custom_host')
	return config.get_per('accounts', account_name, 'hostname')
def get_notification_image_prefix(jid):
	'''returns the prefix for the notification images'''
	transport_name = get_transport_name_from_jid(jid)
	if transport_name in ('aim', 'icq', 'msn', 'yahoo'):
		prefix = transport_name
	else:
		prefix = 'jabber'
	return prefix

def get_name_from_jid(account, jid):
	'''returns from JID's shown name and if no contact returns jids'''
	contact = contacts.get_first_contact_from_jid(account, jid)
	if contact:
		actor = contact.get_shown_name()
	else:
		actor = jid
	return actor
dkirov's avatar
dkirov committed

def get_priority(account, show):
	'''return the priority an account must have'''
	if not show:
		show = 'online'
sb's avatar
sb committed

	if show in ('online', 'chat', 'away', 'xa', 'dnd', 'invisible') and \
	config.get_per('accounts', account, 'adjust_priority_with_status'):
		return config.get_per('accounts', account, 'autopriority_' + show)
dkirov's avatar
dkirov committed
	return config.get_per('accounts', account, 'priority')
steve-e's avatar
steve-e committed
# vim: se ts=3: