示例#1
0
    def test_0_redis_session(self):
        """ Basic redis read-write """
        db = self.db
        response = self.current.response
        Field = db.Field
        db.define_table(
            self.tname,
            Field('locked', 'boolean', default=False),
            Field('client_ip', length=64),
            Field('created_datetime',
                  'datetime',
                  default=datetime.now().isoformat()),
            Field('modified_datetime', 'datetime'),
            Field('unique_key', length=64),
            Field('session_data', 'blob'),
        )
        table = db[self.tname]
        unique_key = web2py_uuid()
        dd = dict(locked=0,
                  client_ip=response.session_client,
                  modified_datetime=datetime.now().isoformat(),
                  unique_key=unique_key,
                  session_data=pickle.dumps({
                      'test': 123,
                      'me': 112312312
                  }, pickle.HIGHEST_PROTOCOL))
        record_id = table.insert(**dd)
        data_from_db = db(table.id == record_id).select()[0]
        self.assertDictEqual(Storage(dd), data_from_db, 'get inserted dict')

        dd['locked'] = 1
        table._db(table.id == record_id).update(**dd)
        data_from_db = db(table.id == record_id).select()[0]
        self.assertDictEqual(Storage(dd), data_from_db,
                             'get the updated value')
示例#2
0
 def _try_store_in_file(self, request, response):
     try:
         if (not response.session_id or not response.session_filename
                 or self._forget or self._unchanged(response)):
             # self.clear_session_cookies()
             return False
         else:
             if response.session_new or not response.session_file:
                 # Tests if the session sub-folder exists, if not, create it
                 session_folder = os.path.dirname(response.session_filename)
                 if not os.path.exists(session_folder):
                     os.mkdir(session_folder)
                 response.session_file = recfile.open(
                     response.session_filename, 'wb')
                 portalocker.lock(response.session_file,
                                  portalocker.LOCK_EX)
                 response.session_locked = True
             if response.session_file:
                 session_pickled = response.session_pickled or pickle.dumps(
                     self, pickle.HIGHEST_PROTOCOL)
                 response.session_file.write(session_pickled)
                 response.session_file.truncate()
             return True
     finally:
         self._close(response)
         self.save_session_id_cookie()
示例#3
0
 def _try_store_in_file(self, request, response):
     try:
         if (not response.session_id or
             not response.session_filename or
             self._forget
                 or self._unchanged(response)):
             # self.clear_session_cookies()
             return False
         else:
             if response.session_new or not response.session_file:
                 # Tests if the session sub-folder exists, if not, create it
                 session_folder = os.path.dirname(response.session_filename)
                 if not os.path.exists(session_folder):
                     os.mkdir(session_folder)
                 response.session_file = recfile.open(response.session_filename, 'wb')
                 portalocker.lock(response.session_file, portalocker.LOCK_EX)
                 response.session_locked = True
             if response.session_file:
                 session_pickled = response.session_pickled or pickle.dumps(self, pickle.HIGHEST_PROTOCOL)
                 response.session_file.write(session_pickled)
                 response.session_file.truncate()
             return True
     finally:
         self._close(response)
         self.save_session_id_cookie()
示例#4
0
def represent(obj):
    """Returns a string representing the given object's value, which should allow the
    code below to determine whether the object changes over time.
    """
    try:
        return pickle.dumps(obj, pickle.HIGHEST_PROTOCOL)
    except:
        return repr(obj)
示例#5
0
def represent(obj):
    """Returns a string representing the given object's value, which should allow the
    code below to determine whether the object changes over time.
    """
    try:
        return pickle.dumps(obj, pickle.HIGHEST_PROTOCOL)
    except:
        return repr(obj)
示例#6
0
 def testSerialization(self):
     from gluon._compat import pickle
     db = DAL(check_reserved=['all'])
     db.define_table('t_a', Field('f_a'))
     db.t_a.insert(f_a='test')
     a = db(db.t_a.id > 0).select(cacheable=True)
     s = pickle.dumps(a)
     b = pickle.loads(s)
     self.assertEqual(a.db, b.db)
     db.t_a.drop()
     db.close()
