Package common :: Module gajim
[hide private]
[frames] | no frames]

Source Code for Module common.gajim

  1  # -*- coding:utf-8 -*- 
  2  ## src/common/gajim.py 
  3  ## 
  4  ## Copyright (C) 2003-2010 Yann Leboulanger <asterix AT lagaule.org> 
  5  ## Copyright (C) 2005-2006 Dimitur Kirov <dkirov AT gmail.com> 
  6  ##                         Travis Shirk <travis AT pobox.com> 
  7  ##                         Nikos Kouremenos <kourem AT gmail.com> 
  8  ## Copyright (C) 2006 Junglecow J <junglecow AT gmail.com> 
  9  ##                    Stefan Bethge <stefan AT lanpartei.de> 
 10  ## Copyright (C) 2006-2008 Jean-Marie Traissard <jim AT lapin.org> 
 11  ## Copyright (C) 2007-2008 Brendan Taylor <whateley AT gmail.com> 
 12  ##                         Stephan Erb <steve-e AT h3c.de> 
 13  ## Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org> 
 14  ## 
 15  ## This file is part of Gajim. 
 16  ## 
 17  ## Gajim is free software; you can redistribute it and/or modify 
 18  ## it under the terms of the GNU General Public License as published 
 19  ## by the Free Software Foundation; version 3 only. 
 20  ## 
 21  ## Gajim is distributed in the hope that it will be useful, 
 22  ## but WITHOUT ANY WARRANTY; without even the implied warranty of 
 23  ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 24  ## GNU General Public License for more details. 
 25  ## 
 26  ## You should have received a copy of the GNU General Public License 
 27  ## along with Gajim. If not, see <http://www.gnu.org/licenses/>. 
 28  ## 
 29   
 30  import sys 
 31  import logging 
 32  import locale 
 33   
 34  import config 
 35  import xmpp 
 36   
 37  try: 
 38      import defs 
 39  except ImportError: 
 40      print >> sys.stderr, '''defs.py is missing! 
 41   
 42  If you start gajim from svn: 
 43  * Make sure you have GNU autotools installed. 
 44  This includes the following packages: 
 45  automake >= 1.8 
 46  autoconf >= 2.59 
 47  intltool-0.35 
 48  libtool 
 49  * Run 
 50  $ sh autogen.sh 
 51  * Optionally, install gajim 
 52  $ make 
 53  $ sudo make install 
 54   
 55  **** Note for translators **** 
 56  You can get the latest string updates, by running: 
 57  $ cd po/ 
 58  $ make update-po 
 59   
 60  ''' 
 61      sys.exit(1) 
 62   
 63  interface = None # The actual interface (the gtk one for the moment) 
 64  thread_interface = None # Interface to run a thread and then a callback 
 65  config = config.Config() 
 66  version = config.get('version') 
 67  connections = {} # 'account name': 'account (connection.Connection) instance' 
 68  ipython_window = None 
 69   
 70  ged = None # Global Events Dispatcher 
 71  nec = None # Network Events Controller 
 72  plugin_manager = None # Plugins Manager 
 73   
 74  log = logging.getLogger('gajim') 
 75   
 76  import logger 
 77  logger = logger.Logger() # init the logger 
 78   
 79  import configpaths 
 80  gajimpaths = configpaths.gajimpaths 
 81   
 82  VCARD_PATH = gajimpaths['VCARD'] 
 83  AVATAR_PATH = gajimpaths['AVATAR'] 
 84  MY_EMOTS_PATH = gajimpaths['MY_EMOTS'] 
 85  MY_ICONSETS_PATH = gajimpaths['MY_ICONSETS'] 
 86  MY_MOOD_ICONSETS_PATH = gajimpaths['MY_MOOD_ICONSETS'] 
 87  MY_ACTIVITY_ICONSETS_PATH = gajimpaths['MY_ACTIVITY_ICONSETS'] 
 88  MY_CACERTS = gajimpaths['MY_CACERTS'] 
 89  TMP = gajimpaths['TMP'] 
 90  DATA_DIR = gajimpaths['DATA'] 
 91  ICONS_DIR = gajimpaths['ICONS'] 
 92  HOME_DIR = gajimpaths['HOME'] 
 93  PLUGINS_DIRS = [gajimpaths['PLUGINS_BASE'], 
 94                  gajimpaths['PLUGINS_USER']] 
 95  PLUGINS_CONFIG_DIR = gajimpaths['PLUGINS_CONFIG_DIR'] 
 96   
 97  try: 
 98      LANG = locale.getdefaultlocale()[0] # en_US, fr_FR, el_GR etc.. 
 99  except (ValueError, locale.Error): 
