'; } else if ( file_exists("skins/$skin/css/$css/graphics/favicon.ico") ) { echo " "; } else { echo ' '; } echo output_link_if_exists(array('fonts/material-icons.woff2'), false, $param = ['global', 'preload', ' as="font" type="font/woff2" crossorigin']); //echo output_link_if_exists(array('fonts/material-icons.woff'), false, $param = ['global', 'preload', ' as="font" type="font/woff" crossorigin']); echo output_link_if_exists(array('css/base/material-icons.css'), false); echo output_link_if_exists(array('fonts/fontawesome-webfont.woff2?v=4.7.0'), false, $param = ['global', 'preload font', ' as="font" type="font/woff2" crossorigin']); echo output_script_if_exists(array( 'js/fontfaceobserver.standalone.js', )); ?> '; } // end function xhtmlHeaders( $file, $title ) // Outputs an opening body tag, and any additional content that should go at the very top, like warnings and error messages. function getBodyTopHTML() { global $view; //Needed for more flexible global governance $classHTML = ' class="'.$view.'-page'.((defined('ZM_WEB_NAVBAR_STICKY') and ZM_WEB_NAVBAR_STICKY) ? ' sticky"' : '"'); echo ' '; global $error_message; if ( $error_message ) { echo '
'.$error_message.'
'; } global $navbar_type; if ($navbar_type == 'left') { getSidebarTopHTML(); } } // end function getBodyTopHTML function buildMenuItem($viewItemName, $id, $itemName, $href, $icon, $classNameForTag_A = '', $subMenu = '') { global $view; /* Highlighting the active menu section */ if ($viewItemName == 'watch') { $activeClass = ($view == $viewItemName && (isset($_REQUEST['cycle']) && $_REQUEST['cycle'] == "true")) ? ' active' : ''; } else { $activeClass = $view == $viewItemName ? ' active' : ''; } $itemName = translate($itemName); $result = ' '.PHP_EOL; return $result; } function buildSidebarMenu() { global $view; global $user; if ( $user and $user->Username() ) { $menuForAuthUser = ' ' . getConsoleHTML($forLeftBar = true) . getMontageHTML($view, $forLeftBar = true) . getCycleHTML($view, $forLeftBar = true) . getMontageReviewHTML($view, $forLeftBar = true) . getEventsHTML($view, $forLeftBar = true) . getOptionsHTML($forLeftBar = true) . getLogHTML($forLeftBar = true) . getDevicesHTML($forLeftBar = true) . getGroupsHTML($view, $forLeftBar = true) . getFilterHTML($view, $forLeftBar = true) . getSnapshotsHTML($view, $forLeftBar = true) . getReportsHTML($view, $forLeftBar = true) . getRprtEvntAuditHTML($view, $forLeftBar = true) . getMapHTML($view, $forLeftBar = true) . getAdditionalLinksHTML($view, $forLeftBar = true) ; } else { // USER IS NOT AUTHORIZED! $menuForAuthUser = ''; } $menu = ' '; return $menu; } function getSidebarTopHTML() { global $skin; global $user; global $running; $blockExtruder = '
'; $block = '
'; echo $block; } // end function getSidebarTopHTML function getSidebarBottomHTML() { global $skin; $block = '
'; echo $block; } // end function getSidebarBottomHTML 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; global $navbar_type; ob_start(); if ( $navbar_type == 'normal' || $navbar_type == 'left') { echo getNormalNavBarHTML($running, $user, $bandwidth_options, $view, $skin); } else { echo getCollapsedNavBarHTML($running, $user, $bandwidth_options, $view, $skin); } return ob_get_clean(); } function output_link($files) { foreach ( $files as $file ) { $html[] = ''; } $html[] = ''; // So we ge a trailing \n return implode(PHP_EOL, $html); } function output_link_if_exists($files, $cache_bust=true, $param=false) { global $skin; $html = array(); if ($param) { $global_file = $param[0]; // The file is global or from a skin $rel = '"'.$param[1].'"'; $suffix = $param[2]; } else { $global_file = false; $rel = '"stylesheet"'; $suffix = ' type="text/css"'; } foreach ( $files as $file ) { // The file name can be for example "fontawesome-webfont.woff2?v=4.7.0". We need to select what is before the "?" $file_ = ($global_file && file_exists(explode('?', $file)[0])) ? $file : getSkinFile($file); if ($file_) { if ( $cache_bust ) { $html[] = ''; } else { $html[] = ''; } } } $html[] = ''; // So we ge a trailing \n return implode(PHP_EOL, $html); } function output_script($files, $cache_bust=true, $must_exist=true) { global $skin; $html = array(); if (!is_array($files)) $files = [$files]; foreach ( $files as $file ) { $found = false; if ( file_exists('skins/'.$skin.'/'.$file) ) { $found = true; if ( $cache_bust ) { $html[] = ''; } else { $html[] = ''; } } else if ( file_exists($file) ) { $found = true; if ( $cache_bust ) { $html[] = ''; } else { $html[] = ''; } } if (!$found and $must_exist) { ZM\Error("Script $file not found"); } } $html[] = ''; // So we ge a trailing \n return implode(PHP_EOL, $html); } function output_script_if_exists($files, $cache_bust=true) { return output_script($files, $cache_bust, false); } 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); } // // The legacy navigation bar that collapses into a pulldown menu on small screens. // function getNormalNavBarHTML($running, $user, $bandwidth_options, $view, $skin) { $status = runtimeStatus($running); ?> menu '; } $block .= '
'; return $block; } // // A new, slimmer navigation bar, permanently collapsed into a dropdown // function getCollapsedNavBarHTML($running, $user, $bandwidth_options, $view, $skin) { $status = runtimeStatus($running); ?> ReadStats(); $result .= ''.PHP_EOL; } return $result; } // Returns the html representing the current unix style system load function getSysLoadHTML() { $result = ''; if ( !canView('System') ) return $result; global $thisServer; if ($thisServer) { $thisServer->ReadStats(); $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() > 95 ) { $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 ''.validHtmlStr($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() > 95 ) $full_warning++; } $class = ''; if ( $full_error ) { $class = 'text-danger'; } else if ( $full_warning ) { $class = 'text-warning'; } if (count($storage_areas) <= 2) { $result .= ''.PHP_EOL; } else { $result .= ''.PHP_EOL; } return $result; } function getRamHTML() { $result = ''; if ( !canView('System') ) return $result; if (file_exists('/proc')) { $contents = file_get_contents('/proc/meminfo'); preg_match_all('/(\w+):\s+(\d+)\s/', $contents, $matches); $meminfo = array_combine($matches[1], array_map(function($v){return 1024*$v;}, $matches[2])); if (!isset($meminfo['MemTotal'])) { ZM\Debug(print_r($meminfo, true)); return ''; } $mem_used = $meminfo['MemTotal'] - $meminfo['MemFree'] - $meminfo['Buffers'] - $meminfo['Cached']; $mem_used_percent = $meminfo['MemTotal'] ? (int)(100*$mem_used/$meminfo['MemTotal']) : 0; $used_class = ''; if ($mem_used_percent > 95) { $used_class = 'text-danger'; } else if ($mem_used_percent > 90) { $used_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 .= ''; } 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 = ''; if (count($bandwidth_options) > 1) { $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($forLeftBar = false) { global $user; $result = ''; if (count($user->viewableMonitorIds()) or !ZM\Monitor::find_one()) { if ($forLeftBar) { $result .= buildMenuItem( $viewItemName = 'console', $id = 'getConsoleHTML', $itemName = 'Console', $href = '?view=console', $icon = 'dashboard', $classNameForTag_A = '', $subMenu = '' ); } else { $result .= ''.PHP_EOL; } } return $result; } // Returns the html representing the Options menu item function getOptionsHTML($forLeftBar = false) { global $zmMenu; $result = ''; // Sorting order of the "Options" submenu items. If a submenu item is in the DB but is not here, it will be automatically added to the end of the list. $zmMenu::buildSubMenuOptions($categoryDisplayOrder = [ 'display', 'system', 'auth', 'config', 'dnsmasq', 'API', 'servers', 'storage', 'web', 'images', 'logging', 'network', 'mail', 'upload', 'x10', 'highband', 'medband', 'lowband', 'users', 'roles', 'groups', 'control', 'privacy', 'MQTT', 'telemetry', 'version' ]); if ( canView('System') ) { if ($forLeftBar) { global $view; $view_ = 'options'; //$tab = isset($_REQUEST['tab']) ? validHtmlStr($_REQUEST['tab']) : 'system'; $tab = isset($_REQUEST['tab']) ? validHtmlStr($_REQUEST['tab']) : ''; $subMenuOptions = ' '; $result .= ' '.PHP_EOL; } else { $result .= ''.PHP_EOL; } } return $result; } // Returns the html representing the Log menu item function getLogHTML($forLeftBar = false) { $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' : ''))); if ($forLeftBar) { $result .= buildMenuItem( $viewItemName = 'log', $id = 'getLogHTML', $itemName = 'Log', $href = '?view=log', $icon = 'notification_important', $classNameForTag_A = $class, $subMenu = '' ); } else { $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 == 'ok') ? 'text-success' : ($logstate == 'alert' ? 'text-warning' : (($logstate == 'alarm' ? 'text-danger' : ''))); $result .= ''.PHP_EOL; } } return $result; } // Returns the html representing the X10 Devices menu item function getDevicesHTML($forLeftBar = false) { $result = ''; if ( ZM_OPT_X10 && canView('Devices') ) { if ($forLeftBar) { $result .= buildMenuItem( $viewItemName = 'devices', $id = 'getDevicesHTML', $itemName = 'Devices', $href = '?view=devices', $icon = 'devices_other', $classNameForTag_A = '', $subMenu = '' ); } else { $result .= ''.PHP_EOL; } } return $result; } // Returns the html representing the Groups menu item function getGroupsHTML($view, $forLeftBar = false) { $result = ''; if ( !canView('Groups') ) return $result; $class = $view == 'groups' ? ' selected' : ''; if ($forLeftBar) { $result .= buildMenuItem( $viewItemName = 'groups', $id = 'getGroupsHTML', $itemName = 'Groups', $href = '?view=groups', $icon = 'group', $classNameForTag_A = '', $subMenu = '' ); } else { $result .= ''.PHP_EOL; } return $result; } // Returns the html representing the Filter menu item function getFilterHTML($view, $forLeftBar = false) { $result = ''; if ( !canView('Events') ) return $result; $class = $view == 'filter' ? ' selected' : ''; if ($forLeftBar) { $result .= buildMenuItem( $viewItemName = 'filter', $id = 'getFilterHTML', $itemName = 'Filters', $href = '?view=filter', $icon = 'filter_alt', $classNameForTag_A = '', $subMenu = '' ); } else { $result .= ''.PHP_EOL; } return $result; } // Returns the html representing the Cycle menu item function getCycleHTML($view, $forLeftBar = false) { $result = ''; if ( canView('Stream') ) { $class = $view == 'cycle' ? ' selected' : ''; if ($forLeftBar) { $result .= buildMenuItem( $viewItemName = 'watch', $id = 'getCycleHTML', $itemName = 'Cycle', $href = '?view=watch&cycle=true', //$icon = 'cyclone', $icon = 'repeat', $classNameForTag_A = '', $subMenu = '' ); } else { $result .= ''.PHP_EOL; } } return $result; } // Returns the html representing the Montage menu item function getMontageHTML($view, $forLeftBar = false) { global $user; $result = ''; if (canView('Stream') and count($user->viewableMonitorIds())) { $class = $view == 'montage' ? ' selected' : ''; if ($forLeftBar) { $result .= buildMenuItem( $viewItemName = 'montage', $id = 'getMontageHTML', $itemName = 'Montage', $href = '?view=montage', $icon = 'live_tv', $classNameForTag_A = '', $subMenu = '' ); } else { $result .= ''.PHP_EOL; } } return $result; } // Returns the html representing the MontageReview menu item function getMontageReviewHTML($view, $forLeftBar = false) { $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' : ''; if ($forLeftBar) { $result .= buildMenuItem( $viewItemName = 'montagereview', $id = 'getMontageReviewHTML', $itemName = 'MontageReview', $href = '?view=montagereview' .$live, $icon = 'movie', $classNameForTag_A = '', $subMenu = '' ); } else { $result .= ''.PHP_EOL; } } return $result; } // Returns the html representing the Montage menu item function getSnapshotsHTML($view, $forLeftBar = false) { $result = ''; if (defined('ZM_FEATURES_SNAPSHOTS') and ZM_FEATURES_SNAPSHOTS and canView('Snapshots')) { $class = $view == 'snapshots' ? ' selected' : ''; if ($forLeftBar) { $result .= buildMenuItem( $viewItemName = 'snapshots', $id = 'getSnapshotsHTML', $itemName = 'Snapshots', $href = '?view=snapshots', $icon = 'preview', $classNameForTag_A = '', $subMenu = '' ); } else { $result .= ''.PHP_EOL; } } return $result; } // Returns the html representing the Events menu item function getEventsHTML($view, $forLeftBar = false) { global $user; $result = ''; if (canView('Events')) { $class = $view == 'events' ? ' selected' : ''; if ($forLeftBar) { $result .= buildMenuItem( $viewItemName = 'events', $id = 'getEventsHTML', $itemName = 'Events', $href = '?view=events', $icon = 'event', $classNameForTag_A = '', $subMenu = '' ); } else { $result .= ''.PHP_EOL; } } return $result; } function getReportsHTML($view, $forLeftBar = false) { $result = ''; if (canView('Events')) { $class = ($view == 'reports' or $view == 'report') ? ' selected' : ''; if ($forLeftBar) { $result .= buildMenuItem( $viewItemName = 'reports', $id = 'getReportsHTML', $itemName = 'Reports', $href = '?view=reports', $icon = 'report', $classNameForTag_A = '', $subMenu = '' ); } else { $result .= ''.PHP_EOL; } } return $result; } // Returns the html representing the Audit Events Report menu item function getRprtEvntAuditHTML($view, $forLeftBar = false) { $result = ''; if ( canView('Events') ) { $class = $view == 'report_event_audit' ? ' selected' : ''; if ($forLeftBar) { $result .= buildMenuItem( $viewItemName = 'report_event_audit', $id = 'getRprtEvntAuditHTML', $itemName = 'ReportEventAudit', $href = '?view=report_event_audit', $icon = 'shield', $classNameForTag_A = '', $subMenu = '' ); } else { $result .= ''.PHP_EOL; } } return $result; } // Returns the html representing the Audit Events Report menu item function getMapHTML($view, $forLeftBar = false) { $result = ''; if (defined('ZM_OPT_USE_GEOLOCATION') and ZM_OPT_USE_GEOLOCATION) { $class = $view == 'map' ? ' selected' : ''; if ($forLeftBar) { $result .= buildMenuItem( $viewItemName = 'map', $id = 'getMapHTML', $itemName = 'Map', $href = '?view=map', $icon = 'language', $classNameForTag_A = '', $subMenu = '' ); } else { $result .= ''.PHP_EOL; } } return $result; } // Returns the html representing the content of the ZM_WEB_NAVBAR_LINKS content function getAdditionalLinksHTML($view, $forLeftBar = false) { $result = ''; if (defined('ZM_WEB_NAVBAR_LINKS')) { if (ZM_WEB_NAVBAR_LINKS) { foreach (explode(',', ZM_WEB_NAVBAR_LINKS) as $link) { if ($forLeftBar) { $doc = new DomDocument(); fixAmps($link); $doc->loadHTML('' . $link); $url = $doc->getElementsByTagName('a')[0]; $value_ = translate('Error in link string: "') . htmlspecialchars($link) . '"'; $href_ = ''; $icon_ = ''; $class_ = ''; $queryView = ''; if ($url) { $value_ = $url->nodeValue; $href_ = $url->getAttribute( 'href' ); $icon_ = $url->getAttribute('data-icon'); $class_ = $url->getAttribute('class'); $parts = parse_url($href_); parse_str($parts['query'], $query); $queryView = $query['view']; } $result .= buildMenuItem( $viewItemName = $queryView, $id = '', $itemName = $value_, $href = $href_, $icon = $icon_, $classNameForTag_A = $class_, $subMenu = '' ); } else { $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, $forLeftBar = false) { $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; if (ZM_SYSTEM_SHUTDOWN) { $result .= '
  • '.PHP_EOL; $result .= ''.PHP_EOL; $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; $result .= ''.PHP_EOL; } } else { $result .= ''.PHP_EOL; //IMPORTANT! There is a problem with Bootstrap here. The class is being moved from '.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']. '
    and "colspan" is not being applied $result .= '' .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 fixAmps(&$html) { //https://stackoverflow.com/questions/1685277/warning-domdocumentloadhtml-htmlparseentityref-expecting-in-entity $positionAmp = strpos($html, '&'); $positionSemiColumn = strpos($html, ';', $positionAmp+1); $string = substr($html, $positionAmp, $positionSemiColumn-$positionAmp+1); if ($positionAmp !== false) { // If an '&' can be found. if ($positionSemiColumn === false) { // If no ';' can be found. $html = substr_replace($html, '&', $positionAmp, 1); // Replace straight away. } else if (preg_match('/&(#[0-9]+|[A-Z|a-z|0-9]+);/', $string) === 0) { // If a standard escape cannot be found. $html = substr_replace($html, '&', $positionAmp, 1); // This mean we need to escape the '&' sign. fixAmps($html, $positionAmp+5); // Recursive call from the new position. } else { fixAmps($html, $positionAmp+1); // Recursive call from the new position. } } } function xhtmlFooter() { global $css; global $cspNonce; global $view; global $skin; global $basename; global $navbar_type; if ($navbar_type == 'left') { getSidebarBottomHTML(); } ?> = 8.4 function mb_ucfirst($str, $encoding='UTF-8') { if (extension_loaded('mbstring')) { $result = mb_strtoupper(mb_substr($str, 0, 1, $encoding)) . mb_substr($str, 1, null, $encoding); } else { $result = (ucfirst($str)); } return $result; } } // $typeMenu we are not using it yet. From now on we will specify either 'leftMenu' or 'topMenu' // $menuItems we are not using it yet. These are main menu items with the ability to be customized by the user. $zmMenu = new ZM_Menu($typeMenu = '', $menuItems = [ ]); ?>