Readonly works - next comes updates

This commit is contained in:
Tim Bentley 2013-09-12 17:46:57 +01:00
parent d0813eddac
commit 448da916e9
2 changed files with 108 additions and 58 deletions

View File

@ -112,15 +112,14 @@ the remotes.
{"results": {"items": [{...}, {...}]}} {"results": {"items": [{...}, {...}]}}
""" """
import base64
import json import json
import logging import logging
import os import os
import re import re
import urllib.request import urllib.request
import urllib.parse
import urllib.error import urllib.error
import urllib.parse from urllib.parse import urlparse, parse_qs
from mako.template import Template from mako.template import Template
@ -129,46 +128,77 @@ from PyQt4 import QtCore
from openlp.core.lib import Registry, Settings, PluginStatus, StringContent, image_to_byte from openlp.core.lib import Registry, Settings, PluginStatus, StringContent, image_to_byte
from openlp.core.utils import AppLocation, translate from openlp.core.utils import AppLocation, translate
from hashlib import sha1
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class HttpRouter(object): class HttpRouter(object):
""" """
This code is called by the HttpServer upon a request and it processes it based on the routing table. This code is called by the HttpServer upon a request and it processes it based on the routing table.
This code is stateless so need
""" """
def initialise(self): def initialise(self):
""" """
Initialise the router Initialise the router stack and any other varables.
""" """
authcode = "%s:%s" % (Settings().value('remotes/user id'), Settings().value('remotes/password'))
try:
self.auth = base64.b64encode(authcode)
except TypeError:
self.auth = base64.b64encode(authcode.encode()).decode()
self.routes = [ self.routes = [
('^/$', self.serve_file), ('^/$', {'function': self.serve_file, 'secure': False}),
('^/(stage)$', self.serve_file), ('^/(stage)$', {'function': self.serve_file, 'secure': False}),
('^/(main)$', self.serve_file), ('^/(main)$', {'function': self.serve_file, 'secure': False}),
(r'^/files/(.*)$', self.serve_file), (r'^/files/(.*)$', {'function': self.serve_file, 'secure': False}),
(r'^/api/poll$', self.poll), (r'^/api/poll$', {'function': self.poll, 'secure': False}),
(r'^/stage/poll$', self.poll), (r'^/stage/poll$', {'function': self.poll, 'secure': False}),
(r'^/main/poll$', self.main_poll), (r'^/main/poll$', {'function': self.poll, 'secure': False}),
(r'^/main/image$', self.main_image), (r'^/main/image$', {'function': self.main_poll, 'secure': False}),
(r'^/api/controller/(live|preview)/(.*)$', self.controller), (r'^/api/controller/(live|preview)/(.*)$', {'function': self.controller, 'secure': False}),
(r'^/stage/controller/(live|preview)/(.*)$', self.controller), (r'^/stage/controller/(live|preview)/(.*)$', {'function': self.controller, 'secure': False}),
(r'^/api/service/(.*)$', self.service), (r'^/api/service/(.*)$', {'function':self.service, 'secure': False}),
(r'^/stage/service/(.*)$', self.service), (r'^/stage/service/(.*)$', {'function': self.service, 'secure': False}),
(r'^/api/display/(hide|show|blank|theme|desktop)$', self.display), (r'^/api/display/(hide|show|blank|theme|desktop)$', {'function': self.display, 'secure': True}),
(r'^/api/alert$', self.alert), (r'^/api/alert$', {'function': self.alert, 'secure': True}),
(r'^/api/plugin/(search)$', self.plugin_info), (r'^/api/plugin/(search)$', {'function': self.plugin_info, 'secure': False}),
(r'^/api/(.*)/search$', self.search), (r'^/api/(.*)/search$', {'function': self.search, 'secure': False}),
(r'^/api/(.*)/live$', self.go_live), (r'^/api/(.*)/live$', {'function': self.go_live, 'secure': True}),
(r'^/api/(.*)/add$', self.add_to_service) (r'^/api/(.*)/add$', {'function': self.add_to_service, 'secure': True})
] ]
self.translate() self.translate()
self.html_dir = os.path.join(AppLocation.get_directory(AppLocation.PluginsDir), 'remotes', 'html') self.html_dir = os.path.join(AppLocation.get_directory(AppLocation.PluginsDir), 'remotes', 'html')
def call_function(self, function, *args):
response = function['function'](*args)
if response:
self.wfile.write(response)
return
def process_http_request(self, url_path, *args): def process_http_request(self, url_path, *args):
""" """
Common function to process HTTP requests Common function to process HTTP requests
``url_path``
The requested URL.
``*args``
Any passed data.
"""
url_path_split = urlparse(url_path)
for route, func in self.routes:
match = re.match(route, url_path_split.path)
if match:
print('Route "%s" matched "%s"', route, url_path)
args = []
for param in match.groups():
args.append(param)
return func, args
return None, None
def _process_http_request(self, url_path, *args):
"""
Common function to process HTTP requests
``url_path`` ``url_path``
The requested URL. The requested URL.
@ -189,7 +219,29 @@ class HttpRouter(object):
return response return response
else: else:
log.debug('Path not found %s', url_path) log.debug('Path not found %s', url_path)
return self._http_not_found() return self.do_not_found()
def do_http_success(self):
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
def do_http_error(self):
self.send_response(404)
self.send_header('Content-type', 'text/html')
self.end_headers()
def do_authorisation(self):
self.send_response(401)
self.send_header('WWW-Authenticate', 'Basic realm=\"Test\"')
self.send_header('Content-type', 'text/html')
self.end_headers()
def do_notfound(self):
self.send_response(404)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(bytes('<html><body>Sorry, an error occurred </body></html>', 'UTF-8'))
def _get_service_items(self): def _get_service_items(self):
""" """
@ -259,25 +311,27 @@ class HttpRouter(object):
file_name = 'main.html' file_name = 'main.html'
path = os.path.normpath(os.path.join(self.html_dir, file_name)) path = os.path.normpath(os.path.join(self.html_dir, file_name))
if not path.startswith(self.html_dir): if not path.startswith(self.html_dir):
return self._http_not_found() return self.http_not_found()
ext = os.path.splitext(file_name)[1] ext = os.path.splitext(file_name)[1]
html = None html = None
if ext == '.html': if ext == '.html':
mimetype = 'text/html' self.send_header('Content-type', 'text/html')
variables = self.template_vars variables = self.template_vars
html = Template(filename=path, input_encoding='utf-8', output_encoding='utf-8').render(**variables) html = Template(filename=path, input_encoding='utf-8', output_encoding='utf-8').render(**variables)
elif ext == '.css': elif ext == '.css':
mimetype = 'text/css' self.send_header('Content-type', 'text/css')
elif ext == '.js': elif ext == '.js':
mimetype = 'application/x-javascript' self.send_header('Content-type', 'application/x-javascript')
elif ext == '.jpg': elif ext == '.jpg':
mimetype = 'image/jpeg' self.send_header('Content-type', 'image/jpeg')
elif ext == '.gif': elif ext == '.gif':
mimetype = 'image/gif' self.send_header('Content-type', 'image/gif')
elif ext == '.ico':
self.send_header('Content-type', 'image/ico')
elif ext == '.png': elif ext == '.png':
mimetype = 'image/png' self.send_header('Content-type', 'image/png')
else: else:
mimetype = 'text/plain' self.send_header('Content-type', 'text/plain')
file_handle = None file_handle = None
try: try:
if html: if html:

