2008-08-15 19:31:51 +02:00
# -*- coding:utf-8 -*-
2008-08-15 05:20:23 +02:00
## src/gajim.py
2003-11-30 23:40:24 +01:00
##
2008-08-15 05:20:23 +02:00
## Copyright (C) 2003-2008 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2004-2005 Vincent Hanquez <tab AT snarc.org>
## Copyright (C) 2005 Alex Podaras <bigpod AT gmail.com>
## Norman Rasmussen <norman AT rasmussen.co.za>
2008-08-15 19:31:51 +02:00
## Stéphan Kochen <stephan AT kochen.nl>
2008-08-15 05:20:23 +02:00
## Copyright (C) 2005-2006 Dimitur Kirov <dkirov AT gmail.com>
## Alex Mauer <hawke AT hawkesnest.net>
## Copyright (C) 2005-2007 Travis Shirk <travis AT pobox.com>
## Nikos Kouremenos <kourem AT gmail.com>
2008-08-15 19:31:51 +02:00
## Copyright (C) 2006 Junglecow J <junglecow AT gmail.com>
2008-08-15 05:20:23 +02:00
## Stefan Bethge <stefan AT lanpartei.de>
## Copyright (C) 2006-2008 Jean-Marie Traissard <jim AT lapin.org>
## Copyright (C) 2007 Lukas Petrovicky <lukas AT petrovicky.net>
## James Newton <redshodan AT gmail.com>
## Copyright (C) 2007-2008 Brendan Taylor <whateley AT gmail.com>
## Julien Pivotto <roidelapluie AT gmail.com>
## Stephan Erb <steve-e AT h3c.de>
## Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org>
2003-11-30 23:40:24 +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
2003-11-30 23:40:24 +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.
2003-11-30 23:40:24 +01:00
##
2007-12-12 09:44:46 +01:00
## Gajim is distributed in the hope that it will be useful,
2003-11-30 23:40:24 +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
2003-11-30 23:40:24 +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
##
2005-11-13 15:55:52 +01:00
2005-08-16 13:55:29 +02:00
import os
2009-06-16 09:30:04 +02:00
import sys
2008-12-03 22:23:04 +01:00
import warnings
2007-12-12 09:44:46 +01:00
if os . name == ' nt ' :
warnings . filterwarnings ( action = ' ignore ' )
2008-05-19 12:58:03 +02:00
if os . path . isdir ( ' gtk ' ) :
# Used to create windows installer with GTK included
paths = os . environ [ ' PATH ' ]
list_ = paths . split ( ' ; ' )
new_list = [ ]
for p in list_ :
if p . find ( ' gtk ' ) < 0 and p . find ( ' GTK ' ) < 0 :
new_list . append ( p )
new_list . insert ( 0 , ' gtk/lib ' )
new_list . insert ( 0 , ' gtk/bin ' )
os . environ [ ' PATH ' ] = ' ; ' . join ( new_list )
os . environ [ ' GTK_BASEPATH ' ] = ' gtk '
2007-12-12 09:44:46 +01:00
2008-11-19 22:47:28 +01:00
if os . name == ' nt ' :
# needed for docutils
sys . path . append ( ' . ' )
2009-03-11 10:16:07 +01:00
from common import logging_helpers
logging_helpers . init ( ' TERM ' in os . environ )
2006-12-23 22:18:07 +01:00
import logging
2009-03-11 10:16:07 +01:00
# gajim.gui or gajim.gtk more appropriate ?
2006-12-23 22:18:07 +01:00
log = logging . getLogger ( ' gajim.gajim ' )
import getopt
2006-06-15 08:49:04 +02:00
2006-12-23 22:18:07 +01:00
def parseOpts ( ) :
profile = ' '
2007-08-09 17:39:18 +02:00
config_path = None
2006-12-23 22:18:07 +01:00
try :
2007-08-09 17:39:18 +02:00
shortargs = ' hqvl:p:c: '
longargs = ' help quiet verbose loglevel= profile= config_path= '
2008-12-02 16:53:23 +01:00
opts = getopt . getopt ( sys . argv [ 1 : ] , shortargs , longargs . split ( ) ) [ 0 ]
2006-12-23 22:18:07 +01:00
except getopt . error , msg :
print msg
print ' for help use --help '
sys . exit ( 2 )
for o , a in opts :
if o in ( ' -h ' , ' --help ' ) :
2008-03-27 14:59:03 +01:00
print ' gajim [--help] [--quiet] [--verbose] [--loglevel subsystem=level[,subsystem=level[...]]] [--profile name] [--config-path] '
2006-12-23 22:18:07 +01:00
sys . exit ( )
elif o in ( ' -q ' , ' --quiet ' ) :
2009-03-11 10:16:07 +01:00
logging_helpers . set_quiet ( )
2006-12-23 22:18:07 +01:00
elif o in ( ' -v ' , ' --verbose ' ) :
2009-03-11 10:16:07 +01:00
logging_helpers . set_verbose ( )
2006-12-23 22:18:07 +01:00
elif o in ( ' -p ' , ' --profile ' ) : # gajim --profile name
profile = a
elif o in ( ' -l ' , ' --loglevel ' ) :
2009-03-11 10:16:07 +01:00
logging_helpers . set_loglevels ( a )
2007-08-09 17:39:18 +02:00
elif o in ( ' -c ' , ' --config-path ' ) :
config_path = a
2009-03-11 10:16:07 +01:00
return profile , config_path
2006-12-23 22:18:07 +01:00
2009-03-11 10:16:07 +01:00
profile , config_path = parseOpts ( )
del parseOpts
2006-12-23 22:18:07 +01:00
2007-08-09 17:39:18 +02:00
import locale
profile = unicode ( profile , locale . getpreferredencoding ( ) )
import common . configpaths
common . configpaths . gajimpaths . init ( config_path )
del config_path
common . configpaths . gajimpaths . init_profile ( profile )
del profile
2009-03-01 14:12:38 +01:00
if os . name == ' nt ' :
class MyStderr ( object ) :
_file = None
_error = None
def write ( self , text ) :
fname = os . path . join ( common . configpaths . gajimpaths . root ,
os . path . split ( sys . executable ) [ 1 ] + ' .log ' )
if self . _file is None and self . _error is None :
try :
self . _file = open ( fname , ' a ' )
except Exception , details :
self . _error = details
if self . _file is not None :
self . _file . write ( text )
self . _file . flush ( )
def flush ( self ) :
if self . _file is not None :
self . _file . flush ( )
sys . stderr = MyStderr ( )
2007-12-12 09:44:46 +01:00
# PyGTK2.10+ only throws a warning
warnings . filterwarnings ( ' error ' , module = ' gtk ' )
try :
import gtk
except Warning , msg :
if str ( msg ) == ' could not open display ' :
2008-06-29 01:05:14 +02:00
print >> sys . stderr , _ ( ' Gajim needs X server to run. Quiting... ' )
2009-07-30 19:21:23 +02:00
else :
print >> sys . stderr , _ ( ' importing PyGTK failed: %s ' ) % str ( msg )
sys . exit ( )
2007-12-12 09:44:46 +01:00
warnings . resetwarnings ( )
2008-04-04 23:31:27 +02:00
if os . name == ' nt ' :
warnings . filterwarnings ( action = ' ignore ' )
2005-12-01 18:17:20 +01:00
pritext = ' '
2005-09-11 16:20:20 +02:00
2008-03-17 08:22:43 +01:00
from common import exceptions
2005-09-22 18:30:46 +02:00
try :
2008-03-17 08:22:43 +01:00
from common import gajim
except exceptions . DatabaseMalformed :
pritext = _ ( ' Database Error ' )
2008-10-22 19:31:45 +02:00
sectext = _ ( ' The database file ( %s ) cannot be read. Try to repair it (see http://trac.gajim.org/wiki/DatabaseBackup) or remove it (all history will be lost). ' ) % common . logger . LOG_DB_PATH
2008-03-17 08:22:43 +01:00
else :
2009-10-15 19:43:10 +02:00
2009-10-05 16:13:12 +02:00
from ctypes import CDLL
from ctypes . util import find_library
import platform
2009-10-15 19:43:10 +02:00
2009-10-05 16:13:12 +02:00
sysname = platform . system ( )
2009-10-15 19:43:10 +02:00
if sysname in ( ' Linux ' , ' FreeBSD ' , ' OpenBSD ' , ' NetBSD ' ) :
libc = CDLL ( find_library ( ' c ' ) )
# The constant defined in <linux/prctl.h> which is used to set the name of
# the process.
PR_SET_NAME = 15
if sysname == ' Linux ' :
libc . prctl ( PR_SET_NAME , ' gajim ' )
elif sysname in ( ' FreeBSD ' , ' OpenBSD ' , ' NetBSD ' ) :
libc . setproctitle ( ' gajim ' )
2008-03-17 08:22:43 +01:00
2009-04-27 21:28:53 +02:00
if gtk . pygtk_version < ( 2 , 12 , 0 ) :
pritext = _ ( ' Gajim needs PyGTK 2.12 or above ' )
sectext = _ ( ' Gajim needs PyGTK 2.12 or above to run. Quiting... ' )
elif gtk . gtk_version < ( 2 , 12 , 0 ) :
pritext = _ ( ' Gajim needs GTK 2.12 or above ' )
sectext = _ ( ' Gajim needs GTK 2.12 or above to run. Quiting... ' )
2005-12-01 18:17:20 +01:00
2008-03-17 08:22:43 +01:00
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 '
else :
sectext = _ ( ' Please make sure that GTK+ and PyGTK have libglade support in your system. ' )
2005-12-01 18:17:20 +01:00
2006-09-13 18:47:58 +02:00
try :
2008-03-17 08:22:43 +01:00
from common import check_paths
except exceptions . PysqliteNotAvailable , e :
pritext = _ ( ' Gajim needs PySQLite2 to run ' )
sectext = str ( e )
if os . name == ' nt ' :
try :
import winsound # windows-only built-in module for playing wav
import win32api # do NOT remove. we req this module
2008-10-11 11:37:13 +02:00
except Exception :
2008-03-17 08:22:43 +01:00
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 '
2006-09-13 18:47:58 +02:00
2005-12-01 18:17:20 +01:00
if pritext :
2007-12-12 09:44:46 +01:00
dlg = gtk . MessageDialog ( None ,
2006-11-18 21:52:28 +01:00
gtk . DIALOG_DESTROY_WITH_PARENT | gtk . DIALOG_MODAL ,
gtk . MESSAGE_ERROR , gtk . BUTTONS_OK , message_format = pritext )
2005-09-22 18:30:46 +02:00
dlg . format_secondary_text ( sectext )
dlg . run ( )
dlg . destroy ( )
sys . exit ( )
2007-02-04 15:09:38 +01:00
del pritext
2005-02-28 19:15:48 +01:00
import gobject
2008-02-14 20:18:07 +01:00
if not hasattr ( gobject , ' timeout_add_seconds ' ) :
def timeout_add_seconds_fake ( time_sec , * args ) :
return gobject . timeout_add ( time_sec * 1000 , * args )
gobject . timeout_add_seconds = timeout_add_seconds_fake
2005-10-03 18:14:41 +02:00
2005-04-18 16:05:30 +02:00
import signal
2005-07-25 16:38:21 +02:00
import gtkgui_helpers
2005-04-14 09:05:10 +02:00
2006-11-18 21:52:28 +01:00
gajimpaths = common . configpaths . gajimpaths
pid_filename = gajimpaths [ ' PID_FILE ' ]
2006-11-22 21:56:25 +01:00
import traceback
import errno
2006-06-14 10:45:30 +02:00
import dialogs
2006-11-22 17:15:16 +01:00
def pid_alive ( ) :
2006-11-22 21:56:25 +01:00
try :
2006-11-22 17:15:16 +01:00
pf = open ( pid_filename )
2008-07-20 15:48:50 +02:00
except IOError :
2006-11-22 21:56:25 +01:00
# probably file not found
return False
2006-12-15 11:57:25 +01:00
try :
pid = int ( pf . read ( ) . strip ( ) )
pf . close ( )
2008-10-11 11:37:13 +02:00
except Exception :
2006-12-15 11:57:25 +01:00
traceback . print_exc ( )
# PID file exists, but something happened trying to read PID
# Could be 0.10 style empty PID file, so assume Gajim is running
return True
2006-11-23 00:27:54 +01:00
2006-12-13 15:41:57 +01:00
if os . name == ' nt ' :
try :
from ctypes import ( windll , c_ulong , c_int , Structure , c_char , POINTER , pointer , )
2008-10-11 11:37:13 +02:00
except Exception :
2006-12-13 15:41:57 +01:00
return True
class PROCESSENTRY32 ( Structure ) :
_fields_ = [
( ' dwSize ' , c_ulong , ) ,
( ' cntUsage ' , c_ulong , ) ,
( ' th32ProcessID ' , c_ulong , ) ,
( ' th32DefaultHeapID ' , c_ulong , ) ,
( ' th32ModuleID ' , c_ulong , ) ,
( ' cntThreads ' , c_ulong , ) ,
( ' th32ParentProcessID ' , c_ulong , ) ,
( ' pcPriClassBase ' , c_ulong , ) ,
( ' dwFlags ' , c_ulong , ) ,
( ' szExeFile ' , c_char * 512 , ) ,
]
def __init__ ( self ) :
Structure . __init__ ( self , 512 + 9 * 4 )
k = windll . kernel32
k . CreateToolhelp32Snapshot . argtypes = c_ulong , c_ulong ,
k . CreateToolhelp32Snapshot . restype = c_int
k . Process32First . argtypes = c_int , POINTER ( PROCESSENTRY32 ) ,
k . Process32First . restype = c_int
k . Process32Next . argtypes = c_int , POINTER ( PROCESSENTRY32 ) ,
k . Process32Next . restype = c_int
def get_p ( p ) :
h = k . CreateToolhelp32Snapshot ( 2 , 0 ) # TH32CS_SNAPPROCESS
assert h > 0 , ' CreateToolhelp32Snapshot failed '
b = pointer ( PROCESSENTRY32 ( ) )
f = k . Process32First ( h , b )
while f :
if b . contents . th32ProcessID == p :
return b . contents . szExeFile
f = k . Process32Next ( h , b )
2007-03-22 19:37:23 +01:00
if get_p ( pid ) in ( ' python.exe ' , ' gajim.exe ' ) :
2006-12-13 15:41:57 +01:00
return True
return False
try :
2006-11-23 00:27:54 +01:00
if not os . path . exists ( ' /proc ' ) :
return True # no /proc, assume Gajim is running
2006-11-22 21:56:25 +01:00
try :
2007-12-12 09:44:46 +01:00
f = open ( ' /proc/ %d /cmdline ' % pid )
2006-11-22 21:56:25 +01:00
except IOError , e :
if e . errno == errno . ENOENT :
return False # file/pid does not exist
2007-12-12 09:44:46 +01:00
raise
2006-11-22 21:56:25 +01:00
n = f . read ( ) . lower ( )
2006-11-22 17:15:16 +01:00
f . close ( )
2006-11-22 21:56:25 +01:00
if n . find ( ' gajim ' ) < 0 :
return False
return True # Running Gajim found at pid
2008-10-11 11:37:13 +02:00
except Exception :
2006-11-22 21:56:25 +01:00
traceback . print_exc ( )
# If we are here, pidfile exists, but some unexpected error occured.
# Assume Gajim is running.
return True
2006-11-22 17:15:16 +01:00
if pid_alive ( ) :
2006-06-15 11:43:08 +02:00
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
2006-05-26 15:32:52 +02:00
pritext = _ ( ' Gajim is already running ' )
2006-06-14 10:45:30 +02:00
sectext = _ ( ' Another instance of Gajim seems to be running \n Run anyway? ' )
dialog = dialogs . YesNoDialog ( pritext , sectext )
2008-08-11 10:41:44 +02:00
dialog . popup ( )
2008-08-11 16:10:30 +02:00
if dialog . run ( ) != gtk . RESPONSE_YES :
2006-06-14 10:45:30 +02:00
sys . exit ( 3 )
2008-08-11 10:41:44 +02:00
dialog . destroy ( )
2006-11-21 19:46:33 +01:00
# run anyway, delete pid and useless global vars
2006-06-15 11:43:08 +02:00
if os . path . exists ( pid_filename ) :
os . remove ( pid_filename )
2006-11-21 19:46:33 +01:00
del path_to_file
del pix
del pritext
del sectext
2006-06-14 10:45:30 +02:00
dialog . destroy ( )
2006-05-26 15:32:52 +02:00
2006-06-15 11:49:44 +02:00
# 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
2007-08-09 17:39:18 +02:00
try :
f = open ( pid_filename , ' w ' )
f . write ( str ( os . getpid ( ) ) )
f . close ( )
except IOError , e :
dlg = dialogs . ErrorDialog ( _ ( ' Disk Write Error ' ) , str ( e ) )
dlg . run ( )
dlg . destroy ( )
sys . exit ( )
2006-11-21 19:46:33 +01:00
del pid_dir
2007-02-04 15:09:38 +01:00
del f
2006-05-26 15:32:52 +02:00
def on_exit ( ) :
# delete pid file on normal exit
if os . path . exists ( pid_filename ) :
os . remove ( pid_filename )
2009-04-29 19:40:50 +02:00
# Shutdown GUI and save config
2009-05-01 11:37:13 +02:00
gajim . interface . roster . prepare_quit ( )
2006-05-26 15:32:52 +02:00
import atexit
atexit . register ( on_exit )
2005-05-14 00:38:48 +02:00
2006-11-18 21:52:28 +01:00
2009-10-18 23:25:03 +02:00
from interface import Interface
2008-11-05 21:00:57 +01:00
2005-04-12 23:09:06 +02:00
if __name__ == ' __main__ ' :
2006-05-26 15:32:52 +02:00
def sigint_cb ( num , stack ) :
sys . exit ( 5 )
# ^C exits the application normally to delete pid file
signal . signal ( signal . SIGINT , sigint_cb )
2005-04-18 16:05:30 +02:00
2009-03-11 10:16:07 +01:00
log . info ( " Encodings: d: %s , fs: %s , p: %s " , sys . getdefaultencoding ( ) , \
sys . getfilesystemencoding ( ) , locale . getpreferredencoding ( ) )
2006-12-20 21:40:08 +01:00
2009-06-15 21:34:38 +02:00
if os . name != ' nt ' :
2005-10-10 15:15:32 +02:00
# Session Management support
2005-10-10 15:12:28 +02:00
try :
import gnome . ui
except ImportError :
2008-11-02 14:33:12 +01:00
pass
2005-10-10 15:12:28 +02:00
else :
def die_cb ( cli ) :
2007-12-15 10:04:10 +01:00
gajim . interface . roster . quit_gtkgui_interface ( )
2005-10-10 15:12:28 +02:00
gnome . program_init ( ' gajim ' , gajim . version )
cli = gnome . ui . master_client ( )
cli . connect ( ' die ' , die_cb )
2007-12-12 09:44:46 +01:00
2006-11-18 21:52:28 +01:00
path_to_gajim_script = gtkgui_helpers . get_abspath_for_script (
' gajim ' )
2007-12-12 09:44:46 +01:00
2005-09-07 23:12:30 +02:00
if path_to_gajim_script :
2005-10-10 15:12:28 +02:00
argv = [ path_to_gajim_script ]
# FIXME: remove this typeerror catch when gnome python is old and
# not bad patched by distro men [2.12.0 + should not need all that
# NORMALLY]
try :
cli . set_restart_command ( argv )
2007-02-12 20:59:40 +01:00
except AttributeError :
2005-10-10 15:12:28 +02:00
cli . set_restart_command ( len ( argv ) , argv )
2007-12-12 09:44:46 +01:00
2006-09-13 18:47:58 +02:00
check_paths . check_and_possibly_create_paths ( )
2006-11-18 21:52:28 +01:00
2009-09-23 18:54:35 +02:00
interface = Interface ( )
interface . run ( )
2008-04-14 17:19:09 +02:00
2007-12-27 02:30:40 +01:00
try :
2009-05-10 22:02:46 +02:00
if os . name != ' nt ' :
# This makes Gajim unusable under windows, and threads are used only
# for GPG, so not under windows
gtk . gdk . threads_init ( )
2007-12-27 02:30:40 +01:00
gtk . main ( )
except KeyboardInterrupt :
print >> sys . stderr , ' KeyboardInterrupt '
2008-07-29 21:49:31 +02:00
2008-07-30 14:21:47 +02:00
# vim: se ts=3: