use and create files in folders using XDG standards. Fixes #2149

This commit is contained in:
Yann Leboulanger 2010-02-04 20:08:30 +01:00
parent eef9e264ae
commit 3e777ea8f1
4 changed files with 144 additions and 100 deletions

View file

@ -35,6 +35,7 @@ import sqlite3 as sqlite
def create_log_db(): def create_log_db():
print _('creating logs database') print _('creating logs database')
print logger.LOG_DB_PATH
con = sqlite.connect(logger.LOG_DB_PATH) con = sqlite.connect(logger.LOG_DB_PATH)
os.chmod(logger.LOG_DB_PATH, 0600) # rw only for us os.chmod(logger.LOG_DB_PATH, 0600) # rw only for us
cur = con.cursor() cur = con.cursor()
@ -127,61 +128,80 @@ def create_cache_db():
def check_and_possibly_create_paths(): def check_and_possibly_create_paths():
LOG_DB_PATH = logger.LOG_DB_PATH 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_PATH = logger.CACHE_DB_PATH
CACHE_DB_FOLDER, CACHE_DB_FILE = os.path.split(CACHE_DB_PATH)
VCARD_PATH = gajim.VCARD_PATH VCARD_PATH = gajim.VCARD_PATH
AVATAR_PATH = gajim.AVATAR_PATH AVATAR_PATH = gajim.AVATAR_PATH
dot_gajim = os.path.dirname(VCARD_PATH) import configpaths
if os.path.isfile(dot_gajim): MY_DATA = configpaths.gajimpaths['MY_DATA']
print _('%s is a file but it should be a directory') % dot_gajim 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') print _('Gajim will now exit')
sys.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): if not os.path.exists(MY_CONFIG):
create_path(VCARD_PATH) create_path(MY_CONFIG)
elif os.path.isfile(VCARD_PATH): elif os.path.isfile(MY_CONFIG):
print _('%s is a file but it should be a directory') % VCARD_PATH print _('%s is a file but it should be a directory') % MY_CONFIG
print _('Gajim will now exit') print _('Gajim will now exit')
sys.exit() sys.exit()
if not os.path.exists(AVATAR_PATH): if not os.path.exists(MY_CACHE):
create_path(AVATAR_PATH) create_path(MY_CACHE)
elif os.path.isfile(AVATAR_PATH): elif os.path.isfile(MY_CACHE):
print _('%s is a file but it should be a directory') % AVATAR_PATH print _('%s is a file but it should be a directory') % MY_CACHE
print _('Gajim will now exit') print _('Gajim will now exit')
sys.exit() sys.exit()
if not os.path.exists(LOG_DB_PATH): if not os.path.exists(VCARD_PATH):
create_log_db() create_path(VCARD_PATH)
gajim.logger.init_vars() elif os.path.isfile(VCARD_PATH):
elif os.path.isdir(LOG_DB_PATH): print _('%s is a file but it should be a directory') % VCARD_PATH
print _('%s is a directory but should be a file') % LOG_DB_PATH print _('Gajim will now exit')
print _('Gajim will now exit') sys.exit()
sys.exit()
if not os.path.exists(CACHE_DB_PATH): if not os.path.exists(AVATAR_PATH):
create_cache_db() create_path(AVATAR_PATH)
elif os.path.isdir(CACHE_DB_PATH): elif os.path.isfile(AVATAR_PATH):
print _('%s is a directory but should be a file') % CACHE_DB_PATH print _('%s is a file but it should be a directory') % AVATAR_PATH
print _('Gajim will now exit') print _('Gajim will now exit')
sys.exit() sys.exit()
else: # dot_gajim doesn't exist if not os.path.exists(LOG_DB_FOLDER):
if dot_gajim: # is '' on win9x so avoid that create_path(LOG_DB_FOLDER)
create_path(dot_gajim) elif os.path.isfile(LOG_DB_FOLDER):
if not os.path.isdir(VCARD_PATH): print _('%s is a file but it should be a directory') % LOG_DB_FOLDER
create_path(VCARD_PATH) print _('Gajim will now exit')
if not os.path.exists(AVATAR_PATH): sys.exit()
create_path(AVATAR_PATH)
if not os.path.isfile(LOG_DB_PATH): if not os.path.exists(LOG_DB_PATH):
create_log_db() create_log_db()
gajim.logger.init_vars() gajim.logger.init_vars()
if not os.path.isfile(CACHE_DB_PATH): elif os.path.isdir(LOG_DB_PATH):
create_cache_db() print _('%s is a directory but should be a file') % LOG_DB_PATH
gajim.logger.attach_cache_database() 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): def create_path(directory):
print _('creating %s directory') % directory print _('creating %s directory') % directory

