diff --git a/zerver/lib/markdown/__init__.py b/zerver/lib/markdown/__init__.py index 4b2436b3cf..d3246f9e4c 100644 --- a/zerver/lib/markdown/__init__.py +++ b/zerver/lib/markdown/__init__.py @@ -25,7 +25,7 @@ from typing import ( Union, ) from typing.re import Match, Pattern -from urllib.parse import urlsplit +from urllib.parse import urlencode, urlsplit from xml.etree import ElementTree as etree from xml.etree.ElementTree import Element, SubElement @@ -587,12 +587,8 @@ class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor): # We strip leading '/' from relative URLs here to ensure # consistency in what gets passed to /thumbnail url = url.lstrip('/') - img.set("src", "/thumbnail?url={}&size=thumbnail".format( - urllib.parse.quote(url, safe=''), - )) - img.set('data-src-fullsize', "/thumbnail?url={}&size=full".format( - urllib.parse.quote(url, safe=''), - )) + img.set("src", "/thumbnail?" + urlencode({"url": url, "size": "thumbnail"})) + img.set('data-src-fullsize', "/thumbnail?" + urlencode({"url": url, "size": "full"})) else: img.set("src", url) diff --git a/zerver/tests/test_signup.py b/zerver/tests/test_signup.py index c9fedecd79..e21285edf7 100644 --- a/zerver/tests/test_signup.py +++ b/zerver/tests/test_signup.py @@ -5,6 +5,7 @@ import time import urllib from typing import Any, List, Optional, Sequence from unittest.mock import MagicMock, patch +from urllib.parse import urlencode import orjson from django.conf import settings @@ -1643,8 +1644,8 @@ so we didn't send them an invitation. We did send invitations to everyone else!" url = "/accounts/register/" response = self.client_post(url, {"key": registration_key, "from_confirmation": 1, "full_name": "alice"}) self.assertEqual(response.status_code, 302) - self.assertEqual(response.url, reverse('login') + '?email=' + - urllib.parse.quote_plus(email)) + self.assertEqual(response.url, reverse('login') + '?' + + urlencode({"email": email})) class InvitationsTestCase(InviteUserBase): def test_do_get_user_invites(self) -> None: diff --git a/zerver/views/registration.py b/zerver/views/registration.py index da84c9ddf2..f55d73026e 100644 --- a/zerver/views/registration.py +++ b/zerver/views/registration.py @@ -2,6 +2,7 @@ import logging import smtplib import urllib from typing import Dict, List, Optional +from urllib.parse import urlencode import pytz from django.conf import settings @@ -163,7 +164,7 @@ def accounts_register(request: HttpRequest) -> HttpResponse: validate_email_not_already_in_realm(realm, email) except ValidationError: view_url = reverse('login') - redirect_url = add_query_to_redirect_url(view_url, 'email=' + urllib.parse.quote_plus(email)) + redirect_url = add_query_to_redirect_url(view_url, urlencode({"email": email})) return HttpResponseRedirect(redirect_url) name_validated = False @@ -352,7 +353,7 @@ def accounts_register(request: HttpRequest) -> HttpResponse: # particularly matter, because the registration form # is hidden for most users. view_url = reverse('login') - query = 'email=' + urllib.parse.quote_plus(email) + query = urlencode({"email": email}) redirect_url = add_query_to_redirect_url(view_url, query) return HttpResponseRedirect(redirect_url) elif not realm_creation: @@ -485,8 +486,7 @@ def send_confirm_registration_email(email: str, activation_url: str, language: s def redirect_to_email_login_url(email: str) -> HttpResponseRedirect: login_url = reverse('login') - email = urllib.parse.quote_plus(email) - redirect_url = add_query_to_redirect_url(login_url, 'already_registered=' + email) + redirect_url = add_query_to_redirect_url(login_url, urlencode({"already_registered": email})) return HttpResponseRedirect(redirect_url) def create_realm(request: HttpRequest, creation_key: Optional[str]=None) -> HttpResponse: