From 2ce1a6e63949f9520eac98a0bda8bb3d179978fe Mon Sep 17 00:00:00 2001 From: geropan Date: Sun, 7 Jun 2020 18:27:20 +0100 Subject: [PATCH 1/2] Added support for custom set of safe characters (configured via addon settings) when escaping paths using direct paths for http(s), dav(s) and (s)ftp urls. --- .../resource.language.en_gb/strings.po | 5 +++ .../resource.language.es_ES/strings.po | 7 +++- resources/lib/app/libsync.py | 2 ++ resources/lib/plex_api/media.py | 2 +- resources/lib/utils.py | 33 ++++++++++++++++--- resources/settings.xml | 1 + 6 files changed, 44 insertions(+), 6 deletions(-) diff --git a/resources/language/resource.language.en_gb/strings.po b/resources/language/resource.language.en_gb/strings.po index 01c63f6f..380936d4 100644 --- a/resources/language/resource.language.en_gb/strings.po +++ b/resources/language/resource.language.en_gb/strings.po @@ -880,6 +880,11 @@ msgctxt "#39036" msgid "Escape special characters in path (e.g. space to %20)" msgstr "" +# PKC Settings - Customize Paths +msgctxt "#39090" +msgid "Safe characters for http(s), dav(s) and (s)ftp urls" +msgstr "" + # PKC Settings - Customize Paths msgctxt "#39037" msgid "Original Plex MOVIE path to replace:" diff --git a/resources/language/resource.language.es_ES/strings.po b/resources/language/resource.language.es_ES/strings.po index aa332347..820ec736 100644 --- a/resources/language/resource.language.es_ES/strings.po +++ b/resources/language/resource.language.es_ES/strings.po @@ -965,7 +965,12 @@ msgstr "" # PKC Settings - Customize Paths msgctxt "#39036" msgid "Escape special characters in path (e.g. space to %20)" -msgstr "Escapar caracteres especiales en la ruta (i.e. espacio a %20)" +msgstr "Escapar caracteres especiales en la ruta (p. ej. espacio a %20)" + +# PKC Settings - Customize Paths +msgctxt "#39090" +msgid "Safe characters for http(s), dav(s) and (s)ftp urls" +msgstr "Caracteres seguros para urls http(s), dav(s) y (s)ftp" # PKC Settings - Customize Paths msgctxt "#39037" diff --git a/resources/lib/app/libsync.py b/resources/lib/app/libsync.py index 3fb37887..c49db72b 100644 --- a/resources/lib/app/libsync.py +++ b/resources/lib/app/libsync.py @@ -42,6 +42,7 @@ class Sync(object): self.remapSMBphotoNew = None # Escape path? self.escape_path = None + self.escape_path_safe_chars = None # Shall we replace custom user ratings with the number of versions available? self.indicate_media_versions = None # Will sync movie trailer differently: either play trailer directly or show @@ -109,6 +110,7 @@ class Sync(object): self.remapSMBphotoOrg = remove_trailing_slash(utils.settings('remapSMBphotoOrg')) self.remapSMBphotoNew = remove_trailing_slash(utils.settings('remapSMBphotoNew')) self.escape_path = utils.settings('escapePath') == 'true' + self.escape_path_safe_chars = utils.settings('escapePathSafeChars').encode('utf-8') self.indicate_media_versions = utils.settings('indicate_media_versions') == "true" self.sync_specific_plex_playlists = utils.settings('syncSpecificPlexPlaylists') == 'true' self.sync_specific_kodi_playlists = utils.settings('syncSpecificKodiPlaylists') == 'true' diff --git a/resources/lib/plex_api/media.py b/resources/lib/plex_api/media.py index 7d091fa4..60353d7c 100644 --- a/resources/lib/plex_api/media.py +++ b/resources/lib/plex_api/media.py @@ -319,7 +319,7 @@ class Media(object): if path.startswith('\\\\'): path = 'smb:' + path.replace('\\', '/') if app.SYNC.escape_path: - path = utils.escape_path(path) + path = utils.escape_path(path, app.SYNC.escape_path_safe_chars) if (app.SYNC.path_verified and not force_check) or omit_check: return path diff --git a/resources/lib/utils.py b/resources/lib/utils.py index 72127168..4af0dceb 100644 --- a/resources/lib/utils.py +++ b/resources/lib/utils.py @@ -56,7 +56,7 @@ REGEX_MUSICPATH = re.compile(r'''^\^(.+)\$$''') REGEX_PLEX_ID_FROM_URL = re.compile(r'''metadata%2F(\d+)''') SAFE_URL_CHARACTERS = "%/:=&?~#+!$,;'@()*[]".encode('utf-8') - +HTTP_DAV_FTP = re.compile(r'(http(s)?|dav(s)?|(s)?ftp)://((.+):(.+)@)?([\w\.]+)(:([\d]+))?/') def garbageCollect(): gc.collect(2) @@ -385,7 +385,7 @@ def urlparse(url, scheme='', allow_fragments=True): return _urlparse.urlparse(url, scheme, allow_fragments) -def escape_path(path): +def escape_path(path, safe_url_char=SAFE_URL_CHARACTERS): """ Uses urllib.quote to escape to escape path [unicode]. See here for the reasoning whether a character is safe or not and whether or not it should @@ -396,8 +396,33 @@ def escape_path(path): you in trouble (e.g. '@') Returns the escaped path as unicode """ - return urllib.quote(path.encode('utf-8'), - safe=SAFE_URL_CHARACTERS).decode('utf-8') + is_http_dav_ftp = HTTP_DAV_FTP.match(path) + if is_http_dav_ftp: + # If path seems to be a http(s), dav(s) or (s)ftp url, the escape path will be constructed using RegExp and + # using safe_url_char as safe characters not to be escaped + protocol = is_http_dav_ftp.group(1) + user = is_http_dav_ftp.group(6) + psswd = is_http_dav_ftp.group(7) + if user and psswd: + user = urllib.quote(user.encode('utf-8'), safe=safe_url_char).decode('utf-8') + psswd = urllib.quote(psswd.encode('utf-8'), safe=safe_url_char).decode('utf-8') + host = is_http_dav_ftp.group(8) + port = is_http_dav_ftp.group(10) + url_path = path.replace(is_http_dav_ftp.group(), '', 1) + if url_path: + url_path = urllib.quote(path.replace(is_http_dav_ftp.group(), '', 1).encode('utf-8'), + safe=safe_url_char).decode('utf-8') + return protocol + \ + u'://' + \ + (user + u':' + psswd + u'@' if (user and psswd) else u'') + \ + host + \ + (u':' + port if port else u'') + \ + u'/' + \ + (url_path if url_path else u'') + else: + # If paths does not seem to be a http(s), dav(s) or (s)ftp url (e.g. plugin://), escape path as before + return urllib.quote(path.encode('utf-8'), + safe=SAFE_URL_CHARACTERS).decode('utf-8') def quote(s, safe='/'): diff --git a/resources/settings.xml b/resources/settings.xml index 6e3de284..a8b0cb76 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -101,6 +101,7 @@ + From 97078fda2c7ec06b98bdb15a820e48e123d4c56f Mon Sep 17 00:00:00 2001 From: geropan Date: Sun, 7 Jun 2020 18:58:46 +0100 Subject: [PATCH 2/2] Addressed line too long issues. --- resources/lib/utils.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/resources/lib/utils.py b/resources/lib/utils.py index 4af0dceb..5f14e5ea 100644 --- a/resources/lib/utils.py +++ b/resources/lib/utils.py @@ -398,8 +398,8 @@ def escape_path(path, safe_url_char=SAFE_URL_CHARACTERS): """ is_http_dav_ftp = HTTP_DAV_FTP.match(path) if is_http_dav_ftp: - # If path seems to be a http(s), dav(s) or (s)ftp url, the escape path will be constructed using RegExp and - # using safe_url_char as safe characters not to be escaped + # If path seems to be a http(s), dav(s) or (s)ftp url, the escape path will be constructed + # using RegExp and using safe_url_char as safe characters not to be escaped protocol = is_http_dav_ftp.group(1) user = is_http_dav_ftp.group(6) psswd = is_http_dav_ftp.group(7) @@ -420,7 +420,8 @@ def escape_path(path, safe_url_char=SAFE_URL_CHARACTERS): u'/' + \ (url_path if url_path else u'') else: - # If paths does not seem to be a http(s), dav(s) or (s)ftp url (e.g. plugin://), escape path as before + # If paths does not seem to be a http(s), dav(s) or (s)ftp url (e.g. plugin://) + # escape path as before return urllib.quote(path.encode('utf-8'), safe=SAFE_URL_CHARACTERS).decode('utf-8')