From 740c712fb59374469e0aa603d3f99b0b9b1e5cd9 Mon Sep 17 00:00:00 2001 From: jperras Date: Mon, 13 Apr 2009 15:47:40 -0400 Subject: [PATCH 1/4] Refactoring core session library to use a proper Session model instead of hard-coded SQL. --- cake/libs/session.php | 133 ++++++++++++------------- cake/tests/cases/libs/session.test.php | 21 +++- 2 files changed, 82 insertions(+), 72 deletions(-) diff --git a/cake/libs/session.php b/cake/libs/session.php index 88b90da52..4d6a29f16 100644 --- a/cake/libs/session.php +++ b/cake/libs/session.php @@ -27,16 +27,7 @@ * @lastmodified $Date$ * @license http://www.opensource.org/licenses/mit-license.php The MIT License */ -/** - * Database name for cake sessions. - * - */ -if (!class_exists('Set')) { - require LIBS . 'set.php'; -} -if (!class_exists('Security')) { - require LIBS . 'security.php'; -} + /** * Session class for Cake. * @@ -125,32 +116,49 @@ class CakeSession extends Object { * @access public */ function __construct($base = null, $start = true) { - if (Configure::read('Session.save') === 'database' && !class_exists('ConnectionManager')) { - App::import('Core', 'ConnectionManager'); - } + App::import('Core', 'Security'); + $this->time = time(); if (Configure::read('Session.checkAgent') === true || Configure::read('Session.checkAgent') === null) { if (env('HTTP_USER_AGENT') != null) { $this->_userAgent = md5(env('HTTP_USER_AGENT') . Configure::read('Security.salt')); } } - $this->time = time(); + + if (Configure::read('Session.save') === 'database') { + $modelName = Configure::read('Session.model'); + $database = Configure::read('Session.database'); + $table = Configure::read('Session.table'); + + if (empty($database)) { + $database = 'default'; + } + + if (empty($modelName)) { + ClassRegistry::init(array( + 'class' => Inflector::classify($table), + 'alias' => 'Session' + )); + } else { + ClassRegistry::init(array( + 'class' => $modelName, + 'alias' => 'Session' + )); + } + } + if ($start === true) { $this->host = env('HTTP_HOST'); - if (empty($base) || strpos($base, '?') === 0 || strpos($base, 'index.php') === 0) { - $this->path = '/'; - } else { - $this->path = $base; - } - if (strpos($this->host, ':') !== false) { $this->host = substr($this->host, 0, strpos($this->host, ':')); } - if (!class_exists('Security')) { - App::import('Core', 'Security'); + if (empty($base) || strpos($base, '?') === 0 || strpos($base, 'index.php') === 0) { + $this->path = '/'; + } else { + $this->path = $base; } $this->sessionTime = $this->time + (Security::inactiveMins() * Configure::read('Session.timeout')); @@ -685,81 +693,60 @@ class CakeSession extends Object { /** * Method used to read from a database session. * - * @param mixed $key The key of the value to read + * @param mixed $id The key of the value to read * @return mixed The value of the key or false if it does not exist * @access private */ - function __read($key) { - $db =& ConnectionManager::getDataSource(Configure::read('Session.database')); - $table = $db->fullTableName(Configure::read('Session.table'), false); - $row = $db->query("SELECT " . $db->name($table.'.data') . " FROM " . $db->name($table) . " WHERE " . $db->name($table.'.id') . " = " . $db->value($key), false); + function __read($id) { + $model = ClassRegistry::getObject('Session'); - if ($row && !isset($row[0][$table]) && isset($row[0][0])) { - $table = 0; - } + $row = $model->find('first', array( + 'conditions' => array($model->primaryKey => $id) + )); - if ($row && $row[0][$table]['data']) { - return $row[0][$table]['data']; - } else { + if (empty($row[$model->alias]['data'])) { return false; } + + return $row[$model->alias]['data']; } /** * Helper function called on write for database sessions. * - * @param mixed $key The name of the var - * @param mixed $value The value of the var - * @return boolean Success + * @param integer $id ID that uniquely identifies session in database + * @param mixed $data The value of the the data to be saved. + * @return boolean True for successful write, false otherwise. * @access private */ - function __write($key, $value) { - $db =& ConnectionManager::getDataSource(Configure::read('Session.database')); - $table = $db->fullTableName(Configure::read('Session.table')); - + function __write($id, $data) { switch (Configure::read('Security.level')) { - case 'high': - $factor = 10; - break; case 'medium': $factor = 100; break; case 'low': $factor = 300; break; + case 'high': default: $factor = 10; break; } - $expires = time() + Configure::read('Session.timeout') * $factor; - $row = $db->query("SELECT COUNT(id) AS count FROM " . $db->name($table) . " WHERE " - . $db->name('id') . " = " - . $db->value($key), false); - if ($row[0][0]['count'] > 0) { - $db->execute("UPDATE " . $db->name($table) . " SET " . $db->name('data') . " = " - . $db->value($value) . ", " . $db->name('expires') . " = " - . $db->value($expires) . " WHERE " . $db->name('id') . " = " - . $db->value($key)); - } else { - $db->execute("INSERT INTO " . $db->name($table) . " (" . $db->name('data') . "," - . $db->name('expires') . "," . $db->name('id') - . ") VALUES (" . $db->value($value) . ", " . $db->value($expires) . ", " - . $db->value($key) . ")"); - } - return true; + $expires = time() + Configure::read('Session.timeout') * $factor; + $return = ClassRegistry::getObject('Session')->save(compact('id', 'data', 'expires')); + + return $return; } /** * Method called on the destruction of a database session. * - * @param integer $key Key that uniquely identifies session in database - * @return boolean Success + * @param integer $id ID that uniquely identifies session in database + * @return boolean True for successful delete, false otherwise. * @access private */ - function __destroy($key) { - $db =& ConnectionManager::getDataSource(Configure::read('Session.database')); - $table = $db->fullTableName(Configure::read('Session.table')); - $db->execute("DELETE FROM " . $db->name($table) . " WHERE " . $db->name($table.'.id') . " = " . $db->value($key)); - return true; + function __destroy($id) { + $return = ClassRegistry::getObject('Session')->delete($id); + return $return; } /** * Helper function called on gc for database sessions. @@ -769,10 +756,14 @@ class CakeSession extends Object { * @access private */ function __gc($expires = null) { - $db =& ConnectionManager::getDataSource(Configure::read('Session.database')); - $table = $db->fullTableName(Configure::read('Session.table')); - $db->execute("DELETE FROM " . $db->name($table) . " WHERE " . $db->name($table.'.expires') . " < ". $db->value(time())); - return true; + $model = ClassRegistry::getObject('Session'); + + if (!$expires) { + $expires = time(); + } + + $return = $model->deleteAll(array("$alias.expires <" => $expires), false, false); + return $return; } } -?> \ No newline at end of file +?> diff --git a/cake/tests/cases/libs/session.test.php b/cake/tests/cases/libs/session.test.php index eacea5651..c50147163 100644 --- a/cake/tests/cases/libs/session.test.php +++ b/cake/tests/cases/libs/session.test.php @@ -34,6 +34,12 @@ if (!class_exists('CakeSession')) { * @subpackage cake.tests.cases.libs */ class SessionTest extends CakeTestCase { +/** + * Fixtures used in the SessionTest + * + * @var array + * @access public + */ var $fixtures = array('core.session'); /** * setUp method @@ -46,6 +52,16 @@ class SessionTest extends CakeTestCase { $this->Session->start(); $this->Session->_checkValid(); } +/** + * tearDown method + * + * @access public + * @return void + */ + function tearDown() { + unset($_SESSION); + session_destroy(); + } /** * testCheck method * @@ -366,6 +382,9 @@ class SessionTest extends CakeTestCase { $this->Session->write('SessionTestCase', 'This is a Test'); $this->assertEqual($this->Session->read('SessionTestCase'), 'This is a Test'); + $this->Session->write('SessionTestCase', 'Some additional data'); + $this->assertEqual($this->Session->read('SessionTestCase'), 'Some additional data'); + $this->Session->destroy(); $this->assertFalse($this->Session->read('SessionTestCase')); session_write_close(); @@ -376,4 +395,4 @@ class SessionTest extends CakeTestCase { $this->setUp(); } } -?> \ No newline at end of file +?> From cadc64c7b6fdff546586eae6baa89bb6195382e8 Mon Sep 17 00:00:00 2001 From: jperras Date: Mon, 13 Apr 2009 23:53:10 -0400 Subject: [PATCH 2/4] Removing EOF newlines. --- cake/libs/session.php | 2 +- cake/tests/cases/libs/session.test.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cake/libs/session.php b/cake/libs/session.php index 4d6a29f16..012a57634 100644 --- a/cake/libs/session.php +++ b/cake/libs/session.php @@ -766,4 +766,4 @@ class CakeSession extends Object { return $return; } } -?> +?> \ No newline at end of file diff --git a/cake/tests/cases/libs/session.test.php b/cake/tests/cases/libs/session.test.php index c50147163..7405a315a 100644 --- a/cake/tests/cases/libs/session.test.php +++ b/cake/tests/cases/libs/session.test.php @@ -395,4 +395,4 @@ class SessionTest extends CakeTestCase { $this->setUp(); } } -?> +?> \ No newline at end of file From 75f303f7b8598e5230b97258889906103be220cb Mon Sep 17 00:00:00 2001 From: jperras Date: Tue, 14 Apr 2009 00:36:13 -0400 Subject: [PATCH 3/4] Removing method chaining from core session library & adding assign by references for php4 compatibility. --- cake/libs/session.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/cake/libs/session.php b/cake/libs/session.php index 012a57634..f2b6de4b2 100644 --- a/cake/libs/session.php +++ b/cake/libs/session.php @@ -698,7 +698,7 @@ class CakeSession extends Object { * @access private */ function __read($id) { - $model = ClassRegistry::getObject('Session'); + $model =& ClassRegistry::getObject('Session'); $row = $model->find('first', array( 'conditions' => array($model->primaryKey => $id) @@ -733,7 +733,9 @@ class CakeSession extends Object { } $expires = time() + Configure::read('Session.timeout') * $factor; - $return = ClassRegistry::getObject('Session')->save(compact('id', 'data', 'expires')); + + $model =& ClassRegistry::getObject('Session'); + $return = $model->save(compact('id', 'data', 'expires')); return $return; } @@ -745,7 +747,9 @@ class CakeSession extends Object { * @access private */ function __destroy($id) { - $return = ClassRegistry::getObject('Session')->delete($id); + $model =& ClassRegistry::getObject('Session'); + $return = $model->delete($id); + return $return; } /** @@ -756,13 +760,13 @@ class CakeSession extends Object { * @access private */ function __gc($expires = null) { - $model = ClassRegistry::getObject('Session'); + $model =& ClassRegistry::getObject('Session'); if (!$expires) { $expires = time(); } - $return = $model->deleteAll(array("$alias.expires <" => $expires), false, false); + $return = $model->deleteAll(array("$alias.expires <" => $expires), false, false); return $return; } } From 5d183cbe9af3e6f12a238118dd063b9ecb1dc96c Mon Sep 17 00:00:00 2001 From: jperras Date: Tue, 14 Apr 2009 20:12:44 -0400 Subject: [PATCH 4/4] Updating core.php with new Session.model configuration directive. --- app/config/core.php | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/app/config/core.php b/app/config/core.php index dfcba1ea5..01b8d563d 100644 --- a/app/config/core.php +++ b/app/config/core.php @@ -96,16 +96,30 @@ * To define a custom session handler, save it at /app/config/.php. * Set the value of 'Session.save' to to utilize it in CakePHP. * - * To use database sessions, execute the SQL file found at /app/config/sql/sessions.sql. + * To use database sessions, run the app/config/schema/sessions.php schema using + * the cake shell command: cake schema run create Sessions * */ Configure::write('Session.save', 'php'); +/** + * The model name to be used for the session model. + * + * 'Session.save' must be set to 'database' in order to utilize this constant. + * + * The model name set here should *not* be used elsewhere in your application. + */ + //Configure::write('Session.model', 'Session'); /** * The name of the table used to store CakePHP database sessions. * * 'Session.save' must be set to 'database' in order to utilize this constant. * * The table name set here should *not* include any table prefix defined elsewhere. + * + * Please note that if you set a value for Session.model (above), any value set for + * Session.table will be ignored. + * + * [Note: Session.table is deprecated as of CakePHP 1.3] */ //Configure::write('Session.table', 'cake_sessions'); /**