View File

@ -49,40 +49,26 @@ from openlp.plugins.remotes.lib import HttpRouter
from socketserver import BaseServer, ThreadingMixIn from socketserver import BaseServer, ThreadingMixIn
from http.server import BaseHTTPRequestHandler, HTTPServer from http.server import BaseHTTPRequestHandler, HTTPServer
from hashlib import sha1
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
def make_sha_hash(password):
"""
Create an encrypted password for the given password.
"""
log.debug("make_sha_hash")
return sha1(password.encode()).hexdigest()
def fetch_password(username):
"""
Fetch the password for a provided user.
"""
log.debug("Fetch Password")
if username != Settings().value('remotes/user id'):
return None
return make_sha_hash(Settings().value('remotes/password'))
class CustomHandler(BaseHTTPRequestHandler, HttpRouter): class CustomHandler(BaseHTTPRequestHandler, HttpRouter):
""" """
Main class to present webpages and authentication. Stateless session handler to handle the HTTP request and process it.
This class handles just the overrides to the base methods and the logic to invoke the
methods within the HttpRouter class.
DO not try change the structure as this is as per the documentation.
""" """
def do_POST(self): def do_POST(self):
"""
Present pages / data and invoke URL level user authentication.
"""
self.do_GET() self.do_GET()
def do_GET(self): def do_GET(self):
""" """
Present frontpage with user authentication. Present pages / data and invoke URL level user authentication.
""" """
if self.path == '/favicon.ico': if self.path == '/favicon.ico':
return return
@ -141,7 +127,7 @@ class HttpThread(QtCore.QThread):
class OpenLPServer(): class OpenLPServer():
def __init__(self): def __init__(self):
""" """
Initialise the http server, and start the server. Initialise the http server, and start the server of the correct type http / https
""" """
log.debug('Initialise httpserver') log.debug('Initialise httpserver')
self.settings_section = 'remotes' self.settings_section = 'remotes'
@ -149,24 +135,34 @@ class OpenLPServer():
self.http_thread.start() self.http_thread.start()
def start_server(self): def start_server(self):
"""
Start the correct server and save the handler
"""
address = Settings().value(self.settings_section + '/ip address') address = Settings().value(self.settings_section + '/ip address')
if Settings().value(self.settings_section + '/https enabled'): if Settings().value(self.settings_section + '/https enabled'):
port = Settings().value(self.settings_section + '/https port') port = Settings().value(self.settings_section + '/https port')
self.httpd = HTTPSServer((address, port), CustomHandler) self.httpd = HTTPSServer((address, port), CustomHandler)
print('started ssl httpd...') log.debug('Started ssl httpd...')
else: else:
port = Settings().value(self.settings_section + '/port') port = Settings().value(self.settings_section + '/port')
self.httpd = ThreadingHTTPServer((address, port), CustomHandler) self.httpd = ThreadingHTTPServer((address, port), CustomHandler)
print('started non ssl httpd...') log.debug('Started non ssl httpd...')
self.httpd.serve_forever() self.httpd.serve_forever()
def stop_server(self): def stop_server(self):
"""
Stop the server
"""
self.httpd.socket.close() self.httpd.socket.close()
self.httpd = None self.httpd = None
log.debug('Stopped the server.')
class HTTPSServer(HTTPServer): class HTTPSServer(HTTPServer):
def __init__(self, address, handler): def __init__(self, address, handler):
"""
Initialise the secure handlers for the SSL server if required.s
"""
BaseServer.__init__(self, address, handler) BaseServer.__init__(self, address, handler)
local_data = AppLocation.get_directory(AppLocation.DataDir) local_data = AppLocation.get_directory(AppLocation.DataDir)
self.socket = ssl.SSLSocket( self.socket = ssl.SSLSocket(