From 915450de1318c9d7b6bd313cc29aec8b39b7df1c Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 1 Jun 2017 17:48:52 -0400 Subject: [PATCH 01/10] spacing and comments --- src/zm_ffmpeg_camera.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp index b296b6fca..d11ea936e 100644 --- a/src/zm_ffmpeg_camera.cpp +++ b/src/zm_ffmpeg_camera.cpp @@ -361,7 +361,7 @@ int FfmpegCamera::OpenFfmpeg() { Fatal( "Unable to open codec for video stream from %s", mPath.c_str() ); } - if (mAudioStreamId >= 0) { + if ( mAudioStreamId >= 0 ) { mAudioCodecContext = mFormatContext->streams[mAudioStreamId]->codec; if ((mAudioCodec = avcodec_find_decoder(mAudioCodecContext->codec_id)) == NULL) { Debug(1, "Can't find codec for audio stream from %s", mPath.c_str()); @@ -434,7 +434,7 @@ int FfmpegCamera::OpenFfmpeg() { mCanCapture = true; return 0; -} +} // int FfmpegCamera::OpenFfmpeg() int FfmpegCamera::ReopenFfmpeg() { @@ -689,8 +689,11 @@ else if ( packet.pts && video_last_pts > packet.pts ) { // The following lines should ensure that the queue always begins with a video keyframe if ( packet.stream_index == mAudioStreamId ) { - if ( record_audio && packetqueue.size() ) // if it's audio, and we are doing audio, and there is already something in the queue +Debug(2, "Have audio packet, reocrd_audio is (%d) and packetqueue.size is (%d)", record_audio, packetqueue.size() ); + if ( record_audio && packetqueue.size() ) { + // if it's audio, and we are doing audio, and there is already something in the queue packetqueue.queuePacket( &packet ); + } } else if ( packet.stream_index == mVideoStreamId ) { if ( key_frame || packetqueue.size() ) // it's a keyframe or we already have something in the queue packetqueue.queuePacket( &packet ); From be5b93a64e90b09c420eae73ff46e778ac09e673 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 2 Jun 2017 11:39:35 -0400 Subject: [PATCH 02/10] whitespace, braces, quotes --- scripts/zmfilter.pl.in | 1649 ++++++++++++++++++---------------------- 1 file changed, 751 insertions(+), 898 deletions(-) diff --git a/scripts/zmfilter.pl.in b/scripts/zmfilter.pl.in index a60fc497e..ef4a2a43e 100644 --- a/scripts/zmfilter.pl.in +++ b/scripts/zmfilter.pl.in @@ -27,7 +27,7 @@ zmfilter.pl - ZoneMinder tool to filter events =head1 SYNOPSIS - zmfilter.pl [-f ,--filter=] | -v, --version +zmfilter.pl [-f ,--filter=] | -v, --version =head1 DESCRIPTION @@ -37,8 +37,8 @@ matching events. =head1 OPTIONS - -f{filter name}, --filter={filter name} - The name of a specific filter to run - -v, --version - Print ZoneMinder version +-f{filter name}, --filter={filter name} - The name of a specific filter to run +-v, --version - Print ZoneMinder version =cut use strict; @@ -70,60 +70,45 @@ use autouse 'Pod::Usage'=>qw(pod2usage); use autouse 'Data::Dumper'=>qw(Dumper); use constant EVENT_PATH => ($Config{ZM_DIR_EVENTS}=~m|/|) - ? $Config{ZM_DIR_EVENTS} - : ($Config{ZM_PATH_WEB}.'/'.$Config{ZM_DIR_EVENTS}) -; + ? $Config{ZM_DIR_EVENTS} + : ($Config{ZM_PATH_WEB}.'/'.$Config{ZM_DIR_EVENTS}) + ; -logInit(); -logSetSignal(); + logInit(); + logSetSignal(); -if ( $Config{ZM_OPT_UPLOAD} ) -{ - # Comment these out if you don't have them and don't want to upload - # or don't want to use that format - if ( $Config{ZM_UPLOAD_ARCH_FORMAT} eq "zip" ) - { - require Archive::Zip; - import Archive::Zip qw( :ERROR_CODES :CONSTANTS ); + if ( $Config{ZM_OPT_UPLOAD} ) { +# Comment these out if you don't have them and don't want to upload +# or don't want to use that format + if ( $Config{ZM_UPLOAD_ARCH_FORMAT} eq 'zip' ) { + require Archive::Zip; + import Archive::Zip qw( :ERROR_CODES :CONSTANTS ); + } else { + require Archive::Tar; } - else - { - require Archive::Tar; - } - if ( $Config{ZM_UPLOAD_PROTOCOL} eq "ftp" ) - { - require Net::FTP; - } - else - { - require Net::SFTP::Foreign; + if ( $Config{ZM_UPLOAD_PROTOCOL} eq 'ftp' ) { + require Net::FTP; + } else { + require Net::SFTP::Foreign; } + } + +if ( $Config{ZM_OPT_EMAIL} ) { + if ( $Config{ZM_NEW_MAIL_MODULES} ) { + require MIME::Lite; + require Net::SMTP; + } else { + require MIME::Entity; + } } -if ( $Config{ZM_OPT_EMAIL} ) -{ - if ( $Config{ZM_NEW_MAIL_MODULES} ) - { - require MIME::Lite; - require Net::SMTP; - } - else - { - require MIME::Entity; - } -} - -if ( $Config{ZM_OPT_MESSAGE} ) -{ - if ( $Config{ZM_NEW_MAIL_MODULES} ) - { - require MIME::Lite; - require Net::SMTP; - } - else - { - require MIME::Entity; - } +if ( $Config{ZM_OPT_MESSAGE} ) { + if ( $Config{ZM_NEW_MAIL_MODULES} ) { + require MIME::Lite; + require Net::SMTP; + } else { + require MIME::Entity; + } } $| = 1; @@ -134,7 +119,7 @@ delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; my $delay = $Config{ZM_FILTER_EXECUTE_INTERVAL}; my $event_id = 0; -my $filter_parm = ""; +my $filter_parm = ''; my $version = 0; # @@ -142,925 +127,793 @@ my $version = 0; GetOptions( 'filter=s' =>\$filter_parm, 'version' =>\$version -) or pod2usage(-exitstatus => -1); + ) or pod2usage(-exitstatus => -1); if ( $version ) { - print ZoneMinder::Base::ZM_VERSION . "\n"; - exit(0); + print ZoneMinder::Base::ZM_VERSION . '\n'; + exit(0); } if ( ! EVENT_PATH ) { - Error( "No event path defined. Config was $Config{ZM_DIR_EVENTS}\n" ); - die; + Error( "No event path defined. Config was $Config{ZM_DIR_EVENTS}\n" ); + die; } chdir( EVENT_PATH ); my $dbh = zmDbConnect(); -if ( $filter_parm ) -{ - Info( "Scanning for events using filter '$filter_parm'\n" ); -} -else -{ - Info( "Scanning for events\n" ); +if ( $filter_parm ) { + Info( "Scanning for events using filter '$filter_parm'\n" ); +} else { + Info( "Scanning for events\n" ); } -if ( !$filter_parm ) -{ - sleep( START_DELAY ); +if ( !$filter_parm ) { + sleep( START_DELAY ); } my $filters; my $last_action = 0; -while( 1 ) -{ - my $now = time; - if ( ($now - $last_action) > $Config{ZM_FILTER_RELOAD_DELAY} ) - { - Debug( "Reloading filters\n" ); - $last_action = $now; - $filters = getFilters( $filter_parm ); - } +while( 1 ) { + my $now = time; + if ( ($now - $last_action) > $Config{ZM_FILTER_RELOAD_DELAY} ) { + Debug( "Reloading filters\n" ); + $last_action = $now; + $filters = getFilters( $filter_parm ); + } - foreach my $filter ( @$filters ) - { - checkFilter( $filter ); - } + foreach my $filter ( @$filters ) { + checkFilter( $filter ); + } - last if ( $filter_parm ); + last if ( $filter_parm ); - Debug( "Sleeping for $delay seconds\n" ); - sleep( $delay ); + Debug( "Sleeping for $delay seconds\n" ); + sleep( $delay ); } -sub getFilters -{ - my $filter_name = shift; +sub getFilters { + my $filter_name = shift; - my @filters; - my $sql = "SELECT * FROM Filters WHERE"; - if ( $filter_name ) - { - $sql .= " Name = ? and"; - } - else - { - $sql .= " Background = 1 and"; - } - $sql .= "( AutoArchive = 1 - or AutoVideo = 1 - or AutoUpload = 1 - or AutoEmail = 1 - or AutoMessage = 1 - or AutoExecute = 1 - or AutoDelete = 1 - ) ORDER BY Name"; - my $sth = $dbh->prepare_cached( $sql ) + my @filters; + my $sql = 'SELECT * FROM Filters WHERE'; + if ( $filter_name ) { + $sql .= ' Name = ? and'; + } else { + $sql .= ' Background = 1 and'; + } + $sql .= '( AutoArchive = 1 + or AutoVideo = 1 + or AutoUpload = 1 + or AutoEmail = 1 + or AutoMessage = 1 + or AutoExecute = 1 + or AutoDelete = 1 + ) ORDER BY Name'; + my $sth = $dbh->prepare_cached( $sql ) + or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res; + if ( $filter_name ) { + $res = $sth->execute( $filter_name ) + or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + } else { + $res = $sth->execute() + or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + } +FILTER: while( my $db_filter = $sth->fetchrow_hashref() ) { + my $filter = new ZoneMinder::Filter( $$db_filter{Id}, $db_filter ); + Debug( "Found filter '$db_filter->{Name}'\n" ); + my $sql = $filter->Sql(); + + if ( ! $sql ) { + Error( "Error parsing Sql. skipping filter '$db_filter->{Name}'\n" ); + next FILTER; + } + push( @filters, $filter ); + } + $sth->finish(); + Debug( 'Got ' . @filters . ' filters' ); + return( \@filters ); +} + +sub checkFilter { + my $filter = shift; + + Debug( "Checking filter '$filter->{Name}'". + ($filter->{AutoDelete}?', delete':''). + ($filter->{AutoArchive}?', archive':''). + ($filter->{AutoVideo}?', video':''). + ($filter->{AutoUpload}?', upload':''). + ($filter->{AutoEmail}?', email':''). + ($filter->{AutoMessage}?', message':''). + ($filter->{AutoExecute}?', execute':''). + '\n' + ); + + foreach my $event ( $filter->Execute() ) { + Debug( "Checking event $event->{Id}\n" ); + my $delete_ok = !undef; + $dbh->ping(); + if ( $filter->{AutoArchive} ) { + Info( "Archiving event $event->{Id}\n" ); +# Do it individually to avoid locking up the table for new events + my $sql = 'update Events set Archived = 1 where Id = ?'; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); - my $res; - if ( $filter_name ) - { - $res = $sth->execute( $filter_name ) - or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + my $res = $sth->execute( $event->{Id} ) + or Error( "Can't execute '$sql': ".$sth->errstr() ); } - else - { - $res = $sth->execute() - or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + if ( $Config{ZM_OPT_FFMPEG} && $filter->{AutoVideo} ) { + if ( !$event->{Videoed} ) { + $delete_ok = undef if ( !generateVideo( $filter, $event ) ); + } } - FILTER: while( my $db_filter = $sth->fetchrow_hashref() ) - { - my $filter = new ZoneMinder::Filter( $$db_filter{Id}, $db_filter ); - Debug( "Found filter '$db_filter->{Name}'\n" ); - my $sql = $filter->Sql(); - - if ( ! $sql ) { - Error( "Error parsing Sql. skipping filter '$db_filter->{Name}'\n" ); - next FILTER; - } - push( @filters, $filter ); + if ( $Config{ZM_OPT_EMAIL} && $filter->{AutoEmail} ) { + if ( !$event->{Emailed} ) { + $delete_ok = undef if ( !sendEmail( $filter, $event ) ); + } } - $sth->finish(); - Debug( "Got " . @filters . " filters" ); - return( \@filters ); -} - -sub checkFilter -{ - my $filter = shift; - - Debug( "Checking filter '$filter->{Name}'". - ($filter->{AutoDelete}?", delete":""). - ($filter->{AutoArchive}?", archive":""). - ($filter->{AutoVideo}?", video":""). - ($filter->{AutoUpload}?", upload":""). - ($filter->{AutoEmail}?", email":""). - ($filter->{AutoMessage}?", message":""). - ($filter->{AutoExecute}?", execute":""). - "\n" - ); - - foreach my $event ( $filter->Execute() ) { - Debug( "Checking event $event->{Id}\n" ); - my $delete_ok = !undef; -$dbh->ping(); - if ( $filter->{AutoArchive} ) - { - Info( "Archiving event $event->{Id}\n" ); - # Do it individually to avoid locking up the table for new events - my $sql = "update Events set Archived = 1 where Id = ?"; - my $sth = $dbh->prepare_cached( $sql ) - or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); - my $res = $sth->execute( $event->{Id} ) - or Error( "Can't execute '$sql': ".$sth->errstr() ); - } - if ( $Config{ZM_OPT_FFMPEG} && $filter->{AutoVideo} ) - { - if ( !$event->{Videoed} ) - { - $delete_ok = undef if ( !generateVideo( $filter, $event ) ); - } - } - if ( $Config{ZM_OPT_EMAIL} && $filter->{AutoEmail} ) - { - if ( !$event->{Emailed} ) - { - $delete_ok = undef if ( !sendEmail( $filter, $event ) ); - } - } - if ( $Config{ZM_OPT_MESSAGE} && $filter->{AutoMessage} ) - { - if ( !$event->{Messaged} ) - { - $delete_ok = undef if ( !sendMessage( $filter, $event ) ); - } - } - if ( $Config{ZM_OPT_UPLOAD} && $filter->{AutoUpload} ) - { - if ( !$event->{Uploaded} ) - { - $delete_ok = undef if ( !uploadArchFile( $filter, $event ) ); - } - } - if ( $filter->{AutoExecute} ) - { - if ( !$event->{Executed} ) - { - $delete_ok = undef if ( !executeCommand( $filter, $event ) ); - } - } - if ( $filter->{AutoDelete} ) - { - if ( $delete_ok ) - { - Info( "Deleting event $event->{Id} from Monitor $event->{MonitorId}\n" ); - # Do it individually to avoid locking up the table for new events - my $sql = "delete from Events where Id = ?"; - my $sth = $dbh->prepare_cached( $sql ) - or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); - my $res = $sth->execute( $event->{Id} ) - or Fatal( "Can't execute '$sql': ".$sth->errstr() ); - - if ( ! $Config{ZM_OPT_FAST_DELETE} ) - { - my $sql = "delete from Frames where EventId = ?"; - my $sth = $dbh->prepare_cached( $sql ) - or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); - my $res = $sth->execute( $event->{Id} ) - or Fatal( "Can't execute '$sql': ".$sth->errstr() ); - - $sql = "delete from Stats where EventId = ?"; - $sth = $dbh->prepare_cached( $sql ) - or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); - $res = $sth->execute( $event->{Id} ) - or Fatal( "Can't execute '$sql': ".$sth->errstr() ); - - deleteEventFiles( $event->{Id}, $event->{MonitorId} ); - } - } - else - { - Error( "Unable to delete event $event->{Id} as previous operations failed\n" ); - } - } + if ( $Config{ZM_OPT_MESSAGE} && $filter->{AutoMessage} ) { + if ( !$event->{Messaged} ) { + $delete_ok = undef if ( !sendMessage( $filter, $event ) ); + } } -} - -sub generateVideo -{ - my $filter = shift; - my $event = shift; - my $phone = shift; - - my $rate = $event->{DefaultRate}/100; - my $scale = $event->{DefaultScale}/100; - my $format; - - my @ffmpeg_formats = split( /\s+/, $Config{ZM_FFMPEG_FORMATS} ); - my $default_video_format; - my $default_phone_format; - foreach my $ffmpeg_format( @ffmpeg_formats ) - { - if ( $ffmpeg_format =~ /^(.+)\*\*$/ ) - { - $default_phone_format = $1; - } - elsif ( $ffmpeg_format =~ /^(.+)\*$/ ) - { - $default_video_format = $1; - } + if ( $Config{ZM_OPT_UPLOAD} && $filter->{AutoUpload} ) { + if ( !$event->{Uploaded} ) { + $delete_ok = undef if ( !uploadArchFile( $filter, $event ) ); + } } - - if ( $phone && $default_phone_format ) - { - $format = $default_phone_format; + if ( $filter->{AutoExecute} ) { + if ( !$event->{Executed} ) { + $delete_ok = undef if ( !executeCommand( $filter, $event ) ); + } } - elsif ( $default_video_format ) - { - $format = $default_video_format; - } - else - { - $format = $ffmpeg_formats[0]; - } - - my $command = $Config{ZM_PATH_BIN}."/zmvideo.pl -e " - .$event->{Id}." -r ".$rate." -s ".$scale." -f ".$format; - my $output = qx($command); - chomp( $output ); - my $status = $? >> 8; - if ( $status || logDebugging() ) - { - Debug( "Output: $output\n" ); - } - if ( $status ) - { - Error( "Video generation '$command' failed with status: $status\n" ); - if ( wantarray() ) - { - return( undef, undef ); - } - return( 0 ); - } - else - { - my $sql = "update Events set Videoed = 1 where Id = ?"; + if ( $filter->{AutoDelete} ) { + if ( $delete_ok ) { + Info( "Deleting event $event->{Id} from Monitor $event->{MonitorId}\n" ); +# Do it individually to avoid locking up the table for new events + my $sql = 'delete from Events where Id = ?'; my $sth = $dbh->prepare_cached( $sql ) - or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); my $res = $sth->execute( $event->{Id} ) + or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + + if ( ! $Config{ZM_OPT_FAST_DELETE} ) { + my $sql = 'delete from Frames where EventId = ?'; + my $sth = $dbh->prepare_cached( $sql ) + or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{Id} ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); - if ( wantarray() ) - { - return( $format, $output ); + + $sql = 'delete from Stats where EventId = ?'; + $sth = $dbh->prepare_cached( $sql ) + or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + $res = $sth->execute( $event->{Id} ) + or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + + deleteEventFiles( $event->{Id}, $event->{MonitorId} ); } + } else { + Error( "Unable to delete event $event->{Id} as previous operations failed\n" ); + } } - return( 1 ); + } +} + +sub generateVideo { + my $filter = shift; + my $event = shift; + my $phone = shift; + + my $rate = $event->{DefaultRate}/100; + my $scale = $event->{DefaultScale}/100; + my $format; + + my @ffmpeg_formats = split( /\s+/, $Config{ZM_FFMPEG_FORMATS} ); + my $default_video_format; + my $default_phone_format; + foreach my $ffmpeg_format( @ffmpeg_formats ) { + if ( $ffmpeg_format =~ /^(.+)\*\*$/ ) { + $default_phone_format = $1; + } elsif ( $ffmpeg_format =~ /^(.+)\*$/ ) { + $default_video_format = $1; + } + } + + if ( $phone && $default_phone_format ) { + $format = $default_phone_format; + } elsif ( $default_video_format ) { + $format = $default_video_format; + } else { + $format = $ffmpeg_formats[0]; + } + + my $command = join('', + $Config{ZM_PATH_BIN}, + '/zmvideo.pl -e ', + .$event->{Id}, + ' -r ',$rate,' -s ',$scale,' -f ',$format, + ); + my $output = qx($command); + chomp( $output ); + my $status = $? >> 8; + if ( $status || logDebugging() ) { + Debug( "Output: $output\n" ); + } + if ( $status ) { + Error( "Video generation '$command' failed with status: $status\n" ); + if ( wantarray() ) { + return( undef, undef ); + } + return( 0 ); + } else { + my $sql = 'update Events set Videoed = 1 where Id = ?'; + my $sth = $dbh->prepare_cached( $sql ) + or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{Id} ) + or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + if ( wantarray() ) { + return( $format, $output ); + } + } + return( 1 ); } # Returns an image absolute path for given event and frame # Optionally an analyse image path may be returned if an analyse image exists # If neither capture nor analyse image exists it will try to extract a frame from .mp4 file if exists # An empty string is returned if no one from methods above works -sub generateImage -{ - my $event = shift; - my $frame = shift; - my $analyse = do { @_ ? shift : 0 }; # don't return analyse image by default +sub generateImage { + my $event = shift; + my $frame = shift; + my $analyse = do { @_ ? shift : 0 }; # don't return analyse image by default - my $capture_image_path = sprintf("%s/%0".$Config{ZM_EVENT_IMAGE_DIGITS}."d-capture.jpg", getEventPath($event), $frame->{FrameId}); - my $analyse_image_path = sprintf("%s/%0".$Config{ZM_EVENT_IMAGE_DIGITS}."d-analyse.jpg", getEventPath($event), $frame->{FrameId}) if $analyse; - my $video_path = sprintf("%s/%d-video.mp4", getEventPath($event), $event->{Id}); - my $image_path = ""; + my $capture_image_path = sprintf('%s/%0'.$Config{ZM_EVENT_IMAGE_DIGITS}.'d-capture.jpg', getEventPath($event), $frame->{FrameId}); + my $analyse_image_path = sprintf('%s/%0'.$Config{ZM_EVENT_IMAGE_DIGITS}.'d-analyse.jpg', getEventPath($event), $frame->{FrameId}) if $analyse; + my $video_path = sprintf('%s/%d-video.mp4', getEventPath($event), $event->{Id}); + my $image_path = ''; - # check if the image file exists. If the file doesn't exist and we use H264 try to extract it from .mp4 video - if ( $analyse && -r $analyse_image_path ) { - $image_path = $analyse_image_path; - } elsif ( -r $capture_image_path ) { - $image_path = $capture_image_path; - } elsif ( -e $video_path ) { - if ( !system("ffmpeg -y -v 0 -i ".$video_path." -vf 'select=gte(n\\,".$frame->{FrameId}."),setpts=PTS-STARTPTS' -vframes 1 -f image2 ".$capture_image_path) ) { - $image_path = $capture_image_path; - } +# check if the image file exists. If the file doesn't exist and we use H264 try to extract it from .mp4 video + if ( $analyse && -r $analyse_image_path ) { + $image_path = $analyse_image_path; + } elsif ( -r $capture_image_path ) { + $image_path = $capture_image_path; + } elsif ( -e $video_path ) { + if ( !system('ffmpeg -y -v 0 -i '.$video_path." -vf 'select=gte(n\\,".$frame->{FrameId}."),setpts=PTS-STARTPTS' -vframes 1 -f image2 ".$capture_image_path) ) { + $image_path = $capture_image_path; } - return $image_path; + } + return $image_path; } -sub uploadArchFile -{ - my $filter = shift; - my $event = shift; +sub uploadArchFile { + my $filter = shift; + my $event = shift; - if ( ! $Config{ZM_UPLOAD_HOST} ) - { - Error( "Cannot upload archive as no upload host defined" ); - return( 0 ); - } + if ( ! $Config{ZM_UPLOAD_HOST} ) { + Error( 'Cannot upload archive as no upload host defined' ); + return( 0 ); + } - my $archFile = $event->{MonitorName}.'-'.$event->{Id}; - my $archImagePath = getEventPath( $event ) - ."/" - .( - ( $Config{ZM_UPLOAD_ARCH_ANALYSE} ) - ? '{*analyse,*capture}' - : '*capture' - ) - .".jpg" + my $archFile = $event->{MonitorName}.'-'.$event->{Id}; + my $archImagePath = getEventPath( $event ) + .'/' + .( + ( $Config{ZM_UPLOAD_ARCH_ANALYSE} ) + ? '{*analyse,*capture}' + : '*capture' + ) + .'.jpg' ; - my @archImageFiles = glob($archImagePath); - my $archLocPath; + my @archImageFiles = glob($archImagePath); + my $archLocPath; - my $archError = 0; - if ( $Config{ZM_UPLOAD_ARCH_FORMAT} eq "zip" ) - { - $archFile .= '.zip'; - $archLocPath = $Config{ZM_UPLOAD_LOC_DIR}.'/'.$archFile; - my $zip = Archive::Zip->new(); - Info( "Creating upload file '$archLocPath', ".int(@archImageFiles)." files\n" ); + my $archError = 0; + if ( $Config{ZM_UPLOAD_ARCH_FORMAT} eq 'zip' ) { + $archFile .= '.zip'; + $archLocPath = $Config{ZM_UPLOAD_LOC_DIR}.'/'.$archFile; + my $zip = Archive::Zip->new(); + Info( "Creating upload file '$archLocPath', ".int(@archImageFiles)." files\n" ); - my $status = &AZ_OK; - foreach my $imageFile ( @archImageFiles ) - { - Debug( "Adding $imageFile\n" ); - my $member = $zip->addFile( $imageFile ); - if ( !$member ) - { - Error( "Unable to add image file $imageFile to zip archive $archLocPath" ); - $archError = 1; - last; - } - $member->desiredCompressionMethod( $Config{ZM_UPLOAD_ARCH_COMPRESS} - ? &COMPRESSION_DEFLATED - : &COMPRESSION_STORED - ); - } - if ( !$archError ) - { - $status = $zip->writeToFileNamed( $archLocPath ); - - if ( $archError = ($status != &AZ_OK) ) - { - Error( "Zip error: $status\n " ); - } - } - else - { - Error( "Error adding images to zip archive $archLocPath, not writing" ); - } + my $status = &AZ_OK; + foreach my $imageFile ( @archImageFiles ) { + Debug( "Adding $imageFile\n" ); + my $member = $zip->addFile( $imageFile ); + if ( !$member ) { + Error( "Unable to add image file $imageFile to zip archive $archLocPath" ); + $archError = 1; + last; + } + $member->desiredCompressionMethod( $Config{ZM_UPLOAD_ARCH_COMPRESS} + ? &COMPRESSION_DEFLATED + : &COMPRESSION_STORED + ); } - elsif ( $Config{ZM_UPLOAD_ARCH_FORMAT} eq "tar" ) - { - if ( $Config{ZM_UPLOAD_ARCH_COMPRESS} ) - { - $archFile .= '.tar.gz'; - } - else - { - $archFile .= '.tar'; - } - $archLocPath = $Config{ZM_UPLOAD_LOC_DIR}.'/'.$archFile; - Info( "Creating upload file '$archLocPath', ".int(@archImageFiles)." files\n" ); + if ( !$archError ) { + $status = $zip->writeToFileNamed( $archLocPath ); - if ( $archError = !Archive::Tar->create_archive( - $archLocPath, - $Config{ZM_UPLOAD_ARCH_COMPRESS}, - @archImageFiles - ) - ) - { - Error( "Tar error: ".Archive::Tar->error()."\n " ); - } + if ( $archError = ($status != &AZ_OK) ) { + Error( "Zip error: $status\n " ); + } + } else { + Error( "Error adding images to zip archive $archLocPath, not writing" ); } + } elsif ( $Config{ZM_UPLOAD_ARCH_FORMAT} eq 'tar' ) { + if ( $Config{ZM_UPLOAD_ARCH_COMPRESS} ) { + $archFile .= '.tar.gz'; + } else { + $archFile .= '.tar'; + } + $archLocPath = $Config{ZM_UPLOAD_LOC_DIR}.'/'.$archFile; + Info( "Creating upload file '$archLocPath', ".int(@archImageFiles)." files\n" ); - if ( $archError ) - { + if ( $archError = !Archive::Tar->create_archive( + $archLocPath, + $Config{ZM_UPLOAD_ARCH_COMPRESS}, + @archImageFiles + ) + ) { + Error( 'Tar error: '.Archive::Tar->error()."\n " ); + } + } + + if ( $archError ) { + return( 0 ); + } else { + if ( $Config{ZM_UPLOAD_PROTOCOL} eq 'ftp' ) { + Info( 'Uploading to '.$Config{ZM_UPLOAD_HOST}." using FTP\n" ); + my $ftp = Net::FTP->new( + $Config{ZM_UPLOAD_HOST}, + Timeout=>$Config{ZM_UPLOAD_TIMEOUT}, + Passive=>$Config{ZM_UPLOAD_FTP_PASSIVE}, + Debug=>$Config{ZM_UPLOAD_DEBUG} + ); + if ( !$ftp ) { + Error( "Can't create FTP connection: $@" ); return( 0 ); - } - else - { - if ( $Config{ZM_UPLOAD_PROTOCOL} eq "ftp" ) - { - Info( "Uploading to ".$Config{ZM_UPLOAD_HOST}." using FTP\n" ); - my $ftp = Net::FTP->new( - $Config{ZM_UPLOAD_HOST}, - Timeout=>$Config{ZM_UPLOAD_TIMEOUT}, - Passive=>$Config{ZM_UPLOAD_FTP_PASSIVE}, - Debug=>$Config{ZM_UPLOAD_DEBUG} - ); - if ( !$ftp ) - { - Error( "Can't create FTP connection: $@" ); - return( 0 ); - } - $ftp->login( $Config{ZM_UPLOAD_USER}, $Config{ZM_UPLOAD_PASS} ) - or Error( "FTP - Can't login" ); - $ftp->binary() - or Error( "FTP - Can't go binary" ); - $ftp->cwd( $Config{ZM_UPLOAD_REM_DIR} ) - or Error( "FTP - Can't cwd" ) - if ( $Config{ZM_UPLOAD_REM_DIR} ); - $ftp->put( $archLocPath ) - or Error( "FTP - Can't upload '$archLocPath'" ); - $ftp->quit() - or Error( "FTP - Can't quit" ); - } - else - { - my $host = $Config{ZM_UPLOAD_HOST}; - $host .= ":".$Config{ZM_UPLOAD_PORT} - if $Config{ZM_UPLOAD_PORT}; - Info( "Uploading to ".$host." using SFTP\n" ); - my %sftpOptions = ( host=>$Config{ZM_UPLOAD_HOST}, user=>$Config{ZM_UPLOAD_USER} ); - $sftpOptions{password} = $Config{ZM_UPLOAD_PASS} - if $Config{ZM_UPLOAD_PASS}; - $sftpOptions{port} = $Config{ZM_UPLOAD_PORT} - if $Config{ZM_UPLOAD_PORT}; - $sftpOptions{timeout} = $Config{ZM_UPLOAD_TIMEOUT} - if $Config{ZM_UPLOAD_TIMEOUT}; - my @more_ssh_args; - push @more_ssh_args, '-o'=>'StrictHostKeyChecking=no' - if ! $Config{ZM_UPLOAD_STRICT}; - push @more_ssh_args, '-v' - if $Config{ZM_UPLOAD_DEBUG}; - $sftpOptions{more} = [@more_ssh_args]; - my $sftp = Net::SFTP::Foreign->new( $Config{ZM_UPLOAD_HOST}, %sftpOptions ); - if ( $sftp->error ) - { - Error( "Can't create SFTP connection: ".$sftp->error ); - return( 0 ); - } - $sftp->setcwd( $Config{ZM_UPLOAD_REM_DIR} ) - or Error( "SFTP - Can't setcwd: ".$sftp->error ) - if $Config{ZM_UPLOAD_REM_DIR}; - $sftp->put( $archLocPath, $archFile ) - or Error( "SFTP - Can't upload '$archLocPath': ".$sftp->error ); - } - unlink( $archLocPath ); - my $sql = "update Events set Uploaded = 1 where Id = ?"; - my $sth = $dbh->prepare_cached( $sql ) - or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); - my $res = $sth->execute( $event->{Id} ) - or Fatal( "Can't execute '$sql': ".$sth->errstr() ); - } - return( 1 ); -} - -sub substituteTags -{ - my $text = shift; - my $filter = shift; - my $event = shift; - my $attachments_ref = shift; - - # First we'd better check what we need to get - # We have a filter and an event, do we need any more - # monitor information? - my $need_monitor = $text =~ /%(?:MET|MEH|MED|MEW|MEN|MEA)%/; - - my $monitor = {}; - if ( $need_monitor ) - { - my $db_now = strftime( "%Y-%m-%d %H:%M:%S", localtime() ); - my $sql = "SELECT - M.Id, - count(E.Id) as EventCount, - count(if(E.Archived,1,NULL)) - as ArchEventCount, - count(if(E.StartTime>'$db_now' - INTERVAL 1 HOUR && E.Archived = 0,1,NULL)) - as HourEventCount, - count(if(E.StartTime>'$db_now' - INTERVAL 1 DAY && E.Archived = 0,1,NULL)) - as DayEventCount, - count(if(E.StartTime>'$db_now' - INTERVAL 7 DAY && E.Archived = 0,1,NULL)) - as WeekEventCount, - count(if(E.StartTime>'$db_now' - INTERVAL 1 MONTH && E.Archived = 0,1,NULL)) - as MonthEventCount - FROM Monitors as M LEFT JOIN Events as E on E.MonitorId = M.Id - WHERE MonitorId = ? - GROUP BY E.MonitorId - ORDER BY Id" - ; - my $sth = $dbh->prepare_cached( $sql ) - or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); - my $res = $sth->execute( $event->{MonitorId} ) - or Fatal( "Can't execute '$sql': ".$sth->errstr() ); - $monitor = $sth->fetchrow_hashref(); - $sth->finish(); - return() if ( !$monitor ); - } - - # Do we need the image information too? - my $need_images = $text =~ /%(?:EPI1|EPIM|EI1|EIM|EI1A|EIMA)%/; - my $first_alarm_frame; - my $max_alarm_frame; - my $max_alarm_score = 0; - if ( $need_images ) - { - my $sql = "SELECT * FROM Frames - WHERE EventId = ? AND Type = 'Alarm' - ORDER BY FrameId" - ; - my $sth = $dbh->prepare_cached( $sql ) - or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); - my $res = $sth->execute( $event->{Id} ) - or Fatal( "Can't execute '$sql': ".$sth->errstr() ); - while( my $frame = $sth->fetchrow_hashref() ) - { - if ( !$first_alarm_frame ) - { - $first_alarm_frame = $frame; - } - if ( $frame->{Score} > $max_alarm_score ) - { - $max_alarm_frame = $frame; - $max_alarm_score = $frame->{Score}; - } - } - $sth->finish(); - } - - my $url = $Config{ZM_URL}; - $text =~ s/%ZP%/$url/g; - $text =~ s/%MN%/$event->{MonitorName}/g; - $text =~ s/%MET%/$monitor->{EventCount}/g; - $text =~ s/%MEH%/$monitor->{HourEventCount}/g; - $text =~ s/%MED%/$monitor->{DayEventCount}/g; - $text =~ s/%MEW%/$monitor->{WeekEventCount}/g; - $text =~ s/%MEM%/$monitor->{MonthEventCount}/g; - $text =~ s/%MEA%/$monitor->{ArchEventCount}/g; - $text =~ s/%MP%/$url?view=watch&mid=$event->{MonitorId}/g; - $text =~ s/%MPS%/$url?view=watchfeed&mid=$event->{MonitorId}&mode=stream/g; - $text =~ s/%MPI%/$url?view=watchfeed&mid=$event->{MonitorId}&mode=still/g; - $text =~ s/%EP%/$url?view=event&mid=$event->{MonitorId}&eid=$event->{Id}/g; - $text =~ s/%EPS%/$url?view=event&mode=stream&mid=$event->{MonitorId}&eid=$event->{Id}/g; - $text =~ s/%EPI%/$url?view=event&mode=still&mid=$event->{MonitorId}&eid=$event->{Id}/g; - $text =~ s/%EI%/$event->{Id}/g; - $text =~ s/%EN%/$event->{Name}/g; - $text =~ s/%EC%/$event->{Cause}/g; - $text =~ s/%ED%/$event->{Notes}/g; - $text =~ s/%ET%/$event->{StartTime}/g; - $text =~ s/%EL%/$event->{Length}/g; - $text =~ s/%EF%/$event->{Frames}/g; - $text =~ s/%EFA%/$event->{AlarmFrames}/g; - $text =~ s/%EST%/$event->{TotScore}/g; - $text =~ s/%ESA%/$event->{AvgScore}/g; - $text =~ s/%ESM%/$event->{MaxScore}/g; - if ( $first_alarm_frame ) - { - $text =~ s/%EPI1%/$url?view=frame&mid=$event->{MonitorId}&eid=$event->{Id}&fid=$first_alarm_frame->{FrameId}/g; - $text =~ s/%EPIM%/$url?view=frame&mid=$event->{MonitorId}&eid=$event->{Id}&fid=$max_alarm_frame->{FrameId}/g; - if ( $attachments_ref && $text =~ s/%EI1%//g ) - { - my $path = generateImage( $event, $first_alarm_frame); - if ( -e $path ) { - push( @$attachments_ref, - { - type=>"image/jpeg", - path=>$path - } - ); - } - } - if ( $attachments_ref && $text =~ s/%EIM%//g ) - { - # Don't attach the same image twice - if ( !@$attachments_ref - || ($first_alarm_frame->{FrameId} != $max_alarm_frame->{FrameId} ) - ) - { - my $path = generateImage( $event, $max_alarm_frame); - if ( -e $path ) { - push( @$attachments_ref, - { - type=>"image/jpeg", - path=>$path - } - ); - } - } - } - if ( $attachments_ref && $text =~ s/%EI1A%//g ) - { - my $path = generateImage( $event, $first_alarm_frame, "analyse" ); - if ( -e $path ) { - push( @$attachments_ref, - { - type=>"image/jpeg", - path=>$path - } - ); - } - } - if ( $attachments_ref && $text =~ s/%EIMA%//g ) - { - # Don't attach the same image twice - if ( !@$attachments_ref - || ($first_alarm_frame->{FrameId} != $max_alarm_frame->{FrameId} ) - ) - { - my $path = generateImage( $event, $max_alarm_frame, "analyse"); - if ( -e $path ) { - push( @$attachments_ref, - { - type=>"image/jpeg", - path=>$path - } - ); - } - } - } - } - if ( $attachments_ref && $Config{ZM_OPT_FFMPEG} ) - { - if ( $text =~ s/%EV%//g ) - { - my ( $format, $path ) = generateVideo( $filter, $event ); - if ( !$format ) - { - return( undef ); - } - push( @$attachments_ref, { type=>"video/$format", path=>$path } ); - } - if ( $text =~ s/%EVM%//g ) - { - my ( $format, $path ) = generateVideo( $filter, $event, 1 ); - if ( !$format ) - { - return( undef ); - } - push( @$attachments_ref, { type=>"video/$format", path=>$path } ); - } - } - $text =~ s/%FN%/$filter->{Name}/g; - ( my $filter_name = $filter->{Name} ) =~ s/ /+/g; - $text =~ s/%FP%/$url?view=filter&mid=$event->{MonitorId}&filter_name=$filter_name/g; - - return( $text ); -} - -sub sendEmail -{ - my $filter = shift; - my $event = shift; - - if ( ! $Config{ZM_FROM_EMAIL} ) - { - Error( "No 'from' email address defined, not sending email" ); + } + $ftp->login( $Config{ZM_UPLOAD_USER}, $Config{ZM_UPLOAD_PASS} ) + or Error( "FTP - Can't login" ); + $ftp->binary() + or Error( "FTP - Can't go binary" ); + $ftp->cwd( $Config{ZM_UPLOAD_REM_DIR} ) + or Error( "FTP - Can't cwd" ) + if ( $Config{ZM_UPLOAD_REM_DIR} ); + $ftp->put( $archLocPath ) + or Error( "FTP - Can't upload '$archLocPath'" ); + $ftp->quit() + or Error( "FTP - Can't quit" ); + } else { + my $host = $Config{ZM_UPLOAD_HOST}; + $host .= ':'.$Config{ZM_UPLOAD_PORT} + if $Config{ZM_UPLOAD_PORT}; + Info( 'Uploading to '.$host." using SFTP\n" ); + my %sftpOptions = ( host=>$Config{ZM_UPLOAD_HOST}, user=>$Config{ZM_UPLOAD_USER} ); + $sftpOptions{password} = $Config{ZM_UPLOAD_PASS} + if $Config{ZM_UPLOAD_PASS}; + $sftpOptions{port} = $Config{ZM_UPLOAD_PORT} + if $Config{ZM_UPLOAD_PORT}; + $sftpOptions{timeout} = $Config{ZM_UPLOAD_TIMEOUT} + if $Config{ZM_UPLOAD_TIMEOUT}; + my @more_ssh_args; + push @more_ssh_args, '-o'=>'StrictHostKeyChecking=no' + if ! $Config{ZM_UPLOAD_STRICT}; + push @more_ssh_args, '-v' + if $Config{ZM_UPLOAD_DEBUG}; + $sftpOptions{more} = [@more_ssh_args]; + my $sftp = Net::SFTP::Foreign->new( $Config{ZM_UPLOAD_HOST}, %sftpOptions ); + if ( $sftp->error ) { + Error( "Can't create SFTP connection: ".$sftp->error ); return( 0 ); + } + $sftp->setcwd( $Config{ZM_UPLOAD_REM_DIR} ) + or Error( "SFTP - Can't setcwd: ".$sftp->error ) + if $Config{ZM_UPLOAD_REM_DIR}; + $sftp->put( $archLocPath, $archFile ) + or Error( "SFTP - Can't upload '$archLocPath': ".$sftp->error ); } - if ( ! $Config{ZM_EMAIL_ADDRESS} ) - { - Error( "No email address defined, not sending email" ); - return( 0 ); - } - - Info( "Creating notification email\n" ); - - my $subject = substituteTags( $Config{ZM_EMAIL_SUBJECT}, $filter, $event ); - return( 0 ) if ( !$subject ); - my @attachments; - my $body = substituteTags( $Config{ZM_EMAIL_BODY}, $filter, $event, \@attachments ); - return( 0 ) if ( !$body ); - - Info( "Sending notification email '$subject'\n" ); - - eval - { - if ( $Config{ZM_NEW_MAIL_MODULES} ) - { - ### Create the multipart container - my $mail = MIME::Lite->new ( - From => $Config{ZM_FROM_EMAIL}, - To => $Config{ZM_EMAIL_ADDRESS}, - Subject => $subject, - Type => "multipart/mixed" - ); - ### Add the text message part - $mail->attach ( - Type => "TEXT", - Data => $body - ); - ### Add the attachments - foreach my $attachment ( @attachments ) - { - Info( "Attaching '$attachment->{path}\n" ); - $mail->attach( - Path => $attachment->{path}, - Type => $attachment->{type}, - Disposition => "attachment" - ); - } - ### Send the Message - if ( $Config{ZM_SSMTP_MAIL} ) { - my $ssmtp_location = $Config{ZM_SSMTP_PATH}; - if ( !$ssmtp_location ) { - if ( logDebugging() ) { - Debug( "which ssmtp: $ssmtp_location - set ssmtp path in options to suppress this message\n" ); - } - $ssmtp_location = qx('which ssmtp'); - } - if ( !$ssmtp_location ) { - Debug( "Can't find ssmtp, trying MIME::Lite->send" ); - MIME::Lite->send( "smtp", $Config{ZM_EMAIL_HOST}, Timeout=>60 ); - $mail->send(); - } else { - ### Send using SSMTP - $mail->send( 'sendmail', $ssmtp_location, $Config{ZM_EMAIL_ADDRESS} ); - } - } else { - MIME::Lite->send( "smtp", $Config{ZM_EMAIL_HOST}, Timeout=>60 ); - $mail->send(); - } - } - else - { - my $mail = MIME::Entity->build( - From => $Config{ZM_FROM_EMAIL}, - To => $Config{ZM_EMAIL_ADDRESS}, - Subject => $subject, - Type => (($body=~//)?'text/html':'text/plain'), - Data => $body - ); - - foreach my $attachment ( @attachments ) - { - Info( "Attaching '$attachment->{path}\n" ); - $mail->attach( - Path => $attachment->{path}, - Type => $attachment->{type}, - Encoding => "base64" - ); - } - $mail->smtpsend( Host => $Config{ZM_EMAIL_HOST}, MailFrom => $Config{ZM_FROM_EMAIL} ); - } - }; - if ( $@ ) - { - Error( "Can't send email: $@" ); - return( 0 ); - } - else - { - Info( "Notification email sent\n" ); - } - my $sql = "update Events set Emailed = 1 where Id = ?"; + unlink( $archLocPath ); + my $sql = 'update Events set Uploaded = 1 where Id = ?'; my $sth = $dbh->prepare_cached( $sql ) - or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); my $res = $sth->execute( $event->{Id} ) - or Fatal( "Can't execute '$sql': ".$sth->errstr() ); - - return( 1 ); + or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + } + return( 1 ); } -sub sendMessage -{ - my $filter = shift; - my $event = shift; +sub substituteTags { + my $text = shift; + my $filter = shift; + my $event = shift; + my $attachments_ref = shift; - if ( ! $Config{ZM_FROM_EMAIL} ) - { - Error( "No 'from' email address defined, not sending message" ); - return( 0 ); - } - if ( ! $Config{ZM_MESSAGE_ADDRESS} ) - { - Error( "No message address defined, not sending message" ); - return( 0 ); - } +# First we'd better check what we need to get +# We have a filter and an event, do we need any more +# monitor information? + my $need_monitor = $text =~ /%(?:MET|MEH|MED|MEW|MEN|MEA)%/; - Info( "Creating notification message\n" ); - - my $subject = substituteTags( $Config{ZM_MESSAGE_SUBJECT}, $filter, $event ); - return( 0 ) if ( !$subject ); - my @attachments; - my $body = substituteTags( $Config{ZM_MESSAGE_BODY}, $filter, $event, \@attachments ); - return( 0 ) if ( !$body ); - - Info( "Sending notification message '$subject'\n" ); - - eval - { - if ( $Config{ZM_NEW_MAIL_MODULES} ) - { - ### Create the multipart container - my $mail = MIME::Lite->new ( - From => $Config{ZM_FROM_EMAIL}, - To => $Config{ZM_MESSAGE_ADDRESS}, - Subject => $subject, - Type => "multipart/mixed" - ); - ### Add the text message part - $mail->attach ( - Type => "TEXT", - Data => $body - ); - ### Add the attachments - foreach my $attachment ( @attachments ) - { - Info( "Attaching '$attachment->{path}\n" ); - $mail->attach( - Path => $attachment->{path}, - Type => $attachment->{type}, - Disposition => "attachment" - ); - } - ### Send the Message - if ( $Config{ZM_SSMTP_MAIL} ) { - my $ssmtp_location = $Config{ZM_SSMTP_PATH}; - if ( !$ssmtp_location ) { - if ( logDebugging() ) { - Debug( "which ssmtp: $ssmtp_location - set ssmtp path in options to suppress this message\n" ); - } - $ssmtp_location = qx('which ssmtp'); - } - if ( !$ssmtp_location ) { - Debug( "Can't find ssmtp, trying MIME::Lite->send" ); - MIME::Lite->send( "smtp", $Config{ZM_EMAIL_HOST}, Timeout=>60 ); - $mail->send(); - } else { - ### Send using SSMTP - $mail->send( 'sendmail', $ssmtp_location, $Config{ZM_MESSAGE_ADDRESS} ); - } - } else { - MIME::Lite->send( "smtp", $Config{ZM_EMAIL_HOST}, Timeout=>60 ); - $mail->send(); - } - } - else - { - my $mail = MIME::Entity->build( - From => $Config{ZM_FROM_EMAIL}, - To => $Config{ZM_MESSAGE_ADDRESS}, - Subject => $subject, - Type => (($body=~//)?'text/html':'text/plain'), - Data => $body - ); - - foreach my $attachment ( @attachments ) - { - Info( "Attaching '$attachment->{path}\n" ); - $mail->attach( - Path => $attachment->{path}, - Type => $attachment->{type}, - Encoding => "base64" - ); - } - $mail->smtpsend( Host => $Config{ZM_EMAIL_HOST}, - MailFrom => $Config{ZM_FROM_EMAIL} - ); - } - }; - if ( $@ ) - { - Error( "Can't send email: $@" ); - return( 0 ); - } - else - { - Info( "Notification message sent\n" ); - } - my $sql = "update Events set Messaged = 1 where Id = ?"; + my $monitor = {}; + if ( $need_monitor ) { + my $db_now = strftime( "%Y-%m-%d %H:%M:%S", localtime() ); + my $sql = "SELECT + M.Id, + count(E.Id) as EventCount, + count(if(E.Archived,1,NULL)) + as ArchEventCount, + count(if(E.StartTime>'$db_now' - INTERVAL 1 HOUR && E.Archived = 0,1,NULL)) + as HourEventCount, + count(if(E.StartTime>'$db_now' - INTERVAL 1 DAY && E.Archived = 0,1,NULL)) + as DayEventCount, + count(if(E.StartTime>'$db_now' - INTERVAL 7 DAY && E.Archived = 0,1,NULL)) + as WeekEventCount, + count(if(E.StartTime>'$db_now' - INTERVAL 1 MONTH && E.Archived = 0,1,NULL)) + as MonthEventCount + FROM Monitors as M LEFT JOIN Events as E on E.MonitorId = M.Id + WHERE MonitorId = ? + GROUP BY E.MonitorId + ORDER BY Id" + ; my $sth = $dbh->prepare_cached( $sql ) - or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{MonitorId} ) + or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + $monitor = $sth->fetchrow_hashref(); + $sth->finish(); + return() if ( !$monitor ); + } + +# Do we need the image information too? + my $need_images = $text =~ /%(?:EPI1|EPIM|EI1|EIM|EI1A|EIMA)%/; + my $first_alarm_frame; + my $max_alarm_frame; + my $max_alarm_score = 0; + if ( $need_images ) { + my $sql = "SELECT * FROM Frames + WHERE EventId = ? AND Type = 'Alarm' + ORDER BY FrameId" + ; + my $sth = $dbh->prepare_cached( $sql ) + or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); my $res = $sth->execute( $event->{Id} ) - or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + while( my $frame = $sth->fetchrow_hashref() ) { + if ( !$first_alarm_frame ) { + $first_alarm_frame = $frame; + } + if ( $frame->{Score} > $max_alarm_score ) { + $max_alarm_frame = $frame; + $max_alarm_score = $frame->{Score}; + } + } + $sth->finish(); + } - return( 1 ); + my $url = $Config{ZM_URL}; + $text =~ s/%ZP%/$url/g; + $text =~ s/%MN%/$event->{MonitorName}/g; + $text =~ s/%MET%/$monitor->{EventCount}/g; + $text =~ s/%MEH%/$monitor->{HourEventCount}/g; + $text =~ s/%MED%/$monitor->{DayEventCount}/g; + $text =~ s/%MEW%/$monitor->{WeekEventCount}/g; + $text =~ s/%MEM%/$monitor->{MonthEventCount}/g; + $text =~ s/%MEA%/$monitor->{ArchEventCount}/g; + $text =~ s/%MP%/$url?view=watch&mid=$event->{MonitorId}/g; + $text =~ s/%MPS%/$url?view=watchfeed&mid=$event->{MonitorId}&mode=stream/g; + $text =~ s/%MPI%/$url?view=watchfeed&mid=$event->{MonitorId}&mode=still/g; + $text =~ s/%EP%/$url?view=event&mid=$event->{MonitorId}&eid=$event->{Id}/g; + $text =~ s/%EPS%/$url?view=event&mode=stream&mid=$event->{MonitorId}&eid=$event->{Id}/g; + $text =~ s/%EPI%/$url?view=event&mode=still&mid=$event->{MonitorId}&eid=$event->{Id}/g; + $text =~ s/%EI%/$event->{Id}/g; + $text =~ s/%EN%/$event->{Name}/g; + $text =~ s/%EC%/$event->{Cause}/g; + $text =~ s/%ED%/$event->{Notes}/g; + $text =~ s/%ET%/$event->{StartTime}/g; + $text =~ s/%EL%/$event->{Length}/g; + $text =~ s/%EF%/$event->{Frames}/g; + $text =~ s/%EFA%/$event->{AlarmFrames}/g; + $text =~ s/%EST%/$event->{TotScore}/g; + $text =~ s/%ESA%/$event->{AvgScore}/g; + $text =~ s/%ESM%/$event->{MaxScore}/g; + + if ( $first_alarm_frame ) { + $text =~ s/%EPI1%/$url?view=frame&mid=$event->{MonitorId}&eid=$event->{Id}&fid=$first_alarm_frame->{FrameId}/g; + $text =~ s/%EPIM%/$url?view=frame&mid=$event->{MonitorId}&eid=$event->{Id}&fid=$max_alarm_frame->{FrameId}/g; + if ( $attachments_ref && $text =~ s/%EI1%//g ) { + my $path = generateImage( $event, $first_alarm_frame ); + if ( -e $path ) { + push( @$attachments_ref, { type=>'image/jpeg', path=>$path } ); + } + } + + if ( $attachments_ref && $text =~ s/%EIM%//g ) { + # Don't attach the same image twice + if ( !@$attachments_ref + || ($first_alarm_frame->{FrameId} != $max_alarm_frame->{FrameId} ) + ) { + my $path = generateImage( $event, $max_alarm_frame ); + if ( -e $path ) { + push( @$attachments_ref, { type=>'image/jpeg', path=>$path } ); + } + } + } + if ( $attachments_ref && $text =~ s/%EI1A%//g ) { + my $path = generateImage( $event, $first_alarm_frame, 'analyse' ); + if ( -e $path ) { + push( @$attachments_ref, { type=>'image/jpeg', path=>$path } ); + } + } + if ( $attachments_ref && $text =~ s/%EIMA%//g ) { + # Don't attach the same image twice + if ( !@$attachments_ref + || ($first_alarm_frame->{FrameId} != $max_alarm_frame->{FrameId} ) + ) { + my $path = generateImage( $event, $max_alarm_frame, 'analyse'); + if ( -e $path ) { + push( @$attachments_ref, { type=>'image/jpeg', path=>$path } ); + } + } + } + } # end if $first_alarm_frame + + if ( $attachments_ref && $Config{ZM_OPT_FFMPEG} ) { + if ( $text =~ s/%EV%//g ) { + my ( $format, $path ) = generateVideo( $filter, $event ); + if ( !$format ) { + return( undef ); + } + push( @$attachments_ref, { type=>"video/$format", path=>$path } ); + } + if ( $text =~ s/%EVM%//g ) { + my ( $format, $path ) = generateVideo( $filter, $event, 1 ); + if ( !$format ) { + return( undef ); + } + push( @$attachments_ref, { type=>"video/$format", path=>$path } ); + } + } + $text =~ s/%FN%/$filter->{Name}/g; + ( my $filter_name = $filter->{Name} ) =~ s/ /+/g; + $text =~ s/%FP%/$url?view=filter&mid=$event->{MonitorId}&filter_name=$filter_name/g; + + return( $text ); +} # end subsitituteTags + +sub sendEmail { + my $filter = shift; + my $event = shift; + + if ( ! $Config{ZM_FROM_EMAIL} ) { + Error( "No 'from' email address defined, not sending email" ); + return( 0 ); + } + if ( ! $Config{ZM_EMAIL_ADDRESS} ) { + Error( 'No email address defined, not sending email' ); + return( 0 ); + } + + Info( "Creating notification email\n" ); + + my $subject = substituteTags( $Config{ZM_EMAIL_SUBJECT}, $filter, $event ); + return( 0 ) if ( !$subject ); + my @attachments; + my $body = substituteTags( $Config{ZM_EMAIL_BODY}, $filter, $event, \@attachments ); + return( 0 ) if ( !$body ); + + Info( "Sending notification email '$subject'\n" ); + + eval { + if ( $Config{ZM_NEW_MAIL_MODULES} ) { +### Create the multipart container + my $mail = MIME::Lite->new ( + From => $Config{ZM_FROM_EMAIL}, + To => $Config{ZM_EMAIL_ADDRESS}, + Subject => $subject, + Type => 'multipart/mixed' + ); +### Add the text message part + $mail->attach ( + Type => 'TEXT', + Data => $body + ); +### Add the attachments + foreach my $attachment ( @attachments ) { + Info( "Attaching '$attachment->{path}\n" ); + $mail->attach( + Path => $attachment->{path}, + Type => $attachment->{type}, + Disposition => 'attachment' + ); + } +### Send the Message + if ( $Config{ZM_SSMTP_MAIL} ) { + my $ssmtp_location = $Config{ZM_SSMTP_PATH}; + if ( !$ssmtp_location ) { + if ( logDebugging() ) { + Debug( "which ssmtp: $ssmtp_location - set ssmtp path in options to suppress this message\n" ); + } + $ssmtp_location = qx('which ssmtp'); + } + if ( !$ssmtp_location ) { + Debug( "Can't find ssmtp, trying MIME::Lite->send" ); + MIME::Lite->send( 'smtp', $Config{ZM_EMAIL_HOST}, Timeout=>60 ); + $mail->send(); + } else { +### Send using SSMTP + $mail->send( 'sendmail', $ssmtp_location, $Config{ZM_EMAIL_ADDRESS} ); + } + } else { + MIME::Lite->send( 'smtp', $Config{ZM_EMAIL_HOST}, Timeout=>60 ); + $mail->send(); + } + } else { + my $mail = MIME::Entity->build( + From => $Config{ZM_FROM_EMAIL}, + To => $Config{ZM_EMAIL_ADDRESS}, + Subject => $subject, + Type => (($body=~//)?'text/html':'text/plain'), + Data => $body + ); + + foreach my $attachment ( @attachments ) { + Info( "Attaching '$attachment->{path}\n" ); + $mail->attach( + Path => $attachment->{path}, + Type => $attachment->{type}, + Encoding => 'base64' + ); + } + $mail->smtpsend( Host => $Config{ZM_EMAIL_HOST}, MailFrom => $Config{ZM_FROM_EMAIL} ); + } + }; + if ( $@ ) { + Error( "Can't send email: $@" ); + return( 0 ); + } else { + Info( "Notification email sent\n" ); + } + my $sql = 'update Events set Emailed = 1 where Id = ?'; + my $sth = $dbh->prepare_cached( $sql ) + or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{Id} ) + or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + + return( 1 ); } -sub executeCommand -{ - my $filter = shift; - my $event = shift; +sub sendMessage { + my $filter = shift; + my $event = shift; - my $event_path = getEventPath( $event ); + if ( ! $Config{ZM_FROM_EMAIL} ) { + Error( 'No 'from' email address defined, not sending message' ); + return( 0 ); + } + if ( ! $Config{ZM_MESSAGE_ADDRESS} ) { + Error( 'No message address defined, not sending message' ); + return( 0 ); + } - my $command = $filter->{AutoExecuteCmd}; - $command .= " $event_path"; - $command = substituteTags( $command, $filter, $event ); + Info( "Creating notification message\n" ); - Info( "Executing '$command'\n" ); - my $output = qx($command); - my $status = $? >> 8; - if ( $status || logDebugging() ) - { - chomp( $output ); - Debug( "Output: $output\n" ); + my $subject = substituteTags( $Config{ZM_MESSAGE_SUBJECT}, $filter, $event ); + return( 0 ) if ( !$subject ); + my @attachments; + my $body = substituteTags( $Config{ZM_MESSAGE_BODY}, $filter, $event, \@attachments ); + return( 0 ) if ( !$body ); + + Info( "Sending notification message '$subject'\n" ); + + eval { + if ( $Config{ZM_NEW_MAIL_MODULES} ) { +### Create the multipart container + my $mail = MIME::Lite->new ( + From => $Config{ZM_FROM_EMAIL}, + To => $Config{ZM_MESSAGE_ADDRESS}, + Subject => $subject, + Type => 'multipart/mixed' + ); +### Add the text message part + $mail->attach ( + Type => 'TEXT', + Data => $body + ); +### Add the attachments + foreach my $attachment ( @attachments ) { + Info( "Attaching '$attachment->{path}\n" ); + $mail->attach( + Path => $attachment->{path}, + Type => $attachment->{type}, + Disposition => 'attachment' + ); + } +### Send the Message + if ( $Config{ZM_SSMTP_MAIL} ) { + my $ssmtp_location = $Config{ZM_SSMTP_PATH}; + if ( !$ssmtp_location ) { + if ( logDebugging() ) { + Debug( "which ssmtp: $ssmtp_location - set ssmtp path in options to suppress this message\n" ); + } + $ssmtp_location = qx('which ssmtp'); + } + if ( !$ssmtp_location ) { + Debug( "Can't find ssmtp, trying MIME::Lite->send" ); + MIME::Lite->send( 'smtp', $Config{ZM_EMAIL_HOST}, Timeout=>60 ); + $mail->send(); + } else { +### Send using SSMTP + $mail->send( 'sendmail', $ssmtp_location, $Config{ZM_MESSAGE_ADDRESS} ); + } + } else { + MIME::Lite->send( 'smtp', $Config{ZM_EMAIL_HOST}, Timeout=>60 ); + $mail->send(); + } + } else { + my $mail = MIME::Entity->build( + From => $Config{ZM_FROM_EMAIL}, + To => $Config{ZM_MESSAGE_ADDRESS}, + Subject => $subject, + Type => (($body=~//)?'text/html':'text/plain'), + Data => $body + ); + + foreach my $attachment ( @attachments ) { + Info( "Attaching '$attachment->{path}\n" ); + $mail->attach( + Path => $attachment->{path}, + Type => $attachment->{type}, + Encoding => 'base64' + ); + } + $mail->smtpsend( Host => $Config{ZM_EMAIL_HOST}, + MailFrom => $Config{ZM_FROM_EMAIL} + ); } - if ( $status ) - { - Error( "Command '$command' exited with status: $status\n" ); - return( 0 ); - } - else - { - my $sql = "update Events set Executed = 1 where Id = ?"; - my $sth = $dbh->prepare_cached( $sql ) - or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); - my $res = $sth->execute( $event->{Id} ) - or Fatal( "Can't execute '$sql': ".$sth->errstr() ); - } - return( 1 ); + }; + if ( $@ ) { + Error( "Can't send email: $@" ); + return( 0 ); + } else { + Info( "Notification message sent\n" ); + } + my $sql = 'update Events set Messaged = 1 where Id = ?'; + my $sth = $dbh->prepare_cached( $sql ) + or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{Id} ) + or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + + return( 1 ); +} + +sub executeCommand { + my $filter = shift; + my $event = shift; + + my $event_path = getEventPath( $event ); + + my $command = $filter->{AutoExecuteCmd}; + $command .= " $event_path"; + $command = substituteTags( $command, $filter, $event ); + + Info( "Executing '$command'\n" ); + my $output = qx($command); + my $status = $? >> 8; + if ( $status || logDebugging() ) { + chomp( $output ); + Debug( "Output: $output\n" ); + } + if ( $status ) { + Error( "Command '$command' exited with status: $status\n" ); + return( 0 ); + } else { + my $sql = 'update Events set Executed = 1 where Id = ?'; + my $sth = $dbh->prepare_cached( $sql ) + or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{Id} ) + or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + } + return( 1 ); } From 5228b9d00896287b0f1c7f4aa2a9f050e84f3101 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 2 Jun 2017 11:54:40 -0400 Subject: [PATCH 03/10] move command line option parsing up, so if we are just getting the version we exit quick before doing a bunch of other things. --- scripts/zmfilter.pl.in | 69 ++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/scripts/zmfilter.pl.in b/scripts/zmfilter.pl.in index ef4a2a43e..4538c099c 100644 --- a/scripts/zmfilter.pl.in +++ b/scripts/zmfilter.pl.in @@ -60,7 +60,6 @@ use constant START_DELAY => 5; # How long to wait before starting @EXTRA_PERL_LIB@ use ZoneMinder; -require ZoneMinder::Filter; use DBI; use POSIX; use Time::HiRes qw/gettimeofday/; @@ -69,29 +68,44 @@ use Getopt::Long; use autouse 'Pod::Usage'=>qw(pod2usage); use autouse 'Data::Dumper'=>qw(Dumper); +my $filter_parm = ''; +my $version = 0; + +GetOptions( + 'filter=s' =>\$filter_parm, + 'version' =>\$version + ) or pod2usage(-exitstatus => -1); + +if ( $version ) { + print ZoneMinder::Base::ZM_VERSION . "\n"; + exit(0); +} + +require ZoneMinder::Filter; + use constant EVENT_PATH => ($Config{ZM_DIR_EVENTS}=~m|/|) ? $Config{ZM_DIR_EVENTS} : ($Config{ZM_PATH_WEB}.'/'.$Config{ZM_DIR_EVENTS}) ; - logInit(); - logSetSignal(); +logInit(); +logSetSignal(); - if ( $Config{ZM_OPT_UPLOAD} ) { +if ( $Config{ZM_OPT_UPLOAD} ) { # Comment these out if you don't have them and don't want to upload # or don't want to use that format - if ( $Config{ZM_UPLOAD_ARCH_FORMAT} eq 'zip' ) { - require Archive::Zip; - import Archive::Zip qw( :ERROR_CODES :CONSTANTS ); - } else { - require Archive::Tar; - } - if ( $Config{ZM_UPLOAD_PROTOCOL} eq 'ftp' ) { - require Net::FTP; - } else { - require Net::SFTP::Foreign; - } + if ( $Config{ZM_UPLOAD_ARCH_FORMAT} eq 'zip' ) { + require Archive::Zip; + import Archive::Zip qw( :ERROR_CODES :CONSTANTS ); + } else { + require Archive::Tar; } + if ( $Config{ZM_UPLOAD_PROTOCOL} eq 'ftp' ) { + require Net::FTP; + } else { + require Net::SFTP::Foreign; + } +} if ( $Config{ZM_OPT_EMAIL} ) { if ( $Config{ZM_NEW_MAIL_MODULES} ) { @@ -119,20 +133,6 @@ delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; my $delay = $Config{ZM_FILTER_EXECUTE_INTERVAL}; my $event_id = 0; -my $filter_parm = ''; -my $version = 0; - -# - -GetOptions( - 'filter=s' =>\$filter_parm, - 'version' =>\$version - ) or pod2usage(-exitstatus => -1); - -if ( $version ) { - print ZoneMinder::Base::ZM_VERSION . '\n'; - exit(0); -} if ( ! EVENT_PATH ) { Error( "No event path defined. Config was $Config{ZM_DIR_EVENTS}\n" ); @@ -330,11 +330,16 @@ sub generateVideo { $format = $ffmpeg_formats[0]; } - my $command = join('', + my $command = join( '', $Config{ZM_PATH_BIN}, '/zmvideo.pl -e ', - .$event->{Id}, - ' -r ',$rate,' -s ',$scale,' -f ',$format, + $event->{Id}, + ' -r ', + $rate, + ' -s ', + $scale, + ' -f ', + $format, ); my $output = qx($command); chomp( $output ); From 352ea6b6aea1b5a29f2e887c26918921e5187300 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 2 Jun 2017 12:12:41 -0400 Subject: [PATCH 04/10] spacing --- web/skins/classic/views/filter.php | 167 +++++++++++++---------------- 1 file changed, 74 insertions(+), 93 deletions(-) diff --git a/web/skins/classic/views/filter.php b/web/skins/classic/views/filter.php index 43b651ea9..3057fad74 100644 --- a/web/skins/classic/views/filter.php +++ b/web/skins/classic/views/filter.php @@ -18,34 +18,31 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // -if ( !canView( 'Events' ) ) -{ - $view = "error"; - return; +if ( !canView( 'Events' ) ) { + $view = 'error'; + return; } -$selectName = "filterName"; +$selectName = 'filterName'; $filterNames = array( ''=>translate('ChooseFilter') ); -foreach ( dbFetchAll( "select * from Filters order by Name" ) as $row ) -{ - $filterNames[$row['Name']] = $row['Name']; - if ( $row['Background'] ) - $filterNames[$row['Name']] .= "*"; - if ( !empty($_REQUEST['reload']) && isset($_REQUEST['filterName']) && $_REQUEST['filterName'] == $row['Name'] ) - $dbFilter = $row; +foreach ( dbFetchAll( 'select * from Filters order by Name' ) as $row ) { + $filterNames[$row['Name']] = $row['Name']; + if ( $row['Background'] ) + $filterNames[$row['Name']] .= '*'; + if ( !empty($_REQUEST['reload']) && isset($_REQUEST['filterName']) && $_REQUEST['filterName'] == $row['Name'] ) + $dbFilter = $row; } -$backgroundStr = ""; -if ( isset($dbFilter) ) -{ - if ( $dbFilter['Background'] ) - $backgroundStr = '['.strtolower(translate('Background')).']'; - $_REQUEST['filter'] = jsonDecode( $dbFilter['Query'] ); - $_REQUEST['sort_field'] = isset($_REQUEST['filter']['sort_field'])?$_REQUEST['filter']['sort_field']:"DateTime"; - $_REQUEST['sort_asc'] = isset($_REQUEST['filter']['sort_asc'])?$_REQUEST['filter']['sort_asc']:"1"; - $_REQUEST['limit'] = isset($_REQUEST['filter']['limit'])?$_REQUEST['filter']['limit']:""; - unset( $_REQUEST['filter']['sort_field'] ); - unset( $_REQUEST['filter']['sort_asc'] ); - unset( $_REQUEST['filter']['limit'] ); +$backgroundStr = ''; +if ( isset($dbFilter) ) { + if ( $dbFilter['Background'] ) + $backgroundStr = '['.strtolower(translate('Background')).']'; + $_REQUEST['filter'] = jsonDecode( $dbFilter['Query'] ); + $_REQUEST['sort_field'] = isset($_REQUEST['filter']['sort_field'])?$_REQUEST['filter']['sort_field']:"DateTime"; + $_REQUEST['sort_asc'] = isset($_REQUEST['filter']['sort_asc'])?$_REQUEST['filter']['sort_asc']:"1"; + $_REQUEST['limit'] = isset($_REQUEST['filter']['limit'])?$_REQUEST['filter']['limit']:""; + unset( $_REQUEST['filter']['sort_field'] ); + unset( $_REQUEST['filter']['sort_asc'] ); + unset( $_REQUEST['filter']['limit'] ); } # reload is set when the dropdown is changed. @@ -64,16 +61,14 @@ if ( isset( $_REQUEST['reload'] ) and ! $_REQUEST['reload'] ) { $conjunctionTypes = array( 'and' => translate('ConjAnd'), 'or' => translate('ConjOr') -); + ); $obracketTypes = array(); $cbracketTypes = array(); -if ( isset($_REQUEST['filter']['terms']) ) -{ - for ( $i = 0; $i <= count($_REQUEST['filter']['terms'])-2; $i++ ) - { - $obracketTypes[$i] = str_repeat( "(", $i ); - $cbracketTypes[$i] = str_repeat( ")", $i ); - } +if ( isset($_REQUEST['filter']['terms']) ) { + for ( $i = 0; $i <= count($_REQUEST['filter']['terms'])-2; $i++ ) { + $obracketTypes[$i] = str_repeat( "(", $i ); + $cbracketTypes[$i] = str_repeat( ")", $i ); + } } $attrTypes = array( @@ -98,7 +93,7 @@ $attrTypes = array( 'DiskBlocks' => translate('AttrDiskBlocks'), 'SystemLoad' => translate('AttrSystemLoad'), 'ServerId' => translate('AttrServer'), -); + ); $opTypes = array( '=' => translate('OpEq'), '!=' => translate('OpNe'), @@ -110,15 +105,14 @@ $opTypes = array( '!~' => translate('OpNotMatches'), '=[]' => translate('OpIn'), '![]' => translate('OpNotIn'), -); + ); $archiveTypes = array( '0' => translate('ArchUnarchived'), '1' => translate('ArchArchived') -); + ); $weekdays = array(); -for ( $i = 0; $i < 7; $i++ ) -{ - $weekdays[$i] = strftime( "%A", mktime( 12, 0, 0, 1, $i+1, 2001 ) ); +for ( $i = 0; $i < 7; $i++ ) { + $weekdays[$i] = strftime( '%A', mktime( 12, 0, 0, 1, $i+1, 2001 ) ); } $sort_fields = array( 'Id' => translate('AttrId'), @@ -133,13 +127,12 @@ $sort_fields = array( 'TotScore' => translate('AttrTotalScore'), 'AvgScore' => translate('AttrAvgScore'), 'MaxScore' => translate('AttrMaxScore'), -); + ); $sort_dirns = array( '1' => translate('SortAsc'), '0' => translate('SortDesc') -); -if ( empty($_REQUEST['sort_field']) ) -{ + ); +if ( empty($_REQUEST['sort_field']) ) { $_REQUEST['sort_field'] = ZM_WEB_EVENT_SORT_FIELD; $_REQUEST['sort_asc'] = (ZM_WEB_EVENT_SORT_ORDER == "asc"); } @@ -174,105 +167,93 @@ xhtmlHeaders(__FILE__, translate('EventFilter') ); - + - +
  2 ) { echo buildSelect( "filter[terms][$i][obr]", $obracketTypes ); } else { ?>  + + + + + + + + + + 2 ) { echo buildSelect( "filter[terms][$i][cbr]", $cbracketTypes ); } else { ?>  1 ) { ?>
@@ -346,9 +327,9 @@ if ( ZM_OPT_MESSAGE ) - - + + From 555a6670357f9e627575023de591def6f5f3bcd6 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 2 Jun 2017 12:12:59 -0400 Subject: [PATCH 05/10] fix filter button --- web/skins/classic/views/console.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/web/skins/classic/views/console.php b/web/skins/classic/views/console.php index 8de087281..ede536295 100644 --- a/web/skins/classic/views/console.php +++ b/web/skins/classic/views/console.php @@ -331,7 +331,7 @@ echo $Server->Name(); - + - + + + + From a9268d10e33400ba55e14f6b6cf956e2b223785e Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 2 Jun 2017 12:21:12 -0400 Subject: [PATCH 06/10] fix the use of ZM_OPT constants in javascript. Instead, check for existence of the element in the form. --- web/skins/classic/views/js/filter.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/web/skins/classic/views/js/filter.js b/web/skins/classic/views/js/filter.js index 599a3c589..385ef3c7e 100644 --- a/web/skins/classic/views/js/filter.js +++ b/web/skins/classic/views/js/filter.js @@ -7,13 +7,13 @@ function updateButtons( element ) { var canExecute = false; if ( form.elements['AutoArchive'].checked ) canExecute = true; - else if ( typeof ZM_OPT_FFMPEG !== "undefined" && form.elements['AutoVideo'].checked ) + else if ( form.elements['AutoVideo'] && form.elements['AutoVideo'].checked ) canExecute = true; - else if ( typeof ZM_OPT_UPLOAD !== "undefined" && form.elements['AutoUpload'].checked ) + else if ( form.elements['AutoUpload'] && form.elements['AutoUpload'].checked ) canExecute = true; - else if ( typeof ZM_OPT_EMAIL !== "undefined" && form.elements['AutoEmail'].checked ) + else if ( form.elements['AutoEmail'] && form.elements['AutoEmail'].checked ) canExecute = true; - else if ( typeof ZM_OPT_MESSAGE !== "undefined" && form.elements['AutoMessage'].checked ) + else if ( form.elements['AutoMessage'] && form.elements['AutoMessage'].checked ) canExecute = true; else if ( form.elements['AutoExecute'].checked && form.elements['AutoExecuteCmd'].value != '' ) canExecute = true; From 71b9ca97c61988bd95bfc870fd9d5997881b8a93 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 2 Jun 2017 12:25:26 -0400 Subject: [PATCH 07/10] no need to store filters as an array ref --- scripts/zmfilter.pl.in | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/scripts/zmfilter.pl.in b/scripts/zmfilter.pl.in index 4538c099c..a508473bf 100644 --- a/scripts/zmfilter.pl.in +++ b/scripts/zmfilter.pl.in @@ -153,7 +153,7 @@ if ( !$filter_parm ) { sleep( START_DELAY ); } -my $filters; +my @filters; my $last_action = 0; while( 1 ) { @@ -161,14 +161,14 @@ while( 1 ) { if ( ($now - $last_action) > $Config{ZM_FILTER_RELOAD_DELAY} ) { Debug( "Reloading filters\n" ); $last_action = $now; - $filters = getFilters( $filter_parm ); + @filters = getFilters( $filter_parm ); } - foreach my $filter ( @$filters ) { + foreach my $filter ( @filters ) { checkFilter( $filter ); } - last if ( $filter_parm ); + last if $filter_parm; Debug( "Sleeping for $delay seconds\n" ); sleep( $delay ); @@ -203,19 +203,19 @@ sub getFilters { or Fatal( "Can't execute '$sql': ".$sth->errstr() ); } FILTER: while( my $db_filter = $sth->fetchrow_hashref() ) { - my $filter = new ZoneMinder::Filter( $$db_filter{Id}, $db_filter ); - Debug( "Found filter '$db_filter->{Name}'\n" ); - my $sql = $filter->Sql(); + my $filter = new ZoneMinder::Filter( $$db_filter{Id}, $db_filter ); + Debug( "Found filter '$db_filter->{Name}'\n" ); + my $sql = $filter->Sql(); - if ( ! $sql ) { - Error( "Error parsing Sql. skipping filter '$db_filter->{Name}'\n" ); - next FILTER; - } - push( @filters, $filter ); - } - $sth->finish(); - Debug( 'Got ' . @filters . ' filters' ); - return( \@filters ); + if ( ! $sql ) { + Error( "Error parsing Sql. skipping filter '$db_filter->{Name}'\n" ); + next FILTER; + } + push( @filters, $filter ); + } + $sth->finish(); + Debug( 'Got ' . @filters . ' filters' ); + return( @filters ); } sub checkFilter { From b6b4738b9fb945189f605db82355d7f84769bd99 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 2 Jun 2017 12:31:54 -0400 Subject: [PATCH 08/10] fix quotes --- scripts/zmfilter.pl.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/zmfilter.pl.in b/scripts/zmfilter.pl.in index a508473bf..aeb11b509 100644 --- a/scripts/zmfilter.pl.in +++ b/scripts/zmfilter.pl.in @@ -794,7 +794,7 @@ sub sendMessage { my $event = shift; if ( ! $Config{ZM_FROM_EMAIL} ) { - Error( 'No 'from' email address defined, not sending message' ); + Error( "No 'from' email address defined, not sending message" ); return( 0 ); } if ( ! $Config{ZM_MESSAGE_ADDRESS} ) { From 8b91403c256955ea90233d7a4454eb25069e519b Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 2 Jun 2017 12:32:02 -0400 Subject: [PATCH 09/10] remove references to Storage object --- scripts/zmaudit.pl.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/zmaudit.pl.in b/scripts/zmaudit.pl.in index c671e9989..58b4a2739 100644 --- a/scripts/zmaudit.pl.in +++ b/scripts/zmaudit.pl.in @@ -185,11 +185,11 @@ MAIN: while( $loop ) { Debug( "Checking day dir $day_dir" ); ( $day_dir ) = ( $day_dir =~ /^(.*)$/ ); # De-taint if ( ! chdir( $day_dir ) ) { - Error( "Can't chdir to '$$Storage{Path}/$day_dir': $!" ); + Error( "Can't chdir to '$day_dir': $!" ); next; } if ( ! opendir( DIR, '.' ) ) { - Error( "Can't open directory '$$Storage{Path}/$day_dir': $!" ); + Error( "Can't open directory '$day_dir': $!" ); next; } From 9c9eaa6851fbdc2470202d6fdfe979cbe4f10068 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 2 Jun 2017 12:35:01 -0400 Subject: [PATCH 10/10] move test for MIN_AGE up. Don't need to constantly check for it because it won't change. --- scripts/zmaudit.pl.in | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/zmaudit.pl.in b/scripts/zmaudit.pl.in index 58b4a2739..6cf2af2e3 100644 --- a/scripts/zmaudit.pl.in +++ b/scripts/zmaudit.pl.in @@ -111,6 +111,10 @@ if ( ($report + $interactive + $continuous) > 1 ) { pod2usage(-exitstatus => -1); } +if ( ! exists $Config{ZM_AUDIT_MIN_AGE} ) { + Fatal('ZM_AUDIT_MIN_AGE is not set in config.'); +} + my $dbh = zmDbConnect(); chdir( EVENT_PATH ); @@ -145,12 +149,8 @@ MAIN: while( $loop ) { sleep 1; } # end if - if ( ! exists $Config{ZM_AUDIT_MIN_AGE} ) { - Fatal('ZM_AUDIT_MIN_AGE is not set in config.'); - } - my $db_monitors; - my $monitorSelectSql = "select Id from Monitors order by Id"; + my $monitorSelectSql = 'select Id from Monitors order by Id'; my $monitorSelectSth = $dbh->prepare_cached( $monitorSelectSql ) or Fatal( "Can't prepare '$monitorSelectSql': ".$dbh->errstr() ); my $eventSelectSql = 'SELECT Id, (unix_timestamp() - unix_timestamp(StartTime)) as Age