Django

Code

Ticket #1375 (new)

Opened 2 years ago

Last modified 5 months ago

Escape primary_key values in admin interface

Reported by: Malcolm Tredinnick <malcolm@pointy-stick.com> Assigned to: yk4ever
Component: Admin interface Version:
Keywords: string primary_key underscore Cc:
Triage Stage: Accepted Has patch: 1
Needs documentation: 0 Needs tests: 0
Patch needs improvement: 0

Description

There is a subtle trap when using the primary_key attribute in a model: if it turns out to be a fully qualified URL (including a schema), then you cannot edit the object through the admin interface. I do not think it is worth trying to work around this in the model API, but we should document the problem.

The attached patch is for model-api.txt to do just that.

Attachments

model-api.diff (0.9 kB) - added by Malcolm Tredinnick <malcolm@pointy-stick.com> on 02/18/06 18:12:33.
Point out potential problem in use of primary_key attribute on fields.
main.diff (2.6 kB) - added by Malcolm Tredinnick <malcolm@pointy-stick.com> on 02/18/06 20:13:09.
Escape object idents in admin editing URLs
main2.diff (2.7 kB) - added by Malcolm Tredinnick <malcolm@pointy-stick.com> on 02/19/06 01:12:58.
The previous main.diff was broken for the common (default) case. :-( Sorry about that.
add_some_characters_to_quote.diff (426 bytes) - added by Eftarjin on 09/15/07 11:06:40.
string_pkey_in_admin.patch (7.2 kB) - added by yk4ever on 12/06/07 01:38:57.
Improved patch

Change History

02/18/06 18:12:33 changed by Malcolm Tredinnick <malcolm@pointy-stick.com>

  • attachment model-api.diff added.

Point out potential problem in use of primary_key attribute on fields.

02/18/06 18:24:44 changed by lukeplant

I imagine with the right use of url encoding it should be possible to fix this bug. Could you indicate the particular sticking points? (no pun on your e-mail address intended!)

02/18/06 19:21:48 changed by Malcolm Tredinnick <malcolm@pointy-stick.com>

  • owner changed from jacob to adrian.
  • component changed from Documentation to Admin interface.

Looking deeper, the problem might be worse than I indicated above. I am working from the source in the magic-removal branch here, but the trunk is similar. Let me lay out my reasoning here and somebody can check if I'm missing something.

In contrib/admin/view/main.py, in ChangeList?.url_for_result(), the URL is constructed using the value of the primary key, as I mentioned above. This is a relative URL (<a href="pk_value">). Since we are already under (typically) http://site.name/admin/model/.

My claim (now) is that not just fully-qualified URLs cause problems here -- which they do -- but also any primary key values that have forward slashes in them. To wit, admin/urls.py tries to match a URL looking like '([/]+)/([/]+)/$' after the 'admin/' portion of the URL (trunk uses named groups in the reg-exp, but the intent is the same). Note that only two slashes are permitted here. So if the primary key value contains a slash (or, for fun, looks like "foo/delete"), things are going to wrong.

I think you are correct, Luke, and we need to fix this, rather than just document the problem, since it's a bit larger than I originally thought. Probably the solution is to escape the first colon and all slashes in any primary key value and then un-escape them in contrib.admin.views.main.change_list().

I'll work on a patch to that effect shortly. This is no longer just a documentation problem, so changing the component back to Admin interface.

02/18/06 20:13:09 changed by Malcolm Tredinnick <malcolm@pointy-stick.com>

  • attachment main.diff added.

Escape object idents in admin editing URLs

02/18/06 20:17:25 changed by Malcolm Tredinnick <malcolm@pointy-stick.com>

The latest patch (main.diff -- against the current magic-removal branch) is an attempt to fix the problem in the code. I could not use urllib.quote and urllib.unquote, since they seemed to be automatically unquoted by the browser at the wrong time (plus, the status bar in Firefox, at least, would display the unquoted string, which was misleading). So I wrote something similar to the urllib functions that only quotes the annoying characters in our case and uses underscores instead of percentage signs as the quote marker.

The test for this is to create a model that has a CharField?(maxlength = 100, primary_key = True) and then use values like "http://www.djangoproject.com/" and "foo/bar/delete" in the field. Without this patch, both of those would lead to fields that couldn't be edited via admin.

02/19/06 01:12:58 changed by Malcolm Tredinnick <malcolm@pointy-stick.com>

  • attachment main2.diff added.

The previous main.diff was broken for the common (default) case. :-( Sorry about that.

02/24/06 05:32:00 changed by Malcolm Tredinnick <malcolm@pointy-stick.com>

  • type changed from enhancement to defect.
  • summary changed from Clarification for model API documentation to Escape primary_key values in admin interface.

02/27/06 02:19:37 changed by Malcolm Tredinnick <malcolm@pointy-stick.com>

  • summary changed from Escape primary_key values in admin interface to [patch] Escape primary_key values in admin interface.

02/27/06 15:36:53 changed by jacob

  • status changed from new to closed.
  • resolution set to fixed.

(In [2418]) Fixed #1375: primary_key values with "bad" characters are now escaped in the admin; thanks, Malcom Tredinnick

02/27/06 15:38:15 changed by jacob

For timeline-readers: this fix is on magic-removal

05/06/07 10:50:55 changed by Eftarjin

  • status changed from closed to reopened.
  • needs_better_patch set to 1.
  • resolution deleted.

Some characters are still problematic.

Possible solution : in django.contrib.admin.views.main.quote, change

if c in ':/_':

to

if c in ':/_#?@=&':

and adapt the docstring.

06/05/07 02:08:18 changed by MichaelRadziej <mir@noris.de>

  • summary changed from [patch] Escape primary_key values in admin interface to Escape primary_key values in admin interface.
  • needs_tests set to 1.
  • stage changed from Unreviewed to Accepted.

Looks reasonable ... obviously, the testcases should be extended to also cover the new problematic cases.

09/15/07 09:19:12 changed by Fredrik Lundh <fredrik@pythonware.com>

Patch, please!

09/15/07 11:06:40 changed by Eftarjin

  • attachment add_some_characters_to_quote.diff added.

09/15/07 11:07:25 changed by Eftarjin

Here is the patch (add_some_characters_to_quote.diff)

(follow-up: ↓ 13 ) 09/15/07 11:15:48 changed by Fredrik Lundh <fredrik@pythonware.com>

  • needs_better_patch deleted.

That was the easy part ;-)

I think it needs some tests as well; do you have time to look into this? If not, I can ask around on the django sprint IRC.

(in reply to: ↑ 12 ) 09/15/07 16:02:39 changed by anonymous

Replying to Fredrik Lundh <fredrik@pythonware.com>:

I think it needs some tests as well; do you have time to look into this? If not, I can ask around on the django sprint IRC.

I've been using this patch with full URLs (of various websites) as primary keys (ie : part of the object's URL in the admin) since my first comment (2007-05-06) without any problem (quoting more is safer and I can't see a case where it's harmful). Aside from this, I don't know what test to do ...

