From 2b05815bfa0c36aae5d486d6d77882db7f6128f6 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 15 Apr 2016 15:44:35 -0400 Subject: [PATCH 01/18] remove set height on the menu bars, fixing flow issues --- web/skins/classic/css/classic/views/event.css | 12 ++++++++++-- web/skins/classic/css/dark/views/event.css | 12 ++++++++++-- web/skins/classic/css/flat/views/event.css | 11 +++++++++-- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/web/skins/classic/css/classic/views/event.css b/web/skins/classic/css/classic/views/event.css index 995a06c1d..13ac0cc0b 100644 --- a/web/skins/classic/css/classic/views/event.css +++ b/web/skins/classic/css/classic/views/event.css @@ -15,7 +15,6 @@ #menuBar1 { width: 100%; - height: 1.5em; padding: 3px 0; text-align: center; clear: both; @@ -41,7 +40,6 @@ #menuBar2 { width: 100%; - height: 1.2em; padding: 3px 0; margin-bottom: 4px; } @@ -57,6 +55,16 @@ text-align: right; } +#menuBar1:after, +#menuBar2:after { + content: "."; + display: block; + height: 0; + font-size: 0; + clear: both; + visibility: hidden; +} + #imageFeed { text-align: center; } diff --git a/web/skins/classic/css/dark/views/event.css b/web/skins/classic/css/dark/views/event.css index 995a06c1d..13ac0cc0b 100644 --- a/web/skins/classic/css/dark/views/event.css +++ b/web/skins/classic/css/dark/views/event.css @@ -15,7 +15,6 @@ #menuBar1 { width: 100%; - height: 1.5em; padding: 3px 0; text-align: center; clear: both; @@ -41,7 +40,6 @@ #menuBar2 { width: 100%; - height: 1.2em; padding: 3px 0; margin-bottom: 4px; } @@ -57,6 +55,16 @@ text-align: right; } +#menuBar1:after, +#menuBar2:after { + content: "."; + display: block; + height: 0; + font-size: 0; + clear: both; + visibility: hidden; +} + #imageFeed { text-align: center; } diff --git a/web/skins/classic/css/flat/views/event.css b/web/skins/classic/css/flat/views/event.css index 17c4f70cf..e69fe14f6 100644 --- a/web/skins/classic/css/flat/views/event.css +++ b/web/skins/classic/css/flat/views/event.css @@ -15,7 +15,6 @@ #menuBar1 { width: 100%; - height: 1.5em; padding: 3px 0; text-align: center; clear: both; @@ -41,7 +40,6 @@ #menuBar2 { width: 100%; - height: 1.2em; padding: 3px 0; margin-bottom: 4px; } @@ -57,6 +55,15 @@ text-align: right; } +#menuBar1:after, +#menuBar2:after { + content: "."; + display: block; + height: 0; + font-size: 0; + clear: both; + visibility: hidden; +} #imageFeed { text-align: center; } From 0dc2987b84e12640bb793b188aae2b42d3e0724b Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 28 Apr 2016 16:32:50 -0400 Subject: [PATCH 02/18] add some error checking, but fix the call to bind which really should have a +1 in it. --- src/zm_stream.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/zm_stream.cpp b/src/zm_stream.cpp index 77c94e68c..eb15fe02c 100644 --- a/src/zm_stream.cpp +++ b/src/zm_stream.cpp @@ -291,7 +291,11 @@ void StreamBase::openComms() if ( connkey > 0 ) { - snprintf( sock_path_lock, sizeof(sock_path_lock), "%s/zms-%06d.lock", config.path_socks, connkey); + unsigned int length = snprintf( sock_path_lock, sizeof(sock_path_lock), "%s/zms-%06d.lock", config.path_socks, connkey); + if ( length >= sizeof(sock_path_lock) ) { + Warning("Socket lock path was truncated."); + length = sizeof(sock_path_lock)-1; + } lock_fd = open(sock_path_lock, O_CREAT|O_WRONLY, S_IRUSR | S_IWUSR); if ( lock_fd <= 0 ) @@ -318,12 +322,19 @@ void StreamBase::openComms() Fatal( "Can't create socket: %s", strerror(errno) ); } - snprintf( loc_sock_path, sizeof(loc_sock_path), "%s/zms-%06ds.sock", config.path_socks, connkey ); + length = snprintf( loc_sock_path, sizeof(loc_sock_path), "%s/zms-%06ds.sock", config.path_socks, connkey ); + if ( length >= sizeof(loc_sock_path) ) { + Warning("Socket path was truncated."); + length = sizeof(loc_sock_path)-1; + } unlink( loc_sock_path ); + if ( sizeof(loc_addr.sun_path) < length ) { + Error("Not enough space %d in loc_addr.sun_path for socket file %s", sizeof(loc_addr.sun_path), loc_sock_path ); + } strncpy( loc_addr.sun_path, loc_sock_path, sizeof(loc_addr.sun_path) ); loc_addr.sun_family = AF_UNIX; - if ( bind( sd, (struct sockaddr *)&loc_addr, strlen(loc_addr.sun_path)+sizeof(loc_addr.sun_family)) < 0 ) + if ( bind( sd, (struct sockaddr *)&loc_addr, strlen(loc_addr.sun_path)+sizeof(loc_addr.sun_family))+1 < 0 ) { Fatal( "Can't bind: %s", strerror(errno) ); } From 75f9fde9202a1f644e0ab3de9474a603a16d7a59 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 2 May 2016 10:37:19 -0400 Subject: [PATCH 03/18] rough in Server object support --- web/api/app/Controller/ServersController.php | 155 +++++++++++++++++++ web/api/app/Model/Server.php | 74 +++++++++ web/api/app/View/Servers/json/edit.ctp | 2 + web/api/app/View/Servers/json/index.ctp | 1 + web/api/app/View/Servers/json/view.ctp | 1 + web/api/app/View/Servers/xml/edit.ctp | 2 + web/api/app/View/Servers/xml/index.ctp | 2 + web/api/app/View/Servers/xml/view.ctp | 2 + 8 files changed, 239 insertions(+) create mode 100644 web/api/app/Controller/ServersController.php create mode 100644 web/api/app/Model/Server.php create mode 100644 web/api/app/View/Servers/json/edit.ctp create mode 100644 web/api/app/View/Servers/json/index.ctp create mode 100644 web/api/app/View/Servers/json/view.ctp create mode 100644 web/api/app/View/Servers/xml/edit.ctp create mode 100644 web/api/app/View/Servers/xml/index.ctp create mode 100644 web/api/app/View/Servers/xml/view.ctp diff --git a/web/api/app/Controller/ServersController.php b/web/api/app/Controller/ServersController.php new file mode 100644 index 000000000..b9afe0033 --- /dev/null +++ b/web/api/app/Controller/ServersController.php @@ -0,0 +1,155 @@ +Session->Read('systemPermission'); + if ($canView =='None') { + throw new UnauthorizedException(__('Insufficient Privileges')); + return; + } + +} + + +/** + * index method + * + * @return void + */ + public function index() { + $this->Server->recursive = 0; + + $options=''; + $servers = $this->Server->find('all',$options); + $this->set(array( + 'servers' => $servers, + '_serialize' => array('servers') + )); + } + +/** + * view method + * + * @throws NotFoundException + * @param string $id + * @return void + */ + public function view($id = null) { + $this->Server->recursive = 0; + if (!$this->Server->exists($id)) { + throw new NotFoundException(__('Invalid server')); + } + $restricted = ''; + + $options = array('conditions' => array( + array('Server.' . $this->Server->primaryKey => $id), + $restricted + ) + ); + $server = $this->Server->find('first', $options); + $this->set(array( + 'server' => $server, + '_serialize' => array('server') + )); + } + +/** + * add method + * + * @return void + */ + public function add() { + if ($this->request->is('post')) { + + if ($this->Session->Read('systemPermission') != 'Edit') + { + throw new UnauthorizedException(__('Insufficient privileges')); + return; + } + + $this->Server->create(); + if ($this->Server->save($this->request->data)) { + # Might be nice to send it a start request + #$this->daemonControl($this->Server->id, 'start', $this->request->data); + return $this->flash(__('The server has been saved.'), array('action' => 'index')); + } + } + } + +/** + * edit method + * + * @throws NotFoundException + * @param string $id + * @return void + */ + public function edit($id = null) { + $this->Server->id = $id; + + if (!$this->Server->exists($id)) { + throw new NotFoundException(__('Invalid server')); + } + if ($this->Session->Read('systemPermission') != 'Edit') + { + throw new UnauthorizedException(__('Insufficient privileges')); + return; + } + if ($this->Server->save($this->request->data)) { + $message = 'Saved'; + } else { + $message = 'Error'; + } + + $this->set(array( + 'message' => $message, + '_serialize' => array('message') + )); + // - restart this server after change + #$this->daemonControl($this->Server->id, 'restart', $this->request->data); + } + +/** + * delete method + * + * @throws NotFoundException + * @param string $id + * @return void + */ + public function delete($id = null) { + $this->Server->id = $id; + if (!$this->Server->exists()) { + throw new NotFoundException(__('Invalid server')); + } + if ($this->Session->Read('systemPermission') != 'Edit') + { + throw new UnauthorizedException(__('Insufficient privileges')); + return; + } + $this->request->allowMethod('post', 'delete'); + + #$this->daemonControl($this->Server->id, 'stop'); + + if ($this->Server->delete()) { + return $this->flash(__('The server has been deleted.'), array('action' => 'index')); + } else { + return $this->flash(__('The server could not be deleted. Please, try again.'), array('action' => 'index')); + } + } +} diff --git a/web/api/app/Model/Server.php b/web/api/app/Model/Server.php new file mode 100644 index 000000000..b58450db5 --- /dev/null +++ b/web/api/app/Model/Server.php @@ -0,0 +1,74 @@ + array( + 'numeric' => array( + 'rule' => array('numeric'), + //'message' => 'Your custom message here', + //'allowEmpty' => false, + //'required' => false, + //'last' => false, // Stop validation after this rule + //'on' => 'create', // Limit validation to 'create' or 'update' operations + ), + ), + ); + + //The Associations below have been created with all possible keys, those that are not needed can be removed + +/** + * hasMany associations + * + * @var array + */ + public $hasMany = array( + 'Monitor' => array( + 'className' => 'Monitor', + 'foreignKey' => 'ServerId', + 'dependent' => false, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'exclusive' => '', + 'finderQuery' => '', + 'counterQuery' => '' + ) + ); +} diff --git a/web/api/app/View/Servers/json/edit.ctp b/web/api/app/View/Servers/json/edit.ctp new file mode 100644 index 000000000..0be859571 --- /dev/null +++ b/web/api/app/View/Servers/json/edit.ctp @@ -0,0 +1,2 @@ +echo json_encode($message); +echo json_encode($server); diff --git a/web/api/app/View/Servers/json/index.ctp b/web/api/app/View/Servers/json/index.ctp new file mode 100644 index 000000000..6e5cbd26d --- /dev/null +++ b/web/api/app/View/Servers/json/index.ctp @@ -0,0 +1 @@ +echo json_encode($servers); diff --git a/web/api/app/View/Servers/json/view.ctp b/web/api/app/View/Servers/json/view.ctp new file mode 100644 index 000000000..c3d0226ab --- /dev/null +++ b/web/api/app/View/Servers/json/view.ctp @@ -0,0 +1 @@ +echo json_encode($server); diff --git a/web/api/app/View/Servers/xml/edit.ctp b/web/api/app/View/Servers/xml/edit.ctp new file mode 100644 index 000000000..09fb8979a --- /dev/null +++ b/web/api/app/View/Servers/xml/edit.ctp @@ -0,0 +1,2 @@ +$xml = Xml::fromArray(array('response' => $message)); +echo $xml->asXML(); diff --git a/web/api/app/View/Servers/xml/index.ctp b/web/api/app/View/Servers/xml/index.ctp new file mode 100644 index 000000000..37afc918b --- /dev/null +++ b/web/api/app/View/Servers/xml/index.ctp @@ -0,0 +1,2 @@ +$xml = Xml::fromArray(array('response' => $monitors)); +echo $xml->asXML(); diff --git a/web/api/app/View/Servers/xml/view.ctp b/web/api/app/View/Servers/xml/view.ctp new file mode 100644 index 000000000..b33c6e79a --- /dev/null +++ b/web/api/app/View/Servers/xml/view.ctp @@ -0,0 +1,2 @@ +$xml = Xml::fromArray(array('response' => $monitor)); +echo $xml->asXML(); From 01aa2c931940794a75348e5d3213dee015ec737d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 2 May 2016 19:48:24 -0400 Subject: [PATCH 04/18] change permissions to stream permissions for view --- web/api/app/Controller/ServersController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/api/app/Controller/ServersController.php b/web/api/app/Controller/ServersController.php index b9afe0033..88a5bec90 100644 --- a/web/api/app/Controller/ServersController.php +++ b/web/api/app/Controller/ServersController.php @@ -19,7 +19,7 @@ class ServersController extends AppController { public function beforeFilter() { parent::beforeFilter(); - $canView = $this->Session->Read('systemPermission'); + $canView = $this->Session->Read('streamPermission'); if ($canView =='None') { throw new UnauthorizedException(__('Insufficient Privileges')); return; From 55d58a140e8f376bd6264912a0ddabc66f3a5c38 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 3 May 2016 08:57:51 -0400 Subject: [PATCH 05/18] instead of code duplication for opening the db, use zmDbConnect everywhere --- scripts/ZoneMinder/lib/ZoneMinder/Logger.pm | 24 ++++----------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm index a6a82db87..4c5acac2b 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm @@ -30,6 +30,7 @@ use warnings; require Exporter; require ZoneMinder::Base; +require ZoneMinder::Database; our @ISA = qw(Exporter ZoneMinder::Base); @@ -460,25 +461,7 @@ sub databaseLevel { if ( !$this->{dbh} ) { - my ( $host, $port ) = ( $Config{ZM_DB_HOST} =~ /^([^:]+)(?::(.+))?$/ ); - - if ( defined($port) ) - { - $this->{dbh} = DBI->connect( "DBI:mysql:database=".$Config{ZM_DB_NAME} - .";host=".$host - .";port=".$port - , $Config{ZM_DB_USER} - , $Config{ZM_DB_PASS} - ); - } - else - { - $this->{dbh} = DBI->connect( "DBI:mysql:database=".$Config{ZM_DB_NAME} - .";host=".$Config{ZM_DB_HOST} - , $Config{ZM_DB_USER} - , $Config{ZM_DB_PASS} - ); - } + $this->{dbh} = zmDbConnect(); if ( !$this->{dbh} ) { $databaseLevel = NOLOG; @@ -505,7 +488,8 @@ sub databaseLevel { if ( $this->{dbh} ) { - $this->{dbh}->disconnect(); + # $this->dbh is now the global dbh, so don't close it. + #$this->{dbh}->disconnect(); undef($this->{dbh}); } } From 30f34a6f49f071b8f2f912d1a177cc7ab13a4a05 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 3 May 2016 08:59:40 -0400 Subject: [PATCH 06/18] instead of code duplication for opening the db, use zmDbConnect everywhere --- scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in index 3a226cdc8..4be86e962 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in @@ -30,6 +30,7 @@ use warnings; require Exporter; require ZoneMinder::Base; +require ZoneMinder::Database; our @ISA = qw(Exporter ZoneMinder::Base); @@ -82,12 +83,7 @@ BEGIN } close( $CONFIG ); - use DBI; - my $dbh = DBI->connect( "DBI:mysql:database=".$Config{ZM_DB_NAME} - .";host=".$Config{ZM_DB_HOST} - , $Config{ZM_DB_USER} - , $Config{ZM_DB_PASS} - ) or croak( "Can't connect to db" ); + my $dbh = zmDbConnect() or croak( "Can't connect to db" ); my $sql = 'select * from Config'; my $sth = $dbh->prepare_cached( $sql ) or croak( "Can't prepare '$sql': ".$dbh->errstr() ); my $res = $sth->execute() or croak( "Can't execute: ".$sth->errstr() ); @@ -95,7 +91,6 @@ BEGIN $Config{$config->{Name}} = $config->{Value}; } $sth->finish(); - #$dbh->disconnect(); if ( ! exists $Config{ZM_SERVER_ID} ) { $Config{ZM_SERVER_ID} = undef; From 9406a2337f5fd20ed5a7af3a62d58f49b825d9b2 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 3 May 2016 10:21:01 -0400 Subject: [PATCH 07/18] Add a BEGIN section to load things in the correct order. --- scripts/ZoneMinder/lib/ZoneMinder.pm | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scripts/ZoneMinder/lib/ZoneMinder.pm b/scripts/ZoneMinder/lib/ZoneMinder.pm index 87a6b14b7..37292a44d 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder.pm @@ -81,6 +81,13 @@ our @EXPORT = ( @EXPORT_OK ); our $VERSION = $ZoneMinder::Base::VERSION; +BEGIN { + require ZoneMinder::Config; + require ZoneMinder::Database; + ZoneMinder::Config::zmConfigLoad(); + ZoneMinder::Database::zmDbConnect(); +} + 1; __END__ From 49e3d3be7aaafdb9975719207e44134dbf210b24 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 3 May 2016 10:21:50 -0400 Subject: [PATCH 08/18] Turn the config loading code from a BEGIN to a function that could be called repeatedly. --- scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in index 4be86e962..03f05d0e8 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in @@ -30,7 +30,6 @@ use warnings; require Exporter; require ZoneMinder::Base; -require ZoneMinder::Database; our @ISA = qw(Exporter ZoneMinder::Base); @@ -64,8 +63,9 @@ use constant ZM_CONFIG => "@ZM_CONFIG@"; # Path to the ZoneMinder config file use Carp; # Load the config from the database into the symbol table -BEGIN -{ +sub zmConfigLoad { + %Config = (); + my $config_file = ZM_CONFIG; open( my $CONFIG, "<", $config_file ) or croak( "Can't open config file '$config_file': $!" ); @@ -83,7 +83,8 @@ BEGIN } close( $CONFIG ); - my $dbh = zmDbConnect() or croak( "Can't connect to db" ); + require ZoneMinder::Database; + my $dbh = ZoneMinder::Database::zmDbConnect() or croak( "Can't connect to db" ); my $sql = 'select * from Config'; my $sth = $dbh->prepare_cached( $sql ) or croak( "Can't prepare '$sql': ".$dbh->errstr() ); my $res = $sth->execute() or croak( "Can't execute: ".$sth->errstr() ); From e80db4c4339c4a86f4583899cb882104aa3883d3 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 3 May 2016 10:22:16 -0400 Subject: [PATCH 09/18] Use zmDbConnect instead of duplicated db connect code --- scripts/ZoneMinder/lib/ZoneMinder/Logger.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm index 4c5acac2b..0e454d784 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm @@ -461,7 +461,7 @@ sub databaseLevel { if ( !$this->{dbh} ) { - $this->{dbh} = zmDbConnect(); + $this->{dbh} = ZoneMinder::Database::zmDbConnect(); if ( !$this->{dbh} ) { $databaseLevel = NOLOG; From 24bf91707f0119fef79af05e8fe0e48917870968 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 3 May 2016 10:22:38 -0400 Subject: [PATCH 10/18] Database module should really use DBI --- scripts/ZoneMinder/lib/ZoneMinder/Database.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Database.pm b/scripts/ZoneMinder/lib/ZoneMinder/Database.pm index 7dfe0654b..fdea725fe 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Database.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Database.pm @@ -27,6 +27,7 @@ package ZoneMinder::Database; use 5.006; use strict; use warnings; +use DBI; require Exporter; require ZoneMinder::Base; From c0509691412fa8312968ed31fb773d050a7922d1 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 5 May 2016 15:33:28 -0400 Subject: [PATCH 11/18] Merge object model classes from storageareas --- web/includes/Event.php | 152 +++++++++++++++++++++++++++++++++++++++ web/includes/Frame.php | 103 ++++++++++++++++++++++++++ web/includes/Server.php | 79 +++++++++++++------- web/includes/Storage.php | 51 +++++++++++++ 4 files changed, 359 insertions(+), 26 deletions(-) create mode 100644 web/includes/Event.php create mode 100644 web/includes/Frame.php create mode 100644 web/includes/Storage.php diff --git a/web/includes/Event.php b/web/includes/Event.php new file mode 100644 index 000000000..5ad1c4031 --- /dev/null +++ b/web/includes/Event.php @@ -0,0 +1,152 @@ + $v) { + $this->{$k} = $v; + } + } else { + Error("No row for Event " . $IdOrRow ); + } + } // end function __construct + public function Storage() { + return new Storage( $this->{'StorageId'} ); + } + public function __call( $fn, array $args){ + if(isset($this->{$fn})){ + return $this->{$fn}; +#array_unshift($args, $this); +#call_user_func_array( $this->{$fn}, $args); + } + } + + public function Time() { + if ( ! isset( $this->{'Time'} ) ) { + $this->{'Time'} = strtotime($this->{'StartTime'}); + } + return $this->{'Time'}; + } + + public function Path() { + $Storage = $this->Storage(); + return $Storage->Path().'/'.$this->Relative_Path(); + } + public function Relative_Path() { + $event_path = ""; + + if ( ZM_USE_DEEP_STORAGE ) + { + $event_path = + $this->{'MonitorId'} + .'/'.strftime( "%y/%m/%d/%H/%M/%S", + $this->Time() + ) + ; + } + else + { + $event_path = + $this->{'MonitorId'} + .'/'.$this->{'Id'} + ; + } + + return( $event_path ); + + } + + public function LinkPath() { + if ( ZM_USE_DEEP_STORAGE ) { + return $this->{'MonitorId'} .'/'.strftime( "%y/%m/%d/.", $this->Time()).$this->{'Id'}; + } + Error("Calling Link_Path when not using deep storage"); + return ''; + } + + public function delete() { + dbQuery( 'DELETE FROM Events WHERE Id = ?', array($this->{'Id'}) ); + if ( !ZM_OPT_FAST_DELETE ) { + dbQuery( 'DELETE FROM Stats WHERE EventId = ?', array($this->{'Id'}) ); + dbQuery( 'DELETE FROM Frames WHERE EventId = ?', array($this->{'Id'}) ); + if ( ZM_USE_DEEP_STORAGE ) { + +# Assumption: All events haev a start time + $start_date = date_parse( $this->{'StartTime'} ); + $start_date['year'] = $start_date['year'] % 100; + + $Storage = $this->Storage(); +# So this is because ZM creates a link under teh day pointing to the time that the event happened. + $eventlink_path = $Storage->Path().'/'.$this->Link_Path(); + + if ( $id_files = glob( $eventlink_path ) ) { +# I know we are using arrays here, but really there can only ever be 1 in the array + $eventPath = preg_replace( '/\.'.$event['Id'].'$/', readlink($id_files[0]), $id_files[0] ); + deletePath( $eventPath ); + deletePath( $id_files[0] ); + $pathParts = explode( '/', $eventPath ); + for ( $i = count($pathParts)-1; $i >= 2; $i-- ) { + $deletePath = join( '/', array_slice( $pathParts, 0, $i ) ); + if ( !glob( $deletePath."/*" ) ) { + deletePath( $deletePath ); + } + } + } else { + Warning( "Found no event files under $eventlink_path" ); + } # end if found files + } else { + $eventPath = $this->Path(); + deletePath( $eventPath ); + } # USE_DEEP_STORAGE OR NOT + } # ! ZM_OPT_FAST_DELETE + } # end Event->delete + +public function getStreamSrc( $args, $querySep='&' ) { + return ZM_BASE_URL.'/index.php?view=view_video&eid='.$this->{'Id'}; + + $streamSrc = ZM_BASE_URL.ZM_PATH_ZMS; + + $args[] = "source=event&event=".$this->{'Id'}; + + if ( ZM_OPT_USE_AUTH ) { + if ( ZM_AUTH_RELAY == "hashed" ) { + $args[] = "auth=".generateAuthHash( ZM_AUTH_HASH_IPS ); + } elseif ( ZM_AUTH_RELAY == "plain" ) { + $args[] = "user=".$_SESSION['username']; + $args[] = "pass=".$_SESSION['password']; + } elseif ( ZM_AUTH_RELAY == "none" ) { + $args[] = "user=".$_SESSION['username']; + } + } + if ( !in_array( "mode=single", $args ) && !empty($GLOBALS['connkey']) ) { + $args[] = "connkey=".$GLOBALS['connkey']; + } + if ( ZM_RAND_STREAM ) { + $args[] = "rand=".time(); + } + + if ( count($args) ) { + $streamSrc .= "?".join( $querySep, $args ); + } + + return( $streamSrc ); + } // end function getStreamSrc +} # end class +?> diff --git a/web/includes/Frame.php b/web/includes/Frame.php new file mode 100644 index 000000000..5973cd1bf --- /dev/null +++ b/web/includes/Frame.php @@ -0,0 +1,103 @@ + $v) { + $this->{$k} = $v; + } + } else { + Error("No row for Frame " . $IdOrRow ); + } + } // end function __construct + public function Storage() { + return $this->Event()->Storage(); + } + public function Event() { + return new Event( $this->{'EventId'} ); + } + public function __call( $fn, array $args){ + if(isset($this->{$fn})){ + return $this->{$fn}; +#array_unshift($args, $this); +#call_user_func_array( $this->{$fn}, $args); + } + } + + public function Path() { + $Storage = $this->Storage(); + return $Storage->Path().'/'.$this->Relative_Path(); + } + public function Relative_Path() { + $event_path = ""; + + if ( ZM_USE_DEEP_STORAGE ) + { + $event_path = + $this->{'MonitorId'} + .'/'.strftime( "%y/%m/%d/%H/%M/%S", + $this->Time() + ) + ; + } + else + { + $event_path = + $this->{'MonitorId'} + .'/'.$this->{'Id'} + ; + } + + return( $event_path ); + + } + + public function getImageSrc( ) { + return ZM_BASE_URL.'/index.php?view=image&fid='.$this->{'Id'}; + } // end function getImageSrc + + public static function find( $parameters = array(), $limit = NULL ) { + $sql = 'SELECT * FROM Frames'; + $values = array(); + if ( sizeof($parameters) ) { + $sql .= ' WHERE ' . implode( ' AND ', array_map( + function($v){ return $v.'=?'; }, + array_keys( $parameters ) + ) ); + $values = array_values( $parameters ); + } + if ( $limit ) { + $sql .= ' LIMIT ' . $limit; + } + $results = dbFetchAll( $sql, NULL, $values ); + if ( $results ) { + return array_map( function($id){ return new Frame($id); }, $results ); + } + } + + public static function find_one( $parameters = array() ) { + $results = Frame::find( $parameters, 1 ); + if ( ! sizeof( $results ) ) { + return; + } + return $results[0]; + } +} # end class +?> diff --git a/web/includes/Server.php b/web/includes/Server.php index e8402809c..dfce67eb8 100644 --- a/web/includes/Server.php +++ b/web/includes/Server.php @@ -1,28 +1,28 @@ $v) { - $this->{$k} = $v; - } - } else { - $this->{'Name'} = ''; - $this->{'Hostname'} = ''; - } +class Server { + public function __construct( $IdOrRow = NULL ) { + $row = NULL; + if ( $IdOrRow ) { + if ( is_integer( $IdOrRow ) or is_numeric( $IdOrRow ) ) { + $row = dbFetchOne( 'SELECT * FROM Servers WHERE Id=?', NULL, array( $IdOrRow ) ); + if ( ! $row ) { + Error("Unable to load Server record for Id=" . $IdOrRow ); + } + } elseif ( is_array( $IdOrRow ) ) { + $row = $IdOrRow; + } + } # end if isset($IdOrRow) + if ( $row ) { + foreach ($row as $k => $v) { + $this->{$k} = $v; + } + } else { + $this->{'Name'} = ''; + $this->{'Hostname'} = ''; } + } public static function find_all() { $servers = array(); $result = dbQuery( 'SELECT * FROM Servers ORDER BY Name'); @@ -47,11 +47,38 @@ class Server { return $this->{'Name'}; } public function __call( $fn, array $args= NULL){ - if(isset($this->{$fn})){ - return $this->{$fn}; - #array_unshift($args, $this); - #call_user_func_array( $this->{$fn}, $args); - } + if(isset($this->{$fn})){ + return $this->{$fn}; +#array_unshift($args, $this); +#call_user_func_array( $this->{$fn}, $args); } + } + public static function find( $parameters = array(), $limit = NULL ) { + $sql = 'SELECT * FROM Servers'; + $values = array(); + if ( sizeof($parameters) ) { + $sql .= ' WHERE ' . implode( ' AND ', array_map( + function($v){ return $v.'=?'; }, + array_keys( $parameters ) + ) ); + $values = array_values( $parameters ); + } + if ( $limit ) { + $sql .= ' LIMIT ' . $limit; + } + $results = dbFetchAll( $sql, NULL, $values ); + if ( $results ) { + return array_map( function($id){ return new Server($id); }, $results ); + } + } + + public static function find_one( $parameters = array() ) { + $results = Server::find( $parameters, 1 ); + if ( ! sizeof( $results ) ) { + return; + } + return $results[0]; + } + } ?> diff --git a/web/includes/Storage.php b/web/includes/Storage.php new file mode 100644 index 000000000..546cb9cbe --- /dev/null +++ b/web/includes/Storage.php @@ -0,0 +1,51 @@ + $v) { + $this->{$k} = $v; + } + } else { + $this->{'Name'} = ''; + $this->{'Path'} = ''; + } + } + + public function Path() { + if ( isset( $this->{'Path'} ) and ( $this->{'Path'} != '' ) ) { + return $this->{'Path'}; + } else if ( ! isset($this->{'Id'}) ) { + return ZM_DIR_EVENTS; + } + return $this->{'Name'}; + } + public function __call( $fn, array $args= NULL){ + if(isset($this->{$fn})){ + return $this->{$fn}; + #array_unshift($args, $this); + #call_user_func_array( $this->{$fn}, $args); + } + } + public static function find_all() { + $storage_areas = array(); + $result = dbQuery( 'SELECT * FROM Storage ORDER BY Name'); + $results = $result->fetchALL(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'Storage' ); + foreach ( $results as $row => $obj ) { + $storage_areas[] = $obj; + } + return $storage_areas; + } +} +?> From f55f979cc9c63201de7d3727265a319312dd00bc Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sat, 7 May 2016 09:30:03 -0400 Subject: [PATCH 12/18] use fully specified Config to simplify symbol tables --- scripts/ZoneMinder/lib/ZoneMinder/Logger.pm | 34 ++++++++++----------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm index 0e454d784..7366ada90 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm @@ -31,6 +31,8 @@ use warnings; require Exporter; require ZoneMinder::Base; require ZoneMinder::Database; +require ZoneMinder::Config; + our @ISA = qw(Exporter ZoneMinder::Base); @@ -87,8 +89,6 @@ our $VERSION = $ZoneMinder::Base::VERSION; # # ========================================================================== -use ZoneMinder::Config qw(:all); - use DBI; use Carp; use POSIX; @@ -152,7 +152,7 @@ sub new $this->{hasTerm} = -t STDERR; ( $this->{fileName} = $0 ) =~ s|^.*/||; - $this->{logPath} = $Config{ZM_PATH_LOGS}; + $this->{logPath} = $ZoneMinder::Config::Config{ZM_PATH_LOGS}; $this->{logFile} = $this->{logPath}."/".$this->{id}.".log"; $this->{trace} = 0; @@ -165,7 +165,7 @@ sub BEGIN { # Fake the config variables that are used in case they are not defined yet # Only really necessary to support upgrade from previous version - if ( !eval('defined($Config{ZM_LOG_DEBUG})') ) + if ( !eval('defined($ZoneMinder::Config::Config{ZM_LOG_DEBUG})') ) { no strict 'subs'; no strict 'refs'; @@ -223,7 +223,7 @@ sub initialise( @ ) } else { - $tempDatabaseLevel = $Config{ZM_LOG_LEVEL_DATABASE}; + $tempDatabaseLevel = $ZoneMinder::Config::Config{ZM_LOG_LEVEL_DATABASE}; } if ( defined($options{fileLevel}) ) { @@ -231,7 +231,7 @@ sub initialise( @ ) } else { - $tempFileLevel = $Config{ZM_LOG_LEVEL_FILE}; + $tempFileLevel = $ZoneMinder::Config::Config{ZM_LOG_LEVEL_FILE}; } if ( defined($options{syslogLevel}) ) { @@ -239,7 +239,7 @@ sub initialise( @ ) } else { - $tempSyslogLevel = $Config{ZM_LOG_LEVEL_SYSLOG}; + $tempSyslogLevel = $ZoneMinder::Config::Config{ZM_LOG_LEVEL_SYSLOG}; } if ( defined($ENV{'LOG_PRINT'}) ) @@ -255,9 +255,9 @@ sub initialise( @ ) $tempFileLevel = $level if ( defined($level = $this->getTargettedEnv('LOG_LEVEL_FILE')) ); $tempSyslogLevel = $level if ( defined($level = $this->getTargettedEnv('LOG_LEVEL_SYSLOG')) ); - if ( $Config{ZM_LOG_DEBUG} ) + if ( $ZoneMinder::Config::Config{ZM_LOG_DEBUG} ) { - foreach my $target ( split( /\|/, $Config{ZM_LOG_DEBUG_TARGET} ) ) + foreach my $target ( split( /\|/, $ZoneMinder::Config::Config{ZM_LOG_DEBUG_TARGET} ) ) { if ( $target eq $this->{id} || $target eq "_".$this->{id} @@ -266,12 +266,12 @@ sub initialise( @ ) || $target eq "" ) { - if ( $Config{ZM_LOG_DEBUG_LEVEL} > NOLOG ) + if ( $ZoneMinder::Config::Config{ZM_LOG_DEBUG_LEVEL} > NOLOG ) { - $tempLevel = $this->limit( $Config{ZM_LOG_DEBUG_LEVEL} ); - if ( $Config{ZM_LOG_DEBUG_FILE} ne "" ) + $tempLevel = $this->limit( $ZoneMinder::Config::Config{ZM_LOG_DEBUG_LEVEL} ); + if ( $ZoneMinder::Config::Config{ZM_LOG_DEBUG_FILE} ne "" ) { - $tempLogFile = $Config{ZM_LOG_DEBUG_FILE}; + $tempLogFile = $ZoneMinder::Config::Config{ZM_LOG_DEBUG_FILE}; $tempFileLevel = $tempLevel; } } @@ -466,9 +466,9 @@ sub databaseLevel { $databaseLevel = NOLOG; Error( "Unable to write log entries to DB, can't connect to database '" - .$Config{ZM_DB_NAME} + .$ZoneMinder::Config::Config{ZM_DB_NAME} ."' on host '" - .$Config{ZM_DB_HOST} + .$ZoneMinder::Config::Config{ZM_DB_HOST} ."'" ); } @@ -566,8 +566,8 @@ sub openFile { $LOGFILE->autoflush() if ( $this->{autoFlush} ); - my $webUid = (getpwnam( $Config{ZM_WEB_USER} ))[2]; - my $webGid = (getgrnam( $Config{ZM_WEB_GROUP} ))[2]; + my $webUid = (getpwnam( $ZoneMinder::Config::Config{ZM_WEB_USER} ))[2]; + my $webGid = (getgrnam( $ZoneMinder::Config::Config{ZM_WEB_GROUP} ))[2]; if ( $> == 0 ) { chown( $webUid, $webGid, $this->{logFile} ) From 6e32b5d26610f40dc5c260ef4271fca1054cd760 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sat, 7 May 2016 09:34:04 -0400 Subject: [PATCH 13/18] Use fully specified COnfig hash to simplify Symbol tables --- scripts/ZoneMinder/lib/ZoneMinder/Database.pm | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Database.pm b/scripts/ZoneMinder/lib/ZoneMinder/Database.pm index fdea725fe..574c382f5 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Database.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Database.pm @@ -31,6 +31,7 @@ use DBI; require Exporter; require ZoneMinder::Base; +require ZoneMinder::Config; our @ISA = qw(Exporter ZoneMinder::Base); @@ -65,7 +66,6 @@ our $VERSION = $ZoneMinder::Base::VERSION; # ========================================================================== use ZoneMinder::Logger qw(:all); -use ZoneMinder::Config qw(:all); use Carp; @@ -80,23 +80,23 @@ sub zmDbConnect } if ( !defined( $dbh ) ) { - my ( $host, $port ) = ( $Config{ZM_DB_HOST} =~ /^([^:]+)(?::(.+))?$/ ); + my ( $host, $port ) = ( $ZoneMinder::Config::Config{ZM_DB_HOST} =~ /^([^:]+)(?::(.+))?$/ ); if ( defined($port) ) { - $dbh = DBI->connect( "DBI:mysql:database=".$Config{ZM_DB_NAME} + $dbh = DBI->connect( "DBI:mysql:database=".$ZoneMinder::Config::Config{ZM_DB_NAME} .";host=".$host .";port=".$port - , $Config{ZM_DB_USER} - , $Config{ZM_DB_PASS} + , $ZoneMinder::Config::Config{ZM_DB_USER} + , $ZoneMinder::Config::Config{ZM_DB_PASS} ); } else { - $dbh = DBI->connect( "DBI:mysql:database=".$Config{ZM_DB_NAME} - .";host=".$Config{ZM_DB_HOST} - , $Config{ZM_DB_USER} - , $Config{ZM_DB_PASS} + $dbh = DBI->connect( "DBI:mysql:database=".$ZoneMinder::Config::Config{ZM_DB_NAME} + .";host=".$ZoneMinder::Config::Config{ZM_DB_HOST} + , $ZoneMinder::Config::Config{ZM_DB_USER} + , $ZoneMinder::Config::Config{ZM_DB_PASS} ); } $dbh->trace( 0 ); From b444c8a6b41238e2557fef4258422bea41d6ec85 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sat, 7 May 2016 09:34:45 -0400 Subject: [PATCH 14/18] Move the BEGIN from ZoneMinder to ZoneMinder/Base. --- scripts/ZoneMinder/lib/ZoneMinder.pm | 6 ------ 1 file changed, 6 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder.pm b/scripts/ZoneMinder/lib/ZoneMinder.pm index 37292a44d..63b7c8108 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder.pm @@ -81,12 +81,6 @@ our @EXPORT = ( @EXPORT_OK ); our $VERSION = $ZoneMinder::Base::VERSION; -BEGIN { - require ZoneMinder::Config; - require ZoneMinder::Database; - ZoneMinder::Config::zmConfigLoad(); - ZoneMinder::Database::zmDbConnect(); -} 1; __END__ From 3522c5796bd05e5a4475484ec277f274a71c16de Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 9 May 2016 12:01:26 -0400 Subject: [PATCH 15/18] add BEGIN Back to ZoneMinder.pm --- scripts/ZoneMinder/lib/ZoneMinder.pm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/ZoneMinder/lib/ZoneMinder.pm b/scripts/ZoneMinder/lib/ZoneMinder.pm index 63b7c8108..6d8b3bfc8 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder.pm @@ -81,6 +81,10 @@ our @EXPORT = ( @EXPORT_OK ); our $VERSION = $ZoneMinder::Base::VERSION; +BEGIN { + ZoneMinder::Config::zmConfigLoad(); + ZoneMinder::Database::zmDbConnect(); +} 1; __END__ From b33e35bda7f1bedbc795fc320d2a65cc8460edab Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 9 May 2016 12:14:59 -0400 Subject: [PATCH 16/18] move the require to the top --- scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in index 03f05d0e8..54cc8c3f3 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in @@ -30,6 +30,7 @@ use warnings; require Exporter; require ZoneMinder::Base; +require ZoneMinder::Database; our @ISA = qw(Exporter ZoneMinder::Base); @@ -83,7 +84,6 @@ sub zmConfigLoad { } close( $CONFIG ); - require ZoneMinder::Database; my $dbh = ZoneMinder::Database::zmDbConnect() or croak( "Can't connect to db" ); my $sql = 'select * from Config'; my $sth = $dbh->prepare_cached( $sql ) or croak( "Can't prepare '$sql': ".$dbh->errstr() ); From 5566d1881df20b0283ae73f0a68e3304deb2635e Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 9 May 2016 21:34:12 -0400 Subject: [PATCH 17/18] add perl dbd mysql to build depends. Seems to need it. --- distros/ubuntu1204/control | 1 + 1 file changed, 1 insertion(+) diff --git a/distros/ubuntu1204/control b/distros/ubuntu1204/control index 6368d9417..3fedf7129 100644 --- a/distros/ubuntu1204/control +++ b/distros/ubuntu1204/control @@ -16,6 +16,7 @@ Build-Depends: debhelper (>= 9), python-sphinx | python3-sphinx, apache2-dev, dh ,libpolkit-gobject-1-dev ,libv4l-dev (>= 0.8.3) [!hurd-any] ,libvlc-dev + ,libdbd-mysql-perl # Unbundled (dh_linktree): ,libjs-jquery ,libjs-mootools From 4d20d35f8d46fc2db6b51e5f30778e17e0a13f11 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 10 May 2016 08:43:38 -0400 Subject: [PATCH 18/18] add back missing depends for perl modules which are needed both for building and installing --- distros/ubuntu1204/control | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/distros/ubuntu1204/control b/distros/ubuntu1204/control index 3fedf7129..0791622ed 100644 --- a/distros/ubuntu1204/control +++ b/distros/ubuntu1204/control @@ -5,18 +5,22 @@ Maintainer: Dmitry Smirnov Uploaders: Vagrant Cascadian Build-Depends: debhelper (>= 9), python-sphinx | python3-sphinx, apache2-dev, dh-linktree ,cmake - ,libavcodec-dev, libavformat-dev (>= 3:0.svn20090204), libswscale-dev (>= 3:0.svn20090204), libavutil-dev, libavdevice-dev + ,libavcodec-dev, libavformat-dev (>= 3:0.svn20090204), libswscale-dev (>= 3:0.svn20090204), libavutil-dev, libavdevice-dev ,libbz2-dev ,libgcrypt-dev ,libcurl4-gnutls-dev ,libgnutls-openssl-dev - ,libjpeg8-dev|libjpeg9-dev|libjpeg62-turbo-dev, + ,libjpeg8-dev|libjpeg9-dev|libjpeg62-turbo-dev, ,libmysqlclient-dev ,libpcre3-dev ,libpolkit-gobject-1-dev ,libv4l-dev (>= 0.8.3) [!hurd-any] ,libvlc-dev + ,libdate-manip-perl ,libdbd-mysql-perl + ,libphp-serialization-perl + ,libsys-mmap-perl [!hurd-any] + ,libwww-perl # Unbundled (dh_linktree): ,libjs-jquery ,libjs-mootools