2018-09-05 02:59:34 +02:00
|
|
|
# Copyright (C) 2006 Jean-Marie Traissard <jim AT lapin.org>
|
|
|
|
# Junglecow J <junglecow AT gmail.com>
|
|
|
|
# Copyright (C) 2006-2014 Yann Leboulanger <asterix AT lagaule.org>
|
|
|
|
# Copyright (C) 2007 Brendan Taylor <whateley AT gmail.com>
|
|
|
|
# Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org>
|
|
|
|
# Copyright (C) 2018 Philipp Hörist <philipp AT hoerist.com>
|
|
|
|
#
|
|
|
|
# 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/>.
|
2008-08-15 05:20:23 +02:00
|
|
|
|
2018-09-13 23:56:12 +02:00
|
|
|
from typing import Dict # pylint: disable=unused-import
|
|
|
|
from typing import List
|
|
|
|
from typing import Generator
|
|
|
|
from typing import Optional # pylint: disable=unused-import
|
|
|
|
from typing import Tuple
|
|
|
|
|
2006-11-04 19:15:38 +01:00
|
|
|
import os
|
2018-04-22 23:12:34 +02:00
|
|
|
import sys
|
2006-11-04 19:15:38 +01:00
|
|
|
import tempfile
|
2018-04-22 23:12:34 +02:00
|
|
|
from pathlib import Path
|
2010-02-04 20:08:30 +01:00
|
|
|
|
2018-05-27 01:18:54 +02:00
|
|
|
import gajim
|
2018-09-13 23:56:12 +02:00
|
|
|
from gajim.common.i18n import _
|
2018-04-21 21:19:32 +02:00
|
|
|
from gajim.common.const import PathType, PathLocation
|
2018-09-13 23:56:12 +02:00
|
|
|
from gajim.common.types import PathTuple
|
2007-07-26 01:04:15 +02:00
|
|
|
|
2017-01-06 18:08:52 +01:00
|
|
|
|
2018-09-23 14:40:49 +02:00
|
|
|
def get(key: str) -> str:
|
2018-04-21 12:44:10 +02:00
|
|
|
return _paths[key]
|
|
|
|
|
|
|
|
|
2018-09-23 14:40:49 +02:00
|
|
|
def get_plugin_dirs() -> List[str]:
|
|
|
|
if gajim.IS_FLATPAK:
|
|
|
|
return ['/app/plugins',
|
|
|
|
_paths['PLUGINS_BASE']]
|
|
|
|
return [_paths['PLUGINS_BASE'],
|
|
|
|
_paths['PLUGINS_USER']]
|
|
|
|
|
|
|
|
|
2018-09-13 23:56:12 +02:00
|
|
|
def get_paths(type_: PathType) -> Generator[str, None, None]:
|
2018-04-21 21:19:32 +02:00
|
|
|
for key, value in _paths.items():
|
2018-09-13 23:56:12 +02:00
|
|
|
path_type = value[2]
|
2018-04-21 21:19:32 +02:00
|
|
|
if type_ != path_type:
|
|
|
|
continue
|
|
|
|
yield _paths[key]
|
|
|
|
|
|
|
|
|
2018-04-25 20:49:37 +02:00
|
|
|
def override_path(*args, **kwargs):
|
2018-09-13 23:56:12 +02:00
|
|
|
_paths.add(*args, **kwargs)
|
2018-04-25 20:49:37 +02:00
|
|
|
|
|
|
|
|
2018-09-13 23:56:12 +02:00
|
|
|
def set_separation(active: bool) -> None:
|
2018-04-21 12:44:10 +02:00
|
|
|
_paths.profile_separation = active
|
|
|
|
|
|
|
|
|
2018-09-13 23:56:12 +02:00
|
|
|
def set_profile(profile: str) -> None:
|
2018-04-21 12:44:10 +02:00
|
|
|
_paths.profile = profile
|
|
|
|
|
|
|
|
|
2018-09-13 23:56:12 +02:00
|
|
|
def set_config_root(config_root: str) -> None:
|
2018-04-21 14:47:47 +02:00
|
|
|
_paths.custom_config_root = config_root
|
2018-04-21 12:44:10 +02:00
|
|
|
|
|
|
|
|
2018-09-13 23:56:12 +02:00
|
|
|
def init() -> None:
|
2018-04-21 12:44:10 +02:00
|
|
|
_paths.init()
|
2017-01-06 19:38:51 +01:00
|
|
|
|
|
|
|
|
2018-09-13 23:56:12 +02:00
|
|
|
def create_paths() -> None:
|
2018-04-22 23:12:34 +02:00
|
|
|
for path in get_paths(PathType.FOLDER):
|
|
|
|
if not isinstance(path, Path):
|
2018-09-13 23:56:12 +02:00
|
|
|
path_ = Path(path)
|
2018-04-22 23:12:34 +02:00
|
|
|
|
2018-09-13 23:56:12 +02:00
|
|
|
if path_.is_file():
|
|
|
|
print(_('%s is a file but it should be a directory') % path_)
|
2018-04-22 23:12:34 +02:00
|
|
|
print(_('Gajim will now exit'))
|
|
|
|
sys.exit()
|
|
|
|
|
2018-09-13 23:56:12 +02:00
|
|
|
if not path_.exists():
|
|
|
|
for parent_path in reversed(path_.parents):
|
2018-04-22 23:12:34 +02:00
|
|
|
# Create all parent folders
|
2018-06-21 01:46:16 +02:00
|
|
|
# don't use mkdir(parent=True), as it ignores `mode`
|
2018-04-22 23:12:34 +02:00
|
|
|
# when creating the parents
|
|
|
|
if not parent_path.exists():
|
|
|
|
print(('creating %s directory') % parent_path)
|
|
|
|
parent_path.mkdir(mode=0o700)
|
2018-09-13 23:56:12 +02:00
|
|
|
print(('creating %s directory') % path_)
|
|
|
|
path_.mkdir(mode=0o700)
|
2018-04-22 23:12:34 +02:00
|
|
|
|
|
|
|
|
2006-11-04 19:15:38 +01:00
|
|
|
class ConfigPaths:
|
2018-09-13 23:56:12 +02:00
|
|
|
def __init__(self) -> None:
|
|
|
|
self._paths = {} # type: Dict[str, PathTuple]
|
2018-04-21 12:44:10 +02:00
|
|
|
self.profile = ''
|
|
|
|
self.profile_separation = False
|
2018-09-13 23:56:12 +02:00
|
|
|
self.custom_config_root = None # type: Optional[str]
|
2010-02-08 15:08:40 +01:00
|
|
|
|
|
|
|
if os.name == 'nt':
|
|
|
|
try:
|
|
|
|
# Documents and Settings\[User Name]\Application Data\Gajim
|
|
|
|
self.config_root = self.cache_root = self.data_root = \
|
2017-01-06 18:08:52 +01:00
|
|
|
os.path.join(os.environ['appdata'], 'Gajim')
|
2010-02-08 15:08:40 +01:00
|
|
|
except KeyError:
|
|
|
|
# win9x, in cwd
|
2013-01-01 19:44:25 +01:00
|
|
|
self.config_root = self.cache_root = self.data_root = '.'
|
2018-04-21 12:44:10 +02:00
|
|
|
else:
|
2016-11-05 15:49:38 +01:00
|
|
|
expand = os.path.expanduser
|
|
|
|
base = os.getenv('XDG_CONFIG_HOME')
|
|
|
|
if base is None or base[0] != '/':
|
|
|
|
base = expand('~/.config')
|
|
|
|
self.config_root = os.path.join(base, 'gajim')
|
|
|
|
base = os.getenv('XDG_CACHE_HOME')
|
|
|
|
if base is None or base[0] != '/':
|
|
|
|
base = expand('~/.cache')
|
|
|
|
self.cache_root = os.path.join(base, 'gajim')
|
|
|
|
base = os.getenv('XDG_DATA_HOME')
|
|
|
|
if base is None or base[0] != '/':
|
|
|
|
base = expand('~/.local/share')
|
|
|
|
self.data_root = os.path.join(base, 'gajim')
|
2010-02-08 15:08:40 +01:00
|
|
|
|
2017-09-16 12:18:22 +02:00
|
|
|
import pkg_resources
|
|
|
|
basedir = pkg_resources.resource_filename("gajim", ".")
|
2017-01-06 17:44:31 +01:00
|
|
|
|
2018-04-21 21:19:32 +02:00
|
|
|
source_paths = [
|
|
|
|
('DATA', os.path.join(basedir, 'data')),
|
2018-03-01 22:47:01 +01:00
|
|
|
('STYLE', os.path.join(basedir, 'data', 'style')),
|
2018-08-15 23:58:02 +02:00
|
|
|
('EMOTICONS', os.path.join(basedir, 'data', 'emoticons')),
|
2018-04-21 21:19:32 +02:00
|
|
|
('GUI', os.path.join(basedir, 'data', 'gui')),
|
|
|
|
('ICONS', os.path.join(basedir, 'data', 'icons')),
|
|
|
|
('HOME', os.path.expanduser('~')),
|
|
|
|
('PLUGINS_BASE', os.path.join(basedir, 'data', 'plugins')),
|
|
|
|
]
|
|
|
|
|
|
|
|
for path in source_paths:
|
2018-09-13 23:56:12 +02:00
|
|
|
self.add(*path)
|
2010-02-08 15:08:40 +01:00
|
|
|
|
2018-09-13 23:56:12 +02:00
|
|
|
def __getitem__(self, key: str) -> str:
|
2018-04-21 21:19:32 +02:00
|
|
|
location, path, _ = self._paths[key]
|
|
|
|
if location == PathLocation.CONFIG:
|
2010-02-08 15:08:40 +01:00
|
|
|
return os.path.join(self.config_root, path)
|
2018-09-13 23:56:12 +02:00
|
|
|
if location == PathLocation.CACHE:
|
2010-02-08 15:08:40 +01:00
|
|
|
return os.path.join(self.cache_root, path)
|
2018-09-13 23:56:12 +02:00
|
|
|
if location == PathLocation.DATA:
|
2010-02-08 15:08:40 +01:00
|
|
|
return os.path.join(self.data_root, path)
|
|
|
|
return path
|
|
|
|
|
2018-09-13 23:56:12 +02:00
|
|
|
def items(self) -> Generator[Tuple[str, PathTuple], None, None]:
|
2018-04-21 21:19:32 +02:00
|
|
|
for key, value in self._paths.items():
|
|
|
|
yield (key, value)
|
|
|
|
|
2018-09-13 23:56:12 +02:00
|
|
|
def _prepare(self, path: str, unique: bool) -> str:
|
2018-04-21 21:19:32 +02:00
|
|
|
if os.name == 'nt':
|
|
|
|
path = path.capitalize()
|
|
|
|
if self.profile:
|
|
|
|
if unique or self.profile_separation:
|
|
|
|
return '%s.%s' % (path, self.profile)
|
|
|
|
return path
|
|
|
|
|
2018-09-13 23:56:12 +02:00
|
|
|
def add(self,
|
|
|
|
name: str,
|
|
|
|
path: str,
|
|
|
|
location: PathLocation = None,
|
|
|
|
path_type: PathType = None,
|
|
|
|
unique: bool = False) -> None:
|
2018-04-22 02:30:08 +02:00
|
|
|
if path and location is not None:
|
2018-04-21 21:19:32 +02:00
|
|
|
path = self._prepare(path, unique)
|
|
|
|
self._paths[name] = (location, path, path_type)
|
2010-02-08 15:08:40 +01:00
|
|
|
|
2018-04-21 12:44:10 +02:00
|
|
|
def init(self):
|
2018-04-21 14:47:47 +02:00
|
|
|
if self.custom_config_root:
|
2018-04-22 00:55:48 +02:00
|
|
|
self.config_root = self.custom_config_root
|
|
|
|
self.cache_root = self.data_root = self.custom_config_root
|
2010-02-08 15:08:40 +01:00
|
|
|
|
2018-04-21 21:19:32 +02:00
|
|
|
user_dir_paths = [
|
|
|
|
('TMP', tempfile.gettempdir()),
|
2018-04-22 02:30:08 +02:00
|
|
|
('MY_CONFIG', '', PathLocation.CONFIG, PathType.FOLDER),
|
|
|
|
('MY_CACHE', '', PathLocation.CACHE, PathType.FOLDER),
|
|
|
|
('MY_DATA', '', PathLocation.DATA, PathType.FOLDER),
|
2018-04-21 21:19:32 +02:00
|
|
|
]
|
|
|
|
|
|
|
|
for path in user_dir_paths:
|
2018-09-13 23:56:12 +02:00
|
|
|
self.add(*path)
|
2018-04-21 21:19:32 +02:00
|
|
|
|
|
|
|
# These paths are unique per profile
|
|
|
|
unique_profile_paths = [
|
|
|
|
# Data paths
|
|
|
|
('SECRETS_FILE', 'secrets', PathLocation.DATA, PathType.FILE),
|
|
|
|
('MY_PEER_CERTS', 'certs', PathLocation.DATA, PathType.FOLDER),
|
2018-09-23 14:25:02 +02:00
|
|
|
('DEBUG', 'debug', PathLocation.DATA, PathType.FOLDER),
|
2018-10-14 17:09:39 +02:00
|
|
|
('PLUGINS_DATA', 'plugins_data', PathLocation.DATA, PathType.FOLDER),
|
2018-04-21 21:19:32 +02:00
|
|
|
|
|
|
|
# Config paths
|
|
|
|
('CONFIG_FILE', 'config', PathLocation.CONFIG, PathType.FILE),
|
2018-04-22 00:55:48 +02:00
|
|
|
('PLUGINS_CONFIG_DIR',
|
|
|
|
'pluginsconfig', PathLocation.CONFIG, PathType.FOLDER),
|
2018-04-21 21:19:32 +02:00
|
|
|
('MY_CERT', 'localcerts', PathLocation.CONFIG, PathType.FOLDER),
|
|
|
|
]
|
|
|
|
|
|
|
|
for path in unique_profile_paths:
|
2018-09-13 23:56:12 +02:00
|
|
|
self.add(*path, unique=True)
|
2018-04-21 21:19:32 +02:00
|
|
|
|
|
|
|
# These paths are only unique per profile if the commandline arg
|
|
|
|
# `separate` is passed
|
|
|
|
paths = [
|
|
|
|
# Data paths
|
|
|
|
('LOG_DB', 'logs.db', PathLocation.DATA, PathType.FILE),
|
|
|
|
('MY_CACERTS', 'cacerts.pem', PathLocation.DATA, PathType.FILE),
|
2018-10-10 14:11:13 +02:00
|
|
|
('PLUGINS_DOWNLOAD', 'plugins_download', PathLocation.CACHE, PathType.FOLDER),
|
2018-04-21 21:19:32 +02:00
|
|
|
('PLUGINS_USER', 'plugins', PathLocation.DATA, PathType.FOLDER),
|
2018-04-22 00:55:48 +02:00
|
|
|
('MY_EMOTS',
|
|
|
|
'emoticons', PathLocation.DATA, PathType.FOLDER_OPTIONAL),
|
|
|
|
('MY_ICONSETS',
|
|
|
|
'iconsets', PathLocation.DATA, PathType.FOLDER_OPTIONAL),
|
|
|
|
('MY_MOOD_ICONSETS',
|
|
|
|
'moods', PathLocation.DATA, PathType.FOLDER_OPTIONAL),
|
|
|
|
('MY_ACTIVITY_ICONSETS',
|
|
|
|
'activities', PathLocation.DATA, PathType.FOLDER_OPTIONAL),
|
2018-04-21 21:19:32 +02:00
|
|
|
|
|
|
|
# Cache paths
|
|
|
|
('CACHE_DB', 'cache.db', PathLocation.CACHE, PathType.FILE),
|
|
|
|
('AVATAR', 'avatars', PathLocation.CACHE, PathType.FOLDER),
|
2018-03-01 22:47:01 +01:00
|
|
|
|
|
|
|
# Config paths
|
|
|
|
('MY_THEME', 'theme', PathLocation.CONFIG, PathType.FOLDER),
|
|
|
|
|
2018-04-21 21:19:32 +02:00
|
|
|
]
|
|
|
|
|
|
|
|
for path in paths:
|
2018-09-13 23:56:12 +02:00
|
|
|
self.add(*path)
|
2016-09-06 23:02:24 +02:00
|
|
|
|
2018-04-21 12:44:10 +02:00
|
|
|
|
|
|
|
_paths = ConfigPaths()
|
|
|
|
|
|
|
|
# For backwards compatibility needed
|
|
|
|
# some plugins use that
|
|
|
|
gajimpaths = _paths
|