tMerge pull request #2193 from bauerj/socks-auth - electrum - Electrum Bitcoin wallet (HTM) git clone https://git.parazyd.org/electrum (DIR) Log (DIR) Files (DIR) Refs (DIR) Submodules --- (DIR) commit bc31d83466ce649675605a8946a3bb26ab909aeb (DIR) parent 622e50163830f7e76e668ea4f54b3b910bb055c8 (HTM) Author: ThomasV <thomasv@electrum.org> Date: Sat, 25 Feb 2017 15:05:57 +0100 Merge pull request #2193 from bauerj/socks-auth Allow using a SOCKS5 proxy with authentication Diffstat: M gui/qt/network_dialog.py | 30 +++++++++++++++++++++--------- M lib/network.py | 15 +++++++++++++-- 2 files changed, 34 insertions(+), 11 deletions(-) --- (DIR) diff --git a/gui/qt/network_dialog.py b/gui/qt/network_dialog.py t@@ -155,15 +155,17 @@ class NetworkChoiceLayout(object): self.proxy_port = QLineEdit() self.proxy_port.setFixedWidth(60) self.proxy_mode.addItems(['NONE', 'SOCKS4', 'SOCKS5', 'HTTP']) + self.proxy_user = QLineEdit() + self.proxy_user.setPlaceholderText(_("Proxy user")) + self.proxy_password = QLineEdit() + self.proxy_password.setPlaceholderText(_("Password")) + self.proxy_password.setEchoMode(QLineEdit.Password) + self.proxy_password.setFixedWidth(60) def check_for_disable(index = False): if self.config.is_modifiable('proxy'): - if self.proxy_mode.currentText() != 'NONE': - self.proxy_host.setEnabled(True) - self.proxy_port.setEnabled(True) - else: - self.proxy_host.setEnabled(False) - self.proxy_port.setEnabled(False) + for w in [self.proxy_host, self.proxy_port, self.proxy_user, self.proxy_password]: + w.setEnabled(self.proxy_mode.currentText() != 'NONE') else: for w in [self.proxy_host, self.proxy_port, self.proxy_mode]: w.setEnabled(False) t@@ -173,20 +175,26 @@ class NetworkChoiceLayout(object): self.proxy_mode.setCurrentIndex(self.proxy_mode.findText(str(proxy_config.get("mode").upper()))) self.proxy_host.setText(proxy_config.get("host")) self.proxy_port.setText(proxy_config.get("port")) + self.proxy_user.setText(proxy_config.get("user", "")) + self.proxy_password.setText(proxy_config.get("password", "")) self.proxy_mode.connect(self.proxy_mode, SIGNAL('currentIndexChanged(int)'), self.proxy_settings_changed) self.proxy_host.connect(self.proxy_host, SIGNAL('textEdited(QString)'), self.proxy_settings_changed) self.proxy_port.connect(self.proxy_port, SIGNAL('textEdited(QString)'), self.proxy_settings_changed) + self.proxy_user.connect(self.proxy_user, SIGNAL('textEdited(QString)'), self.proxy_settings_changed) + self.proxy_password.connect(self.proxy_password, SIGNAL('textEdited(QString)'), self.proxy_settings_changed) grid.addWidget(QLabel(_('Proxy') + ':'), 4, 0) grid.addWidget(self.proxy_mode, 4, 1) grid.addWidget(self.proxy_host, 4, 2) grid.addWidget(self.proxy_port, 4, 3) - self.tor_button = QCheckBox("Use Tor Proxy") + grid.addWidget(self.proxy_user, 5, 2) + grid.addWidget(self.proxy_password, 5, 3) + self.tor_button = QCheckBox(_("Use Tor Proxy")) self.tor_button.setIcon(QIcon(":icons/tor_logo.png")) self.tor_button.hide() self.tor_button.clicked.connect(self.use_tor_proxy) - grid.addWidget(self.tor_button, 5, 1, 1, 2) + grid.addWidget(self.tor_button, 6, 2, 1, 2) self.layout_ = vbox self.td = td = TorDetector() td.found_proxy.connect(self.suggest_proxy) t@@ -258,7 +266,9 @@ class NetworkChoiceLayout(object): if self.proxy_mode.currentText() != 'NONE': proxy = { 'mode':str(self.proxy_mode.currentText()).lower(), 'host':str(self.proxy_host.text()), - 'port':str(self.proxy_port.text()) } + 'port':str(self.proxy_port.text()), + 'user':str(self.proxy_user.text()), + 'password':str(self.proxy_password.text())} else: proxy = None t@@ -284,6 +294,8 @@ class NetworkChoiceLayout(object): self.proxy_mode.setCurrentIndex(2) self.proxy_host.setText("127.0.0.1") self.proxy_port.setText(str(self.tor_proxy[1])) + self.proxy_user.setText("") + self.proxy_password.setText("") self.tor_button.setChecked(True) def proxy_settings_changed(self): (DIR) diff --git a/lib/network.py b/lib/network.py t@@ -129,7 +129,7 @@ proxy_modes = ['socks4', 'socks5', 'http'] def serialize_proxy(p): if type(p) != dict: return None - return ':'.join([p.get('mode'),p.get('host'), p.get('port')]) + return ':'.join([p.get('mode'),p.get('host'), p.get('port'), p.get('user'), p.get('password')]) def deserialize_proxy(s): if type(s) not in [str, unicode]: t@@ -147,8 +147,14 @@ def deserialize_proxy(s): n += 1 if len(args) > n: proxy["port"] = args[n] + n += 1 else: proxy["port"] = "8080" if proxy["mode"] == "http" else "1080" + if len(args) > n: + proxy["user"] = args[n] + n += 1 + if len(args) > n: + proxy["password"] = args[n] return proxy def deserialize_server(server_str): t@@ -400,7 +406,12 @@ class Network(util.DaemonThread): if proxy: self.print_error('setting proxy', proxy) proxy_mode = proxy_modes.index(proxy["mode"]) + 1 - socks.setdefaultproxy(proxy_mode, proxy["host"], int(proxy["port"])) + socks.setdefaultproxy(proxy_mode, + proxy["host"], + int(proxy["port"]), + # socks.py seems to want either None or a non-empty string + username=(proxy.get("user", "") or None), + password=(proxy.get("password", "") or None)) socket.socket = socks.socksocket # prevent dns leaks, see http://stackoverflow.com/questions/13184205/dns-over-proxy socket.getaddrinfo = lambda *args: [(socket.AF_INET, socket.SOCK_STREAM, 6, '', (args[0], args[1]))]