100      # unknown locale, use en is better than fail 
101      LANG = None 
102  if LANG is None: 
103      LANG = 'en' 
104  else: 
105      LANG = LANG[:2] # en, fr, el etc.. 
106   
107  os_info = None # used to cache os information 
108   
109  from contacts import LegacyContactsAPI 
110  from events import Events 
111   
112  gmail_domains = ['gmail.com', 'googlemail.com'] 
113   
114  transport_type = {} # list the type of transport 
115   
116  last_message_time = {} # list of time of the latest incomming message 
117                                                          # {acct1: {jid1: time1, jid2: time2}, } 
118  encrypted_chats = {} # list of encrypted chats {acct1: [jid1, jid2], ..} 
119   
120  contacts = LegacyContactsAPI() 
121  gc_connected = {} # tell if we are connected to the room or not {acct: {room_jid: True}} 
122  gc_passwords = {} # list of the pass required to enter a room {room_jid: password} 
123  automatic_rooms = {} # list of rooms that must be automaticaly configured and for which we have a list of invities {account: {room_jid: {'invities': []}}} 
124  new_room_nick = None # if it's != None, use this nick instead of asking for a new nickname when there is a conflict. 
125   
126  groups = {} # list of groups 
127  newly_added = {} # list of contacts that has just signed in 
128  to_be_removed = {} # list of contacts that has just signed out 
129   
130  events = Events() 
131   
132  nicks = {} # list of our nick names in each account 
133  # should we block 'contact signed in' notifications for this account? 
134  # this is only for the first 30 seconds after we change our show 
135  # to something else than offline 
136  # can also contain account/transport_jid to block notifications for contacts 
137  # from this transport 
138  block_signed_in_notifications = {} 
139  con_types = {} # type of each connection (ssl, tls, tcp, ...) 
140   
141  sleeper_state = {} # whether we pass auto away / xa or not 
142  #'off': don't use sleeper for this account 
143  #'online': online and use sleeper 
144  #'autoaway': autoaway and use sleeper 
145  #'autoxa': autoxa and use sleeper 
146  status_before_autoaway = {} 
147   
148  # jid of transport contacts for which we need to ask avatar when transport will 
149  # be online 
150  transport_avatar = {} # {transport_jid: [jid_list]} 
151   
152  # Is Gnome configured to activate on single click ? 
153  single_click = False 
154  SHOW_LIST = ['offline', 'connecting', 'online', 'chat', 'away', 'xa', 'dnd', 
155          'invisible', 'error'] 
156   
157  # zeroconf account name 
158  ZEROCONF_ACC_NAME = 'Local' 
159   
160  HAVE_ZEROCONF = True 
161  try: 
162      import avahi 
163  except ImportError: 
164      try: 
165          import pybonjour 
166      except Exception: # Linux raises ImportError, Windows raises WindowsError 
167          HAVE_ZEROCONF = False 
168   
169  HAVE_PYCRYPTO = True 
170  try: 
171      import Crypto 
172  except ImportError: 
173      HAVE_PYCRYPTO = False 
174   
175  HAVE_GPG = True 
176  try: 
177      import GnuPGInterface 
178  except ImportError: 
179      HAVE_GPG = False 
180  else: 
181      from os import system 
182      if system('gpg -h >/dev/null 2>&1'): 
183          HAVE_GPG = False 
184   
185  # Depends on use_latex option. Will be correctly set after we config options are 
186  # read. 
187  HAVE_LATEX = False 
188   
189  HAVE_FARSIGHT = True 
190  try: 
191      import farsight, gst 
192  except ImportError: 
193      HAVE_FARSIGHT = False 
194  gajim_identity = {'type': 'pc', 'category': 'client', 'name': 'Gajim'} 
195  gajim_common_features = [xmpp.NS_BYTESTREAM, xmpp.NS_SI, xmpp.NS_FILE, 
196          xmpp.NS_MUC, xmpp.NS_MUC_USER, xmpp.NS_MUC_ADMIN, xmpp.NS_MUC_OWNER, 
197          xmpp.NS_MUC_CONFIG, xmpp.NS_COMMANDS, xmpp.NS_DISCO_INFO, 'ipv6', 
198          'jabber:iq:gateway', xmpp.NS_LAST, xmpp.NS_PRIVACY, xmpp.NS_PRIVATE, 
199          xmpp.NS_REGISTER, xmpp.NS_VERSION, xmpp.NS_DATA, xmpp.NS_ENCRYPTED, 'msglog', 
200          'sslc2s', 'stringprep', xmpp.NS_PING, xmpp.NS_TIME_REVISED, xmpp.NS_SSN, 
201          xmpp.NS_MOOD, xmpp.NS_ACTIVITY, xmpp.NS_NICK, xmpp.NS_ROSTERX, xmpp.NS_SECLABEL] 
202   
203  # Optional features gajim supports per account 
204  gajim_optional_features = {} 
205   
206  # Capabilities hash per account 
207  caps_hash = {} 
208   
209  import caps_cache 
210  caps_cache.initialize(logger) 
211   
212 -def get_nick_from_jid(jid):
213 pos = jid.find('@') 214 return jid[:pos]
215
216 -def get_server_from_jid(jid):
217 pos = jid.find('@') + 1 # after @ 218 return jid[pos:]
219
220 -def get_name_and_server_from_jid(jid):
221 name = get_nick_from_jid(jid) 222 server = get_server_from_jid(jid) 223 return name, server
224
225 -def get_room_and_nick_from_fjid(jid):
226 # fake jid is the jid for a contact in a room 227 # gaim@conference.jabber.no/nick/nick-continued 228 # return ('gaim@conference.jabber.no', 'nick/nick-continued') 229 l = jid.split('/', 1) 230 if len(l) == 1: # No nick 231 l.append('') 232 return l
233
234 -def get_real_jid_from_fjid(account, fjid):
235 """ 236 Return real jid or returns None, if we don't know the real jid 237 """ 238 room_jid, nick = get_room_and_nick_from_fjid(fjid) 239 if not nick: # It's not a fake_jid, it is a real jid 240 return fjid # we return the real jid 241 real_jid = fjid 242 if interface.msg_win_mgr.get_gc_control(room_jid, account): 243 # It's a pm, so if we have real jid it's in contact.jid 244 gc_contact = contacts.get_gc_contact(account, room_jid, nick) 245 if not gc_contact: 246 return 247 # gc_contact.jid is None when it's not a real jid (we don't know real jid) 248 real_jid = gc_contact.jid 249 return real_jid
250
251 -def get_room_from_fjid(jid):
252 return get_room_and_nick_from_fjid(jid)[0]
253
254 -def get_contact_name_from_jid(account, jid):
255 c = contacts.get_first_contact_from_jid(account, jid) 256 return c.name
257
258 -def get_jid_without_resource(jid):
259 return jid.split('/')[0]
260
261 -def construct_fjid(room_jid, nick):
262 """ 263 Nick is in UTF-8 (taken from treeview); room_jid is in unicode 264 """ 265 # fake jid is the jid for a contact in a room 266 # gaim@conference.jabber.org/nick 267 if isinstance(nick, str): 268 nick = unicode(nick, 'utf-8') 269 return room_jid + '/' + nick
270
271 -def get_resource_from_jid(jid):
272 jids = jid.split('/', 1) 273 if len(jids) > 1: 274 return jids[1] # abc@doremi.org/res/res-continued 275 else: 276 return ''
277
278 -def get_number_of_accounts():
279 """ 280 Return the number of ALL accounts 281 """ 282 return len(connections.keys())
283
284 -def get_number_of_connected_accounts(accounts_list = None):
285 """ 286 Returns the number of CONNECTED accounts. Uou can optionally pass an 287 accounts_list and if you do those will be checked, else all will be checked 288 """ 289 connected_accounts = 0 290 if accounts_list is None: 291 accounts = connections.keys() 292 else: 293 accounts = accounts_list 294 for account in accounts: 295 if account_is_connected(account): 296 connected_accounts = connected_accounts + 1 297 return connected_accounts
298
299 -def account_is_connected(account):
300 if account not in connections: 301 return False 302 if connections[account].connected > 1: # 0 is offline, 1 is connecting 303 return True 304 else: 305 return False
306
307 -def account_is_disconnected(account):
308 return not account_is_connected(account)
309
310 -def zeroconf_is_connected():
311 return account_is_connected(ZEROCONF_ACC_NAME) and \ 312 config.get_per('accounts', ZEROCONF_ACC_NAME, 'is_zeroconf')
313
314 -def get_number_of_securely_connected_accounts():
315 """ 316 Return the number of the accounts that are SSL/TLS connected 317 """ 318 num_of_secured = 0 319 for account in connections.keys(): 320 if account_is_securely_connected(account): 321 num_of_secured += 1 322 return num_of_secured
323
324 -def account_is_securely_connected(account):
325 if account_is_connected(account) and \ 326 account in con_types and con_types[account] in ('tls', 'ssl'): 327 return True 328 else: 329 return False
330
331 -def get_transport_name_from_jid(jid, use_config_setting = True):
332 """ 333 Returns 'aim', 'gg', 'irc' etc 334 335 If JID is not from transport returns None. 336 """ 337 #FIXME: jid can be None! one TB I saw had this problem: 338 # in the code block # it is a groupchat presence in handle_event_notify 339 # jid was None. Yann why? 340 if not jid or (use_config_setting and not config.get('use_transports_iconsets')): 341 return 342 343 host = get_server_from_jid(jid) 344 if host in transport_type: 345 return transport_type[host] 346 347 # host is now f.e. icq.foo.org or just icq (sometimes on hacky transports) 348 host_splitted = host.split('.') 349 if len(host_splitted) != 0: 350 # now we support both 'icq.' and 'icq' but not icqsucks.org 351 host = host_splitted[0] 352 353 if host in ('aim', 'irc', 'icq', 'msn', 'sms', 'tlen', 'weather', 'yahoo', 354 'mrim', 'facebook'): 355 return host 356 elif host == 'gg': 357 return 'gadu-gadu' 358 elif host == 'jit': 359 return 'icq' 360 elif host == 'facebook': 361 return 'facebook' 362 else: 363 return None
364
365 -def jid_is_transport(jid):
366 # if not '@' or '@' starts the jid then it is transport 367 if jid.find('@') <= 0: 368 return True 369 return False
370
371 -def get_jid_from_account(account_name):
372 """ 373 Return the jid we use in the given account 374 """ 375 name = config.get_per('accounts', account_name, 'name') 376 hostname = config.get_per('accounts', account_name, 'hostname') 377 jid = name + '@' + hostname 378 return jid
379
380 -def get_our_jids():
381 """ 382 Returns a list of the jids we use in our accounts 383 """ 384 our_jids = list() 385 for account in contacts.get_accounts(): 386 our_jids.append(get_jid_from_account(account)) 387 return our_jids
388
389 -def get_hostname_from_account(account_name, use_srv = False):
390 """ 391 Returns hostname (if custom hostname is used, that is returned) 392 """ 393 if use_srv and connections[account_name].connected_hostname: 394 return connections[account_name].connected_hostname 395 if config.get_per('accounts', account_name, 'use_custom_host'): 396 return config.get_per('accounts', account_name, 'custom_host') 397 return config.get_per('accounts', account_name, 'hostname')
398
399 -def get_notification_image_prefix(jid):
400 """ 401 Returns the prefix for the notification images 402 """ 403 transport_name = get_transport_name_from_jid(jid) 404 if transport_name in ('aim', 'icq', 'msn', 'yahoo', 'facebook'): 405 prefix = transport_name 406 else: 407 prefix = 'jabber' 408 return prefix
409
410 -def get_name_from_jid(account, jid):
411 """ 412 Return from JID's shown name and if no contact returns jids 413 """ 414 contact = contacts.get_first_contact_from_jid(account, jid) 415 if contact: 416 actor = contact.get_shown_name() 417 else: 418 actor = jid 419 return actor
420
421 -def get_priority(account, show):
422 """ 423 Return the priority an account must have 424 """ 425 if not show: 426 show = 'online' 427 428 if show in ('online', 'chat', 'away', 'xa', 'dnd', 'invisible') and \ 429 config.get_per('accounts', account, 'adjust_priority_with_status'): 430 return config.get_per('accounts', account, 'autopriority_' + show) 431 return config.get_per('accounts', account, 'priority')
432