From e5b5fa2c829d0d79f42adb45c5f2ce4aba7d9496 Mon Sep 17 00:00:00 2001 From: Tobias Brox Date: Tue, 24 May 2022 17:44:14 +0200 Subject: [PATCH] potential fix for https://github.com/python-caldav/caldav/issues/189 --- caldav/lib/url.py | 28 ++++++++++++++++++++-------- caldav/objects.py | 4 ++-- tests/test_caldav_unit.py | 3 +++ 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/caldav/lib/url.py b/caldav/lib/url.py index 86a46c9c..192b689e 100644 --- a/caldav/lib/url.py +++ b/caldav/lib/url.py @@ -4,10 +4,11 @@ from six import PY3 from caldav.lib.python_utilities import to_unicode, to_normal_str if PY3: - from urllib.parse import ParseResult, SplitResult, urlparse + from urllib.parse import ParseResult, SplitResult, urlparse, unquote, quote, urlunparse else: from urlparse import ParseResult, SplitResult - from urlparse import urlparse + from urlparse import urlparse, urlunparse + from urllib import unquote, quote def uc2utf8(input): @@ -133,7 +134,7 @@ def canonical(self): """ a canonical URL ... remove authentication details, make sure there are no double slashes, and to make sure the URL is always the same, - run it through the urlparser + run it through the urlparser, and make sure path is properly quoted """ url = self.unauth() @@ -141,13 +142,24 @@ def canonical(self): if '//' in url.path: raise NotImplementedError("remove the double slashes") - # This looks like a noop - but it may have the side effect - # that urlparser be run (actually not - unauth ensures we - # have an urlParseResult object) - url.scheme + arr = list(self.url_parsed) + ## quoting path + arr[2] = quote(unquote(url.path)) + ## sensible defaults + if not arr[0]: + arr[0] = 'https' + if arr[1] and not ':' in arr[1]: + if arr[0] == 'https': + portpart = ':443' + elif arr[0] == 'http': + portpart = ':80' + else: + portpart = '' + arr[1] += portpart # make sure to delete the string version - url.url_raw = None + url.url_raw = urlunparse(arr) + url.url_parsed = None return url diff --git a/caldav/objects.py b/caldav/objects.py index 6ff33a6e..a051f796 100644 --- a/caldav/objects.py +++ b/caldav/objects.py @@ -117,8 +117,8 @@ def children(self, type=None): # And why is the strip_trailing_slash-method needed? # The collection URL should always end with a slash according # to RFC 2518, section 5.2. - if (self.url.strip_trailing_slash() != - self.url.join(path).strip_trailing_slash()): + if (self.url.canonical().strip_trailing_slash() != + self.url.join(path).canonical().strip_trailing_slash()): c.append((self.url.join(path), resource_types, resource_name)) diff --git a/tests/test_caldav_unit.py b/tests/test_caldav_unit.py index 44a5dd9b..edc1ee92 100644 --- a/tests/test_caldav_unit.py +++ b/tests/test_caldav_unit.py @@ -769,6 +769,9 @@ def testURL(self): assert_equal(URL('http://www.example.com:8080/bar/').strip_trailing_slash(), URL('http://www.example.com:8080/bar')) assert_equal(URL('http://www.example.com:8080/bar/').strip_trailing_slash(), URL('http://www.example.com:8080/bar').strip_trailing_slash()) + # 9) canonical + assert_equal(URL('https://www.example.com:443/b%61r/').canonical(), URL('//www.example.com/bar/').canonical()) + def testFilters(self): filter = \ cdav.Filter().append(