# Licensed to the Software Freedom Conservancy (SFC) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The SFC licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. """ The Proxy implementation. """ class ProxyTypeFactory: """ Factory for proxy types. """ @staticmethod def make(ff_value, string): return {"ff_value": ff_value, "string": string} class ProxyType: """ Set of possible types of proxy. Each proxy type has 2 properties: 'ff_value' is value of Firefox profile preference, 'string' is id of proxy type. """ DIRECT = ProxyTypeFactory.make(0, "DIRECT") # Direct connection, no proxy (default on Windows). MANUAL = ProxyTypeFactory.make(1, "MANUAL") # Manual proxy settings (e.g., for httpProxy). PAC = ProxyTypeFactory.make(2, "PAC") # Proxy autoconfiguration from URL. RESERVED_1 = ProxyTypeFactory.make(3, "RESERVED1") # Never used. AUTODETECT = ProxyTypeFactory.make(4, "AUTODETECT") # Proxy autodetection (presumably with WPAD). SYSTEM = ProxyTypeFactory.make(5, "SYSTEM") # Use system settings (default on Linux). UNSPECIFIED = ProxyTypeFactory.make(6, "UNSPECIFIED") # Not initialized (for internal use). @classmethod def load(cls, value): if isinstance(value, dict) and "string" in value: value = value["string"] value = str(value).upper() for attr in dir(cls): attr_value = getattr(cls, attr) if isinstance(attr_value, dict) and "string" in attr_value and attr_value["string"] == value: return attr_value raise Exception(f"No proxy type is found for {value}") class Proxy: """ Proxy contains information about proxy type and necessary proxy settings. """ proxyType = ProxyType.UNSPECIFIED autodetect = False ftpProxy = "" httpProxy = "" noProxy = "" proxyAutoconfigUrl = "" sslProxy = "" socksProxy = "" socksUsername = "" socksPassword = "" socksVersion = None def __init__(self, raw=None): """ Creates a new Proxy. :Args: - raw: raw proxy data. If None, default class values are used. """ if raw: if "proxyType" in raw and raw["proxyType"]: self.proxy_type = ProxyType.load(raw["proxyType"]) if "ftpProxy" in raw and raw["ftpProxy"]: self.ftp_proxy = raw["ftpProxy"] if "httpProxy" in raw and raw["httpProxy"]: self.http_proxy = raw["httpProxy"] if "noProxy" in raw and raw["noProxy"]: self.no_proxy = raw["noProxy"] if "proxyAutoconfigUrl" in raw and raw["proxyAutoconfigUrl"]: self.proxy_autoconfig_url = raw["proxyAutoconfigUrl"] if "sslProxy" in raw and raw["sslProxy"]: self.sslProxy = raw["sslProxy"] if "autodetect" in raw and raw["autodetect"]: self.auto_detect = raw["autodetect"] if "socksProxy" in raw and raw["socksProxy"]: self.socks_proxy = raw["socksProxy"] if "socksUsername" in raw and raw["socksUsername"]: self.socks_username = raw["socksUsername"] if "socksPassword" in raw and raw["socksPassword"]: self.socks_password = raw["socksPassword"] if "socksVersion" in raw and raw["socksVersion"]: self.socks_version = raw["socksVersion"] @property def proxy_type(self): """ Returns proxy type as `ProxyType`. """ return self.proxyType @proxy_type.setter def proxy_type(self, value) -> None: """ Sets proxy type. :Args: - value: The proxy type. """ self._verify_proxy_type_compatibility(value) self.proxyType = value @property def auto_detect(self): """ Returns autodetect setting. """ return self.autodetect @auto_detect.setter def auto_detect(self, value) -> None: """ Sets autodetect setting. :Args: - value: The autodetect value. """ if isinstance(value, bool): if self.autodetect is not value: self._verify_proxy_type_compatibility(ProxyType.AUTODETECT) self.proxyType = ProxyType.AUTODETECT self.autodetect = value else: raise ValueError("Autodetect proxy value needs to be a boolean") @property def ftp_proxy(self): """ Returns ftp proxy setting. """ return self.ftpProxy @ftp_proxy.setter def ftp_proxy(self, value) -> None: """ Sets ftp proxy setting. :Args: - value: The ftp proxy value. """ self._verify_proxy_type_compatibility(ProxyType.MANUAL) self.proxyType = ProxyType.MANUAL self.ftpProxy = value @property def http_proxy(self): """ Returns http proxy setting. """ return self.httpProxy @http_proxy.setter def http_proxy(self, value) -> None: """ Sets http proxy setting. :Args: - value: The http proxy value. """ self._verify_proxy_type_compatibility(ProxyType.MANUAL) self.proxyType = ProxyType.MANUAL self.httpProxy = value @property def no_proxy(self): """ Returns noproxy setting. """ return self.noProxy @no_proxy.setter def no_proxy(self, value) -> None: """ Sets noproxy setting. :Args: - value: The noproxy value. """ self._verify_proxy_type_compatibility(ProxyType.MANUAL) self.proxyType = ProxyType.MANUAL self.noProxy = value @property def proxy_autoconfig_url(self): """ Returns proxy autoconfig url setting. """ return self.proxyAutoconfigUrl @proxy_autoconfig_url.setter def proxy_autoconfig_url(self, value) -> None: """ Sets proxy autoconfig url setting. :Args: - value: The proxy autoconfig url value. """ self._verify_proxy_type_compatibility(ProxyType.PAC) self.proxyType = ProxyType.PAC self.proxyAutoconfigUrl = value @property def ssl_proxy(self): """ Returns https proxy setting. """ return self.sslProxy @ssl_proxy.setter def ssl_proxy(self, value) -> None: """ Sets https proxy setting. :Args: - value: The https proxy value. """ self._verify_proxy_type_compatibility(ProxyType.MANUAL) self.proxyType = ProxyType.MANUAL self.sslProxy = value @property def socks_proxy(self): """ Returns socks proxy setting. """ return self.socksProxy @socks_proxy.setter def socks_proxy(self, value) -> None: """ Sets socks proxy setting. :Args: - value: The socks proxy value. """ self._verify_proxy_type_compatibility(ProxyType.MANUAL) self.proxyType = ProxyType.MANUAL self.socksProxy = value @property def socks_username(self): """ Returns socks proxy username setting. """ return self.socksUsername @socks_username.setter def socks_username(self, value) -> None: """ Sets socks proxy username setting. :Args: - value: The socks proxy username value. """ self._verify_proxy_type_compatibility(ProxyType.MANUAL) self.proxyType = ProxyType.MANUAL self.socksUsername = value @property def socks_password(self): """ Returns socks proxy password setting. """ return self.socksPassword @socks_password.setter def socks_password(self, value) -> None: """ Sets socks proxy password setting. :Args: - value: The socks proxy password value. """ self._verify_proxy_type_compatibility(ProxyType.MANUAL) self.proxyType = ProxyType.MANUAL self.socksPassword = value @property def socks_version(self): """ Returns socks proxy version setting. """ return self.socksVersion @socks_version.setter def socks_version(self, value) -> None: """ Sets socks proxy version setting. :Args: - value: The socks proxy version value. """ self._verify_proxy_type_compatibility(ProxyType.MANUAL) self.proxyType = ProxyType.MANUAL self.socksVersion = value def _verify_proxy_type_compatibility(self, compatible_proxy): if self.proxyType not in (ProxyType.UNSPECIFIED, compatible_proxy): raise Exception( f"Specified proxy type ({compatible_proxy}) not compatible with current setting ({self.proxyType})" ) def add_to_capabilities(self, capabilities): """ Adds proxy information as capability in specified capabilities. :Args: - capabilities: The capabilities to which proxy will be added. """ proxy_caps = {} proxy_caps["proxyType"] = self.proxyType["string"] if self.autodetect: proxy_caps["autodetect"] = self.autodetect if self.ftpProxy: proxy_caps["ftpProxy"] = self.ftpProxy if self.httpProxy: proxy_caps["httpProxy"] = self.httpProxy if self.proxyAutoconfigUrl: proxy_caps["proxyAutoconfigUrl"] = self.proxyAutoconfigUrl if self.sslProxy: proxy_caps["sslProxy"] = self.sslProxy if self.noProxy: proxy_caps["noProxy"] = self.noProxy if self.socksProxy: proxy_caps["socksProxy"] = self.socksProxy if self.socksUsername: proxy_caps["socksUsername"] = self.socksUsername if self.socksPassword: proxy_caps["socksPassword"] = self.socksPassword if self.socksVersion: proxy_caps["socksVersion"] = self.socksVersion capabilities["proxy"] = proxy_caps