diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index d084cda2a..f9bb3866d 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -562,7 +562,7 @@ CREATE TABLE `Monitors` ( `V4LMultiBuffer` tinyint(1) unsigned, `V4LCapturesPerFrame` tinyint(3) unsigned, `Protocol` varchar(16), - `Method` varchar(16) NOT NULL default '', + `Method` varchar(16) default '', `Host` varchar(64), `Port` varchar(8) NOT NULL default '', `SubPath` varchar(64) NOT NULL default '', @@ -841,7 +841,7 @@ CREATE TABLE `Storage` ( `Path` varchar(64) NOT NULL default '', `Name` varchar(64) NOT NULL default '', `Type` enum('local','s3fs') NOT NULL default 'local', - `DiskSpace` bigint unsigned default NULL, + `DiskSpace` bigint default NULL, `Scheme` enum('Deep','Medium','Shallow') NOT NULL default 'Medium', `ServerId` int(10) unsigned, PRIMARY KEY (`Id`) diff --git a/db/zm_update-1.31.31.sql b/db/zm_update-1.31.31.sql new file mode 100644 index 000000000..66e25f95c --- /dev/null +++ b/db/zm_update-1.31.31.sql @@ -0,0 +1 @@ +ALTER TABLE Storage MODIFY DiskSpace BIGINT default NULL; diff --git a/db/zm_update-1.31.32.sql b/db/zm_update-1.31.32.sql new file mode 100644 index 000000000..781fce1fc --- /dev/null +++ b/db/zm_update-1.31.32.sql @@ -0,0 +1,3 @@ +ALTER TABLE Monitors MODIFY TotalEventDiskSpace BIGINT default NULL; +ALTER TABLE Monitors MODIFY Method VARCHAR(16) default NULL; + diff --git a/scripts/ZoneMinder/lib/ZoneMinder/General.pm b/scripts/ZoneMinder/lib/ZoneMinder/General.pm index c362a81bf..692af30d4 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/General.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/General.pm @@ -173,8 +173,7 @@ sub runCommand { chomp( $output ); if ( $status || logDebugging() ) { if ( $status ) { - Error( "Unable to run \"$command\", output is \"$output\"\n" ); - exit( -1 ); + Error( "Unable to run \"$command\", output is \"$output\", status is $status\n" ); } else { Debug( "Output: $output\n" ); } diff --git a/scripts/zmaudit.pl.in b/scripts/zmaudit.pl.in index cdd283b28..7be542391 100644 --- a/scripts/zmaudit.pl.in +++ b/scripts/zmaudit.pl.in @@ -196,7 +196,7 @@ MAIN: while( $loop ) { or Fatal( "Can't prepare '$monitorSelectSql': ".$dbh->errstr() ); my $eventSelectSql = 'SELECT Id, (unix_timestamp() - unix_timestamp(StartTime)) AS Age - FROM Events WHERE MonitorId = ? ORDER BY Id'; + FROM Events WHERE MonitorId = ?'.(@Storage_Areas ? ' AND StorageId IN ('.join(',',map { '?'} @Storage_Areas).')' : '' ). ' ORDER BY Id'; my $eventSelectSth = $dbh->prepare_cached( $eventSelectSql ) or Fatal( "Can't prepare '$eventSelectSql': ".$dbh->errstr() ); @@ -207,7 +207,7 @@ MAIN: while( $loop ) { $Monitors{$$monitor{Id}} = $monitor; my $db_events = $db_monitors->{$monitor->{Id}} = {}; - my $res = $eventSelectSth->execute( $monitor->{Id} ) + my $res = $eventSelectSth->execute( $monitor->{Id}, map { $$_{Id} } @Storage_Areas ) or Fatal( "Can't execute: ".$eventSelectSth->errstr() ); while ( my $event = $eventSelectSth->fetchrow_hashref() ) { $db_events->{$event->{Id}} = $event->{Age}; diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index b2164ca99..b237cf13a 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -1799,7 +1799,7 @@ int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose } Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame ); col++; - const char *method = dbrow[col]; col++; + const char *method = dbrow[col] ? dbrow[col] : ""; col++; int width = atoi(dbrow[col]); col++; int height = atoi(dbrow[col]); col++; @@ -2315,7 +2315,7 @@ int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose const char *linked_monitors = dbrow[col] ? dbrow[col] : ""; col++; const char *path = dbrow[col]; col++; - const char *method = dbrow[col]; col++; + const char *method = dbrow[col] ? dbrow[col] : ""; col++; const char *options = dbrow[col] ? dbrow[col] : ""; col++; int width = atoi(dbrow[col]); col++; diff --git a/version b/version index e9c3366c8..71736e954 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.31.30 +1.31.32 diff --git a/web/includes/actions.php b/web/includes/actions.php index 1b1fa9254..5556f9982 100644 --- a/web/includes/actions.php +++ b/web/includes/actions.php @@ -67,13 +67,20 @@ function do_post_request($url, $data, $optional_headers = null) { function getAffectedIds( $name ) { $names = $name.'s'; $ids = array(); - if ( isset($_REQUEST[$names]) || isset($_REQUEST[$name]) ) { - if ( isset($_REQUEST[$names]) ) - $ids = validInt($_REQUEST[$names]); - else if ( isset($_REQUEST[$name]) ) - $ids[] = validInt($_REQUEST[$name]); - } - return( $ids ); + if ( isset($_REQUEST[$names]) ) { + if ( is_array($_REQUEST[$names]) ) { + $ids = $_REQUEST[$names]; + } else { + $ids = array($_REQUEST[$names]); + } + } else if ( isset($_REQUEST[$name]) ) { + if ( is_array($_REQUEST[$name]) ) { + $ids = $_REQUEST[$name]; + } else { + $ids = array($_REQUEST[$name]); + } + } + return $ids; } @@ -198,33 +205,39 @@ if ( canView( 'Events' ) ) { else { // Event scope actions, edit permissions required - if ( canEdit( 'Events' ) ) { - if ( $action == 'rename' && isset($_REQUEST['eventName']) && !empty($_REQUEST['eid']) ) { + if ( canEdit('Events') ) { + if ( ($action == 'rename') && isset($_REQUEST['eventName']) && !empty($_REQUEST['eid']) ) { dbQuery( 'UPDATE Events SET Name=? WHERE Id=?', array( $_REQUEST['eventName'], $_REQUEST['eid'] ) ); } else if ( $action == 'eventdetail' ) { if ( !empty($_REQUEST['eid']) ) { dbQuery( 'UPDATE Events SET Cause=?, Notes=? WHERE Id=?', array( $_REQUEST['newEvent']['Cause'], $_REQUEST['newEvent']['Notes'], $_REQUEST['eid'] ) ); } else { - foreach( getAffectedIds( 'markEid' ) as $markEid ) { + $dbConn->beginTransaction(); + foreach( getAffectedIds('markEid') as $markEid ) { dbQuery( 'UPDATE Events SET Cause=?, Notes=? WHERE Id=?', array( $_REQUEST['newEvent']['Cause'], $_REQUEST['newEvent']['Notes'], $markEid ) ); } + $dbConn->commit(); } $refreshParent = true; $closePopup = true; } elseif ( $action == 'archive' || $action == 'unarchive' ) { $archiveVal = ($action == 'archive')?1:0; if ( !empty($_REQUEST['eid']) ) { - dbQuery( 'UPDATE Events SET Archived=? WHERE Id=?', array( $archiveVal, $_REQUEST['eid']) ); + dbQuery('UPDATE Events SET Archived=? WHERE Id=?', array($archiveVal, $_REQUEST['eid'])); } else { + $dbConn->beginTransaction(); foreach( getAffectedIds( 'markEid' ) as $markEid ) { - dbQuery( 'UPDATE Events SET Archived=? WHERE Id=?', array( $archiveVal, $markEid ) ); + dbQuery('UPDATE Events SET Archived=? WHERE Id=?', array($archiveVal, $markEid)); } + $dbConn->commit(); $refreshParent = true; } } elseif ( $action == 'delete' ) { + $dbConn->beginTransaction(); foreach( getAffectedIds( 'markEid' ) as $markEid ) { deleteEvent( $markEid ); } + $dbConn->commit(); $refreshParent = true; } } // end if canEdit(Events) @@ -484,19 +497,18 @@ if ( canEdit( 'Monitors' ) ) { ); if ( $_REQUEST['newMonitor']['ServerId'] == 'auto' ) { -Logger::Debug("Auto selecting server"); + Logger::Debug("Auto selecting server"); $_REQUEST['newMonitor']['ServerId'] = dbFetchOne( 'SELECT Id FROM Servers WHERE Status=\'Running\' ORDER BY FreeMem ASC, CpuLoad ASC LIMIT 1', 'Id' ); -Logger::Debug("Auto selecting server: Got " . $_REQUEST['newMonitor']['ServerId'] ); + Logger::Debug("Auto selecting server: Got " . $_REQUEST['newMonitor']['ServerId'] ); if ( ( ! $_REQUEST['newMonitor'] ) and defined('ZM_SERVER_ID') ) { $_REQUEST['newMonitor']['ServerId'] = ZM_SERVER_ID; -Logger::Debug("Auto selecting server to " . ZM_SERVER_ID); + Logger::Debug("Auto selecting server to " . ZM_SERVER_ID); } } else { Logger::Debug("NOT Auto selecting server" . $_REQUEST['newMonitor']['ServerId']); } $columns = getTableColumns( 'Monitors' ); -Logger::Debug('coloumns:'.print_r($columns)); $changes = getFormChanges( $monitor, $_REQUEST['newMonitor'], $types, $columns ); if ( count( $changes ) ) { @@ -553,7 +565,7 @@ Logger::Debug('coloumns:'.print_r($columns)); $restart = true; } else if ( ! $user['MonitorIds'] ) { // Can only create new monitors if we are not restricted to specific monitors # FIXME This is actually a race condition. Should lock the table. - $maxSeq = dbFetchOne( 'SELECT max(Sequence) AS MaxSequence FROM Monitors', 'MaxSequence' ); + $maxSeq = dbFetchOne('SELECT MAX(Sequence) AS MaxSequence FROM Monitors', 'MaxSequence'); $changes[] = 'Sequence = '.($maxSeq+1); if ( dbQuery( 'INSERT INTO Monitors SET '.implode( ', ', $changes ) ) ) { diff --git a/web/includes/database.php b/web/includes/database.php index 1fb18f0e8..250e5fce8 100644 --- a/web/includes/database.php +++ b/web/includes/database.php @@ -98,7 +98,7 @@ function dbLog( $sql, $update=false ) { } function dbError( $sql ) { - Fatal( "SQL-ERR '".$dbConn->errorInfo()."', statement was '".$sql."'" ); + Error( "SQL-ERR '".$dbConn->errorInfo()."', statement was '".$sql."'" ); } function dbEscape( $string ) { @@ -150,14 +150,18 @@ function dbQuery( $sql, $params=NULL ) { function dbFetchOne( $sql, $col=false, $params=NULL ) { $result = dbQuery( $sql, $params ); if ( ! $result ) { - Fatal( "SQL-ERR dbFetchOne no result, statement was '".$sql."'" . ( $params ? 'params: ' . join(',',$params) : '' ) ); + Error( "SQL-ERR dbFetchOne no result, statement was '".$sql."'" . ( $params ? 'params: ' . join(',',$params) : '' ) ); + return false; + } + if ( ! $result->rowCount() ) { + # No rows is not an error return false; } if ( $result && $dbRow = $result->fetch( PDO::FETCH_ASSOC ) ) { if ( $col ) { if ( ! isset( $dbRow[$col] ) ) { - Warning( "$col does not exist in the returned row" ); + Warning( "$col does not exist in the returned row " . print_r($dbRow, true) ); } return $dbRow[$col]; } @@ -169,7 +173,7 @@ function dbFetchOne( $sql, $col=false, $params=NULL ) { function dbFetchAll( $sql, $col=false, $params=NULL ) { $result = dbQuery( $sql, $params ); if ( ! $result ) { - Fatal( "SQL-ERR dbFetchAll no result, statement was '".$sql."'" . ( $params ? 'params: ' .join(',', $params) : '' ) ); + Error( "SQL-ERR dbFetchAll no result, statement was '".$sql."'" . ( $params ? 'params: ' .join(',', $params) : '' ) ); return false; } diff --git a/web/includes/functions.php b/web/includes/functions.php index 7ef1b054c..7531561bb 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -169,9 +169,9 @@ function generateAuthHash( $useRemoteAddr ) { } $_SESSION['AuthHash'] = $auth; $_SESSION['AuthHashGeneratedAt'] = $time; - Logger::Debug("Generated new auth $auth at " . $_SESSION['AuthHashGeneratedAt']. " using $authKey" ); - } else { - Logger::Debug( "Using cached auth " . $_SESSION['AuthHash'] ." beacuse " . $_SESSION['AuthHashGeneratedAt'] . ' < '. $time . ' - ' . ZM_AUTH_HASH_TTL . ' * 1800 = '.( $time - (ZM_AUTH_HASH_TTL * 1800) )); + #Logger::Debug("Generated new auth $auth at " . $_SESSION['AuthHashGeneratedAt']. " using $authKey" ); + #} else { + #Logger::Debug( "Using cached auth " . $_SESSION['AuthHash'] ." beacuse " . $_SESSION['AuthHashGeneratedAt'] . ' < '. $time . ' - ' . ZM_AUTH_HASH_TTL . ' * 1800 = '.( $time - (ZM_AUTH_HASH_TTL * 1800) )); } # end if AuthHash is not cached return $_SESSION['AuthHash']; } else { diff --git a/web/skins/classic/css/base/skin.css b/web/skins/classic/css/base/skin.css index 9ea3e843a..e86264989 100644 --- a/web/skins/classic/css/base/skin.css +++ b/web/skins/classic/css/base/skin.css @@ -95,6 +95,7 @@ input,textarea,select,button,.btn-primary { font-weight: 400; font-size: 100%; color: #333333; + text-align: left; } /* input[type=text], input[type=password], input[type="url"], textarea, select { @@ -544,3 +545,6 @@ margin-left: 0; .nav-pills > li > a { border-radius: 0; } +.chosen-container { +text-align: left; +} diff --git a/web/skins/classic/css/base/views/filter.css b/web/skins/classic/css/base/views/filter.css index 839554c6e..638b85c9b 100644 --- a/web/skins/classic/css/base/views/filter.css +++ b/web/skins/classic/css/base/views/filter.css @@ -56,3 +56,9 @@ select { width: 300px; text-align: right; } +select#Id { +min-width: 400px; +} +.Name input { +min-width: 400px; +} diff --git a/web/skins/classic/includes/functions.php b/web/skins/classic/includes/functions.php index 993441cdf..c788bb039 100644 --- a/web/skins/classic/includes/functions.php +++ b/web/skins/classic/includes/functions.php @@ -81,11 +81,13 @@ echo output_link_if_exists( array( 'css/'.$css.'/views/'.$basename.'.css', '/js/dateTimePicker/jquery-ui-timepicker-addon.css', '/js/jquery-ui-structure.css', + '/css/base/jquery-ui-theme.css', '/css/'.$css.'/jquery-ui-theme.css', ) ); ?> - + + 'All' ); +//$storageareas[0] = 'Default ' . ZM_DIR_EVENTS; foreach ( dbFetchAll( 'SELECT Id,Name FROM Storage ORDER BY lower(Name) ASC' ) as $storage ) { $storageareas[$storage['Id']] = $storage['Name']; } diff --git a/web/skins/classic/views/js/filter.js b/web/skins/classic/views/js/filter.js index c8e6749a4..4df73997e 100644 --- a/web/skins/classic/views/js/filter.js +++ b/web/skins/classic/views/js/filter.js @@ -61,7 +61,7 @@ function updateButtons( element ) { function checkValue ( element ) { let rows = $j(element).closest('tbody').children(); parseRows(rows); - clearValue(element); + //clearValue(element); } function clearValue( element ) { @@ -178,9 +178,15 @@ function parseRows (rows) { } else if (inputTds.eq(2).children().val() == 'StorageId') { //Choose by storagearea let storageSelect = $j('').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]'); + for ( key in storageareas ) { +console.log(key + ' ' + storageareas[key]); + storageSelect.append(''); +} +/* for (let i=0; i < storageareas.length; i++) { storageSelect.append(''); } +*/ let storageVal = inputTds.eq(4).children().val(); inputTds.eq(4).html(storageSelect).children().val(storageVal).chosen({width: "101%"}); diff --git a/web/skins/classic/views/onvifprobe.php b/web/skins/classic/views/onvifprobe.php index f2ca662cb..f9c766846 100644 --- a/web/skins/classic/views/onvifprobe.php +++ b/web/skins/classic/views/onvifprobe.php @@ -158,7 +158,7 @@ if( !isset($_REQUEST['step']) || ($_REQUEST['step'] == "1")) { */ // $sourceDesc = htmlspecialchars(serialize($camera['monitor'])); $sourceDesc = base64_encode(serialize($camera['monitor'])); - $sourceString = $camera['model'].' @ '.$host; + $sourceString = $camera['model'].' @ '.$host . ' using version ' . $camera['monitor']['SOAP'] ; $cameras[$sourceDesc] = $sourceString; }