diff --git a/gui/builtinPreferenceViews/pyfaNetworkPreferences.py b/gui/builtinPreferenceViews/pyfaNetworkPreferences.py index b4c0dedae..bd79dd88c 100644 --- a/gui/builtinPreferenceViews/pyfaNetworkPreferences.py +++ b/gui/builtinPreferenceViews/pyfaNetworkPreferences.py @@ -69,6 +69,9 @@ class PFNetworkPref ( PreferenceView): self.nAddr = self.settings.getAddress() self.nPort = self.settings.getPort() self.nType = self.settings.getType() + self.nAuth = self.settings.getProxyAuthDetails() # tuple of (login, password) + if self.nAuth is None: + self.nAuth = ("", "") # we don't want None here, it should be a tuple ptypeSizer = wx.BoxSizer( wx.HORIZONTAL ) @@ -111,6 +114,21 @@ class PFNetworkPref ( PreferenceView): mainSizer.Add( fgAddrSizer, 0, wx.EXPAND, 5) + # proxy auth information: login and pass + self.stPSetLogin = wx.StaticText(panel, wx.ID_ANY, u"Username:", wx.DefaultPosition, wx.DefaultSize, 0) + self.stPSetLogin.Wrap(-1) + self.editProxySettingsLogin = wx.TextCtrl(panel, wx.ID_ANY, self.nAuth[0], wx.DefaultPosition, wx.DefaultSize, 0) + self.stPSetPassword = wx.StaticText(panel, wx.ID_ANY, u"Password:", wx.DefaultPosition, wx.DefaultSize, 0) + self.stPSetPassword.Wrap(-1) + self.editProxySettingsPassword = wx.TextCtrl(panel, wx.ID_ANY, self.nAuth[1], wx.DefaultPosition, + wx.DefaultSize, wx.TE_PASSWORD) + pAuthSizer = wx.BoxSizer(wx.HORIZONTAL) + pAuthSizer.Add(self.stPSetLogin, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) + pAuthSizer.Add(self.editProxySettingsLogin, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) + pAuthSizer.Add(self.stPSetPassword, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) + pAuthSizer.Add(self.editProxySettingsPassword, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5) + mainSizer.Add(pAuthSizer, 0, wx.EXPAND, 5) + self.stPSAutoDetected = wx.StaticText( panel, wx.ID_ANY, u"Auto-detected: ", wx.DefaultPosition, wx.DefaultSize, 0 ) self.stPSAutoDetected.Wrap( -1 ) mainSizer.Add( self.stPSAutoDetected, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 ) @@ -138,13 +156,15 @@ class PFNetworkPref ( PreferenceView): self.chProxyType.Bind(wx.EVT_CHOICE, self.OnCHProxyTypeSelect) self.editProxySettingsAddr.Bind(wx.EVT_TEXT, self.OnEditPSAddrText) self.editProxySettingsPort.Bind(wx.EVT_TEXT, self.OnEditPSPortText) + self.editProxySettingsLogin.Bind(wx.EVT_TEXT, self.OnEditPSLoginText) + self.editProxySettingsPassword.Bind(wx.EVT_TEXT, self.OnEditPSPasswordText) self.btnApply.Bind(wx.EVT_BUTTON, self.OnBtnApply) self.UpdateApplyButtonState() - if self.nMode is not 2: + if self.nMode is not service.settings.NetworkSettings.PROXY_MODE_MANUAL: # == 2 self.ToggleProxySettings(False) else: self.ToggleProxySettings(True) @@ -180,6 +200,16 @@ class PFNetworkPref ( PreferenceView): self.dirtySettings = True self.UpdateApplyButtonState() + def OnEditPSLoginText(self, event): + self.nAuth = (self.editProxySettingsLogin.GetValue(), self.nAuth[1]) + self.dirtySettings = True + self.UpdateApplyButtonState() + + def OnEditPSPasswordText(self, event): + self.nAuth = (self.nAuth[0], self.editProxySettingsPassword.GetValue()) + self.dirtySettings = True + self.UpdateApplyButtonState() + def OnBtnApply(self, event): self.dirtySettings = False self.UpdateApplyButtonState() @@ -190,6 +220,7 @@ class PFNetworkPref ( PreferenceView): self.settings.setAddress(self.nAddr) self.settings.setPort(self.nPort) self.settings.setType(self.nType) + self.settings.setProxyAuthDetails(self.nAuth[0], self.nAuth[1]) def UpdateApplyButtonState(self): if self.dirtySettings: @@ -205,7 +236,7 @@ class PFNetworkPref ( PreferenceView): self.UpdateApplyButtonState() - if choice is not 2: + if choice is not service.settings.NetworkSettings.PROXY_MODE_MANUAL: self.ToggleProxySettings(False) else: self.ToggleProxySettings(True) @@ -216,11 +247,19 @@ class PFNetworkPref ( PreferenceView): self.editProxySettingsAddr.Enable() self.stPSetPort.Enable() self.editProxySettingsPort.Enable() + self.stPSetLogin.Enable() + self.stPSetPassword.Enable() + self.editProxySettingsLogin.Enable() + self.editProxySettingsPassword.Enable() else: self.stPSetAddr.Disable() self.editProxySettingsAddr.Disable() self.stPSetPort.Disable() self.editProxySettingsPort.Disable() + self.stPSetLogin.Disable() + self.stPSetPassword.Disable() + self.editProxySettingsLogin.Disable() + self.editProxySettingsPassword.Disable() def getImage(self): return BitmapLoader.getBitmap("prefs_proxy", "gui") diff --git a/service/network.py b/service/network.py index 04ba49875..f7383e03d 100644 --- a/service/network.py +++ b/service/network.py @@ -43,6 +43,7 @@ class ServerError(StandardError): class TimeoutError(StandardError): pass + class Network(): # Request constants - every request must supply this, as it is checked if # enabled or not via settings @@ -71,13 +72,31 @@ class Network(): # Set up some things for the request versionString = "{0} {1} - {2} {3}".format(config.version, config.tag, config.expansionName, config.expansionVersion) - headers={"User-Agent" : "pyfa {0} (Python-urllib2)".format(versionString)} + headers = {"User-Agent" : "pyfa {0} (Python-urllib2)".format(versionString)} proxy = NetworkSettings.getInstance().getProxySettings() if proxy is not None: - proxy = urllib2.ProxyHandler({'https': "{0}:{1}".format(*proxy)}) - opener = urllib2.build_opener(proxy) + # proxy is a tuple of (host, port): (u'192.168.20.1', 3128) + proxy_auth = NetworkSettings.getInstance().getProxyAuthDetails() + # proxy_auth is a tuple of (login, password) or None + if proxy_auth is not None: + # add login:password@ in front of proxy address + proxy_handler = urllib2.ProxyHandler({'https': '{0}:{1}@{2}:{3}'.format( + proxy_auth[0], proxy_auth[1], proxy[0], proxy[1])}) + else: + # build proxy handler with no login/pass info + proxy_handler = urllib2.ProxyHandler({'https': "{0}:{1}".format(proxy[0], proxy[1])}) + opener = urllib2.build_opener(proxy_handler) urllib2.install_opener(opener) + else: + # This is a bug fix, explicitly disable possibly previously installed + # opener with proxy, by urllib2.install_opener() a few lines above in code. + # Now this explicitly disables proxy handler, "uninstalling" opener. + # This is used in case when user had proxy enabled, so proxy_handler was already + # installed globally, and then user had disabled the proxy, so we should clear that opener + urllib2.install_opener(None) + # another option could be installing a default opener: + # urllib2.install_opener(urllib2.build_opener()) request = urllib2.Request(url, headers=headers, data=urllib.urlencode(data) if data else None) try: diff --git a/service/settings.py b/service/settings.py index cd1b33b44..d88354f12 100644 --- a/service/settings.py +++ b/service/settings.py @@ -113,6 +113,12 @@ class Settings(): class NetworkSettings(): _instance = None + + # constants for serviceNetworkDefaultSettings["mode"] parameter + PROXY_MODE_NONE = 0 # 0 - No proxy + PROXY_MODE_AUTODETECT = 1 # 1 - Auto-detected proxy settings + PROXY_MODE_MANUAL = 2 # 2 - Manual proxy settings + @classmethod def getInstance(cls): if cls._instance == None: @@ -122,13 +128,18 @@ class NetworkSettings(): def __init__(self): - # mode - # 0 - No proxy - # 1 - Auto-detected proxy settings - # 2 - Manual proxy settings - serviceNetworkDefaultSettings = {"mode": 1, "type": "https", "address": "", "port": "", "access": 15} + serviceNetworkDefaultSettings = { + "mode": self.PROXY_MODE_AUTODETECT, + "type": "https", + "address": "", + "port": "", + "access": 15, + "login": None, + "password": None + } - self.serviceNetworkSettings = SettingsProvider.getInstance().getSettings("pyfaServiceNetworkSettings", serviceNetworkDefaultSettings) + self.serviceNetworkSettings = SettingsProvider.getInstance().getSettings( + "pyfaServiceNetworkSettings", serviceNetworkDefaultSettings) def isEnabled(self, type): if type & self.serviceNetworkSettings["access"]: @@ -198,13 +209,33 @@ class NetworkSettings(): def getProxySettings(self): - if self.getMode() == 0: + if self.getMode() == self.PROXY_MODE_NONE: return None - if self.getMode() == 1: + if self.getMode() == self.PROXY_MODE_AUTODETECT: return self.autodetect() - if self.getMode() == 2: + if self.getMode() == self.PROXY_MODE_MANUAL: return (self.getAddress(), int(self.getPort())) + def getProxyAuthDetails(self): + if self.getMode() == self.PROXY_MODE_NONE: + return None + if (self.serviceNetworkSettings["login"] is None) or (self.serviceNetworkSettings["password"] is None): + return None + # in all other cases, return tuple of (login, password) + return (self.serviceNetworkSettings["login"], self.serviceNetworkSettings["password"]) + + def setProxyAuthDetails(self, login, password): + if (login is None) or (password is None): + self.serviceNetworkSettings["login"] = None + self.serviceNetworkSettings["password"] = None + return + if login == "": # empty login unsets proxy auth info + self.serviceNetworkSettings["login"] = None + self.serviceNetworkSettings["password"] = None + return + self.serviceNetworkSettings["login"] = login + self.serviceNetworkSettings["password"] = password + """