From e277301c2c96915ba1408d57a866bc65e51de95a Mon Sep 17 00:00:00 2001 From: Claude Paroz Date: Fri, 21 Dec 2012 10:01:03 +0100 Subject: [PATCH] Fixed #19387 -- Preserved SafeData status in contrib.messages Thanks Anton Baklanov for the report and the patch. --- django/contrib/messages/storage/cookie.py | 9 +++++++-- django/contrib/messages/tests/cookie.py | 19 +++++++++++++++++++ django/contrib/messages/tests/session.py | 14 ++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/django/contrib/messages/storage/cookie.py b/django/contrib/messages/storage/cookie.py index 6b5b016234a..619c69249e3 100644 --- a/django/contrib/messages/storage/cookie.py +++ b/django/contrib/messages/storage/cookie.py @@ -4,6 +4,7 @@ from django.conf import settings from django.contrib.messages.storage.base import BaseStorage, Message from django.http import SimpleCookie from django.utils.crypto import salted_hmac, constant_time_compare +from django.utils.safestring import SafeData, mark_safe from django.utils import six @@ -15,7 +16,9 @@ class MessageEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, Message): - message = [self.message_key, obj.level, obj.message] + # Using 0/1 here instead of False/True to produce more compact json + is_safedata = 1 if isinstance(obj.message, SafeData) else 0 + message = [self.message_key, is_safedata, obj.level, obj.message] if obj.extra_tags: message.append(obj.extra_tags) return message @@ -30,7 +33,9 @@ class MessageDecoder(json.JSONDecoder): def process_messages(self, obj): if isinstance(obj, list) and obj: if obj[0] == MessageEncoder.message_key: - return Message(*obj[1:]) + if obj[1]: + obj[3] = mark_safe(obj[3]) + return Message(*obj[2:]) return [self.process_messages(item) for item in obj] if isinstance(obj, dict): return dict([(key, self.process_messages(value)) diff --git a/django/contrib/messages/tests/cookie.py b/django/contrib/messages/tests/cookie.py index e0668ab6045..77e4ece0910 100644 --- a/django/contrib/messages/tests/cookie.py +++ b/django/contrib/messages/tests/cookie.py @@ -6,6 +6,7 @@ from django.contrib.messages.storage.cookie import (CookieStorage, MessageEncoder, MessageDecoder) from django.contrib.messages.storage.base import Message from django.test.utils import override_settings +from django.utils.safestring import SafeData, mark_safe def set_cookie_data(storage, messages, invalid=False, encode_empty=False): @@ -132,3 +133,21 @@ class CookieTest(BaseTest): value = encoder.encode(messages) decoded_messages = json.loads(value, cls=MessageDecoder) self.assertEqual(messages, decoded_messages) + + def test_safedata(self): + """ + Tests that a message containing SafeData is keeping its safe status when + retrieved from the message storage. + """ + def encode_decode(data): + message = Message(constants.DEBUG, data) + encoded = storage._encode(message) + decoded = storage._decode(encoded) + return decoded.message + + storage = self.get_storage() + + self.assertIsInstance( + encode_decode(mark_safe("Hello Django!")), SafeData) + self.assertNotIsInstance( + encode_decode("Hello Django!"), SafeData) diff --git a/django/contrib/messages/tests/session.py b/django/contrib/messages/tests/session.py index 741f53136de..e162f49fc28 100644 --- a/django/contrib/messages/tests/session.py +++ b/django/contrib/messages/tests/session.py @@ -1,5 +1,8 @@ +from django.contrib.messages import constants from django.contrib.messages.tests.base import BaseTest +from django.contrib.messages.storage.base import Message from django.contrib.messages.storage.session import SessionStorage +from django.utils.safestring import SafeData, mark_safe def set_session_data(storage, messages): @@ -36,3 +39,14 @@ class SessionTest(BaseTest): set_session_data(storage, example_messages) # Test that the message actually contains what we expect. self.assertEqual(list(storage), example_messages) + + def test_safedata(self): + """ + Tests that a message containing SafeData is keeping its safe status when + retrieved from the message storage. + """ + storage = self.get_storage() + + message = Message(constants.DEBUG, mark_safe("Hello Django!")) + set_session_data(storage, [message]) + self.assertIsInstance(list(storage)[0].message, SafeData)