From ef72e585b9f6d0a41f36955c21eaec84e3efd16d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 13 Feb 2018 05:26:08 -0500 Subject: [PATCH 1/6] Include id in the user object --- src/zm_user.cpp | 17 ++++++++++------- src/zm_user.h | 2 ++ src/zms.cpp | 3 ++- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/zm_user.cpp b/src/zm_user.cpp index a11303be5..86138b6ef 100644 --- a/src/zm_user.cpp +++ b/src/zm_user.cpp @@ -30,6 +30,7 @@ #include "zm_utils.h" User::User() { + id = 0; username[0] = password[0] = 0; enabled = false; stream = events = control = monitors = system = PERM_NONE; @@ -37,6 +38,7 @@ User::User() { User::User( MYSQL_ROW &dbrow ) { int index = 0; + id = atoi( dbrow[index++] ); strncpy( username, dbrow[index++], sizeof(username)-1 ); strncpy( password, dbrow[index++], sizeof(password)-1 ); enabled = (bool)atoi( dbrow[index++] ); @@ -59,6 +61,7 @@ User::~User() { } void User::Copy( const User &u ) { + id=u.id; strncpy( username, u.username, sizeof(username)-1 ); strncpy( password, u.password, sizeof(password)-1 ); enabled = u.enabled; @@ -94,9 +97,9 @@ User *zmLoadUser( const char *username, const char *password ) { if ( password ) { char safer_password[129]; // current db password size is 64 mysql_real_escape_string(&dbconn, safer_password, password, strlen( 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 Password = password('%s') and Enabled = 1", safer_username, safer_password ); + snprintf( sql, sizeof(sql), "select Id, Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds from Users where Username = '%s' and Password = password('%s') and Enabled = 1", safer_username, safer_password ); } else { - 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 ); + snprintf( sql, sizeof(sql), "select Id, 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 ) ) { @@ -124,7 +127,7 @@ User *zmLoadUser( const char *username, const char *password ) { mysql_free_result( result ); - return( user ); + return user; } // Function to validate an authentication string @@ -150,7 +153,7 @@ User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) { Debug( 1, "Attempting to authenticate user from auth string '%s'", auth ); 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" ); + snprintf( sql, sizeof(sql), "SELECT Id, Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds FROM Users WHERE Enabled = 1" ); if ( mysql_query( &dbconn, sql ) ) { Error( "Can't run query: %s", mysql_error( &dbconn ) ); @@ -171,8 +174,8 @@ User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) { } while( MYSQL_ROW dbrow = mysql_fetch_row( result ) ) { - const char *user = dbrow[0]; - const char *pass = dbrow[1]; + const char *user = dbrow[1]; + const char *pass = dbrow[2]; char auth_key[512] = ""; char auth_md5[32+1] = ""; @@ -231,5 +234,5 @@ User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) { Error( "You need to build with gnutls or openssl installed to use hash based authentication" ); #endif // HAVE_DECL_MD5 Debug(1, "No user found for auth_key %s", auth ); - return( 0 ); + return 0; } diff --git a/src/zm_user.h b/src/zm_user.h index 725acbfa2..2c932dd74 100644 --- a/src/zm_user.h +++ b/src/zm_user.h @@ -42,6 +42,7 @@ public: typedef enum { PERM_NONE=1, PERM_VIEW, PERM_EDIT } Permission; protected: + int id; char username[32+1]; char password[64+1]; bool enabled; @@ -62,6 +63,7 @@ public: Copy(u); return *this; } + const int Id() const { return id; } const char *getUsername() const { return( username ); } const char *getPassword() const { return( password ); } bool isEnabled() const { return( enabled ); } diff --git a/src/zms.cpp b/src/zms.cpp index b0bc3f9eb..66b3dc683 100644 --- a/src/zms.cpp +++ b/src/zms.cpp @@ -41,7 +41,8 @@ bool ValidateAccess( User *user, int mon_id ) { allowed = false; } if ( !allowed ) { - Error( "Error, insufficient privileges for requested action" ); + Error( "Error, insufficient privileges for requested action user %d %s for monitor %d", + user->Id(), user->getUsername(), mon_id ); exit( -1 ); } return( allowed ); From 162a08e81d475b780a6c6977c5593401144c1a1d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 13 Feb 2018 10:11:05 -0500 Subject: [PATCH 2/6] return when ReopenFfmpeg fails --- src/zm_ffmpeg_camera.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp index 3640b51de..ece9394b8 100644 --- a/src/zm_ffmpeg_camera.cpp +++ b/src/zm_ffmpeg_camera.cpp @@ -109,7 +109,6 @@ FfmpegCamera::FfmpegCamera( int p_id, const std::string &p_path, const std::stri frameCount = 0; startTime = 0; mCanCapture = false; - mOpenStart = 0; videoStore = NULL; video_last_pts = 0; have_video_keyframe = false; @@ -161,7 +160,7 @@ void FfmpegCamera::Terminate() { int FfmpegCamera::PrimeCapture() { if ( mCanCapture ) { - Info( "Priming capture from %s", mPath.c_str() ); + Info( "Priming capture from %s, CLosing", mPath.c_str() ); CloseFfmpeg(); } mVideoStreamId = -1; @@ -200,7 +199,10 @@ int FfmpegCamera::Capture( Image &image ) { (avResult == -110) ) { Info( "av_read_frame returned \"%s\". Reopening stream.", errbuf ); - ReopenFfmpeg(); + if ( (ret= ReopenFfmpeg() ) < 0 ) { + // OpenFfmpeg will do enough logging. + return -1; + } continue; } @@ -321,7 +323,6 @@ int FfmpegCamera::OpenFfmpeg() { int ret; - mOpenStart = time(NULL); have_video_keyframe = false; // Open the input, not necessarily a file @@ -364,12 +365,21 @@ int FfmpegCamera::OpenFfmpeg() { #endif { Error("Unable to open input %s due to: %s", mPath.c_str(), strerror(errno)); +#if !LIBAVFORMAT_VERSION_CHECK(53, 17, 0, 25, 0) + av_close_input_file( mFormatContext ); +#else + avformat_close_input( &mFormatContext ); +#endif + mFormatContext = NULL; + av_dict_free(&opts); + return -1; } AVDictionaryEntry *e=NULL; while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) { Warning( "Option %s not recognized by ffmpeg", e->key); } + av_dict_free(&opts); Debug(1, "Opened input"); @@ -517,6 +527,7 @@ int FfmpegCamera::OpenFfmpeg() { Warning( "Option %s not recognized by ffmpeg", e->key); } Error( "Unable to open codec for video stream from %s", mPath.c_str() ); + av_dict_free(&opts); return -1; } else { @@ -524,6 +535,7 @@ int FfmpegCamera::OpenFfmpeg() { if ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) { Warning( "Option %s not recognized by ffmpeg", e->key); } + av_dict_free(&opts); } } From 744d776d9ff69c4badead91d896858924f6323c1 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 13 Feb 2018 10:11:39 -0500 Subject: [PATCH 3/6] return when ReopenFfmpeg fails --- src/zm_ffmpeg_camera.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp index ece9394b8..b70ddcde9 100644 --- a/src/zm_ffmpeg_camera.cpp +++ b/src/zm_ffmpeg_camera.cpp @@ -199,7 +199,7 @@ int FfmpegCamera::Capture( Image &image ) { (avResult == -110) ) { Info( "av_read_frame returned \"%s\". Reopening stream.", errbuf ); - if ( (ret= ReopenFfmpeg() ) < 0 ) { + if ( ReopenFfmpeg() < 0 ) { // OpenFfmpeg will do enough logging. return -1; } From 6cfce1d5f2cca7892e1a74e5a655e334b6c04098 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 13 Feb 2018 11:27:20 -0500 Subject: [PATCH 4/6] Improve logging --- scripts/zmaudit.pl.in | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/scripts/zmaudit.pl.in b/scripts/zmaudit.pl.in index 761c07da2..228e7efad 100644 --- a/scripts/zmaudit.pl.in +++ b/scripts/zmaudit.pl.in @@ -620,9 +620,12 @@ FROM Frames WHERE EventId=?'; $res = $selectUnclosedEventsSth->execute() or Fatal( "Can't execute: ".$selectUnclosedEventsSth->errstr() ); while( my $event = $selectUnclosedEventsSth->fetchrow_hashref() ) { - aud_print( "Found open event '$event->{Id}'" ); + aud_print( "Found open event '$event->{Id}' at $$event{StartTime}" ); if ( confirm( 'close', 'closing' ) ) { - $res = $selectFrameDataSth->execute( $event->{Id} ) or Fatal( "Can't execute: ".$selectFrameDataSth->errstr() ); + if ( ! ( $res = $selectFrameDataSth->execute($event->{Id}) ) ) { + Error( "Can't execute: $selectFrameDataSql:".$selectFrameDataSth->errstr() ); + next; + } my $frame = $selectFrameDataSth->fetchrow_hashref(); if ( $frame ) { $res = $updateUnclosedEventsSth->execute( @@ -643,12 +646,13 @@ FROM Frames WHERE EventId=?'; $frame->{MaxScore}, RECOVER_TEXT, $event->{Id} - ) or Fatal( "Can't execute: ".$updateUnclosedEventsSth->errstr() ); + ) or Error( "Can't execute: ".$updateUnclosedEventsSth->errstr() ); } else { Error('SHOULD DELETE'); } # end if has frame data } } # end while unclosed event + Debug("Done closing open events."); # Now delete any old image files if ( my @old_files = grep { -M > $max_image_age } <$image_path/*.{jpg,gif,wbmp}> ) { From 535cdf6485d7ca8d707dfae0a5b8baf33d0d1d69 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 13 Feb 2018 11:27:55 -0500 Subject: [PATCH 5/6] When there isn't an event for the given moment, play the previous one. If still no events found, popup live --- web/skins/classic/views/js/montagereview.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/web/skins/classic/views/js/montagereview.js b/web/skins/classic/views/js/montagereview.js index 90a8d71b7..1d1b6fb60 100644 --- a/web/skins/classic/views/js/montagereview.js +++ b/web/skins/classic/views/js/montagereview.js @@ -706,12 +706,26 @@ function showOneMonitor(monId) { createPopup(url, 'zmWatch', 'watch', monitorWidth[monId], monitorHeight[monId] ); } else { for ( var i=0, len=eId.length; i= eStartSecs[i] && currentTimeSecs <= eEndSecs[i] ) { + if ( eMonId[i] != monId ) + continue; + + if ( currentTimeSecs >= eStartSecs[i] && currentTimeSecs <= eEndSecs[i] ) { url="?view=event&eid=" + eId[i] + '&fid=' + parseInt(Math.max(1, Math.min(eventFrames[i], eventFrames[i] * (currentTimeSecs - eStartSecs[i]) / (eEndSecs[i] - eStartSecs[i] + 1) ) )); break; + } else if ( currentTimeSecs <= eStartSecs[i] ) { + if ( i ) { + // Didn't find an exact event, so go with the one before. + url="?view=event&eid=" + eId[i] + '&fid=' + parseInt(Math.max(1, Math.min(eventFrames[i], eventFrames[i] * (currentTimeSecs - eStartSecs[i]) / (eEndSecs[i] - eStartSecs[i] + 1) ) )); + } + break; } } - createPopup(url, 'zmEvent', 'event', monitorWidth[monId], monitorHeight[monId]); + if ( url ) { + createPopup(url, 'zmEvent', 'event', monitorWidth[monId], monitorHeight[monId]); + } else { + url="?view=watch&mid=" + monId.toString(); + createPopup(url, 'zmWatch', 'watch', monitorWidth[monId], monitorHeight[monId] ); + } } } From c7a43a53f06cdad23ff7b71aa97517af4ee06efd Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 13 Feb 2018 11:28:06 -0500 Subject: [PATCH 6/6] Sort the event records --- web/skins/classic/views/montagereview.php | 1 + 1 file changed, 1 insertion(+) diff --git a/web/skins/classic/views/montagereview.php b/web/skins/classic/views/montagereview.php index 1299473ad..d2d60b8e7 100644 --- a/web/skins/classic/views/montagereview.php +++ b/web/skins/classic/views/montagereview.php @@ -199,6 +199,7 @@ if ( isset($minTime) && isset($maxTime) ) { $frameSql .= " AND TimeStamp > '" . $minTime . "' AND TimeStamp < '" . $maxTime . "'"; } $frameSql .= ' GROUP BY E.Id, E.MonitorId, F.TimeStamp, F.Delta ORDER BY E.MonitorId, F.TimeStamp ASC'; +$eventsSql .= ' ORDER BY E.Id ASC'; $monitors = array(); foreach( $displayMonitors as $row ) {