configpaths.py 7.17 KB
Newer Older
roidelapluie's avatar
roidelapluie committed
1
# -*- coding:utf-8 -*-
roidelapluie's avatar
roidelapluie committed
2 3 4
## src/common/configpaths.py
##
## Copyright (C) 2006 Jean-Marie Traissard <jim AT lapin.org>
roidelapluie's avatar
roidelapluie committed
5
##                    Junglecow J <junglecow AT gmail.com>
Yann Leboulanger's avatar
Yann Leboulanger committed
6
## Copyright (C) 2006-2012 Yann Leboulanger <asterix AT lagaule.org>
roidelapluie's avatar
roidelapluie committed
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
## Copyright (C) 2007 Brendan Taylor <whateley AT gmail.com>
## Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org>
##
## This file is part of Gajim.
##
## Gajim is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published
## by the Free Software Foundation; version 3 only.
##
## Gajim is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
##

25 26 27
import os
import sys
import tempfile
28
import defs
29 30
HAVE_XDG = True
try:
Dicson's avatar
Dicson committed
31
    __import__(xdg)
32
except:
33
    HAVE_XDG = False
34 35 36 37 38 39

(
TYPE_CONFIG,
TYPE_CACHE,
TYPE_DATA
) = range(3)
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58

# Note on path and filename encodings:
#
# In general it is very difficult to do this correctly.
# We may pull information from environment variables, and what encoding that is
# in is anyone's guess. Any information we request directly from the file
# system will be in filesystemencoding, and (parts of) paths that we write in
# this source code will be in whatever encoding the source is in. (I hereby
# declare this file to be UTF-8 encoded.)
#
# To make things more complicated, modern Windows filesystems use UTF-16, but
# the API tends to hide this from us.
#
# I tried to minimize problems by passing Unicode strings to OS functions as
# much as possible. Hopefully this makes the function return an Unicode string
# as well. If not, we get an 8-bit string in filesystemencoding, which we can
# happily pass to functions that operate on files and directories, so we can
# just leave it as is. Since these paths are meant to be internal to Gajim and
# not displayed to the user, Unicode is not really necessary here.
59 60

def fse(s):
61 62 63
    """
    Convert from filesystem encoding if not already Unicode
    """
Yann Leboulanger's avatar
Yann Leboulanger committed
64
    return s
65

66
def windowsify(s):
67 68 69
    if os.name == 'nt':
        return s.capitalize()
    return s
70

71
class ConfigPaths:
72 73 74 75 76 77 78 79 80 81 82 83 84
    def __init__(self):
        # {'name': (type, path), } type can be TYPE_CONFIG, TYPE_CACHE, TYPE_DATA
        # or None
        self.paths = {}

        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.config_root = self.cache_root = self.data_root = \
85
                        os.path.join(fse(os.environ['appdata']), 'Gajim')
86 87
            except KeyError:
                # win9x, in cwd
88
                self.config_root = self.cache_root = self.data_root = '.'
89 90 91 92 93 94 95
        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.\
96
                            xdg_config_dirs[0], 'gajim')
97 98

                self.cache_root = os.path.join(xdg.BaseDirectory.xdg_cache_home,
99
                        'gajim')
100 101 102 103

                self.data_root = xdg.BaseDirectory.save_data_path('gajim')
                if not self.data_root:
                    self.data_root = os.path.join(xdg.BaseDirectory.\
104
                            xdg_data_dirs[0], 'gajim')
105 106
            else:
                expand = os.path.expanduser
107 108 109 110 111 112
                base = os.getenv('XDG_CONFIG_HOME') or expand('~/.config')
                self.config_root = os.path.join(base, 'gajim')
                base = os.getenv('XDG_CACHE_HOME') or expand('~/.cache')
                self.cache_root = os.path.join(base, 'gajim')
                base = os.getenv('XDG_DATA_HOME') or expand('~/.local/share')
                self.data_root = os.path.join(base, 'gajim')
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140

    def add(self, name, type_, path):
        self.paths[name] = (type_, path)

    def __getitem__(self, key):
        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:
            return self[key]
        except KeyError:
            return default

    def iteritems(self):
        for key in self.paths.iterkeys():
            yield (key, self[key])

    def init(self, root=None):
        if root is not None:
            self.config_root = self.cache_root = self.data_root = root

141 142 143 144
        d = {'MY_DATA': '', 'LOG_DB': 'logs.db', 'MY_CACERTS': 'cacerts.pem',
                'MY_EMOTS': 'emoticons', 'MY_ICONSETS': 'iconsets',
                'MY_MOOD_ICONSETS': 'moods', 'MY_ACTIVITY_ICONSETS': 'activities',
                'PLUGINS_USER': 'plugins', 'MY_PEER_CERTS': 'certs'}
145 146 147
        for name in d:
            self.add(name, TYPE_DATA, windowsify(d[name]))

148 149
        d = {'MY_CACHE': '', 'CACHE_DB': 'cache.db', 'VCARD': 'vcards',
                'AVATAR': 'avatars'}
150 151 152 153
        for name in d:
            self.add(name, TYPE_CACHE, windowsify(d[name]))

        self.add('MY_CONFIG', TYPE_CONFIG, '')
154
        self.add('MY_CERT', TYPE_CONFIG, '')
155

156 157 158
        basedir = fse(os.environ.get('GAJIM_BASEDIR', defs.basedir))
        self.add('DATA', None, os.path.join(basedir, windowsify('data')))
        self.add('ICONS', None, os.path.join(basedir, windowsify('icons')))
159
        self.add('HOME', None, fse(os.path.expanduser('~')))
160
        self.add('PLUGINS_BASE', None, os.path.join(basedir,
161
            windowsify('plugins')))
162 163
        try:
            self.add('TMP', None, fse(tempfile.gettempdir()))
Yann Leboulanger's avatar
Yann Leboulanger committed
164
        except IOError as e:
Yann Leboulanger's avatar
Yann Leboulanger committed
165 166
            print('Error opening tmp folder: %s\nUsing %s' % (str(e),
                os.path.expanduser('~')), file=sys.stderr)
167 168 169 170 171 172 173 174 175
            self.add('TMP', None, fse(os.path.expanduser('~')))

        try:
            import svn_config
            svn_config.configure(self)
        except (ImportError, AttributeError):
            pass

    def init_profile(self, profile=''):
176 177 178 179
        conffile = windowsify('config')
        pidfile = windowsify('gajim')
        secretsfile = windowsify('secrets')
        pluginsconfdir = windowsify('pluginsconfig')
180 181

        if len(profile) > 0:
182 183 184 185 186
            conffile += '.' + profile
            pidfile += '.' + profile
            secretsfile += '.' + profile
            pluginsconfdir += '.' + profile
        pidfile += '.pid'
187 188 189
        self.add('CONFIG_FILE', TYPE_CONFIG, conffile)
        self.add('PID_FILE', TYPE_CACHE, pidfile)
        self.add('SECRETS_FILE', TYPE_DATA, secretsfile)
190
        self.add('PLUGINS_CONFIG_DIR', TYPE_CONFIG, pluginsconfdir)
191

192
gajimpaths = ConfigPaths()