Code

Ticket #1375: main2.diff

File main2.diff, 2.7 KB (added by Malcolm Tredinnick <malcolm@…>, 8 years ago)

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

Line 
1Index: contrib/admin/views/main.py
2===================================================================
3--- contrib/admin/views/main.py (revision 2360)
4+++ contrib/admin/views/main.py (working copy)
5@@ -41,6 +41,43 @@
6 class IncorrectLookupParameters(Exception):
7     pass
8 
9+def quote(s):
10+    """
11+    Ensure that primary key values do not confuse the admin URLs by escaping
12+    any '/', '_' and ':' characters. Similar to urllib.quote, except that the
13+       quoting is slightly different so that it doesn't get autoamtically
14+       unquoted by the web browser.
15+    """
16+    if type(s) != type(''):
17+        return s
18+    res = list(s)
19+    for i in range(len(res)):
20+        c = res[i]
21+        if c in ':/_':
22+            res[i] = '_%02X' % ord(c)
23+    return ''.join(res)
24+
25+def unquote(s):
26+    """
27+    Undo the effects of quote(). Based heavily on urllib.unquote().
28+    """
29+    mychr = chr
30+    myatoi = int
31+    list = s.split('_')
32+    res = [list[0]]
33+    myappend = res.append
34+    del list[0]
35+    for item in list:
36+        if item[1:2]:
37+            try:
38+                myappend(mychr(myatoi(item[:2], 16))
39+                     + item[2:])
40+            except ValueError:
41+                myappend('_' + item)
42+        else:
43+            myappend('_' + item)
44+    return "".join(res)
45+
46 def get_javascript_imports(opts, auto_populated_fields, field_sets):
47 # Put in any necessary JavaScript imports.
48     js = ['js/core.js', 'js/admin/RelatedObjectLookups.js']
49@@ -250,6 +287,7 @@
50 
51 def change_stage(request, app_label, model_name, object_id):
52     model = models.get_model(app_label, model_name)
53+    object_id = unquote(object_id)
54     if model is None:
55         raise Http404, "App %r, model %r, not found" % (app_label, model_name)
56     opts = model._meta
57@@ -433,6 +471,7 @@
58 def delete_stage(request, app_label, model_name, object_id):
59     import sets
60     model = models.get_model(app_label, model_name)
61+    object_id = unquote(object_id)
62     if model is None:
63         raise Http404, "App %r, model %r, not found" % (app_label, model_name)
64     opts = model._meta
65@@ -465,6 +504,7 @@
66 
67 def history(request, app_label, model_name, object_id):
68     model = models.get_model(app_label, model_name)
69+    object_id = unquote(object_id)
70     if model is None:
71         raise Http404, "App %r, model %r, not found" % (app_label, model_name)
72     action_list = LogEntry.objects.filter(object_id=object_id,
73@@ -655,7 +695,7 @@
74         return qs
75 
76     def url_for_result(self, result):
77-        return "%s/" % getattr(result, self.pk_attname)
78+        return "%s/" % quote(getattr(result, self.pk_attname))
79 
80 def change_list(request, app_label, model_name):
81     model = models.get_model(app_label, model_name)