示例#7
0
def secure_dumps(data, encryption_key, hash_key=None, compression_level=None):
    dump = pickle.dumps(data, pickle.HIGHEST_PROTOCOL)
    if compression_level:
        dump = zlib.compress(dump, compression_level)
    encryption_key = to_bytes(encryption_key)
    if not hash_key:
        hash_key = hashlib.sha256(encryption_key).digest()
    cipher, IV = AES_new(pad(encryption_key)[:32])
    encrypted_data = base64.urlsafe_b64encode(IV + AES_enc(cipher, pad(dump)))
    signature = to_bytes(hmac.new(to_bytes(hash_key), encrypted_data, hashlib.sha256).hexdigest())
    return b"hmac256:" + signature + b":" + encrypted_data
示例#8
0
 def testSerialization(self):
     from gluon._compat import pickle
     db = DAL(check_reserved=['all'])
     db.define_table('t_a', Field('f_a'))
     db.t_a.insert(f_a='test')
     a = db(db.t_a.id > 0).select(cacheable=True)
     s = pickle.dumps(a)
     b = pickle.loads(s)
     self.assertEqual(a.db, b.db)
     db.t_a.drop()
     db.close()
示例#9
0
def secure_dumps(data, encryption_key, hash_key=None, compression_level=None):
    dump = pickle.dumps(data, pickle.HIGHEST_PROTOCOL)
    if compression_level:
        dump = zlib.compress(dump, compression_level)
    encryption_key = to_bytes(encryption_key)
    if not hash_key:
        hash_key = hashlib.sha256(encryption_key).digest()
    cipher, IV = AES_new(pad(encryption_key)[:32])
    encrypted_data = base64.urlsafe_b64encode(IV + AES_enc(cipher, pad(dump)))
    signature = to_bytes(hmac.new(to_bytes(hash_key), encrypted_data, hashlib.sha256).hexdigest())
    return b'hmac256:' + signature + b':' + encrypted_data
示例#10
0
 def _unchanged(self, response):
     if response.session_new:
         internal = ['_last_timestamp', '_secure', '_start_timestamp']
         for item in self.keys():
             if item not in internal:
                 return False
         return True
     session_pickled = pickle.dumps(self, pickle.HIGHEST_PROTOCOL)
     response.session_pickled = session_pickled
     session_hash = hashlib.md5(session_pickled).hexdigest()
     return response.session_hash == session_hash
示例#11
0
 def _unchanged(self, response):
     if response.session_new:
         internal = ['_last_timestamp', '_secure', '_start_timestamp']
         for item in self.keys():
             if item not in internal:
                 return False
         return True
     session_pickled = pickle.dumps(self, pickle.HIGHEST_PROTOCOL)
     response.session_pickled = session_pickled
     session_hash = hashlib.md5(session_pickled).hexdigest()
     return response.session_hash == session_hash
示例#12
0
文件: utils.py 项目: Iqrar99/web2py
def secure_dumps(data, encryption_key, hash_key=None, compression_level=None):
    encryption_key = to_bytes(encryption_key)
    if not hash_key:
        hash_key = sha1(encryption_key).hexdigest()
    dump = pickle.dumps(data, pickle.HIGHEST_PROTOCOL)
    if compression_level:
        dump = zlib.compress(dump, compression_level)
    key = pad(encryption_key)[:32]
    cipher, IV = AES_new(key)
    encrypted_data = base64.urlsafe_b64encode(IV + cipher.encrypt(pad(dump)))
    signature = to_bytes(hmac.new(to_bytes(hash_key), encrypted_data).hexdigest())
    return signature + b':' + encrypted_data
