openlp-core team mailing list archive
-
openlp-core team
-
Mailing list archive
-
Message #15692
[Merge] lp:~raoul-snyman/openlp/ssl into lp:openlp
Raoul Snyman has proposed merging lp:~raoul-snyman/openlp/ssl into lp:openlp.
Requested reviews:
Tim Bentley (trb143)
For more details, see:
https://code.launchpad.net/~raoul-snyman/openlp/ssl/+merge/106536
Implement an HTTPS server for the web remote and the Android remote.
--
https://code.launchpad.net/~raoul-snyman/openlp/ssl/+merge/106536
Your team OpenLP Core is subscribed to branch lp:openlp.
=== modified file 'openlp/core/utils/__init__.py'
--- openlp/core/utils/__init__.py 2012-05-01 12:58:22 +0000
+++ openlp/core/utils/__init__.py 2012-05-20 18:06:19 +0000
@@ -88,6 +88,7 @@
VersionDir = 5
CacheDir = 6
LanguageDir = 7
+ SharedData = 8
# Base path where data/config/cache dir is located
BaseDir = None
@@ -151,7 +152,8 @@
if dir_type == AppLocation.DataDir:
return os.path.join(unicode(os.getenv(u'APPDATA'), encoding),
u'openlp', u'data')
- elif dir_type == AppLocation.LanguageDir:
+ elif dir_type == AppLocation.LanguageDir or \
+ dir_type == AppLocation.SharedData:
return os.path.split(openlp.__file__)[0]
return os.path.join(unicode(os.getenv(u'APPDATA'), encoding),
u'openlp')
@@ -159,12 +161,14 @@
if dir_type == AppLocation.DataDir:
return os.path.join(unicode(os.getenv(u'HOME'), encoding),
u'Library', u'Application Support', u'openlp', u'Data')
- elif dir_type == AppLocation.LanguageDir:
+ elif dir_type == AppLocation.LanguageDir or \
+ dir_type == AppLocation.SharedData:
return os.path.split(openlp.__file__)[0]
return os.path.join(unicode(os.getenv(u'HOME'), encoding),
u'Library', u'Application Support', u'openlp')
else:
- if dir_type == AppLocation.LanguageDir:
+ if dir_type == AppLocation.LanguageDir or \
+ dir_type == AppLocation.SharedData:
return os.path.join(u'/usr', u'share', u'openlp')
if XDG_BASE_AVAILABLE:
if dir_type == AppLocation.ConfigDir:
=== modified file 'openlp/plugins/remotes/lib/httpserver.py'
--- openlp/plugins/remotes/lib/httpserver.py 2012-04-20 19:36:10 +0000
+++ openlp/plugins/remotes/lib/httpserver.py 2012-05-20 18:06:19 +0000
@@ -27,8 +27,8 @@
"""
The :mod:`http` module contains the API web server. This is a lightweight web
-server used by remotes to interact with OpenLP. It uses JSON to communicate with
-the remotes.
+server used by remotes to interact with OpenLP. It uses JSON to communicate
+with the remotes.
*Routes:*
@@ -126,6 +126,7 @@
log = logging.getLogger(__name__)
+
class HttpResponse(object):
"""
A simple object to encapsulate a pseudo-http response.
@@ -144,14 +145,60 @@
self.code = code
-class HttpServer(object):
+class SslServer(QtNetwork.QTcpServer):
+ """
+ SslServer is a class that implements an HTTPS server.
+ """
+ sslCertificate = None
+ sslPrivateKey = None
+ connections = []
+
+ @staticmethod
+ def checkCertificates():
+ cert_path = AppLocation.get_directory(AppLocation.SharedData)
+ crt_exists = os.path.exists(os.path.join(cert_path, u'openlp.crt'))
+ key_exists = os.path.exists(os.path.join(cert_path, u'openlp.key'))
+ return crt_exists and key_exists
+
+ def incomingConnection(self, socket_descriptor):
+ """
+ This method overrides the default one in :method:`incomingConnection`
+ to provide the SSL socket support needed for HTTPS.
+ """
+ log.debug(u'Incoming HTTPS connection')
+ cert_path = AppLocation.get_directory(AppLocation.SharedData)
+ if not SslServer.sslCertificate:
+ ssl_cert_data = QtCore.QByteArray(
+ open(os.path.join(cert_path, u'openlp.crt'), u'rb').read())
+ SslServer.sslCertificate = QtNetwork.QSslCertificate(ssl_cert_data)
+ if not SslServer.sslPrivateKey:
+ ssl_key_data = QtCore.QByteArray(
+ open(os.path.join(cert_path, u'openlp.key'), u'rb').read())
+ SslServer.sslPrivateKey = QtNetwork.QSslKey(ssl_key_data,
+ QtNetwork.QSsl.Rsa)
+ server_socket = QtNetwork.QSslSocket()
+ if server_socket.setSocketDescriptor(socket_descriptor):
+ server_socket.setPrivateKey(SslServer.sslPrivateKey)
+ server_socket.setLocalCertificate(SslServer.sslCertificate)
+ server_socket.setPeerVerifyMode(QtNetwork.QSslSocket.VerifyNone)
+ server_socket.startServerEncryption()
+ self.connections.append(server_socket)
+ self.addPendingConnection(server_socket)
+
+
+class HttpServer(QtCore.QObject):
"""
Ability to control OpenLP via a web browser.
"""
+
+ http_server = None
+ https_server = None
+
def __init__(self, plugin):
"""
Initialise the httpserver, and start the server.
"""
+ QtCore.QObject.__init__(self)
log.debug(u'Initialise httpserver')
self.plugin = plugin
self.html_dir = os.path.join(
@@ -160,33 +207,82 @@
self.connections = []
self.current_item = None
self.current_slide = None
- self.start_tcp()
-
- def start_tcp(self):
- """
- Start the http server, use the port in the settings default to 4316.
- Listen out for slide and song changes so they can be broadcast to
- clients. Listen out for socket connections.
- """
- log.debug(u'Start TCP server')
- port = QtCore.QSettings().value(
- self.plugin.settingsSection + u'/port',
- QtCore.QVariant(4316)).toInt()[0]
- address = QtCore.QSettings().value(
- self.plugin.settingsSection + u'/ip address',
- QtCore.QVariant(u'0.0.0.0')).toString()
- self.server = QtNetwork.QTcpServer()
- self.server.listen(QtNetwork.QHostAddress(address), port)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'slidecontroller_live_changed'),
self.slide_change)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'slidecontroller_live_started'),
self.item_change)
- QtCore.QObject.connect(self.server,
+ QtCore.QObject.connect(Receiver.get_receiver(),
+ QtCore.SIGNAL(u'remotes_config_updated'),
+ self.update_servers)
+ self.start_tcp()
+ if SslServer.checkCertificates() and \
+ QtCore.QSettings().value(self.plugin.settingsSection + \
+ u'/https enabled', QtCore.QVariant(False)).toBool():
+ self.start_ssl()
+
+ def update_servers(self):
+ """
+ Restart the server(s) if the configuration changes.
+ """
+ log.debug(u'Config changed, updating servers')
+ https_enabled = QtCore.QSettings().value(
+ self.plugin.settingsSection + u'/https enabled',
+ QtCore.QVariant(False)).toBool() and SslServer.checkCertificates()
+ # Restart the HTTP server
+ self.http_server.close()
+ self.http_server = None
+ self.start_tcp()
+ # Check the status of the HTTPS server and restart it
+ if not self.https_server and https_enabled:
+ self.start_ssl()
+ elif https_enabled and self.https_server:
+ self.https_server.close()
+ self.https_server = None
+ self.start_ssl()
+ elif self.https_server and not https_enabled:
+ self.https_server.close()
+ self.https_server = None
+
+ def start_tcp(self):
+ """
+ Start the HTTP server, use the port in the settings default to 4316.
+ Listen out for slide and song changes so they can be broadcast to
+ clients. Listen out for socket connections.
+ """
+ log.debug(u'Start TCP server')
+ settings = QtCore.QSettings()
+ settings.beginGroup(self.plugin.settingsSection)
+ port = settings.value(u'port', QtCore.QVariant(4316)).toInt()[0]
+ address = settings.value(
+ u'ip address', QtCore.QVariant(u'0.0.0.0')).toString()
+ settings.endGroup()
+ self.http_server = QtNetwork.QTcpServer()
+ self.http_server.listen(QtNetwork.QHostAddress(address), port)
+ QtCore.QObject.connect(self.http_server,
QtCore.SIGNAL(u'newConnection()'), self.new_connection)
log.debug(u'TCP listening on port %d' % port)
+ def start_ssl(self):
+ """
+ Start the HTTPS server, use the port in the settings default to 4317.
+ Listen out for slide and song changes so they can be broadcast to
+ clients. Listen out for socket connections.
+ """
+ log.debug(u'Start SSL server')
+ settings = QtCore.QSettings()
+ settings.beginGroup(self.plugin.settingsSection)
+ port = settings.value(u'ssl port', QtCore.QVariant(4317)).toInt()[0]
+ address = settings.value(
+ u'ip address', QtCore.QVariant(u'0.0.0.0')).toString()
+ settings.endGroup()
+ self.https_server = SslServer()
+ self.https_server.listen(QtNetwork.QHostAddress(address), port)
+ QtCore.QObject.connect(self.https_server,
+ QtCore.SIGNAL(u'newConnection()'), self.new_connection)
+ log.debug(u'SSL listening on port %d' % port)
+
def slide_change(self, row):
"""
Slide change listener. Store the item and tell the clients.
@@ -205,7 +301,8 @@
communication.
"""
log.debug(u'new http connection')
- socket = self.server.nextPendingConnection()
+ server = self.sender()
+ socket = server.nextPendingConnection()
if socket:
self.connections.append(HttpConnection(self, socket))
@@ -213,7 +310,7 @@
"""
The connection has been closed. Clean up
"""
- log.debug(u'close http connection')
+ log.debug(u'close connection')
if connection in self.connections:
self.connections.remove(connection)
@@ -222,7 +319,9 @@
Close down the http server.
"""
log.debug(u'close http server')
- self.server.close()
+ self.http_server.close()
+ if self.https_server:
+ self.https_server.close()
class HttpConnection(object):
@@ -252,10 +351,17 @@
(r'^/api/(.*)/live$', self.go_live),
(r'^/api/(.*)/add$', self.add_to_service)
]
- QtCore.QObject.connect(self.socket, QtCore.SIGNAL(u'readyRead()'),
- self.ready_read)
- QtCore.QObject.connect(self.socket, QtCore.SIGNAL(u'disconnected()'),
- self.disconnected)
+ if isinstance(socket, QtNetwork.QSslSocket):
+ QtCore.QObject.connect(self.socket, QtCore.SIGNAL(u'encrypted()'),
+ self.encrypted)
+ QtCore.QObject.connect(self.socket,
+ QtCore.SIGNAL(u'sslErrors(const QList<QSslError> &)'),
+ self.sslErrors)
+ else:
+ QtCore.QObject.connect(self.socket, QtCore.SIGNAL(u'readyRead()'),
+ self.ready_read)
+ QtCore.QObject.connect(self.socket,
+ QtCore.SIGNAL(u'disconnected()'), self.disconnected)
self.translate()
def _get_service_items(self):
@@ -309,17 +415,32 @@
'options': translate('RemotePlugin.Mobile', 'Options')
}
+ def encrypted(self):
+ """
+ Only setup these slots when the data is encrypted.
+ """
+ QtCore.QObject.connect(self.socket, QtCore.SIGNAL(u'readyRead()'),
+ self.ready_read)
+ QtCore.QObject.connect(self.socket, QtCore.SIGNAL(u'disconnected()'),
+ self.disconnected)
+
+ def sslErrors(self, errors):
+ for error in errors:
+ log.warn(unicode(error.errorString()))
+ self.socket.ignoreSslErrors()
+
def ready_read(self):
"""
Data has been sent from the client. Respond to it
"""
- log.debug(u'ready to read socket')
+ log.debug(u'Ready to read socket')
if self.socket.canReadLine():
data = str(self.socket.readLine())
try:
- log.debug(u'received: ' + data)
+ log.debug(u'Received: ' + data)
except UnicodeDecodeError:
# Malicious request containing non-ASCII characters.
+ self.send_response(HttpResponse(code='400 Bad Request'))
self.close()
return
words = data.split(' ')
@@ -342,23 +463,28 @@
else:
self.send_response(HttpResponse(code='404 Not Found'))
self.close()
+ else:
+ return
def serve_file(self, filename=None):
"""
- Send a file to the socket. For now, just a subset of file types
- and must be top level inside the html folder.
- If subfolders requested return 404, easier for security for the present.
+ Send a file to the socket. For now, only a subset of file types will
+ be send, and all files must be at the top level inside the html folder.
+ If sub-folders are requested return 404, easier for security for the
+ present.
Ultimately for i18n, this could first look for xx/file.html before
falling back to file.html... where xx is the language, e.g. 'en'
"""
- log.debug(u'serve file request %s' % filename)
+ log.debug(u'serve file request (original) %s' % filename)
if not filename:
filename = u'index.html'
elif filename == u'stage':
filename = u'stage.html'
+ log.debug(u'serve file request (updated) %s' % filename)
path = os.path.normpath(os.path.join(self.parent.html_dir, filename))
if not path.startswith(self.parent.html_dir):
+ log.debug(u'File not found, returning 404')
return HttpResponse(code=u'404 Not Found')
ext = os.path.splitext(filename)[1]
html = None
@@ -404,8 +530,8 @@
u'slide': self.parent.current_slide or 0,
u'item': self.parent.current_item._uuid \
if self.parent.current_item else u'',
- u'twelve':QtCore.QSettings().value(
- u'remotes/twelve hour', QtCore.QVariant(True)).toBool(),
+ u'twelve': QtCore.QSettings().value(
+ u'remotes/twelve hour', QtCore.QVariant(True)).toBool(),
u'blank': self.parent.plugin.liveController.blankScreen.\
isChecked(),
u'theme': self.parent.plugin.liveController.themeScreen.\
@@ -436,7 +562,7 @@
try:
text = json.loads(
self.url_params[u'data'][0])[u'request'][u'text']
- except KeyError, ValueError:
+ except (KeyError, ValueError):
return HttpResponse(code=u'400 Bad Request')
text = urllib.unquote(text)
Receiver.send_message(u'alerts_text', [text])
@@ -484,7 +610,7 @@
if self.url_params and self.url_params.get(u'data'):
try:
data = json.loads(self.url_params[u'data'][0])
- except KeyError, ValueError:
+ except (KeyError, ValueError):
return HttpResponse(code=u'400 Bad Request')
log.info(data)
# This slot expects an int within a list.
@@ -500,14 +626,16 @@
event = u'servicemanager_%s' % action
if action == u'list':
return HttpResponse(
- json.dumps({u'results': {u'items': self._get_service_items()}}),
+ json.dumps({
+ u'results': {u'items': self._get_service_items()}
+ }),
{u'Content-Type': u'application/json'})
else:
event += u'_item'
if self.url_params and self.url_params.get(u'data'):
try:
data = json.loads(self.url_params[u'data'][0])
- except KeyError, ValueError:
+ except (KeyError, ValueError):
return HttpResponse(code=u'400 Bad Request')
Receiver.send_message(event, data[u'request'][u'id'])
else:
@@ -543,7 +671,7 @@
"""
try:
text = json.loads(self.url_params[u'data'][0])[u'request'][u'text']
- except KeyError, ValueError:
+ except (KeyError, ValueError):
return HttpResponse(code=u'400 Bad Request')
text = urllib.unquote(text)
plugin = self.parent.plugin.pluginManager.get_plugin_by_name(type)
@@ -562,7 +690,7 @@
"""
try:
id = json.loads(self.url_params[u'data'][0])[u'request'][u'id']
- except KeyError, ValueError:
+ except (KeyError, ValueError):
return HttpResponse(code=u'400 Bad Request')
plugin = self.parent.plugin.pluginManager.get_plugin_by_name(type)
if plugin.status == PluginStatus.Active and plugin.mediaItem:
@@ -575,7 +703,7 @@
"""
try:
id = json.loads(self.url_params[u'data'][0])[u'request'][u'id']
- except KeyError, ValueError:
+ except (KeyError, ValueError):
return HttpResponse(code=u'400 Bad Request')
plugin = self.parent.plugin.pluginManager.get_plugin_by_name(type)
if plugin.status == PluginStatus.Active and plugin.mediaItem:
@@ -590,6 +718,7 @@
http += '\r\n'
self.socket.write(http)
self.socket.write(response.content)
+ self.socket.flush()
def disconnected(self):
"""
=== modified file 'openlp/plugins/remotes/lib/remotetab.py'
--- openlp/plugins/remotes/lib/remotetab.py 2012-03-18 09:33:05 +0000
+++ openlp/plugins/remotes/lib/remotetab.py 2012-05-20 18:06:19 +0000
@@ -26,8 +26,10 @@
###############################################################################
from PyQt4 import QtCore, QtGui, QtNetwork
+import os.path
from openlp.core.lib import SettingsTab, translate, Receiver
+from openlp.core.utils import AppLocation
ZERO_URL = u'0.0.0.0'
@@ -41,7 +43,9 @@
def setupUi(self):
self.setObjectName(u'RemoteTab')
SettingsTab.setupUi(self)
+ # Main server settings
self.serverSettingsGroupBox = QtGui.QGroupBox(self.leftColumn)
+ self.serverSettingsGroupBox.setContentsMargins(8, 8, 8, 8)
self.serverSettingsGroupBox.setObjectName(u'serverSettingsGroupBox')
self.serverSettingsLayout = QtGui.QFormLayout(
self.serverSettingsGroupBox)
@@ -60,27 +64,68 @@
self.twelveHourCheckBox = QtGui.QCheckBox(self.serverSettingsGroupBox)
self.twelveHourCheckBox.setObjectName(u'twelveHourCheckBox')
self.serverSettingsLayout.addRow(self.twelveHourCheckBox)
- self.portLabel = QtGui.QLabel(self.serverSettingsGroupBox)
- self.portLabel.setObjectName(u'portLabel')
- self.portSpinBox = QtGui.QSpinBox(self.serverSettingsGroupBox)
- self.portSpinBox.setMaximum(32767)
- self.portSpinBox.setObjectName(u'portSpinBox')
- QtCore.QObject.connect(self.portSpinBox,
- QtCore.SIGNAL(u'valueChanged(int)'), self.setUrls)
- self.serverSettingsLayout.addRow(self.portLabel, self.portSpinBox)
- self.remoteUrlLabel = QtGui.QLabel(self.serverSettingsGroupBox)
- self.remoteUrlLabel.setObjectName(u'remoteUrlLabel')
- self.remoteUrl = QtGui.QLabel(self.serverSettingsGroupBox)
- self.remoteUrl.setObjectName(u'remoteUrl')
- self.remoteUrl.setOpenExternalLinks(True)
- self.serverSettingsLayout.addRow(self.remoteUrlLabel, self.remoteUrl)
- self.stageUrlLabel = QtGui.QLabel(self.serverSettingsGroupBox)
- self.stageUrlLabel.setObjectName(u'stageUrlLabel')
- self.stageUrl = QtGui.QLabel(self.serverSettingsGroupBox)
- self.stageUrl.setObjectName(u'stageUrl')
- self.stageUrl.setOpenExternalLinks(True)
- self.serverSettingsLayout.addRow(self.stageUrlLabel, self.stageUrl)
self.leftLayout.addWidget(self.serverSettingsGroupBox)
+ self.httpSettingsGroupBox = QtGui.QGroupBox(self.leftColumn)
+ self.httpSettingsGroupBox.setObjectName(u'httpSettingsGroupBox')
+ self.httpSettingsLayout = QtGui.QFormLayout(
+ self.httpSettingsGroupBox)
+ self.httpSettingsLayout.setObjectName(u'httpSettingsLayout')
+ self.httpPortLabel = QtGui.QLabel(self.httpSettingsGroupBox)
+ self.httpPortLabel.setObjectName(u'httpPortLabel')
+ self.httpPortSpinBox = QtGui.QSpinBox(self.httpSettingsGroupBox)
+ self.httpPortSpinBox.setMaximum(32767)
+ self.httpPortSpinBox.setObjectName(u'httpPortSpinBox')
+ self.httpSettingsLayout.addRow(
+ self.httpPortLabel, self.httpPortSpinBox)
+ self.remoteHttpUrlLabel = QtGui.QLabel(self.httpSettingsGroupBox)
+ self.remoteHttpUrlLabel.setObjectName(u'remoteHttpUrlLabel')
+ self.remoteHttpUrl = QtGui.QLabel(self.httpSettingsGroupBox)
+ self.remoteHttpUrl.setObjectName(u'remoteHttpUrl')
+ self.remoteHttpUrl.setOpenExternalLinks(True)
+ self.httpSettingsLayout.addRow(
+ self.remoteHttpUrlLabel, self.remoteHttpUrl)
+ self.stageHttpUrlLabel = QtGui.QLabel(self.httpSettingsGroupBox)
+ self.stageHttpUrlLabel.setObjectName(u'stageHttpUrlLabel')
+ self.stageHttpUrl = QtGui.QLabel(self.httpSettingsGroupBox)
+ self.stageHttpUrl.setObjectName(u'stageHttpUrl')
+ self.stageHttpUrl.setOpenExternalLinks(True)
+ self.httpSettingsLayout.addRow(
+ self.stageHttpUrlLabel, self.stageHttpUrl)
+ self.leftLayout.addWidget(self.httpSettingsGroupBox)
+ self.httpsSettingsGroupBox = QtGui.QGroupBox(self.leftColumn)
+ self.httpsSettingsGroupBox.setCheckable(True)
+ self.httpsSettingsGroupBox.setChecked(False)
+ self.httpsSettingsGroupBox.setObjectName(u'httpsSettingsGroupBox')
+ self.httpsSettingsLayout = QtGui.QFormLayout(
+ self.httpsSettingsGroupBox)
+ self.httpsSettingsLayout.setObjectName(u'httpsSettingsLayout')
+ self.httpsErrorLabel = QtGui.QLabel(self.httpsSettingsGroupBox)
+ self.httpsErrorLabel.setVisible(False)
+ self.httpsErrorLabel.setWordWrap(True)
+ self.httpsErrorLabel.setObjectName(u'httpsErrorLabel')
+ self.httpsSettingsLayout.addRow(self.httpsErrorLabel)
+ self.httpsPortLabel = QtGui.QLabel(self.httpsSettingsGroupBox)
+ self.httpsPortLabel.setObjectName(u'httpsPortLabel')
+ self.httpsPortSpinBox = QtGui.QSpinBox(self.httpsSettingsGroupBox)
+ self.httpsPortSpinBox.setMaximum(32767)
+ self.httpsPortSpinBox.setObjectName(u'httpsPortSpinBox')
+ self.httpsSettingsLayout.addRow(
+ self.httpsPortLabel, self.httpsPortSpinBox)
+ self.remoteHttpsUrl = QtGui.QLabel(self.httpsSettingsGroupBox)
+ self.remoteHttpsUrl.setObjectName(u'remoteHttpsUrl')
+ self.remoteHttpsUrl.setOpenExternalLinks(True)
+ self.remoteHttpsUrlLabel = QtGui.QLabel(self.httpsSettingsGroupBox)
+ self.remoteHttpsUrlLabel.setObjectName(u'remoteHttpsUrlLabel')
+ self.httpsSettingsLayout.addRow(
+ self.remoteHttpsUrlLabel, self.remoteHttpsUrl)
+ self.stageHttpsUrlLabel = QtGui.QLabel(self.httpsSettingsGroupBox)
+ self.stageHttpsUrlLabel.setObjectName(u'stageHttpsUrlLabel')
+ self.stageHttpsUrl = QtGui.QLabel(self.httpsSettingsGroupBox)
+ self.stageHttpsUrl.setObjectName(u'stageHttpsUrl')
+ self.stageHttpsUrl.setOpenExternalLinks(True)
+ self.httpsSettingsLayout.addRow(
+ self.stageHttpsUrlLabel, self.stageHttpsUrl)
+ self.leftLayout.addWidget(self.httpsSettingsGroupBox)
self.androidAppGroupBox = QtGui.QGroupBox(self.rightColumn)
self.androidAppGroupBox.setObjectName(u'androidAppGroupBox')
self.rightLayout.addWidget(self.androidAppGroupBox)
@@ -99,6 +144,10 @@
self.qrLayout.addWidget(self.qrDescriptionLabel)
self.leftLayout.addStretch()
self.rightLayout.addStretch()
+ QtCore.QObject.connect(self.httpPortSpinBox,
+ QtCore.SIGNAL(u'valueChanged(int)'), self.setUrls)
+ QtCore.QObject.connect(self.httpsPortSpinBox,
+ QtCore.SIGNAL(u'valueChanged(int)'), self.setUrls)
QtCore.QObject.connect(self.twelveHourCheckBox,
QtCore.SIGNAL(u'stateChanged(int)'),
self.onTwelveHourCheckBoxChanged)
@@ -108,11 +157,25 @@
translate('RemotePlugin.RemoteTab', 'Server Settings'))
self.addressLabel.setText(translate('RemotePlugin.RemoteTab',
'Serve on IP address:'))
- self.portLabel.setText(translate('RemotePlugin.RemoteTab',
- 'Port number:'))
- self.remoteUrlLabel.setText(translate('RemotePlugin.RemoteTab',
- 'Remote URL:'))
- self.stageUrlLabel.setText(translate('RemotePlugin.RemoteTab',
+ self.httpSettingsGroupBox.setTitle(
+ translate('RemotePlugin.RemoteTab', 'HTTP Server'))
+ self.httpPortLabel.setText(translate('RemotePlugin.RemoteTab',
+ 'Port number:'))
+ self.remoteHttpUrlLabel.setText(translate('RemotePlugin.RemoteTab',
+ 'Remote URL:'))
+ self.stageHttpUrlLabel.setText(translate('RemotePlugin.RemoteTab',
+ 'Stage view URL:'))
+ self.httpsSettingsGroupBox.setTitle(
+ translate('RemotePlugin.RemoteTab', 'HTTPS Server'))
+ self.httpsErrorLabel.setText(translate('RemotePlugin.RemoteTab',
+ 'Could not find an SSL certificate. The HTTPS server will not be '
+ 'available unless an SSL certificate is found. Please see the '
+ 'manual for more information.'))
+ self.httpsPortLabel.setText(translate('RemotePlugin.RemoteTab',
+ 'Port number:'))
+ self.remoteHttpsUrlLabel.setText(translate('RemotePlugin.RemoteTab',
+ 'Remote URL:'))
+ self.stageHttpsUrlLabel.setText(translate('RemotePlugin.RemoteTab',
'Stage view URL:'))
self.twelveHourCheckBox.setText(
translate('RemotePlugin.RemoteTab',
@@ -125,7 +188,7 @@
'download</a> to install the Android app from the Market.'))
def setUrls(self):
- ipAddress = u'localhost'
+ ip_address = u'localhost'
if self.addressEdit.text() == ZERO_URL:
ifaces = QtNetwork.QNetworkInterface.allInterfaces()
for iface in ifaces:
@@ -138,41 +201,79 @@
ip = addr.ip()
if ip.protocol() == 0 and \
ip != QtNetwork.QHostAddress.LocalHost:
- ipAddress = ip.toString()
+ ip_address = ip.toString()
break
else:
- ipAddress = self.addressEdit.text()
- url = u'http://%s:%s/' % (ipAddress, self.portSpinBox.value())
- self.remoteUrl.setText(u'<a href="%s">%s</a>' % (url, url))
- url = url + u'stage'
- self.stageUrl.setText(u'<a href="%s">%s</a>' % (url, url))
+ ip_address = self.addressEdit.text()
+ http_url = u'http://%s:%s/' % \
+ (ip_address, self.httpPortSpinBox.value())
+ https_url = u'https://%s:%s/' % \
+ (ip_address, self.httpsPortSpinBox.value())
+ self.remoteHttpUrl.setText(u'<a href="%s">%s</a>' % \
+ (http_url, http_url))
+ self.remoteHttpsUrl.setText(u'<a href="%s">%s</a>' % \
+ (https_url, https_url))
+ http_url += u'stage'
+ https_url += u'stage'
+ self.stageHttpUrl.setText(u'<a href="%s">%s</a>' % \
+ (http_url, http_url))
+ self.stageHttpsUrl.setText(u'<a href="%s">%s</a>' % \
+ (https_url, https_url))
def load(self):
- self.portSpinBox.setValue(
- QtCore.QSettings().value(self.settingsSection + u'/port',
- QtCore.QVariant(4316)).toInt()[0])
+ settings = QtCore.QSettings()
+ settings.beginGroup(self.settingsSection)
+ self.httpPortSpinBox.setValue(
+ settings.value(u'port', QtCore.QVariant(4316)).toInt()[0])
+ self.httpsPortSpinBox.setValue(
+ settings.value(u'ssl port', QtCore.QVariant(4317)).toInt()[0])
self.addressEdit.setText(
- QtCore.QSettings().value(self.settingsSection + u'/ip address',
- QtCore.QVariant(ZERO_URL)).toString())
- self.twelveHour = QtCore.QSettings().value(
- self.settingsSection + u'/twelve hour',
- QtCore.QVariant(True)).toBool()
+ settings.value(
+ u'ip address', QtCore.QVariant(ZERO_URL)).toString())
+ self.twelveHour = settings.value(
+ u'twelve hour', QtCore.QVariant(True)).toBool()
+ shared_data = AppLocation.get_directory(AppLocation.SharedData)
+ if not os.path.exists(os.path.join(shared_data, u'openlp.crt')) or \
+ not os.path.exists(os.path.join(shared_data, u'openlp.key')):
+ self.httpsSettingsGroupBox.setChecked(False)
+ self.httpsSettingsGroupBox.setEnabled(False)
+ self.httpsErrorLabel.setVisible(True)
+ else:
+ self.httpsSettingsGroupBox.setChecked(settings.value(
+ u'https enabled', QtCore.QVariant(False)).toBool())
+ self.httpsSettingsGroupBox.setEnabled(True)
+ self.httpsErrorLabel.setVisible(False)
+ settings.endGroup()
self.twelveHourCheckBox.setChecked(self.twelveHour)
self.setUrls()
def save(self):
changed = False
- if QtCore.QSettings().value(self.settingsSection + u'/ip address',
- QtCore.QVariant(ZERO_URL).toString() != self.addressEdit.text() or
- QtCore.QSettings().value(self.settingsSection + u'/port',
- QtCore.QVariant(4316).toInt()[0]) != self.portSpinBox.value()):
+ settings = QtCore.QSettings()
+ settings.beginGroup(self.settingsSection)
+ ip_address = settings.value(
+ u'ip address', QtCore.QVariant(ZERO_URL).toString())
+ http_port = settings.value(
+ u'port', QtCore.QVariant(4316).toInt()[0])
+ https_port = settings.value(
+ u'ssl port', QtCore.QVariant(4317).toInt()[0])
+ https_enabled = settings.value(
+ u'https enabled', QtCore.QVariant(False)).toBool()
+ if ip_address != self.addressEdit.text() or \
+ http_port != self.httpPortSpinBox.value() or\
+ https_port != self.httpsPortSpinBox.value() or \
+ https_enabled != self.httpsSettingsGroupBox.isChecked():
changed = True
- QtCore.QSettings().setValue(self.settingsSection + u'/port',
- QtCore.QVariant(self.portSpinBox.value()))
- QtCore.QSettings().setValue(self.settingsSection + u'/ip address',
- QtCore.QVariant(self.addressEdit.text()))
- QtCore.QSettings().setValue(self.settingsSection + u'/twelve hour',
- QtCore.QVariant(self.twelveHour))
+ settings.setValue(
+ u'port', QtCore.QVariant(self.httpPortSpinBox.value()))
+ settings.setValue(
+ u'ssl port', QtCore.QVariant(self.httpsPortSpinBox.value()))
+ settings.setValue(
+ u'ip address', QtCore.QVariant(self.addressEdit.text()))
+ settings.setValue(u'twelve hour', QtCore.QVariant(self.twelveHour))
+ settings.setValue(u'https enabled',
+ QtCore.QVariant(self.httpsSettingsGroupBox.isChecked()))
+ settings.endGroup()
if changed:
Receiver.send_message(u'remotes_config_updated')
Follow ups