From 4df313e3cea9dea1c82da6360a27a6fd5a1b6e32 Mon Sep 17 00:00:00 2001 From: Waweic Date: Thu, 1 Mar 2018 11:56:38 +0100 Subject: [PATCH 1/4] Fix unicode problems in web plugin Added Exception to the web plugin to catch non latin-1 characters and change them to ascii chars. Added Description to the changelog file --- beetsplug/web/__init__.py | 11 ++++++----- docs/changelog.rst | 4 ++++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/beetsplug/web/__init__.py b/beetsplug/web/__init__.py index efbc3a99d..c85e6a8c0 100644 --- a/beetsplug/web/__init__.py +++ b/beetsplug/web/__init__.py @@ -24,6 +24,7 @@ import flask from flask import g from werkzeug.routing import BaseConverter, PathConverter import os +from unidecode import unidecode import json import base64 @@ -224,12 +225,12 @@ def item_file(item_id): item_path = util.syspath(item.path) else: item_path = util.py3_path(item.path) + try: + os.path.basename(util.py3_path(item.path)).encode("latin-1", "strict") #Imitate http.server behaviour + response = flask.send_file(item_path,as_attachment=True) + except UnicodeEncodeError: + response = flask.send_file(item_path,as_attachment=True, attachment_filename=unidecode(os.path.basename(util.py3_path(item.path)))) - response = flask.send_file( - item_path, - as_attachment=True, - attachment_filename=os.path.basename(util.py3_path(item.path)), - ) response.headers['Content-Length'] = os.path.getsize(item_path) return response diff --git a/docs/changelog.rst b/docs/changelog.rst index 26de4dfaa..2ae9ef074 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -75,6 +75,10 @@ Fixes: album art would not work and throw an exception. It now works as expected. Additionally, the server will now return a 404 response when the album id is unknown, instead of a 500 response and a thrown exception. :bug:`2823` +* :doc:`/plugins/web`: In a python 3 enviroment, the server would throw an + exception if non latin-1 characters where in the File name. + It now checks if non latin-1 characters are in the filename and changes + them to ascii-characters in that case :bug:`2815` For developers: From d0fd41b47484eca2fcf7c271ec35431f13cccd76 Mon Sep 17 00:00:00 2001 From: Waweic Date: Thu, 1 Mar 2018 19:45:44 +0100 Subject: [PATCH 2/4] Add unicode support for Python 2 and 3 Converts bytes to unicode using util.text_string, assuming that the string is a UTF-8 string. If that fails, it falls back to a hardcoded fallback filename. --- beetsplug/web/__init__.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/beetsplug/web/__init__.py b/beetsplug/web/__init__.py index c85e6a8c0..f9512ddc1 100644 --- a/beetsplug/web/__init__.py +++ b/beetsplug/web/__init__.py @@ -225,12 +225,19 @@ def item_file(item_id): item_path = util.syspath(item.path) else: item_path = util.py3_path(item.path) - try: - os.path.basename(util.py3_path(item.path)).encode("latin-1", "strict") #Imitate http.server behaviour - response = flask.send_file(item_path,as_attachment=True) - except UnicodeEncodeError: - response = flask.send_file(item_path,as_attachment=True, attachment_filename=unidecode(os.path.basename(util.py3_path(item.path)))) + try: + unicode_item_path = util.text_string(item.path) + except: + unicode_item_path = u"fallback" + os.path.splitext(item_path)[1] + + try: + os.path.basename(unicode_item_path).encode("latin-1", "strict") #Imitate http.server behaviour + safe_filename = os.path.basename(unicode_item_path) + except: + safe_filename = unidecode(os.path.basename(unicode_item_path)) + + response = flask.send_file(item_path,as_attachment=True, attachment_filename=safe_filename) response.headers['Content-Length'] = os.path.getsize(item_path) return response From 3c3e579dccbe20936ad44e5a9f6c043dd496983f Mon Sep 17 00:00:00 2001 From: Waweic Date: Thu, 1 Mar 2018 20:20:38 +0100 Subject: [PATCH 3/4] Make programming style pep8 compliant --- beetsplug/web/__init__.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/beetsplug/web/__init__.py b/beetsplug/web/__init__.py index f9512ddc1..29bb6b27a 100644 --- a/beetsplug/web/__init__.py +++ b/beetsplug/web/__init__.py @@ -228,16 +228,21 @@ def item_file(item_id): try: unicode_item_path = util.text_string(item.path) - except: + except (UnicodeDecodeError, UnicodeEncodeError): unicode_item_path = u"fallback" + os.path.splitext(item_path)[1] try: - os.path.basename(unicode_item_path).encode("latin-1", "strict") #Imitate http.server behaviour + # Imitate http.server behaviour + os.path.basename(unicode_item_path).encode("latin-1", "strict") safe_filename = os.path.basename(unicode_item_path) - except: + except (UnicodeDecodeError, UnicodeEncodeError): safe_filename = unidecode(os.path.basename(unicode_item_path)) - response = flask.send_file(item_path,as_attachment=True, attachment_filename=safe_filename) + response = flask.send_file( + item_path, + as_attachment=True, + attachment_filename=safe_filename + ) response.headers['Content-Length'] = os.path.getsize(item_path) return response From 06d4fe254d22a9f5315609f3a0908aef527a5d4c Mon Sep 17 00:00:00 2001 From: Waweic Date: Tue, 6 Mar 2018 17:49:20 +0100 Subject: [PATCH 4/4] Implement recommendations by sampsyo Implemented all recommendations. --- beetsplug/web/__init__.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/beetsplug/web/__init__.py b/beetsplug/web/__init__.py index 29bb6b27a..3cf43ed56 100644 --- a/beetsplug/web/__init__.py +++ b/beetsplug/web/__init__.py @@ -229,14 +229,16 @@ def item_file(item_id): try: unicode_item_path = util.text_string(item.path) except (UnicodeDecodeError, UnicodeEncodeError): - unicode_item_path = u"fallback" + os.path.splitext(item_path)[1] + unicode_item_path = util.displayable_path(item.path) + base_filename = os.path.basename(unicode_item_path) try: # Imitate http.server behaviour - os.path.basename(unicode_item_path).encode("latin-1", "strict") - safe_filename = os.path.basename(unicode_item_path) - except (UnicodeDecodeError, UnicodeEncodeError): - safe_filename = unidecode(os.path.basename(unicode_item_path)) + base_filename.encode("latin-1", "strict") + except UnicodeEncodeError: + safe_filename = unidecode(base_filename) + else: + safe_filename = base_filename response = flask.send_file( item_path,