示例#13
0
def secure_dumps_deprecated(data, encryption_key, hash_key=None, compression_level=None):
    encryption_key = to_bytes(encryption_key)
    if not hash_key:
        hash_key = sha1(encryption_key).hexdigest()
    dump = pickle.dumps(data, pickle.HIGHEST_PROTOCOL)
    if compression_level:
        dump = zlib.compress(dump, compression_level)
    key = __pad_deprecated(encryption_key)[:32]
    cipher, IV = AES_new(key)
    encrypted_data = base64.urlsafe_b64encode(IV + AES_enc(cipher, pad(dump)))
    signature = to_bytes(hmac.new(to_bytes(hash_key), encrypted_data, hashlib.md5).hexdigest())
    return signature + b':' + encrypted_data
示例#14
0
def secure_dumps_deprecated(data, encryption_key, hash_key=None, compression_level=None):
    """dumps data with a signature (deprecated because of incorrect padding)"""
    encryption_key = to_bytes(encryption_key)
    if not hash_key:
        hash_key = hashlib.sha1(encryption_key).hexdigest()
    dump = pickle.dumps(data, pickle.HIGHEST_PROTOCOL)
    if compression_level:
        dump = zlib.compress(dump, compression_level)
    key = __pad_deprecated(encryption_key)[:32]
    cipher, IV = AES_new(key)
    encrypted_data = base64.urlsafe_b64encode(IV + AES_enc(cipher, pad(dump)))
    signature = to_bytes(hmac.new(to_bytes(hash_key), encrypted_data, hashlib.md5).hexdigest())
    return signature + b':' + encrypted_data
示例#15
0
 def _store_in_db(self, request, ticket_id, ticket_data):
     self.db._adapter.reconnect()
     try:
         table = self._get_table(self.db, self.tablename, request.application)
         table.insert(ticket_id=ticket_id,
                      ticket_data=pickle.dumps(ticket_data, pickle.HIGHEST_PROTOCOL),
                      created_datetime=request.now)
         self.db.commit()
         message = 'In FILE: %(layer)s\n\n%(traceback)s\n'
     except Exception:
         self.db.rollback()
         message =' Unable to store in FILE: %(layer)s\n\n%(traceback)s\n'
     self.db.close()
     logger.error(message % ticket_data)
示例#16
0
 def _store_in_db(self, request, ticket_id, ticket_data):
     self.db._adapter.reconnect()
     try:
         table = self._get_table(self.db, self.tablename, request.application)
         table.insert(ticket_id=ticket_id,
                      ticket_data=pickle.dumps(ticket_data, pickle.HIGHEST_PROTOCOL),
                      created_datetime=request.now)
         self.db.commit()
         message = 'In FILE: %(layer)s\n\n%(traceback)s\n'
     except Exception:
         self.db.rollback()
         message =' Unable to store in FILE: %(layer)s\n\n%(traceback)s\n'
     self.db.close()
     logger.error(message % ticket_data)
示例#17
0
    def set_global(self, name, value):
        """Adds a global, or updates it if it already exists.

        Also removes the global from the list of unpicklable names.

        Args:
            name: the name of the global to remove
            value: any picklable value
        """
        blob = pickle.dumps(value, pickle.HIGHEST_PROTOCOL)

        if name in self.global_names:
            index = self.global_names.index(name)
            self.globals[index] = blob
        else:
            self.global_names.append(name)
            self.globals.append(blob)

        self.remove_unpicklable_name(name)
示例#18
0
    def set_global(self, name, value):
        """Adds a global, or updates it if it already exists.

        Also removes the global from the list of unpicklable names.

        Args:
            name: the name of the global to remove
            value: any picklable value
        """
        blob = pickle.dumps(value, pickle.HIGHEST_PROTOCOL)

        if name in self.global_names:
            index = self.global_names.index(name)
            self.globals[index] = blob
        else:
            self.global_names.append(name)
            self.globals.append(blob)

        self.remove_unpicklable_name(name)
