diff --git a/VERSION b/VERSION index 30ff6dd0..bd8fb753 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.1.1 (2012-10-17 09:13:38) dev +Version 2.1.1 (2012-10-17 12:04:15) dev diff --git a/gluon/globals.py b/gluon/globals.py index 18b78321..d601b65e 100644 --- a/gluon/globals.py +++ b/gluon/globals.py @@ -470,6 +470,7 @@ class Session(Storage): check_client=False, cookie_key=None, cookie_expires=None, + compression_level=None ): """ separate can be separate=lambda(session_name): session_name[-2:] @@ -507,8 +508,9 @@ class Session(Storage): if cookie_key: response.session_storage_type = 'cookie' response.session_cookie_key = cookie_key + response.session_cookie_compression_level = compression_level if session_cookie_data: - data = secure_loads(session_cookie_data,cookie_key) + data = secure_loads(session_cookie_data,cookie_key,compression_level=compression_level) if data: self.update(data) # else if we are supposed to use file based sessions @@ -652,7 +654,7 @@ class Session(Storage): def _try_store_in_cookie(self, request, response): if response.session_storage_type!='cookie': return False name = response.session_data_name - value = secure_dumps(dict(self),response.session_cookie_key) + value = secure_dumps(dict(self),response.session_cookie_key, compression_level=response.session_cookie_compression_level) expires = response.session_cookie_expires rcookies = response.cookies rcookies.pop(name,None) diff --git a/gluon/utils.py b/gluon/utils.py index a160cc6e..ecc957bc 100644 --- a/gluon/utils.py +++ b/gluon/utils.py @@ -23,6 +23,7 @@ import logging import socket import cPickle import base64 +import zlib try: from Crypto.Cipher import AES @@ -105,17 +106,19 @@ DIGEST_ALG_BY_SIZE = { def pad(s,n=32,padchar='.'): return s + (32 - len(s) % 32) * padchar -def secure_dumps(data,encryption_key,hash_key=None): +def secure_dumps(data,encryption_key,hash_key=None,compression_level=None): if not hash_key: hash_key = hashlib.sha1(encryption_key).hexdigest() dump = cPickle.dumps(data) + if compression_level: + dump = zlib.compress(dump, compression_level) key = pad(encryption_key[:32]) - cipher = AES.new(key,IV=key) - encrypted_data = base64.b16encode(cipher.encrypt(pad(dump))) + cipher = AES.new(key,IV=key[:16]) + encrypted_data = base64.urlsafe_b64encode(cipher.encrypt(pad(dump))) signature = hmac.new(hash_key,encrypted_data).hexdigest() return signature+':'+encrypted_data -def secure_loads(data,encryption_key,hash_key=None): +def secure_loads(data,encryption_key,hash_key=None, compression_level=None): if not ':' in data: return None if not hash_key: @@ -125,10 +128,12 @@ def secure_loads(data,encryption_key,hash_key=None): if signature!=actual_signature: return None key = pad(encryption_key[:32]) - cipher = AES.new(key,IV=key) + cipher = AES.new(key,IV=key[:16]) try: - data = cipher.decrypt(base64.b16decode(encrypted_data)) + data = cipher.decrypt(base64.urlsafe_b64decode(encrypted_data)) data = data.rstrip(' ') + if compression_level: + data = zlib.decompress(data) return cPickle.loads(data) except (TypeError,cPickle.UnpicklingError): return None