From 8adae6ed0cd749f52af0300923c74c8c7c28b241 Mon Sep 17 00:00:00 2001 From: Ozzie Isaacs Date: Sun, 3 Apr 2022 20:26:43 +0200 Subject: [PATCH] Handle permission errors for static files (Fix for #2358) Version bump --- cps/cache_buster.py | 15 +++++++++------ cps/constants.py | 2 +- cps/error_handler.py | 5 +++-- cps/helper.py | 9 ++++++--- cps/render_template.py | 14 +++++++++----- cps/web.py | 6 +++++- 6 files changed, 33 insertions(+), 18 deletions(-) diff --git a/cps/cache_buster.py b/cps/cache_buster.py index 9619d605..ba19afd6 100644 --- a/cps/cache_buster.py +++ b/cps/cache_buster.py @@ -47,13 +47,16 @@ def init_cache_busting(app): for filename in filenames: # compute version component rooted_filename = os.path.join(dirpath, filename) - with open(rooted_filename, 'rb') as f: - file_hash = hashlib.md5(f.read()).hexdigest()[:7] # nosec + try: + with open(rooted_filename, 'rb') as f: + file_hash = hashlib.md5(f.read()).hexdigest()[:7] # nosec + # save version to tables + file_path = rooted_filename.replace(static_folder, "") + file_path = file_path.replace("\\", "/") # Convert Windows path to web path + hash_table[file_path] = file_hash + except PermissionError: + log.error("No permission to access {} file.".format(rooted_filename)) - # save version to tables - file_path = rooted_filename.replace(static_folder, "") - file_path = file_path.replace("\\", "/") # Convert Windows path to web path - hash_table[file_path] = file_hash log.debug('Finished computing cache-busting values') def bust_filename(filename): diff --git a/cps/constants.py b/cps/constants.py index c2eb0527..f40d16b0 100644 --- a/cps/constants.py +++ b/cps/constants.py @@ -154,7 +154,7 @@ def selected_roles(dictionary): BookMeta = namedtuple('BookMeta', 'file_path, extension, title, author, cover, description, tags, series, ' 'series_id, languages, publisher') -STABLE_VERSION = {'version': '0.6.18'} +STABLE_VERSION = {'version': '0.6.19 Beta'} NIGHTLY_VERSION = dict() NIGHTLY_VERSION[0] = '$Format:%H$' diff --git a/cps/error_handler.py b/cps/error_handler.py index 37b7500e..67252a66 100644 --- a/cps/error_handler.py +++ b/cps/error_handler.py @@ -42,8 +42,9 @@ def error_http(error): def internal_error(error): return render_template('http_error.html', - error_code="Internal Server Error", - error_name=str(error), + error_code="500 Internal Server Error", + error_name='The server encountered an internal error and was unable to complete your ' + 'request. There is an error in the application.', issue=True, unconfigured=False, error_stack=traceback.format_exc().split("\n"), diff --git a/cps/helper.py b/cps/helper.py index 742188d0..5d5cc021 100644 --- a/cps/helper.py +++ b/cps/helper.py @@ -698,9 +698,12 @@ def delete_book(book, calibrepath, book_format): def get_cover_on_failure(use_generic_cover): if use_generic_cover: - return send_from_directory(_STATIC_DIR, "generic_cover.jpg") - else: - return None + try: + return send_from_directory(_STATIC_DIR, "generic_cover.jpg") + except PermissionError: + log.error("No permission to access generic_cover.jpg file.") + abort(403) + abort(404) def get_book_cover(book_id): diff --git a/cps/render_template.py b/cps/render_template.py index 0c5423c9..d2f40d6c 100644 --- a/cps/render_template.py +++ b/cps/render_template.py @@ -18,11 +18,11 @@ from flask import render_template, request from flask_babel import gettext as _ -from flask import g +from flask import g, abort from werkzeug.local import LocalProxy from flask_login import current_user -from . import config, constants, ub, logger, db, calibre_db +from . import config, constants, logger from .ub import User @@ -119,6 +119,10 @@ def get_sidebar_config(kwargs=None): # Returns the template for rendering and includes the instance name def render_title_template(*args, **kwargs): sidebar, simple = get_sidebar_config(kwargs) - return render_template(instance=config.config_calibre_web_title, sidebar=sidebar, simple=simple, - accept=constants.EXTENSIONS_UPLOAD, # read_book_ids=get_readbooks_ids(), - *args, **kwargs) + try: + return render_template(instance=config.config_calibre_web_title, sidebar=sidebar, simple=simple, + accept=constants.EXTENSIONS_UPLOAD, + *args, **kwargs) + except PermissionError: + log.error("No permission to access {} file.".format(args[0])) + abort(403) diff --git a/cps/web.py b/cps/web.py index e8bf48e3..a0ecbb8e 100644 --- a/cps/web.py +++ b/cps/web.py @@ -1368,7 +1368,11 @@ def get_cover(book_id): @web.route("/robots.txt") def get_robots(): - return send_from_directory(constants.STATIC_DIR, "robots.txt") + try: + return send_from_directory(constants.STATIC_DIR, "robots.txt") + except PermissionError: + log.error("No permission to access robots.txt file.") + abort(403) @web.route("/show//", defaults={'anyname': 'None'})