# -*- Mode: Python; tab-width: 4 -*- # a persistent-session manager based on the cookie standard. # ================ # WORK IN PROGRESS # ================ import md5 import string import time import whrandom # maybe we ought to just use hexify() ? ALPHABET = '0123456789abcdefghijklmnopqrstuv' def radix32 (n): result = [] while n: result.append (ALPHABET [int(n & 037)]) n = n >> 5 result.reverse() return string.join (result, '') # basically an attribute holder class session: pass # for now maybe we should support the 'old' cookie type? class session_manager: def __init__ (self): self.sessions = {} self.random = whrandom.whrandom() seed = id(self) + int(time.time()) self.random.seed (seed & 0xff, (seed >> 8) & 0xff, (seed >> 16) & 0xff) def generate_cookie (self, channel): [path, params, query, fragment] = channel.uri # build a random-as-we-can-make-it session cookie # how about 'IP:PORT:header:str(id(channel)):str(time.time())' yak_dung = '%s%d%s%s%s' % ( channel.addr[0], channel.addr[1], channel.header, str(id(channel)), str(time.time()) ) m = md5.md5() m.update (yak_dung) cookie = m.digest() # pick a random 8 bytes from it. pos = self.random.randint (0,7) cookie = cookie[pos:pos+8] # turn it into a number n = 0L for i in range(8): n = n + ord(cookie[i]) n = n << 8 # radix32-it # we've got 64 bits, but we toss the # last 4 because radix-32 uses 5 bits at a time # (64/5 = 12) return radix32 (n)[:12] def new_session (self, channel): cookie = self.generate_cookie (channel) s = session() # what default information should be stored in the # cookie? s.host = channel.addr[0] self.sessions[cookie] = s return cookie def __getattr__ (self, cookie): return self.sessions[cookie] def __delattr__ (self, cookie): del self.sessions[cookie] session_manager = session_manager()