diff --git a/openlp/core/api/http/endpoint/__init__.py b/openlp/core/api/http/endpoint/__init__.py index 3d306efbd..4355416b4 100644 --- a/openlp/core/api/http/endpoint/__init__.py +++ b/openlp/core/api/http/endpoint/__init__.py @@ -66,7 +66,6 @@ class Endpoint(object): if not self.template_dir: raise Exception('No template directory specified') path = os.path.abspath(os.path.join(self.template_dir, filename)) - print("path = ", path) # if self.static_dir: # kwargs['static_url'] = '/{prefix}/static'.format(prefix=self.url_prefix) return Template(filename=path, input_encoding='utf-8').render(**kwargs) diff --git a/openlp/core/api/http/endpoint/controller.py b/openlp/core/api/http/endpoint/controller.py index b605df10e..53d560476 100644 --- a/openlp/core/api/http/endpoint/controller.py +++ b/openlp/core/api/http/endpoint/controller.py @@ -26,15 +26,17 @@ import urllib.error import json from openlp.core.api.http.endpoint import Endpoint -from openlp.core.api.http import register_endpoint +from openlp.core.api.http import register_endpoint, requires_auth from openlp.core.common import Registry, AppLocation, Settings from openlp.core.lib import ItemCapabilities, create_thumb log = logging.getLogger(__name__) controller_endpoint = Endpoint('controller') +api_controller_endpoint = Endpoint('api') +@api_controller_endpoint.route('controller/live/text') @controller_endpoint.route('live/text') def controller_text(request): """ @@ -65,6 +67,7 @@ def controller_text(request): # Create thumbnail if it doesn't exists if not os.path.exists(full_thumbnail_path): create_thumb(current_item.get_frame_path(index), full_thumbnail_path, False) + Registry().get('image_manager').add_image(full_thumbnail_path, frame['title'], None, 88, 88) item['img'] = urllib.request.pathname2url(os.path.sep + thumbnail_path) item['text'] = str(frame['title']) item['html'] = str(frame['title']) @@ -81,6 +84,7 @@ def controller_text(request): data_path = AppLocation.get_data_path() if frame['image'][0:len(data_path)] == data_path: item['img'] = urllib.request.pathname2url(frame['image'][len(data_path):]) + Registry().get('image_manager').add_image(frame['image'], frame['title'], None, 88, 88) item['text'] = str(frame['title']) item['html'] = str(frame['title']) item['selected'] = (live_controller.selected_row == index) @@ -91,7 +95,9 @@ def controller_text(request): return json_data +@api_controller_endpoint.route('controller/live/set') @controller_endpoint.route('live/set') +@requires_auth def controller_set(request): """ Perform an action on the slide controller. @@ -108,3 +114,4 @@ def controller_set(request): return {'results': {'success': True}} register_endpoint(controller_endpoint) +register_endpoint(api_controller_endpoint) diff --git a/openlp/core/api/http/endpoint/core.py b/openlp/core/api/http/endpoint/core.py index 3fc0482cb..1776ec42a 100644 --- a/openlp/core/api/http/endpoint/core.py +++ b/openlp/core/api/http/endpoint/core.py @@ -118,6 +118,7 @@ def toggle_display(request, display): return {'results': {'success': True}} +@blank_endpoint.route('api/plugin/{search:search}') @blank_endpoint.route('plugin/{search:search}') def plugin_search(request, search): """ @@ -131,25 +132,25 @@ def plugin_search(request, search): searches.append([plugin.name, str(plugin.text_strings[StringContent.Name]['plural'])]) return {'results': {'items': searches}} -# @stage_endpoint.route('(stage)/(.*)$') -# def bespoke_file_access(request): -# """ -# Allow Stage view to be delivered with custom views. -# -# :param request: base path of the URL. Not used but passed by caller -# :return: -# """ -# file_name = request.path -# config_dir = os.path.join(AppLocation.get_data_path(), 'stages') -# log.debug('serve file request {name}'.format(name=file_name)) -# parts = file_name.split('/') -# if len(parts) == 1: -# file_name = os.path.join(parts[0], 'stage.mako') -# elif len(parts) == 3: -# file_name = os.path.join(parts[1], parts[2]) -# path = os.path.normpath(os.path.join(config_dir, file_name)) -# #return _process_file(path) -# pass + +@stage_endpoint.route('{local_path}') +def bespoke_file_access(request, local_path): + """ + Allow Stage view to be delivered with custom views. + + :param request: base path of the URL. Not used but passed by caller + :param local_path: path within the stages config directory + :return: + """ + config_dir = os.path.join(AppLocation.get_data_path(), 'stages') + log.debug('serve file request {name}'.format(name=local_path)) + parts = local_path.split('/') + if len(parts) == 1: + file_name = os.path.join(parts[0], 'stage.mako') + elif len(parts) == 3: + file_name = os.path.join(parts[1], parts[2]) + path = os.path.normpath(os.path.join(config_dir, file_name)) + #return _process_file(path) @main_endpoint.route('image') @@ -165,17 +166,6 @@ def main_image(request): } return {'results': result} -# @stage_endpoint.route(r'^/(\w+)/thumbnails([^/]+)?/(.*)$') -# def main_image(request): -# """ -# Get a list of songs -# :param request: base path of the URL. Not used but passed by caller -# :return: -# """ -# # songs = db.query(Song).get() -# # return {'songs': [dictify(song) for song in songs]} -# print("AAA") - def get_content_type(file_name): """ diff --git a/openlp/core/api/http/endpoint/service.py b/openlp/core/api/http/endpoint/service.py index f1d192858..335d81d21 100644 --- a/openlp/core/api/http/endpoint/service.py +++ b/openlp/core/api/http/endpoint/service.py @@ -30,8 +30,10 @@ from openlp.core.common import Registry log = logging.getLogger(__name__) service_endpoint = Endpoint('service') +api_service_endpoint = Endpoint('api/service') +@api_service_endpoint.route('list') @service_endpoint.route('list') def list_service(request): """ @@ -42,6 +44,7 @@ def list_service(request): return {'results': {'items': get_service_items()}} +@api_service_endpoint.route('set') @service_endpoint.route('set') @requires_auth def service_set(request): @@ -82,3 +85,4 @@ def get_service_items(): return service_items register_endpoint(service_endpoint) +register_endpoint(api_service_endpoint) diff --git a/openlp/core/api/http/wsgiapp.py b/openlp/core/api/http/wsgiapp.py index b28d4b365..1406e1035 100644 --- a/openlp/core/api/http/wsgiapp.py +++ b/openlp/core/api/http/wsgiapp.py @@ -79,6 +79,9 @@ def _make_response(view_result): body = json.dumps(body) response = Response(body=body, status=view_result[1], content_type=content_type, charset='utf8') + response.headers.add("Cache-Control", "no-cache, no-store, must-revalidate") + response.headers.add("Pragma", "no-cache") + response.headers.add("Expires", "0") if len(view_result) >= 3: response.headers.update(view_result[2]) return response @@ -134,13 +137,11 @@ class WSGIApplication(object): Find the appropriate URL and run the view function """ # We are not interested in this so discard - if '/favicon.ico' in request.path: + if 'favicon' in request.path: return # First look to see if this is a static file request for route, static_app in self.static_routes.items(): - print(route, request.path) if re.match(route, request.path): - print("matched static") # Pop the path info twice in order to get rid of the "//static" # request.path_info_pop() request.path_info_pop() @@ -148,12 +149,7 @@ class WSGIApplication(object): # If not a static route, try the views for route, views in self.route_map.items(): path = request.path - # /api is legacy so we need to handle backwards compatibility - if path.startswith('/api'): - path = path[4:] - print("route MATCHED", route, request.path, path) match = re.match(route, path) - print(match) if match and request.method.upper() in views: kwargs = match.groupdict() log.debug('Found {method} {url}'.format(method=request.method, url=request.path)) @@ -171,10 +167,16 @@ class WSGIApplication(object): response = self.dispatch(request) except Exception as e: response = _make_response(_handle_exception(e)) + response.headers.add("cache-control", "no-cache, no-store, must-revalidate") + response.headers.add("pragma", "no-cache") + response.headers.add("expires", "0") return response(environ, start_response) def __call__(self, environ, start_response): """ Shortcut for wsgi_app. """ + # We are not interested in this so discard + if 'favicon' in environ["PATH_INFO"]: + return return self.wsgi_app(environ, start_response) diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index 1c25fca25..fe8c06ce5 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -235,8 +235,15 @@ class ImageManager(QtCore.QObject): def get_image(self, path, source, width=-1, height=-1): """ Return the ``QImage`` from the cache. If not present wait for the background thread to process it. + + :param: path: The image path + :param: source: The source of the image + :param: background: The image background colour + :param: width: The processed image width + :param: height: The processed image height """ - log.debug('getImage {path}'.format(path=path)) + log.debug('get_image {path} {source} {width} {height}'.format(path=path, source=source, + width=width, height=height)) image = self._cache[(path, source, width, height)] if image.image is None: self._conversion_queue.modify_priority(image, Priority.High) @@ -255,8 +262,15 @@ class ImageManager(QtCore.QObject): def get_image_bytes(self, path, source, width=-1, height=-1): """ Returns the byte string for an image. If not present wait for the background thread to process it. + + :param: path: The image path + :param: source: The source of the image + :param: background: The image background colour + :param: width: The processed image width + :param: height: The processed image height """ - log.debug('get_image_bytes {path}'.format(path=path)) + log.debug('get_image_bytes {path} {source} {width} {height}'.format(path=path, source=source, + width=width, height=height)) image = self._cache[(path, source, width, height)] if image.image_bytes is None: self._conversion_queue.modify_priority(image, Priority.Urgent) @@ -270,8 +284,15 @@ class ImageManager(QtCore.QObject): def add_image(self, path, source, background, width=-1, height=-1): """ Add image to cache if it is not already there. + + :param: path: The image path + :param: source: The source of the image + :param: background: The image background colour + :param: width: The processed image width + :param: height: The processed image height """ - log.debug('add_image {path}'.format(path=path)) + log.debug('add_image {path} {source} {width} {height}'.format(path=path, source=source, + width=width, height=height)) if not (path, source, width, height) in self._cache: image = Image(path, source, background, width, height) self._cache[(path, source, width, height)] = image diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index ba56cb2d8..1dffbd33d 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -1068,8 +1068,8 @@ class SlideController(DisplayController, RegistryProperties): if self.service_item is not None: if hide: Registry().execute('live_display_hide', HideMode.Screen) - Registry().execute('{text}_hide'.format(text=self.service_item.name.lower()), - [self.service_item, self.is_live]) + # Registry().execute('{text}_hide'.format(text=self.service_item.name.lower()), + # [self.service_item, self.is_live]) else: if not self.service_item.is_command(): Registry().execute('live_display_show') diff --git a/openlp/plugins/presentations/lib/endpoint.py b/openlp/plugins/presentations/lib/endpoint.py index 380a5593d..57b3abdce 100644 --- a/openlp/plugins/presentations/lib/endpoint.py +++ b/openlp/plugins/presentations/lib/endpoint.py @@ -66,5 +66,43 @@ def presentations_service(request): """ return service(request, 'presentations', log) + +# /presentations/thumbnails88x88/PA%20Rota.pdf/slide5.png +@api_presentations_endpoint.route('presentations/thumbnails88x88/{file_name}/{slide}') +@presentations_endpoint.route('thumbnails88x88/{file_name}/{slide}') +def presentations_thumbnails(request, file_name, slide): + """ + Handles requests for adding a song to the service + + :param request: The http request object. + """ + controller_name = 'presentations' + dimensions = '88x88' + import os + import time + import urllib + from urllib.parse import urlparse + from webob import Response + from openlp.core.common import Registry, AppLocation + + log.debug('serve thumbnail {cname}/thumbnails{dim}/{fname}'.format(cname=controller_name, + dim=dimensions, + fname=file_name)) + content = None + if controller_name and file_name: + file_name = urllib.parse.unquote(file_name) + if '..' not in file_name: # no hacking please + full_path = os.path.normpath(os.path.join(AppLocation.get_section_data_path(controller_name), + 'thumbnails/', file_name, slide)) + if os.path.exists(full_path): + image_manager = Registry().get("image_manager") + i = 0 + while i < 4 and content is None: + content = image_manager.get_image_bytes(full_path, file_name, 88, 88) + time.sleep(0.1) + i += 1 + return Response(body=content, status=200, content_type='data:image/png;base64', charset='utf8') + + register_endpoint(presentations_endpoint) register_endpoint(api_presentations_endpoint)