From 6c5596e436af6a29869f269d6726f539d1d9c1ae Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Sat, 24 Sep 2011 16:13:23 +0100 Subject: [PATCH 01/34] Add support for hashes in the Config class. --- source/lib/SihnonFramework/Config.class.php | 22 ++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/source/lib/SihnonFramework/Config.class.php b/source/lib/SihnonFramework/Config.class.php index 50a84e6..1f804ab 100644 --- a/source/lib/SihnonFramework/Config.class.php +++ b/source/lib/SihnonFramework/Config.class.php @@ -32,6 +32,12 @@ class SihnonFramework_Config { */ const TYPE_STRING_LIST = 'array(string)'; + /** + * Hash type with string keys and mixed-type values + * @var array(string=>mixed) + */ + const TYPE_HASH = 'hash'; + /** * Backend to be used for this Config object * @var Sihnon_Config_IPlugin @@ -58,9 +64,11 @@ class SihnonFramework_Config { protected static function pack($type, $value) { switch ($type) { - case static::TYPE_STRING_LIST: { + case static::TYPE_STRING_LIST: return join("\n", $value); - } break; + + case static::TYPE_HASH: + return join("\n", array_map(function($k, $v) { return "{$k}:{$v}"; }, array_keys($value), array_values($value))); default: { return $value; @@ -70,9 +78,17 @@ class SihnonFramework_Config { protected static function unpack($type, $value) { switch ($type) { - case self::TYPE_STRING_LIST: + case static::TYPE_STRING_LIST: + // foo + // bar return array_map('trim', explode("\n", $value)); + case static::TYPE_HASH: + // foo:bar + // baz:quz + preg_match_all("/^([^:]+):(.+)$/m", $value, $pairs); + return array_combine($pairs[1], $pairs[2]); + default: return $value; } From 90f190578d978490dc9527db36cc8fe734dfcf70 Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Sat, 24 Sep 2011 18:16:55 +0100 Subject: [PATCH 02/34] Update formatDuration to support fuzzy times --- source/lib/SihnonFramework/Main.class.php | 88 +++++++++++++++++------ 1 file changed, 65 insertions(+), 23 deletions(-) diff --git a/source/lib/SihnonFramework/Main.class.php b/source/lib/SihnonFramework/Main.class.php index f3cbb76..897b25c 100644 --- a/source/lib/SihnonFramework/Main.class.php +++ b/source/lib/SihnonFramework/Main.class.php @@ -324,32 +324,74 @@ class SihnonFramework_Main { return $default; } - public static function formatDuration($time) { - if (is_null($time)) { - return 'unknown'; - } + public static function formatDuration($seconds, $fuzziness = 0) { + if (is_null($seconds)) { + return 'indeterminate time'; + } + + $labels = array('second', 'minute', 'hour', 'day', 'week', 'month', 'year'); + $pluralLabels = array('seconds', 'minutes', 'hours', 'days', 'weeks', 'months', 'years'); + $limits = array(1, 60, 3600, 86400, 604800, 2592000, 31556926, PHP_INT_MAX); + $components = array(0, 0, 0, 0, 0, 0, 0); + + $workingTime = $seconds; + + $result = ""; + $ptr = count($labels) - 1; - $labels = array('seconds', 'minutes', 'hours', 'days', 'weeks', 'months', 'years'); - $limits = array(1, 60, 3600, 86400, 604800, 2592000, 31556926, PHP_INT_MAX); + while ($ptr >= 0 && $workingTime < $limits[$ptr]) { + --$ptr; + } + $mostSignificantPtr = $ptr; + + // Convert the value into components using the remaining labels + while ($ptr >= 0) { + $unitTime = floor($workingTime / $limits[$ptr]); + $workingTime -= $unitTime * $limits[$ptr]; + $components[$ptr] = $unitTime; + --$ptr; + } + + $componentsUsed = 0; + $approximate = false; + $lastComponent = false; + $ptr = $mostSignificantPtr; + while ($ptr >= 0) { + if ($fuzziness && $componentsUsed >= $fuzziness) { + break; + } elseif ($ptr == 0 || ($fuzziness && $componentsUsed == $fuzziness-1)) { + $lastComponent = true; + } + + $component = $components[$ptr]; + if ($component) { + // If we're going to hide the next value, take its component into account here + if ($lastComponent && $ptr > 0) { + $component += round($components[$ptr-1] / $limits[$ptr]); + $approximate = true; + } + + if ($lastComponent && $ptr < $mostSignificantPtr) { + $result .= ' and'; + } + + $result .= ' ' . $component . ' ' . ($component == 1 ? $labels[$ptr] : $pluralLabels[$ptr]); + + } + + // Increment even if we've hidden this component because it's zero + // Then we don't end up with overly precise times like '2 years and 1 second' + ++$componentsUsed; + + --$ptr; + } - $working_time = $time; + if ($approximate) { + $result = 'approximately ' . $result; + } - $result = ""; - $ptr = count($labels) - 1; - - while ($ptr >= 0 && $working_time < $limits[$ptr]) { - --$ptr; - } - - while ($ptr >= 0) { - $unit_time = floor($working_time / $limits[$ptr]); - $working_time -= $unit_time * $limits[$ptr]; - $result = $result . ' ' . $unit_time . ' ' . $labels[$ptr]; - --$ptr; - } - - return $result; - } + return $result; + } public static function formatFilesize($bytes) { if (is_null($bytes)) { From d7dfdadc147519c3a0b4ac88b24945aa370d94da Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Thu, 6 Oct 2011 22:54:07 +0100 Subject: [PATCH 03/34] Upgrade BackgroundTask to support modified environment --- source/lib/SihnonFramework/BackgroundTask.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/lib/SihnonFramework/BackgroundTask.class.php b/source/lib/SihnonFramework/BackgroundTask.class.php index 90c057f..69491e0 100644 --- a/source/lib/SihnonFramework/BackgroundTask.class.php +++ b/source/lib/SihnonFramework/BackgroundTask.class.php @@ -6,10 +6,10 @@ class SihnonFramework_BackgroundTask { } - public static function run($command) { + public static function run($command, $cwd=null, $env=null) { SihnonFramework_LogEntry::debug(SihnonFramework_Main::instance()->log(), "Running background task: {$command} &", 'default'); $pipes = array(); - $pid = proc_open($command . ' &', array(), $pipes); + $pid = proc_open($command . ' &', array(), $pipes, $cwd, $env); proc_close($pid); } From bc154dd1c80dfe7919f01cead64e93a040ed0253 Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Tue, 13 Dec 2011 01:23:02 +0000 Subject: [PATCH 04/34] Add shortfile option for console logging To reduce the width of console log messages, add an field to display the filename without full path info. --- source/lib/SihnonFramework/Log/Plugin/Console.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/source/lib/SihnonFramework/Log/Plugin/Console.class.php b/source/lib/SihnonFramework/Log/Plugin/Console.class.php index 565e791..d56017a 100644 --- a/source/lib/SihnonFramework/Log/Plugin/Console.class.php +++ b/source/lib/SihnonFramework/Log/Plugin/Console.class.php @@ -34,6 +34,7 @@ class SihnonFramework_Log_Plugin_Console extends SihnonFramework_Log_PluginBase // Make some alterations for ease of display $fields_map['timestamp'] = date('d/m/y H:i:s', $fields_map['ctime']); + $fields_map['shortfile'] = basename($fields_map['file']); // split the map back out again now the modifications have been made $fields = array_keys($fields_map); From 537583a23167760cbe8037fc179b0550d0fa2187 Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Mon, 19 Dec 2011 12:00:08 +0000 Subject: [PATCH 05/34] Add DatabaseObject base class DatabaseObject exposes common behaviours for database table wrapper classes. --- source/lib/SihnonFramework/Database.class.php | 4 +- .../SihnonFramework/DatabaseObject.class.php | 212 ++++++++++++++++++ .../lib/SihnonFramework/Exceptions.class.php | 1 + 3 files changed, 215 insertions(+), 2 deletions(-) create mode 100644 source/lib/SihnonFramework/DatabaseObject.class.php diff --git a/source/lib/SihnonFramework/Database.class.php b/source/lib/SihnonFramework/Database.class.php index 9de43f6..57f596c 100644 --- a/source/lib/SihnonFramework/Database.class.php +++ b/source/lib/SihnonFramework/Database.class.php @@ -68,7 +68,7 @@ class SihnonFramework_Database { } private function query($sql, $count = 0) { - $results = $this->dbh->query($sql); + $results = $this->dbh->query($sql, PDO::FETCH_ASSOC); if (! $results) { list($std_code, $driver_code, $message) = $this->dbh->errorInfo(); @@ -123,7 +123,7 @@ class SihnonFramework_Database { } } - return $stmt->fetchAll(); + return $stmt->fetchAll(PDO::FETCH_ASSOC); } else { $results = array(); diff --git a/source/lib/SihnonFramework/DatabaseObject.class.php b/source/lib/SihnonFramework/DatabaseObject.class.php new file mode 100644 index 0000000..1679390 --- /dev/null +++ b/source/lib/SihnonFramework/DatabaseObject.class.php @@ -0,0 +1,212 @@ + $value) { + if (property_exists(get_called_class(), '_db_' . $property)) { + $this->{'_db_' . $property} = $value; + } else { + throw new Sihnon_Exception_InvalidProperty($property); + } + } + } + + public static function fromDatabaseRow($row) { + $object = new static(); + $object->setDatabaseProperties($row); + + return $object; + } + + /** + * Load a DatabaseObject given its ID + * + * @param int $id + * @return SihnonFramework_DatabaseObject + */ + public static function fromId($id) { + $database = SihnonFramework_Main::instance()->database(); + + $object = self::fromDatabaseRow( + $database->selectOne('SELECT * FROM `'.static::table().'` WHERE id=:id', array( + array('name' => 'id', 'value' => $id, 'type' => PDO::PARAM_INT) + ) + ) + ); + + return $object; + } + + /** + * Load a DatabaseObject given a field name and value + * + * @param string $name Name of the field to match on + * @param mixed $value Value of the field to match on + */ + public static function from($field, $value) { + $database = SihnonFramework_Main::instance()->database(); + + $object = self::fromDatabaseRow( + $database->selectOne("SELECT * FROM `".static::table()."` WHERE `{$field}`=:{$field}", array( + array('name' => $field, 'value' => $value, 'type' => PDO::PARAM_STR) + ) + ) + ); + + return $object; + } + + /** + * Load a list of all objects + * + * @return SihnonFramework_DatabaseObject + */ + public static function all() { + $database = SihnonFramework_Main::instance()->database(); + + $objects = array(); + foreach ($database->selectList('SELECT * FROM `'.static::table().'` WHERE `id` > 0 ORDER BY `id` DESC') as $row) { + $objects[] = static::fromDatabaseRow($row); + } + + return $objects; + } + + public static function all_for($field, $value, $view = null) { + $database = SihnonFramework_Main::instance()->database(); + + if ($view === null) { + $view = static::table(); + } + + $class = new ReflectionClass(get_called_class()); + $properties = $class->getproperties(); + + $fields = array(); + foreach ($properties as $property) { + $matches = array(); + if (preg_match('/^_db_(.*)/', $property->name, $matches)) { + $fields[] = $matches[1]; + } + } + + $field_list = join(', ', array_map(function($v) { return "`{$v}`"; }, $fields));$objects = array(); + + foreach ($database->selectList("SELECT {$field_list} FROM `{$view}` WHERE `{$field}`=:{$field} ORDER BY `id` DESC", array( + array('name' => $field, 'value' => $value, 'type' => PDO::PARAM_STR), + )) as $row) { + $objects[] = static::fromDatabaseRow($row); + } + + return $objects; + } + + public static function exists($field, $value, $view = null) { + $database = Sihnon_Main::instance()->database(); + + return $database->selectOne('SELECT COUNT(*) FROM `'.static::table().'` "WHERE `{$field}`=:{$field} LIMIT 1', array( + array('name' => $field, 'value' => $value, 'type' => PDO::PARAM_STR), + ) + ); + } + + protected function create() { + $database = SihnonFramework_Main::instance()->database(); + + $class = new ReflectionClass(get_called_class()); + $properties = $class->getproperties(); + + $fields = array(); + $params = array(); + foreach ($properties as $property) { + $matches = array(); + if (preg_match('/^_db_(.*)/', $property->name, $matches)) { + $fields[] = $matches[1]; + + $params[] = array( + 'name' => $matches[1], + 'value' => ($matches[1] == 'id') ? 'NULL' : $this->{"_db_{$matches[1]}"}, + 'type' => PDO::PARAM_STR + ); + } + } + + $id_list = join(', ', array_map(function($v) { return "`{$v}`"; }, $fields)); + $value_list = join(', ', array_map(function($v) { return ":{$v}"; }, $fields)); + + $database->insert('INSERT INTO `'.static::table().'` ({$id_list}) VALUES({$value_list})', $params); + + $this->id = $database->lastInsertId(); + } + + protected function save() { + $database = SihnonFramework_Main::instance()->database(); + + $class = new ReflectionClass(get_called_class()); + $properties = $class->getproperties(); + + $fields = array(); + $params = array(); + foreach ($properties as $property) { + $matches = array(); + if (preg_match('/^_db_(.*)/', $property->name, $matches)) { + if ($matches[1] != 'id') { + $fields[] = $matches[1]; + } + + $params[] = array( + 'name' => $matches[1], + 'value' => $this->{"_db_{$matches[1]}"}, + 'type' => PDO::PARAM_STR + ); + } + } + + $id_list = join(', ', array_map(function($v) { return "`{$v}`"; }, $fields)); + $value_list = join(', ', array_map(function($v) { return ":{$v}"; }, $fields)); + + $database->update('UPDATE `'.static::table().'` ({$id_list}) VALUES({$value_list}) WHERE `id`=:id', $params); + } + + public function delete() { + $database = SihnonFramework_Main::instance()->database(); + + $database->update( + 'DELETE FROM `'.static::table().'` WHERE `id`=:id LIMIT 1', + array( + array('name' => 'id', 'value' => $this->id, 'type' => PDO::PARAM_INT), + ) + ); + + $this->id = null; + } + + public function __set($name, $value) { + $fullname = "_db_{$name}"; + if ( ! property_exists(get_called_class(), $fullname)){ + throw new SihnonFramework_Exception_InvalidProperty($name); + } + + $this->{$fullname} = $value; + } + + public function __get($name) { + $fullname = "_db_{$name}"; + if ( ! property_exists(get_called_class(), $fullname)){ + throw new SihnonFramework_Exception_InvalidProperty($name); + } + + return $this->{$fullname}; + } + + +} + +?> \ No newline at end of file diff --git a/source/lib/SihnonFramework/Exceptions.class.php b/source/lib/SihnonFramework/Exceptions.class.php index 0ce68c0..d17205d 100644 --- a/source/lib/SihnonFramework/Exceptions.class.php +++ b/source/lib/SihnonFramework/Exceptions.class.php @@ -21,6 +21,7 @@ class SihnonFramework_Exception_DatabaseConnectFailed extends SihnonFramework_E class SihnonFramework_Exception_NoDatabaseConnection extends SihnonFramework_Exception_DatabaseException {}; class SihnonFramework_Exception_DatabaseQueryFailed extends SihnonFramework_Exception_DatabaseException {}; class SihnonFramework_Exception_ResultCountMismatch extends SihnonFramework_Exception_DatabaseException {}; +class SihnonFramework_Exception_InvalidProperty extends SihnonFramework_Exception_DatabaseException {}; class SihnonFramework_Exception_ConfigException extends SihnonFramework_Exception {}; class SihnonFramework_Exception_UnknownSetting extends SihnonFramework_Exception_ConfigException {}; From 5b72a8a206847fc5abb52dd7ae236f429cf515d2 Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Mon, 19 Dec 2011 12:07:12 +0000 Subject: [PATCH 06/34] Update Page to support processed includes Permit inclusion of templates through the templating code, rather than through smarty. --- source/lib/SihnonFramework/Page.class.php | 34 +++++++++++++++++------ 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/source/lib/SihnonFramework/Page.class.php b/source/lib/SihnonFramework/Page.class.php index ab8be43..5de45ca 100644 --- a/source/lib/SihnonFramework/Page.class.php +++ b/source/lib/SihnonFramework/Page.class.php @@ -7,10 +7,14 @@ class SihnonFramework_Page { private $page; - public function __construct(Smarty $smarty, SihnonFramework_RequestParser $request) { + public function __construct(Smarty $smarty, SihnonFramework_RequestParser $request, $page = null) { $this->smarty = $smarty; $this->request = $request; - $this->page = $request->page(); + $this->page = $page; + + if ($page === null) { + $this->page = $request->page(); + } } public function page() { @@ -20,23 +24,32 @@ class SihnonFramework_Page { public function template_filename() { return $this->page . '.tpl'; } + + public function code_filename() { + return $this->page . '.php'; + } public function evaluate($template_variables = array()) { - $code_filename = $this->page . '.php'; + $code_filename = $this->code_filename(); $template_filename = $this->template_filename(); + $content = ''; try { - $this->render($template_filename, $code_filename, $template_variables); + $this->smarty->assign('page', $this); + $this->smarty->assign('requested_page', $this->page); + $content = $this->render($template_filename, $code_filename, $template_variables); } catch (SihnonFramework_Exception_AbortEntirePage $e) { return false; } catch (SihnonFramework_Exception_FileNotFound $e) { - $this->render('errors/404.tpl', 'errors/404.php'); + $content = $this->render('errors/404.tpl', 'errors/404.php'); } catch (SihnonFramework_Exception $e) { - $this->render('errors/unhandled-exception.tpl', 'errors/unhandled-exception.php', array( + $content = $this->render('errors/unhandled-exception.tpl', 'errors/unhandled-exception.php', array( 'exception' => $e, )); } + $this->smarty->assign('page_content', $content); + return true; } @@ -57,10 +70,13 @@ class SihnonFramework_Page { include $real_code_filename; } - $this->smarty->assign('requested_page', $this->page); - // Now execute the template itself, which will render the results of the code file - $this->smarty->assign('page_content', $this->smarty->fetch($template_filename)); + return $this->smarty->fetch($template_filename); + } + + public function include_template($page, $template_variables = array()) { + $subpage = new Sihnon_Page($this->smarty, $this->request, $page); + return $subpage->render($subpage->template_filename(), $subpage->code_filename(), $template_variables); } public static function redirect($relative_url) { From d92cc576d7d40ae1c94fe4a0a4e7d699e760879b Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Mon, 19 Dec 2011 12:13:14 +0000 Subject: [PATCH 07/34] Initial commit of Session/Authentication code Plugin architecture with single Database-backed implementation. --- source/lib/SihnonFramework/Auth.class.php | 110 ++++++++++++++++++ .../Auth/IFinelyPermissionable.class.php | 9 ++ .../Auth/IPermissionable.class.php | 9 ++ .../SihnonFramework/Auth/IPlugin.class.php | 23 ++++ .../Auth/IUpdateable.class.php | 13 +++ .../lib/SihnonFramework/Auth/IUser.class.php | 11 ++ .../Auth/Plugin/Database.class.php | 83 +++++++++++++ .../Auth/Plugin/Database/Group.class.php | 12 ++ .../Plugin/Database/GroupPermission.class.php | 13 +++ .../Auth/Plugin/Database/Permission.class.php | 20 ++++ .../Auth/Plugin/Database/User.class.php | 74 ++++++++++++ .../Auth/Plugin/Database/UserGroup.class.php | 13 +++ .../Auth/PluginFactory.class.php | 30 +++++ .../lib/SihnonFramework/Exceptions.class.php | 5 + source/lib/SihnonFramework/Main.class.php | 21 ++++ source/lib/SihnonFramework/Session.class.php | 61 ++++++++++ 16 files changed, 507 insertions(+) create mode 100644 source/lib/SihnonFramework/Auth.class.php create mode 100644 source/lib/SihnonFramework/Auth/IFinelyPermissionable.class.php create mode 100644 source/lib/SihnonFramework/Auth/IPermissionable.class.php create mode 100644 source/lib/SihnonFramework/Auth/IPlugin.class.php create mode 100644 source/lib/SihnonFramework/Auth/IUpdateable.class.php create mode 100644 source/lib/SihnonFramework/Auth/IUser.class.php create mode 100644 source/lib/SihnonFramework/Auth/Plugin/Database.class.php create mode 100644 source/lib/SihnonFramework/Auth/Plugin/Database/Group.class.php create mode 100644 source/lib/SihnonFramework/Auth/Plugin/Database/GroupPermission.class.php create mode 100644 source/lib/SihnonFramework/Auth/Plugin/Database/Permission.class.php create mode 100644 source/lib/SihnonFramework/Auth/Plugin/Database/User.class.php create mode 100644 source/lib/SihnonFramework/Auth/Plugin/Database/UserGroup.class.php create mode 100644 source/lib/SihnonFramework/Auth/PluginFactory.class.php create mode 100644 source/lib/SihnonFramework/Session.class.php diff --git a/source/lib/SihnonFramework/Auth.class.php b/source/lib/SihnonFramework/Auth.class.php new file mode 100644 index 0000000..38b71ed --- /dev/null +++ b/source/lib/SihnonFramework/Auth.class.php @@ -0,0 +1,110 @@ +config = $config; + $this->session = $session; + $this->authenticated = false; + + $this->init($this->config->get('auth')); + } + + protected function init($backend) { + $this->backend = Sihnon_Auth_PluginFactory::create($config, $backend); + $this->restoreSession(); + } + + public function isAuthenticated() { + return $this->authenticated; + } + + public function saveSession() { + if ($this->user) { + $this->session->set('user.id', $this->user->username()); + } + } + + public function clearSession() { + $this->session->delete('user.id'); + } + + public function restoreSession() { + if ($this->session->exists('user.id')) { + $this->user = $this->backend->authenticateSession($this->session->get('user.id')); + $this->authenticated = true; + } + } + + public function register($username, $password) { + $this->user = $this->addUser($username, $password); + $this->authenticated = true; + } + + /* + * IPlugin methods + */ + + public function authenticate($username, $password) { + $this->user = $this->backend->authenticate($username, $password); + $this->authenticated = true; + + $this->session->securityLeveLChanged(); + $this->saveSession(); + } + + public function deauthenticate() { + $this->user = null; + $this->authenticated = false; + + $this->clearSession(); + } + + /* + * IUpdateable methods + */ + + public function addUser($username, $password) { + return $this->backend->addUser($username, $password); + } + + public function removeUser() { + $this->backend->removeUser($this->user); + $this->user = null; + $this->authenticated = false; + } + + /* + * IPermissionable methods + */ + + public function isAdministrator() { + if ( ! $this->user) { + return false; + } + + return $this->backend->isAdministrator($this->user); + } + + /* + * IFinelyPermissionable methods + */ + + public function hasPermission($permission) { + if ( ! $this->user) { + return false; + } + + return $this->backend->hasPermission($this->user, $permission); + } + +} + +?> \ No newline at end of file diff --git a/source/lib/SihnonFramework/Auth/IFinelyPermissionable.class.php b/source/lib/SihnonFramework/Auth/IFinelyPermissionable.class.php new file mode 100644 index 0000000..3f291c0 --- /dev/null +++ b/source/lib/SihnonFramework/Auth/IFinelyPermissionable.class.php @@ -0,0 +1,9 @@ + \ No newline at end of file diff --git a/source/lib/SihnonFramework/Auth/IPermissionable.class.php b/source/lib/SihnonFramework/Auth/IPermissionable.class.php new file mode 100644 index 0000000..75abc3c --- /dev/null +++ b/source/lib/SihnonFramework/Auth/IPermissionable.class.php @@ -0,0 +1,9 @@ + \ No newline at end of file diff --git a/source/lib/SihnonFramework/Auth/IPlugin.class.php b/source/lib/SihnonFramework/Auth/IPlugin.class.php new file mode 100644 index 0000000..26dd425 --- /dev/null +++ b/source/lib/SihnonFramework/Auth/IPlugin.class.php @@ -0,0 +1,23 @@ + \ No newline at end of file diff --git a/source/lib/SihnonFramework/Auth/IUpdateable.class.php b/source/lib/SihnonFramework/Auth/IUpdateable.class.php new file mode 100644 index 0000000..971c956 --- /dev/null +++ b/source/lib/SihnonFramework/Auth/IUpdateable.class.php @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/source/lib/SihnonFramework/Auth/IUser.class.php b/source/lib/SihnonFramework/Auth/IUser.class.php new file mode 100644 index 0000000..5ed5814 --- /dev/null +++ b/source/lib/SihnonFramework/Auth/IUser.class.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/source/lib/SihnonFramework/Auth/Plugin/Database.class.php b/source/lib/SihnonFramework/Auth/Plugin/Database.class.php new file mode 100644 index 0000000..5bdad0f --- /dev/null +++ b/source/lib/SihnonFramework/Auth/Plugin/Database.class.php @@ -0,0 +1,83 @@ +config = $config; + $this->database = SihnonFramework_Main::instance()->database(); + } + + /* + * IPlugin methods + */ + + public static function create(SihnonFramework_Config $config) { + return new self($config); + } + + public function userExists($username) { + return Sihnon_Auth_Plugin_Database_User::exists($username); + } + + public function listUsers() { + return Sihnon_Auth_Plugin_Database_User::all(); + } + + public function authenticate($username, $password) { + $user = Sihnon_Auth_Plugin_Database_User::from('username', $username); + + if ( ! $user->checkPassword($password)) { + throw new Sihnon_Exception_IncorrectPassword(); + } + + return $user; + } + + public function authenticateSession($username) { + return Sihnon_Auth_Plugin_Database_User::from('username', $username); + } + + /* + * IUpdateable methods + */ + + public function addUser($username, $password) { + return Sihnon_Auth_Plugin_Database_User::add($username, $password); + } + + public function removeUser(Sihnon_Auth_IUser $user) { + $user->delete(); + } + + public function changePassword(Sihnon_Auth_IUser $user, $new_password) { + $user->changePassword($new_password); + } + + /* + * IPermissionable methods + */ + + public function isAdministrator(Sihnon_Auth_IUser $user) { + // As this class supports fine-grained permissions, map the isAdministrator function to the Superadmin privilege + // to fallback for badly written applications + return $user->hasPermission(Sihnon_Auth_Plugin_Database_Permission::PERM_Administrator); + } + + /* + * IFinelyPermissionable methods + */ + + public function hasPermission(Sihnon_Auth_IUser $user, $permission) { + return new $user->hasPermission($permission); + } + +} + +?> \ No newline at end of file diff --git a/source/lib/SihnonFramework/Auth/Plugin/Database/Group.class.php b/source/lib/SihnonFramework/Auth/Plugin/Database/Group.class.php new file mode 100644 index 0000000..b707c40 --- /dev/null +++ b/source/lib/SihnonFramework/Auth/Plugin/Database/Group.class.php @@ -0,0 +1,12 @@ +username = $username; + $user->password = sha1($password); + $user->last_password_change = time(); + $user->create(); + + return $user; + } + + public function username() { + return $this->username; + } + + public function checkPassword($password) { + return ($this->password == sha1($password)); + } + + public function changePassword($new_password) { + $this->password = sha1($new_password); + $this->save(); + } + + public function groups($ignore_cache = false) { + if ($this->groups === null || $ignore_cache) { + $this->groups = Sihnon_Auth_Plugin_Database_Group::all_for('user', $this->id, 'groups_by_user'); + } + + return $this->groups; + } + + public function permissions($ignore_cache = false) { + if ($this->permissions === null || $ignore_cache) { + $this->permissions = Sihnon_Auth_Plugin_Database_Permission::all_for('user', $this->id, 'permissions_by_user'); + } + + return $this->permissions; + } + + public function hasPermission($permission) { + $permissions = $this->permissions(); + foreach ($permissions as $has_permission) { + if ($permission == $has_permission->id) { + return true; + } + } + + return false; + } + +} + +?> \ No newline at end of file diff --git a/source/lib/SihnonFramework/Auth/Plugin/Database/UserGroup.class.php b/source/lib/SihnonFramework/Auth/Plugin/Database/UserGroup.class.php new file mode 100644 index 0000000..83ef191 --- /dev/null +++ b/source/lib/SihnonFramework/Auth/Plugin/Database/UserGroup.class.php @@ -0,0 +1,13 @@ + 'SihnonFramework/Auth/Plugin/', + Sihnon_Lib => 'Sihnon/Auth/Plugin/', + ); + + public static function init() { + + } + + public static function create(SihnonFramework_Config $config, $plugin) { + self::ensureScanned(); + + if (! self::isValidPlugin($plugin)) { + throw new Sihnon_Exception_InvalidPluginName($plugin); + } + + $classname = self::classname($plugin); + + return call_user_func(array($classname, 'create'), $config); + } + +} + +?> \ No newline at end of file diff --git a/source/lib/SihnonFramework/Exceptions.class.php b/source/lib/SihnonFramework/Exceptions.class.php index d17205d..5ec39c6 100644 --- a/source/lib/SihnonFramework/Exceptions.class.php +++ b/source/lib/SihnonFramework/Exceptions.class.php @@ -39,4 +39,9 @@ class SihnonFramework_Exception_LogException extends SihnonFramework_E class SihnonFramework_Exception_LogFileNotWriteable extends SihnonFramework_Exception_LogException {}; class SihnonFramework_Exception_InvalidLog extends SihnonFramework_Exception_LogException {}; +class SihnonFramework_Exception_AuthException extends SihnonFramework_Exception {}; +class SihnonFramework_Exception_UnknownUser extends SihnonFramework_Exception_AuthException {}; +class SihnonFramework_Exception_IncorrectPassword extends SihnonFramework_Exception_AuthException {}; + + ?> diff --git a/source/lib/SihnonFramework/Main.class.php b/source/lib/SihnonFramework/Main.class.php index 754dbda..ba0062e 100644 --- a/source/lib/SihnonFramework/Main.class.php +++ b/source/lib/SihnonFramework/Main.class.php @@ -17,6 +17,8 @@ class SihnonFramework_Main { protected $database; protected $log; protected $cache; + protected $session; + protected $auth; protected $base_uri; @@ -38,6 +40,9 @@ class SihnonFramework_Main { $this->log = new Sihnon_Log($this->config); $this->cache = new Sihnon_Cache($this->config); + + $this->session = new Sihnon_Session($this->config); + $this->auth = new Sihnon_Auth($this->config, $this->session); } /** @@ -86,6 +91,22 @@ class SihnonFramework_Main { return $this->cache; } + /** + * + * @return SihnonFramework_Session + */ + public function session() { + return $this->session; + } + + /** + * + * @return SihnonFramework_Auth + */ + public function auth() { + return $this->auth; + } + public function baseUri() { return $this->base_uri; } diff --git a/source/lib/SihnonFramework/Session.class.php b/source/lib/SihnonFramework/Session.class.php new file mode 100644 index 0000000..c179b6f --- /dev/null +++ b/source/lib/SihnonFramework/Session.class.php @@ -0,0 +1,61 @@ +config = $config; + $this->dirty = false; + + $this->init(); + } + + public function __destruct() { + $this->teardown(); + } + + protected function init() { + session_start(); + $this->state = $_SESSION; + } + + protected function teardown() { + if ($this->dirty) { + $_SESSION = $this->state; + session_write_close(); + } + } + + public function set($name, $value) { + $this->state[$name] = $value; + $this->dirty = true; + } + + public function get($name, $value, $default = null) { + if ( ! $this->exists($name)) { + return $default; + } + + return $this->state[$name]; + } + + public function exists($name) { + return isset($this->state[$name]); + } + + public function delete($name) { + unset($this->state[$name]); + $this->dirty = true; + } + + public function securityLeveLChanged() { + session_regenerate_id(true); + } + +} + +?> \ No newline at end of file From aaf19079bbebedcee095c61ef6da2346204b1cee Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Mon, 19 Dec 2011 16:06:12 +0000 Subject: [PATCH 08/34] Catch unknown user errors on failed login --- source/lib/SihnonFramework/Auth/Plugin/Database.class.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/lib/SihnonFramework/Auth/Plugin/Database.class.php b/source/lib/SihnonFramework/Auth/Plugin/Database.class.php index 5bdad0f..94bb2bf 100644 --- a/source/lib/SihnonFramework/Auth/Plugin/Database.class.php +++ b/source/lib/SihnonFramework/Auth/Plugin/Database.class.php @@ -31,7 +31,11 @@ class SihnonFramework_Auth_Plugin_Database } public function authenticate($username, $password) { - $user = Sihnon_Auth_Plugin_Database_User::from('username', $username); + try { + $user = Sihnon_Auth_Plugin_Database_User::from('username', $username); + } catch (Sihnon_Exception_ResultCountMismatch $e) { + throw new Sihnon_Exception_UnknownUser(); + } if ( ! $user->checkPassword($password)) { throw new Sihnon_Exception_IncorrectPassword(); From 414b696f6049422eadbf892a2fff9e45cc58379b Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Mon, 19 Dec 2011 19:28:40 +0000 Subject: [PATCH 09/34] Fix bug in save() method's UPDATE query generation --- source/lib/SihnonFramework/DatabaseObject.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/lib/SihnonFramework/DatabaseObject.class.php b/source/lib/SihnonFramework/DatabaseObject.class.php index 1679390..fe08e6a 100644 --- a/source/lib/SihnonFramework/DatabaseObject.class.php +++ b/source/lib/SihnonFramework/DatabaseObject.class.php @@ -141,7 +141,7 @@ abstract class SihnonFramework_DatabaseObject { $id_list = join(', ', array_map(function($v) { return "`{$v}`"; }, $fields)); $value_list = join(', ', array_map(function($v) { return ":{$v}"; }, $fields)); - $database->insert('INSERT INTO `'.static::table().'` ({$id_list}) VALUES({$value_list})', $params); + $database->insert("INSERT INTO `".static::table()."` ({$id_list}) VALUES({$value_list})", $params); $this->id = $database->lastInsertId(); } @@ -169,10 +169,10 @@ abstract class SihnonFramework_DatabaseObject { } } - $id_list = join(', ', array_map(function($v) { return "`{$v}`"; }, $fields)); + $id_list = join(', ', array_map(function($v) { return "`{$v}`=:{$v}"; }, $fields)); $value_list = join(', ', array_map(function($v) { return ":{$v}"; }, $fields)); - $database->update('UPDATE `'.static::table().'` ({$id_list}) VALUES({$value_list}) WHERE `id`=:id', $params); + $database->update("UPDATE `".static::table()."` SET {$id_list} WHERE `id`=:id", $params); } public function delete() { From e30535f88b772c8912e2841c47bf09ce766f94be Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Mon, 19 Dec 2011 19:29:02 +0000 Subject: [PATCH 10/34] Expose changePassword() method through the Auth object --- source/lib/SihnonFramework/Auth.class.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/source/lib/SihnonFramework/Auth.class.php b/source/lib/SihnonFramework/Auth.class.php index 38b71ed..f5b54ad 100644 --- a/source/lib/SihnonFramework/Auth.class.php +++ b/source/lib/SihnonFramework/Auth.class.php @@ -18,7 +18,7 @@ class SihnonFramework_Auth { } protected function init($backend) { - $this->backend = Sihnon_Auth_PluginFactory::create($config, $backend); + $this->backend = Sihnon_Auth_PluginFactory::create($this->config, $backend); $this->restoreSession(); } @@ -26,6 +26,10 @@ class SihnonFramework_Auth { return $this->authenticated; } + public function authenticatedUser() { + return $this->user; + } + public function saveSession() { if ($this->user) { $this->session->set('user.id', $this->user->username()); @@ -81,6 +85,10 @@ class SihnonFramework_Auth { $this->authenticated = false; } + public function changePassword($new_password) { + $this->backend->changePassword($this->user, $new_password); + } + /* * IPermissionable methods */ From 664d5e6923d7f821523874819267059aa9677619 Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Tue, 20 Dec 2011 00:33:53 +0000 Subject: [PATCH 11/34] Expose backend listUsers via Auth class --- source/lib/SihnonFramework/Auth.class.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/lib/SihnonFramework/Auth.class.php b/source/lib/SihnonFramework/Auth.class.php index f5b54ad..383168b 100644 --- a/source/lib/SihnonFramework/Auth.class.php +++ b/source/lib/SihnonFramework/Auth.class.php @@ -56,6 +56,10 @@ class SihnonFramework_Auth { * IPlugin methods */ + public function listUsers() { + return $this->backend->listUsers(); + } + public function authenticate($username, $password) { $this->user = $this->backend->authenticate($username, $password); $this->authenticated = true; From 5584e8e4d81ebcb18928500ce8f37271b2e0d11d Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Tue, 20 Dec 2011 00:34:20 +0000 Subject: [PATCH 12/34] Add a DateTime class to expose a fuzzyTime method --- source/lib/SihnonFramework/DateTime.class.php | 119 ++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 source/lib/SihnonFramework/DateTime.class.php diff --git a/source/lib/SihnonFramework/DateTime.class.php b/source/lib/SihnonFramework/DateTime.class.php new file mode 100644 index 0000000..8de5602 --- /dev/null +++ b/source/lib/SihnonFramework/DateTime.class.php @@ -0,0 +1,119 @@ + 'one', + 2 => 'two', + 3 => 'three', + 4 => 'four', + 5 => 'five', + 6 => 'six', + 7 => 'seven', + 8 => 'eight', + 9 => 'nine', + 10 => 'ten', + 11 => 'eleven' + ); + + // today + if ($sod_now == $sod) { + if ($time > $now - (self::MINUTE * 3)) { + return 'just a moment ago'; + } else if ($time > $now - (self::MINUTE * 7)) { + return 'a few minutes ago'; + } else if ($time > $now - (self::HOUR)) { + return 'less than an hour ago'; + } + return 'today at ' . date('g:ia', $time); + } + + // yesterday + if (($sod_now - $sod) <= self::DAY) { + if (date('i', $time) > (self::MINUTE + 30)) { + $time += self::HOUR / 2; + } + return 'yesterday around ' . date('ga', $time); + } + + // within the last 5 days + if (($sod_now - $sod) <= (self::DAY * 5)) { + $str = date('l', $time); + $hour = date('G', $time); + if ($hour < 12) { + $str .= ' morning'; + } else if ($hour < 17) { + $str .= ' afternoon'; + } else if ($hour < 20) { + $str .= ' evening'; + } else { + $str .= ' night'; + } + return $str; + } + + // number of weeks (between 1 and 3)... + if (($sod_now-$sod) < (self::WEEK * 3.5)) { + if (($sod_now-$sod) < (self::WEEK * 1.5)) { + return 'about a week ago'; + } else if (($sod_now-$sod) < (self::DAY * 2.5)) { + return 'about two weeks ago'; + } else { + return 'about three weeks ago'; + } + } + + // number of months (between 1 and 11)... + if (($sod_now-$sod) < (self::MONTH * 11.5)) { + for ($i = (self::WEEK * 3.5), $m=0; $i < self::YEAR; $i += self::MONTH, $m++) { + if ( ($sod_now-$sod) <= $i ) { + return 'about ' . $convert[$m] . ' month' . (($m>1)?'s':'') . ' ago'; + } + } + } + + // number of years... + for ($i = (self::MONTH * 11.5), $y=0; $i < (self::YEAR * 10); $i += self::YEAR, $y++) { + if (($sod_now-$sod) <= $i) { + return 'about ' . $convert[$y] . ' year' . (($y>1)?'s':'') . ' ago'; + } + } + + // more than ten years... + return 'more than ten years ago'; + } + +} + +?> \ No newline at end of file From 1a490a0ae00081e69fc9a51a08d9c0e2168b9cb7 Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Tue, 20 Dec 2011 01:41:48 +0000 Subject: [PATCH 13/34] Bug fix in Auth->hasPermission() --- source/lib/SihnonFramework/Auth/Plugin/Database.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/lib/SihnonFramework/Auth/Plugin/Database.class.php b/source/lib/SihnonFramework/Auth/Plugin/Database.class.php index 94bb2bf..6200d0b 100644 --- a/source/lib/SihnonFramework/Auth/Plugin/Database.class.php +++ b/source/lib/SihnonFramework/Auth/Plugin/Database.class.php @@ -79,7 +79,7 @@ class SihnonFramework_Auth_Plugin_Database */ public function hasPermission(Sihnon_Auth_IUser $user, $permission) { - return new $user->hasPermission($permission); + return $user->hasPermission($permission); } } From 5181fe1b4c8cfe9d25d8d930cc0c96a7734e6e8f Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Tue, 20 Dec 2011 01:42:21 +0000 Subject: [PATCH 14/34] Add support for 401 errors in the templating system --- source/lib/SihnonFramework/Exceptions.class.php | 1 + source/lib/SihnonFramework/Page.class.php | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/source/lib/SihnonFramework/Exceptions.class.php b/source/lib/SihnonFramework/Exceptions.class.php index 5ec39c6..0d90461 100644 --- a/source/lib/SihnonFramework/Exceptions.class.php +++ b/source/lib/SihnonFramework/Exceptions.class.php @@ -13,6 +13,7 @@ class SihnonFramework_Exception_TemplateException extends SihnonFramework_E class SihnonFramework_Exception_AbortEntirePage extends SihnonFramework_Exception_TemplateException {}; class SihnonFramework_Exception_Unauthorized extends SihnonFramework_Exception_TemplateException {}; class SihnonFramework_Exception_FileNotFound extends SihnonFramework_Exception_TemplateException {}; +class SihnonFramework_Exception_NotAuthorised extends SihnonFramework_Exception_TemplateException {}; class SihnonFramework_Exception_InvalidParameters extends SihnonFramework_Exception_TemplateException {}; class SihnonFramework_Exception_DatabaseException extends SihnonFramework_Exception {}; diff --git a/source/lib/SihnonFramework/Page.class.php b/source/lib/SihnonFramework/Page.class.php index 5de45ca..8bd37d2 100644 --- a/source/lib/SihnonFramework/Page.class.php +++ b/source/lib/SihnonFramework/Page.class.php @@ -41,7 +41,9 @@ class SihnonFramework_Page { } catch (SihnonFramework_Exception_AbortEntirePage $e) { return false; } catch (SihnonFramework_Exception_FileNotFound $e) { - $content = $this->render('errors/404.tpl', 'errors/404.php'); + $content = $this->render('errors/404.tpl', 'errors/404.php'); + } catch (SihnonFramework_Exception_NotAuthorised $e) { + $content = $this->render('errors/401.tpl', 'errors/404.php'); } catch (SihnonFramework_Exception $e) { $content = $this->render('errors/unhandled-exception.tpl', 'errors/unhandled-exception.php', array( 'exception' => $e, From fd2f3af5d001e5923b19c7ffc5def5ce68092d61 Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Tue, 20 Dec 2011 19:10:22 +0000 Subject: [PATCH 15/34] Add support for custom WHERE restrictions DatabaseObject::all_for() now supports additional constraints (with variables) to further filter the results returned. --- .../SihnonFramework/DatabaseObject.class.php | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/source/lib/SihnonFramework/DatabaseObject.class.php b/source/lib/SihnonFramework/DatabaseObject.class.php index fe08e6a..45bcae4 100644 --- a/source/lib/SihnonFramework/DatabaseObject.class.php +++ b/source/lib/SihnonFramework/DatabaseObject.class.php @@ -79,7 +79,7 @@ abstract class SihnonFramework_DatabaseObject { return $objects; } - public static function all_for($field, $value, $view = null) { + public static function all_for($field, $value, $view = null, $additional_conditions = null, $additional_params = null) { $database = SihnonFramework_Main::instance()->database(); if ($view === null) { @@ -99,9 +99,18 @@ abstract class SihnonFramework_DatabaseObject { $field_list = join(', ', array_map(function($v) { return "`{$v}`"; }, $fields));$objects = array(); - foreach ($database->selectList("SELECT {$field_list} FROM `{$view}` WHERE `{$field}`=:{$field} ORDER BY `id` DESC", array( - array('name' => $field, 'value' => $value, 'type' => PDO::PARAM_STR), - )) as $row) { + $params = array( + array('name' => $field, 'value' => $value, 'type' => PDO::PARAM_STR), + ); + if ($additional_params) { + $params = array_merge($params, $additional_params); + } + + if ($additional_conditions) { + $conditions = "AND ({$additional_conditions}) "; + } + + foreach ($database->selectList("SELECT {$field_list} FROM `{$view}` WHERE `{$field}`=:{$field} {$conditions} ORDER BY `id` DESC", $params) as $row) { $objects[] = static::fromDatabaseRow($row); } From 38b687f420bd2cbb14737648808bb1b949c506aa Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Wed, 21 Dec 2011 11:22:08 +0000 Subject: [PATCH 16/34] Fix naming convention for class methods --- .../lib/SihnonFramework/Auth/Plugin/Database/User.class.php | 4 ++-- source/lib/SihnonFramework/DatabaseObject.class.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/lib/SihnonFramework/Auth/Plugin/Database/User.class.php b/source/lib/SihnonFramework/Auth/Plugin/Database/User.class.php index aed9115..606b89f 100644 --- a/source/lib/SihnonFramework/Auth/Plugin/Database/User.class.php +++ b/source/lib/SihnonFramework/Auth/Plugin/Database/User.class.php @@ -44,7 +44,7 @@ class SihnonFramework_Auth_Plugin_Database_User extends Sihnon_DatabaseObject im public function groups($ignore_cache = false) { if ($this->groups === null || $ignore_cache) { - $this->groups = Sihnon_Auth_Plugin_Database_Group::all_for('user', $this->id, 'groups_by_user'); + $this->groups = Sihnon_Auth_Plugin_Database_Group::allFor('user', $this->id, 'groups_by_user'); } return $this->groups; @@ -52,7 +52,7 @@ class SihnonFramework_Auth_Plugin_Database_User extends Sihnon_DatabaseObject im public function permissions($ignore_cache = false) { if ($this->permissions === null || $ignore_cache) { - $this->permissions = Sihnon_Auth_Plugin_Database_Permission::all_for('user', $this->id, 'permissions_by_user'); + $this->permissions = Sihnon_Auth_Plugin_Database_Permission::allFor('user', $this->id, 'permissions_by_user'); } return $this->permissions; diff --git a/source/lib/SihnonFramework/DatabaseObject.class.php b/source/lib/SihnonFramework/DatabaseObject.class.php index 45bcae4..3139676 100644 --- a/source/lib/SihnonFramework/DatabaseObject.class.php +++ b/source/lib/SihnonFramework/DatabaseObject.class.php @@ -79,7 +79,7 @@ abstract class SihnonFramework_DatabaseObject { return $objects; } - public static function all_for($field, $value, $view = null, $additional_conditions = null, $additional_params = null) { + public static function allFor($field, $value, $view = null, $additional_conditions = null, $additional_params = null) { $database = SihnonFramework_Main::instance()->database(); if ($view === null) { @@ -155,7 +155,7 @@ abstract class SihnonFramework_DatabaseObject { $this->id = $database->lastInsertId(); } - protected function save() { + public function save() { $database = SihnonFramework_Main::instance()->database(); $class = new ReflectionClass(get_called_class()); From 3a81b6fe400c53101a19e3ff7452adb651954009 Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Thu, 22 Dec 2011 11:33:20 +0000 Subject: [PATCH 17/34] Added a Formatting class --- .../lib/SihnonFramework/Formatting.class.php | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 source/lib/SihnonFramework/Formatting.class.php diff --git a/source/lib/SihnonFramework/Formatting.class.php b/source/lib/SihnonFramework/Formatting.class.php new file mode 100644 index 0000000..4a5c6b8 --- /dev/null +++ b/source/lib/SihnonFramework/Formatting.class.php @@ -0,0 +1,22 @@ + \ No newline at end of file From c570a6b026fecd67beee295f357a71a20bced67a Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Thu, 22 Dec 2011 22:01:57 +0000 Subject: [PATCH 18/34] Remove superfluous parameter to eliminate warning --- source/lib/SihnonFramework/Session.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/lib/SihnonFramework/Session.class.php b/source/lib/SihnonFramework/Session.class.php index c179b6f..a75587d 100644 --- a/source/lib/SihnonFramework/Session.class.php +++ b/source/lib/SihnonFramework/Session.class.php @@ -35,7 +35,7 @@ class SihnonFramework_Session { $this->dirty = true; } - public function get($name, $value, $default = null) { + public function get($name, $default = null) { if ( ! $this->exists($name)) { return $default; } From 2cddde6d08ca8830ffc3e9376abe3d1bc6c10112 Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Thu, 22 Dec 2011 22:02:23 +0000 Subject: [PATCH 19/34] Fix conditional passing in DatabaseObject --- source/lib/SihnonFramework/DatabaseObject.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/source/lib/SihnonFramework/DatabaseObject.class.php b/source/lib/SihnonFramework/DatabaseObject.class.php index 3139676..5c7df91 100644 --- a/source/lib/SihnonFramework/DatabaseObject.class.php +++ b/source/lib/SihnonFramework/DatabaseObject.class.php @@ -106,6 +106,7 @@ abstract class SihnonFramework_DatabaseObject { $params = array_merge($params, $additional_params); } + $conditions = ''; if ($additional_conditions) { $conditions = "AND ({$additional_conditions}) "; } From 8c352938e9ae8c1b46351644b14861fc2f3b755b Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Thu, 22 Dec 2011 22:04:21 +0000 Subject: [PATCH 20/34] Fix call to base class method --- source/lib/SihnonFramework/Auth/Plugin/Database/User.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/lib/SihnonFramework/Auth/Plugin/Database/User.class.php b/source/lib/SihnonFramework/Auth/Plugin/Database/User.class.php index 606b89f..c9fa180 100644 --- a/source/lib/SihnonFramework/Auth/Plugin/Database/User.class.php +++ b/source/lib/SihnonFramework/Auth/Plugin/Database/User.class.php @@ -16,7 +16,7 @@ class SihnonFramework_Auth_Plugin_Database_User extends Sihnon_DatabaseObject im protected $permissions = null; public static function exists($username) { - return static::exists('username', $username); + return parent::exists('username', $username); } public static function add($username, $password) { From 04f97649049370b2335089623629503161f9097d Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Fri, 23 Dec 2011 01:32:08 +0000 Subject: [PATCH 21/34] Make pluralise argument order more intuitive --- source/lib/SihnonFramework/Formatting.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/lib/SihnonFramework/Formatting.class.php b/source/lib/SihnonFramework/Formatting.class.php index 4a5c6b8..f8ce086 100644 --- a/source/lib/SihnonFramework/Formatting.class.php +++ b/source/lib/SihnonFramework/Formatting.class.php @@ -10,7 +10,7 @@ class SihnonFramework_Formatting { return SihnonFramework_Main::formatDuration($seconds, $fuzziness); } - public static function pluralise($singular, $multiple, $count) { + public static function pluralise($count, $singular, $multiple) { if ($count == 1) { return $singular; } else{ From 786076b5c6ddc0d0ec6e1a52ac779170ddd8294d Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Fri, 23 Dec 2011 01:32:21 +0000 Subject: [PATCH 22/34] Add features on allFor to all and improve code through reuse. --- .../SihnonFramework/DatabaseObject.class.php | 41 +++++++++++-------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/source/lib/SihnonFramework/DatabaseObject.class.php b/source/lib/SihnonFramework/DatabaseObject.class.php index 5c7df91..c4fd3bd 100644 --- a/source/lib/SihnonFramework/DatabaseObject.class.php +++ b/source/lib/SihnonFramework/DatabaseObject.class.php @@ -68,18 +68,7 @@ abstract class SihnonFramework_DatabaseObject { * * @return SihnonFramework_DatabaseObject */ - public static function all() { - $database = SihnonFramework_Main::instance()->database(); - - $objects = array(); - foreach ($database->selectList('SELECT * FROM `'.static::table().'` WHERE `id` > 0 ORDER BY `id` DESC') as $row) { - $objects[] = static::fromDatabaseRow($row); - } - - return $objects; - } - - public static function allFor($field, $value, $view = null, $additional_conditions = null, $additional_params = null) { + public static function all($view = null, $additional_conditions = null, $additional_params = null) { $database = SihnonFramework_Main::instance()->database(); if ($view === null) { @@ -97,11 +86,9 @@ abstract class SihnonFramework_DatabaseObject { } } - $field_list = join(', ', array_map(function($v) { return "`{$v}`"; }, $fields));$objects = array(); + $field_list = join(', ', array_map(function($v) { return "`{$v}`"; }, $fields)); - $params = array( - array('name' => $field, 'value' => $value, 'type' => PDO::PARAM_STR), - ); + $params = array(); if ($additional_params) { $params = array_merge($params, $additional_params); } @@ -111,13 +98,31 @@ abstract class SihnonFramework_DatabaseObject { $conditions = "AND ({$additional_conditions}) "; } - foreach ($database->selectList("SELECT {$field_list} FROM `{$view}` WHERE `{$field}`=:{$field} {$conditions} ORDER BY `id` DESC", $params) as $row) { + $objects = array(); + $sql = "SELECT {$field_list} FROM `{$view}` WHERE `id` > 0 {$conditions} ORDER BY `id` DESC"; + foreach ($database->selectList($sql, $params) as $row) { $objects[] = static::fromDatabaseRow($row); } - + return $objects; } + public static function allFor($field, $value, $view = null, $additional_conditions = null, $additional_params = null) { + $conditions = "`{$field}`=:{$field} "; + if ($additional_conditions) { + $conditions .= "AND ({$additional_conditions}) "; + } + + $params = array( + array('name' => $field, 'value' => $value, 'type' => PDO::PARAM_STR), + ); + if ($additional_params) { + $params = array_merge($params, $additional_params); + } + + return static::all($view, $conditions, $params); + } + public static function exists($field, $value, $view = null) { $database = Sihnon_Main::instance()->database(); From da57ccf8dea668f456d663f2fdf8e10ecd27aef9 Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Mon, 26 Dec 2011 00:52:10 +0000 Subject: [PATCH 23/34] Added first attempt at input validation framework --- .../lib/SihnonFramework/Exceptions.class.php | 3 + .../lib/SihnonFramework/Validation.class.php | 9 +++ .../SihnonFramework/Validation/Text.class.php | 55 +++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 source/lib/SihnonFramework/Validation.class.php create mode 100644 source/lib/SihnonFramework/Validation/Text.class.php diff --git a/source/lib/SihnonFramework/Exceptions.class.php b/source/lib/SihnonFramework/Exceptions.class.php index 0d90461..f7bfa87 100644 --- a/source/lib/SihnonFramework/Exceptions.class.php +++ b/source/lib/SihnonFramework/Exceptions.class.php @@ -44,5 +44,8 @@ class SihnonFramework_Exception_AuthException extends SihnonFramework_E class SihnonFramework_Exception_UnknownUser extends SihnonFramework_Exception_AuthException {}; class SihnonFramework_Exception_IncorrectPassword extends SihnonFramework_Exception_AuthException {}; +class SihnonFramework_Exception_ValidationException extends SihnonFramework_Exception {}; +class SihnonFramework_Exception_InvalidContent extends SihnonFramework_ValidationException {}; +class SihnonFramework_Exception_InvalidLength extends SihnonFramework_ValidationoException {}; ?> diff --git a/source/lib/SihnonFramework/Validation.class.php b/source/lib/SihnonFramework/Validation.class.php new file mode 100644 index 0000000..f9ac15f --- /dev/null +++ b/source/lib/SihnonFramework/Validation.class.php @@ -0,0 +1,9 @@ + \ No newline at end of file diff --git a/source/lib/SihnonFramework/Validation/Text.class.php b/source/lib/SihnonFramework/Validation/Text.class.php new file mode 100644 index 0000000..a906505 --- /dev/null +++ b/source/lib/SihnonFramework/Validation/Text.class.php @@ -0,0 +1,55 @@ + ':alpha:', + static::Digit => ':digit:', + static::Numeric => ':digit:\.-', + static::Symbol => ':punct:', + static::Whitespace => ':space:', + ); + + public static function charset($input, $charset = static::Defaults) { + static::pattern($input, static::buildCharsetPattern($charset)); + } + + public static function length($input, $min_length = null, $max_length = null) { + $length = strlen($input); + + if ($min_length !== null && $length < $min_length) { + throw new SihnonFramework_Exception_InvalidLength(); + } + + if ($max_length !== null && $length > $max_length) { + throw new SihnonFramework_Exception_InvalidLength(); + } + } + + public static function pattern($input, $pattern) { + if ( ! preg_match($pattern, $input)) { + throw new SihnonFramework_Exception_InvalidContent(); + } + } + + protected static function buildCharsetPattern($charset) { + $classes = ''; + foreach (static::$charsets as $set => $class) { + if ($charset & $set) { + $classes .= $class; + } + } + + return "/^[{$classes}]*$/"; + } + +} + +?> \ No newline at end of file From 990effc237a9e32bff11fd4bb0c4b7e934355b17 Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Mon, 26 Dec 2011 00:56:54 +0000 Subject: [PATCH 24/34] Extend text validation to accept multiple inputs --- .../SihnonFramework/Validation/Text.class.php | 36 ++++++++++++------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/source/lib/SihnonFramework/Validation/Text.class.php b/source/lib/SihnonFramework/Validation/Text.class.php index a906505..d6a853a 100644 --- a/source/lib/SihnonFramework/Validation/Text.class.php +++ b/source/lib/SihnonFramework/Validation/Text.class.php @@ -17,25 +17,37 @@ class SihnonFramework_Validation_Text extends SihnonFramework_Validation { static::Whitespace => ':space:', ); - public static function charset($input, $charset = static::Defaults) { - static::pattern($input, static::buildCharsetPattern($charset)); + public static function charset($inputs, $charset = static::Defaults) { + static::pattern($inputs, static::buildCharsetPattern($charset)); } - public static function length($input, $min_length = null, $max_length = null) { - $length = strlen($input); - - if ($min_length !== null && $length < $min_length) { - throw new SihnonFramework_Exception_InvalidLength(); + public static function length($inputs, $min_length = null, $max_length = null) { + if ( ! is_array($inputs)) { + $inputs = array($inputs); } - if ($max_length !== null && $length > $max_length) { - throw new SihnonFramework_Exception_InvalidLength(); + foreach ($inputs as $input) { + $length = strlen($input); + + if ($min_length !== null && $length < $min_length) { + throw new SihnonFramework_Exception_InvalidLength(); + } + + if ($max_length !== null && $length > $max_length) { + throw new SihnonFramework_Exception_InvalidLength(); + } } } - public static function pattern($input, $pattern) { - if ( ! preg_match($pattern, $input)) { - throw new SihnonFramework_Exception_InvalidContent(); + public static function pattern($inputs, $pattern) { + if ( ! is_array($inputs)) { + $inputs = array($inputs); + } + + foreach ($inputs as $input) { + if ( ! preg_match($pattern, $input)) { + throw new SihnonFramework_Exception_InvalidContent(); + } } } From 977254fa1dd69d0299f22bd323eaa37a190e177d Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Mon, 26 Dec 2011 00:58:19 +0000 Subject: [PATCH 25/34] Rename charsets test to contents --- source/lib/SihnonFramework/Validation/Text.class.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/source/lib/SihnonFramework/Validation/Text.class.php b/source/lib/SihnonFramework/Validation/Text.class.php index d6a853a..e6ac68f 100644 --- a/source/lib/SihnonFramework/Validation/Text.class.php +++ b/source/lib/SihnonFramework/Validation/Text.class.php @@ -9,7 +9,7 @@ class SihnonFramework_Validation_Text extends SihnonFramework_Validation { const Symbol = 0x08; const Whitespace = 0x16; - protected static $charsets = array( + protected static $contents = array( static::Alphabetical => ':alpha:', static::Digit => ':digit:', static::Numeric => ':digit:\.-', @@ -17,8 +17,8 @@ class SihnonFramework_Validation_Text extends SihnonFramework_Validation { static::Whitespace => ':space:', ); - public static function charset($inputs, $charset = static::Defaults) { - static::pattern($inputs, static::buildCharsetPattern($charset)); + public static function content($inputs, $content = static::Defaults) { + static::pattern($inputs, static::buildContentPattern($content)); } public static function length($inputs, $min_length = null, $max_length = null) { @@ -51,10 +51,10 @@ class SihnonFramework_Validation_Text extends SihnonFramework_Validation { } } - protected static function buildCharsetPattern($charset) { + protected static function buildContentPattern($contents) { $classes = ''; - foreach (static::$charsets as $set => $class) { - if ($charset & $set) { + foreach (static::$contents as $set => $class) { + if ($contents & $set) { $classes .= $class; } } From 1cc440a885a494ac7eccff4d137f38d9f44b14b0 Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Mon, 26 Dec 2011 01:11:37 +0000 Subject: [PATCH 26/34] Fix typo in exception names --- source/lib/SihnonFramework/Exceptions.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/lib/SihnonFramework/Exceptions.class.php b/source/lib/SihnonFramework/Exceptions.class.php index f7bfa87..bf0b0a0 100644 --- a/source/lib/SihnonFramework/Exceptions.class.php +++ b/source/lib/SihnonFramework/Exceptions.class.php @@ -45,7 +45,7 @@ class SihnonFramework_Exception_UnknownUser extends SihnonFramework_E class SihnonFramework_Exception_IncorrectPassword extends SihnonFramework_Exception_AuthException {}; class SihnonFramework_Exception_ValidationException extends SihnonFramework_Exception {}; -class SihnonFramework_Exception_InvalidContent extends SihnonFramework_ValidationException {}; -class SihnonFramework_Exception_InvalidLength extends SihnonFramework_ValidationoException {}; +class SihnonFramework_Exception_InvalidContent extends SihnonFramework_Exception_ValidationException {}; +class SihnonFramework_Exception_InvalidLength extends SihnonFramework_Exception_ValidationException {}; ?> From 62d5614bb499a6e35310b4629f828c210e78f28a Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Mon, 26 Dec 2011 01:11:58 +0000 Subject: [PATCH 27/34] Fix bug in compile-time statics --- source/lib/SihnonFramework/Validation/Text.class.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/source/lib/SihnonFramework/Validation/Text.class.php b/source/lib/SihnonFramework/Validation/Text.class.php index e6ac68f..1a1a092 100644 --- a/source/lib/SihnonFramework/Validation/Text.class.php +++ b/source/lib/SihnonFramework/Validation/Text.class.php @@ -10,14 +10,14 @@ class SihnonFramework_Validation_Text extends SihnonFramework_Validation { const Whitespace = 0x16; protected static $contents = array( - static::Alphabetical => ':alpha:', - static::Digit => ':digit:', - static::Numeric => ':digit:\.-', - static::Symbol => ':punct:', - static::Whitespace => ':space:', + self::Alphabetical => ':alpha:', + self::Digit => ':digit:', + self::Numeric => ':digit:\.-', + self::Symbol => ':punct:', + self::Whitespace => ':space:', ); - public static function content($inputs, $content = static::Defaults) { + public static function content($inputs, $content = self::Defaults) { static::pattern($inputs, static::buildContentPattern($content)); } From 295e0045f536e0b9da8cea212669fba7441475c0 Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Thu, 29 Dec 2011 17:55:46 +0000 Subject: [PATCH 28/34] Fix character class definitions --- source/lib/SihnonFramework/Validation/Text.class.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/lib/SihnonFramework/Validation/Text.class.php b/source/lib/SihnonFramework/Validation/Text.class.php index 1a1a092..acb60c7 100644 --- a/source/lib/SihnonFramework/Validation/Text.class.php +++ b/source/lib/SihnonFramework/Validation/Text.class.php @@ -10,11 +10,11 @@ class SihnonFramework_Validation_Text extends SihnonFramework_Validation { const Whitespace = 0x16; protected static $contents = array( - self::Alphabetical => ':alpha:', - self::Digit => ':digit:', - self::Numeric => ':digit:\.-', - self::Symbol => ':punct:', - self::Whitespace => ':space:', + self::Alphabetical => '[:alpha:]', + self::Digit => '[:digit:]', + self::Numeric => '[:digit:]\.-', + self::Symbol => '[:punct:]', + self::Whitespace => '[:space:]', ); public static function content($inputs, $content = self::Defaults) { From 7bee3e83bae0a903615cf6c0adfa1b5bff6bc98b Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Thu, 29 Dec 2011 17:56:06 +0000 Subject: [PATCH 29/34] Add Enum validation for class constants --- .../SihnonFramework/Validation/Enum.class.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 source/lib/SihnonFramework/Validation/Enum.class.php diff --git a/source/lib/SihnonFramework/Validation/Enum.class.php b/source/lib/SihnonFramework/Validation/Enum.class.php new file mode 100644 index 0000000..feecc5e --- /dev/null +++ b/source/lib/SihnonFramework/Validation/Enum.class.php @@ -0,0 +1,19 @@ + \ No newline at end of file From 671b87a211de755a6b549e17ebb1905892019a86 Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Fri, 30 Dec 2011 12:59:51 +0000 Subject: [PATCH 30/34] Add placeholder FlatFile Auth classes --- .../Auth/Plugin/FlatFile.class.php | 71 +++++++++++++++++++ .../Auth/Plugin/FlatFile/User.class.php | 35 +++++++++ 2 files changed, 106 insertions(+) create mode 100644 source/lib/SihnonFramework/Auth/Plugin/FlatFile.class.php create mode 100644 source/lib/SihnonFramework/Auth/Plugin/FlatFile/User.class.php diff --git a/source/lib/SihnonFramework/Auth/Plugin/FlatFile.class.php b/source/lib/SihnonFramework/Auth/Plugin/FlatFile.class.php new file mode 100644 index 0000000..7480d9e --- /dev/null +++ b/source/lib/SihnonFramework/Auth/Plugin/FlatFile.class.php @@ -0,0 +1,71 @@ +config = $config; + } + + /* + * IPlugin methods + */ + + public static function create(SihnonFramework_Config $config) { + return new self($config); + } + + public function userExists($username) { + return Sihnon_Auth_Plugin_FlatFile_User::exists($username); + } + + public function listUsers() { + return Sihnon_Auth_Plugin_FlatFile_User::all(); + } + + public function authenticate($username, $password) { + $user = Sihnon_Auth_Plugin_FlatFile_User::load($username); + + if ( ! $user->checkPassword($password)) { + throw new Sihnon_Exception_IncorrectPassword(); + } + + return $user; + } + + public function authenticateSession($username) { + return Sihnon_Auth_Plugin_FlatFile_User::load($username); + } + + /* + * IUpdateable methods + */ + + public function addUser($username, $password) { + return Sihnon_Auth_Plugin_Database_User::add($username, $password); + } + + public function removeUser(Sihnon_Auth_IUser $user) { + $user->delete(); + } + + public function changePassword(Sihnon_Auth_IUser $user, $new_password) { + $user->changePassword($new_password); + } + + /* + * IPermissionable methods + */ + + public function isAdministrator(Sihnon_Auth_IUser $user) { + return $user->isAdministrator(); + } + +} + +?> \ No newline at end of file diff --git a/source/lib/SihnonFramework/Auth/Plugin/FlatFile/User.class.php b/source/lib/SihnonFramework/Auth/Plugin/FlatFile/User.class.php new file mode 100644 index 0000000..4f5a80f --- /dev/null +++ b/source/lib/SihnonFramework/Auth/Plugin/FlatFile/User.class.php @@ -0,0 +1,35 @@ +username; + } + + public function checkPassword($password) { + return ($this->password == sha1($password)); + } + + public function changePassword($new_password) { + throw new SihnonFramework_Exception_NotImplemented(); + } + + public function isAdministrator() { + throw new SihnonFramework_Exception_NotImplemented(); + } + +} + +?> \ No newline at end of file From 830ab78a45835533d9479a8b72d4c7ed01e6224f Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Fri, 30 Dec 2011 13:11:46 +0000 Subject: [PATCH 31/34] Fix base_uri calculation when using site root --- source/lib/SihnonFramework/Main.class.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/lib/SihnonFramework/Main.class.php b/source/lib/SihnonFramework/Main.class.php index ba0062e..1a17a0f 100644 --- a/source/lib/SihnonFramework/Main.class.php +++ b/source/lib/SihnonFramework/Main.class.php @@ -23,7 +23,8 @@ class SihnonFramework_Main { protected $base_uri; protected function __construct() { - $this->base_uri = dirname($_SERVER['SCRIPT_NAME']) . '/'; + $dirname = dirname($_SERVER['SCRIPT_NAME']); + $this->base_uri = $dirname == '/' ? '/' : $dirname . '/'; } protected function init() { From f5187de9f44b28c0655dc000b7758ac41463ad89 Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Sat, 31 Dec 2011 01:15:54 +0000 Subject: [PATCH 32/34] Fix arguments to proc_open --- source/lib/SihnonFramework/ForegroundTask.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/lib/SihnonFramework/ForegroundTask.class.php b/source/lib/SihnonFramework/ForegroundTask.class.php index 3434c4f..837a2fc 100644 --- a/source/lib/SihnonFramework/ForegroundTask.class.php +++ b/source/lib/SihnonFramework/ForegroundTask.class.php @@ -35,7 +35,7 @@ class SihnonFramework_ForegroundTask { ); $pipes = array(); - $process = proc_open($command, $descriptors, $pipes); + $process = proc_open($command, $descriptors, $pipes, $cwd, $env); stream_set_blocking($pipes[self::PIPE_STDIN], 0); // Make stdin/stdout/stderr non-blocking stream_set_blocking($pipes[self::PIPE_STDOUT], 0); From c7077a8813a95d602c1cbab0f95c8ac7e864f45f Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Sat, 31 Dec 2011 01:16:22 +0000 Subject: [PATCH 33/34] Add options for customising Session parameters --- source/lib/SihnonFramework/Session.class.php | 27 +++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/source/lib/SihnonFramework/Session.class.php b/source/lib/SihnonFramework/Session.class.php index a75587d..b6b3ccb 100644 --- a/source/lib/SihnonFramework/Session.class.php +++ b/source/lib/SihnonFramework/Session.class.php @@ -4,13 +4,19 @@ class SihnonFramework_Session { protected $config; + protected $enabled; protected $state; protected $dirty; public function __construct(Sihnon_Config $config) { $this->config = $config; + $this->enabled = false; $this->dirty = false; + if ($this->config->exists('sessions') && $this->config->get('sessions')) { + $this->enabled = true; + } + $this->init(); } @@ -19,12 +25,23 @@ class SihnonFramework_Session { } protected function init() { - session_start(); - $this->state = $_SESSION; + if ($this->enabled) { + session_start(); + $this->state = $_SESSION; + + // Override the session parameters if configured + $params = session_get_cookie_params(); + $lifetime = $this->config->exists('sessions.lifetime') ? $this->config->get('sessions.lifetime') : $params['lifetime']; + $path = $this->config->exists('sessions.path') ? $this->config->get('sessions.path') : $params['path']; + $domain = $this->config->exists('sessions.domain') ? $this->config->get('sessions.domain') : $params['domain']; + $secure = $this->config->exists('sessions.secure') ? $this->config->get('sessions.secure') : $params['secure']; + $httponly = $this->config->exists('sessions.http-only') ? $this->config->get('sessions.http-only') : $params['httponly']; + session_set_cookie_params($lifetime, $path, $domain, $secure, $httponly); + } } protected function teardown() { - if ($this->dirty) { + if ($this->enabled && $this->dirty) { $_SESSION = $this->state; session_write_close(); } @@ -53,7 +70,9 @@ class SihnonFramework_Session { } public function securityLeveLChanged() { - session_regenerate_id(true); + if ($this->enabled) { + session_regenerate_id(true); + } } } From cef9d803cb2cef11d69d6b77fb1ba5c600ec50cc Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Sat, 31 Dec 2011 02:09:26 +0000 Subject: [PATCH 34/34] Add daemon for process locking --- source/lib/SihnonFramework/Daemon.class.php | 50 +++++++++++++++++++ .../lib/SihnonFramework/Exceptions.class.php | 4 ++ 2 files changed, 54 insertions(+) create mode 100644 source/lib/SihnonFramework/Daemon.class.php diff --git a/source/lib/SihnonFramework/Daemon.class.php b/source/lib/SihnonFramework/Daemon.class.php new file mode 100644 index 0000000..0fc3d5b --- /dev/null +++ b/source/lib/SihnonFramework/Daemon.class.php @@ -0,0 +1,50 @@ +config = $config; + $this->lock_file = $config->get('daemon.lock-file'); + $this->lock = null; + $this->locked = false; + + $this->init(); + } + + public function __destruct() { + $this->teardown(); + } + + protected function init() { + $this->lock = fopen($this->lock_file, 'w'); + $wouldBlock = false; + + $result = flock($this->lock, LOCK_EX|LOCK_NB, $wouldBlock); + if ($wouldBlock) { + // Another instance is already running + throw new SihnonFramework_Exception_AlreadyRunning(); + } else if ( ! $result) { + throw new SihnonFramework_Exception_LockingFailed(); + } + + + } + + protected function teardown() { + if ( ! $this->locked) { + return; + } + + flock($this->lock, LOCK_UN); + fclose($this->lock); + unlink($this->lock_file); + } +} + +?> \ No newline at end of file diff --git a/source/lib/SihnonFramework/Exceptions.class.php b/source/lib/SihnonFramework/Exceptions.class.php index bf0b0a0..c67f4d3 100644 --- a/source/lib/SihnonFramework/Exceptions.class.php +++ b/source/lib/SihnonFramework/Exceptions.class.php @@ -48,4 +48,8 @@ class SihnonFramework_Exception_ValidationException extends SihnonFramework_E class SihnonFramework_Exception_InvalidContent extends SihnonFramework_Exception_ValidationException {}; class SihnonFramework_Exception_InvalidLength extends SihnonFramework_Exception_ValidationException {}; +class SihnonFramework_Exception_DaemonException extends SihnonFramework_Exception {}; +class SihnonFramework_Exception_AlreadyRunning extends SihnonFramework_Exception_DaemonException {}; +class SihnonFramework_Exception_LockingFailed extends SihnonFramework_Exception_DaemonException {}; + ?>