09/29/07 12:53:55 changed by anonymous

  • needs_better_patch set to 1.

It seems using '_' in primary keys still does not work. I have primary key: NC_000023.9 and this appears correctly in URL (though I thought it was to be quoted), however I get the following error from admin: sequencerecord object with primary key u'NC\x000023.9' does not exist. It looks like its the fault of the unquote method but I am not familiar enough with the internals of django to be sure.

09/29/07 13:31:44 changed by jflatow@northwestern.edu

It actually looks like the problem is that the primary_key gets unquoted but never quoted. In the case of my ids I am lucky enough to happen to have more than 2 digits following the underscore and so django sees '_00' and replaces with chr(int('00',16)) which of course is '\x00'. I imagine the tests didn't try this pathological case (or even any cases?, since it seems the quote method is never actually called, so I'm not sure how this could have been fixed at all!).

12/06/07 01:38:57 changed by yk4ever

  • attachment string_pkey_in_admin.patch added.

Improved patch

12/06/07 01:43:03 changed by yk4ever

  • keywords set to string primary_key underscore.
  • needs_better_patch deleted.
  • status changed from reopened to new.
  • owner changed from nobody to Fredrik Lundh.

Actually, it can be fixed pretty easily. It's a shame this bug is still alive! I'm offering improved patch which: - fixes underscore ("_") handling in primary keys; - performs correct escaping ("%" and other characters are now handled correctly); - fixes links in "recent actions" and "delete object" pages; - changes custom escaping symbol from "_" to "." (since "_" is more likely to be encountered in primary keys); - moves escaping functions to admin.models (to avoid circular importing).

I tested it with different weird characters in primary keys, it seems to handle all situations correctly. Hope it is accepted soon.

12/06/07 01:46:48 changed by yk4ever

  • owner changed from Fredrik Lundh to yk4ever.
  • needs_tests deleted.
  • stage changed from Accepted to Ready for checkin.

12/06/07 02:19:30 changed by mtredinnick

  • stage changed from Ready for checkin to Accepted.

Please don't mark your own patches as ready for checkin. Let a triager review them first.

I haven't spent too long reviewing this patch, but at first glance, I don't like moving the URL quoting to the models module, since it's 100% view related. I realise why you did it, but there's possibly an alternative solution (like the standard technique of importing the "views" module, rather than something from within the views module namespace, into models).

Moving back to accepted until somebody can go over this in detail.


Add/Change #1375 (Escape primary_key values in admin interface)




Change Properties
Action