示例#19
0
    def _try_store_in_db(self, request, response):
        # don't save if file-based sessions,
        # no session id, or session being forgotten
        # or no changes to session (Unless the session is new)
        if (not response.session_db_table
                or self._forget
                or (self._unchanged(response) and not response.session_new)):
            if (not response.session_db_table
                    and global_settings.db_sessions is not True
                    and response.session_masterapp in global_settings.db_sessions):
                global_settings.db_sessions.remove(response.session_masterapp)
            # self.clear_session_cookies()
            self.save_session_id_cookie()
            return False

        table = response.session_db_table
        record_id = response.session_db_record_id
        if response.session_new:
            unique_key = web2py_uuid()
        else:
            unique_key = response.session_db_unique_key

        session_pickled = response.session_pickled or pickle.dumps(self, pickle.HIGHEST_PROTOCOL)

        dd = dict(locked=False,
                  client_ip=response.session_client,
                  modified_datetime=request.now,
                  session_data=session_pickled,
                  unique_key=unique_key)
        if record_id:
            if not table._db(table.id == record_id).update(**dd):
                record_id = None
        if not record_id:
            record_id = table.insert(**dd)
            response.session_id = '%s:%s' % (record_id, unique_key)
            response.session_db_unique_key = unique_key
            response.session_db_record_id = record_id

        self.save_session_id_cookie()
        return True
示例#20
0
    def _try_store_in_db(self, request, response):
        # don't save if file-based sessions,
        # no session id, or session being forgotten
        # or no changes to session (Unless the session is new)
        if (not response.session_db_table or self._forget
                or (self._unchanged(response) and not response.session_new)):
            if (not response.session_db_table
                    and global_settings.db_sessions is not True and
                    response.session_masterapp in global_settings.db_sessions):
                global_settings.db_sessions.remove(response.session_masterapp)
            # self.clear_session_cookies()
            self.save_session_id_cookie()
            return False

        table = response.session_db_table
        record_id = response.session_db_record_id
        if response.session_new:
            unique_key = web2py_uuid()
        else:
            unique_key = response.session_db_unique_key

        session_pickled = response.session_pickled or pickle.dumps(
            self, pickle.HIGHEST_PROTOCOL)

        dd = dict(locked=False,
                  client_ip=response.session_client,
                  modified_datetime=request.now,
                  session_data=session_pickled,
                  unique_key=unique_key)
        if record_id:
            if not table._db(table.id == record_id).update(**dd):
                record_id = None
        if not record_id:
            record_id = table.insert(**dd)
            response.session_id = '%s:%s' % (record_id, unique_key)
            response.session_db_unique_key = unique_key
            response.session_db_record_id = record_id

        self.save_session_id_cookie()
        return True
示例#21
0
 def test_pickling(self):
     """ Test storage pickling """
     s = Storage(a=1)
     sd = pickle.dumps(s, pickle.HIGHEST_PROTOCOL)
     news = pickle.loads(sd)
     self.assertEqual(news.a, 1)
