Skip to content

Commit 8552f92

Browse files
committed
Fixed URL encoding & decoding issues.
1 parent 52ba6ac commit 8552f92

File tree

3 files changed

+73
-2
lines changed

3 files changed

+73
-2
lines changed

nyawc/helpers/URLHelper.py

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ def append_with_data(url, data):
8686
query = OrderedDict(parse_qsl(url_parts[4], keep_blank_values=True))
8787
query.update(data)
8888

89-
url_parts[4] = urlencode(query)
89+
url_parts[4] = URLHelper.query_dict_to_string(query)
9090

9191
return urlunparse(url_parts)
9292

@@ -233,7 +233,7 @@ def get_ordered_params(url):
233233
if url not in URLHelper.__cache:
234234
URLHelper.__cache[url] = urlparse(url)
235235

236-
params = dict(parse_qsl(URLHelper.__cache[url].query, keep_blank_values=True))
236+
params = URLHelper.query_string_to_dict(URLHelper.__cache[url].query)
237237

238238
return OrderedDict(sorted(params.items()))
239239

@@ -250,3 +250,54 @@ def remove_hash(url):
250250
"""
251251

252252
return url.split("#")[0]
253+
254+
@staticmethod
255+
def query_dict_to_string(query):
256+
"""Convert an OrderedDict to a query string.
257+
258+
Args:
259+
query (obj): The key value object with query params.
260+
261+
Returns:
262+
str: The query string.
263+
264+
Note:
265+
This method does the same as urllib.parse.urlencode except
266+
that it doesn't actually encode the values.
267+
268+
"""
269+
270+
query_params = []
271+
272+
for key, value in query.items():
273+
query_params.append(key + "=" + value)
274+
275+
return "&".join(query_params)
276+
277+
@staticmethod
278+
def query_string_to_dict(query):
279+
"""Convert a string to a query dict.
280+
281+
Args:
282+
query (str): The query string.
283+
284+
Returns:
285+
obj: The key value object with query params.
286+
287+
Note:
288+
This method does the same as urllib.parse.parse_qsl except
289+
that it doesn't actually decode the values.
290+
291+
"""
292+
293+
query_params = {}
294+
295+
for key_value in query.split("&"):
296+
key_value_pair = key_value.split("=", 1)
297+
298+
key = key_value_pair[0] if len(key_value_pair) >= 1 else ""
299+
value = key_value_pair[1] if len(key_value_pair) == 2 else ""
300+
301+
query_params[key] = value
302+
303+
return query_params

test/test_helpers_url_helper.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,3 +142,12 @@ def test_get_ordered_params(self):
142142
val2 = URLHelper.get_ordered_params("http://sub.domain.ltd?c=c&b=b&a=a&d=d")
143143

144144
self.assertEqual(val1, val2)
145+
146+
def test_append_with_data_encoded_and_decoded(self):
147+
"""Make sure values do not get decoded or encoded."""
148+
149+
val1 = URLHelper.append_with_data("http://example.tld/", {"val": "{{aaaa}}"})
150+
val2 = URLHelper.append_with_data("http://example.tld/", {"val": "%7B%7Baaaa%7D%7D"})
151+
152+
self.assertEqual(val1, "http://example.tld/?val={{aaaa}}")
153+
self.assertEqual(val2, "http://example.tld/?val=%7B%7Baaaa%7D%7D")

test/test_queue.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,14 @@ def test_hash_different_query_order(self):
5656
queue.add_request(Request("https://www.example.ltd?a=a&b=b&c=c"))
5757

5858
self.assertEqual(queue.count_total, 1)
59+
60+
61+
def test_hash_different_encoded_and_decoded_values(self):
62+
"""Ensure encoded and decoded values have a different hash."""
63+
64+
queue = Queue(Options())
65+
66+
queue.add_request(Request("http://example.ltd?val={{aaaa}}"))
67+
queue.add_request(Request("http://example.ltd?val=%7B%7Baaaa%7D%7D"))
68+
69+
self.assertEqual(queue.count_total, 2)

0 commit comments

Comments
 (0)