View file

@ -26,6 +26,17 @@ import os
import sys import sys
import tempfile import tempfile
import defs 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: # Note on path and filename encodings:
# #
@ -58,37 +69,56 @@ def windowsify(s):
return s return s
class ConfigPaths: class ConfigPaths:
def __init__(self, root=None): def __init__(self):
self.root = root # {'name': (type, path), } type can be TYPE_CONFIG, TYPE_CACHE, TYPE_DATA
# or None
self.paths = {} self.paths = {}
if self.root is None: if os.name == 'nt':
if os.name == 'nt': try:
try: # Documents and Settings\[User Name]\Application Data\Gajim
# Documents and Settings\[User Name]\Application Data\Gajim
# How are we supposed to know what encoding the environment # How are we supposed to know what encoding the environment
# variable 'appdata' is in? Assuming it to be in filesystem # variable 'appdata' is in? Assuming it to be in filesystem
# encoding. # encoding.
self.root = os.path.join(fse(os.environ[u'appdata']), u'Gajim') self.config_root = self.cache_root = self.data_root = \
except KeyError: os.path.join(fse(os.environ[u'appdata']), u'Gajim')
# win9x, in cwd except KeyError:
self.root = u'.' # win9x, in cwd
else: # Unices self.config_root = self.cache_root = self.data_root = u'.'
# Pass in an Unicode string, and hopefully get one back. else: # Unices
self.root = os.path.expanduser(u'~/.gajim') # 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.cache_root = os.path.join(xdg.BaseDirectory.xdg_cache_home,
self.paths[name] = (True, path) u'gajim')
def add(self, name, path): self.data_root = xdg.BaseDirectory.save_data_path('gajim')
self.paths[name] = (False, path) 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): def __getitem__(self, key):
relative, path = self.paths[key] type_, path = self.paths[key]
if not relative: if type_ == TYPE_CONFIG:
return path return os.path.join(self.config_root, path)
return os.path.join(self.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): def get(self, key, default=None):
try: try:
@ -100,33 +130,33 @@ class ConfigPaths:
for key in self.paths.iterkeys(): for key in self.paths.iterkeys():
yield (key, self[key]) yield (key, self[key])
def init(self, root = None): def init(self, root=None):
if root is not None: if root is not None:
self.root = root self.config_root = self.cache_root = self.data_root = root
# LOG is deprecated d = {'MY_DATA': '', 'LOG_DB': u'logs.db', 'MY_CACERTS': u'cacerts.pem',
k = ( 'LOG', 'LOG_DB', 'CACHE_DB', 'VCARD', 'AVATAR', 'MY_EMOTS', 'MY_EMOTS': u'emoticons', 'MY_ICONSETS': u'iconsets',
'MY_ICONSETS', 'MY_MOOD_ICONSETS', 'MY_ACTIVITY_ICONSETS', 'MY_MOOD_ICONSETS': u'moods', 'MY_ACTIVITY_ICONSETS': u'activities'}
'MY_CACERTS') for name in d:
v = (u'logs', u'logs.db', u'cache.db', u'vcards', u'avatars', self.add(name, TYPE_DATA, windowsify(d[name]))
u'emoticons', u'iconsets', u'moods', u'activities', u'cacerts.pem')
if os.name == 'nt': d = {'MY_CACHE': '', 'CACHE_DB': u'cache.db', 'VCARD': u'vcards',
v = [x.capitalize() for x in v] 'AVATAR': u'avatars'}
for name in d:
self.add(name, TYPE_CACHE, windowsify(d[name]))
for n, p in zip(k, v): self.add('MY_CONFIG', TYPE_CONFIG, '')
self.add_from_root(n, p)
basedir = fse(os.environ.get(u'GAJIM_BASEDIR', defs.basedir)) basedir = fse(os.environ.get(u'GAJIM_BASEDIR', defs.basedir))
self.add('DATA', os.path.join(basedir, windowsify(u'data'))) self.add('DATA', None, os.path.join(basedir, windowsify(u'data')))
self.add('ICONS', os.path.join(basedir, windowsify(u'icons'))) self.add('ICONS', None, os.path.join(basedir, windowsify(u'icons')))
self.add('HOME', fse(os.path.expanduser('~'))) self.add('HOME', None, fse(os.path.expanduser('~')))
try: try:
self.add('TMP', fse(tempfile.gettempdir())) self.add('TMP', None, fse(tempfile.gettempdir()))
except IOError, e: except IOError, e:
print >> sys.stderr, 'Error opening tmp folder: %s\nUsing %s' % ( print >> sys.stderr, 'Error opening tmp folder: %s\nUsing %s' % (
str(e), os.path.expanduser('~')) str(e), os.path.expanduser('~'))
self.add('TMP', fse(os.path.expanduser('~'))) self.add('TMP', None, fse(os.path.expanduser('~')))
try: try:
import svn_config import svn_config
@ -134,10 +164,7 @@ class ConfigPaths:
except (ImportError, AttributeError): except (ImportError, AttributeError):
pass pass
# for k, v in paths.iteritems(): def init_profile(self, profile=''):
# print "%s: %s" % (repr(k), repr(v))
def init_profile(self, profile = ''):
conffile = windowsify(u'config') conffile = windowsify(u'config')
pidfile = windowsify(u'gajim') pidfile = windowsify(u'gajim')
secretsfile = windowsify(u'secrets') secretsfile = windowsify(u'secrets')
@ -147,12 +174,9 @@ class ConfigPaths:
pidfile += u'.' + profile pidfile += u'.' + profile
secretsfile += u'.' + profile secretsfile += u'.' + profile
pidfile += u'.pid' pidfile += u'.pid'
self.add_from_root('CONFIG_FILE', conffile) self.add('CONFIG_FILE', TYPE_CONFIG, conffile)
self.add_from_root('PID_FILE', pidfile) self.add('PID_FILE', TYPE_CONFIG, pidfile)
self.add_from_root('SECRETS_FILE', secretsfile) self.add('SECRETS_FILE', TYPE_DATA, secretsfile)
# for k, v in paths.iteritems():
# print "%s: %s" % (repr(k), repr(v))
gajimpaths = ConfigPaths() gajimpaths = ConfigPaths()

View file

@ -77,7 +77,6 @@ logger = logger.Logger() # init the logger
import configpaths import configpaths
gajimpaths = configpaths.gajimpaths gajimpaths = configpaths.gajimpaths
LOGPATH = gajimpaths['LOG'] # deprecated
VCARD_PATH = gajimpaths['VCARD'] VCARD_PATH = gajimpaths['VCARD']
AVATAR_PATH = gajimpaths['AVATAR'] AVATAR_PATH = gajimpaths['AVATAR']
MY_EMOTS_PATH = gajimpaths['MY_EMOTS'] MY_EMOTS_PATH = gajimpaths['MY_EMOTS']

View file

@ -725,7 +725,8 @@ def play_sound(event):
path_to_soundfile = gajim.config.get_per('soundevents', event, 'path') path_to_soundfile = gajim.config.get_per('soundevents', event, 'path')
play_sound_file(path_to_soundfile) 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 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 d
return None return None
def strip_soundfile_path(file, dirs=(gajim.gajimpaths.root, gajim.DATA_DIR), def strip_soundfile_path(file, dirs=(gajim.gajimpaths.data_root,
abs=True): gajim.DATA_DIR), abs=True):
""" """
Remove knowns paths from a sound file Remove knowns paths from a sound file