From e6a093034c5970704caacfefeb2890cfccc75067 Mon Sep 17 00:00:00 2001 From: Ari Breitkreuz Date: Fri, 31 Jan 2020 13:27:46 +0100 Subject: [PATCH] Use XDG Base Directories --- protonvpn_cli/cli.py | 16 +++++++++++-- protonvpn_cli/connection.py | 20 ++++++++--------- protonvpn_cli/constants.py | 45 ++++++++++++++++++++++++++++++++----- protonvpn_cli/logger.py | 8 +++---- 4 files changed, 67 insertions(+), 22 deletions(-) diff --git a/protonvpn_cli/cli.py b/protonvpn_cli/cli.py index bc271a2..44e81c4 100644 --- a/protonvpn_cli/cli.py +++ b/protonvpn_cli/cli.py @@ -63,7 +63,7 @@ ) # Constants from .constants import ( - CONFIG_DIR, CONFIG_FILE, PASSFILE, USER, VERSION, SPLIT_TUNNEL_FILE + CONFIG_DIR, DATA_DIR, CACHE_DIR, CONFIG_FILE, PASSFILE, USER, VERSION, SPLIT_TUNNEL_FILE ) @@ -80,13 +80,15 @@ def cli(): """Run user's input command.""" # Initial log values - change_file_owner(os.path.join(CONFIG_DIR, "pvpn-cli.log")) + change_file_owner(os.path.join(CACHE_DIR, "pvpn-cli.log")) logger.debug("###########################") logger.debug("### NEW PROCESS STARTED ###") logger.debug("###########################") logger.debug(sys.argv) logger.debug("USER: {0}".format(USER)) logger.debug("CONFIG_DIR: {0}".format(CONFIG_DIR)) + logger.debug("DATA_DIR: {0}".format(DATA_DIR)) + logger.debug("CACHE_DIR: {0}".format(CACHE_DIR)) args = docopt(__doc__, version="ProtonVPN-CLI v{0}".format(VERSION)) logger.debug("Arguments\n{0}".format(str(args).replace("\n", ""))) @@ -180,6 +182,16 @@ def init_config_file(): logger.debug("Config Directory created") change_file_owner(CONFIG_DIR) + if not os.path.isdir(CACHE_DIR): + os.mkdir(CACHE_DIR) + logger.debug("Cache Directory created") + change_file_owner(CACHE_DIR) + + if not os.path.isdir(DATA_DIR): + os.mkdir(DATA_DIR) + logger.debug("Data Directory created") + change_file_owner(DATA_DIR) + # Warn user about reinitialization try: if int(get_config_value("USER", "initialized")): diff --git a/protonvpn_cli/connection.py b/protonvpn_cli/connection.py index d53539c..7ef1cee 100644 --- a/protonvpn_cli/connection.py +++ b/protonvpn_cli/connection.py @@ -22,7 +22,7 @@ ) # Constants from .constants import ( - CONFIG_DIR, TEMPLATE_FILE, OVPN_FILE, PASSFILE, CONFIG_FILE + CACHE_DIR, DATA_DIR, TEMPLATE_FILE, OVPN_FILE, PASSFILE, CONFIG_FILE ) @@ -361,7 +361,7 @@ def status(): if not is_connected(): logger.debug("Disconnected") print("Status: Disconnected") - if os.path.isfile(os.path.join(CONFIG_DIR, "iptables.backup")): + if os.path.isfile(os.path.join(DATA_DIR, "iptables.backup")): print("[!] Kill Switch is currently active.") logger.debug("Kill Switch active while VPN disconnected") else: @@ -416,7 +416,7 @@ def status(): last_connection = get_config_value("metadata", "connected_time") connection_time = time.time() - int(last_connection) - if os.path.isfile(os.path.join(CONFIG_DIR, "iptables.backup")): + if os.path.isfile(os.path.join(DATA_DIR, "iptables.backup")): killswitch_on = True else: killswitch_on = False @@ -471,7 +471,7 @@ def openvpn_connect(servername, protocol): print("Connecting to {0} via {1}...".format(servername, protocol.upper())) - with open(os.path.join(CONFIG_DIR, "ovpn.log"), "w+") as f: + with open(os.path.join(CACHE_DIR, "ovpn.log"), "w+") as f: subprocess.Popen( [ "openvpn", @@ -484,7 +484,7 @@ def openvpn_connect(servername, protocol): logger.debug("OpenVPN process started") time_start = time.time() - with open(os.path.join(CONFIG_DIR, "ovpn.log"), "r") as f: + with open(os.path.join(CACHE_DIR, "ovpn.log"), "r") as f: while True: content = f.read() f.seek(0) @@ -557,7 +557,7 @@ def manage_dns(mode, dns_server=False): restore: Revert changes and restore original configuration """ - backupfile = os.path.join(CONFIG_DIR, "resolv.conf.backup") + backupfile = os.path.join(DATA_DIR, "resolv.conf.backup") resolvconf_path = os.path.realpath("/etc/resolv.conf") if mode == "leak_protection": @@ -642,8 +642,8 @@ def manage_ipv6(mode): restore: Revert changes and restore original configuration. """ - ipv6_backupfile = os.path.join(CONFIG_DIR, "ipv6.backup") - ip6tables_backupfile = os.path.join(CONFIG_DIR, "ip6tables.backup") + ipv6_backupfile = os.path.join(DATA_DIR, "ipv6.backup") + ip6tables_backupfile = os.path.join(DATA_DIR, "ip6tables.backup") if mode == "disable": @@ -773,7 +773,7 @@ def manage_killswitch(mode, proto=None, port=None): reason this will completely block access to the internet. """ - backupfile = os.path.join(CONFIG_DIR, "iptables.backup") + backupfile = os.path.join(DATA_DIR, "iptables.backup") if mode == "restore": logger.debug("Restoring iptables") @@ -797,7 +797,7 @@ def manage_killswitch(mode, proto=None, port=None): logger.debug("Kill Switch backup exists") manage_killswitch("restore") - with open(os.path.join(CONFIG_DIR, "ovpn.log"), "r") as f: + with open(os.path.join(CACHE_DIR, "ovpn.log"), "r") as f: content = f.read() device = re.search(r"(TUN\/TAP device) (.+) opened", content) if not device: diff --git a/protonvpn_cli/constants.py b/protonvpn_cli/constants.py index ae49d57..e7a5797 100644 --- a/protonvpn_cli/constants.py +++ b/protonvpn_cli/constants.py @@ -6,11 +6,44 @@ except KeyError: USER = getpass.getuser() -CONFIG_DIR = os.path.join(os.path.expanduser("~{0}".format(USER)), ".pvpn-cli") +# Ensure backwards compatibility +home_path = os.path.expanduser("~{0}".format(USER)) +home_config = os.path.join(home_path, ".pvpn-cli") +if os.path.exists(home_config): + CONFIG_DIR = home_config + DATA_DIR = home_config + CACHE_DIR = home_config + +else: + # Get the config directory + xdg_config_str = os.getenv("XDG_CONFIG_HOME") + if not xdg_config_str: + xdg_config = os.path.join(home_path, ".config") + else: + xdg_config = os.path.realpath(xdg_config_str) + CONFIG_DIR = os.path.join(xdg_config, "pvpn-cli") + + # Get the data directory + xdg_data_str = os.getenv("XDG_DATA_HOME") + if not xdg_data_str: + xdg_data = os.path.join(home_path, ".local/share") + else: + xdg_data = os.path.realpath(xdg_data_str) + DATA_DIR = os.path.join(xdg_config, "pvpn-cli") + + # Get the cache directory + xdg_cache_str = os.getenv("XDG_CACHE_HOME") + if not xdg_cache_str: + xdg_cache = os.path.join(home_path, ".cache") + else: + xdg_cache = os.path.realpath(xdg_cache_str) + CACHE_DIR = os.path.join(xdg_cache, "pvpn-cli") + + CONFIG_FILE = os.path.join(CONFIG_DIR, "pvpn-cli.cfg") -TEMPLATE_FILE = os.path.join(CONFIG_DIR, "template.ovpn") -SERVER_INFO_FILE = os.path.join(CONFIG_DIR, "serverinfo.json") -SPLIT_TUNNEL_FILE = os.path.join(CONFIG_DIR, "split_tunnel.txt") -OVPN_FILE = os.path.join(CONFIG_DIR, "connect.ovpn") -PASSFILE = os.path.join(CONFIG_DIR, "pvpnpass") +TEMPLATE_FILE = os.path.join(CACHE_DIR, "template.ovpn") +SERVER_INFO_FILE = os.path.join(CACHE_DIR, "serverinfo.json") +SPLIT_TUNNEL_FILE = os.path.join(DATA_DIR, "split_tunnel.txt") +OVPN_FILE = os.path.join(DATA_DIR, "connect.ovpn") +PASSFILE = os.path.join(DATA_DIR, "pvpnpass") VERSION = "2.2.0" diff --git a/protonvpn_cli/logger.py b/protonvpn_cli/logger.py index 3f7e227..7653bcd 100644 --- a/protonvpn_cli/logger.py +++ b/protonvpn_cli/logger.py @@ -2,7 +2,7 @@ import logging from logging.handlers import RotatingFileHandler -from .constants import CONFIG_DIR +from .constants import CACHE_DIR def get_logger(): @@ -13,11 +13,11 @@ def get_logger(): FORMATTER = logging.Formatter( "%(asctime)s — %(name)s — %(levelname)s — %(funcName)s:%(lineno)d — %(message)s" # noqa ) - LOGFILE = os.path.join(CONFIG_DIR, "pvpn-cli.log") + LOGFILE = os.path.join(CACHE_DIR, "pvpn-cli.log") # TBD, maybe /var/log is the better option - if not os.path.isdir(CONFIG_DIR): - os.mkdir(CONFIG_DIR) + if not os.path.isdir(CACHE_DIR): + os.mkdir(CACHE_DIR) logger = logging.getLogger("protonvpn-cli") logger.setLevel(logging.DEBUG)