Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed #2986 -- Made the JavaScript code that drives related model ins…

…tance addition in a popup window handle a model representation containing new lines. Also, moved the escapejs functionality yoo django.utils.html so it can be used from Python code. Thanks andrewwatts for the patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@15131 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 0f783b7f4eac037e22875eeeb6dc85c26b2a65f4 1 parent 544ab30
Ramiro Morales ramiro authored
4 django/contrib/admin/options.py
View
@@ -19,7 +19,7 @@
from django.utils.decorators import method_decorator
from django.utils.datastructures import SortedDict
from django.utils.functional import update_wrapper
-from django.utils.html import escape
+from django.utils.html import escape, escapejs
from django.utils.safestring import mark_safe
from django.utils.functional import curry
from django.utils.text import capfirst, get_text_list
@@ -717,7 +717,7 @@ def response_add(self, request, obj, post_url_continue='../%s/'):
if "_popup" in request.POST:
return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, "%s", "%s");</script>' % \
# escape() calls force_unicode.
- (escape(pk_value), escape(obj)))
+ (escape(pk_value), escapejs(obj)))
elif "_addanother" in request.POST:
self.message_user(request, msg + ' ' + (_("You may add another %s below.") % force_unicode(opts.verbose_name)))
return HttpResponseRedirect(request.path)
24 django/template/defaultfilters.py
View
@@ -64,29 +64,10 @@ def capfirst(value):
capfirst.is_safe=True
capfirst = stringfilter(capfirst)
-_base_js_escapes = (
- ('\\', r'\u005C'),
- ('\'', r'\u0027'),
- ('"', r'\u0022'),
- ('>', r'\u003E'),
- ('<', r'\u003C'),
- ('&', r'\u0026'),
- ('=', r'\u003D'),
- ('-', r'\u002D'),
- (';', r'\u003B'),
- (u'\u2028', r'\u2028'),
- (u'\u2029', r'\u2029')
-)
-
-# Escape every ASCII character with a value less than 32.
-_js_escapes = (_base_js_escapes +
- tuple([('%c' % z, '\\u%04X' % z) for z in range(32)]))
-
def escapejs(value):
"""Hex encodes characters for use in JavaScript strings."""
- for bad, good in _js_escapes:
- value = value.replace(bad, good)
- return value
+ from django.utils.html import escapejs
+ return escapejs(value)
escapejs = stringfilter(escapejs)
def fix_ampersands(value):
@@ -745,7 +726,6 @@ def timesince(value, arg=None):
def timeuntil(value, arg=None):
"""Formats a date as the time until that date (i.e. "4 days, 6 hours")."""
from django.utils.timesince import timeuntil
- from datetime import datetime
if not value:
return u''
try:
25 django/utils/html.py
View
@@ -34,6 +34,31 @@ def escape(html):
return mark_safe(force_unicode(html).replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;').replace('"', '&quot;').replace("'", '&#39;'))
escape = allow_lazy(escape, unicode)
+_base_js_escapes = (
+ ('\\', r'\u005C'),
+ ('\'', r'\u0027'),
+ ('"', r'\u0022'),
+ ('>', r'\u003E'),
+ ('<', r'\u003C'),
+ ('&', r'\u0026'),
+ ('=', r'\u003D'),
+ ('-', r'\u002D'),
+ (';', r'\u003B'),
+ (u'\u2028', r'\u2028'),
+ (u'\u2029', r'\u2029')
+)
+
+# Escape every ASCII character with a value less than 32.
+_js_escapes = (_base_js_escapes +
+ tuple([('%c' % z, '\\u%04X' % z) for z in range(32)]))
+
+def escapejs(value):
+ """Hex encodes characters for use in JavaScript strings."""
+ for bad, good in _js_escapes:
+ value = mark_safe(force_unicode(value).replace(bad, good))
+ return value
+escapejs = allow_lazy(escapejs, unicode)
+
def conditional_escape(html):
"""
Similar to escape(), except that it doesn't operate on pre-escaped strings.
16 tests/regressiontests/admin_views/tests.py
View
@@ -107,6 +107,22 @@ def testBasicAddPost(self):
response = self.client.post('/test_admin/%s/admin_views/section/add/' % self.urlbit, post_data)
self.assertEqual(response.status_code, 302) # redirect somewhere
+ def testPopupAddPost(self):
+ """
+ Ensure http response from a popup is properly escaped.
+ """
+ post_data = {
+ '_popup': u'1',
+ 'title': u'title with a new\nline',
+ 'content': u'some content',
+ 'date_0': u'2010-09-10',
+ 'date_1': u'14:55:39',
+ }
+ response = self.client.post('/test_admin/%s/admin_views/article/add/' % self.urlbit, post_data)
+ self.failUnlessEqual(response.status_code, 200)
+ self.assertContains(response, 'dismissAddAnotherPopup')
+ self.assertContains(response, 'title with a new\u000Aline')
+
# Post data for edit inline
inline_post_data = {
"name": u"Test section",
12 tests/regressiontests/utils/html.py
View
@@ -109,3 +109,15 @@ def test_fix_ampersands(self):
)
for value, output in items:
self.check_output(f, value, output)
+
+ def test_escapejs(self):
+ f = html.escapejs
+ items = (
+ (u'"double quotes" and \'single quotes\'', u'\\u0022double quotes\\u0022 and \\u0027single quotes\\u0027'),
+ (ur'\ : backslashes, too', u'\\u005C : backslashes, too'),
+ (u'and lots of whitespace: \r\n\t\v\f\b', u'and lots of whitespace: \\u000D\\u000A\\u0009\\u000B\\u000C\\u0008'),
+ (ur'<script>and this</script>', u'\\u003Cscript\\u003Eand this\\u003C/script\\u003E'),
+ (u'paragraph separator:\u2029and line separator:\u2028', u'paragraph separator:\\u2029and line separator:\\u2028'),
+ )
+ for value, output in items:
+ self.check_output(f, value, output)
Please sign in to comment.
Something went wrong with that request. Please try again.