Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #1375: primary_key values with "bad" characters are now escaped…

… in the admin; thanks, Malcom Tredinnick

git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@2418 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit bc8547aa9dc4710c8fee5d5ee93b395abdb9ff62 1 parent e9e1820
Jacob Kaplan-Moss authored

Showing 1 changed file with 41 additions and 1 deletion. Show diff stats Hide diff stats

  1. 42  django/contrib/admin/views/main.py
42  django/contrib/admin/views/main.py
@@ -42,6 +42,43 @@
42 42
 class IncorrectLookupParameters(Exception):
43 43
     pass
44 44
 
  45
+def quote(s):
  46
+    """
  47
+    Ensure that primary key values do not confuse the admin URLs by escaping
  48
+    any '/', '_' and ':' characters. Similar to urllib.quote, except that the
  49
+	quoting is slightly different so that it doesn't get autoamtically
  50
+	unquoted by the web browser.
  51
+    """
  52
+    if type(s) != type(''):
  53
+        return s
  54
+    res = list(s)
  55
+    for i in range(len(res)):
  56
+        c = res[i]
  57
+        if c in ':/_':
  58
+            res[i] = '_%02X' % ord(c)
  59
+    return ''.join(res)
  60
+
  61
+def unquote(s):
  62
+    """
  63
+    Undo the effects of quote(). Based heavily on urllib.unquote().
  64
+    """
  65
+    mychr = chr
  66
+    myatoi = int
  67
+    list = s.split('_')
  68
+    res = [list[0]]
  69
+    myappend = res.append
  70
+    del list[0]
  71
+    for item in list:
  72
+        if item[1:2]:
  73
+            try:
  74
+                myappend(mychr(myatoi(item[:2], 16))
  75
+                     + item[2:])
  76
+            except ValueError:
  77
+                myappend('_' + item)
  78
+        else:
  79
+            myappend('_' + item)
  80
+    return "".join(res)
  81
+
45 82
 def get_javascript_imports(opts, auto_populated_fields, field_sets):
46 83
 # Put in any necessary JavaScript imports.
47 84
     js = ['js/core.js', 'js/admin/RelatedObjectLookups.js']
@@ -252,6 +289,7 @@ def add_stage(request, app_label, model_name, show_delete=False, form_url='', po
252 289
 
253 290
 def change_stage(request, app_label, model_name, object_id):
254 291
     model = models.get_model(app_label, model_name)
  292
+    object_id = unquote(object_id)
255 293
     if model is None:
256 294
         raise Http404, "App %r, model %r, not found" % (app_label, model_name)
257 295
     opts = model._meta
@@ -435,6 +473,7 @@ def _get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current
435 473
 def delete_stage(request, app_label, model_name, object_id):
436 474
     import sets
437 475
     model = models.get_model(app_label, model_name)
  476
+    object_id = unquote(object_id)
438 477
     if model is None:
439 478
         raise Http404, "App %r, model %r, not found" % (app_label, model_name)
440 479
     opts = model._meta
@@ -470,6 +509,7 @@ def delete_stage(request, app_label, model_name, object_id):
470 509
 
471 510
 def history(request, app_label, model_name, object_id):
472 511
     model = models.get_model(app_label, model_name)
  512
+    object_id = unquote(object_id)
473 513
     if model is None:
474 514
         raise Http404, "App %r, model %r, not found" % (app_label, model_name)
475 515
     action_list = LogEntry.objects.filter(object_id=object_id,
@@ -663,7 +703,7 @@ def get_query_set(self):
663 703
         return qs
664 704
 
665 705
     def url_for_result(self, result):
666  
-        return "%s/" % getattr(result, self.pk_attname)
  706
+        return "%s/" % quote(getattr(result, self.pk_attname))
667 707
 
668 708
 def change_list(request, app_label, model_name):
669 709
     model = models.get_model(app_label, model_name)

0 notes on commit bc8547a

Please sign in to comment.
Something went wrong with that request. Please try again.