'; } else { $html[] = ''; } } } $html[] = ''; // So we ge a trailing \n return implode(PHP_EOL, $html); } function output_script_if_exists($files, $cache_bust=true) { global $skin; $html = array(); foreach ( $files as $file ) { if ( file_exists('skins/'.$skin.'/'.$file) ) { if ( $cache_bust ) { $html[] = ''; } else { $html[] = ''; } } else if ( file_exists($file) ) { if ( $cache_bust ) { $html[] = ''; } else { $html[] = ''; } } } $html[] = ''; // So we ge a trailing \n return implode(PHP_EOL, $html); } function output_cache_busted_stylesheet_links($files) { $html = array(); foreach ( $files as $file ) { $html[] = ''; } if ( ! count($html) ) { ZM\Warning("No files found for $files"); } $html[] = ''; // So we ge a trailing \n return implode(PHP_EOL, $html); } ?> <?php echo validHtmlStr(ZM_WEB_TITLE_PREFIX) . ' - ' . validHtmlStr($title) ?> "; } else { echo ' '; } echo output_cache_busted_stylesheet_links(array( 'css/reset.css', 'css/font-awesome.min.css', 'css/bootstrap.min.css', 'css/bootstrap-table.min.css', 'css/bootstrap-table-page-jump-to.min.css', )); echo output_link_if_exists(array( 'css/base/skin.css', 'css/base/views/'.$basename.'.css', 'js/dateTimePicker/jquery-ui-timepicker-addon.css', 'js/jquery-ui-1.12.1/jquery-ui.structure.min.css', )); if ( $css != 'base' ) echo output_link_if_exists(array( 'css/'.$css.'/skin.css', 'css/'.$css.'/views/'.$basename.'.css', 'css/'.$css.'/jquery-ui-theme.css', )); ?> '; global $error_message; if ( $error_message ) { echo '
'.$error_message.'
'; } } // end function getBodyTopHTML function getNavBarHTML() { # Provide a facility to turn off the headers if you put navbar=0 into the url if ( isset($_REQUEST['navbar']) and $_REQUEST['navbar'] == '0' ) return ''; global $running; global $user; global $bandwidth_options; global $view; global $skin; ob_start(); if ( ZM_WEB_NAVBAR_TYPE == "normal" ) { echo getNormalNavBarHTML($running, $user, $bandwidth_options, $view, $skin); } else { echo getCollapsedNavBarHTML($running, $user, $bandwidth_options, $view, $skin); } return ob_get_clean(); } // // The legacy navigation bar that collapses into a pulldown menu on small screens. // function getNormalNavBarHTML($running, $user, $bandwidth_options, $view, $skin) { $status = runtimeStatus($running); ?>
'.PHP_EOL; $result .= 'trending_up'.PHP_EOL; $result .= ' '.translate('Load').': '.getLoad().PHP_EOL; $result .= ''.PHP_EOL; return $result; } // Returns the html representing the current number of connections made to the database function getDbConHTML() { $result = ''; if ( !canView('System') ) return $result; $connections = dbFetchOne('SHOW status WHERE variable_name=\'threads_connected\'', 'Value'); $max_connections = dbFetchOne('SHOW variables WHERE variable_name=\'max_connections\'', 'Value'); $percent_used = $max_connections ? 100 * $connections / $max_connections : 100; $class = ( $percent_used > 90 ) ? ' text-warning' : ''; $result .= ''.PHP_EOL; return $result; } // Returns an html dropdown showing capacity of all storage areas function getStorageHTML() { $result = ''; if ( !canView('System') ) return $result; $func = function($S) { $class = ''; if ( $S->disk_usage_percent() > 98 ) { $class = 'text-danger'; } else if ( $S->disk_usage_percent() > 90 ) { $class = 'text-warning'; } $title = human_filesize($S->disk_used_space()) . ' of ' . human_filesize($S->disk_total_space()). ( ( $S->disk_used_space() != $S->event_disk_space() ) ? ' ' .human_filesize($S->event_disk_space()) . ' used by events' : '' ); return ''.$S->Name() . ': ' . $S->disk_usage_percent().'%' . ''; }; $storage_areas = ZM\Storage::find(array('Enabled'=>true)); $num_storage_areas = count($storage_areas); $full_warning = 0; $full_error = 0; foreach ( $storage_areas as $area ) { if ( $area->disk_usage_percent() > 98 ) { $full_error++; continue; } if ( $area->disk_usage_percent() > 90 ) $full_warning++; } $class = ''; if ( $full_error ) { $class = 'text-danger'; } else if ( $full_warning ) { $class = 'text-warning'; } $result .= ''.PHP_EOL; return $result; } // Returns the html representing the current capacity of mapped memory filesystem (usually /dev/shm) function getShmHTML() { $result = ''; if ( !canView('System') ) return $result; $shm_percent = getDiskPercent(ZM_PATH_MAP); $shm_total_space = disk_total_space(ZM_PATH_MAP); $shm_used = $shm_total_space - disk_free_space(ZM_PATH_MAP); $class = ''; if ( $shm_percent > 98 ) { $class = 'text-danger'; } else if ( $shm_percent > 90 ) { $class = 'text-warning'; } $result .= ' '.PHP_EOL; return $result; } // Returns the html representing the optional web console banner text function getConsoleBannerHTML() { $result = ''; if ( defined('ZM_WEB_CONSOLE_BANNER') and ZM_WEB_CONSOLE_BANNER != '' ) { $result .= '

