From 4ccc2c0aec1ee876c4a42d5ffa4385fae5f1e3a9 Mon Sep 17 00:00:00 2001 From: Ozzie Isaacs Date: Mon, 6 Jan 2025 17:36:17 +0100 Subject: [PATCH] Handle kindle browser download filename can only contain ASCII characters (#3266) --- cps/helper.py | 13 ++++++++----- cps/web.py | 7 ++++++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/cps/helper.py b/cps/helper.py index 9a5f0104..07200834 100644 --- a/cps/helper.py +++ b/cps/helper.py @@ -237,7 +237,7 @@ def send_mail(book_id, book_format, convert, ereader_mail, calibrepath, user_id) return _("The requested file could not be read. Maybe wrong permissions?") -def get_valid_filename(value, replace_whitespace=True, chars=128): +def get_valid_filename(value, replace_whitespace=True, chars=128, force_unidecode=False): """ Returns the given string converted to a string that can be used for a clean filename. Limits num characters to 128 max. @@ -245,7 +245,7 @@ def get_valid_filename(value, replace_whitespace=True, chars=128): if value[-1:] == '.': value = value[:-1]+'_' value = value.replace("/", "_").replace(":", "_").strip('\0') - if config.config_unicode_filename: + if config.config_unicode_filename or force_unidecode: value = (unidecode.unidecode(value)) if replace_whitespace: # *+:\"/<>? are replaced by _ @@ -1105,11 +1105,14 @@ def get_download_link(book_id, book_format, client): file_name = book.title if len(book.authors) > 0: file_name = file_name + ' - ' + book.authors[0].name - file_name = get_valid_filename(file_name, replace_whitespace=False) + if client != "kindle": + file_name = get_valid_filename(file_name, replace_whitespace=False, force_unidecode=True) + else: + file_name = quote(get_valid_filename(file_name, replace_whitespace=False)) headers = Headers() headers["Content-Type"] = mimetypes.types_map.get('.' + book_format, "application/octet-stream") - headers["Content-Disposition"] = "attachment; filename=%s.%s; filename*=UTF-8''%s.%s" % ( - quote(file_name), book_format, quote(file_name), book_format) + headers["Content-Disposition"] = ('attachment; filename="{}.{}"; filename*=UTF-8\'\'{}.{}').format( + file_name, book_format, file_name, book_format) return do_download_file(book, book_format, client, data1, headers) else: log.error("Book id {} not found for downloading".format(book_id)) diff --git a/cps/web.py b/cps/web.py index 12e8454d..3fa620a8 100644 --- a/cps/web.py +++ b/cps/web.py @@ -1242,7 +1242,12 @@ def serve_book(book_id, book_format, anyname): @login_required_if_no_ano @download_required def download_link(book_id, book_format, anyname): - client = "kobo" if "Kobo" in request.headers.get('User-Agent') else "" + if "kindle" in request.headers.get('User-Agent').lower(): + client = "kindle" + elif "Kobo" in request.headers.get('User-Agent').lower(): + client = "kobo" + else: + client = "" return get_download_link(book_id, book_format, client)