1#!/usr/local/bin/python3.8 2 3# -*- coding: utf-8 -*- 4# 5# Copyright 2011-2012 Canonical Ltd. 6# Copyright 2014 Erik Devriendt 7# 8# This program is free software: you can redistribute it and/or modify it 9# under the terms of the GNU General Public License version 3, as published 10# by the Free Software Foundation. 11# 12# This program is distributed in the hope that it will be useful, but 13# WITHOUT ANY WARRANTY; without even the implied warranties of 14# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 15# PURPOSE. See the GNU General Public License for more details. 16# 17# You should have received a copy of the GNU General Public License along 18# with this program. If not, see <http://www.gnu.org/licenses/>. 19# 20# In addition, as a special exception, the copyright holders give 21# permission to link the code of portions of this program with the 22# OpenSSL library under certain conditions as described in each 23# individual source file, and distribute linked combinations 24# including the two. 25# You must obey the GNU General Public License in all respects 26# for all of the code used other than OpenSSL. If you modify 27# file(s) with this exception, you may extend this exception to your 28# version of the file(s), but you are not obligated to do so. If you 29# do not wish to do so, delete this exception statement from your 30# version. If you delete this exception statement from all source 31# files in the program, then also delete it here. 32"""Retrieve the proxy configuration from Gnome.""" 33 34import subprocess 35 36 37GSETTINGS_CMDLINE = "gsettings list-recursively org.gnome.system.proxy" 38CANNOT_PARSE_WARNING = "Cannot parse gsettings value: %r" 39 40 41def parse_proxy_hostspec(hostspec): 42 """Parse the hostspec to get protocol, hostname, username and password.""" 43 protocol = None 44 username = None 45 password = None 46 hostname = hostspec 47 48 if "://" in hostname: 49 protocol, hostname = hostname.split("://", 1) 50 if "@" in hostname: 51 username, hostname = hostname.rsplit("@", 1) 52 if ":" in username: 53 username, password = username.split(":", 1) 54 return protocol, hostname, username, password 55 56 57def proxy_url_from_settings(scheme, gsettings): 58 """Build and return the proxy URL for the given scheme, based on the gsettings.""" 59 protocol, host, username, pwd = parse_proxy_hostspec(gsettings[scheme + ".host"]) 60 # if the user did not set a proxy for a type (http/https/ftp) we should 61 # return None to ensure that it is not used 62 if host == '': 63 return None 64 65 port = gsettings[scheme + ".port"] 66 67 if scheme == "http" and gsettings["http.use-authentication"]: 68 username = gsettings["http.authentication-user"] 69 pwd = gsettings["http.authentication-password"] 70 71 proxy_url = "" 72 if username is not None: 73 if pwd is not None: 74 proxy_url = "%s:%s@%s:%d" % (username,pwd,host,port) 75 else: 76 proxy_url = "%s@%s:%d" % (username,host,port) 77 else: 78 proxy_url = "%s:%d" % (host,port) 79 80 if protocol is not None: 81 proxy_url = "%s://%s" % (protocol, proxy_url) 82 83 return proxy_url 84 85def get_proxy_settings(): 86 """Parse the proxy settings as returned by the gsettings executable 87 and return a dictionary with a proxy URL for each scheme .""" 88 output = subprocess.check_output(GSETTINGS_CMDLINE.split()).decode("utf-8") 89 gsettings = {} 90 base_len = len("org.gnome.system.proxy.") 91 # pylint: disable=E1103 92 for line in output.split("\n"): 93 try: 94 path, key, value = line.split(" ", 2) 95 except ValueError: 96 continue 97 if value.startswith("'"): 98 parsed_value = value[1:-1] 99 elif value.startswith(('[', '@')): 100 parsed_value = value 101 elif value in ('true', 'false'): 102 parsed_value = (value == 'true') 103 elif value.isdigit(): 104 parsed_value = int(value) 105 else: 106 print(CANNOT_PARSE_WARNING % value) 107 parsed_value = value 108 relative_key = (path + "." + key)[base_len:] 109 gsettings[relative_key] = parsed_value 110 mode = gsettings["mode"] 111 if mode == "none": 112 settings = {} 113 elif mode == "manual": 114 settings = {} 115 for scheme in ["http", "https"]: 116 scheme_settings = proxy_url_from_settings(scheme, gsettings) 117 if scheme_settings is not None: 118 settings[scheme] = scheme_settings 119 else: 120 # If mode is automatic the PAC javascript should be interpreted 121 # on each request. That is out of scope so it's ignored for now 122 settings = {} 123 124 return settings 125