sessions.py (6465B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\lib\werkzeug\contrib\sessions.py 2 import re 3 import os 4 import sys 5 import tempfile 6 from os import path 7 from time import time 8 from random import random 9 try: 10 from hashlib import sha1 11 except ImportError: 12 from sha import new as sha1 13 14 from cPickle import dump, load, HIGHEST_PROTOCOL 15 from werkzeug import ClosingIterator, dump_cookie, parse_cookie, CallbackDict 16 from werkzeug.posixemulation import rename 17 _sha1_re = re.compile('^[a-f0-9]{40}$') 18 19 def _urandom(): 20 if hasattr(os, 'urandom'): 21 return os.urandom(30) 22 return random() 23 24 25 def generate_key(salt = None): 26 return sha1('%s%s%s' % (salt, time(), _urandom())).hexdigest() 27 28 29 class ModificationTrackingDict(CallbackDict): 30 __slots__ = ('modified',) 31 32 def __init__(self, *args, **kwargs): 33 34 def on_update(self): 35 self.modified = True 36 37 self.modified = False 38 CallbackDict.__init__(self, on_update=on_update) 39 dict.update(self, *args, **kwargs) 40 41 def copy(self): 42 missing = object() 43 result = object.__new__(self.__class__) 44 for name in self.__slots__: 45 val = getattr(self, name, missing) 46 if val is not missing: 47 setattr(result, name, val) 48 49 return result 50 51 def __copy__(self): 52 return self.copy() 53 54 55 class Session(ModificationTrackingDict): 56 __slots__ = ModificationTrackingDict.__slots__ + ('sid', 'new') 57 58 def __init__(self, data, sid, new = False): 59 ModificationTrackingDict.__init__(self, data) 60 self.sid = sid 61 self.new = new 62 63 def __repr__(self): 64 return '<%s %s%s>' % (self.__class__.__name__, dict.__repr__(self), self.should_save and '*' or '') 65 66 @property 67 def should_save(self): 68 return self.modified 69 70 71 class SessionStore(object): 72 73 def __init__(self, session_class = None): 74 if session_class is None: 75 session_class = Session 76 self.session_class = session_class 77 78 def is_valid_key(self, key): 79 return _sha1_re.match(key) is not None 80 81 def generate_key(self, salt = None): 82 return generate_key(salt) 83 84 def new(self): 85 return self.session_class({}, self.generate_key(), True) 86 87 def save(self, session): 88 pass 89 90 def save_if_modified(self, session): 91 if session.should_save: 92 self.save(session) 93 94 def delete(self, session): 95 pass 96 97 def get(self, sid): 98 return self.session_class({}, sid, True) 99 100 101 _fs_transaction_suffix = '.__wz_sess' 102 103 class FilesystemSessionStore(SessionStore): 104 105 def __init__(self, path = None, filename_template = 'werkzeug_%s.sess', session_class = None, renew_missing = False, mode = 420): 106 SessionStore.__init__(self, session_class) 107 if path is None: 108 path = tempfile.gettempdir() 109 self.path = path 110 if isinstance(filename_template, unicode): 111 filename_template = filename_template.encode(sys.getfilesystemencoding() or 'utf-8') 112 self.filename_template = filename_template 113 self.renew_missing = renew_missing 114 self.mode = mode 115 116 def get_session_filename(self, sid): 117 if isinstance(sid, unicode): 118 sid = sid.encode(sys.getfilesystemencoding() or 'utf-8') 119 return path.join(self.path, self.filename_template % sid) 120 121 def save(self, session): 122 fn = self.get_session_filename(session.sid) 123 fd, tmp = tempfile.mkstemp(suffix=_fs_transaction_suffix, dir=self.path) 124 f = os.fdopen(fd, 'wb') 125 try: 126 dump(dict(session), f, HIGHEST_PROTOCOL) 127 finally: 128 f.close() 129 130 try: 131 rename(tmp, fn) 132 os.chmod(fn, self.mode) 133 except (IOError, OSError): 134 pass 135 136 def delete(self, session): 137 fn = self.get_session_filename(session.sid) 138 try: 139 os.unlink(fn) 140 except OSError: 141 pass 142 143 def get(self, sid): 144 if not self.is_valid_key(sid): 145 return self.new() 146 try: 147 f = open(self.get_session_filename(sid), 'rb') 148 except IOError: 149 if self.renew_missing: 150 return self.new() 151 data = {} 152 else: 153 try: 154 data = load(f) 155 except Exception: 156 data = {} 157 finally: 158 f.close() 159 160 return self.session_class(data, sid, False) 161 162 def list(self): 163 before, after = self.filename_template.split('%s', 1) 164 filename_re = re.compile('%s(.{5,})%s$' % (re.escape(before), re.escape(after))) 165 result = [] 166 for filename in os.listdir(self.path): 167 if filename.endswith(_fs_transaction_suffix): 168 continue 169 match = filename_re.match(filename) 170 if match is not None: 171 result.append(match.group(1)) 172 173 return result 174 175 176 class SessionMiddleware(object): 177 178 def __init__(self, app, store, cookie_name = 'session_id', cookie_age = None, cookie_expires = None, cookie_path = '/', cookie_domain = None, cookie_secure = None, cookie_httponly = False, environ_key = 'werkzeug.session'): 179 self.app = app 180 self.store = store 181 self.cookie_name = cookie_name 182 self.cookie_age = cookie_age 183 self.cookie_expires = cookie_expires 184 self.cookie_path = cookie_path 185 self.cookie_domain = cookie_domain 186 self.cookie_secure = cookie_secure 187 self.cookie_httponly = cookie_httponly 188 self.environ_key = environ_key 189 190 def __call__(self, environ, start_response): 191 cookie = parse_cookie(environ.get('HTTP_COOKIE', '')) 192 sid = cookie.get(self.cookie_name, None) 193 if sid is None: 194 session = self.store.new() 195 else: 196 session = self.store.get(sid) 197 environ[self.environ_key] = session 198 199 def injecting_start_response(status, headers, exc_info = None): 200 if session.should_save: 201 self.store.save(session) 202 headers.append(('Set-Cookie', dump_cookie(self.cookie_name, session.sid, self.cookie_age, self.cookie_expires, self.cookie_path, self.cookie_domain, self.cookie_secure, self.cookie_httponly))) 203 return start_response(status, headers, exc_info) 204 205 return ClosingIterator(self.app(environ, injecting_start_response), lambda : self.store.save_if_modified(session))