~ubuntu-branches/ubuntu/saucy/python-django/saucy-updates

« back to all changes in this revision

Viewing changes to django/contrib/sessions/backends/file.py

  • Committer: Package Import Robot
  • Author(s): Luke Faraone, Jakub Wilk, Luke Faraone
  • Date: 2013-05-09 15:10:47 UTC
  • mfrom: (1.1.21) (4.4.27 sid)
  • Revision ID: package-import@ubuntu.com-20130509151047-aqv8d71oj9wvcv8c
Tags: 1.5.1-2
[ Jakub Wilk ]
* Use canonical URIs for Vcs-* fields.

[ Luke Faraone ]
* Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import datetime
1
2
import errno
2
3
import os
3
4
import tempfile
4
5
 
5
6
from django.conf import settings
6
 
from django.contrib.sessions.backends.base import SessionBase, CreateError
 
7
from django.contrib.sessions.backends.base import SessionBase, CreateError, VALID_KEY_CHARS
7
8
from django.core.exceptions import SuspiciousOperation, ImproperlyConfigured
8
 
 
 
9
from django.utils import timezone
9
10
 
10
11
class SessionStore(SessionBase):
11
12
    """
12
13
    Implements a file based session store.
13
14
    """
14
15
    def __init__(self, session_key=None):
15
 
        self.storage_path = getattr(settings, "SESSION_FILE_PATH", None)
16
 
        if not self.storage_path:
17
 
            self.storage_path = tempfile.gettempdir()
18
 
 
19
 
        # Make sure the storage path is valid.
20
 
        if not os.path.isdir(self.storage_path):
21
 
            raise ImproperlyConfigured(
22
 
                "The session storage path %r doesn't exist. Please set your"
23
 
                " SESSION_FILE_PATH setting to an existing directory in which"
24
 
                " Django can store session data." % self.storage_path)
25
 
 
 
16
        self.storage_path = type(self)._get_storage_path()
26
17
        self.file_prefix = settings.SESSION_COOKIE_NAME
27
18
        super(SessionStore, self).__init__(session_key)
28
19
 
29
 
    VALID_KEY_CHARS = set("abcdef0123456789")
 
20
    @classmethod
 
21
    def _get_storage_path(cls):
 
22
        try:
 
23
            return cls._storage_path
 
24
        except AttributeError:
 
25
            storage_path = getattr(settings, "SESSION_FILE_PATH", None)
 
26
            if not storage_path:
 
27
                storage_path = tempfile.gettempdir()
 
28
 
 
29
            # Make sure the storage path is valid.
 
30
            if not os.path.isdir(storage_path):
 
31
                raise ImproperlyConfigured(
 
32
                    "The session storage path %r doesn't exist. Please set your"
 
33
                    " SESSION_FILE_PATH setting to an existing directory in which"
 
34
                    " Django can store session data." % storage_path)
 
35
 
 
36
            cls._storage_path = storage_path
 
37
            return storage_path
30
38
 
31
39
    def _key_to_file(self, session_key=None):
32
40
        """
38
46
        # Make sure we're not vulnerable to directory traversal. Session keys
39
47
        # should always be md5s, so they should never contain directory
40
48
        # components.
41
 
        if not set(session_key).issubset(self.VALID_KEY_CHARS):
 
49
        if not set(session_key).issubset(set(VALID_KEY_CHARS)):
42
50
            raise SuspiciousOperation(
43
51
                "Invalid characters in session key")
44
52
 
45
53
        return os.path.join(self.storage_path, self.file_prefix + session_key)
46
54
 
 
55
    def _last_modification(self):
 
56
        """
 
57
        Return the modification time of the file storing the session's content.
 
58
        """
 
59
        modification = os.stat(self._key_to_file()).st_mtime
 
60
        if settings.USE_TZ:
 
61
            modification = datetime.datetime.utcfromtimestamp(modification)
 
62
            modification = modification.replace(tzinfo=timezone.utc)
 
63
        else:
 
64
            modification = datetime.datetime.fromtimestamp(modification)
 
65
        return modification
 
66
 
47
67
    def load(self):
48
68
        session_data = {}
49
69
        try:
50
 
            session_file = open(self._key_to_file(), "rb")
51
 
            try:
 
70
            with open(self._key_to_file(), "rb") as session_file:
52
71
                file_data = session_file.read()
53
 
                # Don't fail if there is no data in the session file.
54
 
                # We may have opened the empty placeholder file.
55
 
                if file_data:
56
 
                    try:
57
 
                        session_data = self.decode(file_data)
58
 
                    except (EOFError, SuspiciousOperation):
59
 
                        self.create()
60
 
            finally:
61
 
                session_file.close()
 
72
            # Don't fail if there is no data in the session file.
 
73
            # We may have opened the empty placeholder file.
 
74
            if file_data:
 
75
                try:
 
76
                    session_data = self.decode(file_data)
 
77
                except (EOFError, SuspiciousOperation):
 
78
                    self.create()
 
79
 
 
80
                # Remove expired sessions.
 
81
                expiry_age = self.get_expiry_age(
 
82
                    modification=self._last_modification(),
 
83
                    expiry=session_data.get('_session_expiry'))
 
84
                if expiry_age < 0:
 
85
                    session_data = {}
 
86
                    self.delete()
 
87
                    self.create()
62
88
        except IOError:
63
89
            self.create()
64
90
        return session_data
90
116
            fd = os.open(session_file_name, flags)
91
117
            os.close(fd)
92
118
 
93
 
        except OSError, e:
 
119
        except OSError as e:
94
120
            if must_create and e.errno == errno.EEXIST:
95
121
                raise CreateError
96
122
            raise
118
144
            renamed = False
119
145
            try:
120
146
                try:
121
 
                    os.write(output_file_fd, self.encode(session_data))
 
147
                    os.write(output_file_fd, self.encode(session_data).encode())
122
148
                finally:
123
149
                    os.close(output_file_fd)
124
150
                os.rename(output_file_name, session_file_name)
145
171
 
146
172
    def clean(self):
147
173
        pass
 
174
 
 
175
    @classmethod
 
176
    def clear_expired(cls):
 
177
        storage_path = cls._get_storage_path()
 
178
        file_prefix = settings.SESSION_COOKIE_NAME
 
179
 
 
180
        for session_file in os.listdir(storage_path):
 
181
            if not session_file.startswith(file_prefix):
 
182
                continue
 
183
            session_key = session_file[len(file_prefix):]
 
184
            session = cls(session_key)
 
185
            # When an expired session is loaded, its file is removed, and a
 
186
            # new file is immediately created. Prevent this by disabling
 
187
            # the create() method.
 
188
            session.create = lambda: None
 
189
            session.load()