From c37278788233c31e6bef6e9ab79ad4f3bfc07cd2 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 6 Jul 2017 10:50:56 -0400 Subject: [PATCH 01/48] fix typo --- web/includes/functions.php | 3 +-- web/skins/classic/views/events.php | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/web/includes/functions.php b/web/includes/functions.php index b76cb5c55..b85624335 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -2138,8 +2138,7 @@ function getSkinFile( $file ) { return( $skinFile ); } -function getSkinIncludes( $file, $includeBase=false, $asOverride=false ) -{ +function getSkinIncludes( $file, $includeBase=false, $asOverride=false ) { global $skinBase; $skinFile = false; foreach ( $skinBase as $skin ) { diff --git a/web/skins/classic/views/events.php b/web/skins/classic/views/events.php index 59df19e7f..ea1a58f2e 100644 --- a/web/skins/classic/views/events.php +++ b/web/skins/classic/views/events.php @@ -214,7 +214,7 @@ foreach ( $events as $event ) { Id().'&fid='.$thumbData['FrameId'].'&width='.$thumbData['Width'].'&height='.$thumbData['Height']; - $streamSrc = $Event->getStreamSrc( array( 'mode'=>'jpeg', 'scale'=>$scale, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>'single') ); + $streamSrc = $event->getStreamSrc( array( 'mode'=>'jpeg', 'scale'=>$scale, 'maxfps'=>ZM_WEB_VIDEO_MAXFPS, 'replay'=>'single') ); $imgHtml = ''. validHtmlStr('Event '.$event->Id()) .''; From 50adec45c5445381b356f6aa55b3d5900459b9ba Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 6 Jul 2017 11:45:17 -0400 Subject: [PATCH 02/48] Strip non 7-bit ascii chars from log message --- web/ajax/log.php | 1 + 1 file changed, 1 insertion(+) diff --git a/web/ajax/log.php b/web/ajax/log.php index c38a6d5d0..81312d709 100644 --- a/web/ajax/log.php +++ b/web/ajax/log.php @@ -95,6 +95,7 @@ switch ( $_REQUEST['task'] ) foreach ( dbFetchAll( $sql, NULL, $values ) as $log ) { $log['DateTime'] = preg_replace( '/^\d+/', strftime( "%Y-%m-%d %H:%M:%S", intval($log['TimeKey']) ), $log['TimeKey'] ); $log['Server'] = ( $log['ServerId'] and isset($servers_by_Id[$log['ServerId']]) ) ? $servers_by_Id[$log['ServerId']]->Name() : ''; + $log['Message'] = preg_replace('/[\x00-\x1F\x7F-\xFF]/', '', $log['Message'] ); $logs[] = $log; } $options = array(); From c2d21289e199390aabba57f5998c52bd5300b085 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 6 Jul 2017 11:57:56 -0400 Subject: [PATCH 03/48] always offer to upload to zmrepo --- utils/do_debian_package.sh | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/utils/do_debian_package.sh b/utils/do_debian_package.sh index de3c29017..716719e3c 100755 --- a/utils/do_debian_package.sh +++ b/utils/do_debian_package.sh @@ -259,23 +259,20 @@ fi if [ $TYPE == "binary" ]; then if [ "$INTERACTIVE" != "no" ]; then - read -p "Not doing dput since it's a binary release. Do you want to install it? (Y/N)" + read -p "Not doing dput since it's a binary release. Do you want to install it? (y/N)" if [[ $REPLY == [yY] ]]; then sudo dpkg -i $DIRECTORY*.deb - else - echo $REPLY; fi; - if [ "$DISTRO" == "jessie" ]; then - read -p "Do you want to upload this binary to zmrepo? (y/N)" - if [[ $REPLY == [yY] ]]; then - if [ "$RELEASE" != "" ]; then - scp "zoneminder_${VERSION}-${DISTRO}*" "zmrepo@zmrepo.connortechnology.com:debian/stable/mini-dinstall/incoming/" + + read -p "Do you want to upload this binary to zmrepo? (y/N)" + if [[ $REPLY == [yY] ]]; then + if [ "$RELEASE" != "" ]; then + scp "zoneminder_${VERSION}-${DISTRO}*" "zmrepo@zmrepo.connortechnology.com:debian/stable/mini-dinstall/incoming/" + else + if [ "$BRANCH" == "" ]; then + scp "zoneminder_${VERSION}-${DISTRO}*" "zmrepo@zmrepo.connortechnology.com:debian/master/mini-dinstall/incoming/" else - if [ "$BRANCH" == "" ]; then - scp "zoneminder_${VERSION}-${DISTRO}*" "zmrepo@zmrepo.connortechnology.com:debian/master/mini-dinstall/incoming/" - else - scp "$DIRECTORY-${DISTRO}*" "zmrepo@zmrepo.connortechnology.com:debian/${BRANCH}/mini-dinstall/incoming/" - fi; + scp "$DIRECTORY-${DISTRO}*" "zmrepo@zmrepo.connortechnology.com:debian/${BRANCH}/mini-dinstall/incoming/" fi; fi; fi; From d3ec50aa698a8f95b2216b3ea162797f9ac78d0f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 6 Jul 2017 17:45:23 -0400 Subject: [PATCH 04/48] various fixes plus use global db functions in logger --- src/zm_db.cpp | 42 ++++++---------- src/zm_eventstream.cpp | 1 + src/zm_logger.cpp | 54 +++------------------ src/zm_user.cpp | 81 ++++++++++++------------------- web/skins/classic/views/event.php | 1 + 5 files changed, 55 insertions(+), 124 deletions(-) diff --git a/src/zm_db.cpp b/src/zm_db.cpp index f4ec6d4b7..6f2c43918 100644 --- a/src/zm_db.cpp +++ b/src/zm_db.cpp @@ -27,10 +27,11 @@ MYSQL dbconn; int zmDbConnected = false; -void zmDbConnect() -{ - if ( !mysql_init( &dbconn ) ) - { +void zmDbConnect() { + if ( zmDbConnected ) + return; + + if ( !mysql_init( &dbconn ) ) { Error( "Can't initialise database connection: %s", mysql_error( &dbconn ) ); exit( mysql_errno( &dbconn ) ); } @@ -38,48 +39,35 @@ void zmDbConnect() if ( mysql_options( &dbconn, MYSQL_OPT_RECONNECT, &reconnect ) ) Fatal( "Can't set database auto reconnect option: %s", mysql_error( &dbconn ) ); std::string::size_type colonIndex = staticConfig.DB_HOST.find( ":" ); - if ( colonIndex == std::string::npos ) - { - if ( !mysql_real_connect( &dbconn, staticConfig.DB_HOST.c_str(), staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), NULL, 0, NULL, 0 ) ) - { + if ( colonIndex == std::string::npos ) { + if ( !mysql_real_connect( &dbconn, staticConfig.DB_HOST.c_str(), staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), NULL, 0, NULL, 0 ) ) { Error( "Can't connect to server: %s", mysql_error( &dbconn ) ); exit( mysql_errno( &dbconn ) ); } - } - else - { + } else { std::string dbHost = staticConfig.DB_HOST.substr( 0, colonIndex ); std::string dbPortOrSocket = staticConfig.DB_HOST.substr( colonIndex+1 ); - if ( dbPortOrSocket[0] == '/' ) - { - if ( !mysql_real_connect( &dbconn, NULL, staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), NULL, 0, dbPortOrSocket.c_str(), 0 ) ) - { + if ( dbPortOrSocket[0] == '/' ) { + if ( !mysql_real_connect( &dbconn, NULL, staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), NULL, 0, dbPortOrSocket.c_str(), 0 ) ) { Error( "Can't connect to server: %s", mysql_error( &dbconn ) ); exit( mysql_errno( &dbconn ) ); } - - } - else - { - if ( !mysql_real_connect( &dbconn, dbHost.c_str(), staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), NULL, atoi(dbPortOrSocket.c_str()), NULL, 0 ) ) - { + } else { + if ( !mysql_real_connect( &dbconn, dbHost.c_str(), staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), NULL, atoi(dbPortOrSocket.c_str()), NULL, 0 ) ) { Error( "Can't connect to server: %s", mysql_error( &dbconn ) ); exit( mysql_errno( &dbconn ) ); } } } - if ( mysql_select_db( &dbconn, staticConfig.DB_NAME.c_str() ) ) - { + if ( mysql_select_db( &dbconn, staticConfig.DB_NAME.c_str() ) ) { Error( "Can't select database: %s", mysql_error( &dbconn ) ); exit( mysql_errno( &dbconn ) ); } zmDbConnected = true; } -void zmDbClose() -{ - if ( zmDbConnected ) - { +void zmDbClose() { + if ( zmDbConnected ) { mysql_close( &dbconn ); // mysql_init() call implicitly mysql_library_init() but // mysql_close() does not call mysql_library_end() diff --git a/src/zm_eventstream.cpp b/src/zm_eventstream.cpp index 964660213..402c5053e 100644 --- a/src/zm_eventstream.cpp +++ b/src/zm_eventstream.cpp @@ -156,6 +156,7 @@ bool EventStream::loadEventData( int event_id ) { else snprintf( event_data->path, sizeof(event_data->path), "%s/%s/%ld/%ld", staticConfig.PATH_WEB.c_str(), storage_path, event_data->monitor_id, event_data->event_id ); } + delete storage; storage = NULL; updateFrameRate( (double)event_data->frame_count/event_data->duration ); diff --git a/src/zm_logger.cpp b/src/zm_logger.cpp index ee3a5a8b5..a30c819e3 100644 --- a/src/zm_logger.cpp +++ b/src/zm_logger.cpp @@ -21,6 +21,7 @@ #include "zm_config.h" #include "zm_utils.h" +#include "zm_db.h" #include #include @@ -333,45 +334,7 @@ Logger::Level Logger::databaseLevel( Logger::Level databaseLevel ) { databaseLevel = limit(databaseLevel); if ( mDatabaseLevel != databaseLevel ) { if ( databaseLevel > NOLOG && mDatabaseLevel <= NOLOG ) { - if ( !mDbConnected ) { - if ( !mysql_init( &mDbConnection ) ) { - Fatal( "Can't initialise database connection: %s", mysql_error( &mDbConnection ) ); - exit( mysql_errno( &mDbConnection ) ); - } - my_bool reconnect = 1; - if ( mysql_options( &mDbConnection, MYSQL_OPT_RECONNECT, &reconnect ) ) - Fatal( "Can't set database auto reconnect option: %s", mysql_error( &mDbConnection ) ); - std::string::size_type colonIndex = staticConfig.DB_HOST.find( ":" ); - if ( colonIndex == std::string::npos ) { - if ( !mysql_real_connect( &mDbConnection, staticConfig.DB_HOST.c_str(), staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), NULL, 0, NULL, 0 ) ) { - Fatal( "Can't connect to database: %s", mysql_error( &mDbConnection ) ); - exit( mysql_errno( &mDbConnection ) ); - } - } else { - std::string dbHost = staticConfig.DB_HOST.substr( 0, colonIndex ); - std::string dbPortOrSocket = staticConfig.DB_HOST.substr( colonIndex+1 ); - if ( dbPortOrSocket[0] == '/' ) { - if ( !mysql_real_connect( &mDbConnection, NULL, staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), NULL, 0, dbPortOrSocket.c_str(), 0 ) ) { - Fatal( "Can't connect to database: %s", mysql_error( &mDbConnection ) ); - exit( mysql_errno( &mDbConnection ) ); - } - } else { - if ( !mysql_real_connect( &mDbConnection, dbHost.c_str(), staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), NULL, atoi(dbPortOrSocket.c_str()), NULL, 0 ) ) { - Fatal( "Can't connect to database: %s", mysql_error( &mDbConnection ) ); - exit( mysql_errno( &mDbConnection ) ); - } - } - } // end if has colon - unsigned long mysqlVersion = mysql_get_server_version( &mDbConnection ); - if ( mysqlVersion < 50019 ) - if ( mysql_options( &mDbConnection, MYSQL_OPT_RECONNECT, &reconnect ) ) - Fatal( "Can't set database auto reconnect option: %s", mysql_error( &mDbConnection ) ); - if ( mysql_select_db( &mDbConnection, staticConfig.DB_NAME.c_str() ) ) { - Fatal( "Can't select database: %s", mysql_error( &mDbConnection ) ); - exit( mysql_errno( &mDbConnection ) ); - } - mDbConnected = true; - } // end if ! mDbConnected + zmDbConnect(); } // end if ( databaseLevel > NOLOG && mDatabaseLevel <= NOLOG ) mDatabaseLevel = databaseLevel; } // end if ( mDatabaseLevel != databaseLevel ) @@ -439,10 +402,7 @@ void Logger::closeFile() { } void Logger::closeDatabase() { - if ( mDbConnected ) { - mysql_close( &mDbConnection ); - mDbConnected = false; - } + } void Logger::openSyslog() { @@ -548,13 +508,13 @@ void Logger::logPrint( bool hex, const char * const filepath, const int line, co char sql[ZM_SQL_MED_BUFSIZ]; char escapedString[(strlen(syslogStart)*2)+1]; - mysql_real_escape_string( &mDbConnection, escapedString, syslogStart, strlen(syslogStart) ); + mysql_real_escape_string( &dbconn, escapedString, syslogStart, strlen(syslogStart) ); snprintf( sql, sizeof(sql), "insert into Logs ( TimeKey, Component, ServerId, Pid, Level, Code, Message, File, Line ) values ( %ld.%06ld, '%s', %d, %d, %d, '%s', '%s', '%s', %d )", timeVal.tv_sec, timeVal.tv_usec, mId.c_str(), staticConfig.SERVER_ID, tid, level, classString, escapedString, file, line ); - if ( mysql_query( &mDbConnection, sql ) ) { + if ( mysql_query( &dbconn, sql ) ) { Level tempDatabaseLevel = mDatabaseLevel; databaseLevel( NOLOG ); - Error( "Can't insert log entry: sql(%s) error(%s)", sql, mysql_error( &mDbConnection ) ); + Error( "Can't insert log entry: sql(%s) error(%s)", sql, mysql_error( &dbconn ) ); databaseLevel(tempDatabaseLevel); } } @@ -566,6 +526,8 @@ void Logger::logPrint( bool hex, const char * const filepath, const int line, co free(filecopy); if ( level <= FATAL ) { + logTerm(); + zmDbClose(); if ( level <= PANIC ) abort(); exit( -1 ); diff --git a/src/zm_user.cpp b/src/zm_user.cpp index 11b794a2d..58de254bd 100644 --- a/src/zm_user.cpp +++ b/src/zm_user.cpp @@ -27,16 +27,14 @@ #include #include -User::User() -{ +User::User() { username[0] = password[0] = 0; enabled = false; stream = events = control = monitors = system = PERM_NONE; monitor_ids = 0; } -User::User( MYSQL_ROW &dbrow ) -{ +User::User( MYSQL_ROW &dbrow ) { int index = 0; strncpy( username, dbrow[index++], sizeof(username) ); strncpy( password, dbrow[index++], sizeof(password) ); @@ -48,22 +46,18 @@ User::User( MYSQL_ROW &dbrow ) system = (Permission)atoi( dbrow[index++] ); monitor_ids = 0; char *monitor_ids_str = dbrow[index++]; - if ( monitor_ids_str && *monitor_ids_str ) - { + if ( monitor_ids_str && *monitor_ids_str ) { monitor_ids = new int[strlen(monitor_ids_str)]; int n_monitor_ids = 0; const char *ptr = monitor_ids_str; - do - { + do { int id = 0; - while( isdigit( *ptr ) ) - { + while( isdigit( *ptr ) ) { id *= 10; id += *ptr-'0'; ptr++; } - if ( id ) - { + if ( id ) { monitor_ids[n_monitor_ids++] = id; if ( !*ptr ) break; @@ -75,21 +69,16 @@ User::User( MYSQL_ROW &dbrow ) } } -User::~User() -{ +User::~User() { delete monitor_ids; } -bool User::canAccess( int monitor_id ) -{ - if ( !monitor_ids ) - { +bool User::canAccess( int monitor_id ) { + if ( !monitor_ids ) { return( true ); } - for ( int i = 0; monitor_ids[i]; i++ ) - { - if ( monitor_ids[i] == monitor_id ) - { + for ( int i = 0; monitor_ids[i]; i++ ) { + if ( monitor_ids[i] == monitor_id ) { return( true ); } } @@ -98,8 +87,7 @@ bool User::canAccess( int monitor_id ) // Function to load a user from username and password // Please note that in auth relay mode = none, password is NULL -User *zmLoadUser( const char *username, const char *password ) -{ +User *zmLoadUser( const char *username, const char *password ) { char sql[ZM_SQL_SML_BUFSIZ] = ""; char safer_username[65]; // current db username size is 32 char safer_password[129]; // current db password size is 64 @@ -114,22 +102,20 @@ User *zmLoadUser( const char *username, const char *password ) snprintf( sql, sizeof(sql), "select Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds from Users where Username = '%s' and Enabled = 1", safer_username ); } - if ( mysql_query( &dbconn, sql ) ) - { + if ( mysql_query( &dbconn, sql ) ) { Error( "Can't run query: %s", mysql_error( &dbconn ) ); exit( mysql_errno( &dbconn ) ); } MYSQL_RES *result = mysql_store_result( &dbconn ); - if ( !result ) - { + if ( !result ) { Error( "Can't use query result: %s", mysql_error( &dbconn ) ); exit( mysql_errno( &dbconn ) ); } int n_users = mysql_num_rows( result ); - if ( n_users != 1 ) - { + if ( n_users != 1 ) { + mysql_free_result( result ); Warning( "Unable to authenticate user %s", username ); return( 0 ); } @@ -145,13 +131,11 @@ User *zmLoadUser( const char *username, const char *password ) } // Function to validate an authentication string -User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) -{ +User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) { #if HAVE_DECL_MD5 || HAVE_DECL_GNUTLS_FINGERPRINT #ifdef HAVE_GCRYPT_H // Special initialisation for libgcrypt - if ( !gcry_check_version( GCRYPT_VERSION ) ) - { + if ( !gcry_check_version( GCRYPT_VERSION ) ) { Fatal( "Unable to initialise libgcrypt" ); } gcry_control( GCRYCTL_DISABLE_SECMEM, 0 ); @@ -159,11 +143,9 @@ User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) #endif // HAVE_GCRYPT_H const char *remote_addr = ""; - if ( use_remote_addr ) - { + if ( use_remote_addr ) { remote_addr = getenv( "REMOTE_ADDR" ); - if ( !remote_addr ) - { + if ( !remote_addr ) { Warning( "Can't determine remote address, using null" ); remote_addr = ""; } @@ -173,28 +155,25 @@ User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) char sql[ZM_SQL_SML_BUFSIZ] = ""; snprintf( sql, sizeof(sql), "SELECT Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds FROM Users WHERE Enabled = 1" ); - if ( mysql_query( &dbconn, sql ) ) - { + if ( mysql_query( &dbconn, sql ) ) { Error( "Can't run query: %s", mysql_error( &dbconn ) ); exit( mysql_errno( &dbconn ) ); } MYSQL_RES *result = mysql_store_result( &dbconn ); - if ( !result ) - { + if ( !result ) { Error( "Can't use query result: %s", mysql_error( &dbconn ) ); exit( mysql_errno( &dbconn ) ); } int n_users = mysql_num_rows( result ); - if ( n_users < 1 ) - { + if ( n_users < 1 ) { + mysql_free_result( result ); Warning( "Unable to authenticate user" ); return( 0 ); } - while( MYSQL_ROW dbrow = mysql_fetch_row( result ) ) - { + while( MYSQL_ROW dbrow = mysql_fetch_row( result ) ) { const char *user = dbrow[0]; const char *pass = dbrow[1]; @@ -204,7 +183,7 @@ User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) unsigned char md5sum[md5len]; time_t now = time( 0 ); - unsigned int hours =config.auth_hash_ttl; + unsigned int hours = config.auth_hash_ttl; if ( ! hours ) { Warning("No value set for ZM_AUTH_HASH_TTL. Defaulting to 2."); @@ -234,23 +213,23 @@ User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) gnutls_fingerprint( GNUTLS_DIG_MD5, &md5data, md5sum, &md5len ); #endif auth_md5[0] = '\0'; - for ( unsigned int j = 0; j < md5len; j++ ) - { + for ( unsigned int j = 0; j < md5len; j++ ) { sprintf( &auth_md5[2*j], "%02x", md5sum[j] ); } Debug( 1, "Checking auth_key '%s' -> auth_md5 '%s' == '%s'", auth_key, auth_md5, auth ); - if ( !strcmp( auth, auth_md5 ) ) - { + if ( !strcmp( auth, auth_md5 ) ) { // We have a match User *user = new User( dbrow ); Debug(1, "Authenticated user '%s'", user->getUsername() ); + mysql_free_result( result ); return( user ); } else { Debug(1, "No match for %s", auth ); } } } + mysql_free_result( result ); #else // HAVE_DECL_MD5 Error( "You need to build with gnutls or openssl installed to use hash based authentication" ); #endif // HAVE_DECL_MD5 diff --git a/web/skins/classic/views/event.php b/web/skins/classic/views/event.php index 9352f6f2b..1498dcc8f 100644 --- a/web/skins/classic/views/event.php +++ b/web/skins/classic/views/event.php @@ -61,6 +61,7 @@ if ( isset( $_REQUEST['streamMode'] ) ) else $streamMode = 'video'; +$replayMode = ''; if ( isset( $_REQUEST['replayMode'] ) ) $replayMode = validHtmlStr($_REQUEST['replayMode']); if ( isset( $_COOKIE['replayMode']) && preg_match('#^[a-z]+$#', $_COOKIE['replayMode']) ) From 21881235f9d6d5607c613fb15b09fe02f599154b Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 7 Jul 2017 09:31:53 -0400 Subject: [PATCH 05/48] merge changeWidth and changeHeight --- web/skins/classic/views/js/montage.js | 43 +++++++-------------------- web/skins/classic/views/montage.php | 6 ++-- 2 files changed, 12 insertions(+), 37 deletions(-) diff --git a/web/skins/classic/views/js/montage.js b/web/skins/classic/views/js/montage.js index 1366e1511..16dc51a44 100644 --- a/web/skins/classic/views/js/montage.js +++ b/web/skins/classic/views/js/montage.js @@ -140,37 +140,8 @@ function selectLayout( element ) { } } -function changeWidth() { +function changeSize() { var width = $('width').get('value'); - - for ( var x = 0; x < monitors.length; x++ ) { - var monitor = monitors[x]; - /*Stream could be an applet so can't use moo tools*/ - var streamImg = $( 'liveStream'+monitor.id ); - if ( streamImg ) { - if ( streamImg.nodeName == 'IMG' ) { - var src = streamImg.src; - streamImg.src=''; - src = src.replace(/width=[\.\d]+/i,'width='+width ); - src = src.replace(/rand=\d+/i,'rand='+Math.floor((Math.random() * 1000000) )); - streamImg.src = src; - - } - streamImg.style.width = width? width + "px" : null; - //streamImg.style.height = ''; - } - var zonesSVG = $('zones'+monitor.id); - if ( zonesSVG ) { - - zonesSVG.style.width = width ? width + "px" : '100%'; - } - } - $('scale').set('value', '' ); - Cookie.write( 'zmMontageScale', '', { duration: 10*365 } ); - Cookie.write( 'zmMontageWidth', width, { duration: 10*365 } ); -} // end function changeWidth() - -function changeHeight() { var height = $('height').get('value'); for ( var x = 0; x < monitors.length; x++ ) { @@ -181,21 +152,27 @@ function changeHeight() { if ( streamImg.nodeName == 'IMG' ) { var src = streamImg.src; streamImg.src=''; + src = src.replace(/width=[\.\d]+/i,'width='+width ); src = src.replace(/height=[\.\d]+/i,'height='+height ); src = src.replace(/rand=\d+/i,'rand='+Math.floor((Math.random() * 1000000) )); streamImg.src = src; - streamImg.style.height = height ? height + "px" : null; + } + streamImg.style.width = width? width + "px" : null; + streamImg.style.height = height ? height + "px" : null; + //streamImg.style.height = ''; } var zonesSVG = $('zones'+monitor.id); if ( zonesSVG ) { + zonesSVG.style.width = width ? width + "px" : '100%'; zonesSVG.style.height = height + "px"; } } $('scale').set('value', '' ); - Cookie.write( 'zmMontageHeight', height, { duration: 10*365 } ); Cookie.write( 'zmMontageScale', '', { duration: 10*365 } ); -} // end function changeHeight() + Cookie.write( 'zmMontageWidth', width, { duration: 10*365 } ); + Cookie.write( 'zmMontageHeight', height, { duration: 10*365 } ); +} // end function changeSize() function changeScale() { var scale = $('scale').get('value'); diff --git a/web/skins/classic/views/montage.php b/web/skins/classic/views/montage.php index 175d1a98a..e53a5a22c 100644 --- a/web/skins/classic/views/montage.php +++ b/web/skins/classic/views/montage.php @@ -41,7 +41,6 @@ if ( isset( $_REQUEST['showZones'] ) ) { } } $monitors = array(); -<<<<<<< HEAD $widths = array( '' => 'auto', 160 => 160, @@ -68,7 +67,6 @@ if ( isset( $_REQUEST['scale'] ) ) { if ( ! $scale ) $scale = 100; -} foreach( dbFetchAll( $sql ) as $row ) { if ( !visibleMonitor( $row['Id'] ) ) { @@ -142,8 +140,8 @@ if ( $showZones ) {

- - + +
From 39745e49d45ce9f6fdd0597c3926fcfa2169c81a Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 7 Jul 2017 09:51:51 -0400 Subject: [PATCH 06/48] I think we switch to border-box model or something, anyways, the box that the pantilt buttons go in needs to be 100px not 96px --- web/skins/classic/css/classic/control.css | 4 ++-- web/skins/classic/css/dark/control.css | 4 ++-- web/skins/classic/css/flat/control.css | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/web/skins/classic/css/classic/control.css b/web/skins/classic/css/classic/control.css index 8e84b4705..55134cd27 100644 --- a/web/skins/classic/css/classic/control.css +++ b/web/skins/classic/css/classic/control.css @@ -79,8 +79,8 @@ border: 1px solid #006699; text-align: center; padding: 1px; - width: 96px; - height: 96px; + width: 100px; + height: 100px; } .ptzControls .controlsPanel .pantiltPanel .pantiltControls .arrowBtn { diff --git a/web/skins/classic/css/dark/control.css b/web/skins/classic/css/dark/control.css index 8e84b4705..55134cd27 100644 --- a/web/skins/classic/css/dark/control.css +++ b/web/skins/classic/css/dark/control.css @@ -79,8 +79,8 @@ border: 1px solid #006699; text-align: center; padding: 1px; - width: 96px; - height: 96px; + width: 100px; + height: 100px; } .ptzControls .controlsPanel .pantiltPanel .pantiltControls .arrowBtn { diff --git a/web/skins/classic/css/flat/control.css b/web/skins/classic/css/flat/control.css index 8e84b4705..55134cd27 100644 --- a/web/skins/classic/css/flat/control.css +++ b/web/skins/classic/css/flat/control.css @@ -79,8 +79,8 @@ border: 1px solid #006699; text-align: center; padding: 1px; - width: 96px; - height: 96px; + width: 100px; + height: 100px; } .ptzControls .controlsPanel .pantiltPanel .pantiltControls .arrowBtn { From 2dd8b5df1fbdd76da2feaa23321808934ba7b69b Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 7 Jul 2017 09:59:41 -0400 Subject: [PATCH 07/48] in dark and flat, the buttons use a larger font. The fixed size is not appropriate --- web/skins/classic/css/dark/control.css | 1 - web/skins/classic/css/flat/control.css | 1 - 2 files changed, 2 deletions(-) diff --git a/web/skins/classic/css/dark/control.css b/web/skins/classic/css/dark/control.css index 55134cd27..c36cd537b 100644 --- a/web/skins/classic/css/dark/control.css +++ b/web/skins/classic/css/dark/control.css @@ -6,7 +6,6 @@ .ptzControls input.ptzTextBtn { margin-top: 2px; - width: 40px; } .ptzControls .controlsPanel { diff --git a/web/skins/classic/css/flat/control.css b/web/skins/classic/css/flat/control.css index 55134cd27..c36cd537b 100644 --- a/web/skins/classic/css/flat/control.css +++ b/web/skins/classic/css/flat/control.css @@ -6,7 +6,6 @@ .ptzControls input.ptzTextBtn { margin-top: 2px; - width: 40px; } .ptzControls .controlsPanel { From 90882edc31b357d086eea4703d03fe83c377b3d3 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 7 Jul 2017 10:05:20 -0400 Subject: [PATCH 08/48] make montage images be display: block; This makes the layout not jump around when a camera feed dies --- web/skins/classic/css/classic/views/montage.css | 1 + web/skins/classic/css/dark/views/montage.css | 1 + web/skins/classic/css/flat/views/montage.css | 1 + 3 files changed, 3 insertions(+) diff --git a/web/skins/classic/css/classic/views/montage.css b/web/skins/classic/css/classic/views/montage.css index f37156633..c39ea7034 100644 --- a/web/skins/classic/css/classic/views/montage.css +++ b/web/skins/classic/css/classic/views/montage.css @@ -25,6 +25,7 @@ #monitors .imageFeed img { border: 2px solid #ffffff; + display: block; } #monitors .imageFeed img.idle { diff --git a/web/skins/classic/css/dark/views/montage.css b/web/skins/classic/css/dark/views/montage.css index 9553f7ad1..70e50abb1 100644 --- a/web/skins/classic/css/dark/views/montage.css +++ b/web/skins/classic/css/dark/views/montage.css @@ -21,6 +21,7 @@ #monitors .imageFeed img { border: 2px solid #999999; + display: block; } #monitors .imageFeed img.idle { diff --git a/web/skins/classic/css/flat/views/montage.css b/web/skins/classic/css/flat/views/montage.css index e315443ff..27a87069d 100644 --- a/web/skins/classic/css/flat/views/montage.css +++ b/web/skins/classic/css/flat/views/montage.css @@ -21,6 +21,7 @@ #monitors .imageFeed img { border: 2px solid #ffffff; + display: block; } #monitors .imageFeed img.idle { From 0eb7bfabf2de8a8aa012c6b14ec08b75485bafb3 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 7 Jul 2017 12:15:09 -0400 Subject: [PATCH 09/48] put the ajax query back to a post --- web/skins/classic/views/js/log.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/js/log.js b/web/skins/classic/views/js/log.js index f78912681..a7a8aa2c6 100644 --- a/web/skins/classic/views/js/log.js +++ b/web/skins/classic/views/js/log.js @@ -1,5 +1,5 @@ var logParms = "view=request&request=log&task=query"; -var logReq = new Request.JSON( { url: thisUrl, method: 'get', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: logResponse } ); +var logReq = new Request.JSON( { url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: logResponse } ); var logTimer = undefined; var logTable = undefined; From 0faeef58c010207cb15942b351ee2a1766f5ac70 Mon Sep 17 00:00:00 2001 From: Joe Alamo Date: Mon, 10 Jul 2017 22:16:01 +0100 Subject: [PATCH 10/48] Update filterevents.rst (#1944) State where filters are actually saved --- docs/userguide/filterevents.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/userguide/filterevents.rst b/docs/userguide/filterevents.rst index 8477ef157..d3c4955c9 100644 --- a/docs/userguide/filterevents.rst +++ b/docs/userguide/filterevents.rst @@ -101,7 +101,7 @@ How filters actually work -------------------------- It is useful to know how filters actually work behind the scenes in ZoneMinder, in the event you find your filter not functioning as intended: -* the primary filter processing process in ZoneMinder is a perl file called ``zmfilter.pl`` +* the primary filter processing process in ZoneMinder is a perl file called ``zmfilter.pl`` which retrieves filters from the Filters database table * zmfilter.pl runs every FILTER_EXECUTE_INTERVAL seconds (default is 20s, can be changed in Options->System) * in each run, it goes through all the filters which are marked as "Run in Background" and if the conditions match performs the specified action * zmfilter.pl also reloads all the filters every FILTER_RELOAD_DELAY seconds (default is 300s/5mins, can be changed in Options->System) From dfd1c2844a6bb73adb260d80093c9535a309c5aa Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 11 Jul 2017 11:28:15 -0400 Subject: [PATCH 11/48] remove storageId --- web/skins/classic/views/montagereview.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/montagereview.php b/web/skins/classic/views/montagereview.php index 0c4342e8e..d3391387b 100644 --- a/web/skins/classic/views/montagereview.php +++ b/web/skins/classic/views/montagereview.php @@ -116,7 +116,7 @@ if ( !empty($_REQUEST['group']) ) { // Note we round up just a bit on the end time as otherwise you get gaps, like 59.78 to 00 in the next second, which can give blank frames when moved through slowly. $eventsSql = ' - SELECT E.Id,E.Name,E.StorageId,UNIX_TIMESTAMP(E.StartTime) AS StartTimeSecs, + SELECT E.Id,E.Name,UNIX_TIMESTAMP(E.StartTime) AS StartTimeSecs, CASE WHEN E.EndTime IS NULL THEN (SELECT UNIX_TIMESTAMP(DATE_ADD(E.StartTime, Interval max(Delta)+0.5 Second)) FROM Frames F WHERE F.EventId=E.Id) ELSE UNIX_TIMESTAMP(E.EndTime) END AS CalcEndTimeSecs, E.Length, From cb98e3faea953a34c4ec3632a6e47a35d32e7709 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 11 Jul 2017 14:11:15 -0400 Subject: [PATCH 12/48] bump version to 1.31.3 --- db/zm_update-1.31.3.sql | 62 +++++++++++++++++++++++++++++++++++++++++ version | 2 +- 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 db/zm_update-1.31.3.sql diff --git a/db/zm_update-1.31.3.sql b/db/zm_update-1.31.3.sql new file mode 100644 index 000000000..38f500c41 --- /dev/null +++ b/db/zm_update-1.31.3.sql @@ -0,0 +1,62 @@ +-- +-- This adds StorageAreas +-- + +SET @s = (SELECT IF( + (SELECT COUNT(*) + FROM INFORMATION_SCHEMA.TABLES + WHERE table_name = 'Storage' + AND table_schema = DATABASE() + ) > 0, +"SELECT 'Storage table exists'", +"CREATE TABLE `Storage` ( + `Id` smallint(5) unsigned NOT NULL auto_increment, + `Path` varchar(64) NOT NULL default '', + `Name` varchar(64) NOT NULL default '', + PRIMARY KEY (`Id`) +)" +)); + +PREPARE stmt FROM @s; +EXECUTE stmt; + +-- +-- Add StorageId column to Monitors +-- + +SET @s = (SELECT IF( + (SELECT COUNT(*) + FROM INFORMATION_SCHEMA.COLUMNS + WHERE table_name = 'Monitors' + AND table_schema = DATABASE() + AND column_name = 'StorageId' + ) > 0, +"SELECT 'Column StorageId exists in Monitors'", +"ALTER TABLE Monitors ADD `StorageId` smallint(5) unsigned NOT NULL default 0 AFTER `ServerId`" +)); + +PREPARE stmt FROM @s; +EXECUTE stmt; + +-- +-- Add StorageId column to Eventss +-- + +SET @s = (SELECT IF( + (SELECT COUNT(*) + FROM INFORMATION_SCHEMA.COLUMNS + WHERE table_name = 'Events' + AND table_schema = DATABASE() + AND column_name = 'StorageId' + ) > 0, +"SELECT 'Column StorageId exists in Events'", +"ALTER TABLE Events ADD `StorageId` smallint(5) unsigned NOT NULL default 0 AFTER `MonitorId`" +)); + +PREPARE stmt FROM @s; +EXECUTE stmt; + +UPDATE Monitors SET StorageId = 0 WHERE StorageId IS NULL; +ALTER TABLE Monitors MODIFY `StorageId` smallint(5) unsigned NOT NULL default 0; +UPDATE Events SET StorageId = 0 WHERE StorageId IS NULL; +ALTER TABLE Events MODIFY `StorageId` smallint(5) unsigned NOT NULL default 0; diff --git a/version b/version index 3492b09b4..d7f92f588 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.31.2 +1.31.3 From 786dcb0dc1099de02950cfb66d3e192edfc708a9 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 11 Jul 2017 14:31:41 -0400 Subject: [PATCH 13/48] Add orientation to Events --- db/zm_update-1.31.3.sql | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/db/zm_update-1.31.3.sql b/db/zm_update-1.31.3.sql index 38f500c41..be3cb7217 100644 --- a/db/zm_update-1.31.3.sql +++ b/db/zm_update-1.31.3.sql @@ -60,3 +60,18 @@ UPDATE Monitors SET StorageId = 0 WHERE StorageId IS NULL; ALTER TABLE Monitors MODIFY `StorageId` smallint(5) unsigned NOT NULL default 0; UPDATE Events SET StorageId = 0 WHERE StorageId IS NULL; ALTER TABLE Events MODIFY `StorageId` smallint(5) unsigned NOT NULL default 0; + +SET @s = (SELECT IF( + (SELECT COUNT(*) + FROM INFORMATION_SCHEMA.COLUMNS + WHERE table_name = 'Events' + AND table_schema = DATABASE() + AND column_name = 'Orientation' + ) > 0, +"SELECT 'Column Orientation exists in Events'", +"ALTER TABLE `Events` ADD `Orientation` enum('0','90','180','270','hori','vert') NOT NULL default '0' AFTER `Notes`" +)); + +PREPARE stmt FROM @s; +EXECUTE stmt; +~ From 4d130b85958a02cf29745ded60c7ed08b33eafc6 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 11 Jul 2017 14:42:26 -0400 Subject: [PATCH 14/48] updates to do_debian_package --- utils/do_debian_package.sh | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/utils/do_debian_package.sh b/utils/do_debian_package.sh index a825d0b62..5034f0fb9 100755 --- a/utils/do_debian_package.sh +++ b/utils/do_debian_package.sh @@ -259,23 +259,19 @@ fi if [ $TYPE == "binary" ]; then if [ "$INTERACTIVE" != "no" ]; then - read -p "Not doing dput since it's a binary release. Do you want to install it? (Y/N)" + read -p "Not doing dput since it's a binary release. Do you want to install it? (y/N)" if [[ $REPLY == [yY] ]]; then sudo dpkg -i $DIRECTORY*.deb - else - echo $REPLY; fi; - if [ "$DISTRO" == "jessie" ]; then - read -p "Do you want to upload this binary to zmrepo? (y/N)" - if [[ $REPLY == [yY] ]]; then - if [ "$RELEASE" != "" ]; then - scp "zoneminder_${VERSION}-${DISTRO}*" "zmrepo@zmrepo.connortechnology.com:debian/stable/mini-dinstall/incoming/" + read -p "Do you want to upload this binary to zmrepo? (y/N)" + if [[ $REPLY == [yY] ]]; then + if [ "$RELEASE" != "" ]; then + scp "zoneminder_${VERSION}-${DISTRO}"* "zoneminder-doc_${VERSION}-${DISTRO}"* "zoneminder-dbg_${VERSION}-${DISTRO}"* "zoneminder_${VERSION}.orig.tar.gz" "zmrepo@zmrepo.connortechnology.com:debian/stable/mini-dinstall/incoming/" + else + if [ "$BRANCH" == "" ]; then + scp "zoneminder_${VERSION}-${DISTRO}"* "zoneminder-doc_${VERSION}-${DISTRO}"* "zoneminder-dbg_${VERSION}-${DISTRO}"* "zoneminder_${VERSION}.orig.tar.gz" "zmrepo@zmrepo.connortechnology.com:debian/master/mini-dinstall/incoming/" else - if [ "$BRANCH" == "" ]; then - scp "zoneminder_${VERSION}-${DISTRO}*" "zmrepo@zmrepo.connortechnology.com:debian/master/mini-dinstall/incoming/" - else - scp "$DIRECTORY-${DISTRO}*" "zmrepo@zmrepo.connortechnology.com:debian/${BRANCH}/mini-dinstall/incoming/" - fi; + scp "$DIRECTORY-${DISTRO}"* "zoneminder-doc_${VERSION}-${DISTRO}"* "zoneminder-dbg_${VERSION}-${DISTRO}"* "zoneminder_${VERSION}.orig.tar.gz" "zmrepo@zmrepo.connortechnology.com:debian/${BRANCH}/mini-dinstall/incoming/" fi; fi; fi; @@ -295,11 +291,10 @@ else dput="Y"; if [ "$INTERACTIVE" != "no" ]; then - echo "Ready to dput $SC to $PPA ? Y/N..."; - read dput - fi - if [ "$dput" == [Yy] ]; then - dput $PPA $SC + read -p "Ready to dput $SC to $PPA ? Y/N..."; + if [[ "$REPLY" == [yY] ]]; then + dput $PPA $SC + fi; fi; fi; From 8497e4c24d97db22a897a788ba5092788e6b9b88 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 11 Jul 2017 14:59:55 -0400 Subject: [PATCH 15/48] remove tilde --- db/zm_update-1.31.3.sql | 1 - 1 file changed, 1 deletion(-) diff --git a/db/zm_update-1.31.3.sql b/db/zm_update-1.31.3.sql index be3cb7217..09a703b97 100644 --- a/db/zm_update-1.31.3.sql +++ b/db/zm_update-1.31.3.sql @@ -74,4 +74,3 @@ SET @s = (SELECT IF( PREPARE stmt FROM @s; EXECUTE stmt; -~ From a9e72288f6e6c4a028b2e3c6ce0c2200ba88084c Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 11 Jul 2017 16:11:52 -0400 Subject: [PATCH 16/48] add -safe 0 to ffmpeg command line option so that it will generate the concat file --- scripts/zmvideo.pl.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/zmvideo.pl.in b/scripts/zmvideo.pl.in index ff1469253..788ecde87 100644 --- a/scripts/zmvideo.pl.in +++ b/scripts/zmvideo.pl.in @@ -237,7 +237,7 @@ if ( $concat_name ) { } close $fd; my $command = $Config{ZM_PATH_FFMPEG} - . " -f concat -i $concat_list_file -c copy " + . " -f concat -safe 0 -i $concat_list_file -c copy " .$Config{ZM_FFMPEG_OUTPUT_OPTIONS} ." '$video_file' > $Config{ZM_PATH_LOGS}/ffmpeg_${concat_name}.log 2>&1" ; From fed4dae7e580287871dfd7c02bd54f3875bc29d5 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 11 Jul 2017 19:13:29 -0400 Subject: [PATCH 17/48] fix width and height in options --- web/includes/functions.php | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/web/includes/functions.php b/web/includes/functions.php index b50a14917..fc2f6364d 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -2133,18 +2133,14 @@ function getStreamHTML( $monitor, $options = array() ) { $options['height'] = reScale( $monitor->Height(), $options['scale'] ); } else { if ( ! isset( $options['width'] ) ) { - if ( $options['width'] == 100 ) { - $options['width'] = $monitor->Width(); - } else { $options['width'] = NULL; - } + } else if ( $options['width'] == 100 ) { + $options['width'] = $monitor->Width(); } if ( ! isset( $options['height'] ) ) { - if ( $options['height'] == 100 ) { - $options['height'] = $monitor->Height(); - } else { $options['height'] = NULL; - } + } else if ( $options['height'] == 100 ) { + $options['height'] = $monitor->Height(); } } if ( ! isset($options['mode'] ) ) { From 6c68ca40e4086d9d55cfdb07b47a7e06ab30cef1 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 11 Jul 2017 20:33:09 -0400 Subject: [PATCH 18/48] add some indexes --- db/zm_update-1.31.3.sql | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/db/zm_update-1.31.3.sql b/db/zm_update-1.31.3.sql index 09a703b97..59f9ef0f7 100644 --- a/db/zm_update-1.31.3.sql +++ b/db/zm_update-1.31.3.sql @@ -74,3 +74,39 @@ SET @s = (SELECT IF( PREPARE stmt FROM @s; EXECUTE stmt; + +-- +-- Update Monitors table to have an Index on ServerId +-- +SET @s = (SELECT IF( + (SELECT COUNT(*) + FROM INFORMATION_SCHEMA.STATISTICS + WHERE table_name = 'Monitors' + AND table_schema = DATABASE() + AND index_name = 'Monitors_ServerId_idx' + ) > 0, +"SELECT 'Monitors_ServerId Index already exists on Monitors table'", +"CREATE INDEX `Monitors_ServerId_idx` ON `Monitors` (`ServerId`)" +)); + +PREPARE stmt FROM @s; +EXECUTE stmt; + + +-- +-- Update Server table to have an Index on Name +-- +SET @s = (SELECT IF( + (SELECT COUNT(*) + FROM INFORMATION_SCHEMA.STATISTICS + WHERE table_name = 'Servers' + AND table_schema = DATABASE() + AND index_name = 'Servers_Name_idx' + ) > 0, +"SELECT 'Servers_Name Index already exists on Servers table'", +"CREATE INDEX `Servers_Name_idx` ON `Servers` (`Name`)" +)); + +PREPARE stmt FROM @s; +EXECUTE stmt; + From 046acbc05b7c9b06df7c04d7c238f6cc26318e9c Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 11 Jul 2017 20:34:06 -0400 Subject: [PATCH 19/48] fix some field --- db/zm_update-1.31.3.sql | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/db/zm_update-1.31.3.sql b/db/zm_update-1.31.3.sql index 59f9ef0f7..7b905db73 100644 --- a/db/zm_update-1.31.3.sql +++ b/db/zm_update-1.31.3.sql @@ -110,3 +110,9 @@ SET @s = (SELECT IF( PREPARE stmt FROM @s; EXECUTE stmt; + +-- ALTER TABLE Logs ALTER Message DROP DEFAULT; +ALTER TABLE Logs MODIFY Message TEXT NOT NULL; + +ALTER TABLE Config MODIFY DefaultValue TEXT; + From 4a90980fbebb0320aeabf5ee8793ed5ea92c4b8d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 11 Jul 2017 20:35:56 -0400 Subject: [PATCH 20/48] add Id to Filters --- db/zm_update-1.31.3.sql | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/db/zm_update-1.31.3.sql b/db/zm_update-1.31.3.sql index 7b905db73..0f1e6850c 100644 --- a/db/zm_update-1.31.3.sql +++ b/db/zm_update-1.31.3.sql @@ -116,3 +116,21 @@ ALTER TABLE Logs MODIFY Message TEXT NOT NULL; ALTER TABLE Config MODIFY DefaultValue TEXT; + +-- +-- Add an Id column and make it the primary key of the Filters table +-- +SET @s = (SELECT IF( + (SELECT COUNT(*) + FROM INFORMATION_SCHEMA.COLUMNS + WHERE table_name = 'Filters' + AND table_schema = DATABASE() + AND column_name = 'Id' + ) > 0, +"SELECT 'Column Id exists in Filters'", +"ALTER TABLE `Filters` DROP PRIMARY KEY, ADD `Id` int(10) unsigned NOT NULL auto_increment PRIMARY KEY FIRST, ADD KEY `Name` (`Name`);" +)); + +PREPARE stmt FROM @s; +EXECUTE stmt; + From bd681de9555475db87032a7959b75edd8ee592d4 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 12 Jul 2017 10:57:45 -0400 Subject: [PATCH 21/48] fix braces --- web/skins/classic/views/none.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/web/skins/classic/views/none.php b/web/skins/classic/views/none.php index 29ea57dcd..c409a5328 100644 --- a/web/skins/classic/views/none.php +++ b/web/skins/classic/views/none.php @@ -34,8 +34,7 @@ require_once( $skinJsPhpFile ); + From 8bbad9adf8d216e072167aae6408d01e6d22d11f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 13 Jul 2017 17:35:06 -0400 Subject: [PATCH 39/48] braces, spaces --- web/skins/classic/views/js/timeline.js.php | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/web/skins/classic/views/js/timeline.js.php b/web/skins/classic/views/js/timeline.js.php index 481b471c6..6e11ea25d 100644 --- a/web/skins/classic/views/js/timeline.js.php +++ b/web/skins/classic/views/js/timeline.js.php @@ -3,17 +3,14 @@ var filterQuery = ''; var monitors = ; From c294e25dbc327834e93f5efb26cdf719f194fa20 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Fri, 14 Jul 2017 07:23:35 -0500 Subject: [PATCH 40/48] rpm packaging - migrate cakephp htaccess parms into main apache config --- distros/redhat/systemd/zoneminder.conf.in | 29 ++++++++++- distros/redhat/sysvinit/zoneminder.conf.in | 59 +++++++++++++++++++--- 2 files changed, 78 insertions(+), 10 deletions(-) diff --git a/distros/redhat/systemd/zoneminder.conf.in b/distros/redhat/systemd/zoneminder.conf.in index 005c959a6..0e546f9df 100644 --- a/distros/redhat/systemd/zoneminder.conf.in +++ b/distros/redhat/systemd/zoneminder.conf.in @@ -16,7 +16,7 @@ Alias /zm "@ZM_WEBDIR@" DirectoryIndex index.php SSLRequireSSL Options -Indexes +MultiViews +FollowSymLinks - AllowOverride All + AllowOverride None # Apache 2.4 Require all granted @@ -31,7 +31,7 @@ Alias /zm "@ZM_WEBDIR@" ScriptAlias /cgi-bin-zm "@ZM_CGIDIR@" SSLRequireSSL - AllowOverride All + AllowOverride None Options +ExecCGI +FollowSymLinks # Apache 2.4 @@ -44,3 +44,28 @@ ScriptAlias /cgi-bin-zm "@ZM_CGIDIR@" +# For better visibility, the following directives have been migrated from the +# default .htaccess files included with the CakePHP project. +# Parameters not set here are inherited from the parent directive above. + + RewriteEngine on + RewriteRule ^$ app/webroot/ [L] + RewriteRule (.*) app/webroot/$1 [L] + RewriteBase /zm/api + + + + RewriteEngine on + RewriteRule ^$ webroot/ [L] + RewriteRule (.*) webroot/$1 [L] + RewriteBase /zm/api + + + + RewriteEngine On + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule ^ index.php [L] + RewriteBase /zm/api + + diff --git a/distros/redhat/sysvinit/zoneminder.conf.in b/distros/redhat/sysvinit/zoneminder.conf.in index 413910214..0e546f9df 100644 --- a/distros/redhat/sysvinit/zoneminder.conf.in +++ b/distros/redhat/sysvinit/zoneminder.conf.in @@ -11,18 +11,61 @@ RewriteRule ^/?(zm)(.*) https://%{SERVER_NAME}/$1$2 [R,L] Alias /zm "@ZM_WEBDIR@" + # explicitly set index.php as the only directoryindex + DirectoryIndex disabled + DirectoryIndex index.php SSLRequireSSL - Options -Indexes MultiViews FollowSymLinks - AllowOverride All - Order allow,deny - Allow from all + Options -Indexes +MultiViews +FollowSymLinks + AllowOverride None + + # Apache 2.4 + Require all granted + + + # Apache 2.2 + Order deny,allow + Allow from all + ScriptAlias /cgi-bin-zm "@ZM_CGIDIR@" SSLRequireSSL - AllowOverride All - Options ExecCGI FollowSymLinks - Order allow,deny - Allow from all + AllowOverride None + Options +ExecCGI +FollowSymLinks + + # Apache 2.4 + Require all granted + + + # Apache 2.2 + Order deny,allow + Allow from all + + +# For better visibility, the following directives have been migrated from the +# default .htaccess files included with the CakePHP project. +# Parameters not set here are inherited from the parent directive above. + + RewriteEngine on + RewriteRule ^$ app/webroot/ [L] + RewriteRule (.*) app/webroot/$1 [L] + RewriteBase /zm/api + + + + RewriteEngine on + RewriteRule ^$ webroot/ [L] + RewriteRule (.*) webroot/$1 [L] + RewriteBase /zm/api + + + + RewriteEngine On + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule ^ index.php [L] + RewriteBase /zm/api + + From df0497b3a775e45b79c6d7d3bbb129fef734af08 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 14 Jul 2017 09:25:53 -0400 Subject: [PATCH 41/48] always use onmouseover, as we can now pull images fairly quickly from the mp4 --- web/skins/classic/views/timeline.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/web/skins/classic/views/timeline.php b/web/skins/classic/views/timeline.php index 445d5453d..ade6f03e8 100644 --- a/web/skins/classic/views/timeline.php +++ b/web/skins/classic/views/timeline.php @@ -712,6 +712,7 @@ xhtmlHeaders(__FILE__, translate('Timeline') );
<?php echo translate('ViewEvent') ?> @@ -721,6 +722,7 @@ xhtmlHeaders(__FILE__, translate('Timeline') ); Your browser does not support the video tag. o--> +
@@ -817,16 +819,12 @@ foreach( array_keys($monEventSlots) as $monitorId ) { Date: Fri, 14 Jul 2017 09:26:56 -0400 Subject: [PATCH 42/48] imposing a height on the textpanel causes the text to overflow --- web/skins/classic/css/dark/views/timeline.css | 1 - web/skins/classic/css/flat/views/timeline.css | 1 - 2 files changed, 2 deletions(-) diff --git a/web/skins/classic/css/dark/views/timeline.css b/web/skins/classic/css/dark/views/timeline.css index 376dec4a3..bb1053c68 100644 --- a/web/skins/classic/css/dark/views/timeline.css +++ b/web/skins/classic/css/dark/views/timeline.css @@ -69,7 +69,6 @@ #topPanel #textPanel { text-align: left; width: 100%; - height: 140px; margin: 0 auto; color: #dddddd; font-size: 11px; diff --git a/web/skins/classic/css/flat/views/timeline.css b/web/skins/classic/css/flat/views/timeline.css index 6b66ea4e1..7ea3403c7 100644 --- a/web/skins/classic/css/flat/views/timeline.css +++ b/web/skins/classic/css/flat/views/timeline.css @@ -69,7 +69,6 @@ #topPanel #textPanel { text-align: left; width: 100%; - height: 140px; margin: 0 auto; color: #016A9D; font-size: 11px; From 99bb12dcc92395ae4f128e1fd448066b0deef963 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Fri, 14 Jul 2017 08:33:08 -0500 Subject: [PATCH 43/48] Update zoneminder.spec changes from rpmfusion feedback --- distros/redhat/zoneminder.spec | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index b36547c5d..f60ae222a 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -109,6 +109,7 @@ Requires: perl(MIME::Lite) Requires: perl(Net::SMTP) Requires: perl(Net::FTP) Requires: perl(LWP::Protocol::https) +Requires: ca-certificates %{?with_init_systemd:Requires(post): systemd} %{?with_init_systemd:Requires(post): systemd-sysv} @@ -162,7 +163,14 @@ too much degradation of performance. %make_install # Remove unwanted files and folders -find %{buildroot} \( -name .packlist -or -name .git -or -name .gitignore -or -name .gitattributes -or -name .travis.yml \) -type f -delete > /dev/null 2>&1 || : +find %{buildroot} \( -name .htaccess -or -name .editorconfig -or -name .packlist -or -name .git -or -name .gitignore -or -name .gitattributes -or -name .travis.yml \) -type f -delete > /dev/null 2>&1 || : + +# Recursively change shebang in all relevant scripts and set execute permission +find %{buildroot}%{_datadir}/zoneminder/www/api \( -name cake -or -name cake.php \) -type f -exec sed -i 's\^#!/usr/bin/env bash$\#!/usr/bin/bash\' {} \; -exec %{__chmod} 755 {} \; + +# Use the system cacert file rather then the one bundled with CakePHP +%{__rm} -f %{buildroot}%{_datadir}/zoneminder/www/api/lib/Cake/Config/cacert.pem +%{__ln_s} ../../../../../../../..%{_sysconfdir}/pki/tls/certs/ca-bundle.crt %{buildroot}%{_datadir}/zoneminder/www/api/lib/Cake/Config/cacert.pem %post %if 0%{?with_init_sysv} From e9d1474a4d235931c79625e8edd1c3a171eae421 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 14 Jul 2017 10:27:27 -0400 Subject: [PATCH 44/48] fix braces, spacing, move pod docs to bottom --- scripts/zmtrigger.pl.in | 922 ++++++++++++++++++---------------------- 1 file changed, 422 insertions(+), 500 deletions(-) diff --git a/scripts/zmtrigger.pl.in b/scripts/zmtrigger.pl.in index 0c526c83e..a231c63ed 100644 --- a/scripts/zmtrigger.pl.in +++ b/scripts/zmtrigger.pl.in @@ -2,7 +2,7 @@ # # ========================================================================== # -# ZoneMinder External Trigger Script, $Date: 2008-07-25 10:48:16 +0100 (Fri, 25 Jul 2008) $, $Revision: 2612 $ +# ZoneMinder External Trigger Script # Copyright (C) 2001-2008 Philip Coombes # # This program is free software; you can redistribute it and/or @@ -21,6 +21,426 @@ # # ========================================================================== +use strict; +use bytes; + +# ========================================================================== +# +# User config +# +# ========================================================================== + +use constant MAX_CONNECT_DELAY => 10; +use constant MONITOR_RELOAD_INTERVAL => 300; +use constant SELECT_TIMEOUT => 0.25; + +# ========================================================================== +# +# Channel/Connection Modules +# +# ========================================================================== + +@EXTRA_PERL_LIB@ +use ZoneMinder; +use ZoneMinder::Trigger::Channel::Inet; +use ZoneMinder::Trigger::Channel::Unix; +use ZoneMinder::Trigger::Channel::Serial; +use ZoneMinder::Trigger::Connection; + +my @connections; +push( @connections, + ZoneMinder::Trigger::Connection->new( + name=>'Chan1 TCP on port 6802', + channel=>ZoneMinder::Trigger::Channel::Inet->new( port=>6802 ), + mode=>'rw' + ) + ); +push( @connections, + ZoneMinder::Trigger::Connection->new( + name=>'Chan2 Unix Socket at ' . $Config{ZM_PATH_SOCKS}.'/zmtrigger.sock', + channel=>ZoneMinder::Trigger::Channel::Unix->new( + path=>$Config{ZM_PATH_SOCKS}.'/zmtrigger.sock' + ), + mode=>'rw' + ) + ); +#push( @connections, ZoneMinder::Trigger::Connection->new( name=>'Chan3', channel=>ZoneMinder::Trigger::Channel::File->new( path=>'/tmp/zmtrigger.out' ), mode=>'w' ) ); +#push( @connections, ZoneMinder::Trigger::Connection->new( name=>'Chan4', channel=>ZoneMinder::Trigger::Channel::Serial->new( path=>'/dev/ttyS0' ), mode=>'rw' ) ); + +# ========================================================================== +# +# Don't change anything from here on down +# +# ========================================================================== + +use DBI; +#use Socket; +use autouse 'Data::Dumper'=>qw(Dumper); +use POSIX qw( EINTR ); +use Time::HiRes qw( usleep ); + +$| = 1; + +$ENV{PATH} = '/bin:/usr/bin:/usr/local/bin'; +$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; +delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; + +logInit(); +logSetSignal(); + +Info( "Trigger daemon starting\n" ); + +my $dbh = zmDbConnect(); + +my $base_rin = ''; +foreach my $connection ( @connections ) { + Info( "Opening connection '$connection->{name}'\n" ); + $connection->open(); +} + +my @in_select_connections = grep { $_->input() && $_->selectable() } @connections; +my @in_poll_connections = grep { $_->input() && !$_->selectable() } @connections; +my @out_connections = grep { $_->output() } @connections; + +foreach my $connection ( @in_select_connections ) { + vec( $base_rin, $connection->fileno(), 1 ) = 1; +} + +my %spawned_connections; +my %monitors; +my $monitor_reload_time = 0; +my $needsReload = 0; +loadMonitors(); + +$! = undef; +my $rin = ''; +my $win = $rin; +my $ein = $win; +my $timeout = SELECT_TIMEOUT; +my %actions; +while( 1 ) { + $rin = $base_rin; +# Add the file descriptors of any spawned connections + foreach my $fileno ( keys(%spawned_connections) ) { + vec( $rin, $fileno, 1 ) = 1; + } + + my $nfound = select( my $rout = $rin, undef, my $eout = $ein, $timeout ); + if ( $nfound > 0 ) { + Debug( "Got input from $nfound connections\n" ); + foreach my $connection ( @in_select_connections ) { + if ( vec( $rout, $connection->fileno(), 1 ) ) { + Debug( 'Got input from connection ' + .$connection->name() + .' (' + .$connection->fileno() + .")\n" + ); + if ( $connection->spawns() ) { + my $new_connection = $connection->accept(); + $spawned_connections{$new_connection->fileno()} = $new_connection; + Debug( 'Added new spawned connection (' + .$new_connection->fileno() + .'), ' + .int(keys(%spawned_connections)) + ." spawned connections\n" + ); + } else { + my $messages = $connection->getMessages(); + if ( defined($messages) ) { + foreach my $message ( @$messages ) { + handleMessage( $connection, $message ); + } + } + } + } + } # end foreach connection + foreach my $connection ( values(%spawned_connections) ) { + if ( vec( $rout, $connection->fileno(), 1 ) ) { + Debug( 'Got input from spawned connection ' + .$connection->name() + .' (' + .$connection->fileno() + .")\n" + ); + my $messages = $connection->getMessages(); + if ( defined($messages) ) { + foreach my $message ( @$messages ) { + handleMessage( $connection, $message ); + } + } else { + delete( $spawned_connections{$connection->fileno()} ); + Debug( 'Removed spawned connection (' + .$connection->fileno() + .'), ' + .int(keys(%spawned_connections)) + ." spawned connections\n" + ); + $connection->close(); + } + } + } # end foreach spawned connection + } elsif ( $nfound < 0 ) { + if ( $! == EINTR ) { +# Do nothing + } else { + Fatal( "Can't select: $!" ); + } + } + +# Check polled connections + foreach my $connection ( @in_poll_connections ) { + my $messages = $connection->getMessages(); + if ( defined($messages) ) { + foreach my $message ( @$messages ) { + handleMessage( $connection, $message ); + } + } + } + +# Check for alarms that might have happened + my @out_messages; + foreach my $monitor ( values(%monitors) ) { + + if ( ! zmMemVerify($monitor) ) { +# Our attempt to verify the memory handle failed. We should reload the monitors. +# Don't need to zmMemInvalidate because the monitor reload will do it. + $needsReload = 1; + next; + } + + my ( $state, $last_event ) = zmMemRead( $monitor, + [ + 'shared_data:state', + 'shared_data:last_event' + ] + ); + +#print( "$monitor->{Id}: S:$state, LE:$last_event\n" ); +#print( "$monitor->{Id}: mS:$monitor->{LastState}, mLE:$monitor->{LastEvent}\n" ); + if ( $state == STATE_ALARM || $state == STATE_ALERT ) { +# In alarm state + if ( !defined($monitor->{LastEvent}) + || ($last_event != $monitor->{LastEvent}) + ) { +# A new event + push( @out_messages, $monitor->{Id}."|on|".time()."|".$last_event ); + } else { + # The same one as last time, so ignore it +# Do nothing + } + } elsif ( + ($state == STATE_IDLE && $monitor->{LastState} != STATE_IDLE) + || + ($state == STATE_TAPE && $monitor->{LastState} != STATE_TAPE) + ) { +# Out of alarm state + push( @out_messages, $monitor->{Id}.'|off|'.time().'|'.$last_event ); + } elsif ( + defined($monitor->{LastEvent}) + && + ($last_event != $monitor->{LastEvent}) + ) { + # We've missed a whole event + push( @out_messages, $monitor->{Id}.'|on|'.time().'|'.$last_event ); + push( @out_messages, $monitor->{Id}.'|off|'.time().'|'.$last_event ); + } + $monitor->{LastState} = $state; + $monitor->{LastEvent} = $last_event; + } + foreach my $connection ( @out_connections ) { + if ( $connection->canWrite() ) { + $connection->putMessages( \@out_messages ); + } + } + foreach my $connection ( values(%spawned_connections) ) { + if ( $connection->canWrite() ) { + $connection->putMessages( \@out_messages ); + } + } + + Debug( "Checking for timed actions\n" ) if int(keys(%actions)); + my $now = time(); + foreach my $action_time ( sort( grep { $_ < $now } keys( %actions ) ) ) { + Info( "Found actions expiring at $action_time\n" ); + foreach my $action ( @{$actions{$action_time}} ) { + my $connection = $action->{connection}; + my $message = $action->{message}; + Info( "Found action '$message'\n" ); + handleMessage( $connection, $message ); + } + delete( $actions{$action_time} ); + } + +# Allow connections to do their own timed actions + foreach my $connection ( @connections ) { + my $messages = $connection->timedActions(); + if ( defined($messages) ) { + foreach my $message ( @$messages ) { + handleMessage( $connection, $message ); + } + } + } + foreach my $connection ( values(%spawned_connections) ) { + my $messages = $connection->timedActions(); + if ( defined($messages) ) { + foreach my $message ( @$messages ) { + handleMessage( $connection, $message ); + } + } + } + +# If necessary reload monitors + if ( $needsReload || ((time() - $monitor_reload_time) > MONITOR_RELOAD_INTERVAL )) { + foreach my $monitor ( values(%monitors) ) { +# Free up any used memory handle + zmMemInvalidate( $monitor ); + } + loadMonitors(); + $needsReload = 0; + } +} # end while ( 1 ) +Info( "Trigger daemon exiting\n" ); +exit; + +sub loadMonitors { + Debug( "Loading monitors\n" ); + $monitor_reload_time = time(); + + my %new_monitors = (); + + my $sql = "SELECT * FROM Monitors + WHERE find_in_set( Function, 'Modect,Mocord,Nodect' )". + ( $Config{ZM_SERVER_ID} ? 'AND ServerId=?' : '' ) + ; + my $sth = $dbh->prepare_cached( $sql ) + or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID} : () ) + or Fatal( "Can't execute: ".$sth->errstr() ); + while( my $monitor = $sth->fetchrow_hashref() ) { +# Check shared memory ok + if ( !zmMemVerify( $monitor ) ) { + zmMemInvalidate( $monitor ); + next; + } + + if ( defined($monitors{$monitor->{Id}}->{LastState}) ) { + $monitor->{LastState} = $monitors{$monitor->{Id}}->{LastState}; + } else { + $monitor->{LastState} = zmGetMonitorState( $monitor ); + } + if ( defined($monitors{$monitor->{Id}}->{LastEvent}) ) { + $monitor->{LastEvent} = $monitors{$monitor->{Id}}->{LastEvent}; + } else { + $monitor->{LastEvent} = zmGetLastEvent( $monitor ); + } + $new_monitors{$monitor->{Id}} = $monitor; + } # end foreach monitor + %monitors = %new_monitors; +} # end sub loadMonitors + +sub handleMessage { + my $connection = shift; + my $message = shift; + + my ( $id, $action, $score, $cause, $text, $showtext ) + = split( /\|/, $message ); + $score = 0 if !defined($score); + $cause = '' if !defined($cause); + $text = '' if !defined($text); + + my $monitor = $monitors{$id}; + if ( !$monitor ) { + Warning( "Can't find monitor '$id' for message '$message'\n" ); + return; + } + Debug( "Found monitor for id '$id'\n" ); + + next if !zmMemVerify( $monitor ); + + Debug( "Handling action '$action'\n" ); + if ( $action =~ /^(enable|disable)(?:\+(\d+))?$/ ) { + my $state = $1; + my $delay = $2; + if ( $state eq 'enable' ) { + zmMonitorEnable( $monitor ); + } else { + zmMonitorDisable( $monitor ); + } +# Force a reload + $monitor_reload_time = 0; + Info( "Set monitor to $state\n" ); + if ( $delay ) { + my $action_text = $id."|".( ($state eq 'enable') + ? 'disable' + : 'enable' + ); + handleDelay($delay, $connection, $action_text); + } + } elsif ( $action =~ /^(on|off)(?:[ \+](\d+))?$/ ) { + next if !$monitor->{Enabled}; + + my $trigger = $1; + my $delay = $2; + my $trigger_data; + if ( $trigger eq 'on' ) { + zmTriggerEventOn( $monitor, $score, $cause, $text ); + zmTriggerShowtext( $monitor, $showtext ) if defined($showtext); + Info( "Trigger '$trigger' '$cause'\n" ); + if ( $delay ) { + my $action_text = $id.'|cancel'; + handleDelay($delay, $connection, $action_text); + } + } elsif ( $trigger eq 'off' ) { + if ( $delay ) { + my $action_text = $id.'|off|0|'.$cause.'|'.$text; + handleDelay($delay, $connection, $action_text); + } else { + my $last_event = zmGetLastEvent( $monitor ); + zmTriggerEventOff( $monitor ); + zmTriggerShowtext( $monitor, $showtext ) if defined($showtext); + Info( "Trigger '$trigger'\n" ); +# Wait til it's finished + while( zmInAlarm( $monitor ) + && ($last_event == zmGetLastEvent( $monitor )) + ) { +# Tenth of a second + usleep( 100000 ); + } + zmTriggerEventCancel( $monitor ); + } + } + } elsif( $action eq 'cancel' ) { + zmTriggerEventCancel( $monitor ); + zmTriggerShowtext( $monitor, $showtext ) if defined($showtext); + Info( "Cancelled event\n" ); + } elsif( $action eq 'show' ) { + zmTriggerShowtext( $monitor, $showtext ); + Info( "Updated show text to '$showtext'\n" ); + } else { + Error( "Unrecognised action '$action' in message '$message'\n" ); + } +} # end sub handleMessage + +sub handleDelay { + my $delay = shift; + my $connection = shift; + my $action_text = shift; + + my $action_time = time()+$delay; + my $action_array = $actions{$action_time}; + if ( !$action_array ) { + $action_array = $actions{$action_time} = []; + } + push @$action_array, { + connection => $connection, + message => $action_text + }; + Debug( "Added timed event '$action_text', expires at $action_time (+$delay secs)\n" ); +} +1; +__END__ + =head1 NAME zmtrigger.pl - ZoneMinder External Trigger Script @@ -104,504 +524,6 @@ likely to be easier. 3|on+10|1|motion|text|showtext -Triggers "alarm" on camera #3 for 10 seconds with score=1, cause="motion". +Triggers 'alarm' on camera #3 for 10 seconds with score=1, cause='motion'. =cut -use strict; -use bytes; - -# ========================================================================== -# -# User config -# -# ========================================================================== - -use constant MAX_CONNECT_DELAY => 10; -use constant MONITOR_RELOAD_INTERVAL => 300; -use constant SELECT_TIMEOUT => 0.25; - -# ========================================================================== -# -# Channel/Connection Modules -# -# ========================================================================== - -@EXTRA_PERL_LIB@ -use ZoneMinder; -use ZoneMinder::Trigger::Channel::Inet; -use ZoneMinder::Trigger::Channel::Unix; -use ZoneMinder::Trigger::Channel::Serial; -use ZoneMinder::Trigger::Connection; - -my @connections; -push( @connections, - ZoneMinder::Trigger::Connection->new( - name=>"Chan1 TCP on port 6802", - channel=>ZoneMinder::Trigger::Channel::Inet->new( port=>6802 ), - mode=>"rw" - ) -); -push( @connections, - ZoneMinder::Trigger::Connection->new( - name=>"Chan2 Unix Socket at " . $Config{ZM_PATH_SOCKS}.'/zmtrigger.sock', - channel=>ZoneMinder::Trigger::Channel::Unix->new( - path=>$Config{ZM_PATH_SOCKS}.'/zmtrigger.sock' - ), - mode=>"rw" - ) -); -#push( @connections, ZoneMinder::Trigger::Connection->new( name=>"Chan3", channel=>ZoneMinder::Trigger::Channel::File->new( path=>'/tmp/zmtrigger.out' ), mode=>"w" ) ); -#push( @connections, ZoneMinder::Trigger::Connection->new( name=>"Chan4", channel=>ZoneMinder::Trigger::Channel::Serial->new( path=>'/dev/ttyS0' ), mode=>"rw" ) ); - -# ========================================================================== -# -# Don't change anything from here on down -# -# ========================================================================== - -use DBI; -#use Socket; -use autouse 'Data::Dumper'=>qw(Dumper); -use POSIX qw( EINTR ); -use Time::HiRes qw( usleep ); - -$| = 1; - -$ENV{PATH} = '/bin:/usr/bin:/usr/local/bin'; -$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; -delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; - -logInit(); -logSetSignal(); - -Info( "Trigger daemon starting\n" ); - -my $dbh = zmDbConnect(); - -my $base_rin = ''; -foreach my $connection ( @connections ) -{ - Info( "Opening connection '$connection->{name}'\n" ); - $connection->open(); -} - -my @in_select_connections = grep { $_->input() && $_->selectable() } @connections; -my @in_poll_connections = grep { $_->input() && !$_->selectable() } @connections; -my @out_connections = grep { $_->output() } @connections; - -foreach my $connection ( @in_select_connections ) -{ - vec( $base_rin, $connection->fileno(), 1 ) = 1; -} - -my %spawned_connections; -my %monitors; -my $monitor_reload_time = 0; -my $needsReload = 0; -loadMonitors(); - - -$! = undef; -my $rin = ''; -my $win = $rin; -my $ein = $win; -my $timeout = SELECT_TIMEOUT; -my %actions; -while( 1 ) -{ - $rin = $base_rin; - # Add the file descriptors of any spawned connections - foreach my $fileno ( keys(%spawned_connections) ) - { - vec( $rin, $fileno, 1 ) = 1; - } - - my $nfound = select( my $rout = $rin, undef, my $eout = $ein, $timeout ); - if ( $nfound > 0 ) - { - Debug( "Got input from $nfound connections\n" ); - foreach my $connection ( @in_select_connections ) - { - if ( vec( $rout, $connection->fileno(), 1 ) ) - { - Debug( "Got input from connection " - .$connection->name() - ." (" - .$connection->fileno() - .")\n" - ); - if ( $connection->spawns() ) - { - my $new_connection = $connection->accept(); - $spawned_connections{$new_connection->fileno()} = $new_connection; - Debug( "Added new spawned connection (" - .$new_connection->fileno() - ."), " - .int(keys(%spawned_connections)) - ." spawned connections\n" - ); - } - else - { - my $messages = $connection->getMessages(); - if ( defined($messages) ) - { - foreach my $message ( @$messages ) - { - handleMessage( $connection, $message ); - } - } - } - } - } - foreach my $connection ( values(%spawned_connections) ) - { - if ( vec( $rout, $connection->fileno(), 1 ) ) - { - Debug( "Got input from spawned connection " - .$connection->name() - ." (" - .$connection->fileno() - .")\n" - ); - my $messages = $connection->getMessages(); - if ( defined($messages) ) - { - foreach my $message ( @$messages ) - { - handleMessage( $connection, $message ); - } - } - else - { - delete( $spawned_connections{$connection->fileno()} ); - Debug( "Removed spawned connection (" - .$connection->fileno() - ."), " - .int(keys(%spawned_connections)) - ." spawned connections\n" - ); - $connection->close(); - } - } - } - } - elsif ( $nfound < 0 ) - { - if ( $! == EINTR ) - { - # Do nothing - } - else - { - Fatal( "Can't select: $!" ); - } - } - - # Check polled connections - foreach my $connection ( @in_poll_connections ) - { - my $messages = $connection->getMessages(); - if ( defined($messages) ) - { - foreach my $message ( @$messages ) - { - handleMessage( $connection, $message ); - } - } - } - - # Check for alarms that might have happened - my @out_messages; - foreach my $monitor ( values(%monitors) ) - { - - if ( ! zmMemVerify($monitor) ) { - # Our attempt to verify the memory handle failed. We should reload the monitors. - # Don't need to zmMemInvalidate because the monitor reload will do it. - $needsReload = 1; - next; - } - - my ( $state, $last_event ) - = zmMemRead( $monitor, - [ "shared_data:state", - "shared_data:last_event" - ] - ); - - #print( "$monitor->{Id}: S:$state, LE:$last_event\n" ); - #print( "$monitor->{Id}: mS:$monitor->{LastState}, mLE:$monitor->{LastEvent}\n" ); - if ( $state == STATE_ALARM - || $state == STATE_ALERT - ) # In alarm state - { - if ( !defined($monitor->{LastEvent}) - || ($last_event != $monitor->{LastEvent}) - ) # A new event - { - push( @out_messages, $monitor->{Id}."|on|".time()."|".$last_event ); - } - else # The same one as last time, so ignore it - { - # Do nothing - } - } - elsif ( ($state == STATE_IDLE - && $monitor->{LastState} != STATE_IDLE - ) - || ($state == STATE_TAPE - && $monitor->{LastState} != STATE_TAPE - ) - ) # Out of alarm state - { - push( @out_messages, $monitor->{Id}."|off|".time()."|".$last_event ); - } - elsif ( defined($monitor->{LastEvent}) - && ($last_event != $monitor->{LastEvent}) - ) # We've missed a whole event - { - push( @out_messages, $monitor->{Id}."|on|".time()."|".$last_event ); - push( @out_messages, $monitor->{Id}."|off|".time()."|".$last_event ); - } - $monitor->{LastState} = $state; - $monitor->{LastEvent} = $last_event; - } - foreach my $connection ( @out_connections ) - { - if ( $connection->canWrite() ) - { - $connection->putMessages( \@out_messages ); - } - } - foreach my $connection ( values(%spawned_connections) ) - { - if ( $connection->canWrite() ) - { - $connection->putMessages( \@out_messages ); - } - } - - Debug( "Checking for timed actions\n" ) - if ( int(keys(%actions)) ); - my $now = time(); - foreach my $action_time ( sort( grep { $_ < $now } keys( %actions ) ) ) - { - Info( "Found actions expiring at $action_time\n" ); - foreach my $action ( @{$actions{$action_time}} ) - { - my $connection = $action->{connection}; - my $message = $action->{message}; - Info( "Found action '$message'\n" ); - handleMessage( $connection, $message ); - } - delete( $actions{$action_time} ); - } - - # Allow connections to do their own timed actions - foreach my $connection ( @connections ) - { - my $messages = $connection->timedActions(); - if ( defined($messages) ) - { - foreach my $message ( @$messages ) - { - handleMessage( $connection, $message ); - } - } - } - foreach my $connection ( values(%spawned_connections) ) - { - my $messages = $connection->timedActions(); - if ( defined($messages) ) - { - foreach my $message ( @$messages ) - { - handleMessage( $connection, $message ); - } - } - } - - # If necessary reload monitors - if ( $needsReload || ((time() - $monitor_reload_time) > MONITOR_RELOAD_INTERVAL )) - { - foreach my $monitor ( values(%monitors) ) - { - # Free up any used memory handle - zmMemInvalidate( $monitor ); - } - loadMonitors(); - $needsReload = 0; - } -} -Info( "Trigger daemon exiting\n" ); -exit; - -sub loadMonitors -{ - Debug( "Loading monitors\n" ); - $monitor_reload_time = time(); - - my %new_monitors = (); - - my $sql = "SELECT * FROM Monitors - WHERE find_in_set( Function, 'Modect,Mocord,Nodect' )". - ( $Config{ZM_SERVER_ID} ? 'AND ServerId=?' : '' ) - ; - my $sth = $dbh->prepare_cached( $sql ) - or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); - my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID} : () ) - or Fatal( "Can't execute: ".$sth->errstr() ); - while( my $monitor = $sth->fetchrow_hashref() ) - { - # Check shared memory ok - if ( !zmMemVerify( $monitor ) ) { - zmMemInvalidate( $monitor ); - next; - } - - if ( defined($monitors{$monitor->{Id}}->{LastState}) ) - { - $monitor->{LastState} = $monitors{$monitor->{Id}}->{LastState}; - } - else - { - $monitor->{LastState} = zmGetMonitorState( $monitor ); - } - if ( defined($monitors{$monitor->{Id}}->{LastEvent}) ) - { - $monitor->{LastEvent} = $monitors{$monitor->{Id}}->{LastEvent}; - } - else - { - $monitor->{LastEvent} = zmGetLastEvent( $monitor ); - } - $new_monitors{$monitor->{Id}} = $monitor; - } - %monitors = %new_monitors; -} - -sub handleMessage -{ - my $connection = shift; - my $message = shift; - - my ( $id, $action, $score, $cause, $text, $showtext ) - = split( /\|/, $message ); - $score = 0 if ( !defined($score) ); - $cause = "" if ( !defined($cause) ); - $text = "" if ( !defined($text) ); - - my $monitor = $monitors{$id}; - if ( !$monitor ) - { - Warning( "Can't find monitor '$id' for message '$message'\n" ); - return; - } - Debug( "Found monitor for id '$id'\n" ); - - next if ( !zmMemVerify( $monitor ) ); - - Debug( "Handling action '$action'\n" ); - if ( $action =~ /^(enable|disable)(?:\+(\d+))?$/ ) - { - my $state = $1; - my $delay = $2; - if ( $state eq "enable" ) - { - zmMonitorEnable( $monitor ); - } - else - { - zmMonitorDisable( $monitor ); - } - # Force a reload - $monitor_reload_time = 0; - Info( "Set monitor to $state\n" ); - if ( $delay ) - { - my $action_text = $id."|".( ($state eq "enable") - ? "disable" - : "enable" - ); - handleDelay($delay, $connection, $action_text); - } - } - elsif ( $action =~ /^(on|off)(?:[ \+](\d+))?$/ ) - { - next if ( !$monitor->{Enabled} ); - - my $trigger = $1; - my $delay = $2; - my $trigger_data; - if ( $trigger eq "on" ) - { - zmTriggerEventOn( $monitor, $score, $cause, $text ); - zmTriggerShowtext( $monitor, $showtext ) if defined($showtext); - Info( "Trigger '$trigger' '$cause'\n" ); - if ( $delay ) - { - my $action_text = $id."|cancel"; - handleDelay($delay, $connection, $action_text); - } - } - elsif ( $trigger eq "off" ) - { - if ( $delay ) - { - my $action_text = $id."|off|0|".$cause."|".$text; - handleDelay($delay, $connection, $action_text); - } else { - my $last_event = zmGetLastEvent( $monitor ); - zmTriggerEventOff( $monitor ); - zmTriggerShowtext( $monitor, $showtext ) if defined($showtext); - Info( "Trigger '$trigger'\n" ); - # Wait til it's finished - while( zmInAlarm( $monitor ) - && ($last_event == zmGetLastEvent( $monitor )) - ) - { - # Tenth of a second - usleep( 100000 ); - } - zmTriggerEventCancel( $monitor ); - } - } - } - elsif( $action eq "cancel" ) - { - zmTriggerEventCancel( $monitor ); - zmTriggerShowtext( $monitor, $showtext ) if defined($showtext); - Info( "Cancelled event\n" ); - } - elsif( $action eq "show" ) - { - zmTriggerShowtext( $monitor, $showtext ); - Info( "Updated show text to '$showtext'\n" ); - } - else - { - Error( "Unrecognised action '$action' in message '$message'\n" ); - } -} # end sub handleMessage - -sub handleDelay -{ - my $delay = shift; - my $connection = shift; - my $action_text = shift; - - my $action_time = time()+$delay; - my $action_array = $actions{$action_time}; - if ( !$action_array ) - { - $action_array = $actions{$action_time} = []; - } - push( @$action_array, { connection=>$connection, - message=>$action_text - } - ); - Debug( "Added timed event '$action_text', expires at $action_time (+$delay secs)\n" ); -} -1; -__END__ From d5a4aaca5dc59518ab09be4c447c5f163c42cee7 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 14 Jul 2017 10:28:31 -0400 Subject: [PATCH 45/48] fix braces, spacing, move pod docs to bottom --- scripts/zmtrigger.pl.in | 922 ++++++++++++++++++---------------------- 1 file changed, 422 insertions(+), 500 deletions(-) diff --git a/scripts/zmtrigger.pl.in b/scripts/zmtrigger.pl.in index 0c526c83e..a231c63ed 100644 --- a/scripts/zmtrigger.pl.in +++ b/scripts/zmtrigger.pl.in @@ -2,7 +2,7 @@ # # ========================================================================== # -# ZoneMinder External Trigger Script, $Date: 2008-07-25 10:48:16 +0100 (Fri, 25 Jul 2008) $, $Revision: 2612 $ +# ZoneMinder External Trigger Script # Copyright (C) 2001-2008 Philip Coombes # # This program is free software; you can redistribute it and/or @@ -21,6 +21,426 @@ # # ========================================================================== +use strict; +use bytes; + +# ========================================================================== +# +# User config +# +# ========================================================================== + +use constant MAX_CONNECT_DELAY => 10; +use constant MONITOR_RELOAD_INTERVAL => 300; +use constant SELECT_TIMEOUT => 0.25; + +# ========================================================================== +# +# Channel/Connection Modules +# +# ========================================================================== + +@EXTRA_PERL_LIB@ +use ZoneMinder; +use ZoneMinder::Trigger::Channel::Inet; +use ZoneMinder::Trigger::Channel::Unix; +use ZoneMinder::Trigger::Channel::Serial; +use ZoneMinder::Trigger::Connection; + +my @connections; +push( @connections, + ZoneMinder::Trigger::Connection->new( + name=>'Chan1 TCP on port 6802', + channel=>ZoneMinder::Trigger::Channel::Inet->new( port=>6802 ), + mode=>'rw' + ) + ); +push( @connections, + ZoneMinder::Trigger::Connection->new( + name=>'Chan2 Unix Socket at ' . $Config{ZM_PATH_SOCKS}.'/zmtrigger.sock', + channel=>ZoneMinder::Trigger::Channel::Unix->new( + path=>$Config{ZM_PATH_SOCKS}.'/zmtrigger.sock' + ), + mode=>'rw' + ) + ); +#push( @connections, ZoneMinder::Trigger::Connection->new( name=>'Chan3', channel=>ZoneMinder::Trigger::Channel::File->new( path=>'/tmp/zmtrigger.out' ), mode=>'w' ) ); +#push( @connections, ZoneMinder::Trigger::Connection->new( name=>'Chan4', channel=>ZoneMinder::Trigger::Channel::Serial->new( path=>'/dev/ttyS0' ), mode=>'rw' ) ); + +# ========================================================================== +# +# Don't change anything from here on down +# +# ========================================================================== + +use DBI; +#use Socket; +use autouse 'Data::Dumper'=>qw(Dumper); +use POSIX qw( EINTR ); +use Time::HiRes qw( usleep ); + +$| = 1; + +$ENV{PATH} = '/bin:/usr/bin:/usr/local/bin'; +$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; +delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; + +logInit(); +logSetSignal(); + +Info( "Trigger daemon starting\n" ); + +my $dbh = zmDbConnect(); + +my $base_rin = ''; +foreach my $connection ( @connections ) { + Info( "Opening connection '$connection->{name}'\n" ); + $connection->open(); +} + +my @in_select_connections = grep { $_->input() && $_->selectable() } @connections; +my @in_poll_connections = grep { $_->input() && !$_->selectable() } @connections; +my @out_connections = grep { $_->output() } @connections; + +foreach my $connection ( @in_select_connections ) { + vec( $base_rin, $connection->fileno(), 1 ) = 1; +} + +my %spawned_connections; +my %monitors; +my $monitor_reload_time = 0; +my $needsReload = 0; +loadMonitors(); + +$! = undef; +my $rin = ''; +my $win = $rin; +my $ein = $win; +my $timeout = SELECT_TIMEOUT; +my %actions; +while( 1 ) { + $rin = $base_rin; +# Add the file descriptors of any spawned connections + foreach my $fileno ( keys(%spawned_connections) ) { + vec( $rin, $fileno, 1 ) = 1; + } + + my $nfound = select( my $rout = $rin, undef, my $eout = $ein, $timeout ); + if ( $nfound > 0 ) { + Debug( "Got input from $nfound connections\n" ); + foreach my $connection ( @in_select_connections ) { + if ( vec( $rout, $connection->fileno(), 1 ) ) { + Debug( 'Got input from connection ' + .$connection->name() + .' (' + .$connection->fileno() + .")\n" + ); + if ( $connection->spawns() ) { + my $new_connection = $connection->accept(); + $spawned_connections{$new_connection->fileno()} = $new_connection; + Debug( 'Added new spawned connection (' + .$new_connection->fileno() + .'), ' + .int(keys(%spawned_connections)) + ." spawned connections\n" + ); + } else { + my $messages = $connection->getMessages(); + if ( defined($messages) ) { + foreach my $message ( @$messages ) { + handleMessage( $connection, $message ); + } + } + } + } + } # end foreach connection + foreach my $connection ( values(%spawned_connections) ) { + if ( vec( $rout, $connection->fileno(), 1 ) ) { + Debug( 'Got input from spawned connection ' + .$connection->name() + .' (' + .$connection->fileno() + .")\n" + ); + my $messages = $connection->getMessages(); + if ( defined($messages) ) { + foreach my $message ( @$messages ) { + handleMessage( $connection, $message ); + } + } else { + delete( $spawned_connections{$connection->fileno()} ); + Debug( 'Removed spawned connection (' + .$connection->fileno() + .'), ' + .int(keys(%spawned_connections)) + ." spawned connections\n" + ); + $connection->close(); + } + } + } # end foreach spawned connection + } elsif ( $nfound < 0 ) { + if ( $! == EINTR ) { +# Do nothing + } else { + Fatal( "Can't select: $!" ); + } + } + +# Check polled connections + foreach my $connection ( @in_poll_connections ) { + my $messages = $connection->getMessages(); + if ( defined($messages) ) { + foreach my $message ( @$messages ) { + handleMessage( $connection, $message ); + } + } + } + +# Check for alarms that might have happened + my @out_messages; + foreach my $monitor ( values(%monitors) ) { + + if ( ! zmMemVerify($monitor) ) { +# Our attempt to verify the memory handle failed. We should reload the monitors. +# Don't need to zmMemInvalidate because the monitor reload will do it. + $needsReload = 1; + next; + } + + my ( $state, $last_event ) = zmMemRead( $monitor, + [ + 'shared_data:state', + 'shared_data:last_event' + ] + ); + +#print( "$monitor->{Id}: S:$state, LE:$last_event\n" ); +#print( "$monitor->{Id}: mS:$monitor->{LastState}, mLE:$monitor->{LastEvent}\n" ); + if ( $state == STATE_ALARM || $state == STATE_ALERT ) { +# In alarm state + if ( !defined($monitor->{LastEvent}) + || ($last_event != $monitor->{LastEvent}) + ) { +# A new event + push( @out_messages, $monitor->{Id}."|on|".time()."|".$last_event ); + } else { + # The same one as last time, so ignore it +# Do nothing + } + } elsif ( + ($state == STATE_IDLE && $monitor->{LastState} != STATE_IDLE) + || + ($state == STATE_TAPE && $monitor->{LastState} != STATE_TAPE) + ) { +# Out of alarm state + push( @out_messages, $monitor->{Id}.'|off|'.time().'|'.$last_event ); + } elsif ( + defined($monitor->{LastEvent}) + && + ($last_event != $monitor->{LastEvent}) + ) { + # We've missed a whole event + push( @out_messages, $monitor->{Id}.'|on|'.time().'|'.$last_event ); + push( @out_messages, $monitor->{Id}.'|off|'.time().'|'.$last_event ); + } + $monitor->{LastState} = $state; + $monitor->{LastEvent} = $last_event; + } + foreach my $connection ( @out_connections ) { + if ( $connection->canWrite() ) { + $connection->putMessages( \@out_messages ); + } + } + foreach my $connection ( values(%spawned_connections) ) { + if ( $connection->canWrite() ) { + $connection->putMessages( \@out_messages ); + } + } + + Debug( "Checking for timed actions\n" ) if int(keys(%actions)); + my $now = time(); + foreach my $action_time ( sort( grep { $_ < $now } keys( %actions ) ) ) { + Info( "Found actions expiring at $action_time\n" ); + foreach my $action ( @{$actions{$action_time}} ) { + my $connection = $action->{connection}; + my $message = $action->{message}; + Info( "Found action '$message'\n" ); + handleMessage( $connection, $message ); + } + delete( $actions{$action_time} ); + } + +# Allow connections to do their own timed actions + foreach my $connection ( @connections ) { + my $messages = $connection->timedActions(); + if ( defined($messages) ) { + foreach my $message ( @$messages ) { + handleMessage( $connection, $message ); + } + } + } + foreach my $connection ( values(%spawned_connections) ) { + my $messages = $connection->timedActions(); + if ( defined($messages) ) { + foreach my $message ( @$messages ) { + handleMessage( $connection, $message ); + } + } + } + +# If necessary reload monitors + if ( $needsReload || ((time() - $monitor_reload_time) > MONITOR_RELOAD_INTERVAL )) { + foreach my $monitor ( values(%monitors) ) { +# Free up any used memory handle + zmMemInvalidate( $monitor ); + } + loadMonitors(); + $needsReload = 0; + } +} # end while ( 1 ) +Info( "Trigger daemon exiting\n" ); +exit; + +sub loadMonitors { + Debug( "Loading monitors\n" ); + $monitor_reload_time = time(); + + my %new_monitors = (); + + my $sql = "SELECT * FROM Monitors + WHERE find_in_set( Function, 'Modect,Mocord,Nodect' )". + ( $Config{ZM_SERVER_ID} ? 'AND ServerId=?' : '' ) + ; + my $sth = $dbh->prepare_cached( $sql ) + or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID} : () ) + or Fatal( "Can't execute: ".$sth->errstr() ); + while( my $monitor = $sth->fetchrow_hashref() ) { +# Check shared memory ok + if ( !zmMemVerify( $monitor ) ) { + zmMemInvalidate( $monitor ); + next; + } + + if ( defined($monitors{$monitor->{Id}}->{LastState}) ) { + $monitor->{LastState} = $monitors{$monitor->{Id}}->{LastState}; + } else { + $monitor->{LastState} = zmGetMonitorState( $monitor ); + } + if ( defined($monitors{$monitor->{Id}}->{LastEvent}) ) { + $monitor->{LastEvent} = $monitors{$monitor->{Id}}->{LastEvent}; + } else { + $monitor->{LastEvent} = zmGetLastEvent( $monitor ); + } + $new_monitors{$monitor->{Id}} = $monitor; + } # end foreach monitor + %monitors = %new_monitors; +} # end sub loadMonitors + +sub handleMessage { + my $connection = shift; + my $message = shift; + + my ( $id, $action, $score, $cause, $text, $showtext ) + = split( /\|/, $message ); + $score = 0 if !defined($score); + $cause = '' if !defined($cause); + $text = '' if !defined($text); + + my $monitor = $monitors{$id}; + if ( !$monitor ) { + Warning( "Can't find monitor '$id' for message '$message'\n" ); + return; + } + Debug( "Found monitor for id '$id'\n" ); + + next if !zmMemVerify( $monitor ); + + Debug( "Handling action '$action'\n" ); + if ( $action =~ /^(enable|disable)(?:\+(\d+))?$/ ) { + my $state = $1; + my $delay = $2; + if ( $state eq 'enable' ) { + zmMonitorEnable( $monitor ); + } else { + zmMonitorDisable( $monitor ); + } +# Force a reload + $monitor_reload_time = 0; + Info( "Set monitor to $state\n" ); + if ( $delay ) { + my $action_text = $id."|".( ($state eq 'enable') + ? 'disable' + : 'enable' + ); + handleDelay($delay, $connection, $action_text); + } + } elsif ( $action =~ /^(on|off)(?:[ \+](\d+))?$/ ) { + next if !$monitor->{Enabled}; + + my $trigger = $1; + my $delay = $2; + my $trigger_data; + if ( $trigger eq 'on' ) { + zmTriggerEventOn( $monitor, $score, $cause, $text ); + zmTriggerShowtext( $monitor, $showtext ) if defined($showtext); + Info( "Trigger '$trigger' '$cause'\n" ); + if ( $delay ) { + my $action_text = $id.'|cancel'; + handleDelay($delay, $connection, $action_text); + } + } elsif ( $trigger eq 'off' ) { + if ( $delay ) { + my $action_text = $id.'|off|0|'.$cause.'|'.$text; + handleDelay($delay, $connection, $action_text); + } else { + my $last_event = zmGetLastEvent( $monitor ); + zmTriggerEventOff( $monitor ); + zmTriggerShowtext( $monitor, $showtext ) if defined($showtext); + Info( "Trigger '$trigger'\n" ); +# Wait til it's finished + while( zmInAlarm( $monitor ) + && ($last_event == zmGetLastEvent( $monitor )) + ) { +# Tenth of a second + usleep( 100000 ); + } + zmTriggerEventCancel( $monitor ); + } + } + } elsif( $action eq 'cancel' ) { + zmTriggerEventCancel( $monitor ); + zmTriggerShowtext( $monitor, $showtext ) if defined($showtext); + Info( "Cancelled event\n" ); + } elsif( $action eq 'show' ) { + zmTriggerShowtext( $monitor, $showtext ); + Info( "Updated show text to '$showtext'\n" ); + } else { + Error( "Unrecognised action '$action' in message '$message'\n" ); + } +} # end sub handleMessage + +sub handleDelay { + my $delay = shift; + my $connection = shift; + my $action_text = shift; + + my $action_time = time()+$delay; + my $action_array = $actions{$action_time}; + if ( !$action_array ) { + $action_array = $actions{$action_time} = []; + } + push @$action_array, { + connection => $connection, + message => $action_text + }; + Debug( "Added timed event '$action_text', expires at $action_time (+$delay secs)\n" ); +} +1; +__END__ + =head1 NAME zmtrigger.pl - ZoneMinder External Trigger Script @@ -104,504 +524,6 @@ likely to be easier. 3|on+10|1|motion|text|showtext -Triggers "alarm" on camera #3 for 10 seconds with score=1, cause="motion". +Triggers 'alarm' on camera #3 for 10 seconds with score=1, cause='motion'. =cut -use strict; -use bytes; - -# ========================================================================== -# -# User config -# -# ========================================================================== - -use constant MAX_CONNECT_DELAY => 10; -use constant MONITOR_RELOAD_INTERVAL => 300; -use constant SELECT_TIMEOUT => 0.25; - -# ========================================================================== -# -# Channel/Connection Modules -# -# ========================================================================== - -@EXTRA_PERL_LIB@ -use ZoneMinder; -use ZoneMinder::Trigger::Channel::Inet; -use ZoneMinder::Trigger::Channel::Unix; -use ZoneMinder::Trigger::Channel::Serial; -use ZoneMinder::Trigger::Connection; - -my @connections; -push( @connections, - ZoneMinder::Trigger::Connection->new( - name=>"Chan1 TCP on port 6802", - channel=>ZoneMinder::Trigger::Channel::Inet->new( port=>6802 ), - mode=>"rw" - ) -); -push( @connections, - ZoneMinder::Trigger::Connection->new( - name=>"Chan2 Unix Socket at " . $Config{ZM_PATH_SOCKS}.'/zmtrigger.sock', - channel=>ZoneMinder::Trigger::Channel::Unix->new( - path=>$Config{ZM_PATH_SOCKS}.'/zmtrigger.sock' - ), - mode=>"rw" - ) -); -#push( @connections, ZoneMinder::Trigger::Connection->new( name=>"Chan3", channel=>ZoneMinder::Trigger::Channel::File->new( path=>'/tmp/zmtrigger.out' ), mode=>"w" ) ); -#push( @connections, ZoneMinder::Trigger::Connection->new( name=>"Chan4", channel=>ZoneMinder::Trigger::Channel::Serial->new( path=>'/dev/ttyS0' ), mode=>"rw" ) ); - -# ========================================================================== -# -# Don't change anything from here on down -# -# ========================================================================== - -use DBI; -#use Socket; -use autouse 'Data::Dumper'=>qw(Dumper); -use POSIX qw( EINTR ); -use Time::HiRes qw( usleep ); - -$| = 1; - -$ENV{PATH} = '/bin:/usr/bin:/usr/local/bin'; -$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; -delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; - -logInit(); -logSetSignal(); - -Info( "Trigger daemon starting\n" ); - -my $dbh = zmDbConnect(); - -my $base_rin = ''; -foreach my $connection ( @connections ) -{ - Info( "Opening connection '$connection->{name}'\n" ); - $connection->open(); -} - -my @in_select_connections = grep { $_->input() && $_->selectable() } @connections; -my @in_poll_connections = grep { $_->input() && !$_->selectable() } @connections; -my @out_connections = grep { $_->output() } @connections; - -foreach my $connection ( @in_select_connections ) -{ - vec( $base_rin, $connection->fileno(), 1 ) = 1; -} - -my %spawned_connections; -my %monitors; -my $monitor_reload_time = 0; -my $needsReload = 0; -loadMonitors(); - - -$! = undef; -my $rin = ''; -my $win = $rin; -my $ein = $win; -my $timeout = SELECT_TIMEOUT; -my %actions; -while( 1 ) -{ - $rin = $base_rin; - # Add the file descriptors of any spawned connections - foreach my $fileno ( keys(%spawned_connections) ) - { - vec( $rin, $fileno, 1 ) = 1; - } - - my $nfound = select( my $rout = $rin, undef, my $eout = $ein, $timeout ); - if ( $nfound > 0 ) - { - Debug( "Got input from $nfound connections\n" ); - foreach my $connection ( @in_select_connections ) - { - if ( vec( $rout, $connection->fileno(), 1 ) ) - { - Debug( "Got input from connection " - .$connection->name() - ." (" - .$connection->fileno() - .")\n" - ); - if ( $connection->spawns() ) - { - my $new_connection = $connection->accept(); - $spawned_connections{$new_connection->fileno()} = $new_connection; - Debug( "Added new spawned connection (" - .$new_connection->fileno() - ."), " - .int(keys(%spawned_connections)) - ." spawned connections\n" - ); - } - else - { - my $messages = $connection->getMessages(); - if ( defined($messages) ) - { - foreach my $message ( @$messages ) - { - handleMessage( $connection, $message ); - } - } - } - } - } - foreach my $connection ( values(%spawned_connections) ) - { - if ( vec( $rout, $connection->fileno(), 1 ) ) - { - Debug( "Got input from spawned connection " - .$connection->name() - ." (" - .$connection->fileno() - .")\n" - ); - my $messages = $connection->getMessages(); - if ( defined($messages) ) - { - foreach my $message ( @$messages ) - { - handleMessage( $connection, $message ); - } - } - else - { - delete( $spawned_connections{$connection->fileno()} ); - Debug( "Removed spawned connection (" - .$connection->fileno() - ."), " - .int(keys(%spawned_connections)) - ." spawned connections\n" - ); - $connection->close(); - } - } - } - } - elsif ( $nfound < 0 ) - { - if ( $! == EINTR ) - { - # Do nothing - } - else - { - Fatal( "Can't select: $!" ); - } - } - - # Check polled connections - foreach my $connection ( @in_poll_connections ) - { - my $messages = $connection->getMessages(); - if ( defined($messages) ) - { - foreach my $message ( @$messages ) - { - handleMessage( $connection, $message ); - } - } - } - - # Check for alarms that might have happened - my @out_messages; - foreach my $monitor ( values(%monitors) ) - { - - if ( ! zmMemVerify($monitor) ) { - # Our attempt to verify the memory handle failed. We should reload the monitors. - # Don't need to zmMemInvalidate because the monitor reload will do it. - $needsReload = 1; - next; - } - - my ( $state, $last_event ) - = zmMemRead( $monitor, - [ "shared_data:state", - "shared_data:last_event" - ] - ); - - #print( "$monitor->{Id}: S:$state, LE:$last_event\n" ); - #print( "$monitor->{Id}: mS:$monitor->{LastState}, mLE:$monitor->{LastEvent}\n" ); - if ( $state == STATE_ALARM - || $state == STATE_ALERT - ) # In alarm state - { - if ( !defined($monitor->{LastEvent}) - || ($last_event != $monitor->{LastEvent}) - ) # A new event - { - push( @out_messages, $monitor->{Id}."|on|".time()."|".$last_event ); - } - else # The same one as last time, so ignore it - { - # Do nothing - } - } - elsif ( ($state == STATE_IDLE - && $monitor->{LastState} != STATE_IDLE - ) - || ($state == STATE_TAPE - && $monitor->{LastState} != STATE_TAPE - ) - ) # Out of alarm state - { - push( @out_messages, $monitor->{Id}."|off|".time()."|".$last_event ); - } - elsif ( defined($monitor->{LastEvent}) - && ($last_event != $monitor->{LastEvent}) - ) # We've missed a whole event - { - push( @out_messages, $monitor->{Id}."|on|".time()."|".$last_event ); - push( @out_messages, $monitor->{Id}."|off|".time()."|".$last_event ); - } - $monitor->{LastState} = $state; - $monitor->{LastEvent} = $last_event; - } - foreach my $connection ( @out_connections ) - { - if ( $connection->canWrite() ) - { - $connection->putMessages( \@out_messages ); - } - } - foreach my $connection ( values(%spawned_connections) ) - { - if ( $connection->canWrite() ) - { - $connection->putMessages( \@out_messages ); - } - } - - Debug( "Checking for timed actions\n" ) - if ( int(keys(%actions)) ); - my $now = time(); - foreach my $action_time ( sort( grep { $_ < $now } keys( %actions ) ) ) - { - Info( "Found actions expiring at $action_time\n" ); - foreach my $action ( @{$actions{$action_time}} ) - { - my $connection = $action->{connection}; - my $message = $action->{message}; - Info( "Found action '$message'\n" ); - handleMessage( $connection, $message ); - } - delete( $actions{$action_time} ); - } - - # Allow connections to do their own timed actions - foreach my $connection ( @connections ) - { - my $messages = $connection->timedActions(); - if ( defined($messages) ) - { - foreach my $message ( @$messages ) - { - handleMessage( $connection, $message ); - } - } - } - foreach my $connection ( values(%spawned_connections) ) - { - my $messages = $connection->timedActions(); - if ( defined($messages) ) - { - foreach my $message ( @$messages ) - { - handleMessage( $connection, $message ); - } - } - } - - # If necessary reload monitors - if ( $needsReload || ((time() - $monitor_reload_time) > MONITOR_RELOAD_INTERVAL )) - { - foreach my $monitor ( values(%monitors) ) - { - # Free up any used memory handle - zmMemInvalidate( $monitor ); - } - loadMonitors(); - $needsReload = 0; - } -} -Info( "Trigger daemon exiting\n" ); -exit; - -sub loadMonitors -{ - Debug( "Loading monitors\n" ); - $monitor_reload_time = time(); - - my %new_monitors = (); - - my $sql = "SELECT * FROM Monitors - WHERE find_in_set( Function, 'Modect,Mocord,Nodect' )". - ( $Config{ZM_SERVER_ID} ? 'AND ServerId=?' : '' ) - ; - my $sth = $dbh->prepare_cached( $sql ) - or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); - my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID} : () ) - or Fatal( "Can't execute: ".$sth->errstr() ); - while( my $monitor = $sth->fetchrow_hashref() ) - { - # Check shared memory ok - if ( !zmMemVerify( $monitor ) ) { - zmMemInvalidate( $monitor ); - next; - } - - if ( defined($monitors{$monitor->{Id}}->{LastState}) ) - { - $monitor->{LastState} = $monitors{$monitor->{Id}}->{LastState}; - } - else - { - $monitor->{LastState} = zmGetMonitorState( $monitor ); - } - if ( defined($monitors{$monitor->{Id}}->{LastEvent}) ) - { - $monitor->{LastEvent} = $monitors{$monitor->{Id}}->{LastEvent}; - } - else - { - $monitor->{LastEvent} = zmGetLastEvent( $monitor ); - } - $new_monitors{$monitor->{Id}} = $monitor; - } - %monitors = %new_monitors; -} - -sub handleMessage -{ - my $connection = shift; - my $message = shift; - - my ( $id, $action, $score, $cause, $text, $showtext ) - = split( /\|/, $message ); - $score = 0 if ( !defined($score) ); - $cause = "" if ( !defined($cause) ); - $text = "" if ( !defined($text) ); - - my $monitor = $monitors{$id}; - if ( !$monitor ) - { - Warning( "Can't find monitor '$id' for message '$message'\n" ); - return; - } - Debug( "Found monitor for id '$id'\n" ); - - next if ( !zmMemVerify( $monitor ) ); - - Debug( "Handling action '$action'\n" ); - if ( $action =~ /^(enable|disable)(?:\+(\d+))?$/ ) - { - my $state = $1; - my $delay = $2; - if ( $state eq "enable" ) - { - zmMonitorEnable( $monitor ); - } - else - { - zmMonitorDisable( $monitor ); - } - # Force a reload - $monitor_reload_time = 0; - Info( "Set monitor to $state\n" ); - if ( $delay ) - { - my $action_text = $id."|".( ($state eq "enable") - ? "disable" - : "enable" - ); - handleDelay($delay, $connection, $action_text); - } - } - elsif ( $action =~ /^(on|off)(?:[ \+](\d+))?$/ ) - { - next if ( !$monitor->{Enabled} ); - - my $trigger = $1; - my $delay = $2; - my $trigger_data; - if ( $trigger eq "on" ) - { - zmTriggerEventOn( $monitor, $score, $cause, $text ); - zmTriggerShowtext( $monitor, $showtext ) if defined($showtext); - Info( "Trigger '$trigger' '$cause'\n" ); - if ( $delay ) - { - my $action_text = $id."|cancel"; - handleDelay($delay, $connection, $action_text); - } - } - elsif ( $trigger eq "off" ) - { - if ( $delay ) - { - my $action_text = $id."|off|0|".$cause."|".$text; - handleDelay($delay, $connection, $action_text); - } else { - my $last_event = zmGetLastEvent( $monitor ); - zmTriggerEventOff( $monitor ); - zmTriggerShowtext( $monitor, $showtext ) if defined($showtext); - Info( "Trigger '$trigger'\n" ); - # Wait til it's finished - while( zmInAlarm( $monitor ) - && ($last_event == zmGetLastEvent( $monitor )) - ) - { - # Tenth of a second - usleep( 100000 ); - } - zmTriggerEventCancel( $monitor ); - } - } - } - elsif( $action eq "cancel" ) - { - zmTriggerEventCancel( $monitor ); - zmTriggerShowtext( $monitor, $showtext ) if defined($showtext); - Info( "Cancelled event\n" ); - } - elsif( $action eq "show" ) - { - zmTriggerShowtext( $monitor, $showtext ); - Info( "Updated show text to '$showtext'\n" ); - } - else - { - Error( "Unrecognised action '$action' in message '$message'\n" ); - } -} # end sub handleMessage - -sub handleDelay -{ - my $delay = shift; - my $connection = shift; - my $action_text = shift; - - my $action_time = time()+$delay; - my $action_array = $actions{$action_time}; - if ( !$action_array ) - { - $action_array = $actions{$action_time} = []; - } - push( @$action_array, { connection=>$connection, - message=>$action_text - } - ); - Debug( "Added timed event '$action_text', expires at $action_time (+$delay secs)\n" ); -} -1; -__END__ From a07f8961d1bd58a05b65a414daf6796a7c66e71d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 14 Jul 2017 10:30:12 -0400 Subject: [PATCH 46/48] add another zmDbConnect at the bottom of the while(1) loop which will ping and reconnect to db if neccessary. --- scripts/zmtrigger.pl.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/zmtrigger.pl.in b/scripts/zmtrigger.pl.in index a231c63ed..052bf4a2d 100644 --- a/scripts/zmtrigger.pl.in +++ b/scripts/zmtrigger.pl.in @@ -299,6 +299,8 @@ while( 1 ) { loadMonitors(); $needsReload = 0; } + # zmDbConnect will ping and reconnect if neccessary + $dbh = zmDbConnect(); } # end while ( 1 ) Info( "Trigger daemon exiting\n" ); exit; From 9824049c0c428fbcb3c08e2ea0f9a591f3aeca61 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 14 Jul 2017 11:46:36 -0400 Subject: [PATCH 47/48] fix conf.d loading in api --- web/api/app/Config/bootstrap.php.in | 73 ++++++++++++++++++----------- 1 file changed, 45 insertions(+), 28 deletions(-) diff --git a/web/api/app/Config/bootstrap.php.in b/web/api/app/Config/bootstrap.php.in index ac3bcb62c..a3213d150 100644 --- a/web/api/app/Config/bootstrap.php.in +++ b/web/api/app/Config/bootstrap.php.in @@ -101,49 +101,66 @@ CakeLog::config('debug', array( 'engine' => 'File', 'types' => array('notice', 'info', 'debug'), 'file' => 'cake_debug', + 'path' => '@ZM_LOGDIR@/' )); CakeLog::config('error', array( 'engine' => 'File', 'types' => array('warning', 'error', 'critical', 'alert', 'emergency'), 'file' => 'cake_error', + 'path' => '@ZM_LOGDIR@/' )); CakeLog::config('custom_path', array( 'engine' => 'File', - 'path' => '@ZM_LOGDIR@' + 'path' => '@ZM_LOGDIR@/' )); Configure::write('ZM_CONFIG', '@ZM_CONFIG@'); +Configure::write('ZM_CONFIG_SUBDIR', '@ZM_CONFIG_SUBDIR@'); Configure::write('ZM_VERSION', '@VERSION@'); Configure::write('ZM_API_VERSION', '@API_VERSION@'); -loadConfigFile(); +# Process name, value pairs from the main config file first +$configvals = process_configfile(Configure::read('ZM_CONFIG')); -function loadConfigFile() { - $configFile = Configure::read('ZM_CONFIG'); - $localConfigFile = basename($configFile); - if ( file_exists( $localConfigFile ) && filesize( $localConfigFile ) > 0 ) - { - if ( php_sapi_name() == 'cli' && empty($_SERVER['REMOTE_ADDR']) ) - print( "Warning, overriding installed $localConfigFile file with local copy\n" ); - else - error_log( "Warning, overriding installed $localConfigFile file with local copy" ); - $configFile = $localConfigFile; - } - - $cfg = fopen( $configFile, "r") or die("Could not open config file."); - while ( !feof($cfg) ) - { - $str = fgets( $cfg, 256 ); - if ( preg_match( '/^\s*$/', $str )) - continue; - elseif ( preg_match( '/^\s*#/', $str )) - continue; - elseif ( preg_match( '/^\s*([^=\s]+)\s*=\s*(.*?)\s*$/', $str, $matches )) { - Configure::write( $matches[1], $matches[2] ); - define( $matches[1], $matches[2] ); - } - } - fclose( $cfg ); +# Search for user created config files. If one or more are found then +# update our config value array with those values +$configSubFolder = Configure::read('ZM_CONFIG_SUBDIR'); +if ( is_dir($configSubFolder) ) { + if ( is_readable($configSubFolder) ) { + foreach ( glob("$configSubFolder/*.conf") as $filename ) { + $configvals = array_replace($configvals, process_configfile($filename) ); + } + } else { + error_log( "WARNING: ZoneMinder configuration subfolder found but is not readable. Check folder permissions on $configSubFolder." ); + } } +# Now that our array our finalized, define each key => value +# pair in the array as a constant +foreach( $configvals as $key => $value) { + define( $key, $value ); + Configure::write( $matches[1], $matches[2] ); +} + +function process_configfile($configFile) { + if ( is_readable( $configFile ) ) { + $configvals = array(); + + $cfg = fopen( $configFile, "r") or die("Could not open config file."); + while ( !feof($cfg) ) { + $str = fgets( $cfg, 256 ); + if ( preg_match( '/^\s*$/', $str )) + continue; + elseif ( preg_match( '/^\s*#/', $str )) + continue; + elseif ( preg_match( '/^\s*([^=\s]+)\s*=\s*(.*?)\s*$/', $str, $matches )) + $configvals[$matches[1]] = $matches[2]; + } + fclose( $cfg ); + return( $configvals ); + } else { + error_log( "WARNING: ZoneMinder configuration file found but is not readable. Check file permissions on $configFile." ); + return( false ); + } +} From b030fee429f939ada89c1db5c6e9146ea24ea26a Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 14 Jul 2017 12:29:24 -0400 Subject: [PATCH 48/48] don't do csrf checks for control commands --- web/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/index.php b/web/index.php index a8848118d..6673b3079 100644 --- a/web/index.php +++ b/web/index.php @@ -194,7 +194,7 @@ isset($view) || $view = NULL; isset($request) || $request = NULL; isset($action) || $action = NULL; -if ( ZM_ENABLE_CSRF_MAGIC && $action != 'login' && $view != 'view_video' ) { +if ( ZM_ENABLE_CSRF_MAGIC && $action != 'login' && $view != 'view_video' && $request != 'control' ) { require_once( 'includes/csrf/csrf-magic.php' ); Logger::Debug("Calling csrf_check with the following values: \$request = \"$request\", \$view = \"$view\", \$action = \"$action\""); csrf_check();