summaryrefslogtreecommitdiff
path: root/lib/python2.7/site-packages/django/contrib/messages/storage
diff options
context:
space:
mode:
authorttt2017-05-13 00:29:47 +0530
committerttt2017-05-13 00:29:47 +0530
commitabf599be33b383a6a5baf9493093b2126a622ac8 (patch)
tree4c5ab6e0d935d5e65fabcf0258e4a00dd20a5afa /lib/python2.7/site-packages/django/contrib/messages/storage
downloadSBHS-2018-Rpi-abf599be33b383a6a5baf9493093b2126a622ac8.tar.gz
SBHS-2018-Rpi-abf599be33b383a6a5baf9493093b2126a622ac8.tar.bz2
SBHS-2018-Rpi-abf599be33b383a6a5baf9493093b2126a622ac8.zip
added all server files
Diffstat (limited to 'lib/python2.7/site-packages/django/contrib/messages/storage')
-rw-r--r--lib/python2.7/site-packages/django/contrib/messages/storage/__init__.py8
-rw-r--r--lib/python2.7/site-packages/django/contrib/messages/storage/base.py184
-rw-r--r--lib/python2.7/site-packages/django/contrib/messages/storage/cookie.py158
-rw-r--r--lib/python2.7/site-packages/django/contrib/messages/storage/fallback.py54
-rw-r--r--lib/python2.7/site-packages/django/contrib/messages/storage/session.py46
5 files changed, 450 insertions, 0 deletions
diff --git a/lib/python2.7/site-packages/django/contrib/messages/storage/__init__.py b/lib/python2.7/site-packages/django/contrib/messages/storage/__init__.py
new file mode 100644
index 0000000..9a09aff
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/messages/storage/__init__.py
@@ -0,0 +1,8 @@
+from django.conf import settings
+from django.utils.module_loading import import_by_path as get_storage
+
+
+# Callable with the same interface as the storage classes i.e. accepts a
+# 'request' object. It is wrapped in a lambda to stop 'settings' being used at
+# the module level
+default_storage = lambda request: get_storage(settings.MESSAGE_STORAGE)(request)
diff --git a/lib/python2.7/site-packages/django/contrib/messages/storage/base.py b/lib/python2.7/site-packages/django/contrib/messages/storage/base.py
new file mode 100644
index 0000000..7fe8a07
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/messages/storage/base.py
@@ -0,0 +1,184 @@
+from __future__ import unicode_literals
+
+from django.conf import settings
+from django.utils.encoding import force_text, python_2_unicode_compatible
+from django.contrib.messages import constants, utils
+
+
+LEVEL_TAGS = utils.get_level_tags()
+
+
+@python_2_unicode_compatible
+class Message(object):
+ """
+ Represents an actual message that can be stored in any of the supported
+ storage classes (typically session- or cookie-based) and rendered in a view
+ or template.
+ """
+
+ def __init__(self, level, message, extra_tags=None):
+ self.level = int(level)
+ self.message = message
+ self.extra_tags = extra_tags
+
+ def _prepare(self):
+ """
+ Prepares the message for serialization by forcing the ``message``
+ and ``extra_tags`` to unicode in case they are lazy translations.
+
+ Known "safe" types (None, int, etc.) are not converted (see Django's
+ ``force_text`` implementation for details).
+ """
+ self.message = force_text(self.message, strings_only=True)
+ self.extra_tags = force_text(self.extra_tags, strings_only=True)
+
+ def __eq__(self, other):
+ return isinstance(other, Message) and self.level == other.level and \
+ self.message == other.message
+
+ def __str__(self):
+ return force_text(self.message)
+
+ def _get_tags(self):
+ label_tag = force_text(LEVEL_TAGS.get(self.level, ''),
+ strings_only=True)
+ extra_tags = force_text(self.extra_tags, strings_only=True)
+ if extra_tags and label_tag:
+ return ' '.join([extra_tags, label_tag])
+ elif extra_tags:
+ return extra_tags
+ elif label_tag:
+ return label_tag
+ return ''
+ tags = property(_get_tags)
+
+
+class BaseStorage(object):
+ """
+ This is the base backend for temporary message storage.
+
+ This is not a complete class; to be a usable storage backend, it must be
+ subclassed and the two methods ``_get`` and ``_store`` overridden.
+ """
+
+ def __init__(self, request, *args, **kwargs):
+ self.request = request
+ self._queued_messages = []
+ self.used = False
+ self.added_new = False
+ super(BaseStorage, self).__init__(*args, **kwargs)
+
+ def __len__(self):
+ return len(self._loaded_messages) + len(self._queued_messages)
+
+ def __iter__(self):
+ self.used = True
+ if self._queued_messages:
+ self._loaded_messages.extend(self._queued_messages)
+ self._queued_messages = []
+ return iter(self._loaded_messages)
+
+ def __contains__(self, item):
+ return item in self._loaded_messages or item in self._queued_messages
+
+ @property
+ def _loaded_messages(self):
+ """
+ Returns a list of loaded messages, retrieving them first if they have
+ not been loaded yet.
+ """
+ if not hasattr(self, '_loaded_data'):
+ messages, all_retrieved = self._get()
+ self._loaded_data = messages or []
+ return self._loaded_data
+
+ def _get(self, *args, **kwargs):
+ """
+ Retrieves a list of stored messages. Returns a tuple of the messages
+ and a flag indicating whether or not all the messages originally
+ intended to be stored in this storage were, in fact, stored and
+ retrieved; e.g., ``(messages, all_retrieved)``.
+
+ **This method must be implemented by a subclass.**
+
+ If it is possible to tell if the backend was not used (as opposed to
+ just containing no messages) then ``None`` should be returned in
+ place of ``messages``.
+ """
+ raise NotImplementedError()
+
+ def _store(self, messages, response, *args, **kwargs):
+ """
+ Stores a list of messages, returning a list of any messages which could
+ not be stored.
+
+ One type of object must be able to be stored, ``Message``.
+
+ **This method must be implemented by a subclass.**
+ """
+ raise NotImplementedError()
+
+ def _prepare_messages(self, messages):
+ """
+ Prepares a list of messages for storage.
+ """
+ for message in messages:
+ message._prepare()
+
+ def update(self, response):
+ """
+ Stores all unread messages.
+
+ If the backend has yet to be iterated, previously stored messages will
+ be stored again. Otherwise, only messages added after the last
+ iteration will be stored.
+ """
+ self._prepare_messages(self._queued_messages)
+ if self.used:
+ return self._store(self._queued_messages, response)
+ elif self.added_new:
+ messages = self._loaded_messages + self._queued_messages
+ return self._store(messages, response)
+
+ def add(self, level, message, extra_tags=''):
+ """
+ Queues a message to be stored.
+
+ The message is only queued if it contained something and its level is
+ not less than the recording level (``self.level``).
+ """
+ if not message:
+ return
+ # Check that the message level is not less than the recording level.
+ level = int(level)
+ if level < self.level:
+ return
+ # Add the message.
+ self.added_new = True
+ message = Message(level, message, extra_tags=extra_tags)
+ self._queued_messages.append(message)
+
+ def _get_level(self):
+ """
+ Returns the minimum recorded level.
+
+ The default level is the ``MESSAGE_LEVEL`` setting. If this is
+ not found, the ``INFO`` level is used.
+ """
+ if not hasattr(self, '_level'):
+ self._level = getattr(settings, 'MESSAGE_LEVEL', constants.INFO)
+ return self._level
+
+ def _set_level(self, value=None):
+ """
+ Sets a custom minimum recorded level.
+
+ If set to ``None``, the default level will be used (see the
+ ``_get_level`` method).
+ """
+ if value is None and hasattr(self, '_level'):
+ del self._level
+ else:
+ self._level = int(value)
+
+ level = property(_get_level, _set_level, _set_level)
diff --git a/lib/python2.7/site-packages/django/contrib/messages/storage/cookie.py b/lib/python2.7/site-packages/django/contrib/messages/storage/cookie.py
new file mode 100644
index 0000000..619c692
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/messages/storage/cookie.py
@@ -0,0 +1,158 @@
+import json
+
+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
+
+
+class MessageEncoder(json.JSONEncoder):
+ """
+ Compactly serializes instances of the ``Message`` class as JSON.
+ """
+ message_key = '__json_message'
+
+ def default(self, obj):
+ if isinstance(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
+ return super(MessageEncoder, self).default(obj)
+
+
+class MessageDecoder(json.JSONDecoder):
+ """
+ Decodes JSON that includes serialized ``Message`` instances.
+ """
+
+ def process_messages(self, obj):
+ if isinstance(obj, list) and obj:
+ if obj[0] == MessageEncoder.message_key:
+ 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))
+ for key, value in six.iteritems(obj)])
+ return obj
+
+ def decode(self, s, **kwargs):
+ decoded = super(MessageDecoder, self).decode(s, **kwargs)
+ return self.process_messages(decoded)
+
+class CookieStorage(BaseStorage):
+ """
+ Stores messages in a cookie.
+ """
+ cookie_name = 'messages'
+ # uwsgi's default configuration enforces a maximum size of 4kb for all the
+ # HTTP headers. In order to leave some room for other cookies and headers,
+ # restrict the session cookie to 1/2 of 4kb. See #18781.
+ max_cookie_size = 2048
+ not_finished = '__messagesnotfinished__'
+
+ def _get(self, *args, **kwargs):
+ """
+ Retrieves a list of messages from the messages cookie. If the
+ not_finished sentinel value is found at the end of the message list,
+ remove it and return a result indicating that not all messages were
+ retrieved by this storage.
+ """
+ data = self.request.COOKIES.get(self.cookie_name)
+ messages = self._decode(data)
+ all_retrieved = not (messages and messages[-1] == self.not_finished)
+ if messages and not all_retrieved:
+ # remove the sentinel value
+ messages.pop()
+ return messages, all_retrieved
+
+ def _update_cookie(self, encoded_data, response):
+ """
+ Either sets the cookie with the encoded data if there is any data to
+ store, or deletes the cookie.
+ """
+ if encoded_data:
+ response.set_cookie(self.cookie_name, encoded_data,
+ domain=settings.SESSION_COOKIE_DOMAIN)
+ else:
+ response.delete_cookie(self.cookie_name,
+ domain=settings.SESSION_COOKIE_DOMAIN)
+
+ def _store(self, messages, response, remove_oldest=True, *args, **kwargs):
+ """
+ Stores the messages to a cookie, returning a list of any messages which
+ could not be stored.
+
+ If the encoded data is larger than ``max_cookie_size``, removes
+ messages until the data fits (these are the messages which are
+ returned), and add the not_finished sentinel value to indicate as much.
+ """
+ unstored_messages = []
+ encoded_data = self._encode(messages)
+ if self.max_cookie_size:
+ # data is going to be stored eventually by SimpleCookie, which
+ # adds it's own overhead, which we must account for.
+ cookie = SimpleCookie() # create outside the loop
+ def stored_length(val):
+ return len(cookie.value_encode(val)[1])
+
+ while encoded_data and stored_length(encoded_data) > self.max_cookie_size:
+ if remove_oldest:
+ unstored_messages.append(messages.pop(0))
+ else:
+ unstored_messages.insert(0, messages.pop())
+ encoded_data = self._encode(messages + [self.not_finished],
+ encode_empty=unstored_messages)
+ self._update_cookie(encoded_data, response)
+ return unstored_messages
+
+ def _hash(self, value):
+ """
+ Creates an HMAC/SHA1 hash based on the value and the project setting's
+ SECRET_KEY, modified to make it unique for the present purpose.
+ """
+ key_salt = 'django.contrib.messages'
+ return salted_hmac(key_salt, value).hexdigest()
+
+ def _encode(self, messages, encode_empty=False):
+ """
+ Returns an encoded version of the messages list which can be stored as
+ plain text.
+
+ Since the data will be retrieved from the client-side, the encoded data
+ also contains a hash to ensure that the data was not tampered with.
+ """
+ if messages or encode_empty:
+ encoder = MessageEncoder(separators=(',', ':'))
+ value = encoder.encode(messages)
+ return '%s$%s' % (self._hash(value), value)
+
+ def _decode(self, data):
+ """
+ Safely decodes a encoded text stream back into a list of messages.
+
+ If the encoded text stream contained an invalid hash or was in an
+ invalid format, ``None`` is returned.
+ """
+ if not data:
+ return None
+ bits = data.split('$', 1)
+ if len(bits) == 2:
+ hash, value = bits
+ if constant_time_compare(hash, self._hash(value)):
+ try:
+ # If we get here (and the JSON decode works), everything is
+ # good. In any other case, drop back and return None.
+ return json.loads(value, cls=MessageDecoder)
+ except ValueError:
+ pass
+ # Mark the data as used (so it gets removed) since something was wrong
+ # with the data.
+ self.used = True
+ return None
diff --git a/lib/python2.7/site-packages/django/contrib/messages/storage/fallback.py b/lib/python2.7/site-packages/django/contrib/messages/storage/fallback.py
new file mode 100644
index 0000000..6c35343
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/messages/storage/fallback.py
@@ -0,0 +1,54 @@
+from django.contrib.messages.storage.base import BaseStorage
+from django.contrib.messages.storage.cookie import CookieStorage
+from django.contrib.messages.storage.session import SessionStorage
+
+class FallbackStorage(BaseStorage):
+ """
+ Tries to store all messages in the first backend, storing any unstored
+ messages in each subsequent backend backend.
+ """
+ storage_classes = (CookieStorage, SessionStorage)
+
+ def __init__(self, *args, **kwargs):
+ super(FallbackStorage, self).__init__(*args, **kwargs)
+ self.storages = [storage_class(*args, **kwargs)
+ for storage_class in self.storage_classes]
+ self._used_storages = set()
+
+ def _get(self, *args, **kwargs):
+ """
+ Gets a single list of messages from all storage backends.
+ """
+ all_messages = []
+ for storage in self.storages:
+ messages, all_retrieved = storage._get()
+ # If the backend hasn't been used, no more retrieval is necessary.
+ if messages is None:
+ break
+ if messages:
+ self._used_storages.add(storage)
+ all_messages.extend(messages)
+ # If this storage class contained all the messages, no further
+ # retrieval is necessary
+ if all_retrieved:
+ break
+ return all_messages, all_retrieved
+
+ def _store(self, messages, response, *args, **kwargs):
+ """
+ Stores the messages, returning any unstored messages after trying all
+ backends.
+
+ For each storage backend, any messages not stored are passed on to the
+ next backend.
+ """
+ for storage in self.storages:
+ if messages:
+ messages = storage._store(messages, response,
+ remove_oldest=False)
+ # Even if there are no more messages, continue iterating to ensure
+ # storages which contained messages are flushed.
+ elif storage in self._used_storages:
+ storage._store([], response)
+ self._used_storages.remove(storage)
+ return messages
diff --git a/lib/python2.7/site-packages/django/contrib/messages/storage/session.py b/lib/python2.7/site-packages/django/contrib/messages/storage/session.py
new file mode 100644
index 0000000..c3e293c
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/messages/storage/session.py
@@ -0,0 +1,46 @@
+import json
+
+from django.contrib.messages.storage.base import BaseStorage
+from django.contrib.messages.storage.cookie import MessageEncoder, MessageDecoder
+from django.utils import six
+
+
+class SessionStorage(BaseStorage):
+ """
+ Stores messages in the session (that is, django.contrib.sessions).
+ """
+ session_key = '_messages'
+
+ def __init__(self, request, *args, **kwargs):
+ assert hasattr(request, 'session'), "The session-based temporary "\
+ "message storage requires session middleware to be installed, "\
+ "and come before the message middleware in the "\
+ "MIDDLEWARE_CLASSES list."
+ super(SessionStorage, self).__init__(request, *args, **kwargs)
+
+ def _get(self, *args, **kwargs):
+ """
+ Retrieves a list of messages from the request's session. This storage
+ always stores everything it is given, so return True for the
+ all_retrieved flag.
+ """
+ return self.deserialize_messages(self.request.session.get(self.session_key)), True
+
+ def _store(self, messages, response, *args, **kwargs):
+ """
+ Stores a list of messages to the request's session.
+ """
+ if messages:
+ self.request.session[self.session_key] = self.serialize_messages(messages)
+ else:
+ self.request.session.pop(self.session_key, None)
+ return []
+
+ def serialize_messages(self, messages):
+ encoder = MessageEncoder(separators=(',', ':'))
+ return encoder.encode(messages)
+
+ def deserialize_messages(self, data):
+ if data and isinstance(data, six.string_types):
+ return json.loads(data, cls=MessageDecoder)
+ return data