'.validHtmlStr(ZM_WEB_CONSOLE_BANNER).'

'; } return $result; } // Returns the html representing the current high,medium,low bandwidth setting function getBandwidthHTML($bandwidth_options, $user) { # Limit available options to what are available in user if ( $user && !empty($user['MaxBandwidth']) ) { if ( $user['MaxBandwidth'] == 'low' ) { unset($bandwidth_options['high']); unset($bandwidth_options['medium']); } else if ( $user['MaxBandwidth'] == 'medium' ) { unset($bandwidth_options['high']); } } $result = ''.PHP_EOL; return $result; } // Returns the html representing the version of ZoneMinder function getZMVersionHTML() { $result = ''; if ( !canView('System') ) return $result; $content = ''; if ( ZM_DYN_DB_VERSION && (ZM_DYN_DB_VERSION != ZM_VERSION) ) { // Must upgrade before proceeding $class = 'text-danger'; $tt_text = translate('RunLocalUpdate'); $content = 'v'.ZM_VERSION.PHP_EOL; } else if ( verNum( ZM_DYN_LAST_VERSION ) <= verNum( ZM_VERSION ) || !ZM_CHECK_FOR_UPDATES || ZM_DYN_NEXT_REMINDER > time() ) { // No update needed $class = ''; // Don't change the text color under normal conditions $tt_text = translate('UpdateNotNecessary'); $content = 'v'.ZM_VERSION.PHP_EOL; } else if ( canEdit('System') ) { // An update is available and the user is an administrator $class = 'text-warning'; $tt_text = translate('UpdateAvailable'); $content = 'v' .ZM_VERSION. ''.PHP_EOL; $content .= ''.PHP_EOL; } else { // An update is available and the user is NOT an administrator $class = 'text-warning'; $tt_text = translate('UpdateAvailable'); $content = 'v'.ZM_VERSION.PHP_EOL; } $result .= ''.PHP_EOL; return $result; } // Returns the html representing the ZoneMinder logo and about menu function getNavBrandHTML() { $result = ''; if ( ZM_HOME_ABOUT ) { $result .= 'ZoneMinder'.PHP_EOL; $result .= ''.PHP_EOL; } else { $result .= '' .ZM_HOME_CONTENT. ''.PHP_EOL; } return $result; } // Returns the html representing the Console menu item function getConsoleHTML() { $result = ''; if ( canView('Monitors') ) { $result .= ''.PHP_EOL; } return $result; } // Returns the html representing the Options menu item function getOptionsHTML() { $result = ''; if ( canView('System') ) { $result .= ''.PHP_EOL; } return $result; } // Returns the html representing the Log menu item function getLogHTML() { $result = ''; if ( canView('System') ) { if ( ZM\logToDatabase() > ZM\Logger::NOLOG ) { $logstate = logState(); $class = ($logstate == 'ok') ? 'text-success' : ($logstate == 'alert' ? 'text-warning' : (($logstate == 'alarm' ? 'text-danger' : ''))); $result .= ''.PHP_EOL; } } return $result; } // Returns the html representing the log icon function getLogIconHTML() { $result = ''; if ( canView('System') ) { if ( ZM\logToDatabase() > ZM\Logger::NOLOG ) { $logstate = logState(); $class = ( $logstate == 'alert' ) ? 'text-warning' : (( $logstate == 'alarm' ) ? 'text-danger' : ''); $result .= ''.PHP_EOL; } } return $result; } // Returns the html representing the X10 Devices menu item function getDevicesHTML() { $result = ''; if ( ZM_OPT_X10 && canView('Devices') ) { $result .= ''.PHP_EOL; } return $result; } // Returns the html representing the Groups menu item function getGroupsHTML($view) { $result = ''; if ( !canView('Groups') ) return $result; $class = $view == 'groups' ? ' selected' : ''; $result .= ''.PHP_EOL; return $result; } // Returns the html representing the Filter menu item function getFilterHTML($view) { $result = ''; if ( !canView('Events') ) return $result; $class = $view == 'filter' ? ' selected' : ''; $result .= ''.PHP_EOL; return $result; } // Returns the html representing the Cycle menu item function getCycleHTML($view) { $result = ''; if ( canView('Stream') ) { $class = $view == 'cycle' ? ' selected' : ''; $result .= ''.PHP_EOL; } return $result; } // Returns the html representing the Montage menu item function getMontageHTML($view) { $result = ''; if ( canView('Stream') ) { $class = $view == 'montage' ? ' selected' : ''; $result .= ''.PHP_EOL; } return $result; } // Returns the html representing the MontageReview menu item function getMontageReviewHTML($view) { $result = ''; if ( canView('Events') ) { if ( isset($_REQUEST['filter']['Query']['terms']['attr']) ) { $terms = $_REQUEST['filter']['Query']['terms']; $count = 0; foreach ($terms as $term) { if ( $term['attr'] == 'StartDateTime' ) { $count += 1; if ($term['op'] == '>=') $minTime = $term['val']; if ($term['op'] == '<=') $maxTime = $term['val']; } } if ( $count == 2 ) { $montageReviewQuery = '&minTime='.$minTime.'&maxTime='.$maxTime; } } $live = isset($montageReviewQuery) ? '&fit=1'.$montageReviewQuery.'&live=0' : ''; $class = $view == 'montagereview' ? ' selected' : ''; $result .= ''.PHP_EOL; } return $result; } // Returns the html representing the Montage menu item function getSnapshotsHTML($view) { $result = ''; if ( canView('Events') ) { $class = $view == 'snapshots' ? ' selected' : ''; $result .= ''.PHP_EOL; } return $result; } // Returns the html representing the Audit Events Report menu item function getRprtEvntAuditHTML($view) { $result = ''; if ( canView('Events') ) { $class = $view == 'report_event_audit' ? ' selected' : ''; $result .= ''.PHP_EOL; } return $result; } // Returns the html representing the header collapse toggle menu item function getHeaderFlipHTML() { $result = ''; $header = ( isset($_COOKIE['zmHeaderFlip']) and $_COOKIE['zmHeaderFlip'] == 'down') ? 'down' : 'up'; $result .= ''.PHP_EOL; return $result; } // Returns the html representing the logged in user name and avatar function getAccountCircleHTML($skin, $user=null) { $result = ''; if ( ZM_OPT_USE_AUTH and $user ) { $result .= ''.PHP_EOL; } return $result; } // Returns the html representing the runtime status button function getStatusBtnHTML($status) { $result = ''; if ( canEdit('System') ) { //$result .= '
  • '.PHP_EOL; $result .= ''.PHP_EOL; $result .= '
  • '.PHP_EOL; //$result .= ''.PHP_EOL; if ( ZM_SYSTEM_SHUTDOWN ) { $result .= ''.PHP_EOL; } } else if ( canView('System') ) { $result .= ''.PHP_EOL; } return $result; } function runtimeStatus($running=null) { if ( $running == null ) $running = daemonCheck(); if ( $running ) { $state = dbFetchOne('SELECT Name FROM States WHERE isActive=1', 'Name'); if ( $state == 'default' ) $state = ''; } return $running ? ($state ? $state : translate('Running')) : translate('Stopped'); } function getStatsTableHTML($eid, $fid, $row='') { if ( !canView('Events') ) return; $result = ''; $sql = 'SELECT S.*,E.*,Z.Name AS ZoneName,Z.Units,Z.Area,M.Name AS MonitorName FROM Stats AS S LEFT JOIN Events AS E ON S.EventId = E.Id LEFT JOIN Zones AS Z ON S.ZoneId = Z.Id LEFT JOIN Monitors AS M ON E.MonitorId = M.Id WHERE S.EventId = ? AND S.FrameId = ? ORDER BY S.ZoneId'; $stats = dbFetchAll( $sql, NULL, array( $eid, $fid ) ); $result .= ''.PHP_EOL; $result .= ''.PHP_EOL; $result .= ''.PHP_EOL; $result .= ''.PHP_EOL; $result .= ''.PHP_EOL; $result .= ''.PHP_EOL; $result .= ''.PHP_EOL; $result .= ''.PHP_EOL; $result .= ''.PHP_EOL; $result .= ''.PHP_EOL; $result .= ''.PHP_EOL; $result .= ''.PHP_EOL; $result .= ''.PHP_EOL; $result .= ''.PHP_EOL; $result .= ''.PHP_EOL; if ( count($stats) ) { foreach ( $stats as $stat ) { $result .= ''.PHP_EOL; $result .= ''.PHP_EOL; $result .= ''.PHP_EOL; $result .= ''.PHP_EOL; $result .= ''.PHP_EOL; $result .= ''.PHP_EOL; $result .= ''.PHP_EOL; if ( $stat['Blobs'] > 1 ) { $result .= ''.PHP_EOL; } else { $result .= ''.PHP_EOL; } $result .= ''.PHP_EOL; $result .= ''.PHP_EOL; } } else { $result .= ''.PHP_EOL; $result .= ''.PHP_EOL; $result .= ''.PHP_EOL; } $result .= ''.PHP_EOL; $result .= '
    ' .translate('Zone'). '' .translate('PixelDiff'). '' .translate('AlarmPx'). '' .translate('FilterPx'). '' .translate('BlobPx'). '' .translate('Blobs'). '' .translate('BlobSizes'). '' .translate('AlarmLimits'). '' .translate('Score'). '
    ' .validHtmlStr($stat['ZoneName']). '' .validHtmlStr($stat['PixelDiff']). '' .sprintf( "%d (%d%%)", $stat['AlarmPixels'], (100*$stat['AlarmPixels']/$stat['Area']) ). '' .sprintf( "%d (%d%%)", $stat['FilterPixels'], (100*$stat['FilterPixels']/$stat['Area']) ).'' .sprintf( "%d (%d%%)", $stat['BlobPixels'], (100*$stat['BlobPixels']/$stat['Area']) ). '' .validHtmlStr($stat['Blobs']). '' .sprintf( "%d-%d (%d%%-%d%%)", $stat['MinBlobSize'], $stat['MaxBlobSize'], (100*$stat['MinBlobSize']/$stat['Area']), (100*$stat['MaxBlobSize']/$stat['Area']) ). '' .sprintf( "%d (%d%%)", $stat['MinBlobSize'], 100*$stat['MinBlobSize']/$stat['Area'] ). '' .validHtmlStr($stat['MinX'].",".$stat['MinY']."-".$stat['MaxX'].",".$stat['MaxY']). '' .$stat['Score']. '
    ' .translate('NoStatisticsRecorded'). '
    '.PHP_EOL; return $result; } // Use this function to manually insert the csrf key into the form when using a modal generated via ajax call function getCSRFinputHTML() { if ( isset($GLOBALS['csrf']['key']) ) { $result = ''.PHP_EOL; } else { $result = ''; } return $result; } function xhtmlFooter() { global $css; global $cspNonce; global $view; global $skin; global $basename; $skinJsPhpFile = getSkinFile('js/skin.js.php'); $viewJsFile = getSkinFile('views/js/'.$basename.'.js'); $viewJsPhpFile = getSkinFile('views/js/'.$basename.'.js.php'); ?>