NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

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))