diff --git a/docs/api.rst b/docs/api.rst index a5bdd35f3..942d701e2 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -29,13 +29,13 @@ This means if you plan to use cuRL to experiment with these APIs, you first need :: - curl -XPOST -d "user=XXXX&pass=YYYY" -c cookies.txt http://yourzmip/zm/api/login.json + curl -XPOST -d "user=XXXX&pass=YYYY" -c cookies.txt http://yourzmip/zm/api/host/login.json Staring ZM 1.32.0, you also have a `logout` API that basically clears your session. It looks like this: :: - curl -b cookies.txt http://yourzmip/zm/api/logout.json + curl -b cookies.txt http://yourzmip/zm/api/host/logout.json **Login process for older versions of ZoneMinder** diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Event.pm b/scripts/ZoneMinder/lib/ZoneMinder/Event.pm index 8eca805aa..71986ad05 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Event.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Event.pm @@ -254,6 +254,33 @@ sub LinkPath { return $$event{LinkPath}; } # end sub LinkPath +sub createPath { + makePath($_[0]->Path()); +} + +sub createLinkPath { + my $LinkPath = $_[0]->LinkPath(); + my $EventPath = $_[0]->EventPath(); + if ( $LinkPath ) { + if ( !symlink($EventPath, $LinkPath) ) { + Error("Failed symlinking $EventPath to $LinkPath"); + } + } +} + +sub idPath { + return sprintf('%s/.%d', $_[0]->Path(), $_[0]->{Id}); +} + +sub createIdFile { + my $event = shift; + my $idFile = $event->idPath(); + open( my $ID_FP, '>', $idFile ) + or Error("Can't open $idFile: $!"); + close($ID_FP); + setFileOwner($idFile); +} + sub GenerateVideo { my ( $self, $rate, $fps, $scale, $size, $overwrite, $format ) = @_; diff --git a/scripts/ZoneMinder/lib/ZoneMinder/General.pm b/scripts/ZoneMinder/lib/ZoneMinder/General.pm index c91511869..1dc9291f5 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/General.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/General.pm @@ -47,10 +47,8 @@ our %EXPORT_TAGS = ( getCmdFormat runCommand setFileOwner - getEventPath createEventPath createEvent - deleteEventFiles makePath jsonEncode jsonDecode @@ -181,70 +179,14 @@ sub runCommand { return( $output ); } -sub getEventPath { - my $event = shift; - - my $Storage = new ZoneMinder::Storage( $$event{StorageId} ); - my $event_path = join( '/', - $Storage->Path(), - $event->{MonitorId}, - ( $Config{ZM_USE_DEEP_STORAGE} ? strftime( "%y/%m/%d/%H/%M/%S", localtime($event->{Time}) ) : $event->{Id} ), - ); - - return( $event_path ); -} - sub createEventPath { -# -# WARNING assumes running from events directory -# my $event = shift; - my $Storage = new ZoneMinder::Storage( $$event{Id} ); - my $eventPath = $Storage->Path() . '/'.$event->{MonitorId}; + my $eventPath = $event->Path(); + $event->createPath(); + $event->createIdFile(); + $event->createLinkPath(); - if ( $Config{ZM_USE_DEEP_STORAGE} ) { - my @startTime = localtime( $event->{StartTime} ); - - my @datetimeParts = (); - $datetimeParts[0] = sprintf( "%02d", $startTime[5]-100 ); - $datetimeParts[1] = sprintf( "%02d", $startTime[4]+1 ); - $datetimeParts[2] = sprintf( "%02d", $startTime[3] ); - $datetimeParts[3] = sprintf( "%02d", $startTime[2] ); - $datetimeParts[4] = sprintf( "%02d", $startTime[1] ); - $datetimeParts[5] = sprintf( "%02d", $startTime[0] ); - - my $datePath = join('/',@datetimeParts[0..2]); - my $timePath = join('/',@datetimeParts[3..5]); - - makePath( $datePath, $eventPath ); - $eventPath .= '/'.$datePath; - -# Create event id symlink - my $idFile = sprintf( "%s/.%d", $eventPath, $event->{Id} ); - symlink( $timePath, $idFile ) - or Fatal( "Can't symlink $idFile -> $eventPath: $!" ); - - makePath( $timePath, $eventPath ); - $eventPath .= '/'.$timePath; - setFileOwner( $idFile ); # Must come after directory has been created - -# Create empty id tag file - $idFile = sprintf( "%s/.%d", $eventPath, $event->{Id} ); - open( my $ID_FP, ">", $idFile ) - or Fatal( "Can't open $idFile: $!" ); - close( $ID_FP ); - setFileOwner( $idFile ); - } else { - makePath( $event->{Id}, $eventPath ); - $eventPath .= '/'.$event->{Id}; - - my $idFile = sprintf( "%s/.%d", $eventPath, $event->{Id} ); - open( my $ID_FP, ">", $idFile ) - or Fatal( "Can't open $idFile: $!" ); - close( $ID_FP ); - setFileOwner( $idFile ); - } - return( $eventPath ); + return $eventPath; } use Data::Dumper; @@ -481,53 +423,6 @@ sub updateEvent { or Fatal( "Can't execute sql '$sql': ".$sth->errstr() ); } -sub deleteEventFiles { -# -# WARNING assumes running from events directory -# - my $event_id = shift; - my $monitor_id = shift; - $monitor_id = '*' if ( !defined($monitor_id) ); - - if ( $Config{ZM_USE_DEEP_STORAGE} ) { - my $link_path = $monitor_id."/*/*/*/.".$event_id; -#Debug( "LP1:$link_path" ); - my @links = glob($link_path); -#Debug( "L:".$links[0].": $!" ); - if ( @links ) { - ( $link_path ) = ( $links[0] =~ /^(.*)$/ ); # De-taint -#Debug( "LP2:$link_path" ); - - ( my $day_path = $link_path ) =~ s/\.\d+//; -#Debug( "DP:$day_path" ); - my $event_path = $day_path.readlink( $link_path ); - ( $event_path ) = ( $event_path =~ /^(.*)$/ ); # De-taint -#Debug( "EP:$event_path" ); - my $command = "/bin/rm -rf ".$event_path; -#Debug( "C:$command" ); - executeShellCommand( $command ); - - unlink( $link_path ) or Error( "Unable to unlink '$link_path': $!" ); - my @path_parts = split( /\//, $event_path ); - for ( my $i = int(@path_parts)-2; $i >= 1; $i-- ) { - my $delete_path = join( '/', @path_parts[0..$i] ); -#Debug( "DP$i:$delete_path" ); - my @has_files = glob( $delete_path."/*" ); -#Debug( "HF1:".$has_files[0] ) if ( @has_files ); - last if ( @has_files ); - @has_files = glob( $delete_path."/.[0-9]*" ); -#Debug( "HF2:".$has_files[0] ) if ( @has_files ); - last if ( @has_files ); - my $command = "/bin/rm -rf ".$delete_path; - executeShellCommand( $command ); - } - } - } else { - my $command = "/bin/rm -rf $monitor_id/$event_id"; - executeShellCommand( $command ); - } -} - sub makePath { my $path = shift; my $root = shift; diff --git a/scripts/zmfilter.pl.in b/scripts/zmfilter.pl.in index 0d76cbd97..6277469b6 100644 --- a/scripts/zmfilter.pl.in +++ b/scripts/zmfilter.pl.in @@ -475,7 +475,7 @@ sub uploadArchFile { } my $archFile = $event->{MonitorName}.'-'.$event->{Id}; - my $archImagePath = getEventPath($event) + my $archImagePath = $event->Path() .'/' .( ( $Config{ZM_UPLOAD_ARCH_ANALYSE} ) @@ -951,7 +951,7 @@ sub executeCommand { my $filter = shift; my $event = shift; - my $event_path = getEventPath($event); + my $event_path = $event->Path(); my $command = $filter->{AutoExecuteCmd}; $command .= " $event_path"; diff --git a/utils/packpack/startpackpack.sh b/utils/packpack/startpackpack.sh index 3ed227a44..677fa1f32 100755 --- a/utils/packpack/startpackpack.sh +++ b/utils/packpack/startpackpack.sh @@ -154,7 +154,7 @@ movecrud () { echo "Unpacking CakePHP-Enum-Behavior plugin..." tar -xzf build/cakephp-enum-behavior-${CEBVER}.tar.gz rmdir web/api/app/Plugin/CakePHP-Enum-Behavior - mv -f crud-${CEBVER} web/api/app/Plugin/CakePHP-Enum-Behavior + mv -f CakePHP-Enum-Behavior-${CEBVER} web/api/app/Plugin/CakePHP-Enum-Behavior fi } diff --git a/web/includes/Monitor.php b/web/includes/Monitor.php index f6ceca734..1ad2df517 100644 --- a/web/includes/Monitor.php +++ b/web/includes/Monitor.php @@ -510,8 +510,12 @@ private $control_fields = array( $source = preg_replace( '/^.*\//', '', $this->{'Path'} ); } elseif ( $this->{'Type'} == 'Ffmpeg' || $this->{'Type'} == 'Libvlc' || $this->{'Type'} == 'WebSite' ) { $url_parts = parse_url( $this->{'Path'} ); - if ( ZM_WEB_FILTER_SOURCE == "Hostname" ) { # Filter out everything but the hostname - $source = $url_parts['host']; + if ( ZM_WEB_FILTER_SOURCE == 'Hostname' ) { # Filter out everything but the hostname + if ( isset($url_parts['host']) ) { + $source = $url_parts['host']; + } else { + $source = $this->{'Path'}; + } } elseif ( ZM_WEB_FILTER_SOURCE == "NoCredentials" ) { # Filter out sensitive and common items unset($url_parts['user']); unset($url_parts['pass']); @@ -531,6 +535,9 @@ private $control_fields = array( return $source; } // end function Source + public function Url() { + return $this->Server()->Url() .':'. ( ZM_MIN_STREAMING_PORT ? (ZM_MIN_STREAMING_PORT+$this->Id()) : $_SERVER['SERVER_PORT'] ); + } } // end class Monitor ?> diff --git a/web/includes/functions.php b/web/includes/functions.php index 5537d94bb..639de596f 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -36,25 +36,26 @@ function noCacheHeaders() { } function CORSHeaders() { - if ( isset( $_SERVER['HTTP_ORIGIN'] ) ) { + if ( isset($_SERVER['HTTP_ORIGIN']) ) { # The following is left for future reference/use. $valid = false; - $servers = dbFetchAll( 'SELECT * FROM Servers' ); + $servers = dbFetchAll('SELECT * FROM Servers'); if ( sizeof($servers) <= 1 ) { # Only need CORSHeaders in the event that there are multiple servers in use. return; } foreach( $servers as $row ) { - $Server = new Server( $row ); - if ( $_SERVER['HTTP_ORIGIN'] == $Server->Url() ) { + $Server = new Server($row); + if ( preg_match('/^'.preg_quote($Server->Url(),'/').'/', $_SERVER['HTTP_ORIGIN']) ) { $valid = true; - header('Access-Control-Allow-Origin: ' . $Server->Url() ); + header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']); header('Access-Control-Allow-Headers: x-requested-with,x-request'); + break; } } - if ( ! $valid ) { - Warning( $_SERVER['HTTP_ORIGIN'] . ' is not found in servers list.' ); + if ( !$valid ) { + Warning($_SERVER['HTTP_ORIGIN'] . ' is not found in servers list.'); } } } diff --git a/web/skins/classic/views/js/montage.js.php b/web/skins/classic/views/js/montage.js.php index 1b67d764b..3b0c5005b 100644 --- a/web/skins/classic/views/js/montage.js.php +++ b/web/skins/classic/views/js/montage.js.php @@ -35,7 +35,7 @@ monitorData[monitorData.length] = { 'connKey': connKey() ?>, 'width': Width() ?>, 'height':Height() ?>, - 'server_url': 'Server()->Url().$_SERVER['PHP_SELF'] ?>', + 'server_url': 'Url() ?>', 'onclick': function(){createPopup( '?view=watch&mid=Id() ?>', 'zmWatchId() ?>', 'watch', Width(), $monitor->PopupScale() ); ?>, Height(), $monitor->PopupScale() ); ?> );}, 'type': 'Type() ?>', 'refresh': 'Refresh() ?>' diff --git a/web/skins/classic/views/js/watch.js.php b/web/skins/classic/views/js/watch.js.php index c446703cf..51c1801e8 100644 --- a/web/skins/classic/views/js/watch.js.php +++ b/web/skins/classic/views/js/watch.js.php @@ -48,7 +48,7 @@ var maxDisplayEvents = ; var monitorId = Id() ?>; var monitorWidth = Width() ?>; var monitorHeight = Height() ?>; -var monitorUrl = 'Server()->Url() . ( ZM_MIN_STREAMING_PORT ? ':'. (ZM_MIN_STREAMING_PORT+$monitor->Id()) : '' ) ) ?>'; +var monitorUrl = 'Url(); ?>'; var monitorType = 'Type() ) ?>'; var monitorRefresh = 'Refresh() ) ?>';