示例#22
0
    def connect(self,
                request=None,
                response=None,
                db=None,
                tablename='web2py_session',
                masterapp=None,
                migrate=True,
                separate=None,
                check_client=False,
                cookie_key=None,
                cookie_expires=None,
                compression_level=None):
        """
        Used in models, allows to customize Session handling

        Args:
            request: the request object
            response: the response object
            db: to store/retrieve sessions in db (a table is created)
            tablename(str): table name
            masterapp(str): points to another's app sessions. This enables a
                "SSO" environment among apps
            migrate: passed to the underlying db
            separate: with True, creates a folder with the 2 initials of the
                session id. Can also be a function, e.g. ::

                    separate=lambda(session_name): session_name[-2:]

            check_client: if True, sessions can only come from the same ip
            cookie_key(str): secret for cookie encryption
            cookie_expires: sets the expiration of the cookie
            compression_level(int): 0-9, sets zlib compression on the data
                before the encryption
        """
        from gluon.dal import Field
        request = request or current.request
        response = response or current.response
        masterapp = masterapp or request.application
        cookies = request.cookies

        self._unlock(response)

        response.session_masterapp = masterapp
        response.session_id_name = 'session_id_%s' % masterapp.lower()
        response.session_data_name = 'session_data_%s' % masterapp.lower()
        response.session_cookie_expires = cookie_expires
        response.session_client = str(request.client).replace(':', '.')
        current._session_cookie_key = cookie_key
        response.session_cookie_compression_level = compression_level

        # check if there is a session_id in cookies
        try:
            old_session_id = cookies[response.session_id_name].value
        except KeyError:
            old_session_id = None
        response.session_id = old_session_id

        # if we are supposed to use cookie based session data
        if cookie_key:
            response.session_storage_type = 'cookie'
        elif db:
            response.session_storage_type = 'db'
        else:
            response.session_storage_type = 'file'
            # why do we do this?
            # because connect may be called twice, by web2py and in models.
            # the first time there is no db yet so it should do nothing
            if (global_settings.db_sessions is True
                    or masterapp in global_settings.db_sessions):
                return

        if response.session_storage_type == 'cookie':
            # check if there is session data in cookies
            if response.session_data_name in cookies:
                session_cookie_data = cookies[response.session_data_name].value
            else:
                session_cookie_data = None
            if session_cookie_data:
                data = secure_loads(session_cookie_data,
                                    cookie_key,
                                    compression_level=compression_level)
                if data:
                    self.update(data)
            response.session_id = True

        # else if we are supposed to use file based sessions
        elif response.session_storage_type == 'file':
            response.session_new = False
            response.session_file = None
            # check if the session_id points to a valid sesion filename
            if response.session_id:
                if not regex_session_id.match(response.session_id):
                    response.session_id = None
                else:
                    response.session_filename = \
                        os.path.join(up(request.folder), masterapp,
                                     'sessions', response.session_id)
                    try:
                        response.session_file = \
                            recfile.open(response.session_filename, 'rb+')
                        portalocker.lock(response.session_file,
                                         portalocker.LOCK_EX)
                        response.session_locked = True
                        self.update(pickle.load(response.session_file))
                        response.session_file.seek(0)
                        oc = response.session_filename.split('/')[-1].split(
                            '-')[0]
                        if check_client and response.session_client != oc:
                            raise Exception("cookie attack")
                    except:
                        response.session_id = None
            if not response.session_id:
                uuid = web2py_uuid()
                response.session_id = '%s-%s' % (response.session_client, uuid)
                separate = separate and (
                    lambda session_name: session_name[-2:])
                if separate:
                    prefix = separate(response.session_id)
                    response.session_id = '%s/%s' % (prefix,
                                                     response.session_id)
                response.session_filename = \
                    os.path.join(up(request.folder), masterapp,
                                 'sessions', response.session_id)
                response.session_new = True

        # else the session goes in db
        elif response.session_storage_type == 'db':
            if global_settings.db_sessions is not True:
                global_settings.db_sessions.add(masterapp)
            # if had a session on file alreday, close it (yes, can happen)
            if response.session_file:
                self._close(response)
            # if on GAE tickets go also in DB
            if settings.global_settings.web2py_runtime_gae:
                request.tickets_db = db
            if masterapp == request.application:
                table_migrate = migrate
            else:
                table_migrate = False
            tname = tablename + '_' + masterapp
            table = db.get(tname, None)
            # Field = db.Field
            if table is None:
                db.define_table(
                    tname,
                    Field('locked', 'boolean', default=False),
                    Field('client_ip', length=64),
                    Field('created_datetime', 'datetime', default=request.now),
                    Field('modified_datetime', 'datetime'),
                    Field('unique_key', length=64),
                    Field('session_data', 'blob'),
                    migrate=table_migrate,
                )
                table = db[tname]  # to allow for lazy table
            response.session_db_table = table
            if response.session_id:
                # Get session data out of the database
                try:
                    (record_id, unique_key) = response.session_id.split(':')
                    record_id = long(record_id)
                except (TypeError, ValueError):
                    record_id = None

                # Select from database
                if record_id:
                    row = table(record_id, unique_key=unique_key)
                    # Make sure the session data exists in the database
                    if row:
                        # rows[0].update_record(locked=True)
                        # Unpickle the data
                        session_data = pickle.loads(row.session_data)
                        self.update(session_data)
                        response.session_new = False
                    else:
                        record_id = None
                if record_id:
                    response.session_id = '%s:%s' % (record_id, unique_key)
                    response.session_db_unique_key = unique_key
                    response.session_db_record_id = record_id
                else:
                    response.session_id = None
                    response.session_new = True
            # if there is no session id yet, we'll need to create a
            # new session
            else:
                response.session_new = True

        # set the cookie now if you know the session_id so user can set
        # cookie attributes in controllers/models
        # cookie will be reset later
        # yet cookie may be reset later
        #   Removed comparison between old and new session ids - should send
        #    the cookie all the time
        if isinstance(response.session_id, str):
            response.cookies[response.session_id_name] = response.session_id
            response.cookies[response.session_id_name]['path'] = '/'
            if cookie_expires:
                response.cookies[response.session_id_name]['expires'] = \
                    cookie_expires.strftime(FMT)

        session_pickled = pickle.dumps(self, pickle.HIGHEST_PROTOCOL)
        response.session_hash = hashlib.md5(session_pickled).hexdigest()

        if self.flash:
            (response.flash, self.flash) = (self.flash, None)
 def test_pickling(self):
     """ Test storage pickling """
     s = Storage(a=1)
     sd = pickle.dumps(s, pickle.HIGHEST_PROTOCOL)
     news = pickle.loads(sd)
     self.assertEqual(news.a, 1)
