From 6c3d877d99f3f2b28849990db6787b96108eae6a Mon Sep 17 00:00:00 2001 From: bhaal2 Date: Wed, 21 Sep 2016 10:11:40 +1000 Subject: [PATCH] Storageareas (#2) * quick update to Monitor to use Object methods * add more debugging and fix LinkPath -> LinkPath * add disk_usage_percent and fix whitespace * fixup saving Filters and executing them * fix getDiskPercent to take a StorageArea as a param and use it's disk_usage_percent function. When parsing filter, DiskPercent requires a storagearea now, so look for it in the terms * replace getDiskPercent call with code to show percent for all storageareas * instead of filterId, use Id so that the object in is properly filled out. Add object=filter to hidden fields * add ffmpeg as an option to libav-tools * update zm_create.sql.in to match the update scripts * contains due to glob * don't output jpeg header unless there is some kind of success * maybe fixes, maybe big memleaks --- db/zm_create.sql.in | 28 ++--- distros/ubuntu1604/control | 2 +- scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm | 60 ++--------- scripts/zmaudit.pl.in | 6 +- src/zm_ffmpeg_camera.cpp | 9 +- src/zm_packetqueue.cpp | 14 ++- src/zm_packetqueue.h | 1 + src/zm_videostore.cpp | 20 +++- web/includes/Event.php | 20 +++- web/includes/Storage.php | 107 +++++++++++-------- web/includes/actions.php | 58 +++++----- web/includes/functions.php | 60 ++++++----- web/skins/classic/includes/functions.php | 9 +- web/skins/classic/views/filter.php | 17 +-- web/views/image.php | 17 ++- 15 files changed, 227 insertions(+), 201 deletions(-) diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index a93437cda..21a4d4cc1 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -328,22 +328,22 @@ CREATE TABLE `Monitors` ( `Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL') NOT NULL default 'Local', `Function` enum('None','Monitor','Modect','Record','Mocord','Nodect') NOT NULL default 'Monitor', `Enabled` tinyint(3) unsigned NOT NULL default '1', - `LinkedMonitors` varchar(255) NOT NULL default '', + `LinkedMonitors` varchar(255), `Triggers` set('X10') NOT NULL default '', `Device` tinytext NOT NULL default '', `Channel` tinyint(3) unsigned NOT NULL default '0', `Format` int(10) unsigned NOT NULL default '0', `V4LMultiBuffer` tinyint(1) unsigned, `V4LCapturesPerFrame` tinyint(3) unsigned, - `Protocol` varchar(16) NOT NULL default '', + `Protocol` varchar(16), `Method` varchar(16) NOT NULL default '', - `Host` varchar(64) NOT NULL default '', + `Host` varchar(64), `Port` varchar(8) NOT NULL default '', `SubPath` varchar(64) NOT NULL default '', `Path` varchar(255) NOT NULL default '', - `Options` varchar(255) not null default '', - `User` varchar(64) NOT NULL default '', - `Pass` varchar(64) NOT NULL default '', + `Options` varchar(255), + `User` varchar(64), + `Pass` varchar(64), `Width` smallint(5) unsigned NOT NULL default '0', `Height` smallint(5) unsigned NOT NULL default '0', `Colours` tinyint(3) unsigned NOT NULL default '1', @@ -354,13 +354,13 @@ CREATE TABLE `Monitors` ( `VideoWriter` TINYINT NOT NULL DEFAULT '0', `EncoderParameters` TEXT NOT NULL, `RecordAudio` TINYINT NOT NULL DEFAULT '0', - `RTSPDescribe` tinyint(1) unsigned NOT NULL default '0', + `RTSPDescribe` tinyint(1) unsigned, `Brightness` mediumint(7) NOT NULL default '-1', `Contrast` mediumint(7) NOT NULL default '-1', `Hue` mediumint(7) NOT NULL default '-1', `Colour` mediumint(7) NOT NULL default '-1', `EventPrefix` varchar(32) NOT NULL default 'Event-', - `LabelFormat` varchar(64) NOT NULL default '%N - %y/%m/%d %H:%M:%S', + `LabelFormat` varchar(64) default '%N - %y/%m/%d %H:%M:%S', `LabelX` smallint(5) unsigned NOT NULL default '0', `LabelY` smallint(5) unsigned NOT NULL default '0', `LabelSize` smallint(5) unsigned NOT NULL DEFAULT '1', @@ -381,14 +381,14 @@ CREATE TABLE `Monitors` ( `RefBlendPerc` tinyint(3) unsigned NOT NULL default '6', `AlarmRefBlendPerc` tinyint(3) unsigned NOT NULL default '6', `Controllable` tinyint(3) unsigned NOT NULL default '0', - `ControlId` int(10) unsigned NOT NULL default '0', + `ControlId` int(10) unsigned, `ControlDevice` varchar(255) default NULL, `ControlAddress` varchar(255) default NULL, `AutoStopTimeout` decimal(5,2) default NULL, `TrackMotion` tinyint(3) unsigned NOT NULL default '0', - `TrackDelay` smallint(5) unsigned NOT NULL default '0', + `TrackDelay` smallint(5) unsigned, `ReturnLocation` tinyint(3) NOT NULL default '-1', - `ReturnDelay` smallint(5) unsigned NOT NULL default '0', + `ReturnDelay` smallint(5) unsigned, `DefaultView` enum('Events','Control') NOT NULL default 'Events', `DefaultRate` smallint(5) unsigned NOT NULL default '100', `DefaultScale` smallint(5) unsigned NOT NULL default '100', @@ -477,7 +477,7 @@ CREATE TABLE `Users` ( `Id` int(10) unsigned NOT NULL auto_increment, `Username` varchar(32) character set latin1 collate latin1_bin NOT NULL default '', `Password` varchar(64) NOT NULL default '', - `Language` varchar(8) NOT NULL default '', + `Language` varchar(8), `Enabled` tinyint(3) unsigned NOT NULL default '1', `Stream` enum('None','View') NOT NULL default 'None', `Events` enum('None','View','Edit') NOT NULL default 'None', @@ -486,8 +486,8 @@ CREATE TABLE `Users` ( `Groups` enum('None','View','Edit') NOT NULL default 'None', `Devices` enum('None','View','Edit') NOT NULL default 'None', `System` enum('None','View','Edit') NOT NULL default 'None', - `MaxBandwidth` varchar(16) NOT NULL default '', - `MonitorIds` tinytext NOT NULL, + `MaxBandwidth` varchar(16), + `MonitorIds` tinytext, PRIMARY KEY (`Id`), UNIQUE KEY `UC_Username` (`Username`) ) ENGINE=@ZM_MYSQL_ENGINE@; diff --git a/distros/ubuntu1604/control b/distros/ubuntu1604/control index f2d94de48..bf5556c7b 100644 --- a/distros/ubuntu1604/control +++ b/distros/ubuntu1604/control @@ -37,7 +37,7 @@ Package: zoneminder Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends} ,javascript-common - ,libav-tools + ,libav-tools | ffmpeg ,libdate-manip-perl, libmime-lite-perl, libmime-tools-perl ,libdbd-mysql-perl ,libphp-serialization-perl diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm b/scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm index efbccf30f..0ab20d162 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm @@ -28,29 +28,13 @@ use 5.006; use strict; use warnings; -require Exporter; require ZoneMinder::Base; +require ZoneMinder::Object; +require ZoneMinder::Storage; +require ZoneMinder::Server; -our @ISA = qw(Exporter ZoneMinder::Base); - -# Items to export into callers namespace by default. Note: do not export -# names by default without a very good reason. Use EXPORT_OK instead. -# Do not simply export all your public functions/methods/constants. - -# This allows declaration use ZoneMinder ':all'; -# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK -# will save memory. -our %EXPORT_TAGS = ( - 'functions' => [ qw( - ) ] -); -push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS; - -our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); - -our @EXPORT = qw(); - -our $VERSION = $ZoneMinder::Base::VERSION; +#our @ISA = qw(Exporter ZoneMinder::Base); +use parent qw(ZoneMinder::Object); # ========================================================================== # @@ -61,39 +45,11 @@ our $VERSION = $ZoneMinder::Base::VERSION; use ZoneMinder::Config qw(:all); use ZoneMinder::Logger qw(:all); use ZoneMinder::Database qw(:all); -require ZoneMinder::Server; -require ZoneMinder::Storage; use POSIX; - -sub new { - my ( $parent, $id, $data ) = @_; - - my $self = {}; - bless $self, $parent; - if ( ( $$self{Id} = $id ) or $data ) { -#$log->debug("loading $parent $id") if $debug or DEBUG_ALL; - $self->load( $data ); - } - return $self; -} # end sub new - -sub load { - my ( $self, $data ) = @_; - my $type = ref $self; - if ( ! $data ) { -#$log->debug("Object::load Loading from db $type"); - $data = $ZoneMinder::Database::dbh->selectrow_hashref( 'SELECT * FROM Monitors WHERE Id=?', {}, $$self{Id} ); - if ( ! $data ) { - if ( $ZoneMinder::Database::dbh->errstr ) { - Error( "Failure to load Monitor record for $$self{id}: Reason: " . $ZoneMinder::Database::dbh->errstr ); - } # end if - } # end if - } # end if ! $data - if ( $data and %$data ) { - @$self{keys %$data} = values %$data; - } # end if -} # end sub load +use vars qw/ $table $primary_key /; +$table = 'Monitors'; +$primary_key = 'Id'; sub Server { return new ZoneMinder::Server( $_[0]{ServerId} ); diff --git a/scripts/zmaudit.pl.in b/scripts/zmaudit.pl.in index ca4430c22..b1004d81d 100644 --- a/scripts/zmaudit.pl.in +++ b/scripts/zmaudit.pl.in @@ -206,11 +206,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}/$monitor_dir/$day_dir': $!" ); + Error( "Can't chdir to '$$Storage{Path}/$day_dir': $!" ); next; } if ( ! opendir( DIR, '.' ) ) { - Error( "Can't open directory $$Storage{Path}/$monitor_dir/'$day_dir': $!" ); + Error( "Can't open directory '$$Storage{Path}/$day_dir': $!" ); next; } my @event_links = sort { $b <=> $a } grep { -l $_ } readdir( DIR ); @@ -237,7 +237,7 @@ MAIN: while( $loop ) { Debug( "Checking link $event_link points to $event_path " ); my $Event = $fs_events->{$event} = new ZoneMinder::Event(); $$Event{Id} = $event; - $$Event{Path} = join('/', $Storage->Path(), $monitor_dir,$day_dir,$event_path); + $$Event{Path} = join('/', $Storage->Path(), $day_dir,$event_path); $Event->MonitorId( $monitor_dir ); $Event->StorageId( $Storage->Id() ); } # event path exists diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp index d04aca2db..bd72ae3a9 100644 --- a/src/zm_ffmpeg_camera.cpp +++ b/src/zm_ffmpeg_camera.cpp @@ -167,7 +167,7 @@ int FfmpegCamera::Capture( Image &image ) Error( "Unable to read packet from stream %d: error %d \"%s\".", packet.stream_index, avResult, errbuf ); return( -1 ); } - Debug( 5, "Got packet from stream %d", packet.stream_index ); + Debug( 5, "Got packet from stream %d dts (%d) pts(%d)", packet.stream_index, packet.pts, packet.dts ); // What about audio stream? Maybe someday we could do sound detection... if ( packet.stream_index == mVideoStreamId ) { #if LIBAVCODEC_VERSION_CHECK(52, 23, 0, 23, 0) @@ -290,7 +290,6 @@ int FfmpegCamera::OpenFfmpeg() { Debug ( 1, "Opened input" ); Info( "Stream open %s", mPath.c_str() ); - startTime=av_gettime();//FIXME here or after find_Stream_info //FIXME can speed up initial analysis but need sensible parameters... //mFormatContext->probesize = 32; @@ -305,6 +304,7 @@ int FfmpegCamera::OpenFfmpeg() { #endif Fatal( "Unable to find stream info from %s due to: %s", mPath.c_str(), strerror(errno) ); + startTime=av_gettime();//FIXME here or after find_Stream_info Debug ( 1, "Got stream info" ); // Find first video stream present @@ -584,7 +584,7 @@ Debug(5, "After av_read_frame (%d)", ret ); Error( "Unable to read packet from stream %d: error %d \"%s\".", packet->stream_index, ret, errbuf ); return( -1 ); } - Debug( 5, "Got packet from stream %d", packet->stream_index ); + Debug( 4, "Got packet from stream %d dts (%d) pts(%d)", packet->stream_index, packet->dts, packet->pts ); //Video recording if ( recording ) { @@ -636,7 +636,7 @@ Debug(5, "After av_read_frame (%d)", ret ); while ( ( queued_packet = packetqueue.popPacket() ) ) { packet_count += 1; //Write the packet to our video store - Debug(2, "Writing queued packet stream: %d KEY %d", queued_packet->stream_index, packet->flags & AV_PKT_FLAG_KEY ); + Debug(2, "Writing queued packet stream: %d KEY %d, remaining (%d)", queued_packet->stream_index, packet->flags & AV_PKT_FLAG_KEY, packetqueue.size() ); if ( queued_packet->stream_index == mVideoStreamId ) { ret = videoStore->writeVideoFramePacket( queued_packet, mFormatContext->streams[mVideoStreamId]); } else if ( queued_packet->stream_index == mAudioStreamId ) { @@ -748,6 +748,7 @@ Debug(5, "After av_read_frame (%d)", ret ); Debug( 3, "Some other stream index %d", packet->stream_index ); #endif } + if ( videoStore ) zm_av_unref_packet( packet ); } // end while ! frameComplete return (frameCount); diff --git a/src/zm_packetqueue.cpp b/src/zm_packetqueue.cpp index 42a74af98..5758e8871 100644 --- a/src/zm_packetqueue.cpp +++ b/src/zm_packetqueue.cpp @@ -37,10 +37,14 @@ bool zm_packetqueue::queuePacket( AVPacket* packet ) { //AVPacket *input_ref = (AVPacket *)av_malloc(sizeof(AVPacket)); //if ( av_packet_ref( input_ref, packet ) < 0 ) { - //free(input_ref); - //return false; - //} + if ( av_packet_ref( packet, packet ) < 0 ) { +Error("error refing packet"); + //av_free_packet(input_ref); + return false; + } + pktQueue.push( packet ); + //pktQueue.push( input_ref ); return true; } @@ -66,3 +70,7 @@ void zm_packetqueue::clearQueue() { zm_av_unref_packet( packet ); } } + +unsigned int zm_packetqueue::size() { + return pktQueue.size(); +} diff --git a/src/zm_packetqueue.h b/src/zm_packetqueue.h index f79502996..60a9620a4 100644 --- a/src/zm_packetqueue.h +++ b/src/zm_packetqueue.h @@ -38,6 +38,7 @@ public: bool popVideoPacket(AVPacket* packet); bool popAudioPacket(AVPacket* packet); void clearQueue( ); + unsigned int size(); private: std::queue pktQueue; diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index 311318a90..95dc9dd7f 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -274,6 +274,7 @@ Debug(2, "Have audio_output_context"); startDts = 0; filter_in_rescale_delta_last = AV_NOPTS_VALUE; + // now - when streaming started startTime=av_gettime()-nStartTime;//oc->start_time; Info("VideoStore startTime=%d\n",startTime); } // VideoStore::VideoStore @@ -342,26 +343,39 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt, AVStream *input_video_stre Debug(2, "writeVideoFrame init_packet"); av_init_packet(&opkt); +if ( 1 ) { + if ( ! startPts ) { + //never gets set, so the first packet can set it. + startPts = ipkt->pts; + } //Scale the PTS of the outgoing packet to be the correct time base if (ipkt->pts != AV_NOPTS_VALUE) { - opkt.pts = av_rescale_q(ipkt->pts-startPts, input_video_stream->time_base, video_stream->time_base) - ost_tb_start_time; + opkt.pts = av_rescale_q(ipkt->pts-startPts, input_video_stream->time_base, video_stream->time_base); + //- ost_tb_start_time; Debug(3, "opkt.pts = %d from ipkt->pts(%d) - startPts(%d), input->time_base(%d) video_stream->time-base(%d)", opkt.pts, ipkt->pts, startPts, input_video_stream->time_base, video_stream->time_base ); } else { + Debug(3, "opkt.pts = undef"); opkt.pts = AV_NOPTS_VALUE; } + if ( ! startDts ) { + startDts = input_video_stream->cur_dts; +} //Scale the DTS of the outgoing packet to be the correct time base if(ipkt->dts == AV_NOPTS_VALUE) { opkt.dts = av_rescale_q(input_video_stream->cur_dts-startDts, AV_TIME_BASE_Q, video_stream->time_base); - Debug(3, "opkt.dts = %d from input_video_stream->cur_dts(%d) - startDts(%d), video_stream->time-base(%d)", opkt.dts, input_video_stream->cur_dts, startDts, video_stream->time_base ); + Debug(3, "opkt.dts = %d from input_video_stream->cur_dts(%d) - startDts(%d), video_stream->time-base(%d)", opkt.dts, input_video_stream->cur_dts, startDts, video_stream->time_base ); } else { opkt.dts = av_rescale_q(ipkt->dts-startDts, input_video_stream->time_base, video_stream->time_base); Debug(3, "opkt.dts = %d from ipkt->dts(%d) - startDts(%d), video_stream->time-base(%d)", opkt.dts, ipkt->dts, startDts, video_stream->time_base ); } - opkt.dts -= ost_tb_start_time; + //opkt.dts -= ost_tb_start_time; opkt.duration = av_rescale_q(ipkt->duration, input_video_stream->time_base, video_stream->time_base); +} else { + av_packet_rescale_ts( &opkt, input_video_stream->time_base, video_stream->time_base ); +} opkt.flags = ipkt->flags; opkt.pos=-1; diff --git a/web/includes/Event.php b/web/includes/Event.php index e368d8e89..430c64202 100644 --- a/web/includes/Event.php +++ b/web/includes/Event.php @@ -73,7 +73,7 @@ class Event { } - public function LinkPath() { + public function Link_Path() { if ( ZM_USE_DEEP_STORAGE ) { return $this->{'MonitorId'} .'/'.strftime( "%y/%m/%d/.", $this->Time()).$this->{'Id'}; } @@ -82,6 +82,7 @@ class Event { } public function delete() { + # This wouldn't work with foreign keys dbQuery( 'DELETE FROM Events WHERE Id = ?', array($this->{'Id'}) ); if ( !ZM_OPT_FAST_DELETE ) { dbQuery( 'DELETE FROM Stats WHERE EventId = ?', array($this->{'Id'}) ); @@ -90,15 +91,28 @@ class Event { # Assumption: All events haev a start time $start_date = date_parse( $this->{'StartTime'} ); + if ( ! $start_date ) { + Error("Unable to parse start time for event " . $this->{'Id'} . ' not deleting files.' ); + return; + } $start_date['year'] = $start_date['year'] % 100; $Storage = $this->Storage(); # So this is because ZM creates a link under teh day pointing to the time that the event happened. + if ( ! $this->Link_Path() ) { + Error("Unable to determine link path for event " . $this->{'Id'} . ' not deleting files.' ); + return; + } + $eventlink_path = $Storage->Path().'/'.$this->Link_Path(); if ( $id_files = glob( $eventlink_path ) ) { + if ( ! $eventPath = readlink($id_files[0]) ) { + Error("Unable to read link at $id_files[0]"); + return; + } # I know we are using arrays here, but really there can only ever be 1 in the array - $eventPath = preg_replace( '/\.'.$event['Id'].'$/', readlink($id_files[0]), $id_files[0] ); + $eventPath = preg_replace( '/\.'.$this->{'Id'}.'$/', $eventPath, $id_files[0] ); deletePath( $eventPath ); deletePath( $id_files[0] ); $pathParts = explode( '/', $eventPath ); @@ -118,7 +132,7 @@ class Event { } # ! ZM_OPT_FAST_DELETE } # end Event->delete -public function getStreamSrc( $args, $querySep='&' ) { + public function getStreamSrc( $args, $querySep='&' ) { return ( ZM_BASE_PATH != '/' ? ZM_BASE_PATH : '' ).'/index.php?view=view_video&eid='.$this->{'Id'}; $streamSrc = ZM_BASE_URL.ZM_PATH_ZMS; diff --git a/web/includes/Storage.php b/web/includes/Storage.php index 546cb9cbe..e5814ef61 100644 --- a/web/includes/Storage.php +++ b/web/includes/Storage.php @@ -1,51 +1,74 @@ $v) { - $this->{$k} = $v; - } - } else { - $this->{'Name'} = ''; - $this->{'Path'} = ''; - } + public function __construct( $IdOrRow = NULL ) { + $row = NULL; + if ( $IdOrRow ) { + if ( is_integer( $IdOrRow ) or is_numeric( $IdOrRow ) ) { + $row = dbFetchOne( 'SELECT * FROM Storage WHERE Id=?', NULL, array( $IdOrRow ) ); + if ( ! $row ) { + Error("Unable to load Storage record for Id=" . $IdOrRow ); + } + } elseif ( is_array( $IdOrRow ) ) { + $row = $IdOrRow; + } } + if ( $row ) { + foreach ($row as $k => $v) { + $this->{$k} = $v; + } + } else { + $this->{'Name'} = ''; + $this->{'Path'} = ''; + } + } - public function Path() { - if ( isset( $this->{'Path'} ) and ( $this->{'Path'} != '' ) ) { - return $this->{'Path'}; - } else if ( ! isset($this->{'Id'}) ) { - return ZM_DIR_EVENTS; - } - return $this->{'Name'}; - } - public function __call( $fn, array $args= NULL){ - if(isset($this->{$fn})){ - return $this->{$fn}; - #array_unshift($args, $this); - #call_user_func_array( $this->{$fn}, $args); - } + public function Path() { + if ( isset( $this->{'Path'} ) and ( $this->{'Path'} != '' ) ) { + return $this->{'Path'}; + } else if ( ! isset($this->{'Id'}) ) { + return ZM_DIR_EVENTS; } - public static function find_all() { - $storage_areas = array(); - $result = dbQuery( 'SELECT * FROM Storage ORDER BY Name'); - $results = $result->fetchALL(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'Storage' ); - foreach ( $results as $row => $obj ) { - $storage_areas[] = $obj; - } - return $storage_areas; + return $this->{'Name'}; + } + public function Name() { + if ( isset( $this->{'Name'} ) and ( $this->{'Name'} != '' ) ) { + return $this->{'Name'}; + } else if ( ! isset($this->{'Id'}) ) { + return 'Default'; } + return $this->{'Name'}; + } + + public function __call( $fn, array $args= NULL){ + if(isset($this->{$fn})){ + return $this->{$fn}; +#array_unshift($args, $this); +#call_user_func_array( $this->{$fn}, $args); + } + } + public static function find_all() { + $storage_areas = array(); + $result = dbQuery( 'SELECT * FROM Storage ORDER BY Name'); + $results = $result->fetchALL(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'Storage' ); + foreach ( $results as $row => $obj ) { + $storage_areas[] = $obj; + } + return $storage_areas; + } + public function disk_usage_percent() { + $path = $this->Path(); + $total = disk_total_space( $path ); + if ( ! $total ) { + Error("disk_total_space returned false for " . $path ); + return 0; + } + $free = disk_free_space( $path ); + if ( ! $free ) { + Error("disk_free_space returned false for " . $path ); + } + $usage = round(($total - $free) / $total * 100); + return $usage; + } } ?> diff --git a/web/includes/actions.php b/web/includes/actions.php index 09b43696b..6b94b7c68 100644 --- a/web/includes/actions.php +++ b/web/includes/actions.php @@ -124,36 +124,31 @@ if ( !empty($action) ) { } // Event scope actions, view permissions only required - if ( canView( 'Events' ) ) - { - if ( $action == "filter" ) - { - if ( !empty($_REQUEST['subaction']) ) - { + if ( canView( 'Events' ) ) { + + if ( $action == 'filter' ) { + if ( !empty($_REQUEST['subaction']) ) { if ( $_REQUEST['subaction'] == "addterm" ) $_REQUEST['filter'] = addFilterTerm( $_REQUEST['filter'], $_REQUEST['line'] ); elseif ( $_REQUEST['subaction'] == "delterm" ) $_REQUEST['filter'] = delFilterTerm( $_REQUEST['filter'], $_REQUEST['line'] ); - } - elseif ( canEdit( 'Events' ) ) - { - if ( !empty($_REQUEST['execute']) ) - $tempFilterName = "_TempFilter".time(); - if ( isset($tempFilterName) ) { - $filterName = $tempFilterName; - } - elseif ( !empty($_REQUEST['newFilterName']) ) { + } elseif ( canEdit( 'Events' ) ) { + $sql = ''; + $endSql = ''; + $filterName = ''; + if ( !empty($_REQUEST['execute']) ) { + // TempFilterName is used in event listing later on + $tempFilterName = $filterName = "_TempFilter".time(); + } elseif ( !empty($_REQUEST['newFilterName']) ) { $filterName = $_REQUEST['newFilterName']; - $sql = "replace into Filters set Name = ".dbEscape($filterName).","; - $endSql = ''; } - else { - $doUpdate = 1; - $sql = "update Filters set"; - $endSql = "where Id = ".$_REQUEST['filterId']; + if ( $filterName ) { + $sql = "REPLACE INTO Filters SET Name = ".dbEscape($filterName).","; + } else { + $sql = 'UPDATE Filters SET'; + $endSql = "where Id = ".$_REQUEST['Id']; } - if ( !empty($filterName) || $doUpdate ) - { + if ( !empty($filterName) || $endSql ) { $_REQUEST['filter']['sort_field'] = validStr($_REQUEST['sort_field']); $_REQUEST['filter']['sort_asc'] = validStr($_REQUEST['sort_asc']); $_REQUEST['filter']['limit'] = validInt($_REQUEST['limit']); @@ -180,9 +175,9 @@ if ( !empty($action) ) { dbQuery( $sql ); $refreshParent = true; } - } - } - } + } // end if canedit events + } // end if action == filter + } // end if canview events // Event scope actions, edit permissions required if ( canEdit( 'Events' ) ) @@ -223,17 +218,18 @@ if ( !empty($action) ) { } } } - elseif ( $action == "delete" ) + elseif ( $action == 'delete' ) { foreach( getAffectedIds( 'markEid' ) as $markEid ) { deleteEvent( $markEid ); $refreshParent = true; } - if ( !empty($_REQUEST['fid']) ) - { - dbQuery( 'DELETE FROM Filters WHERE Id=?', array( $_REQUEST['filterId'] ) ); - //$refreshParent = true; + if ( isset( $_REQUEST['object'] ) and ( $_REQUEST['object'] == 'filter' ) ) { + if ( !empty($_REQUEST['Id']) ) { + dbQuery( 'DELETE FROM Filters WHERE Id=?', array( $_REQUEST['Id'] ) ); + //$refreshParent = true; + } } } } diff --git a/web/includes/functions.php b/web/includes/functions.php index 2b97456f7..a3e3834dc 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -450,6 +450,7 @@ function getEventDefaultVideoPath( $event ) { } function deletePath( $path ) { +Error("deletePath $path"); if ( is_dir( $path ) ) { system( escapeshellcmd( "rm -rf ".$path ) ); } else { @@ -1220,6 +1221,8 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&' ) { $filter['sql'] = ''; $filter['fields'] = ''; + $StorageArea = NULL; + if ( isset($filter['terms']) && count($filter['terms']) ) { for ( $i = 0; $i < count($filter['terms']); $i++ ) { if ( isset($filter['terms'][$i]['cnj']) ) { @@ -1270,10 +1273,27 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&' ) { $filter['sql'] .= 'E.'.$filter['terms'][$i]['attr']; break; case 'DiskPercent': - $filter['sql'] .= getDiskPercent(); + // Need to specify a storage area, so need to look through other terms looking for a storage area, else we default to ZM_EVENTS_PATH + if ( ! $StorageArea ) { + for ( $j = $i; $j < count($filter['terms']); $j++ ) { + if ( isset($filter['terms'][$i]['attr']) and $filter['terms'][$i]['attr'] == 'StorageId' ) { + $StorageArea = new Storage( $filter['terms'][$i]['val'] ); + } + } // end foreach remaining term + } // end no StorageArea found yet + + $filter['sql'] .= getDiskPercent( $StorageArea ); break; case 'DiskBlocks': - $filter['sql'] .= getDiskBlocks(); + // Need to specify a storage area, so need to look through other terms looking for a storage area, else we default to ZM_EVENTS_PATH + if ( ! $StorageArea ) { + for ( $j = $i; $j < count($filter['terms']); $j++ ) { + if ( isset($filter['terms'][$i]['attr']) and $filter['terms'][$i]['attr'] == 'StorageId' ) { + $StorageArea = new Storage( $filter['terms'][$i]['val'] ); + } + } // end foreach remaining term + } // end no StorageArea found yet + $filter['sql'] .= getDiskBlocks( $StorageArea ); break; case 'SystemLoad': $filter['sql'] .= getLoad(); @@ -1294,6 +1314,10 @@ function parseFilter( &$filter, $saveToSession=false, $querySep='&' ) { } else { $value = dbEscape($value); } + case 'StorageId': + $StorageArea = new Storage( $value ); + $value = dbEscape($value); + break; case 'DateTime': $value = "'".strftime( STRF_FMT_DATETIME_DB, strtotime( $value ) )."'"; break; @@ -1460,35 +1484,15 @@ function getLoad() { return( $load[0] ); } -function getDiskPercent() { - if ( !empty(ZM_DIR_EVENTS) ) { - $total = disk_total_space(ZM_DIR_EVENTS); - if ( ! $total ) { - Error("disk_total_space returned false for " . ZM_DIR_EVENTS ); - return 0; - } - $free = disk_free_space(ZM_DIR_EVENTS); - if ( ! $free ) { - Error("disk_free_space returned false for " . ZM_DIR_EVENTS ); - } - $space = round(($total - $free) / $total * 100); - $spaceString = 'Default '.$space.'%'; - } - else { - $spaceString = ''; - } - $storageAreas = Storage::find_all(); - foreach($storageAreas as $storageArea) { - $storageTotal = disk_total_space($storageArea->Path); - $storageFree = disk_free_space($storageArea->Path); - $storageSpace = round(($storageTotal - $storageFree) / $storageTotal * 100); - $spaceString .= ', '.$storageArea->Name.' '.$storageSpace.'%'; - } - return( $spaceString ); +function getDiskPercent( $StorageArea = NULL ) { + if ( ! $StorageArea ) $StorageArea = new Storage(); + + return $StorageArea->disk_usage_percent(); } function getDiskBlocks() { - $df = shell_exec( 'df '.ZM_DIR_EVENTS ); + if ( ! $StorageArea ) $StorageArea = new Storage(); + $df = shell_exec( 'df '.$StorageArea->Path() ); $space = -1; if ( preg_match( '/\s(\d+)\s+\d+\s+\d+%/ms', $df, $matches ) ) $space = $matches[1]; diff --git a/web/skins/classic/includes/functions.php b/web/skins/classic/includes/functions.php index 057245de0..42ee5ec52 100644 --- a/web/skins/classic/includes/functions.php +++ b/web/skins/classic/includes/functions.php @@ -249,7 +249,14 @@ function getNavBarHTML() { diff --git a/web/skins/classic/views/filter.php b/web/skins/classic/views/filter.php index 4d818a408..93dd66597 100644 --- a/web/skins/classic/views/filter.php +++ b/web/skins/classic/views/filter.php @@ -19,23 +19,26 @@ // if ( !canView( 'Events' ) ) { - $view = "error"; + $view = 'error'; return; } -$selectName = "filterId"; +$selectName = 'Id'; $filterNames = array( ''=>translate('ChooseFilter') ); +$dbFilter = NULL; + foreach ( dbFetchAll( "select * from Filters order by Name" ) as $row ) { $filterNames[$row['Id']] = $row['Name']; if ( $row['Background'] ) $filterNames[$row['Id']] .= "*"; if ( $row['Concurrent'] ) $filterNames[$row['Id']] .= "&"; - if ( !empty($_REQUEST['reload']) && isset($_REQUEST['filterId']) && $_REQUEST['filterId'] == $row['Id'] ) + if ( !empty($_REQUEST['reload']) && isset($_REQUEST['Id']) && $_REQUEST['Id'] == $row['Id'] ) { $dbFilter = $row; + } } -$backgroundStr = ""; -if ( isset($dbFilter) ) { +$backgroundStr = ''; +if ( $dbFilter ) { if ( $dbFilter['Background'] ) $backgroundStr = '['.strtolower(translate('Background')).']'; $_REQUEST['filter'] = jsonDecode( $dbFilter['Query'] ); @@ -57,7 +60,7 @@ if ( isset( $_REQUEST['reload'] ) and ! $_REQUEST['reload'] ) { $dbFilter['AutoUpload'] = isset( $_REQUEST['AutoUpload'] ); $dbFilter['AutoVideo'] = isset( $_REQUEST['AutoVideo'] ); $dbFilter['AutoDelete'] = isset( $_REQUEST['AutoDelete'] ); - $dbFilter['Name'] = $_REQUEST['filterId']; + $dbFilter['Name'] = $_REQUEST['Id']; } $conjunctionTypes = array( @@ -163,7 +166,7 @@ xhtmlHeaders(__FILE__, translate('EventFilter') ); - +
1 ) { echo buildSelect( $selectName, $filterNames, "submitToFilter( this, 1 );" ); } else { ?>

diff --git a/web/views/image.php b/web/views/image.php index 17de2ec81..bce07e765 100644 --- a/web/views/image.php +++ b/web/views/image.php @@ -39,8 +39,6 @@ if ( !canView( 'Events' ) ) { require_once('includes/Event.php'); require_once('includes/Frame.php'); -header( 'Content-type: image/jpeg' ); - // Compatibility for PHP 5.4 if (!function_exists('imagescale')) { function imagescale($image, $new_width, $new_height = -1, $mode = 0) { @@ -85,6 +83,10 @@ if ( empty($_REQUEST['path']) ) { $retval = 0; exec( $command, $output, $retval ); Debug("Retval: $retval, output: " . implode("\n", $output)); + if ( ! file_exists( $path ) ) { + header("HTTP/1.0 404 Not Found"); + Fatal("Can't create frame images from video for this event (".$Event->DefaultVideo() ); + } } else { header("HTTP/1.0 404 Not Found"); Fatal("Can't create frame images from video becuase there is no video file for this event (".$Event->DefaultVideo() ); @@ -138,6 +140,8 @@ if( !empty($_REQUEST['height']) ) { } +header( 'Content-type: image/jpeg' ); + if ( $errorText ) { Error( $errorText ); } else { @@ -167,13 +171,8 @@ if ( $errorText ) { # Slight optimisation, thumbnails always specify width and height, so we can cache them. $scaled_path = preg_replace('/\.jpg$/', "-${width}x${height}.jpg", $path ); - if ( file_exists( $scaled_path ) ) { - Debug( "Using cached scaled image at $scaled_path."); - if ( ! readfile( $scaled_path ) ) { - Error("No bytes read from scaled image". $scaled_path ); - } - } else { - Debug( "Cached scaled image does not exist at $scaled_path. Creating it"); + if ( ! file_exists( $scaled_path ) or ! readfile( $scaled_path ) ) { + Debug( "Cached scaled image does not exist at $scaled_path or is no good.. Creating it"); ob_start(); if ( ! $i ) $i = imagecreatefromjpeg( $path );