From 3e777ea8f120dc58d4e65ce501ab3ab3785a5d40 Mon Sep 17 00:00:00 2001 From: Yann Leboulanger Date: Thu, 4 Feb 2010 20:08:30 +0100 Subject: [PATCH] use and create files in folders using XDG standards. Fixes #2149 --- src/common/check_paths.py | 110 +++++++++++++++++++-------------- src/common/configpaths.py | 126 +++++++++++++++++++++++--------------- src/common/gajim.py | 1 - src/common/helpers.py | 7 ++- 4 files changed, 144 insertions(+), 100 deletions(-) diff --git a/src/common/check_paths.py b/src/common/check_paths.py index d3a7d29df..77a7f3809 100644 --- a/src/common/check_paths.py +++ b/src/common/check_paths.py @@ -35,6 +35,7 @@ import sqlite3 as sqlite def create_log_db(): print _('creating logs database') + print logger.LOG_DB_PATH con = sqlite.connect(logger.LOG_DB_PATH) os.chmod(logger.LOG_DB_PATH, 0600) # rw only for us cur = con.cursor() @@ -127,61 +128,80 @@ def create_cache_db(): def check_and_possibly_create_paths(): LOG_DB_PATH = logger.LOG_DB_PATH + LOG_DB_FOLDER, LOG_DB_FILE = os.path.split(LOG_DB_PATH) CACHE_DB_PATH = logger.CACHE_DB_PATH + CACHE_DB_FOLDER, CACHE_DB_FILE = os.path.split(CACHE_DB_PATH) VCARD_PATH = gajim.VCARD_PATH AVATAR_PATH = gajim.AVATAR_PATH - dot_gajim = os.path.dirname(VCARD_PATH) - if os.path.isfile(dot_gajim): - print _('%s is a file but it should be a directory') % dot_gajim + import configpaths + MY_DATA = configpaths.gajimpaths['MY_DATA'] + MY_CONFIG = configpaths.gajimpaths['MY_CONFIG'] + MY_CACHE = configpaths.gajimpaths['MY_CACHE'] + + if not os.path.exists(MY_DATA): + create_path(MY_DATA) + elif os.path.isfile(MY_DATA): + print _('%s is a file but it should be a directory') % MY_DATA print _('Gajim will now exit') sys.exit() - elif os.path.isdir(dot_gajim): - s = os.stat(dot_gajim) - if s.st_mode & stat.S_IROTH: # others have read permission! - os.chmod(dot_gajim, 0700) # rwx------ - if not os.path.exists(VCARD_PATH): - create_path(VCARD_PATH) - elif os.path.isfile(VCARD_PATH): - print _('%s is a file but it should be a directory') % VCARD_PATH - print _('Gajim will now exit') - sys.exit() + if not os.path.exists(MY_CONFIG): + create_path(MY_CONFIG) + elif os.path.isfile(MY_CONFIG): + print _('%s is a file but it should be a directory') % MY_CONFIG + print _('Gajim will now exit') + sys.exit() - if not os.path.exists(AVATAR_PATH): - create_path(AVATAR_PATH) - elif os.path.isfile(AVATAR_PATH): - print _('%s is a file but it should be a directory') % AVATAR_PATH - print _('Gajim will now exit') - sys.exit() + if not os.path.exists(MY_CACHE): + create_path(MY_CACHE) + elif os.path.isfile(MY_CACHE): + print _('%s is a file but it should be a directory') % MY_CACHE + print _('Gajim will now exit') + sys.exit() - if not os.path.exists(LOG_DB_PATH): - create_log_db() - gajim.logger.init_vars() - elif os.path.isdir(LOG_DB_PATH): - print _('%s is a directory but should be a file') % LOG_DB_PATH - print _('Gajim will now exit') - sys.exit() + if not os.path.exists(VCARD_PATH): + create_path(VCARD_PATH) + elif os.path.isfile(VCARD_PATH): + print _('%s is a file but it should be a directory') % VCARD_PATH + print _('Gajim will now exit') + sys.exit() - if not os.path.exists(CACHE_DB_PATH): - create_cache_db() - elif os.path.isdir(CACHE_DB_PATH): - print _('%s is a directory but should be a file') % CACHE_DB_PATH - print _('Gajim will now exit') - sys.exit() + if not os.path.exists(AVATAR_PATH): + create_path(AVATAR_PATH) + elif os.path.isfile(AVATAR_PATH): + print _('%s is a file but it should be a directory') % AVATAR_PATH + print _('Gajim will now exit') + sys.exit() - else: # dot_gajim doesn't exist - if dot_gajim: # is '' on win9x so avoid that - create_path(dot_gajim) - if not os.path.isdir(VCARD_PATH): - create_path(VCARD_PATH) - if not os.path.exists(AVATAR_PATH): - create_path(AVATAR_PATH) - if not os.path.isfile(LOG_DB_PATH): - create_log_db() - gajim.logger.init_vars() - if not os.path.isfile(CACHE_DB_PATH): - create_cache_db() - gajim.logger.attach_cache_database() + if not os.path.exists(LOG_DB_FOLDER): + create_path(LOG_DB_FOLDER) + elif os.path.isfile(LOG_DB_FOLDER): + print _('%s is a file but it should be a directory') % LOG_DB_FOLDER + print _('Gajim will now exit') + sys.exit() + + if not os.path.exists(LOG_DB_PATH): + create_log_db() + gajim.logger.init_vars() + elif os.path.isdir(LOG_DB_PATH): + print _('%s is a directory but should be a file') % LOG_DB_PATH + print _('Gajim will now exit') + sys.exit() + + if not os.path.exists(CACHE_DB_FOLDER): + create_path(CACHE_DB_FOLDER) + elif os.path.isfile(CACHE_DB_FOLDER): + print _('%s is a file but it should be a directory') % CACHE_DB_FOLDER + print _('Gajim will now exit') + sys.exit() + + if not os.path.exists(CACHE_DB_PATH): + create_cache_db() + gajim.logger.attach_cache_database() + elif os.path.isdir(CACHE_DB_PATH): + print _('%s is a directory but should be a file') % CACHE_DB_PATH + print _('Gajim will now exit') + sys.exit() def create_path(directory): print _('creating %s directory') % directory diff --git a/src/common/configpaths.py b/src/common/configpaths.py index 856eb7e04..33c118280 100644 --- a/src/common/configpaths.py +++ b/src/common/configpaths.py @@ -26,6 +26,17 @@ import os import sys import tempfile import defs +HAVE_XDG = True +try: + import xdg.BaseDirectory +except: + HAVE_XDG = False + +( +TYPE_CONFIG, +TYPE_CACHE, +TYPE_DATA +) = range(3) # Note on path and filename encodings: # @@ -58,37 +69,56 @@ def windowsify(s): return s class ConfigPaths: - def __init__(self, root=None): - self.root = root + def __init__(self): + # {'name': (type, path), } type can be TYPE_CONFIG, TYPE_CACHE, TYPE_DATA + # or None self.paths = {} - if self.root is None: - if os.name == 'nt': - try: - # Documents and Settings\[User Name]\Application Data\Gajim + if os.name == 'nt': + try: + # Documents and Settings\[User Name]\Application Data\Gajim - # How are we supposed to know what encoding the environment - # variable 'appdata' is in? Assuming it to be in filesystem - # encoding. - self.root = os.path.join(fse(os.environ[u'appdata']), u'Gajim') - except KeyError: - # win9x, in cwd - self.root = u'.' - else: # Unices - # Pass in an Unicode string, and hopefully get one back. - self.root = os.path.expanduser(u'~/.gajim') + # How are we supposed to know what encoding the environment + # variable 'appdata' is in? Assuming it to be in filesystem + # encoding. + self.config_root = self.cache_root = self.data_root = \ + os.path.join(fse(os.environ[u'appdata']), u'Gajim') + except KeyError: + # win9x, in cwd + self.config_root = self.cache_root = self.data_root = u'.' + else: # Unices + # Pass in an Unicode string, and hopefully get one back. + if HAVE_XDG: + self.config_root = xdg.BaseDirectory.load_first_config('gajim') + if not self.config_root: + # Folder doesn't exist yet. + self.config_root = os.path.join(xdg.BaseDirectory.\ + xdg_config_dirs[0], u'gajim') - def add_from_root(self, name, path): - self.paths[name] = (True, path) + self.cache_root = os.path.join(xdg.BaseDirectory.xdg_cache_home, + u'gajim') - def add(self, name, path): - self.paths[name] = (False, path) + self.data_root = xdg.BaseDirectory.save_data_path('gajim') + if not self.data_root: + self.data_root = os.path.join(xdg.BaseDirectory.\ + xdg_data_dirs[0], u'gajim') + else: + self.config_root = os.path.expanduser(u'~/.config/gajim') + self.cache_root = os.path.expanduser(u'~/.cache/gajim') + self.data_root = os.path.expanduser(u'~/.local/share/gajim') + + def add(self, name, type_, path): + self.paths[name] = (type_, path) def __getitem__(self, key): - relative, path = self.paths[key] - if not relative: - return path - return os.path.join(self.root, path) + type_, path = self.paths[key] + if type_ == TYPE_CONFIG: + return os.path.join(self.config_root, path) + elif type_ == TYPE_CACHE: + return os.path.join(self.cache_root, path) + elif type_ == TYPE_DATA: + return os.path.join(self.data_root, path) + return path def get(self, key, default=None): try: @@ -100,33 +130,33 @@ class ConfigPaths: for key in self.paths.iterkeys(): yield (key, self[key]) - def init(self, root = None): + def init(self, root=None): if root is not None: - self.root = root + self.config_root = self.cache_root = self.data_root = root - # LOG is deprecated - k = ( 'LOG', 'LOG_DB', 'CACHE_DB', 'VCARD', 'AVATAR', 'MY_EMOTS', - 'MY_ICONSETS', 'MY_MOOD_ICONSETS', 'MY_ACTIVITY_ICONSETS', - 'MY_CACERTS') - v = (u'logs', u'logs.db', u'cache.db', u'vcards', u'avatars', - u'emoticons', u'iconsets', u'moods', u'activities', u'cacerts.pem') + d = {'MY_DATA': '', 'LOG_DB': u'logs.db', 'MY_CACERTS': u'cacerts.pem', + 'MY_EMOTS': u'emoticons', 'MY_ICONSETS': u'iconsets', + 'MY_MOOD_ICONSETS': u'moods', 'MY_ACTIVITY_ICONSETS': u'activities'} + for name in d: + self.add(name, TYPE_DATA, windowsify(d[name])) - if os.name == 'nt': - v = [x.capitalize() for x in v] + d = {'MY_CACHE': '', 'CACHE_DB': u'cache.db', 'VCARD': u'vcards', + 'AVATAR': u'avatars'} + for name in d: + self.add(name, TYPE_CACHE, windowsify(d[name])) - for n, p in zip(k, v): - self.add_from_root(n, p) + self.add('MY_CONFIG', TYPE_CONFIG, '') basedir = fse(os.environ.get(u'GAJIM_BASEDIR', defs.basedir)) - self.add('DATA', os.path.join(basedir, windowsify(u'data'))) - self.add('ICONS', os.path.join(basedir, windowsify(u'icons'))) - self.add('HOME', fse(os.path.expanduser('~'))) + self.add('DATA', None, os.path.join(basedir, windowsify(u'data'))) + self.add('ICONS', None, os.path.join(basedir, windowsify(u'icons'))) + self.add('HOME', None, fse(os.path.expanduser('~'))) try: - self.add('TMP', fse(tempfile.gettempdir())) + self.add('TMP', None, fse(tempfile.gettempdir())) except IOError, e: print >> sys.stderr, 'Error opening tmp folder: %s\nUsing %s' % ( str(e), os.path.expanduser('~')) - self.add('TMP', fse(os.path.expanduser('~'))) + self.add('TMP', None, fse(os.path.expanduser('~'))) try: import svn_config @@ -134,10 +164,7 @@ class ConfigPaths: except (ImportError, AttributeError): pass - # for k, v in paths.iteritems(): - # print "%s: %s" % (repr(k), repr(v)) - - def init_profile(self, profile = ''): + def init_profile(self, profile=''): conffile = windowsify(u'config') pidfile = windowsify(u'gajim') secretsfile = windowsify(u'secrets') @@ -147,12 +174,9 @@ class ConfigPaths: pidfile += u'.' + profile secretsfile += u'.' + profile pidfile += u'.pid' - self.add_from_root('CONFIG_FILE', conffile) - self.add_from_root('PID_FILE', pidfile) - self.add_from_root('SECRETS_FILE', secretsfile) - - # for k, v in paths.iteritems(): - # print "%s: %s" % (repr(k), repr(v)) + self.add('CONFIG_FILE', TYPE_CONFIG, conffile) + self.add('PID_FILE', TYPE_CONFIG, pidfile) + self.add('SECRETS_FILE', TYPE_DATA, secretsfile) gajimpaths = ConfigPaths() diff --git a/src/common/gajim.py b/src/common/gajim.py index 810ae7c6d..6ef66d6b9 100644 --- a/src/common/gajim.py +++ b/src/common/gajim.py @@ -77,7 +77,6 @@ logger = logger.Logger() # init the logger import configpaths gajimpaths = configpaths.gajimpaths -LOGPATH = gajimpaths['LOG'] # deprecated VCARD_PATH = gajimpaths['VCARD'] AVATAR_PATH = gajimpaths['AVATAR'] MY_EMOTS_PATH = gajimpaths['MY_EMOTS'] diff --git a/src/common/helpers.py b/src/common/helpers.py index 8069470ae..d3caa4266 100644 --- a/src/common/helpers.py +++ b/src/common/helpers.py @@ -725,7 +725,8 @@ def play_sound(event): path_to_soundfile = gajim.config.get_per('soundevents', event, 'path') play_sound_file(path_to_soundfile) -def check_soundfile_path(file, dirs=(gajim.gajimpaths.root, gajim.DATA_DIR)): +def check_soundfile_path(file, dirs=(gajim.gajimpaths.data_root, +gajim.DATA_DIR)): """ Check if the sound file exists @@ -745,8 +746,8 @@ def check_soundfile_path(file, dirs=(gajim.gajimpaths.root, gajim.DATA_DIR)): return d return None -def strip_soundfile_path(file, dirs=(gajim.gajimpaths.root, gajim.DATA_DIR), - abs=True): +def strip_soundfile_path(file, dirs=(gajim.gajimpaths.data_root, +gajim.DATA_DIR), abs=True): """ Remove knowns paths from a sound file