From 57389e462fe908d6eff3170aecc94f1a60ebbfbb Mon Sep 17 00:00:00 2001 From: Deon George Date: Thu, 17 Oct 2013 15:15:13 +1100 Subject: [PATCH] Updated to KH 3.3 and overhaul --- .htaccess | 2 +- application/bootstrap.php | 60 ++++-- application/classes/Event.php | 154 +++++++++++++++ .../{model/account.php => Model/Account.php} | 7 +- .../{model/contact.php => Model/Contact.php} | 3 +- .../{model/event.php => Model/Event.php} | 4 +- application/classes/Model/Model.php | 26 +++ .../{model/alarm.php => Model/PanelUser.php} | 6 +- .../{model/model.php => Model/PanelZone.php} | 9 +- .../{model/trigger.php => Model/Trigger.php} | 8 +- application/classes/{orm.php => ORM.php} | 23 +-- application/classes/{panel.php => Panel.php} | 12 +- application/classes/Panel/NessD8.php | 177 ++++++++++++++++++ application/classes/Protocol.php | 35 ++++ application/classes/Protocol/ContactID.php | 78 ++++++++ application/classes/Task/Event/Load.php | 44 +++++ application/classes/URL.php | 72 +++++++ application/classes/contactid.php | 100 ---------- application/classes/controller/task/event.php | 113 ----------- application/classes/events.php | 74 -------- application/classes/panel/nessd8.php | 88 --------- application/config/database.php | 2 +- application/config/debug.php | 17 ++ application/views/template.php | 0 includes/kohana | 2 +- index.php | 38 ++-- 26 files changed, 695 insertions(+), 459 deletions(-) create mode 100644 application/classes/Event.php rename application/classes/{model/account.php => Model/Account.php} (66%) rename application/classes/{model/contact.php => Model/Contact.php} (85%) rename application/classes/{model/event.php => Model/Event.php} (76%) create mode 100644 application/classes/Model/Model.php rename application/classes/{model/alarm.php => Model/PanelUser.php} (73%) rename application/classes/{model/model.php => Model/PanelZone.php} (60%) rename application/classes/{model/trigger.php => Model/Trigger.php} (67%) rename application/classes/{orm.php => ORM.php} (69%) rename application/classes/{panel.php => Panel.php} (59%) create mode 100644 application/classes/Panel/NessD8.php create mode 100644 application/classes/Protocol.php create mode 100644 application/classes/Protocol/ContactID.php create mode 100644 application/classes/Task/Event/Load.php create mode 100644 application/classes/URL.php delete mode 100644 application/classes/contactid.php delete mode 100644 application/classes/controller/task/event.php delete mode 100644 application/classes/events.php delete mode 100644 application/classes/panel/nessd8.php create mode 100644 application/config/debug.php delete mode 100644 application/views/template.php diff --git a/.htaccess b/.htaccess index dfdb9a6..c8dada9 100644 --- a/.htaccess +++ b/.htaccess @@ -17,5 +17,5 @@ RewriteRule ^(?:application|modules|includes/kohana)\b.* index.php/$0 [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d -# Rewrite all other URLs to kh.php/URL +# Rewrite all other URLs to index.php/URL RewriteRule .* index.php/$0 [PT] diff --git a/application/bootstrap.php b/application/bootstrap.php index 9f78fdb..606db3a 100644 --- a/application/bootstrap.php +++ b/application/bootstrap.php @@ -3,48 +3,56 @@ // -- Environment setup -------------------------------------------------------- // Load the core Kohana class -require SYSPATH.'classes/kohana/core'.EXT; +require SYSPATH.'classes/Kohana/Core'.EXT; -if (is_file(APPPATH.'classes/kohana'.EXT)) +if (is_file(APPPATH.'classes/Kohana'.EXT)) { // Application extends the core - require APPPATH.'classes/kohana'.EXT; + require APPPATH.'classes/Kohana'.EXT; } else { // Load empty core extension - require SYSPATH.'classes/kohana'.EXT; + require SYSPATH.'classes/Kohana'.EXT; } /** * Set the default time zone. * - * @see http://kohanaframework.org/guide/using.configuration - * @see http://php.net/timezones + * @link http://kohanaframework.org/guide/using.configuration + * @link http://www.php.net/manual/timezones */ date_default_timezone_set('Australia/Melbourne'); /** * Set the default locale. * - * @see http://kohanaframework.org/guide/using.configuration - * @see http://php.net/setlocale + * @link http://kohanaframework.org/guide/using.configuration + * @link http://www.php.net/manual/function.setlocale */ setlocale(LC_ALL, 'en_US.utf-8'); /** * Enable the Kohana auto-loader. * - * @see http://kohanaframework.org/guide/using.autoloading - * @see http://php.net/spl_autoload_register + * @link http://kohanaframework.org/guide/using.autoloading + * @link http://www.php.net/manual/function.spl-autoload-register */ spl_autoload_register(array('Kohana', 'auto_load')); +/** + * Optionally, you can enable a compatibility auto-loader for use with + * older modules that have not been updated for PSR-0. + * + * It is recommended to not enable this unless absolutely necessary. + */ +//spl_autoload_register(array('Kohana', 'auto_load_lowercase')); + /** * Enable the Kohana auto-loader for unserialization. * - * @see http://php.net/spl_autoload_call - * @see http://php.net/manual/var.configuration.php#unserialize-callback-func + * @link http://www.php.net/manual/function.spl-autoload-call + * @link http://www.php.net/manual/var.configuration#unserialize-callback-func */ ini_set('unserialize_callback_func', 'spl_autoload_call'); @@ -75,15 +83,16 @@ if (isset($_SERVER['KOHANA_ENV'])) * - string index_file name of your index file, usually "index.php" index.php * - string charset internal character set used for input and output utf-8 * - string cache_dir set the internal cache directory APPPATH/cache + * - integer cache_life lifetime, in seconds, of items cached 60 * - boolean errors enable or disable error handling TRUE * - boolean profile enable or disable internal profiling TRUE * - boolean caching enable or disable internal caching FALSE + * - boolean expose set the X-Powered-By header FALSE */ Kohana::init(array( 'base_url' => '', - 'index_file' => '', 'caching' => TRUE, - 'cache_dir' => '/dev/shm/halmon', + 'index_file' => '', )); /** @@ -105,10 +114,11 @@ Kohana::modules(array( // 'codebench' => SMDPATH.'codebench', // Benchmarking tool 'database' => SMDPATH.'database', // Database access // 'image' => SMDPATH.'image', // Image manipulation + 'khemail' => SMDPATH.'khemail', // Email module for Kohana 3 PHP Framework + 'minion' => SMDPATH.'minion', // CLI Tasks 'orm' => SMDPATH.'orm', // Object Relationship Mapping // 'unittest' => SMDPATH.'unittest', // Unit testing 'userguide' => SMDPATH.'userguide', // User guide and API documentation - 'email' => SMDPATH.'email', // Email Module )); /** @@ -116,24 +126,34 @@ Kohana::modules(array( */ Route::set('sections', '/(/(/(/)))', array( - 'directory' => '('.implode('|',Kohana::config('config.method_directory')).')' + 'directory' => '('.implode('|',array_values(URL::$method_directory)).')' + )) + ->defaults(array( + 'action' => 'index', )); // Static file serving (CSS, JS, images) Route::set('default/media', 'media(/)', array('file' => '.+')) ->defaults(array( - 'controller' => 'welcome', - 'action' => 'media', - 'file' => NULL, + 'controller' => 'media', + 'action' => 'get', )); /** * Set the routes. Each route must have a minimum of a name, a URI and a set of * defaults for the URI. */ -Route::set('default', '((/(/)))', array('id' => '[a-zA-Z0-9_.-]+')) +Route::set('default', '((/(/)))', array('id'=>'[a-zA-Z0-9_.-]+')) ->defaults(array( 'controller' => 'welcome', 'action' => 'index', )); + +/** + * If APC is enabled, and we need to clear the cache + */ +if (file_exists(APPPATH.'cache/CLEAR_APC_CACHE') AND function_exists('apc_clear_cache') AND (PHP_SAPI !== 'cli')) { + if (! apc_clear_cache() OR ! unlink(APPPATH.'cache/CLEAR_APC_CACHE')) + throw new Kohana_Exception('Unable to clear the APC cache.'); +} ?> diff --git a/application/classes/Event.php b/application/classes/Event.php new file mode 100644 index 0000000..7867d5a --- /dev/null +++ b/application/classes/Event.php @@ -0,0 +1,154 @@ +array(),'orm'=>array()); + private $_timestamp = NULL; + + public function __construct($file) { + if (! file_exists($file)) + throw new Kohana_Exception('File doesnt exist (:file)',array(':file'=>$file)); + + $this->process(file_get_contents($file)); + } + + public function __toString() { + return (string)sprintf('%s %s',join('|',$this->_events['protocol']),date('d-m-Y H:i:s',$this->_timestamp)); + } + + /** + * Check that our Event is valid + */ + public function check() { + return $this->_caller AND $this->_timestamp AND $this->_events['protocol']; + } + + private function process($content) { + $meta = $event = FALSE; + $et = NULL; + $good = TRUE; + $events = array(); + + foreach (explode("\n",$content) as $line) { + // Ignore out blank lines + if (! trim($line)) + continue; + + if (preg_match('/^\[metadata\]/',$line)) { + $meta = TRUE; + $event = FALSE; + + continue; + + } elseif (preg_match('/^\[events\]/',$line)) { + $meta = FALSE; + $event = TRUE; + + continue; + } + + if ($meta) { + list ($k,$v) = explode('=',$line,2); + + switch ($k) { + case 'PROTOCOL': + switch ($v) { + case 'ADEMCO_CONTACT_ID': + $protocol = 'Protocol_ContactID'; + + break; + + default: + throw new Kohana_Exception('Unknown protocol :protocol',array(':protocol'=>$v)); + } + + break; + + case 'CALLINGFROM': + $this->_caller = $v; + break; + + case 'CALLERNAME': + $this->_callername = $v; + break; + + case 'TIMESTAMP': + $this->_timestamp = $v; + break; + + default: + printf('Extra data in event file - meta section (%s)',$line); + } + + } elseif ($event) { + $x = new $protocol($line); + + if ($x->event()) + array_push($this->_events['protocol'],$x); + } + } + } + + public function save() { + $result = FALSE; + + foreach ($this->_events['protocol'] as $id => $po) { + $eo = ORM::factory('Event'); + $eo->values(array( + 'alarmevent'=>$po, + 'datetime'=>$this->_timestamp, + 'account_id'=>ORM::factory('Account',array('alarmphone'=>$this->_caller,'siteid'=>$po->accnum())), + 'protocol'=>$po->protocol(), + )); + + // @todo With this logic and multiple events, if 1 event doesnt save, we'll loose it. + if ($eo->save() AND ! $result) + $result = TRUE; + + $this->_events['orm'][$id] = $eo; + } + + return $result; + } + + public function trigger() { + // Work through each of the account triggers + foreach ($this->_events['orm'] as $id => $orm) { + + $contacts = array(); + foreach ($orm->account_id->trigger->find_all() as $to) { + if (! in_array($to->contact->id,$contacts) AND (is_null($to->alarm) OR $to->alarm == $this->_events['protocol'][$id]->etype())) { + // Get details of the event. + $po = $orm->account_id->model->plugin($this->_events['protocol'][$id],$orm->account_id); + + if ($to->email) { + $e = Email::connect(); + $sm = Swift_Message::newInstance(); + $sm->setSubject('Notice from your alarm'); + $sm->setBody(sprintf('Event ID: %s, Message: %s',$orm->id,(string)$po)); + $sm->setTo($to->contact->email); + $sm->setFrom('noreply@leenooks.net'); + $e->send($sm); + } + + if ($to->sms) { + } + + // We dont need to process any more triggers to the same account. + array_push($contacts,$to->contact->id); + } + } + } + } +} +?> diff --git a/application/classes/model/account.php b/application/classes/Model/Account.php similarity index 66% rename from application/classes/model/account.php rename to application/classes/Model/Account.php index 4facfe3..21f7644 100644 --- a/application/classes/model/account.php +++ b/application/classes/Model/Account.php @@ -1,9 +1,9 @@ array('foreign_key'=>'id'), ); protected $_has_many = array( + 'contact'=>array('far_key'=>'id'), 'trigger'=>array('far_key'=>'id'), + 'paneluser'=>array('model'=>'PanelUser','far_key'=>'id'), + 'panelzone'=>array('model'=>'PanelZone','far_key'=>'id'), ); } ?> diff --git a/application/classes/model/contact.php b/application/classes/Model/Contact.php similarity index 85% rename from application/classes/model/contact.php rename to application/classes/Model/Contact.php index 8a9eb41..dc210ee 100644 --- a/application/classes/model/contact.php +++ b/application/classes/Model/Contact.php @@ -2,8 +2,7 @@ /** * - * @package HAM - * @subpackage Contacts + * @package HAlMon * @category Models * @author Deon George * @copyright (c) 2010 Deon George diff --git a/application/classes/model/event.php b/application/classes/Model/Event.php similarity index 76% rename from application/classes/model/event.php rename to application/classes/Model/Event.php index 81d31d4..5cbcf50 100644 --- a/application/classes/model/event.php +++ b/application/classes/Model/Event.php @@ -1,9 +1,9 @@ array('far_key'=>'id'), + ); + + public function plugin(Protocol $eo,Model $ao) { + $x = 'Panel_'.$this->model; + + if (class_exists($x)) + return new $x($eo,$ao); + else + throw new Kohana_Exception('Unknown Panel :panel',array(':panel'=>$this->model)); + } +} +?> diff --git a/application/classes/model/alarm.php b/application/classes/Model/PanelUser.php similarity index 73% rename from application/classes/model/alarm.php rename to application/classes/Model/PanelUser.php index 44aa6a2..c51289d 100644 --- a/application/classes/model/alarm.php +++ b/application/classes/Model/PanelUser.php @@ -1,14 +1,14 @@ diff --git a/application/classes/model/model.php b/application/classes/Model/PanelZone.php similarity index 60% rename from application/classes/model/model.php rename to application/classes/Model/PanelZone.php index 731fce7..7518899 100644 --- a/application/classes/model/model.php +++ b/application/classes/Model/PanelZone.php @@ -1,17 +1,14 @@ array('far_key'=>'id'), - ); +class Model_PanelZone extends ORM { } ?> diff --git a/application/classes/model/trigger.php b/application/classes/Model/Trigger.php similarity index 67% rename from application/classes/model/trigger.php rename to application/classes/Model/Trigger.php index 4eff054..a26c03b 100644 --- a/application/classes/model/trigger.php +++ b/application/classes/Model/Trigger.php @@ -1,9 +1,9 @@ array('foreign_key'=>'id'), ); - - public function trigger($code) { - return $this->where('alarm','=',$code)->or_where('alarm','=',null)->find(); - } } ?> diff --git a/application/classes/orm.php b/application/classes/ORM.php similarity index 69% rename from application/classes/orm.php rename to application/classes/ORM.php index e69c2f1..6ebfff3 100644 --- a/application/classes/orm.php +++ b/application/classes/ORM.php @@ -3,8 +3,8 @@ /** * This class overrides Kohana's ORM * - * @package lnApp/Modifications - * @category Classes + * @package HAlMon + * @category Modifications * @author Deon George * @copyright (c) 2010 Deon George * @license http://dev.leenooks.net/license.html @@ -17,25 +17,6 @@ class ORM extends Kohana_ORM { // Our filters used to display values in a friendly format protected $_display_filters = array(); - // Override check() so that it doesnt throw an exception. - // @todo Need to figure out how to show the items that fail validation - final public function check(Validation $extra_validation = NULL) { - // Determine if any external validation failed - $extra_errors = ($extra_validation AND ! $extra_validation->check()); - - // Always build a new validation object - $this->_validation(); - - $array = $this->_validation; - - if (($this->_valid = $array->check()) === FALSE OR $extra_errors) - { - return FALSE; - } - - return $this; - } - /** * Format fields for display purposes * diff --git a/application/classes/panel.php b/application/classes/Panel.php similarity index 59% rename from application/classes/panel.php rename to application/classes/Panel.php index d98749c..4d21028 100644 --- a/application/classes/panel.php +++ b/application/classes/Panel.php @@ -3,19 +3,21 @@ /** * This class provides the base for Alarm Panel models * - * @package HAM + * @package HAlMon * @category Helpers * @author Deon George * @copyright (c) 2010 Deon George * @license http://dev.leenooks.net/license.html */ abstract class Panel { - protected $events = array(); + protected $_ao = NULL; + protected $_eo = NULL; - public function __construct(array $events) { - $this->events = $events; + public function __construct(Protocol $eo,Model $ao) { + $this->_ao = $ao; + $this->_eo = $eo; } - abstract public function trigger(); + abstract public function __toString(); } ?> diff --git a/application/classes/Panel/NessD8.php b/application/classes/Panel/NessD8.php new file mode 100644 index 0000000..676f273 --- /dev/null +++ b/application/classes/Panel/NessD8.php @@ -0,0 +1,177 @@ +_eo->type() !== '18') ? 'Unkown Alarm: '.$this->_eo->event() : $this->event(); + } catch (exception $e) { + return $e->getMessage(); + } + } + + private function area() { + $x = $this->_ao->panelzone->where('zoneid','=',$this->_eo->area())->find(); + return $x->loaded() ? $x->description : 'Area '.$this->_eo->area(); + } + + public function event() { + switch ($this->_eo->etype()) { + // Medical + case 100: + return (($this->_eo->equal() == 1) AND ($this->_eo->area() == '01') AND ($this->_eo->info() == '033')) ? 'Medical Alarm' : 'Unknown Alarm '.$this->_eo->etype(); + + // Fire + case 110: + return (($this->_eo->equal() == 1) AND ($this->_eo->area() == '01') AND ($this->_eo->info() == '034')) ? 'Fire Alarm' : 'Unknown Alarm '.$this->_eo->etype(); + + // Panic + case 120: + switch ($this->_eo->info()) { + case '031': return ($this->_eo->area() == '01') ? 'Keyswitch Panic' : 'Unknown Panic Alarm '.$this->_eo->area(); + case '032': return ($this->_eo->area() == '01') ? 'Keypad Panic' : 'Unknown Panic Alarm '.$this->_eo->area(); + default: return ($this->_eo->area() == '01') ? 'Radio Key Panic: '.$this->_eo->info() : 'Unknown Panic Alarm '.$this->_eo->area(); + } + + // Duress Alarm + case 121: + return (($this->_eo->equal() == 1) AND ($this->_eo->area() == '01') AND ($this->_eo->info() == '030')) ? 'Duress Alaram' : 'Unknown Alarm '.$this->_eo->etype(); + + // Alarm + case 130: + switch ($this->_eo->equal()) { + case 1: $action = 'Alarm'; break; + case 3: $action = 'Reset'; break; + default: $action = 'Unknown'; + } + + return sprintf('Alarm %s (Area: %s) (Zone: %s)',$action,$this->area(),$this->zone()); + + // Mains Fail + case 301: + return (($this->_eo->equal() == 1) AND ($this->_eo->area() == '01') AND ($this->_eo->info() == '050')) ? 'Mains Fail' : 'Unknown Alarm '.$this->_eo->etype(); + + // Exit Installer Mode + case 306: + return (($this->_eo->equal() == 1) AND ($this->_eo->area() == '01') AND ($this->_eo->info() == '035')) ? 'Exit Install Mode' : 'Unknown Alarm '.$this->_eo->etype(); + + // Tamper + case 307: + switch ($this->_eo->equal()) { + case 1: $action = 'Alarm'; break; + case 3: $action = 'Reset'; break; + default: $action = 'Unknown'; + } + + switch ($this->_eo->info()) { + case '040': return ($this->_eo->area() == '01') ? sprintf('External Tamper %s',$action) : 'Unknown Tamper Alarm '.$this->_eo->area(); + case '041': return ($this->_eo->area() == '01') ? sprintf('Internal Tamper %s',$action) : 'Unknown Tamper Alarm '.$this->_eo->area(); + case '042': return ($this->_eo->area() == '01') ? sprintf('keypad Tamper %s',$action) : 'Unknown Tamper Alarm '.$this->_eo->area(); + default: return 'Unknown Tamper Alarm '.$this->_eo->info(); + } + + // Panel Battery Fail + case 309: + return (($this->_eo->equal() == 1) AND ($this->_eo->area() == '01') AND ($this->_eo->info() == '051')) ? 'Panel Battery Fail' : 'Unknown Alarm '.$this->_eo->etype(); + + // Auto Exclude + case 380: + switch ($this->_eo->equal()) { + case 1: $action = 'Start'; break; + case 3: $action = 'Stop'; break; + default: $action = 'Unknown'; + } + + return sprintf('Auto Exclude %s (Area: %s) (Zone: %s)',$action,$this->area(),$this->zone()); + + // Radio Sensor Supervision + case 381: + switch ($this->_eo->equal()) { + case 1: $action = 'Start'; break; + case 3: $action = 'Stop'; break; + default: $action = 'Unknown'; + } + + return sprintf('Radio Sensor Supervision %s (Zone: %s)',$action,$this->_eo->info()); + + // Radio Sensor Tamper + case 383: + switch ($this->_eo->equal()) { + case 1: $action = 'Start'; break; + case 3: $action = 'Stop'; break; + default: $action = 'Unknown'; + } + + return sprintf('Radio Sensor Tamper %s (Zone: %s)',$action,$this->_eo->info()); + + // Radio Sensor Low Battery + case 384: + switch ($this->_eo->equal()) { + case 1: $action = 'Start'; break; + case 3: $action = 'Stop'; break; + default: $action = 'Unknown'; + } + + return sprintf('Radio Sensor Low Battery %s (Zone: %s)',$action,$this->_eo->info()); + + // Arm/Disarm Call + case 402: + switch ($this->_eo->equal()) { + case 1: $action = 'Disarmed'; break; + case 3: $action = 'Armed'; break; + default: $action = 'Unknown'; + } + + return sprintf('Panel %s (Area: %s) (By: %s)',$action,$this->area(),$this->user()); + + // Force Arm/Disarm Call + case 406: + switch ($this->_eo->equal()) { + case 1: $action = 'Disarmed'; break; + case 3: $action = 'Armed'; break; + default: $action = 'Unknown'; + } + + return sprintf('Force Panel %s (Area: %s) (By: %s)',$action,$this->area(),$this->user()); + + // Manual Exclude + case 573: + switch ($this->_eo->equal()) { + case 1: $action = 'Start'; break; + case 3: $action = 'Stop'; break; + default: $action = 'Unknown'; + } + + return sprintf('Manual Exclude %s (Area: %s) (Zone: %s)',$action,$this->area(),$this->zone()); + + // Test Call + case 602: + return (($this->_eo->equal() == 1) AND ($this->_eo->area() == '01') AND ($this->_eo->info() == '063')) ? 'Test Call' : 'Unknown Alarm '.$this->_eo->etype(); + + default: + return 'Unkown Event Code: '.$this->_eo->etype(); + } + } + + public function user() { + if ($this->_eo->info()==58) + Return 'Short Cut'; + + $x = $this->_ao->paneluser->where('userid','=',$this->_eo->info())->find(); + return $x->loaded() ? $x->username : 'User '.$this->_eo->info(); + } + + public function zone() { + $x = $this->_ao->panelzone->where('zoneid','=',$this->_eo->info())->find(); + return $x->loaded() ? $x->username : 'Zone '.$this->_eo->info(); + } +} +?> diff --git a/application/classes/Protocol.php b/application/classes/Protocol.php new file mode 100644 index 0000000..904c3e9 --- /dev/null +++ b/application/classes/Protocol.php @@ -0,0 +1,35 @@ +_id = $this->check($event) ? $event : NULL; + } + + public function __toString() { + return (string)$this->event(); + } + + public function event() { + return $this->_id; + } + + public function protocol() { + return $this->_protocol; + } +} +?> diff --git a/application/classes/Protocol/ContactID.php b/application/classes/Protocol/ContactID.php new file mode 100644 index 0000000..68ccb74 --- /dev/null +++ b/application/classes/Protocol/ContactID.php @@ -0,0 +1,78 @@ +10, + '1'=>1, + '2'=>2, + '3'=>3, + '4'=>4, + '5'=>5, + '6'=>6, + '7'=>7, + '8'=>8, + '9'=>9, + '*'=>11, + '#'=>12, + 'A'=>13, + 'B'=>14, + 'C'=>15, + ); + + public function accnum() { + return substr($this->_id,0,4); + } + + public function area() { + return substr($this->_id,10,2); + } + + // Check that this event is valid + public function check($id) { + if (strlen($id) != 16) + return FALSE; + + // Our checksum should be mod15 + $c = $t = 0; + while ($c_checksum_map[substr($id,$c++,1)]; + + return ($t%15 === 0) ? TRUE : FALSE; + } + + public function checksum() { + return substr($this->_id,15,1); + } + + public function equal() { + return substr($this->_id,6,1); + } + + public function etype() { + return substr($this->_id,7,3); + } + + public function info() { + return substr($this->_id,12,3); + } + + /** + * Message Type + * @note This is typically always 18 + */ + public function type() { + return substr($this->_id,4,2); + } +} +?> diff --git a/application/classes/Task/Event/Load.php b/application/classes/Task/Event/Load.php new file mode 100644 index 0000000..d39eb64 --- /dev/null +++ b/application/classes/Task/Event/Load.php @@ -0,0 +1,44 @@ +NULL, + 'verbose'=>FALSE, + ); + + protected function _execute(array $params) { + if (! $params['file']) + throw new Kohana_Exception('--file not supplied'); + + $eo = new Event($params['file']); + + if (! $eo->save()) { + if (! Kohana::$config->load('debug')->test_mode) + rename($params['file'],$params['file'].'.bad'); + + echo 'Bad Event File: '.$params['file']; + die(1); + } + + if (! Kohana::$config->load('debug')->test_mode) { + if (Kohana::$config->load('config')->event_file_keep) + rename($params['file'],$params['file'].'.processed'); + else + unlink($params['file']); + } + + $eo->trigger(); + + printf("Processed event(s) %s\n",$eo); + } +} +?> diff --git a/application/classes/URL.php b/application/classes/URL.php new file mode 100644 index 0000000..28d4113 --- /dev/null +++ b/application/classes/URL.php @@ -0,0 +1,72 @@ +'a', + 'user'=>'u', + ); + + public static function admin_url() { + return (Request::current() AND ((Auth::instance()->logged_in() AND ! empty(URL::$method_directory[strtolower(Request::current()->directory())])) OR in_array(strtolower(Request::current()->controller()),array('login','oauth')))); + } + + /** + * Function to reveal the real directory for a URL + */ + public static function dir($dir) { + // Quick check if we can do something here + if (! in_array(strtolower($dir),URL::$method_directory)) + return $dir; + + // OK, we can, find it. + foreach (URL::$method_directory as $k=>$v) + if (strtolower($dir) == $v) + return ucfirst($k); + + // If we get here, we didnt have anything. + return $dir; + } + + /** + * Wrapper to provide a URL::site() link based on function + */ + public static function link($dir,$src,$site=FALSE) { + if (! $dir) + return $src; + + if (! array_key_exists($dir,URL::$method_directory)) + throw new Kohana_Exception('Unknown directory :dir for :src',array(':dir'=>$dir,':src'=>$src)); + + $x = URL::$method_directory[$dir].'/'.$src; + + return $site ? URL::site($x) : $x; + } + + public static function navbar() { + $result = array(); + + foreach (array_reverse(static::$method_directory) as $k=>$v) + switch ($k) { + case 'admin': $result[$k] = array('name'=>'Administrator','icon'=>'icon-globe'); + break; + + case 'user': $result[$k] = array('name'=>Auth::instance()->get_user()->name(),'icon'=>'icon-user'); + break; + + default: $result[$k] = array('name'=>$k,'icon'=>'icon-question-sign'); + } + + return $result; + } +} +?> diff --git a/application/classes/contactid.php b/application/classes/contactid.php deleted file mode 100644 index a4f0095..0000000 --- a/application/classes/contactid.php +++ /dev/null @@ -1,100 +0,0 @@ -check($id)) - throw new Kohana_Exception('ContactID event :event is not valid',array(':event'=>$id)); - - // Process event trigger - $this->id = $id; - $this->acct = substr($id,0,4); - $this->sub = substr($id,4,2); - $this->qualifier = substr($id,6,1); - $this->type = substr($id,7,3); - $this->area = substr($id,10,2); - $this->info = substr($id,12,3); - $this->checksum = substr($id,15,1); - $this->datetime = $dt; - - // Check the event is from a valid account - // @todo This shouldnt stop program execution, rather it should generate an email to an admin - $ao = ORM::factory('account',array('alarmphone'=>$cf,'siteid'=>$this->acct)); - if (! $ao->loaded()) - throw new Kohana_Exception('Event from unknown account :id is not valid',array(':id'=>$ao->id)); - - $eo = ORM::factory('event'); - $eo->account_id = $ao->id; - $eo->alarmevent = $id; - $eo->datetime = $dt; - $eo->save(); - - // @todo This shouldnt stop program execution, rather it should generate an email to an admin - if (! $eo->saved()) - throw new Kohana_Exception('ContactID event :event is not valid',array(':event'=>$id)); - - return $this; - } - - public function __get($k) { - if (isset($this->{$k})) - return $this->{$k}; - else - throw new Kohana_Exception('Unknown property :property',array(':property'=>$k));; - } - - // Check that this event is valid - private function check($id) { - $checksum_map = array( - '0'=>10, - '1'=>1, - '2'=>2, - '3'=>3, - '4'=>4, - '5'=>5, - '6'=>6, - '7'=>7, - '8'=>8, - '9'=>9, - '*'=>11, - '#'=>12, - 'A'=>13, - 'B'=>14, - 'C'=>15, - ); - - if (strlen($id) != 16) - throw new Kohana_Exception('ContactID event :event has an invalid length :length',array(':event'=>$id,':length'=>strlen($id))); - - // Our checksum should be mod15 - $c = $t = 0; - while ($c diff --git a/application/classes/controller/task/event.php b/application/classes/controller/task/event.php deleted file mode 100644 index f5dd3a6..0000000 --- a/application/classes/controller/task/event.php +++ /dev/null @@ -1,113 +0,0 @@ -event_file(file_get_contents($eventfile))) { - // Delete the event file, so that it isnt processed again - if (Kohana::config('config.event_file_keep')) - rename($eventfile,Kohana::config('config.event_dir').'/processed-'.$f); - else - unlink($eventfile); - - // Trigger - $eo = new Events($events); - $eo->trigger(); - - } else - rename($eventfile,Kohana::config('config.event_dir').'/bad-'.$f); - } - } - } - - private function event_file($file) { - $meta = $event = FALSE; - $et = $cf = $cn = $dt = NULL; - $good = TRUE; - $events = array(); - - foreach (explode("\n",$file) as $line) { - // Ignore out blank lines - if (! trim($line)) - continue; - - if (preg_match('/^\[metadata\]/',$line)) { - $meta = TRUE; - $event = FALSE; - - continue; - } elseif (preg_match('/^\[events\]/',$line)) { - $meta = FALSE; - $event = TRUE; - - continue; - } - - if ($meta) { - list ($k,$v) = explode('=',$line,2); - - switch ($k) { - case 'PROTOCOL': - switch ($v) { - case 'ADEMCO_CONTACT_ID': - $et = 'ContactID'; - - break; - - default: - throw new Kohana_Exception('Unknown protocol :protocol',array(':protocol'=>$v)); - } - - break; - - case 'CALLINGFROM': - $cf = $v; - break; - - case 'CALLERNAME': - $cn = $v; - break; - - case 'TIMESTAMP': - $dt = $v; - break; - - default: - printf('Extra data in event file - meta section (%s)',$line); - } - - } elseif ($event) { - if (! $et) - throw new Kohana_Exception('Event data without any protocol'); - - $eo = new $et; - if (! $eo->event($line,$dt,$cf,$cn)) - $good = FALSE; - else - array_push($events,$eo); - } - } - - return $events; - } -} -?> diff --git a/application/classes/events.php b/application/classes/events.php deleted file mode 100644 index 4a9dcbb..0000000 --- a/application/classes/events.php +++ /dev/null @@ -1,74 +0,0 @@ -acct)) - $this->acct = $event->acct; - - elseif ($this->acct != $event->acct) - throw new Kohana_Exception('Events are for multiple accounts, unable to handle this.'); - } - - // Save our events - $this->events = $events; - } - - public function trigger() { - $ao = ORM::factory('account',array('siteid'=>$this->acct)); - - if (! $ao->loaded()) - throw new Kohana_Exception('No site configuration for :siteid?',array(':siteid'=>$this->acct)); - - if (! $ao->model->model) - throw new Kohana_Exception('No configured Alarm Model for Alarm ID :id',array(':id'=>$ao->model->id)); - - $ac = sprintf('Panel_%s',$ao->model->model); - if (! class_exists($ac)) - throw new Kohana_Exception('Unable to handle events for Alarm :model',array(':model'=>$ao->model->model)); - - $panel = new $ac($this->events); - - foreach ($panel->trigger() as $event) { - $to = $ao->trigger->trigger($event['alarm']); - - if (! $to->loaded()) - continue; - - // We need to email this event - if ($to->email) { - $e = Email::connect(); - $sm = Swift_Message::newInstance(); - $sm->setSubject('Notice from your alarm'); - $sm->setBody(sprintf('Alarm: %s. Received: %s',$event['desc'],date('d-m-Y h:i:s',$event['date'])),'text/plain'); - $sm->setTo($to->contact->email); - $sm->setFrom('noreply@leenooks.net'); - $e->send($sm); - } - - // We need to sms this event - if ($to->sms) { - printf('Alarm: %s, SMS: %s, Email: %s, To: %s (%s)', - $alo->description, - $to->sms, - $to->email, - $to->contact->email,$to->contact->phone); - echo "\n"; - } - } - } -} -?> diff --git a/application/classes/panel/nessd8.php b/application/classes/panel/nessd8.php deleted file mode 100644 index 118e63c..0000000 --- a/application/classes/panel/nessd8.php +++ /dev/null @@ -1,88 +0,0 @@ -events as $eo) { - $i = count($return); - - $return[$i]['date'] = $eo->datetime; - $return[$i]['alarm'] = $eo->type; - - if ($eo->sub != 18) { - $return[$i]['desc'] = sprintf('Unknown Alarm: %s',$eo->id); - continue; - } - - switch ($eo->type) { - // Alarm - case 130: - switch ($eo->qualifier) { - case 1: $action = 'Alarm'; break; - case 3: $action = 'Reset'; break; - default: $action = 'Unknown'; - } - - $return[$i]['desc'] = sprintf('Alarm (%s) (Area %s) (%s)',$action,$eo->area,$eo->info); - break; - - // Exit Installer Mode - case 306: - switch ($eo->qualifier) { - case 1: $action = 'Exit Installer Mode'; break; - default: $action = 'Unknown'; - } - - $return[$i]['desc'] = sprintf('Auto Exclude (%s) (Area %s) (%s)',$action,$eo->area,$eo->info); - break; - - // Auto Exclude - case 380: - switch ($eo->qualifier) { - case 1: $action = 'Disarmed'; break; - case 3: $action = 'Armed'; break; - default: $action = 'Unknown'; - } - - $return[$i]['desc'] = sprintf('Auto Exclude (%s) (Area %s) (%s)',$action,$eo->area,$eo->info); - break; - - // Arm/Disarm Call - case 402: - switch ($eo->qualifier) { - case 1: $action = 'Disarmed'; break; - case 3: $action = 'Armed'; break; - default: $action = 'Unknown'; - } - - // @todo Change this to include the user name. - $user = substr($eo->info,1,2)==58 ? 'Short Cut' : substr($eo->info,1,2); - - // @todo Change this to include the area name. - $return[$i]['desc'] = sprintf('Panel %s (Area %s) (By %s)',$action,$eo->area,$user); - break; - - // Test Call - case 602: - $return[$i]['desc'] = 'Test Call'; - break; - - default: - $return[$i]['desc'] = sprintf('Unknown Alarm: %s',$eo->id); - } - } - - return $return; - } -} -?> diff --git a/application/config/database.php b/application/config/database.php index 1da52f7..84ee708 100644 --- a/application/config/database.php +++ b/application/config/database.php @@ -4,7 +4,7 @@ return array ( 'default' => array ( - 'type' => 'mysql', + 'type' => 'MySQL', 'connection' => array( /** * The following options are available for MySQL: diff --git a/application/config/debug.php b/application/config/debug.php new file mode 100644 index 0000000..d23777d --- /dev/null +++ b/application/config/debug.php @@ -0,0 +1,17 @@ +FALSE, // Test Mode +); +?> diff --git a/application/views/template.php b/application/views/template.php deleted file mode 100644 index e69de29..0000000 diff --git a/includes/kohana b/includes/kohana index f96694b..f5c623d 160000 --- a/includes/kohana +++ b/includes/kohana @@ -1 +1 @@ -Subproject commit f96694b18fdaa9bd6310debca71427068fe24046 +Subproject commit f5c623d89783fc9bf3c8dbea7699fcefa0015c3d diff --git a/index.php b/index.php index 96cbe16..c7bb26f 100644 --- a/index.php +++ b/index.php @@ -4,14 +4,14 @@ * The directory in which your application specific resources are located. * The application directory must contain the bootstrap.php file. * - * @see http://kohanaframework.org/guide/about.install#application + * @link http://kohanaframework.org/guide/about.install#application */ $application = 'application'; /** * The directory in which your modules are located. * - * @see http://kohanaframework.org/guide/about.install#modules + * @link http://kohanaframework.org/guide/about.install#modules */ $modules = 'modules'; @@ -24,7 +24,7 @@ $sysmodules = 'includes/kohana/modules'; * The directory in which the Kohana resources are located. The system * directory must contain the classes/kohana.php file. * - * @see http://kohanaframework.org/guide/about.install#system + * @link http://kohanaframework.org/guide/about.install#system */ $system = 'includes/kohana/system'; @@ -32,13 +32,13 @@ $system = 'includes/kohana/system'; * The default extension of resource files. If you change this, all resources * must be renamed to use the new extension. * - * @see http://kohanaframework.org/guide/about.install#ext + * @link http://kohanaframework.org/guide/about.install#ext */ define('EXT', '.php'); /** * Set the PHP error reporting level. If you set this in php.ini, you remove this. - * @see http://php.net/error_reporting + * @link http://www.php.net/manual/errorfunc.configuration#ini.error-reporting * * When developing your application, it is highly recommended to enable notices * and strict warnings. Enable them by using: E_ALL | E_STRICT @@ -55,7 +55,7 @@ error_reporting(E_ALL | E_STRICT); * End of standard configuration! Changing any of the code below should only be * attempted by those with a working knowledge of Kohana internals. * - * @see http://kohanaframework.org/guide/using.configuration + * @link http://kohanaframework.org/guide/using.configuration */ // Set the full path to the docroot @@ -111,11 +111,21 @@ if ( ! defined('KOHANA_START_MEMORY')) // Bootstrap the application require APPPATH.'bootstrap'.EXT; -/** - * Execute the main request. A source of the URI can be passed, eg: $_SERVER['PATH_INFO']. - * If no source is specified, the URI will be automatically detected. - */ -echo Request::factory() - ->execute() - ->send_headers() - ->body(); +if (PHP_SAPI == 'cli') // Try and load minion +{ + class_exists('Minion_Task') OR die('Please enable the Minion module for CLI support.'); + set_exception_handler(array('Minion_Exception', 'handler')); + + Minion_Task::factory(Minion_CLI::options())->execute(); +} +else +{ + /** + * Execute the main request. A source of the URI can be passed, eg: $_SERVER['PATH_INFO']. + * If no source is specified, the URI will be automatically detected. + */ + echo Request::factory(TRUE, array(), FALSE) + ->execute() + ->send_headers(TRUE) + ->body(); +}