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": [{...}, {...}]}}
"""
import base64
import json
import logging
import os
import re
import urllib.request
import urllib.parse
import urllib.error
import urllib.parse
from urllib.parse import urlparse, parse_qs
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.utils import AppLocation, translate
from hashlib import sha1
log = logging.getLogger(__name__)
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 stateless so need
"""
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.serve_file),
('^/(stage)$', self.serve_file),
('^/(main)$', self.serve_file),
(r'^/files/(.*)$', self.serve_file),
(r'^/api/poll$', self.poll),
(r'^/stage/poll$', self.poll),
(r'^/main/poll$', self.main_poll),
(r'^/main/image$', self.main_image),
(r'^/api/controller/(live|preview)/(.*)$', self.controller),
(r'^/stage/controller/(live|preview)/(.*)$', self.controller),
(r'^/api/service/(.*)$', self.service),
(r'^/stage/service/(.*)$', self.service),
(r'^/api/display/(hide|show|blank|theme|desktop)$', self.display),
(r'^/api/alert$', self.alert),
(r'^/api/plugin/(search)$', self.plugin_info),
(r'^/api/(.*)/search$', self.search),
(r'^/api/(.*)/live$', self.go_live),
(r'^/api/(.*)/add$', self.add_to_service)
('^/$', {'function': self.serve_file, 'secure': False}),
('^/(stage)$', {'function': self.serve_file, 'secure': False}),
('^/(main)$', {'function': self.serve_file, 'secure': False}),
(r'^/files/(.*)$', {'function': self.serve_file, 'secure': False}),
(r'^/api/poll$', {'function': self.poll, 'secure': False}),
(r'^/stage/poll$', {'function': self.poll, 'secure': False}),
(r'^/main/poll$', {'function': self.poll, 'secure': False}),
(r'^/main/image$', {'function': self.main_poll, 'secure': False}),
(r'^/api/controller/(live|preview)/(.*)$', {'function': self.controller, 'secure': False}),
(r'^/stage/controller/(live|preview)/(.*)$', {'function': self.controller, 'secure': False}),
(r'^/api/service/(.*)$', {'function':self.service, 'secure': False}),
(r'^/stage/service/(.*)$', {'function': self.service, 'secure': False}),
(r'^/api/display/(hide|show|blank|theme|desktop)$', {'function': self.display, 'secure': True}),
(r'^/api/alert$', {'function': self.alert, 'secure': True}),
(r'^/api/plugin/(search)$', {'function': self.plugin_info, 'secure': False}),
(r'^/api/(.*)/search$', {'function': self.search, 'secure': False}),
(r'^/api/(.*)/live$', {'function': self.go_live, 'secure': True}),
(r'^/api/(.*)/add$', {'function': self.add_to_service, 'secure': True})
]
self.translate()
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):
"""
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``
The requested URL.
@ -189,7 +219,29 @@ class HttpRouter(object):
return response
else:
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):
"""
@ -259,25 +311,27 @@ class HttpRouter(object):
file_name = 'main.html'
path = os.path.normpath(os.path.join(self.html_dir, file_name))
if not path.startswith(self.html_dir):
return self._http_not_found()
return self.http_not_found()
ext = os.path.splitext(file_name)[1]
html = None
if ext == '.html':
mimetype = 'text/html'
self.send_header('Content-type', 'text/html')
variables = self.template_vars
html = Template(filename=path, input_encoding='utf-8', output_encoding='utf-8').render(**variables)
elif ext == '.css':
mimetype = 'text/css'
self.send_header('Content-type', 'text/css')
elif ext == '.js':
mimetype = 'application/x-javascript'
self.send_header('Content-type', 'application/x-javascript')
elif ext == '.jpg':
mimetype = 'image/jpeg'
self.send_header('Content-type', 'image/jpeg')
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':
mimetype = 'image/png'
self.send_header('Content-type', 'image/png')
else:
mimetype = 'text/plain'
self.send_header('Content-type', 'text/plain')
file_handle = None
try:
if html:

View File

@ -49,40 +49,26 @@ from openlp.plugins.remotes.lib import HttpRouter
from socketserver import BaseServer, ThreadingMixIn
from http.server import BaseHTTPRequestHandler, HTTPServer
from hashlib import sha1
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):
"""
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):
"""
Present pages / data and invoke URL level user authentication.
"""
self.do_GET()
def do_GET(self):
"""
Present frontpage with user authentication.
Present pages / data and invoke URL level user authentication.
"""
if self.path == '/favicon.ico':
return
@ -141,7 +127,7 @@ class HttpThread(QtCore.QThread):
class OpenLPServer():
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')
self.settings_section = 'remotes'
@ -149,24 +135,34 @@ class OpenLPServer():
self.http_thread.start()
def start_server(self):
"""
Start the correct server and save the handler
"""
address = Settings().value(self.settings_section + '/ip address')
if Settings().value(self.settings_section + '/https enabled'):
port = Settings().value(self.settings_section + '/https port')
self.httpd = HTTPSServer((address, port), CustomHandler)
print('started ssl httpd...')
log.debug('Started ssl httpd...')
else:
port = Settings().value(self.settings_section + '/port')
self.httpd = ThreadingHTTPServer((address, port), CustomHandler)
print('started non ssl httpd...')
log.debug('Started non ssl httpd...')
self.httpd.serve_forever()
def stop_server(self):
"""
Stop the server
"""
self.httpd.socket.close()
self.httpd = None
log.debug('Stopped the server.')
class HTTPSServer(HTTPServer):
def __init__(self, address, handler):
"""
Initialise the secure handlers for the SSL server if required.s
"""
BaseServer.__init__(self, address, handler)
local_data = AppLocation.get_directory(AppLocation.DataDir)
self.socket = ssl.SSLSocket(