#30043: AdminURLFieldWidget incorrectly unquotes URLs e.g. containing %2F
-------------------------------------+-------------------------------------
     Reporter:  Brenton Partridge    |                    Owner:  Brady
         Type:  Bug                  |                   Status:  assigned
    Component:  contrib.admin        |                  Version:  master
     Severity:  Normal               |               Resolution:
     Keywords:  admin, urlfield,     |             Triage Stage:  Accepted
  smart_urlquote, url, quote         |
    Has patch:  1                    |      Needs documentation:  0
  Needs tests:  1                    |  Patch needs improvement:  1
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------

Comment (by Carlton Gibson):

 Right, yes, that was it. The issue is that there's no (easy) way to know
 if a string has already been quoted, which re-reading is exactly what
 Florian said above:

 > The main issue here is that we do not know if the URL supplied is
 already sufficiently quoted or not.

 I think the use-case will be where you have a URL, with a quoted-URL as a
 query parameter (say). As understand it, you do want `%2F`s in there, so
 you'd use `quote_plus`, as used by default by `urlencode`:

 {{{
 >>> from urllib.parse import quote, quote_plus, urlencode
 >>> quote('https://djangoproject.com/')
 'https%3A//djangoproject.com/'
 >>> quote_plus('https://djangoproject.com/testing/')
 'https%3A%2F%2Fdjangoproject.com%2Ftesting%2F'
 >>> urlencode({'q':'https://djangoproject.com/testing/'})
 'q=https%3A%2F%2Fdjangoproject.com%2Ftesting%2F'
 }}}

 But, if it's part of the path, and not the query parameters, you don't
 want `quote_plus`. Taking Florian's example:

 {{{
 >>> quote('/äöü')
 '/%C3%A4%C3%B6%C3%BC'
 >>> quote_plus('/äöü')
 '%2F%C3%A4%C3%B6%C3%BC'
 }}}

 The 2nd, as part of the path, would be wrong.

 The good thing about `iri_to_uri()` is that it won't ''double-percent-
 escape'', whereas `quote()` keeps on changing the input (re-quoting) each
 time, so if a URL does **look** quoted you can pass it through and get the
 right results. **But edge cases...???**

 `smart_urlquote()`, perhaps why it has the name,
 
[https://github.com/django/django/blob/315357ad25a6590e7f4564ec2e56a22132b09001/django/utils/html.py#L224-L233
 **already** handles the the query string parameters separately, using
 `urlencode`]. (And looking at the issue linked in the comment there, that
 was the exact discussion from #22267...) — **SO** short of concrete test
 cases (i.e. full example URLs where the behaviour is wrong) I can't see
 that we can progress.

 On that basis, I'm going to close as `needsinfo`. Happy to re-open if full
 test cases come up.

 Thank you for your effort and time looking into this Brady! Welcome
 aboard! 🎉

-- 
Ticket URL: <https://code.djangoproject.com/ticket/30043#comment:9>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/068.5286721087945093c035a69be6c72d3d%40djangoproject.com.

Reply via email to