diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index 44eb1a048..d4efb5317 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -434,6 +434,7 @@ DROP TABLE IF EXISTS `Monitors`; CREATE TABLE `Monitors` ( `Id` int(10) unsigned NOT NULL auto_increment, `Name` varchar(64) NOT NULL default '', + `Notes` TEXT NOT NULL default '', `ServerId` int(10) unsigned, `StorageId` smallint(5) unsigned default 0, `Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL','WebSite','NVSocket') NOT NULL default 'Local', diff --git a/db/zm_update-1.33.16.sql b/db/zm_update-1.33.16.sql new file mode 100644 index 000000000..aacfd9425 --- /dev/null +++ b/db/zm_update-1.33.16.sql @@ -0,0 +1,12 @@ + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitors' + AND column_name = 'Notes' + ) > 0, + "SELECT 'Column Notes already exists in Monitors'", + "ALTER TABLE `Monitors` ADD `Notes` TEXT NOT NULL default '' AFTER `Name`" + )); + +PREPARE stmt FROM @s; +EXECUTE stmt; diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec index 2773a4ad0..ffaa075a3 100644 --- a/distros/redhat/zoneminder.spec +++ b/distros/redhat/zoneminder.spec @@ -23,7 +23,7 @@ %global _hardened_build 1 Name: zoneminder -Version: 1.33.15 +Version: 1.33.16 Release: 1%{?dist} Summary: A camera monitoring and analysis tool Group: System Environment/Daemons diff --git a/version b/version index 63984dc0b..c0bd57583 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.33.15 +1.33.16 diff --git a/web/api/app/Controller/GroupsController.php b/web/api/app/Controller/GroupsController.php index 6f0a88300..5d19b5d98 100644 --- a/web/api/app/Controller/GroupsController.php +++ b/web/api/app/Controller/GroupsController.php @@ -77,16 +77,24 @@ class GroupsController extends AppController { } $this->Group->create(); - if ( $this->Group->save($this->request->data) ) { + + if ( $this->request->data['Group']['MonitorIds'] and ! isset($this->request->data['Monitor']) ) { + $this->request->data['Monitor'] = explode(',', $this->request->data['Group']['MonitorIds']); + unset($this->request->data['Group']['MonitorIds']); + } + if ( $this->Group->saveAssociated($this->request->data, array('atomic'=>true)) ) { return $this->flash( __('The group has been saved.'), array('action' => 'index') ); - } - } - $monitors = $this->Group->Monitor->find('list'); + } else { + ZM\Error("Failed to save Group"); + debug($this->Group->invalidFields()); + } + } # end if post + $monitors = $this->Group->Monitor->find('list'); $this->set(compact('monitors')); - } + } # end add /** * edit method diff --git a/web/api/app/Model/Group.php b/web/api/app/Model/Group.php index 108f9b9c7..8d8f533ca 100644 --- a/web/api/app/Model/Group.php +++ b/web/api/app/Model/Group.php @@ -59,7 +59,7 @@ class Group extends AppModel { * * @var array */ - public $hasMany = array( + public $hasAndBelongsToMany = array( 'Monitor' => array( 'className' => 'Monitor', 'joinTable' => 'Groups_Monitors', diff --git a/web/includes/Monitor.php b/web/includes/Monitor.php index 1353f375b..cc51926fd 100644 --- a/web/includes/Monitor.php +++ b/web/includes/Monitor.php @@ -9,111 +9,112 @@ require_once('Storage.php'); class Monitor extends ZM_Object { protected static $table = 'Monitors'; -protected $defaults = array( - 'Id' => null, - 'Name' => '', - 'ServerId' => 0, - 'StorageId' => 0, - 'Type' => 'Ffmpeg', - 'Function' => 'Mocord', - 'Enabled' => array('type'=>'boolean','default'=>1), - 'LinkedMonitors' => array('type'=>'set', 'default'=>null), - 'Triggers' => array('type'=>'set','default'=>''), - 'Device' => '', - 'Channel' => 0, - 'Format' => '0', - 'V4LMultiBuffer' => null, - 'V4LCapturesPerFrame' => 1, - 'Protocol' => null, - 'Method' => '', - 'Host' => null, - 'Port' => '', - 'SubPath' => '', - 'Path' => null, - 'Options' => null, - 'User' => null, - 'Pass' => null, - // These are NOT NULL default 0 in the db, but 0 is not a valid value. FIXME - 'Width' => null, - 'Height' => null, - 'Colours' => 4, - 'Palette' => '0', - 'Orientation' => null, - 'Deinterlacing' => 0, - 'DecoderHWAccelName' => null, - 'DecoderHWAccelDevice' => null, - 'SaveJPEGs' => 3, - 'VideoWriter' => '0', - 'OutputCodec' => null, - 'OutputContainer' => null, - 'EncoderParameters' => "# Lines beginning with # are a comment \n# For changing quality, use the crf option\n# 1 is best, 51 is worst quality\n#crf=23\n", - 'RecordAudio' => array('type'=>'boolean', 'default'=>0), - 'RTSPDescribe' => array('type'=>'boolean','default'=>0), - 'Brightness' => -1, - 'Contrast' => -1, - 'Hue' => -1, - 'Colour' => -1, - 'EventPrefix' => 'Event-', - 'LabelFormat' => '%N - %d/%m/%y %H:%M:%S', - 'LabelX' => 0, - 'LabelY' => 0, - 'LabelSize' => 1, - 'ImageBufferCount' => 100, - 'WarmupCount' => 0, - 'PreEventCount' => 0, - 'PostEventCount' => 0, - 'StreamReplayBuffer' => 0, - 'AlarmFrameCount' => 1, - 'SectionLength' => 600, - 'MinSectionLength' => 10, - 'FrameSkip' => 0, - 'MotionFrameSkip' => 0, - 'AnalysisFPSLimit' => null, - 'AnalysisUpdateDelay' => 0, - 'MaxFPS' => null, - 'AlarmMaxFPS' => null, - 'FPSReportInterval' => 100, - 'RefBlendPerc' => 6, - 'AlarmRefBlendPerc' => 6, - 'Controllable' => array('type'=>'boolean','default'=>0), - 'ControlId' => null, - 'ControlDevice' => null, - 'ControlAddress' => null, - 'AutoStopTimeout' => null, - 'TrackMotion' => array('type'=>'boolean','default'=>0), - 'TrackDelay' => null, - 'ReturnLocation' => -1, - 'ReturnDelay' => null, - 'DefaultRate' => 100, - 'DefaultScale' => 100, - 'SignalCheckPoints' => 0, - 'SignalCheckColour' => '#0000BE', - 'WebColour' => 'red', - 'Exif' => array('type'=>'boolean','default'=>0), - 'Sequence' => null, - 'TotalEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), - 'TotalEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), - 'HourEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), - 'HourEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), - 'DayEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), - 'DayEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), - 'WeekEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), - 'WeekEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), - 'MonthEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), - 'MonthEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), - 'ArchivedEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), - 'ArchivedEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), - 'ZoneCount' => 0, - 'Refresh' => null, - 'DefaultCodec' => 'auto', - 'GroupIds' => array('default'=>array(), 'do_not_update'=>1), -); -private $status_fields = array( - 'Status' => null, - 'AnalysisFPS' => null, - 'CaptureFPS' => null, - 'CaptureBandwidth' => null, -); + protected $defaults = array( + 'Id' => null, + 'Name' => '', + 'Notes' => '', + 'ServerId' => 0, + 'StorageId' => 0, + 'Type' => 'Ffmpeg', + 'Function' => 'Mocord', + 'Enabled' => array('type'=>'boolean','default'=>1), + 'LinkedMonitors' => array('type'=>'set', 'default'=>null), + 'Triggers' => array('type'=>'set','default'=>''), + 'Device' => '', + 'Channel' => 0, + 'Format' => '0', + 'V4LMultiBuffer' => null, + 'V4LCapturesPerFrame' => 1, + 'Protocol' => null, + 'Method' => '', + 'Host' => null, + 'Port' => '', + 'SubPath' => '', + 'Path' => null, + 'Options' => null, + 'User' => null, + 'Pass' => null, + // These are NOT NULL default 0 in the db, but 0 is not a valid value. FIXME + 'Width' => null, + 'Height' => null, + 'Colours' => 4, + 'Palette' => '0', + 'Orientation' => null, + 'Deinterlacing' => 0, + 'DecoderHWAccelName' => null, + 'DecoderHWAccelDevice' => null, + 'SaveJPEGs' => 3, + 'VideoWriter' => '0', + 'OutputCodec' => null, + 'OutputContainer' => null, + 'EncoderParameters' => "# Lines beginning with # are a comment \n# For changing quality, use the crf option\n# 1 is best, 51 is worst quality\n#crf=23\n", + 'RecordAudio' => array('type'=>'boolean', 'default'=>0), + 'RTSPDescribe' => array('type'=>'boolean','default'=>0), + 'Brightness' => -1, + 'Contrast' => -1, + 'Hue' => -1, + 'Colour' => -1, + 'EventPrefix' => 'Event-', + 'LabelFormat' => '%N - %d/%m/%y %H:%M:%S', + 'LabelX' => 0, + 'LabelY' => 0, + 'LabelSize' => 1, + 'ImageBufferCount' => 100, + 'WarmupCount' => 0, + 'PreEventCount' => 0, + 'PostEventCount' => 0, + 'StreamReplayBuffer' => 0, + 'AlarmFrameCount' => 1, + 'SectionLength' => 600, + 'MinSectionLength' => 10, + 'FrameSkip' => 0, + 'MotionFrameSkip' => 0, + 'AnalysisFPSLimit' => null, + 'AnalysisUpdateDelay' => 0, + 'MaxFPS' => null, + 'AlarmMaxFPS' => null, + 'FPSReportInterval' => 100, + 'RefBlendPerc' => 6, + 'AlarmRefBlendPerc' => 6, + 'Controllable' => array('type'=>'boolean','default'=>0), + 'ControlId' => null, + 'ControlDevice' => null, + 'ControlAddress' => null, + 'AutoStopTimeout' => null, + 'TrackMotion' => array('type'=>'boolean','default'=>0), + 'TrackDelay' => null, + 'ReturnLocation' => -1, + 'ReturnDelay' => null, + 'DefaultRate' => 100, + 'DefaultScale' => 100, + 'SignalCheckPoints' => 0, + 'SignalCheckColour' => '#0000BE', + 'WebColour' => 'red', + 'Exif' => array('type'=>'boolean','default'=>0), + 'Sequence' => null, + 'TotalEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), + 'TotalEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), + 'HourEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), + 'HourEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), + 'DayEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), + 'DayEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), + 'WeekEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), + 'WeekEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), + 'MonthEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), + 'MonthEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), + 'ArchivedEvents' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), + 'ArchivedEventDiskSpace' => array('type'=>'integer', 'default'=>null, 'do_not_update'=>1), + 'ZoneCount' => 0, + 'Refresh' => null, + 'DefaultCodec' => 'auto', + 'GroupIds' => array('default'=>array(), 'do_not_update'=>1), + ); + private $status_fields = array( + 'Status' => null, + 'AnalysisFPS' => null, + 'CaptureFPS' => null, + 'CaptureBandwidth' => null, + ); public function Control() { if ( !property_exists($this, 'Control') ) { diff --git a/web/includes/Object.php b/web/includes/Object.php index 6a82ec37f..1c17ce312 100644 --- a/web/includes/Object.php +++ b/web/includes/Object.php @@ -158,14 +158,24 @@ class ZM_Object { # perhaps should turn into a comma-separated string $this->{$k} = implode(',', $v); } else if ( is_string($v) ) { - if ( $v == '' and array_key_exists($k, $this->defaults) ) { - if ( is_array($this->defaults[$k]) ) +if ( 0 ) { +# Remarking this out. We are setting a value, not asking for a default to be set. +# So don't do defaults here, do them somewhere else + if ( ($v == null) and array_key_exists($k, $this->defaults) ) { +Logger::Debug("$k => Have default for $v: "); + if ( is_array($this->defaults[$k]) ) { $this->{$k} = $this->defaults[$k]['default']; - else - $this->{$k} = $this->defaults[$k]; - } else { - $this->{$k} = trim($v); + } else { + $this->{$k} = $this->defaults[$k]; + Logger::Debug("$k => Have default for $v: " . $this->{$k}); + } + } else { + $this->{$k} = trim($v); } +} else { + $this->{$k} = trim($v); +} + } else if ( is_integer($v) ) { $this->{$k} = $v; } else if ( is_bool($v) ) { diff --git a/web/skins/classic/css/base/views/monitor.css b/web/skins/classic/css/base/views/monitor.css index 2b41e7d06..217b2f374 100644 --- a/web/skins/classic/css/base/views/monitor.css +++ b/web/skins/classic/css/base/views/monitor.css @@ -9,6 +9,10 @@ width: 100%; } +textarea, +input[name="newMonitor[Name]"] { + width: 100%; +} input[name="newMonitor[Width]"], input[name="newMonitor[Height]"] { width: 80px; diff --git a/web/skins/classic/views/monitor.php b/web/skins/classic/views/monitor.php index 03e4ce1f8..df3718735 100644 --- a/web/skins/classic/views/monitor.php +++ b/web/skins/classic/views/monitor.php @@ -40,8 +40,8 @@ if ( !empty($_REQUEST['mid']) ) { if ( $monitor and ZM_OPT_X10 ) $x10Monitor = dbFetchOne('SELECT * FROM TriggersX10 WHERE MonitorId = ?', NULL, array($_REQUEST['mid'])); } -if ( !$monitor ) { +if ( !$monitor ) { $nextId = getTableAutoInc('Monitors'); if ( isset($_REQUEST['dupId']) ) { $monitor = new ZM\Monitor($_REQUEST['dupId']); @@ -67,7 +67,6 @@ if ( ZM_OPT_X10 && empty($x10Monitor) ) { function fourcc($a, $b, $c, $d) { return ord($a) | (ord($b) << 8) | (ord($c) << 16) | (ord($d) << 24); } - if ( isset($_REQUEST['newMonitor']) ) { # Update the monitor object with whatever has been set so far. $monitor->set($_REQUEST['newMonitor']); @@ -371,13 +370,6 @@ $label_size = array( 'Large' => 2 ); -$savejpegopts = array( - 'Disabled' => 0, - 'Frames only' => 1, - 'Analysis images only (if available)' => 2, - 'Frames + Analysis images (if available)' => 3, - ); - $codecs = array( 'auto' => translate('Auto'), 'MP4' => translate('MP4'), @@ -459,8 +451,8 @@ foreach ( $tabs as $name=>$value ) { if ( $tab != 'general' ) { ?> + - GroupIds() as $group_id ) { @@ -529,6 +521,7 @@ if ( $tab != 'source' ) { } if ( $tab != 'storage' ) { ?> + @@ -612,6 +605,10 @@ switch ( $tab ) {