# -*- 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()