示例#24
0
    def connect(self,
                request=None,
                response=None,
                db=None,
                tablename='web2py_session',
                masterapp=None,
                migrate=True,
                separate=None,
                check_client=False,
                cookie_key=None,
                cookie_expires=None,
                compression_level=None
                ):
        """
        Used in models, allows to customize Session handling

        Args:
            request: the request object
            response: the response object
            db: to store/retrieve sessions in db (a table is created)
            tablename(str): table name
            masterapp(str): points to another's app sessions. This enables a
                "SSO" environment among apps
            migrate: passed to the underlying db
            separate: with True, creates a folder with the 2 initials of the
                session id. Can also be a function, e.g. ::

                    separate=lambda(session_name): session_name[-2:]

            check_client: if True, sessions can only come from the same ip
            cookie_key(str): secret for cookie encryption
            cookie_expires: sets the expiration of the cookie
            compression_level(int): 0-9, sets zlib compression on the data
                before the encryption
        """
        from gluon.dal import Field
        request = request or current.request
        response = response or current.response
        masterapp = masterapp or request.application
        cookies = request.cookies

        self._unlock(response)

        response.session_masterapp = masterapp
        response.session_id_name = 'session_id_%s' % masterapp.lower()
        response.session_data_name = 'session_data_%s' % masterapp.lower()
        response.session_cookie_expires = cookie_expires
        response.session_client = str(request.client).replace(':', '.')
        current._session_cookie_key = cookie_key
        response.session_cookie_compression_level = compression_level

        # check if there is a session_id in cookies
        try:
            old_session_id = cookies[response.session_id_name].value
        except KeyError:
            old_session_id = None
        response.session_id = old_session_id

        # if we are supposed to use cookie based session data
        if cookie_key:
            response.session_storage_type = 'cookie'
        elif db:
            response.session_storage_type = 'db'
        else:
            response.session_storage_type = 'file'
            # why do we do this?
            # because connect may be called twice, by web2py and in models.
            # the first time there is no db yet so it should do nothing
            if (global_settings.db_sessions is True
                    or masterapp in global_settings.db_sessions):
                return

        if response.session_storage_type == 'cookie':
            # check if there is session data in cookies
            if response.session_data_name in cookies:
                session_cookie_data = cookies[response.session_data_name].value
            else:
                session_cookie_data = None
            if session_cookie_data:
                data = secure_loads(session_cookie_data, cookie_key,
                                    compression_level=compression_level)
                if data:
                    self.update(data)
            response.session_id = True

        # else if we are supposed to use file based sessions
        elif response.session_storage_type == 'file':
            response.session_new = False
            response.session_file = None
            # check if the session_id points to a valid sesion filename
            if response.session_id:
                if not regex_session_id.match(response.session_id):
                    response.session_id = None
                else:
                    response.session_filename = \
                        os.path.join(up(request.folder), masterapp,
                                     'sessions', response.session_id)
                    try:
                        response.session_file = \
                            recfile.open(response.session_filename, 'rb+')
                        portalocker.lock(response.session_file,
                                         portalocker.LOCK_EX)
                        response.session_locked = True
                        self.update(pickle.load(response.session_file))
                        response.session_file.seek(0)
                        oc = response.session_filename.split('/')[-1].split('-')[0]
                        if check_client and response.session_client != oc:
                            raise Exception("cookie attack")
                    except:
                        response.session_id = None
            if not response.session_id:
                uuid = web2py_uuid()
                response.session_id = '%s-%s' % (response.session_client, uuid)
                separate = separate and (lambda session_name: session_name[-2:])
                if separate:
                    prefix = separate(response.session_id)
                    response.session_id = '%s/%s' % (prefix, response.session_id)
                response.session_filename = \
                    os.path.join(up(request.folder), masterapp,
                                 'sessions', response.session_id)
                response.session_new = True

        # else the session goes in db
        elif response.session_storage_type == 'db':
            if global_settings.db_sessions is not True:
                global_settings.db_sessions.add(masterapp)
            # if had a session on file alreday, close it (yes, can happen)
            if response.session_file:
                self._close(response)
            # if on GAE tickets go also in DB
            if settings.global_settings.web2py_runtime_gae:
                request.tickets_db = db
            if masterapp == request.application:
                table_migrate = migrate
            else:
                table_migrate = False
            tname = tablename + '_' + masterapp
            table = db.get(tname, None)
            # Field = db.Field
            if table is None:
                db.define_table(
                    tname,
                    Field('locked', 'boolean', default=False),
                    Field('client_ip', length=64),
                    Field('created_datetime', 'datetime',
                          default=request.now),
                    Field('modified_datetime', 'datetime'),
                    Field('unique_key', length=64),
                    Field('session_data', 'blob'),
                    migrate=table_migrate,
                )
                table = db[tname]  # to allow for lazy table
            response.session_db_table = table
            if response.session_id:
                # Get session data out of the database
                try:
                    (record_id, unique_key) = response.session_id.split(':')
                    record_id = long(record_id)
                except (TypeError, ValueError):
                    record_id = None

                # Select from database
                if record_id:
                    row = table(record_id, unique_key=unique_key)
                    # Make sure the session data exists in the database
                    if row:
                        # rows[0].update_record(locked=True)
                        # Unpickle the data
                        session_data = pickle.loads(row.session_data)
                        self.update(session_data)
                        response.session_new = False
                    else:
                        record_id = None
                if record_id:
                    response.session_id = '%s:%s' % (record_id, unique_key)
                    response.session_db_unique_key = unique_key
                    response.session_db_record_id = record_id
                else:
                    response.session_id = None
                    response.session_new = True
            # if there is no session id yet, we'll need to create a
            # new session
            else:
                response.session_new = True

        # set the cookie now if you know the session_id so user can set
        # cookie attributes in controllers/models
        # cookie will be reset later
        # yet cookie may be reset later
        #   Removed comparison between old and new session ids - should send
        #    the cookie all the time
        if isinstance(response.session_id, str):
            response.cookies[response.session_id_name] = response.session_id
            response.cookies[response.session_id_name]['path'] = '/'
            if cookie_expires:
                response.cookies[response.session_id_name]['expires'] = \
                    cookie_expires.strftime(FMT)

        session_pickled = pickle.dumps(self, pickle.HIGHEST_PROTOCOL)
        response.session_hash = hashlib.md5(session_pickled).hexdigest()

        if self.flash:
            (response.flash, self.flash) = (self.flash, None)