diff --git a/openlp/plugins/remotes/html/openlp.js b/openlp/plugins/remotes/html/openlp.js index 0c15d9c07..626ab51cb 100644 --- a/openlp/plugins/remotes/html/openlp.js +++ b/openlp/plugins/remotes/html/openlp.js @@ -72,7 +72,9 @@ window.OpenLP = { ); }, loadController: function (event) { - event.preventDefault(); + if (event) { + event.preventDefault(); + } $.getJSON( "/api/controller/live/text", function (data, status) { @@ -91,6 +93,7 @@ window.OpenLP = { li.children("a").click(OpenLP.setSlide); ul.append(li); } + OpenLP.currentItem = data.results.item; ul.listview("refresh"); } ); @@ -208,9 +211,8 @@ window.OpenLP = { }, showAlert: function (event) { event.preventDefault(); - var text = "{\"request\": {\"text\": \"" + - $("#alert-text").val().replace(/\\/g, "\\\\").replace(/"/g, "\\\"") + - "\"}}"; + var alert = OpenLP.escapeString($("#alert-text").val()) + var text = "{\"request\": {\"text\": \"" + alert + "\"}}"; $.getJSON( "/api/alert", {"data": text}, @@ -221,9 +223,8 @@ window.OpenLP = { }, search: function (event) { event.preventDefault(); - var text = "{\"request\": {\"text\": \"" + - $("#search-text").val().replace(/\\/g, "\\\\").replace(/"/g, "\\\"") + - "\"}}"; + var query = OpenLP.escapeString($("#search-text").val()) + var text = "{\"request\": {\"text\": \"" + query + "\"}}"; $.getJSON( "/api/" + $("#search-plugin").val() + "/search", {"data": text}, @@ -280,6 +281,9 @@ window.OpenLP = { ); $("#options").dialog("close"); $.mobile.changePage("#service-manager"); + }, + escapeString: function (string) { + return string.replace(/\\/g, "\\\\").replace(/"/g, "\\\"") } } // Service Manager diff --git a/openlp/plugins/remotes/lib/httpserver.py b/openlp/plugins/remotes/lib/httpserver.py index b9df5ebd3..383c7fa03 100644 --- a/openlp/plugins/remotes/lib/httpserver.py +++ b/openlp/plugins/remotes/lib/httpserver.py @@ -111,15 +111,12 @@ the remotes. {"results": {"items": [{...}, {...}]}} """ +import json import logging import os -import urlparse import re - -try: - import json -except ImportError: - import simplejson as json +import urllib +import urlparse from PyQt4 import QtCore, QtNetwork from mako.template import Template @@ -314,11 +311,14 @@ class HttpConnection(object): """ log.debug(u'ready to read socket') if self.socket.canReadLine(): - data = self.socket.readLine() - data = QtCore.QByteArray.fromPercentEncoding(data) - data = unicode(data, 'utf8') - log.debug(u'received: ' + data) - words = data.split(u' ') + data = str(self.socket.readLine()) + try: + log.debug(u'received: ' + data) + except UnicodeDecodeError: + # Malicious request containing non-ASCII characters. + self.close() + return + words = data.split(' ') response = None if words[0] == u'GET': url = urlparse.urlparse(words[1]) @@ -426,11 +426,19 @@ class HttpConnection(object): """ Send an alert. """ - text = json.loads(self.url_params[u'data'][0])[u'request'][u'text'] plugin = self.parent.plugin.pluginManager.get_plugin_by_name("alerts") if plugin.status == PluginStatus.Active: + try: + text = json.loads( + self.url_params[u'data'][0])[u'request'][u'text'] + except KeyError, ValueError: + return HttpResponse(code=u'400 Bad Request') + text = urllib.unquote(text) Receiver.send_message(u'alerts_text', [text]) - return HttpResponse(json.dumps({u'results': {u'success': True}}), + success = True + else: + success = False + return HttpResponse(json.dumps({u'results': {u'success': success}}), {u'Content-Type': u'application/json'}) def controller(self, type, action): @@ -465,9 +473,14 @@ class HttpConnection(object): item[u'selected'] = (self.parent.current_slide == index) data.append(item) json_data = {u'results': {u'slides': data}} + if current_item: + json_data[u'results'][u'item'] = self.parent.current_item._uuid else: if self.url_params and self.url_params.get(u'data'): - data = json.loads(self.url_params[u'data'][0]) + try: + data = json.loads(self.url_params[u'data'][0]) + except KeyError, ValueError: + return HttpResponse(code=u'400 Bad Request') log.info(data) # This slot expects an int within a list. id = data[u'request'][u'id'] @@ -487,7 +500,10 @@ class HttpConnection(object): else: event += u'_item' if self.url_params and self.url_params.get(u'data'): - data = json.loads(self.url_params[u'data'][0]) + try: + data = json.loads(self.url_params[u'data'][0]) + except KeyError, ValueError: + return HttpResponse(code=u'400 Bad Request') Receiver.send_message(event, data[u'request'][u'id']) else: Receiver.send_message(event) @@ -520,7 +536,11 @@ class HttpConnection(object): ``type`` The plugin name to search in. """ - text = json.loads(self.url_params[u'data'][0])[u'request'][u'text'] + try: + text = json.loads(self.url_params[u'data'][0])[u'request'][u'text'] + except KeyError, ValueError: + return HttpResponse(code=u'400 Bad Request') + text = urllib.unquote(text) plugin = self.parent.plugin.pluginManager.get_plugin_by_name(type) if plugin.status == PluginStatus.Active and \ plugin.mediaItem and plugin.mediaItem.hasSearch: @@ -535,20 +555,28 @@ class HttpConnection(object): """ Go live on an item of type ``type``. """ - id = json.loads(self.url_params[u'data'][0])[u'request'][u'id'] + try: + id = json.loads(self.url_params[u'data'][0])[u'request'][u'id'] + 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: plugin.mediaItem.goLive(id, remote=True) + return HttpResponse(code=u'200 OK') def add_to_service(self, type): """ Add item of type ``type`` to the end of the service. """ - id = json.loads(self.url_params[u'data'][0])[u'request'][u'id'] + try: + id = json.loads(self.url_params[u'data'][0])[u'request'][u'id'] + 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: item_id = plugin.mediaItem.createItemFromId(id) plugin.mediaItem.addToService(item_id, remote=True) + return HttpResponse(code=u'200 OK') def send_response(self, response): http = u'HTTP/1.1 %s\r\n' % response.code