From 83053e44a2b2e492f71060be18161b2e89867454 Mon Sep 17 00:00:00 2001 From: Philipp Wolfer Date: Tue, 22 Oct 2013 18:30:38 +0200 Subject: [PATCH 1/2] Add option to limit browser integration to localhost. This will make Picard's browser integration to listen on localhost only, as listening on the public interface is a possible security and privacy concern. There is still an option to enable listening on the external interface to allow for special requirements such as using the Picard Barcode Scanner android app. --- picard/browser/browser.py | 11 ++- picard/ui/options/network.py | 6 ++ picard/ui/ui_options_network.py | 28 +++++-- ui/options_network.ui | 125 ++++++++++++++++++++------------ 4 files changed, 113 insertions(+), 57 deletions(-) diff --git a/picard/browser/browser.py b/picard/browser/browser.py index bfa315140..b12086625 100644 --- a/picard/browser/browser.py +++ b/picard/browser/browser.py @@ -29,13 +29,20 @@ class BrowserIntegration(QtNetwork.QTcpServer): QtNetwork.QTcpServer.__init__(self, parent) self.newConnection.connect(self._accept_connection) self.port = 0 + self.host_address = None def start(self): if self.port: self.stop() + + if config.setting["browser_integration_localhost_only"]: + self.host_address = QtNetwork.QHostAddress(QtNetwork.QHostAddress.LocalHost) + else: + self.host_address = QtNetwork.QHostAddress(QtNetwork.QHostAddress.Any) + for port in range(config.setting["browser_integration_port"], 65535): - if self.listen(QtNetwork.QHostAddress(QtNetwork.QHostAddress.Any), port): - log.debug("Starting the browser integration (port %d)", port) + if self.listen(self.host_address, port): + log.debug("Starting the browser integration (%s:%d)", self.host_address.toString(), port) self.port = port self.tagger.listen_port_changed.emit(self.port) break diff --git a/picard/ui/options/network.py b/picard/ui/options/network.py index 5da16febf..9270b1a99 100644 --- a/picard/ui/options/network.py +++ b/picard/ui/options/network.py @@ -39,6 +39,7 @@ class NetworkOptionsPage(OptionsPage): config.TextOption("setting", "proxy_password", ""), config.BoolOption("setting", "browser_integration", True), config.IntOption("setting", "browser_integration_port", 8000), + config.BoolOption("setting", "browser_integration_localhost_only", True) ] def __init__(self, parent=None): @@ -55,6 +56,8 @@ class NetworkOptionsPage(OptionsPage): self.ui.password.setText(config.setting["proxy_password"]) self.ui.browser_integration.setChecked(config.setting["browser_integration"]) self.ui.browser_integration_port.setValue(config.setting["browser_integration_port"]) + self.ui.browser_integration_localhost_only.setChecked( + config.setting["browser_integration_localhost_only"]) QtCore.QObject.connect(self.ui.browser_integration_port, QtCore.SIGNAL('valueChanged(int)'), self.change_browser_integration_port) @@ -68,6 +71,9 @@ class NetworkOptionsPage(OptionsPage): self.tagger.xmlws.setup_proxy() config.setting["browser_integration"] = self.ui.browser_integration.isChecked() config.setting["browser_integration_port"] = self.ui.browser_integration_port.value() + config.setting["browser_integration_localhost_only"] = \ + self.ui.browser_integration_localhost_only.isChecked() + self.update_browser_integration() def update_browser_integration(self): if self.ui.browser_integration.isChecked(): diff --git a/picard/ui/ui_options_network.py b/picard/ui/ui_options_network.py index d1c82a9b5..c3e92a738 100644 --- a/picard/ui/ui_options_network.py +++ b/picard/ui/ui_options_network.py @@ -2,8 +2,8 @@ # Form implementation generated from reading ui file 'ui/options_network.ui' # -# Created: Mon Aug 5 22:00:12 2013 -# by: PyQt4 UI code generator 4.9.3 +# Created: Tue Oct 22 09:34:33 2013 +# by: PyQt4 UI code generator 4.10.3 # # WARNING! All changes made in this file will be lost! @@ -12,22 +12,31 @@ from PyQt4 import QtCore, QtGui try: _fromUtf8 = QtCore.QString.fromUtf8 except AttributeError: - _fromUtf8 = lambda s: s + def _fromUtf8(s): + return s + +try: + _encoding = QtGui.QApplication.UnicodeUTF8 + def _translate(context, text, disambig): + return QtGui.QApplication.translate(context, text, disambig, _encoding) +except AttributeError: + def _translate(context, text, disambig): + return QtGui.QApplication.translate(context, text, disambig) class Ui_NetworkOptionsPage(object): def setupUi(self, NetworkOptionsPage): NetworkOptionsPage.setObjectName(_fromUtf8("NetworkOptionsPage")) - NetworkOptionsPage.resize(233, 252) + NetworkOptionsPage.resize(316, 337) self.vboxlayout = QtGui.QVBoxLayout(NetworkOptionsPage) - self.vboxlayout.setMargin(9) self.vboxlayout.setSpacing(6) + self.vboxlayout.setMargin(9) self.vboxlayout.setObjectName(_fromUtf8("vboxlayout")) self.web_proxy = QtGui.QGroupBox(NetworkOptionsPage) self.web_proxy.setCheckable(True) self.web_proxy.setObjectName(_fromUtf8("web_proxy")) self.gridlayout = QtGui.QGridLayout(self.web_proxy) - self.gridlayout.setMargin(9) self.gridlayout.setSpacing(2) + self.gridlayout.setMargin(9) self.gridlayout.setObjectName(_fromUtf8("gridlayout")) self.password = QtGui.QLineEdit(self.web_proxy) self.password.setEchoMode(QtGui.QLineEdit.Password) @@ -49,8 +58,8 @@ class Ui_NetworkOptionsPage(object): self.label_7.setObjectName(_fromUtf8("label_7")) self.gridlayout.addWidget(self.label_7, 0, 1, 1, 1) self.server_port = QtGui.QSpinBox(self.web_proxy) - self.server_port.setMaximum(65535) self.server_port.setMinimum(1) + self.server_port.setMaximum(65535) self.server_port.setProperty("value", 80) self.server_port.setObjectName(_fromUtf8("server_port")) self.gridlayout.addWidget(self.server_port, 1, 1, 1, 1) @@ -90,6 +99,10 @@ class Ui_NetworkOptionsPage(object): self.browser_integration_port.setObjectName(_fromUtf8("browser_integration_port")) self.horizontalLayout.addWidget(self.browser_integration_port) self.verticalLayout_2.addWidget(self.widget) + self.browser_integration_localhost_only = QtGui.QCheckBox(self.browser_integration) + self.browser_integration_localhost_only.setChecked(False) + self.browser_integration_localhost_only.setObjectName(_fromUtf8("browser_integration_localhost_only")) + self.verticalLayout_2.addWidget(self.browser_integration_localhost_only) self.vboxlayout.addWidget(self.browser_integration) spacerItem = QtGui.QSpacerItem(101, 31, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) self.vboxlayout.addItem(spacerItem) @@ -111,4 +124,5 @@ class Ui_NetworkOptionsPage(object): self.label.setText(_("Server address:")) self.browser_integration.setTitle(_("Browser Integration")) self.label_2.setText(_("Default listening port:")) + self.browser_integration_localhost_only.setText(_("Listen only on localhost")) diff --git a/ui/options_network.ui b/ui/options_network.ui index 8d9a5751e..1dc6f010c 100644 --- a/ui/options_network.ui +++ b/ui/options_network.ui @@ -1,95 +1,114 @@ - + + NetworkOptionsPage - - + + 0 0 - 233 - 252 + 316 + 337 - - - 9 - - + + 6 + + 9 + + + 9 + + + 9 + + + 9 + - - + + Web Proxy - + true - - + + 9 - + + 9 + + + 9 + + + 9 + + 2 - - - + + + QLineEdit::Password - - + + - - - + + + Password: - + password - - - + + + Username: - + username - - + + - - - + + + Port: - - - - 65535 - - + + + 1 - + + 65535 + + 80 - - - + + + Server address: - + server_host @@ -102,7 +121,7 @@ Browser Integration - + true @@ -162,15 +181,25 @@ + + + + Listen only on localhost + + + false + + + - + Qt::Vertical - + 101 31 From e6272f1da5b3a2325f791769a83a4aa37744500c Mon Sep 17 00:00:00 2001 From: Philipp Wolfer Date: Tue, 22 Oct 2013 18:32:09 +0200 Subject: [PATCH 2/2] Apply changes to browser integration only on save. Fixes the case where the user disables the browser integration checkbox but does not save the settings. This lead to the browser integration being disabled while the option was still enabled. --- picard/ui/options/network.py | 1 - 1 file changed, 1 deletion(-) diff --git a/picard/ui/options/network.py b/picard/ui/options/network.py index 9270b1a99..c5f88efd8 100644 --- a/picard/ui/options/network.py +++ b/picard/ui/options/network.py @@ -46,7 +46,6 @@ class NetworkOptionsPage(OptionsPage): super(NetworkOptionsPage, self).__init__(parent) self.ui = Ui_NetworkOptionsPage() self.ui.setupUi(self) - self.ui.browser_integration.clicked.connect(self.update_browser_integration) def load(self): self.ui.web_proxy.setChecked(config.setting["use_proxy"])