public static function render_page_process($PATH)
 {
     $suite_dir = phoromatic_server::phoromatic_account_suite_path($_SESSION['AccountID']);
     $main = '<h1>Local Suites</h1><p>These are test suites created by you or another account within your group. Suites are an easy collection of test profiles. New suits can be trivially made via the <a href="/?build_suite">build suite</a> page.</p>';
     $suite_count = 0;
     foreach (pts_file_io::glob($suite_dir . '*/suite-definition.xml') as $xml_path) {
         $suite_count++;
         $id = basename(dirname($xml_path));
         $test_suite = new pts_test_suite($xml_path);
         $main .= '<a name="' . $id . '"></a><h1>' . $test_suite->get_title() . ' [' . $id . ']</h1>';
         $main .= '<p><strong>' . $test_suite->get_maintainer() . '</strong></p>';
         $main .= '<p><em>' . $test_suite->get_description() . '</em></p>';
         $main .= '<div style="max-height: 200px; overflow-y: scroll;">';
         foreach ($test_suite->get_contained_test_result_objects() as $tro) {
             $main .= '<h3>' . $tro->test_profile->get_title() . ' [' . $tro->test_profile->get_identifier() . ']</h3>';
             $main .= '<p>' . $tro->get_arguments_description() . '</p>';
         }
         $main .= '</div>';
         $main .= '<hr />';
     }
     if ($suite_count == 0) {
         $main .= '<h1>No Test Suites Found</h1>';
     }
     echo phoromatic_webui_header_logged_in();
     echo '<div id="pts_phoromatic_main_area">' . $main . '</div>';
     echo phoromatic_webui_footer();
 }
 public static function render_page_process($PATH)
 {
     echo phoromatic_webui_header_logged_in();
     $main = '<h1>Systems</h1>';
     $main .= '<p>Various system interaction vitals for the Phoronix Test Suite systems associated with this account.</p>';
     $stmt = phoromatic_server::$db->prepare('SELECT Title, SystemID, Hardware, Software, ClientVersion, LastIP, NetworkMAC, LastCommunication, CurrentTask, CoreVersion, NetworkWakeOnLAN, BlockPowerOffs FROM phoromatic_systems WHERE AccountID = :account_id AND State >= 0 ORDER BY LastCommunication DESC');
     $stmt->bindValue(':account_id', $_SESSION['AccountID']);
     $result = $stmt->execute();
     while ($row = $result->fetchArray()) {
         $stmt = phoromatic_server::$db->prepare('SELECT UploadTime FROM phoromatic_results WHERE AccountID = :account_id AND SystemID = :system_id ORDER BY UploadTime DESC LIMIT 1');
         $stmt->bindValue(':account_id', $_SESSION['AccountID']);
         $stmt->bindValue(':system_id', $row['SystemID']);
         $latest_result = $stmt->execute();
         $latest_result = $latest_result->fetchArray();
         $latest_result = $latest_result['UploadTime'];
         $components[$row['SystemID']]['Last Communication'] = date('H:i d F', strtotime($row['LastCommunication']));
         $components[$row['SystemID']]['Current Task'] = $row['CurrentTask'];
         $components[$row['SystemID']]['Last IP'] = $row['LastIP'];
         $components[$row['SystemID']]['Phoronix Test Suite'] = $row['ClientVersion'] . ' [' . $row['CoreVersion'] . ']';
         $components[$row['SystemID']]['MAC'] = $row['NetworkMAC'];
         $components[$row['SystemID']]['Wake-On-LAN'] = (empty($row['NetworkWakeOnLAN']) ? 'N/A' : $row['NetworkWakeOnLAN']) . ' - ' . ($row['BlockPowerOffs'] == 1 ? 'Blocked' : 'Permitted');
         $components[$row['SystemID']]['Latest Result Upload'] = $latest_result != null ? date('d F', strtotime($latest_result)) : 'N/A';
         $system_ids[$row['SystemID']] = $row['Title'];
     }
     $main .= '<div style="margin: 10px auto; overflow: auto;"><table width="100%">';
     $component_types = array('Last Communication', 'Current Task', 'Phoronix Test Suite', 'Last IP', 'MAC', 'Wake-On-LAN', 'Latest Result Upload');
     $main .= '<tr><th>&nbsp;</th>';
     foreach ($component_types as $type) {
         $main .= '<th>' . $type . '</th>';
     }
     foreach ($components as $system_id => $component_array) {
         $main .= '<tr>';
         $main .= '<th><a href="/?systems/' . $system_id . '">' . $system_ids[$system_id] . '</a></th>';
         foreach ($component_types as $type) {
             $c = isset($component_array[$type]) ? $component_array[$type] : 'N/A';
             if (($x = stripos($c, ' @ ')) !== false) {
                 $c = substr($c, 0, $x);
             }
             if (($x = stripos($c, ' (')) !== false) {
                 $c = substr($c, 0, $x);
             }
             $main .= '<td>' . $c . '</td>';
         }
         $main .= '</tr>';
     }
     $main .= '</table></div>';
     $right = null;
     echo phoromatic_webui_main($main, phoromatic_webui_right_panel_logged_in($right));
     echo phoromatic_webui_footer();
 }
    public static function render_page_process($PATH)
    {
        if (isset($_POST['register_password']) && isset($_POST['register_password_confirm']) && isset($_POST['old_password'])) {
            $matching_user = phoromatic_server::$db->querySingle('SELECT Password FROM phoromatic_users WHERE UserName = \'' . $_SESSION['UserName'] . '\' AND AccountID = \'' . $_SESSION['AccountID'] . '\'', true);
            if (!empty($matching_user)) {
                $hashed_password = $matching_user['Password'];
                $account_salt = phoromatic_server::$db->querySingle('SELECT Salt FROM phoromatic_accounts WHERE AccountID = \'' . $_SESSION['AccountID'] . '\'');
                if ($account_salt != null && hash('sha256', $account_salt . $_POST['old_password']) == $hashed_password) {
                    if (strlen($_POST['register_password']) < 6) {
                        phoromatic_error_page('Oops!', 'Please go back and ensure the supplied password is at least six characters long.');
                        return false;
                    }
                    if ($_POST['register_password'] != $_POST['register_password_confirm']) {
                        phoromatic_error_page('Oops!', 'Please go back and ensure the supplied password matches the password confirmation.');
                        return false;
                    }
                    $new_salted_password = hash('sha256', $account_salt . $_POST['register_password']);
                    phoromatic_server::$db->exec('UPDATE phoromatic_users SET Password = \'' . $new_salted_password . '\' WHERE UserName = "' . $_SESSION['UserName'] . '"');
                    echo '<h1>Password Updated!</h1>';
                } else {
                    phoromatic_error_page('Oops!', 'The original password does not match the records for this account.');
                    return false;
                }
            } else {
                phoromatic_error_page('Oops!', 'Problem fetching user information. Try again.');
                return false;
            }
        }
        echo phoromatic_webui_header_logged_in();
        $main = '<h1>Change Password</h1>
		<form name="reset_password" id="reset_password" action="?password" method="post" onsubmit="return phoromatic_password_reset(this);">
		<div style="clear: both;">
			<div style="float: left; font-weight: bold; padding-right: 10px;">
			<p style="height: 50px;">Password</p>
			<p style="height: 50px;">New Password</p>
			<p style="height: 50px;">Confirm New Password</p>
			</div>

			<div style="float: left;">
			<p style="height: 50px;"><input type="password" name="old_password" /></p>
			<p style="height: 50px;"><input type="password" name="register_password" /> <sup>1</sup></p>
			<p style="height: 50px;"><input type="password" name="register_password_confirm" /></p>
			<p style="height: 50px;"><input type="submit" value="Change Password" /></p>
			</div>
		</div>
		<p style="clear: both;"><sup>1</sup> Passwords shall be at least six characters long.</p>';
        echo phoromatic_webui_main($main, phoromatic_webui_right_panel_logged_in());
        echo phoromatic_webui_footer();
    }
 public static function render_page_process($PATH)
 {
     echo phoromatic_webui_header_logged_in();
     $main = '<h1>System Components</h1>';
     $main .= '<p>Detected hardware/software components via Phoronix Test Suite\'s Phodevi implementation on the Phoromatic client systems.</p>';
     $stmt = phoromatic_server::$db->prepare('SELECT Title, SystemID, Hardware, Software, ClientVersion, NetworkWakeOnLAN, NetworkMAC FROM phoromatic_systems WHERE AccountID = :account_id AND State >= 0 ORDER BY Title ASC');
     $stmt->bindValue(':account_id', $_SESSION['AccountID']);
     $result = $stmt->execute();
     while ($row = $result->fetchArray()) {
         $components[$row['SystemID']] = array_merge(pts_result_file_analyzer::system_component_string_to_array($row['Software'], array('OS', 'Kernel', 'OpenGL', 'File-System')), pts_result_file_analyzer::system_component_string_to_array($row['Hardware'], array('Processor', 'Motherboard', 'Memory', 'Disk', 'Graphics')));
         $components[$row['SystemID']]['Phoronix Test Suite'] = $row['ClientVersion'];
         $components[$row['SystemID']]['WoL Info'] = $row['NetworkWakeOnLAN'];
         $components[$row['SystemID']]['MAC'] = $row['NetworkMAC'];
         $system_ids[$row['SystemID']] = $row['Title'];
     }
     $main .= '<div style="margin: 10px auto; overflow: auto;"><table>';
     $component_types = array('MAC', 'Processor', 'Motherboard', 'Memory', 'Disk', 'Graphics', 'OS', 'Kernel', 'OpenGL', 'File-System', 'Phoronix Test Suite', 'WoL Info');
     $main .= '<tr><th>&nbsp;</th>';
     foreach ($component_types as $type) {
         $main .= '<th>' . $type . '</th>';
     }
     foreach ($components as $system_id => $component_array) {
         $main .= '<tr>';
         $main .= '<th><a href="/?systems/' . $system_id . '">' . $system_ids[$system_id] . '</a></th>';
         foreach ($component_types as $type) {
             $c = isset($component_array[$type]) ? $component_array[$type] : 'N/A';
             if (($x = stripos($c, ' @ ')) !== false) {
                 $c = substr($c, 0, $x);
             }
             if (($x = stripos($c, ' (')) !== false) {
                 $c = substr($c, 0, $x);
             }
             $main .= '<td>' . $c . '</td>';
         }
         $main .= '</tr>';
     }
     $main .= '</table></div>';
     $right = null;
     echo phoromatic_webui_main($main, phoromatic_webui_right_panel_logged_in($right));
     echo phoromatic_webui_footer();
 }
    public static function render_page_process($PATH)
    {
        echo phoromatic_webui_header_logged_in();
        $main = '<h1>Cache Settings</h1>
				<h2>Test Profile Download Cache</h2>
				<p>Below are a list of files for verification/debugging purposes that are currently cached by the Phoromatic Server and available for Phoronix Test Suite client systems to download. These are files that are needed by various test profiles in the Phoronix Test Suite. To add more data to this Phoromatic Server cache, from the server run <strong>phoronix-test-suite make-download-cache</strong> while passing the names of any tests/suites you wish to have download and generate a cache for so they can be made available to the Phoronix Test Suite clients on your network.</p>';
        $dc = pts_strings::add_trailing_slash(pts_strings::parse_for_home_directory(pts_config::read_user_config('PhoronixTestSuite/Options/Installation/CacheDirectory', PTS_DOWNLOAD_CACHE_PATH)));
        $dc_exists = is_file($dc . 'pts-download-cache.json');
        if ($dc_exists) {
            $cache_json = file_get_contents($dc . 'pts-download-cache.json');
            $cache_json = json_decode($cache_json, true);
        }
        if (is_file($dc . 'pts-download-cache.json')) {
            if ($cache_json && isset($cache_json['phoronix-test-suite']['download-cache'])) {
                $total_file_size = 0;
                $main .= '<table style="margin: 0 auto;"><tr><th>File</th><th>Size</th></tr>';
                foreach ($cache_json['phoronix-test-suite']['download-cache'] as $file_name => $inf) {
                    $total_file_size += $cache_json['phoronix-test-suite']['download-cache'][$file_name]['file_size'];
                    $main .= '<tr><td>' . $file_name . '</td><td>' . round(max(0.1, $cache_json['phoronix-test-suite']['download-cache'][$file_name]['file_size'] / 1000000), 1) . 'MB</td></tr>';
                }
                $main .= '</table>';
                $main .= '<p><strong>' . count($cache_json['phoronix-test-suite']['download-cache']) . ' Files / ' . round($total_file_size / 1000000) . ' MB Cache Size</strong></p>';
            }
        } else {
            $main .= '<h3>No download cache file could be found; on the Phoromatic Server you should run <strong>phoronix-test-suite make-download-cache</strong>.</h3>';
            // TODO XXX implement from the GUI
        }
        $main .= '<hr /><h2>OpenBenchmarking.org Cache Data</h2>';
        $main .= '<p>Below is information pertaining to the OpenBenchmarking.org cache present on the Phoromatic Server. To update this cache, run <strong>phoronix-test-suite make-openbenchmarking-cache</strong> from the server.</p>';
        $index_files = pts_file_io::glob(PTS_OPENBENCHMARKING_SCRATCH_PATH . '*.index');
        $main .= '<table style="margin: 0 auto;"><tr><th>Repository</th><th>Last Updated</th></tr>';
        foreach ($index_files as $index_file) {
            $index_data = json_decode(file_get_contents($index_file), true);
            $main .= '<tr><td>' . basename($index_file, '.index') . '</td><td>' . date('d F Y H:i', $index_data['main']['generated']) . '</td></tr>';
        }
        $main .= '</table>';
        echo phoromatic_webui_main($main, phoromatic_webui_right_panel_logged_in());
        echo phoromatic_webui_footer();
    }
 public static function render_page_process($PATH)
 {
     $main = null;
     if (isset($PATH[0])) {
         if ($PATH[0] == 'context' && isset($PATH[1])) {
             $attribs = explode(',', $PATH[1]);
             $stmt = phoromatic_server::$db->prepare('SELECT UserContextStep, UserContextLog FROM phoromatic_system_context_logs WHERE AccountID = :account_id AND ScheduleID = :schedule_id AND SystemID = :system_id AND TriggerID = :trigger_id ORDER BY UploadTime ASC');
             $stmt->bindValue(':account_id', $_SESSION['AccountID']);
             $stmt->bindValue(':system_id', $attribs[0]);
             $stmt->bindValue(':schedule_id', $attribs[1]);
             $stmt->bindValue(':trigger_id', base64_decode($attribs[2]));
             $result = $stmt->execute();
             while ($row = $result->fetchArray()) {
                 $main .= '<h2>' . $row['UserContextStep'] . '</h2><p>' . str_replace(PHP_EOL, '<br />', $row['UserContextLog']) . '</p><hr />';
             }
         } else {
             if ($PATH[0] == 'system' && isset($PATH[1])) {
                 $zip_file = phoromatic_server::phoromatic_account_result_path($_SESSION['AccountID'], $PATH[1]) . 'system-logs.zip';
                 if (is_file($zip_file)) {
                     $zip = new ZipArchive();
                     $res = $zip->open($zip_file);
                     if ($res === true) {
                         for ($i = 0; $i < $zip->numFiles; $i++) {
                             if ($zip->getFromIndex($i) != null) {
                                 $main .= '<h2>' . basename($zip->getNameIndex($i)) . '</h2><p>' . str_replace(PHP_EOL, '<br />', $zip->getFromIndex($i)) . '</p><hr />';
                             }
                         }
                         $zip->close();
                     }
                 }
             }
         }
     }
     echo phoromatic_webui_header_logged_in();
     echo phoromatic_webui_main($main, phoromatic_webui_right_panel_logged_in(null));
     echo phoromatic_webui_footer();
 }
 public static function render_page_process($PATH)
 {
     $main = '<h1>Recent Account Activity</h1>';
     $stmt = phoromatic_server::$db->prepare('SELECT * FROM phoromatic_activity_stream WHERE AccountID = :account_id ORDER BY ActivityTime DESC');
     $stmt->bindValue(':account_id', $_SESSION['AccountID']);
     $result = $stmt->execute();
     $row = $result->fetchArray();
     $prev_date = null;
     do {
         if ($prev_date != substr($row['ActivityTime'], 0, 10)) {
             if ($prev_date != null) {
                 $main .= '</p><hr />';
             }
             $prev_date = substr($row['ActivityTime'], 0, 10);
             $new_date = strtotime($row['ActivityTime']);
             if (date('Y-m-d') == $prev_date) {
                 $main .= '<h2>Today</h2>';
             } else {
                 if ($new_date > time() - 60 * 60 * 24 * 6) {
                     $main .= '<h2>' . date('l', $new_date) . '</h2>';
                 } else {
                     $main .= '<h2>' . date('j F Y', $new_date) . '</h2>';
                 }
             }
             $main .= '<p>';
         }
         $id_link_format = $row['ActivityEventID'];
         switch ($row['ActivityEvent']) {
             case 'settings':
                 $event_link_format = '<a href="?settings">settings</a>';
                 break;
             case 'users':
                 $event_link_format = '<a href="?users">a user</a>';
                 break;
             case 'schedule':
                 $event_link_format = '<a href="?schedules">schedule</a>';
                 $stmt1 = phoromatic_server::$db->prepare('SELECT Title FROM phoromatic_schedules WHERE AccountID = :account_id AND ScheduleID = :schedule_id');
                 $stmt1->bindValue(':account_id', $_SESSION['AccountID']);
                 $stmt1->bindValue(':schedule_id', $row['ActivityEventID']);
                 $result1 = $stmt1->execute();
                 $row1 = $result1->fetchArray();
                 $id_link_format = '<a href="?schedules/' . $row['ActivityEventID'] . '">' . $row1['Title'] . '</a>';
                 break;
             case 'tests_for_schedule':
                 $event_link_format = 'a test for a schedule';
                 $stmt1 = phoromatic_server::$db->prepare('SELECT Title FROM phoromatic_schedules WHERE AccountID = :account_id AND ScheduleID = :schedule_id');
                 $stmt1->bindValue(':account_id', $_SESSION['AccountID']);
                 $stmt1->bindValue(':schedule_id', $row['ActivityEventID']);
                 $result1 = $stmt1->execute();
                 $row1 = $result1->fetchArray();
                 $id_link_format = '<a href="?schedules/' . $row['ActivityEventID'] . '">' . $row1['Title'] . '</a>';
                 break;
             case 'groups':
                 $event_link_format = '<a href="?systems#group_edit">a group</a>';
                 break;
             default:
                 $event_link_format = $row['ActivityEvent'];
                 break;
         }
         if ($row['ActivityCreatorType'] == 'USER') {
             $main .= '<em>' . date('H:i', strtotime($row['ActivityTime'])) . '</em> &nbsp; <strong>' . $row['ActivityCreator'] . '</strong> <strong> ' . $row['ActivityEventType'] . '</strong> <strong>' . $event_link_format . '</strong>';
             if ($id_link_format != null) {
                 $main .= ': ' . $id_link_format;
             }
             $main .= '<br />' . PHP_EOL;
         }
         //$main .= '<p>' .  $row['ActivityCreator'] . ' ' . $row['ActivityCreatorType'] . ' ' . $row['ActivityEvent'] . ' ' . $row['ActivityEventID'] . ' ' . $row['ActivityEventType'] . '</p>';
     } while ($row = $result->fetchArray());
     if ($prev_date != null) {
         $main .= '</p>';
     }
     echo phoromatic_webui_header_logged_in();
     echo phoromatic_webui_main($main);
     echo phoromatic_webui_footer();
 }
 public static function render_page_process($PATH)
 {
     $main = null;
     $identifier_item = isset($PATH[1]) ? $PATH[0] . '/' . $PATH[1] : false;
     if ($identifier_item && pts_test_profile::is_test_profile($identifier_item)) {
         $tp = new pts_test_profile($identifier_item);
         $tp_identifier = $tp->get_identifier(false);
         $main .= '<h1>' . $tp->get_title() . '</h1><p>' . $tp->get_description() . '</p>';
         $main .= '<p><strong>' . $tp->get_test_hardware_type() . ' - ' . phoromatic_server::test_result_count_for_test_profile($_SESSION['AccountID'], $tp_identifier) . ' Results On This Account - ' . $tp->get_test_software_type() . ' - Maintained By: ' . $tp->get_maintainer() . ' - Supported Platforms: ' . implode(', ', $tp->get_supported_platforms()) . '</strong></p>';
         $main .= '<p><a href="http://openbenchmarking.org/test/' . $tp_identifier . '">Find out more about this test profile on OpenBenchmarking.org</a>.</p>';
         $main .= '<h2>Recent Results With This Test</h2>';
         $stmt = phoromatic_server::$db->prepare('SELECT Title, PPRID FROM phoromatic_results WHERE AccountID = :account_id AND UploadID IN (SELECT DISTINCT UploadID FROM phoromatic_results_results WHERE AccountID = :account_id AND TestProfile LIKE :tp) ORDER BY UploadTime DESC LIMIT 30');
         $stmt->bindValue(':account_id', $_SESSION['AccountID']);
         $stmt->bindValue(':tp', $tp_identifier . '%');
         $result = $stmt->execute();
         $recent_result_count = 0;
         while ($result && ($row = $result->fetchArray())) {
             $recent_result_count++;
             $main .= '<h2><a href="/?result/' . $row['PPRID'] . '">' . $row['Title'] . '</a></h2>';
         }
         if ($recent_result_count == 0) {
             $main .= '<p>No results found on this Phoromatic Server for the ' . $tp->get_title() . ' test profile.</p>';
         } else {
             if ($recent_result_count > 5) {
                 $stmt = phoromatic_server::$db->prepare('SELECT UploadID, SystemID, UploadTime FROM phoromatic_results WHERE AccountID = :account_id AND UploadID IN (SELECT DISTINCT UploadID FROM phoromatic_results_results WHERE AccountID = :account_id AND TestProfile LIKE :tp) ORDER BY UploadTime DESC LIMIT 1000');
                 $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                 $stmt->bindValue(':tp', $tp_identifier . '%');
                 $result = $stmt->execute();
                 $recent_result_count = 0;
                 $result_file = new pts_result_file(null, true);
                 while ($result && ($row = $result->fetchArray())) {
                     $composite_xml = phoromatic_server::phoromatic_account_result_path($_SESSION['AccountID'], $row['UploadID']) . 'composite.xml';
                     if (!is_file($composite_xml)) {
                         continue;
                     }
                     // Add to result file
                     $system_name = strtotime($row['UploadTime']) . ': ' . phoromatic_server::system_id_to_name($row['SystemID']);
                     $sub_result_file = new pts_result_file($composite_xml, true);
                     foreach ($sub_result_file->get_result_objects() as $obj) {
                         if ($obj->test_profile->get_identifier(false) == $tp_identifier) {
                             $obj->test_result_buffer->rename(null, $system_name);
                             $result_file->add_result($obj);
                         }
                     }
                 }
                 $table = null;
                 $extra_attributes = array('multi_way_comparison_invert_default' => false);
                 $f = false;
                 foreach ($result_file->get_result_objects() as $obj) {
                     $obj->test_profile->set_display_format('SCATTER_PLOT');
                     foreach ($obj->test_result_buffer->buffer_items as $i => &$item) {
                         if (!is_numeric(substr($item->get_result_identifier(), 0, strpos($item->get_result_identifier(), ':')))) {
                             unset($obj->test_result_buffer->buffer_items[$i]);
                         }
                     }
                     $result_file = null;
                     $main .= '<p align="center">' . pts_render::render_graph_inline_embed($obj, $result_file, $extra_attributes) . '</p>';
                 }
             }
         }
     } else {
         $dc = pts_strings::add_trailing_slash(pts_strings::parse_for_home_directory(pts_config::read_user_config('PhoronixTestSuite/Options/Installation/CacheDirectory', PTS_DOWNLOAD_CACHE_PATH)));
         $dc_exists = is_file($dc . 'pts-download-cache.json');
         if ($dc_exists) {
             $cache_json = file_get_contents($dc . 'pts-download-cache.json');
             $cache_json = json_decode($cache_json, true);
         }
         $test_counts_for_account = phoromatic_server::test_result_count_for_test_profiles($_SESSION['AccountID']);
         foreach (pts_openbenchmarking::available_tests() as $test) {
             $cache_checked = false;
             if ($dc_exists) {
                 if ($cache_json && isset($cache_json['phoronix-test-suite']['cached-tests'])) {
                     $cache_checked = true;
                     if (!in_array($test, $cache_json['phoronix-test-suite']['cached-tests'])) {
                         //continue;
                     }
                 }
             }
             if (!$cache_checked && phoromatic_server::read_setting('show_local_tests_only') && pts_test_install_request::test_files_in_cache($test, true, true) == false) {
                 continue;
             }
             $tp = new pts_test_profile($test);
             if ($tp->get_title() == null) {
                 continue;
             }
             $test_count = 0;
             $tpid = $tp->get_identifier(false);
             foreach ($test_counts_for_account as $test => $count) {
                 if (strpos($test, $tpid) !== false) {
                     $test_count += $count;
                     unset($test_counts_for_account[$test]);
                 }
             }
             $main .= '<h1 style="margin-bottom: 0;"><a href="/?tests/' . $tp->get_identifier(false) . '">' . $tp->get_title() . '</a></h1>';
             $main .= '<p style="font-size: 90%;"><strong>' . $tp->get_test_hardware_type() . '</strong> <em>-</em> ' . $test_count . ' Results On This Account' . ' </p>';
         }
     }
     echo phoromatic_webui_header_logged_in();
     echo '<div id="pts_phoromatic_main_area">' . $main . '</div>';
     echo phoromatic_webui_footer();
 }
    public static function render_page_process($PATH)
    {
        if (isset($_POST['suite_title'])) {
            //	echo '<pre>';
            //	var_dump($_POST);
            //	echo '</pre>';
            if (strlen($_POST['suite_title']) < 3) {
                echo '<h2>Suite title must be at least three characters.</h2>';
            }
            //echo 'TEST SUITE: ' . $_POST['suite_title'] . '<br />';
            //echo 'TEST SUITE: ' . $_POST['suite_description'] . '<br />';
            $tests = array();
            foreach ($_POST['test_add'] as $i => $test_identifier) {
                $test_prefix = $_POST['test_prefix'][$i];
                $args = array();
                $args_name = array();
                foreach ($_POST as $i => $v) {
                    if (strpos($i, $test_prefix) !== false && substr($i, -9) != '_selected') {
                        if (strpos($v, '||') !== false) {
                            $opts = explode('||', $v);
                            $a = array();
                            $d = array();
                            foreach ($opts as $opt) {
                                $t = explode('::', $opt);
                                array_push($a, $t[1]);
                                array_push($d, $t[0]);
                            }
                            array_push($args, $a);
                            array_push($args_name, $d);
                        } else {
                            array_push($args, array($v));
                            array_push($args_name, array($_POST[$i . '_selected']));
                        }
                    }
                }
                $test_args = array();
                $test_args_description = array();
                pts_test_run_options::compute_all_combinations($test_args, null, $args, 0);
                pts_test_run_options::compute_all_combinations($test_args_description, null, $args_name, 0, ' - ');
                foreach (array_keys($test_args) as $i) {
                    array_push($tests, array('test' => $test_identifier, 'description' => $test_args_description[$i], 'args' => $test_args[$i]));
                }
            }
            if (count($tests) < 1) {
                echo '<h2>You must add at least one test to the suite.</h2>';
            }
            $suite_writer = new pts_test_suite_writer();
            $version_bump = 0;
            do {
                $suite_version = '1.' . $version_bump . '.0';
                $suite_id = $suite_writer->clean_save_name_string($_POST['suite_title']) . '-' . $suite_version;
                $suite_dir = phoromatic_server::phoromatic_account_suite_path($_SESSION['AccountID'], $suite_id);
                $version_bump++;
            } while (is_dir($suite_dir));
            pts_file_io::mkdir($suite_dir);
            $save_to = $suite_dir . '/suite-definition.xml';
            $suite_writer->add_suite_information($_POST['suite_title'], $suite_version, $_SESSION['UserName'], 'System', $_POST['suite_description']);
            foreach ($tests as $m) {
                $suite_writer->add_to_suite($m['test'], $m['args'], $m['description']);
            }
            $suite_writer->save_xml($save_to);
            echo '<h2>Saved As ' . $suite_id . '</h2>';
        }
        echo phoromatic_webui_header_logged_in();
        $main = '<h1>Local Suites</h1><p>Find already created local test suites by your account/group via the <a href="/?local_suites">local suites</a> page.</p>';
        if (!PHOROMATIC_USER_IS_VIEWER) {
            $main .= '<h1>Build Suite</h1><p>A test suite in the realm of the Phoronix Test Suite, OpenBenchmarking.org, and Phoromatic is <strong>a collection of test profiles with predefined settings</strong>. Establishing a test suite makes it easy to run repetitive testing on the same set of test profiles by simply referencing the test suite name.</p>';
            $main .= '<form action="' . $_SERVER['REQUEST_URI'] . '" name="build_suite" id="build_suite" method="post" onsubmit="return validate_suite();">
			<h3>Title:</h3>
			<p><input type="text" name="suite_title" /></p>
			<h3>Description:</h3>
			<p><textarea name="suite_description" id="suite_description" cols="60" rows="2"></textarea></p>
			<h3>Tests In Schedule:</h3>
			<p><div id="test_details"></div></p>
			<h3>Add Another Test</h3>';
            $main .= '<select name="add_to_suite_select_test" id="add_to_suite_select_test" onchange="phoromatic_build_suite_test_details();">';
            $dc = pts_strings::add_trailing_slash(pts_client::parse_home_directory(pts_config::read_user_config('PhoronixTestSuite/Options/Installation/CacheDirectory', PTS_DOWNLOAD_CACHE_PATH)));
            $dc_exists = is_file($dc . 'pts-download-cache.json');
            foreach (pts_openbenchmarking::available_tests(false, true) as $test) {
                $cache_checked = false;
                if ($dc_exists) {
                    $cache_json = file_get_contents($dc . 'pts-download-cache.json');
                    $cache_json = json_decode($cache_json, true);
                    if ($cache_json && isset($cache_json['phoronix-test-suite']['cached-tests'])) {
                        $cache_checked = true;
                        if (!in_array($test, $cache_json['phoronix-test-suite']['cached-tests'])) {
                            continue;
                        }
                    }
                }
                if (!$cache_checked && phoromatic_server::read_setting('show_local_tests_only') && pts_test_install_request::test_files_in_cache($test, true, true) == false) {
                    continue;
                }
                $main .= '<option value="' . $test . '">' . $test . '</option>';
            }
            $main .= '</select>';
            $main .= '<p align="right"><input name="submit" value="Create Suite" type="submit" onclick="return pts_rmm_validate_suite();" /></p>';
        }
        echo '<div id="pts_phoromatic_main_area">' . $main . '</div>';
        echo phoromatic_webui_footer();
    }
    public static function render_page_process($PATH)
    {
        $main = null;
        if (isset($PATH[0])) {
            $upload_ids = explode(',', $PATH[0]);
            foreach ($upload_ids as $i => $upload_id) {
                if (isset($upload_id[5]) && substr($upload_id, 0, 2) == 'S:') {
                    $t = explode(':', $upload_id);
                    $stmt = phoromatic_server::$db->prepare('SELECT UploadID, UploadTime FROM phoromatic_results WHERE AccountID = :account_id AND ScheduleID = :schedule_id ORDER BY UploadTime DESC');
                    $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                    $stmt->bindValue(':schedule_id', $t[1]);
                    $test_result_result = $stmt->execute();
                    $cutoff_time = is_numeric($t[2]) ? strtotime('today -' . $t[2] . ' days') : false;
                    while ($test_result_row = $test_result_result->fetchArray()) {
                        if ($cutoff_time !== false && strtotime($test_result_row['UploadTime']) < $cutoff_time) {
                            break;
                        }
                        $upload_ids[] = $test_result_row['UploadID'];
                    }
                    unset($upload_ids[$i]);
                }
            }
            $upload_ids = array_unique($upload_ids);
            $result_files = array();
            $display_rows = array();
            $system_types = array();
            $schedule_types = array();
            $trigger_types = array();
            $upload_times = array();
            $benchmark_tickets = array();
            $xml_result_hash = array();
            $tickets = array();
            foreach ($upload_ids as $id) {
                $result_share_opt = phoromatic_server::read_setting('force_result_sharing') ? '1 = 1' : 'AccountID = (SELECT AccountID FROM phoromatic_account_settings WHERE LetOtherGroupsViewResults = "1" AND AccountID = phoromatic_results.AccountID)';
                $stmt = phoromatic_server::$db->prepare('SELECT * FROM phoromatic_results WHERE PPRID = :pprid AND (AccountID = :account_id OR ' . $result_share_opt . ') LIMIT 1');
                $stmt->bindValue(':pprid', $id);
                $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                $result = $stmt->execute();
                $row = $result->fetchArray();
                if (false && empty($row)) {
                    // TODO XXX
                    // XXX this code is ultimately dead
                    $stmt = phoromatic_server::$db->prepare('SELECT * FROM phoromatic_results WHERE AccountID = :account_id AND UploadID = :upload_id LIMIT 1');
                    $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                    $stmt->bindValue(':upload_id', $id);
                    $result = $stmt->execute();
                    $row = $result->fetchArray();
                }
                if (empty($row)) {
                    continue;
                }
                $composite_xml = phoromatic_server::phoromatic_account_result_path($row['AccountID'], $row['UploadID']) . 'composite.xml';
                if (!is_file($composite_xml)) {
                    echo 'File Not Found: ' . $composite_xml;
                    return false;
                }
                $display_rows[$composite_xml] = $row;
                pts_arrays::unique_push($benchmark_tickets, $row['BenchmarkTicketID']);
                pts_arrays::unique_push($upload_times, $row['UploadTime']);
                pts_arrays::unique_push($xml_result_hash, $row['XmlUploadHash']);
                pts_arrays::unique_push($system_types, $row['SystemID']);
                pts_arrays::unique_push($schedule_types, $row['ScheduleID']);
                pts_arrays::unique_push($trigger_types, $row['Trigger']);
                pts_arrays::unique_push($tickets, $row['BenchmarkTicketID']);
                // Update view counter
                $stmt_view = phoromatic_server::$db->prepare('UPDATE phoromatic_results SET TimesViewed = (TimesViewed + 1) WHERE AccountID = :account_id AND UploadID = :upload_id');
                $stmt_view->bindValue(':account_id', $_SESSION['AccountID']);
                $stmt_view->bindValue(':upload_id', $row['UploadID']);
                $stmt_view->execute();
            }
            $result_file_title = null;
            if (count($system_types) == 1) {
                $result_file_title = phoromatic_system_id_to_name($system_types[0]) . ' Tests';
            }
            if (!empty($tickets) && $tickets[0] != null) {
                $system_name_format = 'ORIGINAL_DATA';
            } else {
                if (count($trigger_types) == 1 && $trigger_types[0] != null && $benchmark_tickets[0] != null && count($display_rows) > 1) {
                    $system_name_format = 'TRIGGER_AND_SYSTEM';
                } else {
                    if (empty($schedule_types[0])) {
                        $system_name_format = 'ORIGINAL_DATA';
                    } else {
                        if (count($display_rows) == 1) {
                            $system_name_format = 'SYSTEM_NAME';
                        } else {
                            if (count($schedule_types) == 1 && count($system_types) == 1) {
                                $system_name_format = 'TRIGGER';
                                $result_file_title = phoromatic_schedule_id_to_name($schedule_types[0]);
                            } else {
                                if (count($schedule_types) == 1) {
                                    $system_name_format = 'TRIGGER_AND_SYSTEM';
                                } else {
                                    if (false && count($trigger_types) == 1) {
                                        // TODO XXX: this approach yields garbage strings generally without refining the selector
                                        // i.e. first make sure all the schedules match or are comparable
                                        $system_name_format = 'SYSTEM_AND_SCHEDULE';
                                    } else {
                                        $system_name_format = null;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if (count($schedule_types) == 1 && $schedule_types[0] != 0) {
                self::$schedule_id = $schedule_types[0];
            }
            foreach ($display_rows as $composite_xml => $row) {
                //  $row['SystemID'] . ' ' . $row['ScheduleID'] . ' ' . $row['Trigger']
                switch ($system_name_format) {
                    case 'ORIGINAL_DATA':
                        $system_name = null;
                        break;
                    case 'SYSTEM_NAME':
                        $system_name = phoromatic_system_id_to_name($row['SystemID']);
                        break;
                    case 'TRIGGER':
                        $system_name = $row['Trigger'];
                        break;
                    case 'TRIGGER_AND_SYSTEM':
                        $system_name = phoromatic_system_id_to_name($row['SystemID']) . ': ' . $row['Trigger'];
                        break;
                    case 'SYSTEM_AND_SCHEDULE':
                        $system_name = phoromatic_schedule_id_to_name($row['ScheduleID']) . ': ' . $row['Trigger'];
                        break;
                    default:
                        $system_name = phoromatic_system_id_to_name($row['SystemID']) . ' - ' . phoromatic_schedule_id_to_name($row['ScheduleID']) . ' - ' . $row['Trigger'];
                }
                if ($system_name == null) {
                    $rf = new pts_result_file($composite_xml);
                    $identifiers = $rf->get_system_identifiers();
                    if (count($identifiers) == 1) {
                        $system_name = $identifiers[0];
                    }
                }
                $system_name = str_replace('.SYSTEM', phoromatic_system_id_to_name($row['SystemID']), $system_name);
                $system_name = str_replace('.GROUP', phoromatic_account_id_to_group_name($row['AccountID']), $system_name);
                $system_variables = explode(';', phoromatic_server::system_id_variables($row['SystemID'], $row['AccountID']));
                foreach ($system_variables as $var) {
                    $var = explode('=', $var);
                    if (count($var) == 2) {
                        $system_name = str_replace('.' . $var[0], $var[1], $system_name);
                    }
                }
                $result_files[] = new pts_result_merge_select($composite_xml, null, $system_name);
            }
            $result_file = new pts_result_file(null, true);
            $result_file->set_title('Phoromatic Results');
            if (!empty($result_files)) {
                $attributes = array('new_result_file_title' => $result_file_title);
                if (!empty($result_files)) {
                    $result_file->merge($result_files, $attributes);
                }
            }
            $extra_attributes = array();
            if (isset($_GET['upload_to_openbenchmarking'])) {
                $ob_url = pts_openbenchmarking_client::upload_test_result($result_file, false);
                if ($ob_url) {
                    header('Location: ' . $ob_url);
                }
            }
            $attribute_options = array('normalize_results' => 'normalize_result_buffer', 'sort_by_performance' => 'sort_result_buffer_values', 'sort_by_reverse' => 'reverse_result_buffer', 'sort_by_name' => 'sort_result_buffer', 'condense_comparison' => 'condense_multi_way', 'force_line_graph' => 'force_tracking_line_graph');
            $url_append = null;
            foreach ($attribute_options as $web_var => $attr_var) {
                if (isset($_REQUEST[$web_var])) {
                    $extra_attributes[$attr_var] = true;
                    $url_append .= '&' . $web_var . '=1';
                }
            }
            if (isset($_POST['transpose_comparison'])) {
                $result_file->invert_multi_way_invert();
            }
            $intent = null;
            if (isset($_GET['download']) && $_GET['download'] == 'csv') {
                $result_csv = pts_result_file_output::result_file_to_csv($result_file);
                header('Content-Description: File Transfer');
                header('Content-Type: application/csv');
                header('Content-Disposition: attachment; filename=phoromatic-result.csv');
                header('Expires: 0');
                header('Cache-Control: must-revalidate');
                header('Pragma: public');
                header('Content-Length: ' . strlen($result_csv));
                ob_clean();
                flush();
                echo $result_csv;
                return;
            } else {
                if (isset($_GET['download']) && $_GET['download'] == 'txt') {
                    $result_txt = pts_result_file_output::result_file_to_text($result_file);
                    header('Content-Description: File Transfer');
                    header('Content-Type: application/txt');
                    header('Content-Disposition: attachment; filename=phoromatic-result.txt');
                    header('Expires: 0');
                    header('Cache-Control: must-revalidate');
                    header('Pragma: public');
                    header('Content-Length: ' . strlen($result_txt));
                    ob_clean();
                    flush();
                    echo $result_txt;
                    return;
                } else {
                    if (isset($_GET['download']) && $_GET['download'] == 'pdf') {
                        ob_start();
                        $_REQUEST['force_format'] = 'PNG';
                        // Force to PNG renderer
                        $_REQUEST['svg_dom_gd_no_interlacing'] = true;
                        // Otherwise FPDF will fail
                        $tdir = pts_client::create_temporary_directory();
                        pts_client::generate_result_file_graphs($result_file, $tdir, $extra_attributes);
                        $pdf = new pts_pdf_template($result_file->get_title(), null);
                        $pdf->AddPage();
                        $pdf->Image(PTS_CORE_STATIC_PATH . 'images/pts-308x160.png', 69, 85, 73, 38);
                        $pdf->Ln(120);
                        $pdf->WriteStatementCenter('www.phoronix-test-suite.com');
                        $pdf->Ln(15);
                        $pdf->WriteBigHeaderCenter($result_file->get_title());
                        $pdf->WriteText($result_file->get_description());
                        $pdf->AddPage();
                        $pdf->Ln(15);
                        $pdf->SetSubject($result_file->get_title() . ' Benchmarks');
                        //$pdf->SetKeywords(implode(', ', $identifiers));
                        $pdf->WriteHeader('Test Systems:');
                        foreach ($result_file->get_systems() as $s) {
                            $pdf->WriteMiniHeader($s->get_identifier());
                            $pdf->WriteText($s->get_hardware());
                            $pdf->WriteText($s->get_software());
                        }
                        $pdf->AddPage();
                        $placement = 1;
                        $results = $result_file->get_result_objects();
                        for ($i = 1; $i <= count($results); $i++) {
                            if (is_file($tdir . 'result-graphs/' . $i . '.png')) {
                                $pdf->Ln(100);
                                $pdf->Image($tdir . 'result-graphs/' . $i . '.png', 50, 40 + ($placement - 1) * 120, 120);
                            }
                            if ($placement == 2) {
                                $placement = 0;
                                if ($i != count($results)) {
                                    $pdf->AddPage();
                                }
                            }
                            $placement++;
                        }
                        ob_get_clean();
                        $pdf->Output('phoromatic.pdf', 'I');
                        //pts_file_io::delete($tdir, null, true);
                        return;
                    } else {
                        if (isset($_GET['download']) && $_GET['download'] == 'xml') {
                            echo $result_file->get_xml();
                            return;
                        }
                    }
                }
            }
            $main .= '<h1>' . $result_file->get_title() . '</h1>';
            $main .= phoromatic_annotate_entry('RESULT', implode(',', $upload_ids), 'TOP');
            if ($result_file->get_system_count() == 1 || ($intent = pts_result_file_analyzer::analyze_result_file_intent($result_file, $intent, true))) {
                $table = new pts_ResultFileCompactSystemsTable($result_file, $intent);
            } else {
                $table = new pts_ResultFileSystemsTable($result_file);
            }
            $main .= '<p style="text-align: center; overflow: auto;" class="result_object">' . pts_render::render_graph_inline_embed($table, $result_file, $extra_attributes) . '</p>';
            $table = new pts_ResultFileTable($result_file, $intent);
            $main .= '<p style="text-align: center; overflow: auto;" class="result_object">' . pts_render::render_graph_inline_embed($table, $result_file, $extra_attributes) . '</p>';
            $main .= '<div id="pts_results_area">';
            foreach ($result_file->get_result_objects(isset($_POST['show_only_changed_results']) ? 'ONLY_CHANGED_RESULTS' : -1) as $i => $result_object) {
                $main .= '<h2><a name="r-' . $i . '"></a><a name="' . $result_object->get_comparison_hash(true, false) . '"></a>' . $result_object->test_profile->get_title() . '</h2>';
                $main .= phoromatic_annotate_entry('RESULT', implode(',', $upload_ids), $result_object->get_comparison_hash(true, false));
                $main .= '<p class="result_object">';
                $main .= pts_render::render_graph_inline_embed($result_object, $result_file, $extra_attributes);
                $main .= '</p>';
            }
            $main .= '</div>';
        } else {
            // No result
        }
        $right = null;
        if (self::$schedule_id && !empty(self::$schedule_id)) {
            $stmt = phoromatic_server::$db->prepare('SELECT * FROM phoromatic_schedules WHERE AccountID = :account_id AND ScheduleID = :schedule_id LIMIT 1');
            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
            $stmt->bindValue(':schedule_id', self::$schedule_id);
            $result = $stmt->execute();
            $row = $result->fetchArray();
            if (!empty($row)) {
                $right .= '<h3><a href="?schedules/' . $row['ScheduleID'] . '">' . $row['Title'] . '</a></h3>';
                if (!empty($row['ActiveOn'])) {
                    $right .= '<p align="center"><strong>' . phoromatic_schedule_activeon_string($row['ActiveOn'], $row['RunAt']) . '</strong></p>';
                }
                $right .= '<p>Compare this result file to the latest results from the past: ';
                $right .= '<select name="view_results_from_past" id="view_results_from_past" onchange="phoromatic_jump_to_results_from(\'' . $row['ScheduleID'] . '\', \'view_results_from_past\', \'' . $PATH[0] . ',\');">';
                $oldest_upload_time = strtotime(phoromatic_oldest_result_for_schedule(self::$schedule_id));
                $opts = array('Week' => 7, 'Three Weeks' => 21, 'Month' => 30, 'Quarter' => 90, 'Six Months' => 180, 'Year' => 365);
                foreach ($opts as $str_name => $time_offset) {
                    if ($oldest_upload_time > time() - 86400 * $time_offset) {
                        break;
                    }
                    $right .= '<option value="' . $time_offset . '">' . $str_name . '</option>';
                }
                $right .= '<option value="all">All Results</option>';
                $right .= '</select>';
                $right .= '</p>';
            }
        }
        if (true) {
            $compare_results = array();
            $hash_matches = 0;
            $ticket_matches = 0;
            $stmt = phoromatic_server::$db->prepare('SELECT * FROM phoromatic_results WHERE AccountID = :account_id AND ComparisonHash = :comparison_hash AND PPRID NOT IN (:pprid) ORDER BY UploadTime DESC LIMIT 12');
            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
            $stmt->bindValue(':comparison_hash', $result_file->get_contained_tests_hash(false));
            $stmt->bindValue(':pprid', implode(',', $upload_ids));
            $result = $stmt->execute();
            while ($row = $result->fetchArray()) {
                $compare_results[$row['PPRID']] = $row;
                $hash_matches++;
            }
            foreach ($benchmark_tickets as $ticket_id) {
                $stmt = phoromatic_server::$db->prepare('SELECT * FROM phoromatic_results WHERE AccountID = :account_id AND BenchmarkTicketID = :ticket_id AND PPRID NOT IN (:pprid) ORDER BY UploadTime DESC LIMIT 12');
                $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                $stmt->bindValue(':ticket_id', $ticket_id);
                $stmt->bindValue(':pprid', implode(',', $upload_ids));
                $result = $stmt->execute();
                while ($row = $result->fetchArray()) {
                    $compare_results[$row['PPRID']] = $row;
                    $ticket_matches++;
                }
            }
            if (!empty($compare_results)) {
                $right .= '<hr /><h3>Compare Results</h3><form name="compare_similar_results" onsubmit="return false;">
						<input type="hidden" value="' . implode(',', $upload_ids) . '" id="compare_similar_results_this" />';
                foreach ($compare_results as &$row) {
                    $right .= '<p><input type="checkbox" value="' . $row['PPRID'] . '" name="compare_results" /> ' . $row['Title'] . '<br /><em>' . phoromatic_system_id_to_name($row['SystemID'], $row['AccountID']) . '</em></p>';
                }
                $right .= '<p><input type="submit" value="Compare Results" id="compare_results_submit" onclick="javascript:phoromatic_do_custom_compare_results(this); return false;" /></p></form>';
                if ($ticket_matches > 3) {
                    $right .= '<p><a href="/results/ticket/' . $ticket_id . '">Find All Matching Results</a>';
                } else {
                    if ($hash_matches > 3) {
                        $right .= '<p><a href="/results/hash/' . $result_file->get_contained_tests_hash(false) . '">Find All Matching Results</a>';
                    }
                }
            }
        }
        if (count($upload_ids) > 1) {
            $checkbox_options = array('normalize_results' => 'Normalize Results', 'sort_by_performance' => 'Sort Results By Performance', 'sort_by_name' => 'Reverse Result By Identifier', 'sort_by_reverse' => 'Reverse Result Order', 'show_only_changed_results' => 'Show Only Results With Result Variation', 'force_line_graph' => 'Force Line Graph');
            if ($result_file->is_multi_way_comparison()) {
                $checkbox_options['condense_comparison'] = 'Condense Comparison';
                $checkbox_options['transpose_comparison'] = 'Transpose Comparison';
            }
            $right .= '<form action="' . $_SERVER['REQUEST_URI'] . '" name="update_result_view" method="post"><hr /><h3>Result Analysis Options</h3><p align="left">' . PHP_EOL;
            foreach ($checkbox_options as $val => $name) {
                $right .= '<input type="checkbox" name="' . $val . '" value="1" ' . (isset($_POST[$val]) ? 'checked="checked" ' : null) . '/> ' . $name . '<br />';
            }
            $right .= '<br /><input type="submit" value="Refresh Results"></p></form>';
        }
        if (self::$schedule_id && !empty(self::$schedule_id) && $system_types[0] && $trigger_types[0]) {
            $stmt = phoromatic_server::$db->prepare('SELECT UserContextStep FROM phoromatic_system_context_logs WHERE AccountID = :account_id AND ScheduleID = :schedule_id AND SystemID = :system_id AND TriggerID = :trigger_id');
            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
            $stmt->bindValue(':system_id', $system_types[0]);
            $stmt->bindValue(':schedule_id', self::$schedule_id);
            $stmt->bindValue(':trigger_id', $trigger_types[0]);
            $result = $stmt->execute();
            if ($row = $result->fetchArray()) {
                $right .= '<hr /><h3>User Context Logs</h3>';
                do {
                    $right .= '<p><a href="?logs/context/' . $system_types[0] . ',' . self::$schedule_id . ',' . base64_encode($trigger_types[0]) . '">' . $row['UserContextStep'] . '</a></p>';
                } while ($row = $result->fetchArray());
            }
        }
        $right .= '<hr /><h3>Result Export</h3>';
        $right .= '<p><a href="/public.php?t=result&ut=' . implode(',', $upload_ids) . $url_append . '">Public Viewer</a></p>';
        $right .= '<p><a href="?' . $_SERVER['QUERY_STRING'] . '/&download=pdf' . $url_append . '">Download As PDF</a></p>';
        $right .= '<p><a href="?' . $_SERVER['QUERY_STRING'] . '/&download=csv">Download As CSV</a></p>';
        $right .= '<p><a href="?' . $_SERVER['QUERY_STRING'] . '/&download=xml">Download As XML</a></p>';
        $right .= '<p><a href="?' . $_SERVER['QUERY_STRING'] . '/&download=txt">Download As TEXT</a></p>';
        $right .= '<p><a href="?' . $_SERVER['QUERY_STRING'] . '/&upload_to_openbenchmarking">Upload To OpenBenchmarking.org</a></p>';
        if (is_file(phoromatic_server::phoromatic_account_result_path($_SESSION['AccountID'], $row['UploadID']) . 'system-logs.zip')) {
            $right .= '<hr /><p><a href="?logs/system/' . $row['UploadID'] . '">View System Logs</a></p>';
        }
        echo phoromatic_webui_header_logged_in();
        echo phoromatic_webui_main($main, phoromatic_webui_right_panel_logged_in($right));
        echo phoromatic_webui_footer();
    }
    public static function render_page_process($PATH)
    {
        $main = null;
        echo phoromatic_webui_header_logged_in();
        if (!empty($PATH[0]) && is_numeric($PATH[0])) {
            $stmt = phoromatic_server::$db->prepare('SELECT * FROM phoromatic_schedules WHERE AccountID = :account_id AND ScheduleID = :schedule_id');
            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
            $stmt->bindValue(':schedule_id', $PATH[0]);
            $result = $stmt->execute();
            $row = $result->fetchArray();
            if (empty($row)) {
                $main = '<h1>Test Schedules</h1>';
                $main .= '<h3>No Resource Found</h3>';
            } else {
                if (!PHOROMATIC_USER_IS_VIEWER) {
                    if (isset($_POST['add_to_schedule_select_test'])) {
                        $name = $_POST['add_to_schedule_select_test'];
                        $args = array();
                        $args_name = array();
                        foreach ($_POST as $i => $v) {
                            if (substr($i, 0, 12) == 'test_option_' && substr($i, -9) != '_selected') {
                                array_push($args, $v);
                                array_push($args_name, $_POST[$i . '_selected']);
                            }
                        }
                        $args_name = implode(' - ', $args_name);
                        $args = implode(' ', $args);
                        if (!empty($name)) {
                            $stmt = phoromatic_server::$db->prepare('INSERT INTO phoromatic_schedules_tests (AccountID, ScheduleID, TestProfile, TestArguments, TestDescription) VALUES (:account_id, :schedule_id, :test_profile, :test_arguments, :test_description)');
                            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                            $stmt->bindValue(':schedule_id', $PATH[0]);
                            $stmt->bindValue(':test_profile', $name);
                            $stmt->bindValue(':test_arguments', $args);
                            $stmt->bindValue(':test_description', $args_name);
                            $result = $stmt->execute();
                            phoromatic_add_activity_stream_event('tests_for_schedule', $PATH[0], 'added');
                        }
                    } else {
                        if (isset($PATH[1]) && $PATH[1] == 'remove' && !empty($PATH[2])) {
                            // REMOVE TEST
                            $to_remove = explode(PHP_EOL, base64_decode($PATH[2]));
                            $stmt = phoromatic_server::$db->prepare('DELETE FROM phoromatic_schedules_tests WHERE AccountID = :account_id AND ScheduleID = :schedule_id AND TestProfile = :test AND TestArguments = :test_args');
                            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                            $stmt->bindValue(':schedule_id', $PATH[0]);
                            $stmt->bindValue(':test', $to_remove[0]);
                            $stmt->bindValue(':test_args', $to_remove[1]);
                            $result = $stmt->execute();
                            phoromatic_add_activity_stream_event('tests_for_schedule', $to_remove[0] . ' - ' . $to_remove[1], 'removed');
                        } else {
                            if (isset($PATH[1]) && $PATH[1] == 'delete-trigger' && !empty($PATH[2])) {
                                // REMOVE TRIGGER
                                $trigger = base64_decode($PATH[2]);
                                $stmt = phoromatic_server::$db->prepare('DELETE FROM phoromatic_schedules_triggers WHERE AccountID = :account_id AND Trigger = :trigger AND ScheduleID = :schedule_id');
                                $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                                $stmt->bindValue(':schedule_id', $PATH[0]);
                                $stmt->bindValue(':trigger', $trigger);
                                $result = $stmt->execute();
                                if ($result) {
                                    $main .= '<h2 style="color: red;">Trigger Removed: ' . $trigger . '</h2>';
                                }
                            } else {
                                if (isset($PATH[1]) && in_array($PATH[1], array('activate', 'deactivate'))) {
                                    switch ($PATH[1]) {
                                        case 'deactivate':
                                            $new_state = 0;
                                            break;
                                        case 'activate':
                                        default:
                                            $new_state = 1;
                                            break;
                                    }
                                    // REMOVE TEST
                                    $stmt = phoromatic_server::$db->prepare('UPDATE phoromatic_schedules SET State = :new_state WHERE AccountID = :account_id AND ScheduleID = :schedule_id');
                                    $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                                    $stmt->bindValue(':schedule_id', $PATH[0]);
                                    $stmt->bindValue(':new_state', $new_state);
                                    $result = $stmt->execute();
                                    $row['State'] = $new_state;
                                    phoromatic_add_activity_stream_event('schedule', $PATH[0], $PATH[1]);
                                } else {
                                    if (isset($_POST['do_manual_test_run'])) {
                                        $stmt = phoromatic_server::$db->prepare('INSERT INTO phoromatic_schedules_triggers (AccountID, ScheduleID, Trigger, TriggeredOn) VALUES (:account_id, :schedule_id, :trigger, :triggered_on)');
                                        $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                                        $stmt->bindValue(':schedule_id', $PATH[0]);
                                        $stmt->bindValue(':trigger', $_SESSION['UserName'] . ' - Manual Test Run - ' . date('H:i j M Y'));
                                        $stmt->bindValue(':triggered_on', phoromatic_server::current_time());
                                        $stmt->execute();
                                        $main .= '<h2 style="color: red;">Manual Test Run Triggered</h2>';
                                    } else {
                                        if (isset($_POST['skip_current_ticket'])) {
                                            $stmt = phoromatic_server::$db->prepare('INSERT INTO phoromatic_schedules_trigger_skips (AccountID, ScheduleID, Trigger) VALUES (:account_id, :schedule_id, :trigger)');
                                            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                                            $stmt->bindValue(':schedule_id', $PATH[0]);
                                            $stmt->bindValue(':trigger', date('Y-m-d'));
                                            $stmt->execute();
                                            $main .= '<h2 style="color: red;">Current Trigger To Be Ignored</h2>';
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                $main .= '<h1>' . $row['Title'] . '</h1>';
                $main .= '<h3>' . $row['Description'] . '</h3>';
                $main .= '<p>This schedule was last modified on <strong>' . date('j F Y \\a\\t H:i', strtotime($row['LastModifiedOn'])) . '</strong> by <strong>' . $row['LastModifiedBy'] . '</strong>.';
                if (!PHOROMATIC_USER_IS_VIEWER) {
                    $main .= '<p><a href="?sched/' . $PATH[0] . '">Edit Schedule</a> | ';
                    if ($row['State'] == 1) {
                        $main .= '<a href="?schedules/' . $PATH[0] . '/deactivate">Deactivate Schedule</a>';
                    } else {
                        $main .= '<a href="?schedules/' . $PATH[0] . '/activate">Activate Schedule</a>';
                    }
                    $main .= '</p>';
                }
                $main .= '<hr />';
                $main .= '<h2>Schedule</h2>';
                if (!empty($row['ActiveOn'])) {
                    $active_days = explode(',', $row['ActiveOn']);
                    $week = array('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday');
                    foreach ($active_days as $i => &$day) {
                        if (!isset($week[$day])) {
                            unset($active_days[$i]);
                        } else {
                            $day = $week[$day];
                        }
                    }
                    switch (count($active_days)) {
                        case 2:
                            $day_show = implode(' and ', $active_days);
                            break;
                        default:
                            $day_show = implode(', ', $active_days);
                            break;
                    }
                    $main .= '<p>This test is scheduled to run every <strong>' . $day_show . '</strong> at <strong>' . str_replace('.', ':', $row['RunAt']) . '</strong>.</p>';
                } else {
                    $main .= '<p>This test schedule is not currently set to run a pre-defined time-based schedule.</p>';
                }
                if (!PHOROMATIC_USER_IS_VIEWER) {
                    $trigger_url = 'http://' . phoromatic_web_socket_server_ip() . '/event.php?type=trigger&user=' . $_SESSION['UserName'] . '&public_key=' . $row['PublicKey'] . '&trigger=XXX';
                    $main .= '<p>This test schedule can be manually triggered to run at any time by calling <strong>' . $trigger_url . '</strong> where <em>XXX</em> is the trigger value to be used (if relevant, such as a time-stamp, Git/SVN commit number or hash, etc). There\'s also the option of sub-targeting system(s) part of this schedule. One option is appending <em>&sub_target_this_ip</em> if this URL is being called from one of the client test systems to only sub-target the triggered testing on that client, among other options.</p>';
                    $main .= '<p>If you wish to run this test schedule now, click the following button and the schedule will be run on all intended systems at their next earliest possible convenience.</p>';
                    $main .= '<p><form action="?schedules/' . $PATH[0] . '" name="manual_run" method="post">';
                    $main .= '<input type="hidden" name="do_manual_test_run" value="1" /><input type="submit" value="Run Test Schedule Now" onclick="return confirm(\'Run this test schedule now?\');" />';
                    $main .= '</form></p>';
                    $main .= '<p><form action="?schedules/' . $PATH[0] . '" name="skip_run" method="post">';
                    $main .= '<input type="hidden" name="skip_current_ticket" value="1" /><input type="submit" value="Skip Current Test Ticket" onclick="return confirm(\'Skip any currently active test ticket on all systems?\');" />';
                    $main .= '</form></p>';
                }
                $main .= '<hr />';
                $contexts = array('SetContextPreInstall' => 'Pre-Install', 'SetContextPostInstall' => 'Post-Install', 'SetContextPreRun' => 'Pre-Test-Run', 'SetContextPostRun' => 'Post-Test-Run');
                $scripts = 0;
                foreach ($contexts as $context => $v) {
                    if (isset($row[$context]) && !empty($row[$context]) && is_file(phoromatic_server::phoromatic_account_path($_SESSION['AccountID']) . 'context_' . $row[$context])) {
                        $scripts++;
                        $main .= '<h2>' . $v . ' Context Script</h2>';
                        $main .= '<blockquote>' . str_replace(PHP_EOL, '<br />', htmlentities(file_get_contents(phoromatic_server::phoromatic_account_path($_SESSION['AccountID']) . 'context_' . $row[$context]))) . '</blockquote>';
                    }
                }
                if ($scripts > 0) {
                    $main .= '<hr />';
                }
                $main .= '<h2>Tests To Run</h2>';
                $stmt = phoromatic_server::$db->prepare('SELECT * FROM phoromatic_schedules_tests WHERE AccountID = :account_id AND ScheduleID = :schedule_id ORDER BY TestProfile ASC');
                $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                $stmt->bindValue(':schedule_id', $PATH[0]);
                $result = $stmt->execute();
                $test_count = 0;
                $main .= '<p>';
                while ($row = $result->fetchArray()) {
                    $test_count++;
                    $main .= $row['TestProfile'] . ($row['TestDescription'] != null ? ' - <em>' . $row['TestDescription'] . '</em>' : '') . (!PHOROMATIC_USER_IS_VIEWER ? ' <a href="?schedules/' . $PATH[0] . '/remove/' . base64_encode(implode(PHP_EOL, array($row['TestProfile'], $row['TestArguments']))) . '">Remove Test</a>' : null) . '<br />';
                    /*
                    if(!PHOROMATIC_USER_IS_VIEWER && isset($_REQUEST['make_version_lock_tests']))
                    {
                    	if(strpos($row['TestProfile'], '.') == false)
                    	{
                    		$test_profile = new pts_test_profile($row['TestProfile']);
                    		$full_identifier = $test_profile->get_identifier(true);
                    
                    		$stmt = phoromatic_server::$db->prepare('UPDATE phoromatic_schedules_tests SET TestProfile = :version_locked_tp WHERE AccountID = :account_id AND ScheduleID = :schedule_id AND TestProfile = :test');
                    		$stmt->bindValue(':account_id', $_SESSION['AccountID']);
                    		$stmt->bindValue(':schedule_id', $PATH[0]);
                    		$stmt->bindValue(':test', $row['TestProfile']);
                    		$stmt->bindValue(':version_locked_tp', $full_identifier);
                    		$result2 = $stmt->execute();
                    	}
                    }
                    */
                }
                $main .= '</p>';
                if ($test_count == 0) {
                    $main .= '<h3 style="text-transform: uppercase;">No tests have been added yet for this test schedule.</h3>';
                }
                if (!PHOROMATIC_USER_IS_VIEWER) {
                    $main .= '<hr /><h2>Add A Test</h2>';
                    $main .= '<form action="?schedules/' . $PATH[0] . '" name="add_test" id="add_test" method="post">';
                    $main .= '<select name="add_to_schedule_select_test" id="add_to_schedule_select_test" onchange="phoromatic_schedule_test_details(\'\');">';
                    $dc = pts_strings::add_trailing_slash(pts_client::parse_home_directory(pts_config::read_user_config('PhoronixTestSuite/Options/Installation/CacheDirectory', PTS_DOWNLOAD_CACHE_PATH)));
                    $dc_exists = is_file($dc . 'pts-download-cache.json');
                    foreach (pts_openbenchmarking::available_tests(false, true) as $test) {
                        $cache_checked = false;
                        if ($dc_exists) {
                            $cache_json = file_get_contents($dc . 'pts-download-cache.json');
                            $cache_json = json_decode($cache_json, true);
                            if ($cache_json && isset($cache_json['phoronix-test-suite']['cached-tests'])) {
                                $cache_checked = true;
                                if (!in_array($test, $cache_json['phoronix-test-suite']['cached-tests'])) {
                                    continue;
                                }
                            }
                        }
                        if (!$cache_checked && phoromatic_server::read_setting('show_local_tests_only') && pts_test_install_request::test_files_in_cache($test, true, true) == false) {
                            continue;
                        }
                        $main .= '<option value="' . $test . '">' . $test . '</option>';
                    }
                    $main .= '</select>';
                    $main .= '<p><div id="test_details"></div></p>';
                    $main .= '</form>';
                }
                $systems_in_schedule = phoromatic_server::systems_associated_with_schedule($_SESSION['AccountID'], $PATH[0]);
                if (!empty($systems_in_schedule)) {
                    $main .= '<hr /><h2>Systems In Schedule</h2>';
                    if (!PHOROMATIC_USER_IS_VIEWER) {
                        $main .= '<p>To run this schedule on more systems, <a href="?sched/' . $PATH[0] . '">edit the schedule</a>.</p>';
                    }
                    $main .= '<div class="pts_phoromatic_info_box_area" style="margin: 0 10%;"><ul><li><h1>Systems</h1></li>';
                    foreach ($systems_in_schedule as $system_id) {
                        $row = phoromatic_server::get_system_details($_SESSION['AccountID'], $system_id);
                        $main .= '<a href="?systems/' . $row['SystemID'] . '"><li>' . $row['Title'] . '<br /><table><tr><td>' . $row['LocalIP'] . '</td><td><strong>' . $row['CurrentTask'] . '</strong></td><td><strong>Last Communication:</strong> ' . date('j F Y H:i', strtotime($row['LastCommunication'])) . '</td></tr></table></li></a>';
                    }
                    $main .= '</ul></div><hr />';
                }
                $stmt = phoromatic_server::$db->prepare('SELECT Trigger, TriggeredOn FROM phoromatic_schedules_triggers WHERE AccountID = :account_id AND ScheduleID = :schedule_id ORDER BY TriggeredOn DESC LIMIT 10');
                $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                $stmt->bindValue(':schedule_id', $PATH[0]);
                $test_result_result = $stmt->execute();
                $test_result_row = $test_result_result->fetchArray();
                if ($test_result_row) {
                    $main .= '<div class="pts_phoromatic_info_box_area" style="margin: 0 10%;">';
                    $main .= '<ul><li><h1>Recent Triggers For This Schedule</h1></li>';
                    do {
                        $main .= '<a onclick=""><li>' . $test_result_row['Trigger'] . '<br /><table><tr><td>' . phoromatic_user_friendly_timedate($test_result_row['TriggeredOn']) . '</td><td><a href="?schedules/' . $PATH[0] . '/delete-trigger/' . base64_encode($test_result_row['Trigger']) . '">Remove Trigger</a></td></tr></table></li></a>';
                    } while ($test_result_row = $test_result_result->fetchArray());
                    $main .= '</ul>';
                    $main .= '</div>';
                }
                $stmt = phoromatic_server::$db->prepare('SELECT Title, SystemID, ScheduleID, PPRID, UploadTime FROM phoromatic_results WHERE AccountID = :account_id AND ScheduleID = :schedule_id ORDER BY UploadTime DESC');
                $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                $stmt->bindValue(':schedule_id', $PATH[0]);
                $test_result_result = $stmt->execute();
                $test_result_row = $test_result_result->fetchArray();
                if ($test_result_row) {
                    $main .= '<div class="pts_phoromatic_info_box_area" style="margin: 0 10%;">';
                    $main .= '<ul><li><h1>Recent Test Results For This Schedule</h1></li>';
                    $results = 0;
                    do {
                        $oldest_upload_time = $test_result_row['UploadTime'];
                        if ($results > 100) {
                            continue;
                        }
                        $main .= '<a href="?result/' . $test_result_row['PPRID'] . '"><li>' . $test_result_row['Title'] . '<br /><table><tr><td>' . phoromatic_system_id_to_name($test_result_row['SystemID']) . '</td><td>' . phoromatic_user_friendly_timedate($test_result_row['UploadTime']) . '</td></tr></table></li></a>';
                        $results++;
                    } while ($test_result_row = $test_result_result->fetchArray());
                    $main .= '</ul>';
                    $main .= '</div>';
                }
                $num_results = phoromatic_results_for_schedule($PATH[0]);
                if ($num_results > 1) {
                    $main .= '<p>Jump to the latest results from the past: ';
                    $main .= '<select name="view_results_from_past" id="view_results_from_past" onchange="phoromatic_jump_to_results_from(\'' . $PATH[0] . '\', \'view_results_from_past\');">';
                    $oldest_upload_time = strtotime($oldest_upload_time);
                    $opts = array('Week' => 7, 'Three Weeks' => 21, 'Month' => 30, 'Quarter' => 90, 'Six Months' => 180, 'Year' => 365);
                    foreach ($opts as $str_name => $time_offset) {
                        if ($oldest_upload_time > time() - 86400 * $time_offset) {
                            break;
                        }
                        $main .= '<option value="' . $time_offset . '">' . $str_name . '</option>';
                    }
                    $main .= '<option value="all">All Results</option>';
                    $main .= '</select>';
                    $main .= '</p><hr />';
                }
                $main .= '<p><strong>' . $num_results . ' Test Results Available For This Schedule.</strong></p>';
            }
            echo phoromatic_webui_main($main, phoromatic_webui_right_panel_logged_in());
            echo phoromatic_webui_footer();
            return;
        }
        $main = '<h1>Test Schedules</h1>
			<p>Test schedules are used for tests that are intended to be run on a recurring basis -- either daily or other defined time period -- or whenever a trigger/event occurs, like a new Git commit to a software repository being tracked. Test schedules can be run on any given system(s)/group(s) and can be later edited.</p>';
        if (!PHOROMATIC_USER_IS_VIEWER) {
            $main .= '
				<hr />
				<h2>Create A Schedule</h2>
				<p><a href="?sched">Create a schedule</a> followed by adding tests/suites to run for that schedule on the selected systems.</p>';
        }
        $main .= '<hr /><h2>Current Schedules</h2>';
        $main .= '<div class="pts_phoromatic_info_box_area">
					<ul>
						<li><h1>Active Test Schedules</h1></li>';
        $stmt = phoromatic_server::$db->prepare('SELECT Title, ScheduleID, Description, RunTargetSystems, RunTargetGroups, RunAt, ActiveOn FROM phoromatic_schedules WHERE AccountID = :account_id AND State >= 1 ORDER BY Title ASC');
        $stmt->bindValue(':account_id', $_SESSION['AccountID']);
        $result = $stmt->execute();
        $row = $result->fetchArray();
        if ($row == false) {
            $main .= '<li class="light" style="text-align: center;">No Schedules Found</li>';
        } else {
            do {
                $stmt_tests = phoromatic_server::$db->prepare('SELECT COUNT(*) AS TestCount FROM phoromatic_schedules_tests WHERE AccountID = :account_id AND ScheduleID = :schedule_id ORDER BY TestProfile ASC');
                $stmt_tests->bindValue(':account_id', $_SESSION['AccountID']);
                $stmt_tests->bindValue(':schedule_id', $row['ScheduleID']);
                $result_tests = $stmt_tests->execute();
                $row_tests = $result_tests->fetchArray();
                $test_count = !empty($row_tests) ? $row_tests['TestCount'] : 0;
                $group_count = empty($row['RunTargetGroups']) ? 0 : count(explode(',', $row['RunTargetGroups']));
                $main .= '<a href="?schedules/' . $row['ScheduleID'] . '"><li>' . $row['Title'] . '<br /><table><tr><td>' . pts_strings::plural_handler(count(phoromatic_server::systems_associated_with_schedule($_SESSION['AccountID'], $row['ScheduleID'])), 'System') . '</td><td>' . pts_strings::plural_handler($group_count, 'Group') . '</td><td>' . pts_strings::plural_handler($test_count, 'Test') . '</td><td>' . pts_strings::plural_handler(phoromatic_results_for_schedule($row['ScheduleID']), 'Result') . ' Total</td><td>' . pts_strings::plural_handler(phoromatic_results_for_schedule($row['ScheduleID'], 'TODAY'), 'Result') . ' Today</td><td><strong>' . phoromatic_schedule_activeon_string($row['ActiveOn'], $row['RunAt']) . '</strong></td></tr></table></li></a>';
            } while ($row = $result->fetchArray());
        }
        $main .= '</ul>
			</div>';
        $main .= '<hr /><h2>Schedule Overview</h2>';
        $week = array('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday');
        foreach ($week as $i => $day) {
            $stmt = phoromatic_server::$db->prepare('SELECT Title, ScheduleID, RunAt, RunTargetGroups, RunTargetSystems FROM phoromatic_schedules WHERE AccountID = :account_id AND State >= 1 AND ActiveOn LIKE :active_on ORDER BY RunAt,ActiveOn,Title ASC');
            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
            $stmt->bindValue(':active_on', '%' . $i . '%');
            $result = $stmt->execute();
            $has_matched = false;
            while ($row = $result->fetchArray()) {
                if (!$has_matched) {
                    $main .= '<h3>' . $day . '</h3>' . PHP_EOL . '<p>';
                    $has_matched = true;
                }
                $main .= '<em>' . $row['RunAt'] . '</em> <a href="?schedules/' . $row['ScheduleID'] . '">' . $row['Title'] . '</a>';
                //$main .= $row['RunTargetSystems'] . ' ' . $row['RunTargetGroups'];
                $main .= '<br />';
            }
            if ($has_matched) {
                $main .= '</p>' . PHP_EOL;
            }
        }
        $main .= '<div class="pts_phoromatic_info_box_area">
					<ul>
						<li><h1>Deactivated Test Schedules</h1></li>';
        $stmt = phoromatic_server::$db->prepare('SELECT Title, ScheduleID, Description, RunTargetSystems, RunTargetGroups, RunAt, ActiveOn FROM phoromatic_schedules WHERE AccountID = :account_id AND State < 1 ORDER BY Title ASC');
        $stmt->bindValue(':account_id', $_SESSION['AccountID']);
        $result = $stmt->execute();
        $row = $result->fetchArray();
        if ($row == false) {
            $main .= '<li class="light" style="text-align: center;">No Schedules Found</li>';
        } else {
            do {
                $stmt_tests = phoromatic_server::$db->prepare('SELECT COUNT(*) AS TestCount FROM phoromatic_schedules_tests WHERE AccountID = :account_id AND ScheduleID = :schedule_id ORDER BY TestProfile ASC');
                $stmt_tests->bindValue(':account_id', $_SESSION['AccountID']);
                $stmt_tests->bindValue(':schedule_id', $row['ScheduleID']);
                $result_tests = $stmt_tests->execute();
                $row_tests = $result_tests->fetchArray();
                $test_count = !empty($row_tests) ? $row_tests['TestCount'] : 0;
                $group_count = empty($row['RunTargetGroups']) ? 0 : count(explode(',', $row['RunTargetGroups']));
                $main .= '<a href="?schedules/' . $row['ScheduleID'] . '"><li>' . $row['Title'] . '<br /><table><tr><td>' . pts_strings::plural_handler(count(phoromatic_server::systems_associated_with_schedule($_SESSION['AccountID'], $row['ScheduleID'])), 'System') . '</td><td>' . pts_strings::plural_handler($group_count, 'Group') . '</td><td>' . pts_strings::plural_handler($test_count, 'Test') . '</td><td>' . pts_strings::plural_handler(phoromatic_results_for_schedule($row['ScheduleID']), 'Result') . ' Total</td><td>' . pts_strings::plural_handler(phoromatic_results_for_schedule($row['ScheduleID'], 'TODAY'), 'Result') . ' Today</td><td><strong>' . phoromatic_schedule_activeon_string($row['ActiveOn'], $row['RunAt']) . '</strong></td></tr></table></li></a>';
            } while ($row = $result->fetchArray());
        }
        $main .= '</ul>
			</div>';
        echo '<div id="pts_phoromatic_main_area">' . $main . '</div>';
        echo phoromatic_webui_footer();
    }
    public static function render_page_process($PATH)
    {
        if ($_SESSION['AdminLevel'] != -40) {
            header('Location: /?main');
        }
        $main = null;
        if (isset($_POST['disable_user'])) {
            $stmt = phoromatic_server::$db->prepare('UPDATE phoromatic_users SET AdminLevel = (AdminLevel * -1) WHERE UserName = :user_name');
            $stmt->bindValue(':user_name', $_POST['disable_user']);
            $result = $stmt->execute();
            $main .= '<h2>Disabled Account: ' . $_POST['disable_user'] . '</h2>';
        } else {
            if (isset($_POST['register_username']) && isset($_POST['register_password']) && isset($_POST['register_password_confirm']) && isset($_POST['register_email'])) {
                $new_account = create_new_phoromatic_account($_POST['register_username'], $_POST['register_password'], $_POST['register_password_confirm'], $_POST['register_email'], isset($_POST['seed_accountid']) ? $_POST['seed_accountid'] : null);
            }
        }
        $main .= '<h1>Phoromatic Server Administration</h1>';
        $main .= '<hr /><h2>Server Information</h2>';
        $main .= '<p><strong>HTTP Server Port:</strong> ' . getenv('PTS_WEB_PORT') . '<br /><strong>WebSocket Server Port:</strong> ' . getenv('PTS_WEBSOCKET_PORT') . '<br /><strong>Phoromatic Server Path:</strong> ' . phoromatic_server::phoromatic_path() . '<br /><strong>Configuration File:</strong>: ' . pts_config::get_config_file_location() . '</p>';
        $main .= '<hr /><h2>Statistics</h2>';
        $stmt = phoromatic_server::$db->prepare('SELECT COUNT(Title) AS SystemCount FROM phoromatic_systems WHERE State >= 0');
        $result = $stmt->execute();
        $row = $result->fetchArray();
        $stats['Total System Count'] = $row['SystemCount'];
        $stmt = phoromatic_server::$db->prepare('SELECT COUNT(Title) AS ScheduleCount FROM phoromatic_schedules WHERE State >= 1');
        $result = $stmt->execute();
        $row = $result->fetchArray();
        $stats['Total Schedule Count'] = $row['ScheduleCount'];
        $stmt = phoromatic_server::$db->prepare('SELECT COUNT(UploadID) AS ResultCount FROM phoromatic_results');
        $result = $stmt->execute();
        $row = $result->fetchArray();
        $stats['Total Result Count'] = $row['ResultCount'];
        $stmt = phoromatic_server::$db->prepare('SELECT COUNT(ActivityTime) AS ActivityCount FROM phoromatic_activity_stream');
        $stmt->bindValue(':today_date', date('Y-m-d') . '%');
        $result = $stmt->execute();
        $row = $result->fetchArray();
        $stats['Total Activity Count'] = $row['ActivityCount'];
        $main .= '<p>';
        foreach ($stats as $what => $c) {
            $main .= '<strong>' . $what . ':</strong> ' . $c . '<br />';
        }
        $main .= '<hr /><h2>Account Topology</h2>';
        $stmt = phoromatic_server::$db->prepare('SELECT * FROM phoromatic_users ORDER BY AccountID,AdminLevel ASC');
        $result = $stmt->execute();
        $plevel = -1;
        $user_list = array();
        while ($row = $result->fetchArray()) {
            switch ($row['AdminLevel']) {
                case 1:
                    $level = 'Group Administrator';
                    $offset = null;
                    break;
                case 2:
                    $level = 'Administrator';
                    $offset = str_repeat('-', 10);
                    break;
                case 3:
                    $level = 'Power User';
                    $offset = str_repeat('-', 20);
                    break;
                case 10:
                    $level = 'Viewer';
                    $offset = str_repeat('-', 30);
                    break;
                default:
                    if ($row['AdminLevel'] < 1) {
                        $level = 'Disabled';
                    } else {
                        $level = 'Unknown';
                    }
                    $offset = null;
                    break;
            }
            if ($row['AdminLevel'] == 1) {
                if ($plevel != -1) {
                    $main .= '</p>';
                }
                $main .= '<p>';
            }
            $main .= $offset . ' <strong>' . $row['UserName'] . '</strong> (<em>' . $level . '</em>) <strong>Created On:</strong> ' . phoromatic_user_friendly_timedate($row['CreatedOn']) . ' <strong>Last Log-In:</strong> ' . ($row['LastLogin'] != null ? phoromatic_user_friendly_timedate($row['LastLogin']) : 'N/A') . ($row['AdminLevel'] == 1 ? ' [<strong>ACCOUNT ID:</strong> ' . $row['AccountID'] . ']' : null) . '<br />';
            $plevel = $row['AdminLevel'];
            $user_list[$row['UserName']] = $row['AdminLevel'];
        }
        if ($plevel != -1) {
            $main .= '</p>';
        }
        $main .= '<hr /><h2>Disable Account</h2>';
        $main .= '<form action="' . $_SERVER['REQUEST_URI'] . '" name="disable_user" id="disable_user" method="post"><p><select name="disable_user">';
        foreach ($user_list as $user_name => $user_level) {
            if ($user_level > 0) {
                $main .= '<option value="' . $user_name . '">' . $user_name . '</option>';
            }
        }
        $main .= '</select></p><p><input name="submit" value="Disable User" type="submit" /></p></form>';
        $main .= '<hr /><h2>Create New Account Group</h2>';
        $main .= '<form name="register_form" id="register_form" action="?admin" method="post" onsubmit="return phoromatic_initial_registration(this);">
		<h3>Username</h3>
		<p><input type="text" name="register_username" /> <sup>1</sup></p>
		<h3>Password</h3>
		<p><input type="password" name="register_password" /> <sup>2</sup></p>
		<h3>Confirm Password</h3>
		<p><input type="password" name="register_password_confirm" /></p>
		<h3>Email</h3>
		<p><input type="text" name="register_email" /> <sup>3</sup></p>
		<h3>Account ID</h3>
		<p><input type="text" name="seed_accountid" /> <sup>4</sup></p>
		<p><input type="submit" value="Create Account" /></p>
		</form>
		<p style="font-size: 11px;"><sup>1</sup> Usernames shall be at least four characters long, not contain any spaces, and only be composed of normal ASCII characters.<br />
		<sup>2</sup> Passwords shall be at least six characters long.<br />
		<sup>3</sup> A valid email address is required for notifications, password reset, and other verification purposes.<br />
		<sup>4</sup> The account ID field is optional and is used to pre-seed the account identifier for advanced purposes. The field must be six characters. Leave this field blank if you are unsure.<br />
						</p>';
        //
        $server_log = explode(PHP_EOL, file_get_contents(getenv('PTS_PHOROMATIC_LOG_LOCATION')));
        foreach ($server_log as $i => $line_item) {
            if (strpos($line_item, '[200]') !== false || strpos($line_item, '[302]') !== false) {
                unset($server_log[$i]);
            }
        }
        $server_log = implode(PHP_EOL, $server_log);
        $main .= '<hr /><h2>Phoromatic Server Log</h2>';
        $main .= '<p><textarea style="width: 80%; height: 400px;">' . $server_log . '</textarea></p>';
        echo phoromatic_webui_header_logged_in();
        echo phoromatic_webui_main($main, phoromatic_webui_right_panel_logged_in());
        echo phoromatic_webui_footer();
    }
    public static function render_page_process($PATH)
    {
        if (PHOROMATIC_USER_IS_VIEWER) {
            return;
        }
        $is_new = true;
        if (!empty($PATH[0]) && is_numeric($PATH[0])) {
            $stmt = phoromatic_server::$db->prepare('SELECT * FROM phoromatic_schedules WHERE AccountID = :account_id AND ScheduleID = :schedule_id');
            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
            $stmt->bindValue(':schedule_id', $PATH[0]);
            $result = $stmt->execute();
            $e_schedule = $result->fetchArray();
            if (!empty($e_schedule)) {
                $is_new = false;
            }
        }
        if (isset($_POST['schedule_title']) && !empty($_POST['schedule_title'])) {
            $title = phoromatic_get_posted_var('schedule_title');
            $description = phoromatic_get_posted_var('schedule_description');
            $pre_install_context = phoromatic_get_posted_var('pre_install_set_context');
            $post_install_context = phoromatic_get_posted_var('post_install_set_context');
            $pre_run_context = phoromatic_get_posted_var('pre_run_set_context');
            $post_run_context = phoromatic_get_posted_var('post_run_set_context');
            $system_all = phoromatic_get_posted_var('system_all');
            $run_target_systems = phoromatic_get_posted_var('run_on_systems', array());
            $run_target_groups = phoromatic_get_posted_var('run_on_groups', array());
            if (!is_array($run_target_systems)) {
                $run_target_systems = array();
            }
            if (!is_array($run_target_groups)) {
                $run_target_groups = array();
            }
            $run_target_systems = implode(',', $run_target_systems);
            $run_target_groups = implode(',', $run_target_groups);
            $schedule_hour = phoromatic_get_posted_var('schedule_hour');
            $schedule_minute = phoromatic_get_posted_var('schedule_minute');
            $days_active = phoromatic_get_posted_var('days_active');
            $context_files = array('SetContextPreInstall' => 'pre_install_set_context', 'SetContextPostInstall' => 'post_install_set_context', 'SetContextPreRun' => 'pre_run_set_context', 'SetContextPostRun' => 'post_run_set_context');
            foreach ($context_files as $i => $context) {
                ${$context} = $is_new ? null : $e_schedule[$i];
            }
            foreach ($context_files as $context) {
                ${$context} = null;
                if ($_FILES[$context]['error'] == 0 && $_FILES[$context]['size'] > 0) {
                    $sha1_hash = sha1_file($_FILES[$context]['tmp_name']);
                    if (!is_file(phoromatic_server::phoromatic_account_path($_SESSION['AccountID']) . 'context_' . $sha1_hash)) {
                        move_uploaded_file($_FILES[$context]['tmp_name'], phoromatic_server::phoromatic_account_path($_SESSION['AccountID']) . 'context_' . $sha1_hash);
                    }
                    ${$context} = $sha1_hash;
                }
            }
            // TODO XXX: Validation of input
            // Need a unique schedule ID
            if ($is_new) {
                do {
                    $schedule_id = rand(10, 9999);
                    $matching_schedules = phoromatic_server::$db->querySingle('SELECT ScheduleID FROM phoromatic_schedules WHERE AccountID = \'' . $_SESSION['AccountID'] . '\' AND ScheduleID = \'' . $schedule_id . '\'');
                } while (!empty($matching_schedules));
                // Need a unique public ID
                do {
                    $public_key = pts_strings::random_characters(12, true);
                    $matching_schedules = phoromatic_server::$db->querySingle('SELECT ScheduleID FROM phoromatic_schedules WHERE AccountID = \'' . $_SESSION['AccountID'] . '\' AND PublicKey = \'' . $public_key . '\'');
                } while (!empty($matching_schedules));
            } else {
                $schedule_id = $e_schedule['ScheduleID'];
                $public_key = $e_schedule['PublicKey'];
            }
            // Add schedule
            $stmt = phoromatic_server::$db->prepare('INSERT OR REPLACE INTO phoromatic_schedules (AccountID, ScheduleID, Title, Description, State, ActiveOn, RunAt, SetContextPreInstall, SetContextPostInstall, SetContextPreRun, SetContextPostRun, LastModifiedBy, LastModifiedOn, PublicKey, RunTargetGroups, RunTargetSystems) VALUES (:account_id, :schedule_id, :title, :description, :state, :active_on, :run_at, :context_pre_install, :context_post_install, :context_pre_run, :context_post_run, :modified_by, :modified_on, :public_key, :run_target_groups, :run_target_systems)');
            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
            $stmt->bindValue(':schedule_id', $schedule_id);
            $stmt->bindValue(':title', $title);
            $stmt->bindValue(':description', $description);
            $stmt->bindValue(':state', 1);
            $stmt->bindValue(':active_on', implode(',', $days_active));
            $stmt->bindValue(':run_at', $schedule_hour . '.' . $schedule_minute);
            $stmt->bindValue(':context_pre_install', $pre_install_set_context);
            $stmt->bindValue(':context_post_install', $post_install_set_context);
            $stmt->bindValue(':context_pre_run', $pre_run_set_context);
            $stmt->bindValue(':context_post_run', $post_run_set_context);
            $stmt->bindValue(':modified_by', $_SESSION['UserName']);
            $stmt->bindValue(':modified_on', phoromatic_server::current_time());
            $stmt->bindValue(':public_key', $public_key);
            $stmt->bindValue(':run_target_groups', $run_target_groups);
            $stmt->bindValue(':run_target_systems', $run_target_systems);
            $result = $stmt->execute();
            phoromatic_add_activity_stream_event('schedule', $schedule_id, $is_new ? 'added' : 'modified');
            if ($result) {
                header('Location: ?schedules/' . $schedule_id);
            }
        }
        echo phoromatic_webui_header_logged_in();
        $main = '
		<hr />
		<h2>' . ($is_new ? 'Create' : 'Edit') . ' A Schedule</h2>
		<p>A test schedule is used to facilitate automatically running a set of test(s)/suite(s) on either a routine timed basis or whenever triggered by an external script or process, e.g. Git/VCS commit, manually triggered, etc.</p>';
        $main .= '<form action="' . $_SERVER['REQUEST_URI'] . '" name="add_test" id="add_test" method="post" enctype="multipart/form-data" onsubmit="return validate_schedule();">
		<h3>Title:</h3>
		<p><input type="text" name="schedule_title" value="' . (!$is_new ? $e_schedule['Title'] : null) . '" /></p>
		<h3><sup>1</sup> Pre-Install Set Context Script:</h3>
		<p><input type="file" name="pre_install_set_context" /></p>
		<h3><sup>1</sup> Post-Install Set Context Script:</h3>
		<p><input type="file" name="post_install_set_context" /></p>
		<h3><sup>1</sup> Pre-Run Set Context Script:</h3>
		<p><input type="file" name="pre_run_set_context" /></p>
		<h3><sup>1</sup>Post-Run Set Context Script:</h3>
		<p><input type="file" name="post_run_set_context" /></p>
		<h3>System Targets:</h3>
		<p>';
        $stmt = phoromatic_server::$db->prepare('SELECT Title, SystemID FROM phoromatic_systems WHERE AccountID = :account_id AND State >= 0 ORDER BY Title ASC');
        $stmt->bindValue(':account_id', $_SESSION['AccountID']);
        $result = $stmt->execute();
        if (!$is_new) {
            $e_schedule['RunTargetSystems'] = explode(',', $e_schedule['RunTargetSystems']);
            $e_schedule['RunTargetGroups'] = explode(',', $e_schedule['RunTargetGroups']);
        }
        if ($row = $result->fetchArray()) {
            $main .= '<h4>Systems: ';
            do {
                $main .= '<input type="checkbox" name="run_on_systems[]" value="' . $row['SystemID'] . '" ' . (!$is_new && in_array($row['SystemID'], $e_schedule['RunTargetSystems']) ? 'checked="checked" ' : null) . '/> ' . $row['Title'] . ' ';
            } while ($row = $result->fetchArray());
            $main .= '</h4>';
        }
        $stmt = phoromatic_server::$db->prepare('SELECT GroupName FROM phoromatic_groups WHERE AccountID = :account_id ORDER BY GroupName ASC');
        $stmt->bindValue(':account_id', $_SESSION['AccountID']);
        $result = $stmt->execute();
        if ($row = $result->fetchArray()) {
            $main .= '<h4>Groups: ';
            do {
                $main .= '<input type="checkbox" name="run_on_groups[]" value="' . $row['GroupName'] . '" ' . (!$is_new && in_array($row['GroupName'], $e_schedule['RunTargetGroups']) ? 'checked="checked" ' : null) . '/> ' . $row['GroupName'] . ' ';
            } while ($row = $result->fetchArray());
            $main .= '</h4>';
        }
        $main .= '</p>
		<h3>Description:</h3>
		<p><textarea name="schedule_description" id="schedule_description" cols="50" rows="3">' . (!$is_new ? $e_schedule['Description'] : null) . '</textarea></p>
		<table class="pts_phoromatic_schedule_type">
<tr>
  <td><h3>Time-Based Testing</h3><em>Time-based testing allows tests to automatically commence at a given time on a defined cycle each day/week. This option is primarly aimed for those wishing to run a set of benchmarks every morning or night or at another defined period.</em></td>
  <td><h3>Run Time:</h3>
			<p><select name="schedule_hour" id="schedule_hour">';
        if (!$is_new) {
            $run_at = explode('.', $e_schedule['RunAt']);
            $days_active = !empty($e_schedule['ActiveOn']) ? explode(',', $e_schedule['ActiveOn']) : array();
        }
        for ($i = 0; $i <= 23; $i++) {
            $i_f = strlen($i) == 1 ? '0' . $i : $i;
            $main .= '<option value="' . $i_f . '"' . (!$is_new && $run_at[0] == $i ? 'selected="selected" ' : null) . '>' . $i_f . '</option>';
        }
        $main .= '</select> <select name="schedule_minute" id="schedule_minute">';
        for ($i = 0; $i < 60; $i += 10) {
            $i_f = strlen($i) == 1 ? '0' . $i : $i;
            $main .= '<option value="' . $i_f . '"' . (!$is_new && $run_at[1] == $i ? 'selected="selected" ' : null) . '>' . $i_f . '</option>';
        }
        $main .= '</select><h3>Active On:</h3><p>';
        $week = array('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday');
        foreach ($week as $index => $day) {
            $main .= '<input type="checkbox" name="days_active[]" value="' . $index . '"' . (!$is_new && in_array($index, $days_active) ? 'checked="checked" ' : null) . '/> ' . $day;
        }
        $main .= '</p></td>
</tr>
<tr>
  <td><h3>Trigger-Based Testing</h3><em>To carry out trigger-based testing, you can simply have an external process/script trigger (&quot;ping&quot;) a specialized URL whenever an event occurs to commence a new round of testing. This is the most customizable approach to having Phoromatic run tests on a system if you wish to have it occur whenever a Git/SVN commit takes place or other operations.</em></td>
  <td><h3>Once creating the test schedule there will be a specialized URL you can use for &quot;pinging&quot; where you can pass it a Git commit hash, SVN revision number, date, or other unique identifiers to externally trigger the test schedules and systems to begin testing. This custom trigger is passed to any of the used context scripts for setting up the system in an appropriate state.</h3></td>
</tr>
<tr>
  <td><h3>One-Time / Manual Testing</h3><em>Carrying out Phoromatic-controlled benchmark on no routine schedule, similar to the trigger-based testing.</em></td>
  <td><h3>If you wish to only run a set of tests once on a given system or to do so seldom with the same set of tests, simply proceed with creating the test schedule without setting any run time / active days. When going to the web page for this test schedule there will be a button to trigger the tests to run on all affected systems.</h3></td>
</tr>
</table>

			<p><sup>1</sup> <em>Indicates optional field.</em></p>
			<p align="right"><input name="submit" value="' . ($is_new ? 'Create' : 'Edit') . ' Schedule" type="submit" onclick="return pts_rmm_validate_schedule();" /></p>
			</form>';
        echo phoromatic_webui_main($main, phoromatic_webui_right_panel_logged_in());
        echo phoromatic_webui_footer();
    }
    public static function render_page_process($PATH)
    {
        if ($_SESSION['AdminLevel'] != -40) {
            header('Location: /?main');
        }
        if (isset($PATH[0]) && isset($PATH[1])) {
            switch ($PATH[0]) {
                case 'delete':
                    if ($PATH[1] == 'result') {
                        $pprids = explode(',', $PATH[2]);
                        foreach ($pprids as $pprid) {
                            $stmt = phoromatic_server::$db->prepare('DELETE FROM phoromatic_results WHERE PPRID = :pprid');
                            $stmt->bindValue(':pprid', $pprid);
                            $result = $stmt->execute();
                        }
                        /*						$stmt = phoromatic_server::$db->prepare('DELETE FROM phoromatic_results_results WHERE AccountID = :account_id AND UploadID = :upload_id');
                        						$stmt->bindValue(':account_id', $PATH[2]);
                        						$stmt->bindValue(':upload_id', $PATH[3]);
                        						$result = $stmt->execute();
                        						$stmt = phoromatic_server::$db->prepare('DELETE FROM phoromatic_results_systems WHERE AccountID = :account_id AND UploadID = :upload_id');
                        						$stmt->bindValue(':account_id', $PATH[2]);
                        						$stmt->bindValue(':upload_id', $PATH[3]);
                        						$result = $stmt->execute();
                        
                        						$result_dir = phoromatic_server::phoromatic_account_result_path($PATH[2], $PATH[3]);
                        						if(is_dir($result_dir))
                        						{
                        							pts_file_io::delete($result_dir, null, true);
                        						}
                        */
                    } else {
                        if ($PATH[1] == 'schedule') {
                            $stmt = phoromatic_server::$db->prepare('DELETE FROM phoromatic_schedules WHERE AccountID = :account_id AND ScheduleID = :schedule_id');
                            $stmt->bindValue(':account_id', $PATH[2]);
                            $stmt->bindValue(':schedule_id', $PATH[3]);
                            $result = $stmt->execute();
                        } else {
                            if ($PATH[1] == 'system') {
                                $stmt = phoromatic_server::$db->prepare('DELETE FROM phoromatic_systems WHERE AccountID = :account_id AND SystemID = :system_id');
                                $stmt->bindValue(':account_id', $PATH[2]);
                                $stmt->bindValue(':system_id', $PATH[3]);
                                $result = $stmt->execute();
                            } else {
                                if ($PATH[1] == 'ticket') {
                                    $stmt = phoromatic_server::$db->prepare('DELETE FROM phoromatic_benchmark_tickets WHERE AccountID = :account_id AND TicketID = :ticket_id');
                                    $stmt->bindValue(':account_id', $PATH[2]);
                                    $stmt->bindValue(':ticket_id', $PATH[3]);
                                    $result = $stmt->execute();
                                } else {
                                    if ($PATH[1] == 'trigger') {
                                        $stmt = phoromatic_server::$db->prepare('DELETE FROM phoromatic_schedules_triggers WHERE AccountID = :account_id AND ScheduleID = :schedule_id AND Trigger = :trigger');
                                        $stmt->bindValue(':account_id', $PATH[2]);
                                        $stmt->bindValue(':schedule_id', $PATH[3]);
                                        $stmt->bindValue(':trigger', $PATH[4]);
                                        $result = $stmt->execute();
                                        var_dump($result);
                                    }
                                }
                            }
                        }
                    }
                    break;
            }
        }
        $main = '<h1>Phoromatic Server Data</h1>';
        $main .= '<h1>Test Results</h1>';
        $main .= '<a onclick="javascript:phoromatic_generate_comparison(\'public.php?ut=\');"><div id="phoromatic_result_compare_info_box" style="background: #1976d2; border: 1px solid #000;"></div></a> <a onclick="javascript:phoromatic_delete_results(\'?admin_data/delete/result/\'); return false;"><div id="phoromatic_result_delete_box" style="background: #1976d2; border: 1px solid #000;">Delete Selected Results</div></a>';
        $main .= '<div class="pts_phoromatic_info_box_area">';
        $main .= '<div style="height: 500px;"><ul style="max-height: 100%;"><li><h1>Recent Test Results</h1></li>';
        $stmt = phoromatic_server::$db->prepare('SELECT Title, SystemID, ScheduleID, PPRID, UploadTime, TimesViewed, AccountID, UploadID FROM phoromatic_results ORDER BY UploadTime DESC');
        $test_result_result = $stmt->execute();
        $results = 0;
        while ($test_result_row = $test_result_result->fetchArray()) {
            $main .= '<a onclick=""><li id="result_select_' . $test_result_row['PPRID'] . '"><input type="checkbox" id="result_compare_checkbox_' . $test_result_row['PPRID'] . '" onclick="javascript:phoromatic_checkbox_toggle_result_comparison(\'' . $test_result_row['PPRID'] . '\');" onchange="return false;"></input> <span onclick="javascript:phoromatic_window_redirect(\'public.php?ut=' . $test_result_row['PPRID'] . '\');">' . $test_result_row['Title'] . '</span><br /><table><tr><td>' . phoromatic_system_id_to_name($test_result_row['SystemID'], $test_result_row['AccountID']) . '</td><td>' . phoromatic_user_friendly_timedate($test_result_row['UploadTime']) . '</td><td>' . $test_result_row['TimesViewed'] . ' Times Viewed</td></table></li></a>';
            $results++;
        }
        if ($results == 0) {
            $main .= '<li class="light" style="text-align: center;">No Results Found</li>';
        }
        $main .= '</ul></div>';
        $main .= '</div>';
        $main .= '<hr /><h1>Schedules</h1>';
        $main .= '<h2>Active Test Schedules</h2>';
        $main .= '<div class="pts_phoromatic_info_box_area">
				<ul>
					<li><h1>Active Test Schedules</h1></li>';
        $stmt = phoromatic_server::$db->prepare('SELECT Title, ScheduleID, Description, RunTargetSystems, RunTargetGroups, RunAt, ActiveOn, AccountID FROM phoromatic_schedules WHERE State >= 1 ORDER BY Title ASC');
        $result = $stmt->execute();
        $row = $result->fetchArray();
        if ($row == false) {
            $main .= '<li class="light" style="text-align: center;">No Schedules Found</li>';
        } else {
            do {
                $main .= '<a onclick=""><li>' . $row['Title'] . '<br /><table><tr><td>' . phoromatic_account_id_to_group_name($row['AccountID']) . '</td><td>' . pts_strings::plural_handler(count(phoromatic_server::systems_associated_with_schedule($row['AccountID'], $row['ScheduleID'])), 'System') . '</td><td><strong>' . phoromatic_schedule_activeon_string($row['ActiveOn'], $row['RunAt']) . '</strong></td><td><a onclick="return confirm(\'Permanently remove this schedule?\');" href="/?admin_data/delete/schedule/' . $row['AccountID'] . '/' . $row['ScheduleID'] . '">Permanently Remove</a></td></tr></table></li></a>';
            } while ($row = $result->fetchArray());
        }
        $main .= '</ul></div>';
        $main .= '<hr /><h2>Inactive Test Schedules</h2>';
        $main .= '<div class="pts_phoromatic_info_box_area">
				<ul>
					<li><h1>Active Test Schedules</h1></li>';
        $stmt = phoromatic_server::$db->prepare('SELECT Title, ScheduleID, Description, RunTargetSystems, RunTargetGroups, RunAt, ActiveOn, AccountID FROM phoromatic_schedules WHERE State < 1 ORDER BY Title ASC');
        $result = $stmt->execute();
        $row = $result->fetchArray();
        if ($row == false) {
            $main .= '<li class="light" style="text-align: center;">No Schedules Found</li>';
        } else {
            do {
                $main .= '<a onclick=""><li>' . $row['Title'] . '<br /><table><tr><td>' . phoromatic_account_id_to_group_name($row['AccountID']) . '</td><td>' . pts_strings::plural_handler(count(phoromatic_server::systems_associated_with_schedule($row['AccountID'], $row['ScheduleID'])), 'System') . '</td><td><strong>' . phoromatic_schedule_activeon_string($row['ActiveOn'], $row['RunAt']) . '</strong></td><td><a onclick="return confirm(\'Permanently remove this schedule?\');" href="/?admin_data/delete/schedule/' . $row['AccountID'] . '/' . $row['ScheduleID'] . '">Permanently Remove</a></td></tr></table></li></a>';
            } while ($row = $result->fetchArray());
        }
        $main .= '</ul></div>';
        $main .= '<hr /><h2>Schedule Triggers</h2>';
        $main .= '<div class="pts_phoromatic_info_box_area">
				<ul>
					<li><h1>Triggers</h1></li>';
        $stmt = phoromatic_server::$db->prepare('SELECT Trigger, TriggeredOn, AccountID, ScheduleID FROM phoromatic_schedules_triggers ORDER BY TriggeredOn DESC');
        $result = $stmt->execute();
        $row = $result->fetchArray();
        if ($row == false) {
            $main .= '<li class="light" style="text-align: center;">No Triggers Found</li>';
        } else {
            do {
                $main .= '<a onclick=""><li>' . $row['Trigger'] . '<br /><table><tr><td>' . $row['TriggeredOn'] . '</td><td>' . phoromatic_account_id_to_group_name($row['AccountID']) . '</td><td><a onclick="return confirm(\'Permanently remove this trigger?\');" href="/?admin_data/delete/trigger/' . $row['AccountID'] . '/' . $row['ScheduleID'] . '/' . $row['Trigger'] . '">Permanently Remove</a></td></tr></table></li></a>';
            } while ($row = $result->fetchArray());
        }
        $main .= '</ul></div>';
        $main .= '<hr /><h1>Systems</h1>
			<h2>Active Systems</h2>
			<div class="pts_phoromatic_info_box_area">

					<ul>
						<li><h1>Active Systems</h1></li>';
        $stmt = phoromatic_server::$db->prepare('SELECT Title, SystemID, LocalIP, CurrentTask, LastCommunication, EstimatedTimeForTask, TaskPercentComplete, AccountID FROM phoromatic_systems WHERE State >= 0 ORDER BY LastCommunication DESC');
        $result = $stmt->execute();
        $row = $result->fetchArray();
        $active_system_count = 0;
        if ($row == false) {
            $main .= '<li class="light" style="text-align: center;">No Systems Found</li>';
        } else {
            do {
                $main .= '<a onclick=""><li>' . $row['Title'] . '<br /><table><tr><td>' . phoromatic_account_id_to_group_name($row['AccountID']) . '</td><td>' . $row['LocalIP'] . '</td><td><strong>' . $row['CurrentTask'] . '</strong></td><td><strong>Last Communication:</strong> ' . date('j F Y H:i', strtotime($row['LastCommunication'])) . '</td><td><a onclick="return confirm(\'Permanently remove this system?\');" href="/?admin_data/delete/system/' . $row['AccountID'] . '/' . $row['SystemID'] . '">Permanently Remove</a></td></tr></table></li></a>';
                $active_system_count++;
            } while ($row = $result->fetchArray());
        }
        $main .= '</ul></div>';
        $main .= '<h2>Inactive Systems</h2>
			<div class="pts_phoromatic_info_box_area">

					<ul>
						<li><h1>Inactive Systems</h1></li>';
        $stmt = phoromatic_server::$db->prepare('SELECT Title, SystemID, LocalIP, CurrentTask, LastCommunication, EstimatedTimeForTask, TaskPercentComplete, AccountID FROM phoromatic_systems WHERE State < 0 ORDER BY LastCommunication DESC');
        $result = $stmt->execute();
        $row = $result->fetchArray();
        $active_system_count = 0;
        if ($row == false) {
            $main .= '<li class="light" style="text-align: center;">No Systems Found</li>';
        } else {
            do {
                $main .= '<a onclick=""><li>' . $row['Title'] . '<br /><table><tr><td>' . phoromatic_account_id_to_group_name($row['AccountID']) . '</td><td>' . $row['LocalIP'] . '</td><td><strong>' . $row['CurrentTask'] . '</strong></td><td><strong>Last Communication:</strong> ' . date('j F Y H:i', strtotime($row['LastCommunication'])) . '</td><td><a onclick="return confirm(\'Permanently remove this system?\');" href="/?admin_data/delete/system/' . $row['AccountID'] . '/' . $row['SystemID'] . '">Permanently Remove</a></td></tr></table></li></a>';
                $active_system_count++;
            } while ($row = $result->fetchArray());
        }
        $main .= '</ul></div>';
        $stmt = phoromatic_server::$db->prepare('SELECT * FROM phoromatic_benchmark_tickets ORDER BY TicketIssueTime DESC');
        $result = $stmt->execute();
        $main .= '<hr /><h1>Benchmark Tickets</h1>
			<div class="pts_phoromatic_info_box_area"><ul><li><h1>Tickets</h1></li>';
        while ($result && ($row = $result->fetchArray())) {
            $main .= '<a onclick=""><li>' . $row['Title'] . '<br /><table><tr><td><a onclick="return confirm(\'Permanently remove this system?\');" href="/?admin_data/delete/ticket/' . $row['AccountID'] . '/' . $row['TicketID'] . '">Permanently Remove</a></td></tr></table></li></a>';
        }
        $main .= '</ul></div>';
        echo phoromatic_webui_header_logged_in();
        echo phoromatic_webui_main($main, phoromatic_webui_right_panel_logged_in());
        echo phoromatic_webui_footer();
    }
    public static function render_page_process($PATH)
    {
        if (PHOROMATIC_USER_IS_VIEWER) {
            return;
        }
        $is_new = true;
        if (!empty($PATH[0]) && $PATH[0] == 'all') {
            $main = '<h1>Past Benchmark Tickets</h1>';
            $stmt = phoromatic_server::$db->prepare('SELECT * FROM phoromatic_benchmark_tickets WHERE AccountID = :account_id AND State >= 0 ORDER BY TicketIssueTime DESC');
            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
            $result = $stmt->execute();
            $main .= '<ol>';
            if ($result) {
                $row = $result->fetchArray();
                if (!empty($row)) {
                    do {
                        $main .= '<li><a href="?benchmark/' . $row['TicketID'] . '">' . $row['Title'] . '</a></li>';
                    } while ($row = $result->fetchArray());
                }
            } else {
                $main .= '<li>No Benchmark Tickets Found</li>';
            }
            $main .= '</ol>';
        } else {
            if (!empty($PATH[0]) && is_numeric($PATH[0])) {
                $stmt = phoromatic_server::$db->prepare('SELECT * FROM phoromatic_benchmark_tickets WHERE AccountID = :account_id AND TicketID = :ticket_id');
                $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                $stmt->bindValue(':ticket_id', $PATH[0]);
                $result = $stmt->execute();
                $row = $result->fetchArray();
                if (!empty($row)) {
                    if (isset($_GET['remove'])) {
                        $stmt = phoromatic_server::$db->prepare('DELETE FROM phoromatic_benchmark_tickets WHERE AccountID = :account_id AND TicketID = :ticket_id');
                        $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                        $stmt->bindValue(':ticket_id', $PATH[0]);
                        $result = $stmt->execute();
                        header('Location: /?benchmark');
                    } else {
                        if (isset($_GET['repeat'])) {
                            $stmt = phoromatic_server::$db->prepare('UPDATE phoromatic_benchmark_tickets SET TicketIssueTime = :new_ticket_time, State = 1 WHERE AccountID = :account_id AND TicketID = :ticket_id');
                            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                            $stmt->bindValue(':ticket_id', $PATH[0]);
                            $stmt->bindValue(':new_ticket_time', time());
                            $result = $stmt->execute();
                        } else {
                            if (isset($_GET['disable'])) {
                                $stmt = phoromatic_server::$db->prepare('UPDATE phoromatic_benchmark_tickets SET State = 0 WHERE AccountID = :account_id AND TicketID = :ticket_id');
                                $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                                $stmt->bindValue(':ticket_id', $PATH[0]);
                                $result = $stmt->execute();
                            }
                        }
                    }
                    $main = null;
                    $main .= '<h1>' . $row['Title'] . '</h1>';
                    $main .= '<h3>' . $row['Description'] . '</h3>';
                    $main .= '<p>This benchmark ticket was created on <strong>' . date('j F Y \\a\\t H:i', strtotime($row['LastModifiedOn'])) . '</strong> by <strong>' . $row['LastModifiedBy'] . '. The ticket was last issued for testing at ' . date('j F Y \\a\\t H:i', $row['TicketIssueTime']) . '</strong>.';
                    $main .= '<p> <a href="/?benchmark/' . $PATH[0] . '/&repeat">Repeat Ticket</a> &nbsp; &nbsp; &nbsp; <a href="/?benchmark/' . $PATH[0] . '/&remove">Remove Ticket</a>' . (!isset($_GET['disable']) && $row['State'] > 0 ? ' &nbsp; &nbsp; &nbsp; <a href="/?benchmark/' . $PATH[0] . '/&disable">End Ticket</a>' : null) . '</p>';
                    $main .= '<hr /><h1>System Targets</h1><ol>';
                    foreach (explode(',', $row['RunTargetSystems']) as $system_id) {
                        $main .= '<li><a href="?systems/' . $system_id . '">' . phoromatic_server::system_id_to_name($system_id) . '</a></li>';
                    }
                    $main .= '</ol>';
                    $main .= '<hr /><h1>Ticket Payload</h1>';
                    $main .= '<p>This ticket runs the <strong>' . $row['SuiteToRun'] . '</strong> test suite:</p>';
                    $main .= '<div style="max-height: 400px; overflow-y: scroll;">';
                    $xml_path = phoromatic_server::phoromatic_account_suite_path($_SESSION['AccountID'], $row['SuiteToRun']) . 'suite-definition.xml';
                    if (is_file($xml_path)) {
                        $test_suite = new pts_test_suite($xml_path);
                        //	$main .= '<h2>' . $test_suite->get_title() . '</h2>';
                        //	$main .= '<p><strong>' . $test_suite->get_maintainer() . '</strong></p>';
                        //	$main .= '<p><em>' . $test_suite->get_description() . '</em></p>';
                        foreach ($test_suite->get_contained_test_result_objects() as $tro) {
                            $main .= '<h3>' . $tro->test_profile->get_title() . ' [' . $tro->test_profile->get_identifier() . ']</h3>';
                            $main .= '<p>' . $tro->get_arguments_description() . '</p>';
                        }
                        //$main .= '<hr />';
                    }
                    $main .= '</div><hr />';
                    $main .= '<div class="pts_phoromatic_info_box_area">';
                    $main .= '<div style="margin: 0 5%;"><ul style="max-height: 100%;"><li><h1>Test Results</h1></li>';
                    $stmt = phoromatic_server::$db->prepare('SELECT Title, SystemID, ScheduleID, PPRID, UploadTime, TimesViewed FROM phoromatic_results WHERE AccountID = :account_id AND BenchmarkTicketID = :ticket_id ORDER BY UploadTime DESC');
                    $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                    $stmt->bindValue(':ticket_id', $PATH[0]);
                    $test_result_result = $stmt->execute();
                    $results = 0;
                    while ($test_result_row = $test_result_result->fetchArray()) {
                        $main .= '<a onclick=""><li id="result_select_' . $test_result_row['PPRID'] . '"><input type="checkbox" id="result_compare_checkbox_' . $test_result_row['PPRID'] . '" onclick="javascript:phoromatic_checkbox_toggle_result_comparison(\'' . $test_result_row['PPRID'] . '\');" onchange="return false;"></input> <span onclick="javascript:phoromatic_window_redirect(\'?result/' . $test_result_row['PPRID'] . '\');">' . $test_result_row['Title'] . '</span><br /><table><tr><td>' . phoromatic_system_id_to_name($test_result_row['SystemID']) . '</td><td>' . phoromatic_user_friendly_timedate($test_result_row['UploadTime']) . '</td><td>' . $test_result_row['TimesViewed'] . ' Times Viewed</td></table></li></a>';
                        $results++;
                    }
                    if ($results == 0) {
                        $main .= '<li class="light" style="text-align: center;">No Results Found</li>';
                    } else {
                        if ($results > 3) {
                            $main .= '<a onclick=""><li id="global_bottom_totals"><input type="checkbox" id="global_checkbox" onclick="javascript:phoromatic_toggle_checkboxes_on_page(this);" onchange="return false;"></input> <strong>' . $results . ' Results</strong></li></a>';
                        }
                    }
                    $main .= '</ul></div>';
                    $main .= '</div>';
                }
            } else {
                if (isset($_POST['benchmark_title']) && !empty($_POST['benchmark_title'])) {
                    $title = phoromatic_get_posted_var('benchmark_title');
                    $description = phoromatic_get_posted_var('benchmark_description');
                    $result_identifier = phoromatic_get_posted_var('benchmark_identifier');
                    $suite_to_run = phoromatic_get_posted_var('suite_to_run');
                    if (strlen($title) < 3) {
                        echo '<h2>Title must be at least three characters.</h2>';
                        exit;
                    }
                    if (strlen($result_identifier) < 3) {
                        echo '<h2>Identifier must be at least three characters.</h2>';
                        exit;
                    }
                    if (strlen($suite_to_run) < 3) {
                        echo '<h2>You must specify a suite to run.</h2>';
                        exit;
                    }
                    $run_target_systems = phoromatic_get_posted_var('run_on_systems', array());
                    $run_target_groups = phoromatic_get_posted_var('run_on_groups', array());
                    if (!is_array($run_target_systems)) {
                        $run_target_systems = array();
                    }
                    if (!is_array($run_target_groups)) {
                        $run_target_groups = array();
                    }
                    $run_target_systems = implode(',', $run_target_systems);
                    $run_target_groups = implode(',', $run_target_groups);
                    if ($is_new) {
                        do {
                            $ticket_id = rand(10, 999999);
                            $matching_tickets = phoromatic_server::$db->querySingle('SELECT TicketID FROM phoromatic_benchmark_tickets WHERE TicketID = \'' . $ticket_id . '\'');
                        } while (!empty($matching_tickets));
                    }
                    $env_vars = array();
                    if (is_numeric($_POST['PTS_CONCURRENT_TEST_RUNS']) && $_POST['PTS_CONCURRENT_TEST_RUNS'] > 0) {
                        array_push($env_vars, 'PTS_CONCURRENT_TEST_RUNS=' . $_POST['PTS_CONCURRENT_TEST_RUNS']);
                    }
                    if (is_numeric($_POST['TOTAL_LOOP_TIME']) && $_POST['TOTAL_LOOP_TIME'] > 0) {
                        array_push($env_vars, 'TOTAL_LOOP_TIME=' . $_POST['TOTAL_LOOP_TIME']);
                    }
                    $env_vars = implode(';', $env_vars);
                    // Add benchmark
                    $stmt = phoromatic_server::$db->prepare('INSERT OR REPLACE INTO phoromatic_benchmark_tickets (AccountID, TicketID, TicketIssueTime, Title, ResultIdentifier, SuiteToRun, Description, State, LastModifiedBy, LastModifiedOn, RunTargetGroups, RunTargetSystems, EnvironmentVariables) VALUES (:account_id, :ticket_id, :ticket_time, :title, :result_identifier, :suite_to_run, :description, :state, :modified_by, :modified_on, :run_target_groups, :run_target_systems, :environment_variables)');
                    $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                    $stmt->bindValue(':ticket_id', $ticket_id);
                    $stmt->bindValue(':ticket_time', time());
                    $stmt->bindValue(':title', $title);
                    $stmt->bindValue(':result_identifier', $result_identifier);
                    $stmt->bindValue(':suite_to_run', $suite_to_run);
                    $stmt->bindValue(':description', $description);
                    $stmt->bindValue(':state', 1);
                    $stmt->bindValue(':modified_by', $_SESSION['UserName']);
                    $stmt->bindValue(':modified_on', phoromatic_server::current_time());
                    $stmt->bindValue(':public_key', $public_key);
                    $stmt->bindValue(':run_target_groups', $run_target_groups);
                    $stmt->bindValue(':run_target_systems', $run_target_systems);
                    $stmt->bindValue(':environment_variables', $env_vars);
                    $result = $stmt->execute();
                    phoromatic_add_activity_stream_event('benchmark', $benchmark_id, $is_new ? 'added' : 'modified');
                    if ($result) {
                        header('Location: ?benchmark/' . $schedule_id);
                    }
                }
                $main = '
			<h2>' . ($is_new ? 'Create' : 'Edit') . ' A Benchmark</h2>
			<p>This page allows you to run a test suite -- consisting of a single or multiple test suites -- on a given set/group of systems right away at their next earliest possibility. This benchmark mode is an alternative to the <a href="?schedules">benchmark schedules</a> for reptitive/routine testing.</p>';
                $local_suites = pts_file_io::glob(phoromatic_server::phoromatic_account_suite_path($_SESSION['AccountID']) . '*/suite-definition.xml');
                if (empty($local_suites)) {
                    $main .= '<p><strong>Before you can create a benchmark ticket you must first <a href="?build_suite">create a test suite</a> with the tests you wish to run.</strong></p>';
                } else {
                    $main .= '<form action="' . $_SERVER['REQUEST_URI'] . '" name="run_benchmark" id="run_benchmark" method="post" enctype="multipart/form-data" onsubmit="return validate_run_benchmark();">
				<h3>Title:</h3>
				<p>The title is the name of the result file for this test run.</p>
				<p><input type="text" name="benchmark_title" value="' . (!$is_new ? $e_schedule['Title'] : null) . '" /></p>
				<h3>Test Run Identifier:</h3>
				<p>The test run identifier is the per-system name for the system(s) being benchmarked. The following variables may be used: <strong>.SYSTEM</strong>, <strong>.GROUP</strong>. Any custom per-user system variables set via the individual system pages can also be used.</p>
				<p><input type="text" name="benchmark_identifier" value="' . (!$is_new ? $e_schedule['Identifier'] : null) . '" /></p>
				<h3>Test Suite To Run:</h3>
				<p><a href="?build_suite">Build a suite</a> to add/select more tests to run or <a href="?local_suites">view local suites</a> for more information on a particular suite. A test suite is a set of test profiles to run in a pre-defined manner.</p>';
                    $main .= '<p><select name="suite_to_run">';
                    foreach ($local_suites as $xml_path) {
                        $id = basename(dirname($xml_path));
                        $test_suite = new pts_test_suite($xml_path);
                        $main .= '<option value="' . $id . '">' . $test_suite->get_title() . ' - ' . $id . '</option>';
                    }
                    $main .= '</select></p>';
                    $main .= '<h3>Description:</h3>
				<p>The description is an optional way to add more details about the intent or objective of this test run.</p>
				<p><textarea name="benchmark_description" id="benchmark_description" cols="50" rows="3">' . (!$is_new ? $e_schedule['Description'] : null) . '</textarea></p>
				<hr /><h3>System Targets:</h3>
				<p>Select the systems that should be benchmarked at their next earliest convenience.</p>
				<p style="white-space: nowrap;">';
                    $stmt = phoromatic_server::$db->prepare('SELECT Title, SystemID FROM phoromatic_systems WHERE AccountID = :account_id AND State >= 0 ORDER BY Title ASC');
                    $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                    $result = $stmt->execute();
                    if (!$is_new) {
                        $e_schedule['RunTargetSystems'] = explode(',', $e_schedule['RunTargetSystems']);
                        $e_schedule['RunTargetGroups'] = explode(',', $e_schedule['RunTargetGroups']);
                    }
                    if ($row = $result->fetchArray()) {
                        $main .= '<h4>Systems: ';
                        do {
                            $main .= '<input type="checkbox" name="run_on_systems[]" value="' . $row['SystemID'] . '" ' . (!$is_new && in_array($row['SystemID'], $e_schedule['RunTargetSystems']) ? 'checked="checked" ' : null) . '/> ' . $row['Title'] . ' ';
                        } while ($row = $result->fetchArray());
                        $main .= '</h4>';
                    }
                    $stmt = phoromatic_server::$db->prepare('SELECT GroupName FROM phoromatic_groups WHERE AccountID = :account_id ORDER BY GroupName ASC');
                    $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                    $result = $stmt->execute();
                    if ($row = $result->fetchArray()) {
                        $main .= '<h4>Groups: ';
                        do {
                            $main .= '<input type="checkbox" name="run_on_groups[]" value="' . $row['GroupName'] . '" ' . (!$is_new && in_array($row['GroupName'], $e_schedule['RunTargetGroups']) ? 'checked="checked" ' : null) . '/> ' . $row['GroupName'] . ' ';
                        } while ($row = $result->fetchArray());
                        $main .= '</h4>';
                    }
                    $main .= '</p>
				<hr /><h3>Environment Options</h3>
				<h4>Stress Testing</h4>
				<p>If you wish to test systems for stability/reliability rather than performance, use this option and specify the number of tests to run concurrently (two or more) and (optionally) for the total period of time to continue looping the benchmarks. These options are intended to just stress the system and will not record any benchmark results. From the command-line this testing mode can be used via the <em>phoronix-test-suite stress-run</em> sub-command.</p>
				<p><strong>Concurrent Number Of Test Processes:</strong> <select name="PTS_CONCURRENT_TEST_RUNS"><option value="0">Disabled</option>';
                    for ($i = 2; $i <= 24; $i++) {
                        $main .= '<option value="' . $i . '">' . $i . '</option>';
                    }
                    $main .= '</select></p>
				<p><strong>Force Loop Time:</strong> <select name="TOTAL_LOOP_TIME"><option value="0">Disabled</option>';
                    $s = true;
                    for ($i = 60; $i <= 60 * 24 * 90; $i += 60) {
                        if ($i > 10080) {
                            // 7 days
                            if ($i % 1440 != 0) {
                                continue;
                            }
                        } else {
                            if ($i > 480) {
                                $s = !$s;
                                if (!$s) {
                                    continue;
                                }
                            }
                        }
                        $main .= '<option value="' . $i . '">' . pts_strings::format_time($i, 'MINUTES') . '</option>';
                    }
                    $main .= '</select></p>

				<h4>System Monitoring</h4>
				<p>The Phoronix Test Suite system monitor module allows for select hardware/software sensors to be logged in real-time while running the selected test suite. The supported sensors are then shown within the result file upon the test\'s completion.</p>';
                    foreach (phodevi::available_sensors() as $sensor) {
                        $main .= '<input type="checkbox" name="MONITOR" value="' . phodevi::sensor_identifier($sensor) . '" /> ' . phodevi::sensor_name($sensor) . ' &nbsp; ';
                    }
                    $main .= '<hr /><p align="left"><input name="submit" value="' . ($is_new ? 'Run' : 'Edit') . ' Benchmark" type="submit" onclick="return pts_rmm_validate_schedule();" /></p>
					</form>';
                }
            }
        }
        $stmt = phoromatic_server::$db->prepare('SELECT * FROM phoromatic_benchmark_tickets WHERE AccountID = :account_id AND State >= 0 AND TicketIssueTime > :time_cutoff ORDER BY TicketIssueTime DESC LIMIT 30');
        $stmt->bindValue(':account_id', $_SESSION['AccountID']);
        $stmt->bindValue(':time_cutoff', time() - 60 * 60 * 24 * 14);
        $result = $stmt->execute();
        $right = '<ul><li>Benchmark Tickets</li>';
        if ($result) {
            $row = $result->fetchArray();
            if (!empty($row)) {
                do {
                    $right .= '<li><a href="?benchmark/' . $row['TicketID'] . '">' . $row['Title'] . '</a></li>';
                } while ($row = $result->fetchArray());
            }
        }
        $right .= '<li><em><a href="?benchmark/all">View All Past Tickets</a></em></li>';
        $right .= '</ul>';
        echo phoromatic_webui_header_logged_in();
        echo phoromatic_webui_main($main, phoromatic_webui_right_panel_logged_in($right));
        echo phoromatic_webui_footer();
    }
 public static function render_page_process($PATH)
 {
     $search_query = $_REQUEST['search'];
     $main = null;
     if (strlen($search_query) < 4) {
         $main = '<h1>Search Failed</h1>';
         $main .= '<p>Search Queries Must Be At Least Four Characters.</p>';
     } else {
         $main .= '<h1>Search Results For: ' . $search_query . '</h1>';
         $category_matches = 0;
         $tests = self::search_test_profiles($search_query);
         if ($tests != null) {
             $category_matches++;
             $main .= '<h2>Test Profile Matches</h2>' . $tests . '<hr />';
         }
         $local_suites = self::search_local_test_suites($search_query);
         if ($local_suites != null) {
             $category_matches++;
             $main .= '<h2>Local Test Suite Matches</h2>' . $local_suites . '<hr />';
         }
         $test_schedules = self::search_test_schedules($search_query);
         if ($test_schedules != null) {
             $category_matches++;
             $main .= '<h2>Test Schedule Matches</h2>' . $test_schedules . '<hr />';
         }
         $test_results = self::search_test_results($search_query);
         if ($test_results != null) {
             $category_matches++;
             $main .= '<h2>Test Result Matches</h2>' . $test_results . '<hr />';
         }
         $test_systems = self::search_test_systems($search_query);
         if ($test_systems != null) {
             $category_matches++;
             $main .= '<h2>Test System Matches</h2>' . $test_systems . '<hr />';
         }
         if ($category_matches == 0) {
             $main .= '<h2>No Matches Found</h2>';
         }
     }
     echo phoromatic_webui_header_logged_in();
     echo phoromatic_webui_main($main, phoromatic_webui_right_panel_logged_in());
     echo phoromatic_webui_footer();
 }
 public static function render_page_process($PATH)
 {
     echo phoromatic_webui_header_logged_in();
     $stmt = phoromatic_server::$db->prepare('SELECT * FROM phoromatic_systems WHERE AccountID = :account_id AND State >= 0 ORDER BY LastCommunication DESC');
     $stmt->bindValue(':account_id', $_SESSION['AccountID']);
     $result = $stmt->execute();
     echo '<script type="text/javascript"> setInterval(function() { window.location.reload(); }, 79000); </script>';
     echo '<div style="margin: 10px 0 30px; clear: both; padding-bottom: 40px;">';
     while ($row = $result->fetchArray()) {
         $opacity = null;
         // stripos($row['CurrentTask'], 'idling') !== false ||
         if (phoromatic_server::system_check_if_down($_SESSION['AccountID'], $row['SystemID'], $row['LastCommunication'], $row['CurrentTask']) || stripos($row['CurrentTask'], 'Unknown') !== false) {
             $not_testing = false;
             $opacity = ' style="background: #f44336; color: #FFF;"';
         } else {
             if (stripos($row['CurrentTask'], 'idling') !== false) {
                 $not_testing = true;
                 //	continue;
             } else {
                 if (stripos($row['CurrentTask'], 'waiting') !== false || stripos($row['CurrentTask'], 'shutdown') !== false) {
                     $not_testing = true;
                     $opacity = ' style="opacity: 0.3;"';
                 } else {
                     $not_testing = false;
                 }
             }
         }
         echo '<a href="?systems/' . $row['SystemID'] . '"><div class="phoromatic_dashboard_block"' . $opacity . '>';
         echo '<div style="float: left; width: 30%;">';
         echo '<h1>' . $row['Title'] . '</h1>';
         $components = array_merge(pts_result_file_analyzer::system_component_string_to_array($row['Hardware'], array('Processor', 'Motherboard')), pts_result_file_analyzer::system_component_string_to_array($row['Software'], array('OS', 'Kernel')));
         foreach ($components as &$c) {
             if (($x = stripos($c, ' @')) !== false) {
                 $c = substr($c, 0, $x);
             }
             if (($x = stripos($c, ' (')) !== false) {
                 $c = substr($c, 0, $x);
             }
         }
         echo '<p><em>' . implode(' - ', $components) . '</em></p>';
         echo '<h2>' . $row['CurrentTask'] . '</h2>';
         if (!empty($row['CurrentProcessSchedule'])) {
             echo '<h2>' . phoromatic_server::schedule_id_to_name($row['CurrentProcessSchedule']) . '</h2>';
         }
         echo '</div>';
         echo '<div style="float: left;">';
         echo '<h2>' . $row['LastIP'] . '</h2>';
         echo '</div>';
         $time_remaining = phoromatic_compute_estimated_time_remaining($row['EstimatedTimeForTask'], $row['LastCommunication']);
         if ($time_remaining) {
             echo '<div style="float: left; text-align: center; margin: 0 6px;">';
             echo '<h2>~ ' . $time_remaining . ' <sub>mins</sub></h2>';
             echo '<p class="font-size: 90%;"><em>Estimated Time Remaining</em></p>';
             if (!empty($row['TimeToNextCommunication'])) {
                 echo '<p><em>' . phoromatic_compute_estimated_time_remaining_string($row['TimeToNextCommunication'], $row['LastCommunication'], 'To Next Communication') . '</em></p>';
             }
             echo '</div>';
         }
         if ($not_testing) {
             $next_job_in = phoromatic_server::time_to_next_scheduled_job($_SESSION['AccountID'], $row['SystemID']);
             if ($next_job_in > 0) {
                 if ($next_job_in > 240) {
                     $next_job_in = round($next_job_in / 60);
                     $next_unit = 'hours';
                 } else {
                     $next_unit = 'mins';
                 }
                 echo '<div style="float: left; margin: 0 0 0 10px; text-align: center;">';
                 echo '<h2>' . $next_job_in . ' <sub>' . $next_unit . '</sub></h2>';
                 echo '<p class="font-size: 90%;"><em>Time To Next Scheduled Task</em></p>';
                 echo '</div>';
             }
         }
         $system_path = phoromatic_server::phoromatic_account_system_path($_SESSION['AccountID'], $row['SystemID']);
         if (is_file($system_path . 'sensors-pool.json')) {
             $sensors = file_get_contents($system_path . 'sensors-pool.json');
             $sensors = json_decode($sensors, true);
             echo '<div style="float: right; margin: 0 10px 0 10px;">';
             $g_count = 0;
             foreach (array('CPU Usage', 'Memory Usage', 'CPU Temperature', 'System Temperature', 'GPU Temperature', 'Swap Usage', 'System Iowait', 'CPU Frequency') as $s) {
                 if (!isset($sensors[$s]) || !isset($sensors[$s]['values']) || count($sensors[$s]['values']) < 5) {
                     continue;
                 }
                 $g_count++;
                 if ($g_count <= 3) {
                     $graph = new pts_sys_graph(array('title' => $s, 'x_scale' => 'm', 'y_scale' => $sensors[$s]['unit'], 'text_size' => 10, 'reverse_x_direction' => false, 'width' => 300, 'height' => 120));
                     $graph->render_base();
                     $svg_dom = $graph->render_graph_data($sensors[$s]['values']);
                     if ($svg_dom === false) {
                         continue;
                     }
                     $output_type = 'SVG';
                     $graph = $svg_dom->output(null, $output_type);
                     echo substr($graph, strpos($graph, '<svg'));
                 } else {
                     break;
                 }
             }
             echo '</div>';
         }
         echo '<hr style="width: ' . $row['TaskPercentComplete'] . '%;" />';
         echo '</div></a>';
     }
     echo '</div>';
     echo phoromatic_webui_footer();
 }
    public static function render_page_process($PATH)
    {
        echo phoromatic_webui_header_logged_in();
        $main = '<h1>Settings</h1>
				<h2>User Settings</h2>
				<p>User settings are specific to your particular account, in cases where there are multiple individuals/accounts managing the same test systems and data.</p>
				';
        $stmt = phoromatic_server::$db->prepare('SELECT * FROM phoromatic_user_settings WHERE AccountID = :account_id AND UserID = :user_id');
        $stmt->bindValue(':account_id', $_SESSION['AccountID']);
        $stmt->bindValue(':user_id', $_SESSION['UserID']);
        $result = $stmt->execute();
        $row = $result->fetchArray();
        $user_settings = array('Email' => array('NotifyOnResultUploads' => 'Send notification when test results are uploaded to Phoromatic.', 'NotifyOnWarnings' => 'Send notification when any warnings are generated on a test system.', 'NotifyOnNewSystems' => 'Send notification when new test systems are added.', 'NotifyOnHungSystems' => 'Send notification when system(s) appear hung.'));
        $main .= '<form name="system_form" id="system_form" action="?settings" method="post">';
        foreach ($user_settings as $section => $section_settings) {
            $main .= '<h3>' . $section . '</h3><p>';
            foreach ($section_settings as $key => $setting) {
                if (isset($_POST['user_settings_update'])) {
                    if (isset($_POST[$key]) && $_POST[$key] == 'yes') {
                        $row[$key] = 1;
                    } else {
                        $row[$key] = 0;
                    }
                    $stmt = phoromatic_server::$db->prepare('UPDATE phoromatic_user_settings SET ' . $key . ' = :val WHERE AccountID = :account_id AND UserID = :user_id');
                    $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                    $stmt->bindValue(':user_id', $_SESSION['UserID']);
                    $stmt->bindValue(':val', $row[$key]);
                    $stmt->execute();
                    //echo phoromatic_server::$db->lastErrorMsg();
                }
                $main .= '<input type="checkbox" name="' . $key . '" ' . (isset($row[$key]) && $row[$key] == 1 ? 'checked="checked" ' : '') . 'value="yes" /> ' . $setting . '<br />';
            }
            $main .= '</p>';
        }
        $main .= '<p><input type="hidden" value="1" name="user_settings_update" /><input type="submit" value="Save User Settings" /></p>';
        $main .= '</form>';
        if (!PHOROMATIC_USER_IS_VIEWER) {
            $main .= '<hr />
				<h2>Account Settings</h2>
				<p>Account settings are system-wide, in cases where there are multiple individuals/accounts managing the same test systems and data.</p>';
            $stmt = phoromatic_server::$db->prepare('SELECT * FROM phoromatic_account_settings WHERE AccountID = :account_id');
            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
            $result = $stmt->execute();
            $row = $result->fetchArray();
            $account_settings = array('Global Settings' => array('ArchiveResultsLocally' => 'Archive test results on local test systems after the results have been uploaded.', 'UploadSystemLogs' => 'Upload system logs when uploading test results.', 'RunInstallCommand' => 'For all test schedules, always run the install command for test(s) prior to running them on the system.', 'ForceInstallTests' => 'For all test schedules, force the test installation/re-installation of tests each time prior to running the test.', 'SystemSensorMonitoring' => 'Enable the system sensor monitoring while tests are taking place.', 'UploadResultsToOpenBenchmarking' => 'For all test schedules, also upload test results to OpenBenchmarking.org.', 'PowerOffWhenDone' => 'Power off system(s) when scheduled tests are completed for the day.', 'PreSeedTestInstalls' => 'Attempt to pre-install commonly used tests on client systems while idling.', 'NetworkPowerUpWhenNeeded' => 'Use network Wake-On-LAN to power on systems when needed.', 'LetOtherGroupsViewResults' => 'Let other accounts/groups on this Phoromatic Server view (read-only) this account\'s results.', 'LetPublicViewResults' => 'Allow public/unauthenticated visitors to access these test results from the public viewer page.', 'PowerOnSystemDaily' => 'Attempt to power-on systems daily (unless there\'s a daily test schedule / trigger on the system) to maintain the DHCP lease on the network, update any software/hardware information, etc. When the daily update is done, the system will power off unless there\'s a test to run and the power-off setting above is enabled. This option is namely useful for systems that otherwise may be idling/powered-off for long periods of time between tests.', 'AutoApproveNewSystems' => 'Enabling this option will make new test systems immediately available for this account rather than the default behavior of first needing an administrator to approve/deny the system via the Phoromatic Server web interface. With this option enabled, the systems are automatically approved by default but can be later disabled/removed via the Phoromatic web interface.'));
            $main .= '<form name="system_form" id="system_form" action="?settings" method="post">';
            $settings_updated = false;
            foreach ($account_settings as $section => $section_settings) {
                $main .= '<h3>' . $section . '</h3><p>';
                foreach ($section_settings as $key => $setting) {
                    if (isset($_POST['account_settings_update'])) {
                        if (isset($_POST[$key]) && $_POST[$key] == 'yes') {
                            $row[$key] = 1;
                        } else {
                            $row[$key] = 0;
                        }
                        $stmt = phoromatic_server::$db->prepare('UPDATE phoromatic_account_settings SET ' . $key . ' = :val WHERE AccountID = :account_id');
                        $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                        $stmt->bindValue(':val', $row[$key]);
                        $stmt->execute();
                        if ($settings_updated == false) {
                            phoromatic_add_activity_stream_event('settings', null, 'modified');
                            $settings_updated = true;
                        }
                        //echo phoromatic_server::$db->lastErrorMsg();
                    }
                    $main .= '<input type="checkbox" name="' . $key . '" ' . (isset($row[$key]) && $row[$key] === 1 ? 'checked="checked" ' : '') . 'value="yes" /> ' . $setting . '<br />';
                }
                $main .= '</p>';
            }
            $main .= '<p><input type="hidden" value="1" name="account_settings_update" /><input type="submit" value="Save Account Settings" /></p>';
            $main .= '</form>';
        }
        $main .= '<hr />
			<h2>Cache Settings</h2>
			<p>Proceed to the <a href="?caches">download cache page</a> for information about the Phoromatic Server\'s download caches.</p>';
        $main .= '<hr />
			<h2>User Password</h2>
			<p>Proceed to the <a href="?password">password page</a> if you wish to update your account\'s password.</p>';
        if (!PHOROMATIC_USER_IS_VIEWER) {
            $main .= '<hr />
				<h2>Build A Suite</h2>
				<p><a href="?build_suite">Create a custom test suite</a>.</p>';
            $update_script_path = phoromatic_server::phoromatic_account_path($_SESSION['AccountID']) . 'client-update-script.sh';
            if (isset($_POST['client_update_script'])) {
                file_put_contents($update_script_path, str_replace("\r\n", PHP_EOL, $_POST['client_update_script']));
            }
            if (!is_file($update_script_path)) {
                $script_contents = pts_file_io::file_get_contents(PTS_CORE_STATIC_PATH . 'sample-pts-client-update-script.sh');
            } else {
                $script_contents = pts_file_io::file_get_contents($update_script_path);
            }
            $main .= '<form name="update_client_script_form" id="update_client_script_form" action="?settings" method="post">
<hr /><h2>Auto-Updating Clients</h2><p>If desired, you can paste a script in the below field if you wish to have Phoronix Test Suite / Phoromatic clients attempt to auto-update themselves. Any commands copied below are automatically executed by the client upon completing a test / beginning a new idle process / prior to attempting a system shutdown. If your script determines the client is to be updated, it should <em>reboot</em> the system afterwards to ensure no issues in the upgrade of the Phoronix Test Suite installation. A reference/example script is provided by default. This update script feature does not attempt to update the Phoromatic Server software.</p>
				<p><textarea style="width: 80%; height: 400px;" name="client_update_script" id="client_update_script">' . $script_contents . '</textarea></p>
				<p><input type="submit" value="Save Client Auto-Update Script" /></p>
				</form>';
        }
        echo '<div id="pts_phoromatic_main_area">' . $main . '</div>';
        echo phoromatic_webui_footer();
    }
 public static function render_page_process($PATH)
 {
     echo phoromatic_webui_header_logged_in();
     $main = null;
     if (!PHOROMATIC_USER_IS_VIEWER && isset($PATH[0]) && $PATH[0] == 'delete') {
         $pprids = explode(',', $PATH[1]);
         foreach ($pprids as $pprid) {
             $stmt = phoromatic_server::$db->prepare('DELETE FROM phoromatic_results WHERE AccountID = :account_id AND PPRID = :pprid');
             $stmt->bindValue(':account_id', $_SESSION['AccountID']);
             $stmt->bindValue(':pprid', $pprid);
             $result = $stmt->execute();
             // TODO XXX fix below
             //$upload_dir = phoromatic_server::phoromatic_account_result_path($_SESSION['AccountID'], $upload_id);
             //pts_file_io::delete($upload_dir);
         }
     }
     if ($main == null) {
         $time_limit = false;
         $time_str = false;
         if (isset($_POST['time'])) {
             $time_str = $_POST['time'];
             $time_limit = strtotime('- ' . $time_str);
         }
         if ($time_limit == false) {
             $time_str = '1 month';
             $time_limit = strtotime('- ' . $time_str);
         }
         $result_limit = isset($_POST['result_limit']) && is_numeric($_POST['result_limit']) && $_POST['result_limit'] > 9 ? $_POST['result_limit'] : 50;
         $main .= '<form action="' . $_SERVER['REQUEST_URI'] . '" method="post"><div style="text-align: left; font-weight: bold;">Show Results For <select id="result_time_limit" name="time">';
         $results_for_length = array('24 hours' => '24 Hours', '3 days' => '3 Days', '1 week' => 'Week', '2 week' => '2 Weeks', '1 month' => 'Month', '2 months' => '2 Months', '3 months' => 'Quarter', '6 months' => '6 Months', '1 year' => 'Year', '2 year' => 'Two Years');
         foreach ($results_for_length as $val => $str) {
             $main .= '<option value="' . $val . '"' . ($time_str == $val ? ' selected="selected"' : null) . '>Past ' . $str . '</option>';
         }
         $main .= '</select> Search For <input type="text" name="search" value="' . (isset($_POST['search']) ? $_POST['search'] : null) . '" /> &nbsp; Limit Results To <select id="result_limit" name="result_limit">';
         for ($i = 25; $i <= 150; $i += 25) {
             $main .= '<option value="' . $i . '"' . ($result_limit == $i ? ' selected="selected"' : null) . '>' . $i . '</option>';
         }
         $main .= '</select> &nbsp; <input type="submit" value="Update" /></div></form>';
         $main .= '<h1>Account Test Results</h1>';
         $main .= '<div class="pts_phoromatic_info_box_area">';
         $search_for = !isset($_POST['search']) || empty($_POST['search']) ? null : 'AND (Title LIKE :search OR Description LIKE :search OR UploadID IN (SELECT UploadID FROM phoromatic_results_systems WHERE AccountID = :account_id AND (Software LIKE :search OR Hardware LIKE :search)))';
         $main .= '<div style="margin: 0 5%;"><ul style="max-height: 100%;"><li><h1>Recent Test Results</h1></li>';
         if (isset($PATH[1]) && $PATH[0] == 'hash') {
             // Find matching comparison hashes
             $stmt = phoromatic_server::$db->prepare('SELECT Title, SystemID, ScheduleID, PPRID, UploadTime, TimesViewed FROM phoromatic_results WHERE AccountID = :account_id ' . $search_for . ' AND ComparisonHash = :comparison_hash ORDER BY UploadTime DESC LIMIT ' . $result_limit);
             $stmt->bindValue(':comparison_hash', $PATH[1]);
         } else {
             if (isset($PATH[1]) && $PATH[0] == 'ticket') {
                 // Find matching ticket results
                 $stmt = phoromatic_server::$db->prepare('SELECT Title, SystemID, ScheduleID, PPRID, UploadTime, TimesViewed FROM phoromatic_results WHERE AccountID = :account_id ' . $search_for . ' AND BenchmarkTicketID = :ticket_id ORDER BY UploadTime DESC LIMIT ' . $result_limit);
                 $stmt->bindValue(':ticket_id', $PATH[1]);
             } else {
                 $stmt = phoromatic_server::$db->prepare('SELECT Title, SystemID, ScheduleID, PPRID, UploadTime, TimesViewed FROM phoromatic_results WHERE AccountID = :account_id ' . $search_for . ' ORDER BY UploadTime DESC LIMIT ' . $result_limit);
             }
         }
         $stmt->bindValue(':account_id', $_SESSION['AccountID']);
         $stmt->bindValue(':search', isset($_POST['search']) ? '%' . $_POST['search'] . '%' : null);
         $test_result_result = $stmt->execute();
         $results = 0;
         while ($test_result_row = $test_result_result->fetchArray()) {
             if (strtotime($test_result_row['UploadTime']) < $time_limit) {
                 break;
             }
             if ($results > 150) {
                 break;
             }
             $main .= '<a onclick=""><li id="result_select_' . $test_result_row['PPRID'] . '"><input type="checkbox" id="result_compare_checkbox_' . $test_result_row['PPRID'] . '" onclick="javascript:phoromatic_checkbox_toggle_result_comparison(\'' . $test_result_row['PPRID'] . '\');" onchange="return false;"></input> <span onclick="javascript:phoromatic_window_redirect(\'?result/' . $test_result_row['PPRID'] . '\');">' . $test_result_row['Title'] . '</span><br /><table><tr><td>' . phoromatic_system_id_to_name($test_result_row['SystemID']) . '</td><td>' . phoromatic_user_friendly_timedate($test_result_row['UploadTime']) . '</td><td>' . $test_result_row['TimesViewed'] . ' Times Viewed</td></table></li></a>';
             $results++;
         }
         if ($results == 0) {
             $main .= '<li class="light" style="text-align: center;">No Results Found</li>';
         } else {
             if ($results > 3) {
                 $main .= '<a onclick=""><li id="global_bottom_totals"><input type="checkbox" id="global_checkbox" onclick="javascript:phoromatic_toggle_checkboxes_on_page(this);" onchange="return false;"></input> <strong>' . $results . ' Results</strong></li></a>';
             }
         }
         $main .= '</ul></div>';
         $main .= '</div>';
         $result_share_opt = phoromatic_server::read_setting('force_result_sharing') ? '1 = 1' : 'AccountID IN (SELECT AccountID FROM phoromatic_account_settings WHERE LetOtherGroupsViewResults = "1")';
         $stmt = phoromatic_server::$db->prepare('SELECT Title, SystemID, ScheduleID, PPRID, UploadTime, TimesViewed, AccountID FROM phoromatic_results WHERE ' . $result_share_opt . ' AND AccountID != :account_id ' . $search_for . ' ORDER BY UploadTime DESC LIMIT ' . $result_limit);
         $stmt->bindValue(':account_id', $_SESSION['AccountID']);
         $stmt->bindValue(':search', isset($_POST['search']) ? '%' . $_POST['search'] . '%' : null);
         $test_result_result = $stmt->execute();
         if (!empty($test_result_result) && ($test_result_row = $test_result_result->fetchArray())) {
             $main .= '<div class="pts_phoromatic_info_box_area">';
             $main .= '<div style="margin: 0 5%;"><ul style="max-height: 100%;"><li><h1>Results Shared By Other Groups</h1></li>';
             $results = 0;
             do {
                 if (strtotime($test_result_row['UploadTime']) < $time_limit) {
                     break;
                 }
                 if ($results > 150) {
                     break;
                 }
                 $main .= '<a onclick=""><li id="result_select_' . $test_result_row['PPRID'] . '"><input type="checkbox" id="result_compare_checkbox_' . $test_result_row['PPRID'] . '" onclick="javascript:phoromatic_checkbox_toggle_result_comparison(\'' . $test_result_row['PPRID'] . '\');" onchange="return false;"></input> <span onclick="javascript:phoromatic_window_redirect(\'?result/' . $test_result_row['PPRID'] . '\');">' . $test_result_row['Title'] . '</span><br /><table><tr><td><strong>' . phoromatic_account_id_to_group_name($test_result_row['AccountID']) . '</strong></td><td>' . phoromatic_system_id_to_name($test_result_row['SystemID'], $test_result_row['AccountID']) . '</td><td>' . phoromatic_user_friendly_timedate($test_result_row['UploadTime']) . '</td><td>' . $test_result_row['TimesViewed'] . ' Times Viewed</td></table></li></a>';
                 $results++;
             } while ($test_result_row = $test_result_result->fetchArray());
             $main .= '</ul></div>';
         }
     }
     echo phoromatic_webui_main($main, phoromatic_webui_right_panel_logged_in());
     echo phoromatic_webui_footer();
 }
    public static function render_page_process($PATH)
    {
        echo phoromatic_webui_header_logged_in();
        $main = null;
        if (!PHOROMATIC_USER_IS_VIEWER) {
            if (function_exists('ssh2_connect') && isset($_POST['ip']) && isset($_POST['port']) && isset($_POST['password']) && isset($_POST['username'])) {
                $connection = ssh2_connect($_POST['ip'], $_POST['port']);
                if (ssh2_auth_password($connection, $_POST['username'], $_POST['password'])) {
                    $tmp_local_file = tempnam('/tmp', 'pts-ssh');
                    $tmp_remote_file = 'pts-ssh-' . rand(9999, 99999);
                    file_put_contents($tmp_local_file, '#!/bin/sh
if [ -w /var/lib/phoronix-test-suite/ ]
then
	PHORO_FILE_PATH=/var/lib/phoronix-test-suite/
elif [ -w $HOME/.phoronix-test-suite/ ]
then
	PHORO_FILE_PATH=$HOME/.phoronix-test-suite/
fi

echo "' . phoromatic_web_socket_server_ip() . '" >> $PHORO_FILE_PATH/phoromatic-servers
mkdir -p $PHORO_FILE_PATH/modules-data/phoromatic
echo "' . phoromatic_web_socket_server_addr() . '" > $PHORO_FILE_PATH/modules-data/phoromatic/last-phoromatic-server
');
                    ssh2_scp_send($connection, $tmp_local_file, $tmp_remote_file);
                    unlink($tmp_local_file);
                    ssh2_exec($connection, 'chmod +x ' . $tmp_remote_file);
                    ssh2_exec($connection, './' . $tmp_remote_file);
                    ssh2_exec($connection, 'rm' . $tmp_remote_file);
                }
            }
            if (isset($_POST['ip_claim']) && !empty($_POST['ip_claim']) && isset($_POST['ping'])) {
                $ip_ping = ip2long($_POST['ip_claim']) !== false ? $_POST['ip_claim'] : null;
                if ($ip_ping) {
                    echo '<h3>Ping Test: ' . $ip_ping . '</h3>';
                    echo '<pre>';
                    echo shell_exec('ping -c 1 ' . $ip_ping);
                    echo '</pre>';
                }
            } else {
                if (isset($_POST['ip_claim']) && !empty($_POST['ip_claim']) || isset($_POST['mac_claim']) && !empty($_POST['mac_claim'])) {
                    $stmt = phoromatic_server::$db->prepare('INSERT INTO phoromatic_system_association_claims (AccountID, IPAddress, NetworkMAC, CreationTime) VALUES (:account_id, :ip_address, :mac_address, :creation_time)');
                    $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                    $stmt->bindValue(':ip_address', $_POST['ip_claim']);
                    $stmt->bindValue(':mac_address', $_POST['mac_claim']);
                    $stmt->bindValue(':creation_time', phoromatic_server::current_time());
                    $result = $stmt->execute();
                }
            }
            if (isset($_POST['remove_claim']) && !empty($_POST['remove_claim'])) {
                list($ipc, $macc) = explode(',', $_POST['remove_claim']);
                $stmt = phoromatic_server::$db->prepare('DELETE FROM phoromatic_system_association_claims WHERE AccountID = :account_id AND NetworkMAC = :mac_address AND IPAddress = :ip_address');
                $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                $stmt->bindValue(':ip_address', $ipc);
                $stmt->bindValue(':mac_address', $macc);
                $stmt->bindValue(':creation_time', phoromatic_server::current_time());
                $result = $stmt->execute();
            }
            $main .= '<h2>Add Phoromatic Server Info Via SSH</h2>
			<p>If your Phoromatic client systems are SSH-enabled, you can specify their SSH connection information below. In doing so, the Phoromatic Server will do a one-time connection to it immediately to pre-seed the system with the Phoromatic Server account information for this account. This should allow the client systems to then find the server automatically next time the phoronix-test-suite is run. This command assumes the Phoronix Test Suite is already pre-installed on the client system in your desired configuration.</p>';
            if (function_exists('ssh2_connect')) {
                $main .= '<h3>Phoromatic Client SSH Information:</h3>';
                $main .= '<form action="' . $_SERVER['REQUEST_URI'] . '" name="ssh_connect" method="post">
				<p><strong>IP Address:</strong> <input type="text" name="ip" /></p>
				<p><strong>SSH Port:</strong> <input type="text" name="port" value="22" /></p>
				<p><strong>Username:</strong> <input type="text" name="username" /></p>
				<p><strong>Password:</strong> <input type="password" name="password" /></p>
				<p><input name="submit" value="Seed Phoromatic Server Account Information" type="submit" /></p>
				</form>';
            } else {
                $main .= '<h3>PHP SSH2 Must Be Installed For This Feature</h3>';
            }
            $main .= '<hr />';
            $main .= '<h2>Add Phoromatic Server Info Via IP/MAC</h2>
			<p>If deploying a Phoromatic Server within an organization, you can attempt for automatic configuration of Phoromatic clients if you know the system\'s IP or MAC addresses. When specifying either of these fields, if a Phoromatic client attempts to connect to this Phoromatic system without being associated to an account, it will be claimed by this account as long as no other Phoromatic accounts are attempting to claim the IP/MAC. This method can be particularly useful if running the Phoromatic client as a systemd/Upstart service where it will continually poll every 90 seconds auto-detected Phoromatic Servers on the LAN via zero-conf networking. For this feature to work, the zero-conf networking (Avahi) support must be enabled and working.</p>';
            $main .= '<form action="' . $_SERVER['REQUEST_URI'] . '" name="auto_associate" method="post">
			<p><strong>IP Address Claim:</strong> <input type="text" name="ip_claim" /></p>
			<p><strong>MAC Address Claim:</strong> <input type="text" name="mac_claim" /></p>
			<p><input name="ping" value="Ping Test" type="submit" /> &nbsp; <input name="submit" value="Submit Claim" type="submit" /></p>
			</form>';
            $stmt = phoromatic_server::$db->prepare('SELECT * FROM phoromatic_system_association_claims WHERE AccountID = :account_id ORDER BY IPAddress ASC');
            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
            $result = $stmt->execute();
            $claims = array();
            $main .= '<p style="max-height: 500px; overflow-y: auto; ">';
            while ($row = $result->fetchArray()) {
                $ip = $row['IPAddress'] != null ? $row['IPAddress'] : '<em>' . pts_network::mac_to_ip($row['NetworkMAC']) . '</em>';
                $main .= $ip . ' ' . $row['NetworkMAC'] . '<br />';
                array_push($claims, $row['IPAddress'] . ',' . $row['NetworkMAC']);
            }
            $main .= '</p>';
            if (!empty($claims)) {
                $main .= '<hr /><h2>Remove Claim</h2><p>Removing a claimed IP / MAC address.</p>';
                $main .= '<p><form action="' . $_SERVER['REQUEST_URI'] . '" name="remove_claim" method="post"><select name="remove_claim" id="remove_claim">';
                foreach ($claims as $claim) {
                    $main .= '<option value="' . $claim . '">' . str_replace(',', ' ', $claim) . '</option>';
                }
                $main .= '</select> <input name="submit" value="Remove Claim" type="submit" /></form></p>';
            }
            $main .= '<hr />';
        }
        $right = null;
        echo phoromatic_webui_main($main, phoromatic_webui_right_panel_logged_in($right));
        echo phoromatic_webui_footer();
    }
    public static function render_page_process($PATH)
    {
        echo phoromatic_webui_header_logged_in();
        $main = null;
        if (!PHOROMATIC_USER_IS_VIEWER && !empty($PATH[0]) && isset($_POST['system_title']) && !empty($_POST['system_title']) && isset($_POST['system_description']) && isset($_POST['system_state'])) {
            $stmt = phoromatic_server::$db->prepare('UPDATE phoromatic_systems SET Title = :title, Description = :description, State = :state, CurrentTask = \'Awaiting Task\', BlockPowerOffs = :block_power_offs WHERE AccountID = :account_id AND SystemID = :system_id');
            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
            $stmt->bindValue(':system_id', $PATH[0]);
            $stmt->bindValue(':title', $_POST['system_title']);
            $stmt->bindValue(':description', $_POST['system_description']);
            $stmt->bindValue(':state', $_POST['system_state']);
            $stmt->bindValue(':block_power_offs', $_POST['block_power_offs']);
            $stmt->execute();
        }
        if (!PHOROMATIC_USER_IS_VIEWER && !empty($PATH[0]) && isset($_POST['maintenance_mode'])) {
            $stmt = phoromatic_server::$db->prepare('UPDATE phoromatic_systems SET MaintenanceMode = :maintenance_mode WHERE AccountID = :account_id AND SystemID = :system_id');
            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
            $stmt->bindValue(':system_id', $PATH[0]);
            $stmt->bindValue(':maintenance_mode', $_POST['maintenance_mode']);
            $stmt->execute();
        }
        if (!PHOROMATIC_USER_IS_VIEWER && !empty($PATH[0]) && isset($_POST['tick_thread_reboot'])) {
            $stmt = phoromatic_server::$db->prepare('UPDATE phoromatic_systems SET TickThreadEvent = :event WHERE AccountID = :account_id AND SystemID = :system_id');
            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
            $stmt->bindValue(':system_id', $PATH[0]);
            $stmt->bindValue(':event', time() . ':reboot');
            $stmt->execute();
        }
        if (!PHOROMATIC_USER_IS_VIEWER && !empty($PATH[0]) && isset($_POST['tick_thread_halt'])) {
            $stmt = phoromatic_server::$db->prepare('UPDATE phoromatic_systems SET TickThreadEvent = :event WHERE AccountID = :account_id AND SystemID = :system_id');
            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
            $stmt->bindValue(':system_id', $PATH[0]);
            $stmt->bindValue(':event', time() . ':halt-testing');
            $stmt->execute();
        }
        if (!PHOROMATIC_USER_IS_VIEWER && !empty($PATH[0]) && isset($_POST['system_var_names']) && isset($_POST['system_var_values'])) {
            $vars = array();
            foreach ($_POST['system_var_names'] as $i => $name) {
                if (isset($_POST['system_var_values'][$i])) {
                    $name = pts_strings::keep_in_string(strtoupper($name), pts_strings::CHAR_LETTER | pts_strings::CHAR_NUMERIC | pts_strings::CHAR_UNDERSCORE);
                    $val = pts_strings::keep_in_string($_POST['system_var_values'][$i], pts_strings::CHAR_LETTER | pts_strings::CHAR_NUMERIC | pts_strings::CHAR_DASH | pts_strings::CHAR_UNDERSCORE | pts_strings::CHAR_COMMA | pts_strings::CHAR_SLASH | pts_strings::CHAR_SPACE | pts_strings::CHAR_DECIMAL | pts_strings::CHAR_PLUS | pts_strings::CHAR_EQUAL);
                    if ($name != null) {
                        $vars[$name] = $val;
                    }
                }
            }
            $var_string = null;
            foreach ($vars as $name => $val) {
                $var_string .= $name . '=' . $val . ';';
            }
            $stmt = phoromatic_server::$db->prepare('UPDATE phoromatic_systems SET SystemVariables = :system_variables WHERE AccountID = :account_id AND SystemID = :system_id');
            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
            $stmt->bindValue(':system_id', $PATH[0]);
            $stmt->bindValue(':system_variables', $var_string);
            $stmt->execute();
        }
        if (!empty($PATH[0])) {
            $stmt = phoromatic_server::$db->prepare('SELECT * FROM phoromatic_systems WHERE AccountID = :account_id AND SystemID = :system_id ORDER BY LastCommunication DESC');
            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
            $stmt->bindValue(':system_id', $PATH[0]);
            $result = $stmt->execute();
            if (!empty($result)) {
                $row = $result->fetchArray();
                if (!PHOROMATIC_USER_IS_VIEWER && isset($PATH[1]) && $PATH[1] == 'edit') {
                    $main = '<h1>' . $row['Title'] . '</h1>';
                    $main .= '<form name="system_form" id="system_form" action="?systems/' . $PATH[0] . '" method="post" onsubmit="return phoromatic_system_edit(this);">
			<p><div style="width: 200px; font-weight: bold; float: left;">System Title:</div> <input type="text" style="width: 400px;" name="system_title" value="' . $row['Title'] . '" /></p>
			<p><div style="width: 200px; font-weight: bold; float: left;">System Description:</div> <textarea style="width: 400px;" name="system_description">' . $row['Description'] . '</textarea></p>
			<p><div style="width: 200px; font-weight: bold; float: left;">System State:</div><select name="system_state" style="width: 200px;"><option value="-1">Disabled</option><option value="1" selected="selected">Enabled</option></select></p>
			<p><div style="width: 200px; font-weight: bold; float: left;">Allow Phoromatic To Power Off System When Testing Complete:</div><select name="block_power_offs" style="width: 200px;"><option value="0">Permitted</option><option value="1">Block Power-Off Signaling For This System</option></select> <sup>Assuming the power-off setting is enabled from the account settings page.</sup></p>
			<p><div style="width: 200px; font-weight: bold; float: left;">&nbsp;</div> <input type="submit" value="Submit" /></p></form>';
                } else {
                    $main = '<h1>' . $row['Title'] . '</h1><p><em>' . ($row['Description'] != null ? $row['Description'] : 'No system description.') . '</em></p>';
                    if (phoromatic_server::system_check_if_down($_SESSION['AccountID'], $row['SystemID'], $row['LastCommunication'], $row['CurrentTask'])) {
                        $main .= '<h3 style="text-align: center; color: red;">This system appears to be offline or inactive and there are pending tests scheduled to be run on this system that have yet to be completed. This system has not communicated with the Phoromatic Server in ' . pts_strings::format_time(time() - strtotime($row['LastCommunication']), 'SECONDS', true, 60) . '.</h3>';
                    }
                    if (!PHOROMATIC_USER_IS_VIEWER) {
                        $main .= '<p><a href="?systems/' . $PATH[0] . '/edit">Edit Task & Enable/Disable System</a></p>';
                    }
                }
                switch ($row['State']) {
                    case -1:
                        $state = 'Disabled';
                        break;
                    case 0:
                        $state = 'Connected; Awaiting Approval';
                        break;
                    case 1:
                        $state = 'Active';
                        break;
                }
                $main .= '<hr />';
                $info_table = array('Status:' => $row['CurrentTask'], 'Last Communication:' => phoromatic_user_friendly_timedate($row['LastCommunication']), 'Estimated Time Left For Task: ' => phoromatic_compute_estimated_time_remaining_string($row['EstimatedTimeForTask'], $row['LastCommunication']), 'State:' => $state, 'Phoronix Test Suite Client:' => $row['ClientVersion'], 'Initial Creation:' => phoromatic_user_friendly_timedate($row['CreatedOn']), 'System ID:' => $row['SystemID'], 'Last IP:' => $row['LastIP'], 'MAC Address:' => $row['NetworkMAC'], 'Wake-On-LAN Information:' => empty($row['NetworkWakeOnLAN']) ? 'N/A' : $row['NetworkWakeOnLAN'], 'Power-Off Sequence Permitted: ' => $row['BlockPowerOffs'] == 1 ? 'Blocked' : 'Permitted');
                $main .= '<h2>System State</h2>' . pts_webui::r2d_array_to_table($info_table, 'auto');
                if (!PHOROMATIC_USER_IS_VIEWER) {
                    if ($row['MaintenanceMode'] == 1) {
                        $mm_str = 'Disable Maintenance Mode';
                        $mm_val = 0;
                        $mm_onclick = 'return true;';
                    } else {
                        $mm_str = 'Enter Maintenance Mode';
                        $mm_val = 1;
                        $mm_onclick = 'return confirm(\'Enter maintenance mode now?\');';
                    }
                    $main .= '<p><form action="' . $_SERVER['REQUEST_URI'] . '" name="update_groups" method="post"><input type="hidden" name="maintenance_mode" value="' . $mm_val . '" /><input type="submit" value="' . $mm_str . '" onclick="' . $mm_onclick . '" style="float: left; margin: 0 20px 5px 0;" /></form> Putting the system into maintenance mode will power up the system (if supported and applicable) and cause the Phoronix Test Suite Phoromatic client to idle and block all testing until the mode has been disabled. If a test is already running on the system, the maintenance mode will not be entered until after the testing has completed. The maintenance mode can be used if wishing to update the system software or carry out other tasks without interfering with the Phoromatic client process. Once disabled, the Phoronix Test Suite will continue to function as normal.</p>';
                    if ($row['CoreVersion'] >= 5730) {
                        $main .= '<p><form action="' . $_SERVER['REQUEST_URI'] . '" name="update_groups" method="post"><input type="hidden" name="tick_thread_reboot" value="1" /><input type="submit" value="Reboot System" style="float: left; margin: 0 20px 5px 0;" /></form> If the system is currently powered up and connected to the Phoromatic Server, this will send a message to the system to issue a reboot -- in case the system is hung on a test or you wish to otherwise manually reboot the server. This feature was added with Phoronix Test Suite 5.8.</p>';
                        $main .= '<p><form action="' . $_SERVER['REQUEST_URI'] . '" name="update_groups" method="post"><input type="hidden" name="tick_thread_halt" value="1" /><input type="submit" value="Halt Testing" style="float: left; margin: 0 20px 5px 0;" /></form> If the system is currently powered up and running a test/benchmark via the Phoromatic Server, this will tell the system to halt the testing prematurely as soon as the currently-active test has finished. The results successfully ran will then be uploaded to the Phoromatic Server. This feature was added with Phoronix Test Suite 5.8.</p>';
                    }
                }
                $main .= '<hr /><h2>System Variables</h2><p>System variables are a new feature of Phoronix Test Suite 5.6 to allow for providing per-system information in an easy-to-use manner for other parts of the Phoromatic system. Initially these named variables can be used for the results identifier when <a href="/?benchmark">creating a benchmark ticket</a> and in the future the system variables may be used elsewhere. Examples of system variables could include providing a <em>.SERIAL</em> variable to acknowledge the system\'s serial number that may not be presented elsewhere by the Phoronix Test Suite, <em>.ADMIN</em> for the system\'s local administrator, etc. Variable names can only be alpha-numeric strings while their values are also alpha-numeric strings but with spaces allowed. System variables are always prefixed by a period. These system variables are also automatically transferred to the Phoromatic clients and set as environment variables prior to running any scheduled tests/process via Phoromatic.</p>';
                $system_variables = explode(';', $row['SystemVariables']);
                $main .= '<form action="' . $_SERVER['REQUEST_URI'] . '" name="update_system_variables" method="post">';
                $main .= '<table width="80%"><tr><th>Variable Name</th><th>Value</th></tr>';
                foreach ($system_variables as $i => $v_string) {
                    $var = explode('=', $v_string);
                    if (count($var) == 2) {
                        $main .= '<tr id="system_var_' . $i . '">';
                        $main .= '<td><span style="font-weight: 800; font-size: 16px;">.</span><input name="system_var_names[]" value="' . $var[0] . '" readonly /></td>';
                        $main .= '<td><input name="system_var_values[]" value="' . $var[1] . '" readonly /></td>';
                        $main .= '</tr>';
                    }
                }
                $main .= '<tr id="system_var_' . ($i + 1) . '">';
                $main .= '<td><span style="font-weight: 800; font-size: 16px;">.</span><input name="system_var_names[]" /></td>';
                $main .= '<td><input name="system_var_values[]" /></td>';
                $main .= '</tr>';
                $main .= '</table>';
                $main .= '<p><input name="submit" value="Update System Variables" type="submit" /></p></form>';
                $main .= '<hr /><h2>System Components</h2><div style="float: left; width: 50%;">';
                $components = pts_result_file_analyzer::system_component_string_to_array($row['Hardware']);
                $main .= pts_webui::r2d_array_to_table($components) . '</div><div style="float: left; width: 50%;">';
                $components = pts_result_file_analyzer::system_component_string_to_array($row['Software']);
                $main .= pts_webui::r2d_array_to_table($components) . '</div>';
                $system_path = phoromatic_server::phoromatic_account_system_path($_SESSION['AccountID'], $row['SystemID']);
                $main .= '<hr />';
                if (is_file($system_path . 'sensors-pool.json')) {
                    $sensors = file_get_contents($system_path . 'sensors-pool.json');
                    $sensors = json_decode($sensors, true);
                    foreach ($sensors as $title => $s) {
                        if (!isset($s['values']) || count($s['values']) < 5 || max($s['values']) == min($s['values'])) {
                            continue;
                        }
                        $graph = new pts_sys_graph(array('title' => $title, 'x_scale' => 'm', 'y_scale' => $s['unit'], 'text_size' => 12, 'reverse_x_direction' => false, 'width' => 920, 'height' => 400));
                        $graph->render_base();
                        $svg_dom = $graph->render_graph_data($s['values']);
                        if ($svg_dom === false) {
                            continue;
                        }
                        $output_type = 'SVG';
                        $graph = $svg_dom->output(null, $output_type);
                        $main .= '<p align="center">' . substr($graph, strpos($graph, '<svg')) . '</p>';
                    }
                } else {
                    if (is_file($system_path . 'sensors.json')) {
                        $sensor_file = file_get_contents($system_path . 'sensors.json');
                        $sensor_file = json_decode($sensor_file, true);
                        if ($sensor_file && isset($sensor_file['sensors']) && !empty($sensor_file['sensors'])) {
                            $i = 0;
                            $col = array(1 => array(), 2 => array(), 3 => array(), 0 => array());
                            foreach ($sensor_file['sensors'] as $name => $sensor) {
                                array_push($col[$i % 4], '<strong>' . $name . ':</strong> ' . $sensor['value'] . ' ' . $sensor['unit']);
                                $i++;
                            }
                            $main .= '<h2>System Sensors</h2>';
                            foreach ($col as $sensors) {
                                $main .= '<div style="float: left; width: 25%;">';
                                foreach ($sensors as $sensor) {
                                    $main .= '<p>' . $sensor . '</p>';
                                }
                                $main .= '</div>';
                            }
                            $main .= '<p><em><strong>Last Updated:</strong>' . date('d F H:i', filemtime(phoromatic_server::phoromatic_account_system_path($_SESSION['AccountID'], $row['SystemID']) . 'sensors.json')) . ' <strong>System Uptime:</strong> ' . $sensor_file['uptime'] . ' Minutes</em></p>';
                        }
                    }
                }
                $log_file = phoromatic_server::phoromatic_account_system_path($_SESSION['AccountID'], $row['SystemID']) . 'phoronix-test-suite.log';
                if (is_file($log_file)) {
                    $main .= '<hr /><h2>Phoronix Test Suite Client Log</h2>';
                    $main .= '<p><textarea style="width: 60%; height: 200px;">' . file_get_contents($log_file) . '</textarea></p>';
                    $main .= '<p><em><strong>Last Updated:</strong>' . date('d F H:i', filemtime($log_file)) . '</em></p>';
                }
                $groups = explode('#', $row['Groups']);
                foreach ($groups as $i => $group) {
                    if (empty($group)) {
                        unset($groups[$i]);
                    }
                }
                $schedules = phoromatic_server::schedules_that_run_on_system($_SESSION['AccountID'], $row['SystemID']);
                if (!empty($groups) || !empty($schedules)) {
                    $main .= '<hr /><h2>Schedules</h2>';
                    if (!empty($groups)) {
                        $group_msg = 'This system belongs to the following groups: <strong>' . implode(', ', $groups) . '</strong>.';
                    } else {
                        $group_msg = 'This system does not currently belong to any groups.';
                    }
                    $main .= '<p>' . $group_msg . ' Manage groups via the <a href="?systems">systems page</a>.</p>';
                    if (!empty($schedules)) {
                        $main .= '<div class="pts_phoromatic_info_box_area" style="margin: 0 10%;"><ul><li><h1>Schedules Running On This System</h1></li>';
                        foreach ($schedules as &$row) {
                            $group_count = empty($row['RunTargetGroups']) ? 0 : count(explode(',', $row['RunTargetGroups']));
                            $main .= '<a href="?schedules/' . $row['ScheduleID'] . '"><li>' . $row['Title'] . '<br /><table><tr><td>' . pts_strings::plural_handler(count(phoromatic_server::systems_associated_with_schedule($_SESSION['AccountID'], $row['ScheduleID'])), 'System') . '</td><td>' . pts_strings::plural_handler($group_count, 'Group') . '</td><td>' . pts_strings::plural_handler(phoromatic_results_for_schedule($row['ScheduleID']), 'Result') . '</td><td><strong>' . phoromatic_schedule_activeon_string($row['ActiveOn'], $row['RunAt']) . '</strong></td></tr></table></li></a>';
                        }
                        $main .= '</ul></div>';
                    }
                }
                $stmt = phoromatic_server::$db->prepare('SELECT Title, SystemID, ScheduleID, PPRID, UploadTime FROM phoromatic_results WHERE AccountID = :account_id AND SystemID = :system_id ORDER BY UploadTime DESC');
                $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                $stmt->bindValue(':system_id', $PATH[0]);
                $test_result_result = $stmt->execute();
                $test_result_row = $test_result_result->fetchArray();
                $results = 0;
                if ($test_result_row != false) {
                    $main .= '<hr /><h2>Test Results</h2>';
                    $main .= '<div class="pts_phoromatic_info_box_area" style="margin: 0 10%;">';
                    $main .= '<ul><li><h1>Recent Test Results</h1></li>';
                    do {
                        if ($results > 20) {
                            break;
                        }
                        $main .= '<a href="?result/' . $test_result_row['PPRID'] . '"><li>' . $test_result_row['Title'] . '<br /><table><tr><td>' . phoromatic_system_id_to_name($test_result_row['SystemID']) . '</td><td>' . phoromatic_user_friendly_timedate($test_result_row['UploadTime']) . '</td></tr></table></li></a>';
                        $results++;
                    } while ($test_result_row = $test_result_result->fetchArray());
                }
                if ($results > 0) {
                    $main .= '</ul></div>';
                }
                // Any System Errors?
                $stmt = phoromatic_server::$db->prepare('SELECT ErrorMessage, UploadTime, SystemID, TestIdentifier FROM phoromatic_system_client_errors WHERE AccountID = :account_id AND SystemID = :system_id ORDER BY UploadTime DESC LIMIT 10');
                $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                $stmt->bindValue(':system_id', $PATH[0]);
                $result = $stmt->execute();
                $row = $result->fetchArray();
                if ($row != false) {
                    $main .= '<hr /><div class="pts_phoromatic_info_box_area" style="margin: 0 10%;"><ul><li><h1>Recent System Warnings &amp; Errors</h1></li>';
                    do {
                        $main .= '<a onclick=""><li>' . $row['ErrorMessage'] . '<br /><table><tr><td>' . $row['UploadTime'] . '</td><td>' . $row['TestIdentifier'] . '</td></tr></table></li></a>';
                    } while ($row = $result->fetchArray());
                    $main .= '	</ul></div>';
                }
            }
        }
        if ($main == null) {
            if (!PHOROMATIC_USER_IS_VIEWER && isset($_POST['new_group']) && !empty($_POST['new_group'])) {
                $group = trim($_POST['new_group']);
                if ($group) {
                    $stmt = phoromatic_server::$db->prepare('INSERT INTO phoromatic_groups (AccountID, GroupName) VALUES (:account_id, :group_name)');
                    $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                    $stmt->bindValue(':group_name', $group);
                    $result = $stmt->execute();
                    phoromatic_add_activity_stream_event('groups', $group, 'added');
                    if (!empty($_POST['systems_for_group']) && is_array($_POST['systems_for_group'])) {
                        foreach ($_POST['systems_for_group'] as $sid) {
                            // Find current groups
                            $stmt = phoromatic_server::$db->prepare('SELECT Groups FROM phoromatic_systems WHERE AccountID = :account_id AND SystemID = :system_id ORDER BY LastCommunication DESC');
                            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                            $stmt->bindValue(':system_id', $sid);
                            $result = $stmt->execute();
                            $row = $result->fetchArray();
                            $existing_groups = $row != false ? $row['Groups'] : null;
                            // Append new Group
                            $stmt = phoromatic_server::$db->prepare('UPDATE phoromatic_systems SET Groups = :new_group WHERE AccountID = :account_id AND SystemID = :system_id');
                            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                            $stmt->bindValue(':system_id', $sid);
                            $stmt->bindValue(':new_group', $existing_groups . '#' . $group . '#');
                            $stmt->execute();
                        }
                    }
                }
            } else {
                if (!PHOROMATIC_USER_IS_VIEWER && isset($_POST['system_group_update'])) {
                    $stmt = phoromatic_server::$db->prepare('SELECT SystemID FROM phoromatic_systems WHERE AccountID = :account_id');
                    $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                    $result = $stmt->execute();
                    phoromatic_add_activity_stream_event('groups', null, 'modified');
                    while ($row = $result->fetchArray()) {
                        if (isset($_POST['groups_' . $row['SystemID']])) {
                            $group_string = null;
                            foreach ($_POST['groups_' . $row['SystemID']] as $group) {
                                if ($group != null) {
                                    $group_string .= '#' . $group . '#';
                                }
                            }
                            $stmt1 = phoromatic_server::$db->prepare('UPDATE phoromatic_systems SET Groups = :new_groups WHERE AccountID = :account_id AND SystemID = :system_id');
                            $stmt1->bindValue(':account_id', $_SESSION['AccountID']);
                            $stmt1->bindValue(':system_id', $row['SystemID']);
                            $stmt1->bindValue(':new_groups', $group_string);
                            $stmt1->execute();
                        }
                    }
                } else {
                    if (!PHOROMATIC_USER_IS_VIEWER && isset($_POST['remove_group'])) {
                        $stmt = phoromatic_server::$db->prepare('DELETE FROM phoromatic_groups WHERE AccountID = :account_id AND GroupName = :group_name');
                        $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                        $stmt->bindValue(':group_name', $_POST['remove_group']);
                        $stmt->execute();
                        phoromatic_add_activity_stream_event('groups', $group, 'removed');
                        $stmt = phoromatic_server::$db->prepare('SELECT SystemID, Groups FROM phoromatic_systems WHERE AccountID = :account_id AND Groups LIKE \'%#' . $_POST['remove_group'] . '#%\'');
                        $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                        $result = $stmt->execute();
                        while ($row = $result->fetchArray()) {
                            $revised_groups = str_replace('#' . $_POST['remove_group'] . '#', null, $row['Groups']);
                            $stmt1 = phoromatic_server::$db->prepare('UPDATE phoromatic_systems SET Groups = :new_groups WHERE AccountID = :account_id AND SystemID = :system_id');
                            $stmt1->bindValue(':account_id', $_SESSION['AccountID']);
                            $stmt1->bindValue(':system_id', $row['SystemID']);
                            $stmt1->bindValue(':new_groups', $revised_groups);
                            $stmt1->execute();
                        }
                    }
                }
            }
            $main = '<h1>Test Systems</h1>';
            if (!PHOROMATIC_USER_IS_VIEWER) {
                $main .= phoromatic_systems_needing_attention();
                $main .= '<h2>Add A System</h2>
				<p>To connect a <a href="http://www.phoronix-test-suite.com/">Phoronix Test Suite</a> test system to this account for remotely managing and/or carrying out routine automated benchmarking, follow these simple and quick steps:</p>
				<ol><li>From a system with <em>Phoronix Test Suite 5.4 or newer</em> run <strong>phoronix-test-suite phoromatic.connect ' . phoromatic_web_socket_server_addr() . '</strong>. (The test system must be able to access this server\'s correct IP address / domain name.)</li><li>When you have run the command from the test system, you will need to log into this page on Phoromatic server again where you can approve the system and configure the system settings so you can begin using it as part of this Phoromatic account.</li><li>Repeat the two steps for as many systems as you would like! When you are all done -- if you haven\'t done so already, you can start creating test schedules, groups, and other Phoromatic events.</li></ol>
				<p>Those having to connect many Phoronix Test Suite Phoromatic clients can also attempt <a href="?system_claim">adding the server configuration</a> via SSH or an IP/MAC address claim.</p>
				<p><button onclick="javascript:window.location.replace(\'?system_claim\');">Add Via SSH Or IP/MAC Claim</button></p>';
            }
            $main .= '<hr />

			<h2>Systems</h2>
			<div class="pts_phoromatic_info_box_area" style="margin: 0 10%;">

					<ul>
						<li><h1>Active Systems</h1></li>';
            $stmt = phoromatic_server::$db->prepare('SELECT Title, SystemID, LocalIP, CurrentTask, LastCommunication, EstimatedTimeForTask, TaskPercentComplete FROM phoromatic_systems WHERE AccountID = :account_id AND State >= 0 ORDER BY LastCommunication DESC');
            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
            $result = $stmt->execute();
            $row = $result->fetchArray();
            $active_system_count = 0;
            if ($row == false) {
                $main .= '<li class="light" style="text-align: center;">No Systems Found</li>';
            } else {
                do {
                    $acti = phoromatic_compute_estimated_time_remaining_string($row['EstimatedTimeForTask'], $row['LastCommunication']) . ($row['TaskPercentComplete'] > 0 ? ' [' . $row['TaskPercentComplete'] . '% Complete]' : null);
                    if (empty($acti)) {
                        $next_job_in = phoromatic_server::time_to_next_scheduled_job($_SESSION['AccountID'], $row['SystemID']);
                        if ($next_job_in > 0) {
                            if ($next_job_in > 600) {
                                $next_job_in = round($next_job_in / 60);
                                $next_unit = 'hours';
                            } else {
                                $next_unit = 'minutes';
                            }
                            $acti = 'Next job in ' . $next_job_in . ' ' . $next_unit;
                        }
                    }
                    $main .= '<a href="?systems/' . $row['SystemID'] . '"><li>' . $row['Title'] . '<br /><table><tr><td>' . $row['LocalIP'] . '</td><td><strong>' . $row['CurrentTask'] . '</strong></td><td><strong>' . $acti . '</strong></td><td><strong>Last Communication:</strong> ' . date('j F Y H:i', strtotime($row['LastCommunication'])) . '</td></tr></table></li></a>';
                    $active_system_count++;
                } while ($row = $result->fetchArray());
            }
            $main .= '</ul>';
            $stmt = phoromatic_server::$db->prepare('SELECT Title, SystemID, LocalIP, CurrentTask, LastCommunication, EstimatedTimeForTask, TaskPercentComplete FROM phoromatic_systems WHERE AccountID = :account_id AND State < 0 ORDER BY LastCommunication DESC');
            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
            $result = $stmt->execute();
            $row = $result->fetchArray();
            if ($row != false) {
                $main .= '<ul>
				<li><h1>Inactive Systems</h1></li>';
                do {
                    $main .= '<a href="?systems/' . $row['SystemID'] . '"><li>' . $row['Title'] . '<br /><table><tr><td>' . $row['LocalIP'] . '</td><td><strong>' . $row['CurrentTask'] . '</strong></td><td><strong>Deactivated</strong></td><td><strong>Last Communication:</strong> ' . date('j F Y H:i', strtotime($row['LastCommunication'])) . '</td></tr></table></li></a>';
                } while ($row = $result->fetchArray());
                $main .= '</ul>';
            }
            $main .= '</div>';
            if ($active_system_count > 2) {
                $main .= '<h3 align="center"><a href="/?component_table">System Component Table</a> | <a href="/?maintenance_table">System Maintenance Table</a> | <a href="/?dashboard">System Dashboard</a></h3>';
            }
            if (!PHOROMATIC_USER_IS_VIEWER) {
                $main .= '<hr />
				<h2>System Groups</h2>
				<p>System groups make it very easy to organize multiple test systems for targeting by test schedules. You can always add/remove systems to groups, create new groups, and add systems to multiple groups. After creating a group and adding systems to the group, you can begin targeting tests against a particular group of systems. Systems can always be added/removed from groups later and a system can belong to multiple groups.</p>';
                $main .= '<div style="float: left;"><form name="new_group_form" id="new_group_form" action="?systems" method="post" onsubmit="return phoromatic_new_group(this);">
				<p><div style="width: 200px; font-weight: bold; float: left;">New Group Name:</div> <input type="text" style="width: 300px;" name="new_group" value="" /></p>
				<p><div style="width: 200px; font-weight: bold; float: left;">Select System(s) To Add To Group:</div><select name="systems_for_group[]" multiple="multiple" style="width: 300px;">';
                $stmt = phoromatic_server::$db->prepare('SELECT Title, SystemID FROM phoromatic_systems WHERE AccountID = :account_id AND State >= 0 ORDER BY Title ASC');
                $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                $result = $stmt->execute();
                $row = $result->fetchArray();
                if ($row != false) {
                    do {
                        $main .= '<option value="' . $row['SystemID'] . '">' . $row['Title'] . '</option>';
                    } while ($row = $result->fetchArray());
                }
                $main .= '</select></p>
				<p><div style="width: 200px; font-weight: bold; float: left;">&nbsp;</div> <input type="submit" value="Create Group" /></p></form></div>';
                $stmt = phoromatic_server::$db->prepare('SELECT GroupName FROM phoromatic_groups WHERE AccountID = :account_id ORDER BY GroupName ASC');
                $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                $result = $stmt->execute();
                $row = $result->fetchArray();
                if ($row != false) {
                    $main .= '<div style="float: left; margin-left: 90px;"><h3>Current System Groups</h3>';
                    do {
                        $stmt_count = phoromatic_server::$db->prepare('SELECT COUNT(SystemID) AS system_count FROM phoromatic_systems WHERE AccountID = :account_id AND State >= 0 AND Groups LIKE \'%#' . $row['GroupName'] . '#%\'');
                        $stmt_count->bindValue(':account_id', $_SESSION['AccountID']);
                        $result_count = $stmt_count->execute();
                        $row_count = $result_count->fetchArray();
                        $row_count['system_count'] = isset($row_count['system_count']) ? $row_count['system_count'] : 0;
                        $main .= '<div style="clear: both;"><div style="width: 200px; float: left; font-weight: bold;">' . $row['GroupName'] . '</div> ' . $row_count['system_count'] . ' System' . ($row_count['system_count'] != 1 ? 's' : '') . '</div>';
                    } while ($row = $result->fetchArray());
                    $main .= '</div>';
                    $main .= '<hr /><a name="group_edit"></a><h2>System Group Editing</h2><div style="text-align: center;"><form action="' . $_SERVER['REQUEST_URI'] . '" name="update_groups" method="post"><input type="hidden" name="system_group_update"  value="1" />';
                    $main .= '<table style="margin: 5px auto; overflow: auto;">';
                    $main .= '<tr>';
                    $main .= '<th></th>';
                    $stmt = phoromatic_server::$db->prepare('SELECT GroupName FROM phoromatic_groups WHERE AccountID = :account_id ORDER BY GroupName ASC');
                    $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                    $result = $stmt->execute();
                    $all_groups = array();
                    while ($row = $result->fetchArray()) {
                        $main .= '<th>' . $row['GroupName'] . '</th>';
                        array_push($all_groups, $row['GroupName']);
                    }
                    $main .= '</tr>';
                    $stmt = phoromatic_server::$db->prepare('SELECT Title, SystemID, Groups FROM phoromatic_systems WHERE AccountID = :account_id AND State >= 0 ORDER BY Title ASC');
                    $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                    $result = $stmt->execute();
                    while ($row = $result->fetchArray()) {
                        $main .= '<tr>';
                        $main .= '<th>' . $row['Title'] . '</th>';
                        $main .= '<input type="hidden" name="groups_' . $row['SystemID'] . '[]" value="" />';
                        foreach ($all_groups as $group) {
                            $checked = stripos($row['Groups'], '#' . $group . '#') !== false ? 'checked="checked" ' : null;
                            $main .= '<td><input type="checkbox" name="groups_' . $row['SystemID'] . '[]" value="' . $group . '" ' . $checked . '/></td>';
                        }
                        $main .= '</tr>';
                    }
                    $main .= '</table><p><input name="submit" value="Update Groups" type="submit" /></p></form></div>';
                    $main .= '<hr /><h2>Remove A Group</h2><p>Removing a group is a permanent action that cannot be undone.</p>';
                    $main .= '<p><form action="' . $_SERVER['REQUEST_URI'] . '" name="remove_group" method="post"><select name="remove_group" id="remove_group">';
                    foreach ($all_groups as $group) {
                        $main .= '<option value="' . $group . '">' . $group . '</option>';
                    }
                    $main .= '</select> <input name="submit" value="Remove Group" type="submit" /></form></p>';
                }
            }
        }
        $right = '<ul><li>Active Systems</li>';
        $stmt = phoromatic_server::$db->prepare('SELECT Title, SystemID FROM phoromatic_systems WHERE AccountID = :account_id AND State > 0 ORDER BY Title ASC');
        $stmt->bindValue(':account_id', $_SESSION['AccountID']);
        $result = $stmt->execute();
        $row = $result->fetchArray();
        if ($row == false) {
            $right .= '</ul><p style="text-align: left; margin: 6px 10px;">No Systems Found</p>';
        } else {
            do {
                $right .= '<li><a href="?systems/' . $row['SystemID'] . '">' . $row['Title'] . '</a></li>';
            } while ($row = $result->fetchArray());
            $right .= '</ul>';
        }
        echo '<div id="pts_phoromatic_main_area">' . $main . '</div>';
        echo phoromatic_webui_footer();
    }
    public static function render_page_process($PATH)
    {
        echo phoromatic_webui_header_logged_in();
        $main = '<h1>Phoromatic</h1>';
        $main .= phoromatic_systems_needing_attention();
        $main .= '<p>Phoromatic is the remote management and test orchestration component to the <a href="http://www.phoronix-test-suite.com/">Phoronix Test Suite</a>. Phoromatic allows you to take advantage of the Phoronix Test Suite\'s vast feature-set across multiple systems over the LAN/WAN, manage entire test farms of systems for benchmarking via a centralized interface, centrally collect test results, and carry out other enteprise-focused tasks.</p>';
        $main_page_message = phoromatic_server::read_setting('main_page_message');
        if (!PHOROMATIC_USER_IS_VIEWER) {
            $main .= '<p>To get started with your new account, the basic steps to get started include:</p>
				<ol>
					<li>Connect/sync the Phoronix Test Suite client systems (the systems to be benchmarked) to this account. In the simplest form, you just need to run the following command on the test systems: <strong>phoronix-test-suite phoromatic.connect ' . phoromatic_web_socket_server_addr() . '</strong>. For more information view the instructions on the <a href="?systems">systems page</a>.</li>
					<li>Configure your <a href="?settings">account settings</a>.</li>
					<li><a href="?schedules">Create a test schedule</a>. A schedule is for running test(s) on selected system(s) on a routine, timed basis or whenever a custom trigger is passed to the Phoromatic server. A test schedule could be for running benchmarks on a daily basis, whenever a new Git commit is applied to a code-base, or other events occurred. You can also enrich the potential by adding pre/post-test hooks for ensuring the system is set to a proper state for benchmarking. Alternatively, you can <a href="?benchmark">create a benchmark ticket</a> for one-time testing on one or more systems.</li>
					<li>View the automatically generated <a href="?results">test results</a>.</li>';
            if (!empty($main_page_message)) {
                $main .= '<li><strong>' . $main_page_message . '</strong></li>';
            } else {
                $main .= '<li><strong>If you are interested in Phoromatic and the Phoronix Test Suite for enterprise testing, please <a href="http://commercial.phoronix-test-suite.com/">contact us</a> for commercial support, custom test development, custom engineering services, and other professional services. It\'s not without corporate support and sponsorship that we can continue to develop this leading open-source Linux benchmarking software. If you run into any problems with our open-source software or would like to contribute patches, you can do so via our <a href="https://www.github.com/phoronix-test-suite/phoronix-test-suite">GitHub project</a>.</strong></li>
				</ol>';
            }
        } else {
            if (!empty($main_page_message)) {
                $main .= '<p><strong>' . $main_page_message . '</strong></p>';
            }
        }
        $main .= '<hr /><div id="phoromatic_fixed_main_table">';
        $systems_needing_attention = phoromatic_server::systems_appearing_down($_SESSION['AccountID']);
        $systems_idling = phoromatic_server::systems_idling($_SESSION['AccountID']);
        $systems_shutdown = phoromatic_server::systems_shutdown($_SESSION['AccountID']);
        $systems_running_tests = phoromatic_server::systems_running_tests($_SESSION['AccountID']);
        $main .= '<div id="phoromatic_main_table_cell">
			<h2>' . pts_strings::plural_handler(count($systems_running_tests), 'System') . ' Running Tests</h2>
			<h2>' . pts_strings::plural_handler(count($systems_idling), 'System') . ' Idling</h2>
			<h2>' . pts_strings::plural_handler(count($systems_shutdown), 'System') . ' Shutdown</h2>
			<h2>' . pts_strings::plural_handler(count($systems_needing_attention), 'System') . ' Needing Attention</h2>';
        $main .= '<hr /><h2>Systems Running Tests</h2>';
        $stmt = phoromatic_server::$db->prepare('SELECT * FROM phoromatic_systems WHERE AccountID = :account_id AND State >= 0 AND CurrentTask NOT LIKE \'%Idling%\' AND CurrentTask NOT LIKE \'%Shutdown%\' ORDER BY LastCommunication DESC');
        $stmt->bindValue(':account_id', $_SESSION['AccountID']);
        $result = $stmt->execute();
        while ($result && ($row = $result->fetchArray())) {
            $main .= '<div class="phoromatic_overview_box">';
            $main .= '<h1><a href="?systems/' . $row['SystemID'] . '">' . $row['Title'] . '</a></h1>';
            $main .= $row['CurrentTask'] . '<br />';
            if (!empty($row['CurrentProcessSchedule'])) {
                $main .= '<a href="?schedules/' . $row['CurrentProcessSchedule'] . '">' . phoromatic_server::schedule_id_to_name($row['CurrentProcessSchedule']) . '</a><br />';
            }
            $time_remaining = phoromatic_compute_estimated_time_remaining($row['EstimatedTimeForTask'], $row['LastCommunication']);
            if ($time_remaining) {
                $main .= '<em>~ ' . pts_strings::plural_handler($time_remaining, 'Minute') . ' Remaining</em>';
            }
            $main .= '</div>';
        }
        $main .= '</div>';
        $schedules_today = phoromatic_server::schedules_today($_SESSION['AccountID']);
        $schedules_total = phoromatic_server::schedules_total($_SESSION['AccountID']);
        $benchmark_tickets_today = phoromatic_server::benchmark_tickets_today($_SESSION['AccountID']);
        $main .= '<div id="phoromatic_main_table_cell">
		<h2>' . pts_strings::plural_handler(count($schedules_today), 'Schedule') . ' Active Today</h2>
		<h2>' . pts_strings::plural_handler(count($schedules_total), 'Schedule') . ' In Total</h2>
		<h2>' . pts_strings::plural_handler(count($benchmark_tickets_today), 'Active Benchmark Ticket') . '</h2>
		<h2> &nbsp; </h2>';
        $main .= '<hr /><h2>Today\'s Scheduled Tests</h2>';
        foreach ($schedules_today as &$row) {
            $systems_for_schedule = phoromatic_server::systems_associated_with_schedule($_SESSION['AccountID'], $row['ScheduleID']);
            $extra_css = null;
            if (empty($systems_for_schedule)) {
                $extra_css = ' opacity: 0.4;';
            }
            list($h, $m) = explode('.', $row['RunAt']);
            $main .= '<div style="' . $extra_css . '" class="phoromatic_overview_box">';
            $main .= '<h1><a href="?schedules/' . $row['ScheduleID'] . '">' . $row['Title'] . '</a></h1>';
            if (!empty($systems_for_schedule)) {
                if ($row['RunAt'] > date('H.i')) {
                    $run_in_future = true;
                    $main .= '<h3>Runs In ' . pts_strings::format_time($h * 60 + $m - (date('H') * 60 + date('i')), 'MINUTES') . '</h3>';
                } else {
                    $run_in_future = false;
                    $main .= '<h3>Triggered ' . pts_strings::format_time(max(1, date('H') * 60 + date('i') - ($h * 60 + $m)), 'MINUTES') . ' Ago</h3>';
                }
            }
            foreach ($systems_for_schedule as $system_id) {
                $pprid = self::result_match($row['ScheduleID'], $system_id, date('Y-m-d'));
                if ($pprid) {
                    $main .= '<a href="?result/' . $pprid . '">';
                }
                $main .= phoromatic_server::system_id_to_name($system_id);
                if ($pprid) {
                    $main .= '</a>';
                } else {
                    if (!$run_in_future) {
                        $sys_info = self::system_info($system_id);
                        $last_comm_diff = time() - strtotime($sys_info['LastCommunication']);
                        $main .= ' <sup><a href="?systems/' . $system_id . '">';
                        if ($last_comm_diff > 3600) {
                            $main .= '<strong>Last Communication: ' . pts_strings::format_time($last_comm_diff, 'SECONDS', true, 60) . ' Ago</strong>';
                        } else {
                            $main .= $sys_info['CurrentTask'];
                        }
                        $main .= '</a></sup>';
                    }
                }
                $main .= '<br />';
            }
            $main .= '</div>';
        }
        $main .= '</div>';
        $results_today = phoromatic_server::test_results($_SESSION['AccountID'], strtotime('today'));
        $results_this_week = phoromatic_server::test_results($_SESSION['AccountID'], mktime(0, 0, 0, date('n'), date('j') - date('N') + 1));
        $results_total = phoromatic_server::test_results($_SESSION['AccountID'], null);
        $main .= '<div id="phoromatic_main_table_cell">
		<h2>' . pts_strings::plural_handler(count($results_today), 'Test Result') . ' Today</h2>
		<h2>' . pts_strings::plural_handler(count($results_this_week), 'Test Result') . ' This Week</h2>
		<h2>' . pts_strings::plural_handler(count($results_total), 'Test Result') . ' Total</h2>
		<h2>' . pts_strings::plural_handler(phoromatic_server::test_results_benchmark_count($_SESSION['AccountID']), 'Benchmark Result') . ' Total</h2>
		<hr /><h2>Today\'s Results</h2>';
        foreach ($results_today as $result) {
            $main .= '<h3><a href="?result/' . $result['PPRID'] . '">' . $result['Title'] . '</a></h3>';
        }
        $main .= '</div>';
        $main .= '</div>';
        /*
        		$has_flagged_results = false;
        		$stmt = phoromatic_server::$db->prepare('SELECT ScheduleID, GROUP_CONCAT(SystemID,\',\') AS Systems FROM phoromatic_results WHERE AccountID = :account_id AND ScheduleID NOT LIKE 0 GROUP BY ScheduleID ORDER BY UploadTime DESC');
        		$stmt->bindValue(':account_id', $_SESSION['AccountID']);
        		$test_result_result = $stmt->execute();
        		while($test_result_row = $test_result_result->fetchArray())
        		{
        			$systems = array_count_values(explode(',', $test_result_row['Systems']));
        
        			foreach($systems as $system_id => $system_count)
        			{
        				if($system_count < 2)
        					unset($systems[$system_id]);
        			}
        
        			$printed_schedule_name = false;
        			if(!empty($systems))
        			{
        				foreach(array_keys($systems) as $system_id)
        				{
        					$stmt_uploads = phoromatic_server::$db->prepare('SELECT PPRID, UploadID FROM phoromatic_results WHERE AccountID = :account_id AND SystemID = :system_id AND ScheduleID = :schedule_id ORDER BY UploadTime DESC LIMIT 2');
        					$stmt_uploads->bindValue(':account_id', $_SESSION['AccountID']);
        					$stmt_uploads->bindValue(':system_id', $system_id);
        					$stmt_uploads->bindValue(':schedule_id', $test_result_row['ScheduleID']);
        					$result_uploads = $stmt_uploads->execute();
        
        					$result_file = array();
        					$pprids = array();
        					while($result_uploads_row = $result_uploads->fetchArray())
        					{
        						$composite_xml = phoromatic_server::phoromatic_account_result_path($_SESSION['AccountID'], $result_uploads_row['UploadID']) . 'composite.xml';
        						if(is_file($composite_xml))
        						{
        							array_push($result_file, new pts_result_merge_select($composite_xml));
        						}
        						array_push($pprids, $result_uploads_row['PPRID']);
        					}
        					$result_file = array_reverse($result_file);
        
        					if(count($result_file) == 2)
        					{
        						$writer = new pts_result_file_writer(null);
        						$attributes = array();
        						pts_merge::merge_test_results_process($writer, $result_file, $attributes);
        						$result_file = new pts_result_file($writer->get_xml());
        
        						foreach($result_file->get_result_objects('ONLY_CHANGED_RESULTS') as $i => $result_object)
        						{
        							$vari = round($result_object->largest_result_variation(), 3);
        							if(abs($vari) < 0.03)
        								continue;
        							if(!$has_flagged_results)
        							{
        								$main .= '<hr /><h2>Flagged Results</h2>';
        								$main .= '<p>Displayed are results for each system of each scheduled test where there is a measurable change (currently set to a 0.1% threshold) when comparing the most recent result to the previous result for that system for that test schedule. Click on the change to jump to that individualized result file comparison.</p>';
        								$main .= '<span style="font-size: 80%;">';
        								$has_flagged_results = true;
        							}
        							if(!$printed_schedule_name)
        							{
        								$main .= '<h3>' . phoromatic_schedule_id_to_name($test_result_row['ScheduleID']) . '</h3><p>';
        								$printed_schedule_name = true;
        							}
        
        							$pcolor = $vari > 0 ? 'green' : 'red';
        
        							$main .= '<a href="?result/' . implode(',', $pprids) . '#' . $result_object->get_comparison_hash(true, false) . '"><span style="color: ' . $pcolor . ';"><strong>' . phoromatic_system_id_to_name($system_id) . ' - ' . $result_object->test_profile->get_title() . ':</strong> ' . implode(' &gt; ', $result_file->get_system_identifiers()) . ': ' . ($vari * 100) . '%</span></a><br />';
        						}
        					}
        				}
        			}
        			if($printed_schedule_name)
        				$main .= '</p>';
        		}
        		if($has_flagged_results)
        			$main .= '</span>';
        */
        // ACTIVE TEST SCHEDULES
        /*
        $main .= '<div style="float: left; width: 50%;"><ul><li><h1>Active Test Schedules</h1></li>';
        $stmt = phoromatic_server::$db->prepare('SELECT Title, ScheduleID, Description, RunTargetSystems, RunTargetGroups, ActiveOn, RunAt FROM phoromatic_schedules WHERE AccountID = :account_id AND State >= 1 ORDER BY Title ASC');
        $stmt->bindValue(':account_id', $_SESSION['AccountID']);
        $result = $stmt->execute();
        $row = $result->fetchArray();
        
        if($row == false)
        {
        	$main .= '<li class="light" style="text-align: center;">No Schedules Found</li>';
        }
        else
        {
        	do
        	{
        		$group_count = empty($row['RunTargetGroups']) ? 0 : count(explode(',', $row['RunTargetGroups']));
        		$main .= '<a href="?schedules/' . $row['ScheduleID'] . '"><li>' . $row['Title'] . '<br /><table><tr><td>' . pts_strings::plural_handler(count(phoromatic_server::systems_associated_with_schedule($_SESSION['AccountID'], $row['ScheduleID'])), 'System') . '</td><td>' . pts_strings::plural_handler($group_count, 'Group') . '</td><td>' . pts_strings::plural_handler(phoromatic_results_for_schedule($row['ScheduleID']), 'Result') . '</td><td><strong>' . phoromatic_schedule_activeon_string($row['ActiveOn'], $row['RunAt']) . '</strong></td></tr></table></li></a>';
        	}
        	while($row = $result->fetchArray());
        }
        $main .= '</ul></div>';
        */
        echo '<div id="pts_phoromatic_main_area">' . $main . '</div>';
        //echo phoromatic_webui_main($main, phoromatic_webui_right_panel_logged_in());
        echo phoromatic_webui_footer();
    }
    public static function render_page_process($PATH)
    {
        echo phoromatic_webui_header_logged_in();
        $main = null;
        if (isset($PATH[0]) && !empty($PATH[0])) {
            ini_set('memory_limit', '4G');
            if (isset($_POST['view_results_from_past']) && is_numeric($_POST['view_results_from_past'])) {
                $cut_duration = $_POST['view_results_from_past'];
            } else {
                $cut_duration = 21;
            }
            $stmt = phoromatic_server::$db->prepare('SELECT UploadID, UploadTime, ScheduleID, Trigger, SystemID FROM phoromatic_results WHERE AccountID = :account_id AND ScheduleID = :schedule_id ORDER BY UploadTime DESC');
            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
            $stmt->bindValue(':schedule_id', $PATH[0]);
            $test_result_result = $stmt->execute();
            $cutoff_time = is_numeric($cut_duration) ? strtotime('today -' . $cut_duration . ' days') : false;
            $show_only_latest_systems = array();
            $result_files = array();
            while ($test_result_result && ($row = $test_result_result->fetchArray())) {
                if ($cutoff_time !== false && strtotime($row['UploadTime']) < $cutoff_time) {
                    break;
                }
                $composite_xml = phoromatic_server::phoromatic_account_result_path($_SESSION['AccountID'], $row['UploadID']) . 'composite.xml';
                if (!is_file($composite_xml)) {
                    continue;
                }
                // Add to result file
                $system_name = phoromatic_server::system_id_to_name($row['SystemID']) . ': ' . $row['Trigger'];
                array_push($result_files, new pts_result_merge_select($composite_xml, null, $system_name));
                if (!isset($show_only_latest_systems[$_SESSION['AccountID'] . $row['SystemID']])) {
                    $show_only_latest_systems[$_SESSION['AccountID'] . $row['SystemID']] = new pts_result_merge_select($composite_xml, null, $system_name);
                }
            }
            if (count($result_files) < 21) {
                $show_only_latest_systems = null;
            }
            $attributes = array('new_result_file_title' => phoromatic_schedule_id_to_name($row['ScheduleID']));
            $result_file = new pts_result_file(null, true);
            $result_file->merge($result_files, $attributes);
            $extra_attributes = array('reverse_result_buffer' => true, 'force_simple_keys' => true, 'force_line_graph_compact' => true, 'force_tracking_line_graph' => true);
            if (isset($_POST['normalize_results']) && $_POST['normalize_results']) {
                $extra_attributes['normalize_result_buffer'] = true;
            }
            $main .= '<h1>' . $result_file->get_title() . '</h1>';
            if ($result_file->get_system_count() == 1 || ($intent = pts_result_file_analyzer::analyze_result_file_intent($result_file, $intent, true))) {
                $table = new pts_ResultFileCompactSystemsTable($result_file, $intent);
            } else {
                $table = new pts_ResultFileSystemsTable($result_file);
            }
            $main .= '<p style="text-align: center; overflow: auto;" class="result_object">' . pts_render::render_graph_inline_embed($table, $result_file, $extra_attributes) . '</p>';
            $table = new pts_ResultFileTable($result_file, $intent);
            $main .= '<p style="text-align: center; overflow: auto;" class="result_object">' . pts_render::render_graph_inline_embed($table, $result_file, $extra_attributes) . '</p>';
            $main .= '<div id="pts_results_area">';
            foreach ($result_file->get_result_objects(isset($_POST['show_only_changed_results']) ? 'ONLY_CHANGED_RESULTS' : -1) as $i => $result_object) {
                $main .= '<h2><a name="r-' . $i . '"></a><a name="' . $result_object->get_comparison_hash(true, false) . '"></a>' . $result_object->test_profile->get_title() . '</h2>';
                $main .= '<p class="result_object">';
                $main .= pts_render::render_graph_inline_embed($result_object, $result_file, $extra_attributes);
                $main .= '</p>';
            }
            $main .= '</div>';
            $right = '<form action="' . $_SERVER['REQUEST_URI'] . '" name="update_result_view" method="post">';
            $right .= '<p>Compare results for the past: ';
            $right .= '<select name="view_results_from_past" id="view_results_from_past">';
            $oldest_upload_time = strtotime(phoromatic_oldest_result_for_schedule($PATH[0]));
            $opts = array('Two Weeks' => 14, 'Three Weeks' => 21, 'One Month' => 30, 'Two Months' => 60, 'Quarter' => 90, 'Six Months' => 180, 'Year' => 365);
            foreach ($opts as $str_name => $time_offset) {
                if ($oldest_upload_time > time() - 86400 * $time_offset) {
                    break;
                }
                $right .= '<option value="' . $time_offset . '">' . $str_name . '</option>';
            }
            $right .= '<option value="all">All Results</option>';
            $right .= '</select>';
            $right .= '</p>';
            $right .= '<p><input type="checkbox" name="normalize_results" value="1" ' . (isset($_POST['normalize_results']) ? 'checked="checked" ' : null) . '/> Normalize Results?</p>';
            $right .= '<p><input type="submit" value="Refresh Results"></p></form>';
        } else {
            if (empty($PATH)) {
                $main .= '<h1>Phoromatic Tracker</h1>
					<p>The Phoromatic Tracker will show result schedules that have enough uploaded test results from the associated systems to begin providing concise overviews of performance over time.</p>
					<div class="pts_phoromatic_info_box_area">
					<ul>
						<li><h1>Trackable Results</h1></li>';
                $stmt = phoromatic_server::$db->prepare('SELECT Title, ScheduleID, Description, RunTargetSystems, RunTargetGroups, RunAt, ActiveOn, (SELECT COUNT(*) FROM phoromatic_results WHERE ScheduleID = phoromatic_schedules.ScheduleID) AS UploadedResultCount FROM phoromatic_schedules WHERE AccountID = :account_id AND State >= 1 ORDER BY Title ASC');
                $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                $result = $stmt->execute();
                $row = $result->fetchArray();
                if ($row == false) {
                    $main .= '<li class="light" style="text-align: center;">No Relevant Schedules Found</li>';
                } else {
                    do {
                        if ($row['UploadedResultCount'] > ($row['RunTargetSystems'] + $row['RunTargetGroups'] + 1) * 7) {
                            $stmt_tests = phoromatic_server::$db->prepare('SELECT COUNT(*) AS TestCount FROM phoromatic_schedules_tests WHERE AccountID = :account_id AND ScheduleID = :schedule_id ORDER BY TestProfile ASC');
                            $stmt_tests->bindValue(':account_id', $_SESSION['AccountID']);
                            $stmt_tests->bindValue(':schedule_id', $row['ScheduleID']);
                            $result_tests = $stmt_tests->execute();
                            $row_tests = $result_tests->fetchArray();
                            $test_count = !empty($row_tests) ? $row_tests['TestCount'] : 0;
                            $group_count = empty($row['RunTargetGroups']) ? 0 : count(explode(',', $row['RunTargetGroups']));
                            $main .= '<a href="?tracker/' . $row['ScheduleID'] . '"><li>' . $row['Title'] . '<br /><table><tr><td>' . pts_strings::plural_handler(count(phoromatic_server::systems_associated_with_schedule($_SESSION['AccountID'], $row['ScheduleID'])), 'System') . '</td><td>' . pts_strings::plural_handler($group_count, 'Group') . '</td><td>' . pts_strings::plural_handler($test_count, 'Test') . '</td><td>' . pts_strings::plural_handler($row['UploadedResultCount'], 'Result') . ' Total</td></tr></table></li></a>';
                        }
                    } while ($row = $result->fetchArray());
                }
                $main .= '</ul>
			</div>';
                $right = null;
            }
        }
        echo phoromatic_webui_main($main, $right);
        echo phoromatic_webui_footer();
    }
 public static function render_page_process($PATH)
 {
     if ($_SESSION['AdminLevel'] != -40) {
         header('Location: /?main');
     }
     $main = null;
     if (isset($_POST['new_phoromatic_path']) && !empty($_POST['new_phoromatic_path'])) {
         $new_dir = dirname($_POST['new_phoromatic_path']);
         if (!is_dir($new_dir)) {
             $main .= '<h2 style="color: red;"><em>' . $new_dir . '</em> must be a valid directory.</h2>';
         } else {
             if (!is_writable($new_dir)) {
                 $main .= '<h2 style="color: red;"><em>' . $new_dir . '</em> is not a writable location.</h2>';
             } else {
                 if (!is_dir($_POST['new_phoromatic_path'])) {
                     if (mkdir($_POST['new_phoromatic_path']) == false) {
                         $main .= '<h2 style="color: red;">Failed to make directory <em>' . $_POST['new_phoromatic_path'] . '</em>.</h2>';
                     }
                 }
                 if (is_dir($_POST['new_phoromatic_path'])) {
                     $new_phoromatic_dir = pts_strings::add_trailing_slash($_POST['new_phoromatic_path']);
                     $d = glob($new_phoromatic_dir . '*');
                     if (!empty($d)) {
                         $new_phoromatic_dir .= 'phoromatic/';
                         pts_file_io::mkdir($new_phoromatic_dir);
                     }
                     $d = glob($new_phoromatic_dir . '*');
                     if (!empty($d)) {
                         $main .= '<h2 style="color: red;"><em>' . $new_phoromatic_dir . '</em> must be an empty directory.</h2>';
                     } else {
                         if (pts_file_io::copy(phoromatic_server::phoromatic_path(), $new_phoromatic_dir)) {
                             pts_config::user_config_generate(array('PhoromaticStorage' => $new_phoromatic_dir));
                             header('Location: /?admin');
                         } else {
                             $main .= '<h2 style="color: red;"><em>Failed to copy old Phoromatic data to new location.</h2>';
                         }
                     }
                 }
             }
         }
     }
     if (isset($_POST['new_dc_path']) && !empty($_POST['new_dc_path'])) {
         $new_dir = dirname($_POST['new_dc_path']);
         if (!is_dir($new_dir)) {
             $main .= '<h2 style="color: red;"><em>' . $new_dir . '</em> must be a valid directory.</h2>';
         } else {
             if (!is_writable($new_dir)) {
                 $main .= '<h2 style="color: red;"><em>' . $new_dir . '</em> is not a writable location.</h2>';
             } else {
                 if (!is_dir($_POST['new_dc_path'])) {
                     if (mkdir($_POST['new_dc_path']) == false) {
                         $main .= '<h2 style="color: red;">Failed to make directory <em>' . $_POST['new_dc_path'] . '</em>.</h2>';
                     }
                 }
                 if (is_dir($_POST['new_dc_path'])) {
                     $new_dc_dir = pts_strings::add_trailing_slash($_POST['new_dc_path']);
                     if (pts_file_io::copy(pts_strings::add_trailing_slash(pts_client::parse_home_directory(pts_config::read_user_config('PhoronixTestSuite/Options/Installation/CacheDirectory', PTS_DOWNLOAD_CACHE_PATH))), $new_dc_dir)) {
                         pts_config::user_config_generate(array('CacheDirectory' => $new_dc_dir));
                         header('Location: /?admin');
                     } else {
                         $main .= '<h2 style="color: red;"><em>Failed to copy old Phoromatic data to new location.</h2>';
                     }
                 }
             }
         }
     }
     if (isset($_POST['new_proxy_address']) && isset($_POST['new_proxy_port'])) {
         if (pts_network::http_get_contents('http://www.phoronix-test-suite.com/PTS', $_POST['new_proxy_address'], $_POST['new_proxy_port']) == 'PTS') {
             pts_config::user_config_generate(array('PhoronixTestSuite/Options/Networking/ProxyAddress' => $_POST['new_proxy_address'], 'PhoronixTestSuite/Options/Networking/ProxyPort' => $_POST['new_proxy_port']));
         } else {
             $main .= '<h2 style="color: red;">Failed to connect via proxy server.</h2>';
         }
     }
     if (isset($_POST['new_http_port']) && isset($_POST['new_ws_port'])) {
         if (empty($_POST['new_http_port']) || !is_numeric($_POST['new_http_port']) && $_POST['new_http_port'] != 'RANDOM') {
             $main .= '<h2 style="color: red;">The HTTP port must be a valid port number or <em>RANDOM</em>.</h2>';
         }
         if (empty($_POST['new_ws_port']) || !is_numeric($_POST['new_ws_port']) && $_POST['new_ws_port'] != 'RANDOM') {
             $main .= '<h2 style="color: red;">The WebSocket port must be a valid port number or <em>RANDOM</em>.</h2>';
         }
         pts_config::user_config_generate(array('PhoronixTestSuite/Options/Server/RemoteAccessPort' => $_POST['new_http_port'], 'PhoronixTestSuite/Options/Server/WebSocketPort' => $_POST['new_ws_port']));
     }
     if (isset($_POST['add_new_users_to_account'])) {
         if (empty($_POST['add_new_users_to_account'])) {
             phoromatic_server::save_setting('add_new_users_to_account', null);
         } else {
             $stmt = phoromatic_server::$db->prepare('SELECT COUNT(AccountID) AS AccountHitCount FROM phoromatic_accounts WHERE AccountID = :account_id');
             $stmt->bindValue(':account_id', $_POST['add_new_users_to_account']);
             $result = $stmt->execute();
             $row = $result->fetchArray();
             if (empty($row['AccountHitCount'])) {
                 $main .= '<h2 style="color: red;"><em>' . $_POST['add_new_users_to_account'] . '</em> is not a valid account ID.</h2>';
             } else {
                 phoromatic_server::save_setting('add_new_users_to_account', $_POST['add_new_users_to_account']);
             }
         }
     }
     if (isset($_POST['account_creation_alt'])) {
         phoromatic_server::save_setting('account_creation_alt', $_POST['account_creation_alt']);
     }
     if (isset($_POST['main_page_message'])) {
         phoromatic_server::save_setting('main_page_message', $_POST['main_page_message']);
     }
     if (isset($_POST['force_result_sharing'])) {
         phoromatic_server::save_setting('force_result_sharing', $_POST['force_result_sharing']);
     }
     if (isset($_POST['show_local_tests_only'])) {
         phoromatic_server::save_setting('show_local_tests_only', $_POST['show_local_tests_only']);
     }
     if (isset($_POST['new_admin_support_email'])) {
         phoromatic_server::save_setting('admin_support_email', $_POST['new_admin_support_email']);
     }
     if (isset($_POST['rebuild_results_db'])) {
         foreach (pts_file_io::glob(phoromatic_server::phoromatic_path() . 'accounts/*/results/*/composite.xml') as $composite_xml) {
             $account_id = basename(dirname(dirname(dirname($composite_xml))));
             $upload_id = basename(dirname($composite_xml));
             $result_file = new pts_result_file($composite_xml);
             // Validate the XML
             $relative_id = 0;
             foreach ($result_file->get_result_objects() as $result_object) {
                 $relative_id++;
                 $stmt = phoromatic_server::$db->prepare('INSERT INTO phoromatic_results_results (AccountID, UploadID, AbstractID, TestProfile, ComparisonHash) VALUES (:account_id, :upload_id, :abstract_id, :test_profile, :comparison_hash)');
                 $stmt->bindValue(':account_id', $account_id);
                 $stmt->bindValue(':upload_id', $upload_id);
                 $stmt->bindValue(':abstract_id', $relative_id);
                 $stmt->bindValue(':test_profile', $result_object->test_profile->get_identifier());
                 $stmt->bindValue(':comparison_hash', $result_object->get_comparison_hash(true, false));
                 $result = $stmt->execute();
             }
             if ($relative_id > 0) {
                 foreach ($result_file->get_systems() as $s) {
                     $stmt = phoromatic_server::$db->prepare('INSERT INTO phoromatic_results_systems (AccountID, UploadID, SystemIdentifier, Hardware, Software) VALUES (:account_id, :upload_id, :system_identifier, :hardware, :software)');
                     $stmt->bindValue(':account_id', $account_id);
                     $stmt->bindValue(':upload_id', $upload_id);
                     $stmt->bindValue(':system_identifier', $s->get_identifier());
                     $stmt->bindValue(':hardware', $s->get_hardware());
                     $stmt->bindValue(':software', $s->get_software());
                     $result = $stmt->execute();
                 }
             }
         }
     }
     $main .= '<h1>Phoromatic Server Configuration</h1>';
     $main .= '<h2>Phoromatic Storage Location</h2>';
     $main .= '<p>The Phoromatic Storage location is where all Phoromatic-specific test results, account data, and other information is archived. This path is controlled via the <em>' . pts_config::get_config_file_location() . '</em> configuration file with the <em>PhoromaticStorage</em> element. Adjusting the directory from the user configuration XML file is the recommended way to adjust the Phoromatic storage path when the Phoromatic Server is not running, while using the below form is an alternative method to attempt to live migrate the storage path.</p>';
     $main .= '<p><strong>Current Storage Path:</strong> ' . phoromatic_server::phoromatic_path() . '</p>';
     $main .= '<form action="' . $_SERVER['REQUEST_URI'] . '" name="update_phoromatic_path" method="post">';
     $main .= '<p><input type="text" name="new_phoromatic_path" value="' . (isset($_POST['new_phoromatic_path']) ? $_POST['new_phoromatic_path'] : null) . '" /></p>';
     $main .= '<p><input name="submit" value="Update Phoromatic Storage Location" type="submit" /></p>';
     $main .= '</form>';
     $main .= '<hr /><h2>Download Cache Location</h2>';
     $main .= '<p>The download cache is where the Phoronix Test Suite is able to make an archive of files needed by test profiles. The Phoromatic Server is then able to allow Phoronix Test Suite client systems on the intranet. To add test files to this cache on the Phoromatic Server, run <strong>phoronix-test-suite make-download-cache <em>&lt;the test identifers you wish to download and cache&gt;</em></strong>.</p>';
     $main .= '<p><strong>Current Download Cache Path:</strong> ' . pts_strings::add_trailing_slash(pts_client::parse_home_directory(pts_config::read_user_config('PhoronixTestSuite/Options/Installation/CacheDirectory', PTS_DOWNLOAD_CACHE_PATH))) . '</p>';
     $main .= '<form action="' . $_SERVER['REQUEST_URI'] . '" name="update_dc_path" method="post">';
     $main .= '<p><input type="text" name="new_dc_path" value="' . (isset($_POST['new_dc_path']) ? $_POST['new_dc_path'] : null) . '" /></p>';
     $main .= '<p><input name="submit" value="Update Download Cache Location" type="submit" /></p>';
     $main .= '</form>';
     $main .= '<hr /><h2>Network Proxy</h2>';
     $main .= '<p>If a network proxy is needed for the Phoromatic Server to access the open Internet, please provide the IP address and HTTP port address below.</p>';
     $main .= '<form action="' . $_SERVER['REQUEST_URI'] . '" name="update_proxy" method="post">';
     $main .= '<p><strong>Proxy HTTP Port:</strong> <input type="text" name="new_proxy_port" size="4" value="' . (isset($_POST['new_proxy_port']) ? $_POST['new_proxy_port'] : pts_config::read_user_config('PhoronixTestSuite/Options/Networking/ProxyPort')) . '" /></p>';
     $main .= '<p><strong>Proxy IP Address:</strong> <input type="text" name="new_proxy_address" value="' . (isset($_POST['new_proxy_address']) ? $_POST['new_proxy_address'] : pts_config::read_user_config('PhoronixTestSuite/Options/Networking/ProxyAddress')) . '" /></p>';
     $main .= '<p><input name="submit" value="Update Network Proxy" type="submit" /></p>';
     $main .= '</form>';
     $main .= '<hr /><h2>Phoromatic Server Ports</h2>';
     $main .= '<p>The HTTP and WebSocket ports for the Phoromatic Server can be adjusted via this form or the user configuration XML file. The new ports will not go into effect until the Phoromatic Server instance has been restarted.</p>';
     $main .= '<form action="' . $_SERVER['REQUEST_URI'] . '" name="update_ports" method="post">';
     $main .= '<p><strong>HTTP Port:</strong> <input type="text" name="new_http_port" size="4" value="' . (isset($_POST['new_http_port']) ? $_POST['new_http_port'] : pts_config::read_user_config('PhoronixTestSuite/Options/Server/RemoteAccessPort')) . '" /></p>';
     $main .= '<p><strong>WebSocket Port:</strong> <input type="text" name="new_ws_port" size="4" value="' . (isset($_POST['new_ws_port']) ? $_POST['new_ws_port'] : pts_config::read_user_config('PhoronixTestSuite/Options/Server/WebSocketPort')) . '" /></p>';
     $main .= '<p><input name="submit" value="Update Web Ports" type="submit" /></p>';
     $main .= '</form>';
     $main .= '<hr /><h2>Support Email Address</h2>';
     $main .= '<p>This email address will be shown as the sender of emails regarding new account registration and other non-group-related messages. This email address may also be shown as a support email address in case of user problems.</p>';
     $main .= '<form action="' . $_SERVER['REQUEST_URI'] . '" name="support_email" method="post">';
     $main .= '<p><strong>E-Mail:</strong> <input type="text" name="new_admin_support_email" value="' . phoromatic_server::read_setting('admin_support_email') . '" /></p>';
     $main .= '<p><input name="submit" value="Update E-Mail Address" type="submit" /></p>';
     $main .= '</form>';
     $main .= '<hr /><h1>Account Creation</h1>';
     $main .= '<h2>Add To Existing Account</h2><p>Whenever a new account is created via the main log-in page, rather than creating a new group account, you can opt to have the account added as a viewer to an existing group of accounts. To do so, enter the account ID in the field below. The user is added to that account ID with viewer privileges while the main administrator for that account can elevate the privileges from their account\'s Users page. You can find the list of account IDs via the main rootadmin page account listing. Leave this field blank to disable the feature. This option only affects the creation of new accounts.</p>';
     $main .= '<form action="' . $_SERVER['REQUEST_URI'] . '" name="add_accounts_to_one" method="post">';
     $main .= '<p><strong>Main Account ID:</strong> <input type="text" name="add_new_users_to_account" size="6" value="' . phoromatic_server::read_setting('add_new_users_to_account') . '" /></p>';
     $main .= '<p><input name="submit" value="Update Account Handling" type="submit" /></p>';
     $main .= '</form>';
     $main .= '<hr /><h1>Account Creation</h1>';
     $main .= '<p>By default, new accounts can be created at-will from the main page of the Phoromatic Server web interface. <strong>To disable the ability to create new accounts from the main welcome page</strong>, enter a message in the field below -- e.g. account creation disabled, contact XYZ department via email to request a new account, or other string to present to the user in place of the account creation box. Leave this box empty to allow new accounts to be created. HTML input is allowed.</p>';
     $main .= '<form action="' . $_SERVER['REQUEST_URI'] . '" name="account_creation_text" method="post">';
     $main .= '<p><strong>Account Creation String:</strong> <textarea name="account_creation_alt" cols="50" rows="4">' . phoromatic_server::read_setting('account_creation_alt') . '</textarea></p>';
     $main .= '<p><input name="submit" value="Update Account Handling" type="submit" /></p>';
     $main .= '</form>';
     $main .= '<hr /><h1>Main Page Message</h1>';
     $main .= '<p>If you wish to present users with a custom message once logging into their Phoromatic account, set the HTML-allowed string below and it will be shown on the main page once logging in.</p>';
     $main .= '<form action="' . $_SERVER['REQUEST_URI'] . '" name="main_page_message" method="post">';
     $main .= '<p><strong>Main Page Message String:</strong> <textarea name="main_page_message" cols="50" rows="4">' . phoromatic_server::read_setting('main_page_message') . '</textarea></p>';
     $main .= '<p><input name="submit" value="Update Main Page Message" type="submit" /></p>';
     $main .= '</form>';
     $main .= '<hr /><h1>Force Results To Be Shared</h1>';
     $main .= '<p>If you wish to force that all accounts/groups on this Phoromatic Server instance are shared/viewable amongst other groups on this server, set this value to True. Otherwise the result sharing is limited to each group\'s selected option on the account settings page.</p>';
     $main .= '<form action="' . $_SERVER['REQUEST_URI'] . '" name="force_result_share" method="post">';
     $main .= '<p><strong>Force Result Sharing:</strong> <select name="force_result_sharing"><option value="0">False</option><option value="1" ' . (phoromatic_server::read_setting('force_result_sharing') ? 'selected="selected"' : null) . '>True</option></select></p>';
     $main .= '<p><input name="submit" value="Update" type="submit" /></p>';
     $main .= '</form>';
     $main .= '<hr /><h1>Only Advertise Tests With Files Locally Cached</h1>';
     $main .= '<p>Enabling this option will only advertise test profiles on the Phoromatic Server web interface if the needed files for that test are present within the Phoromatic Server\'s PTS download cache. This feature is particularly useful for environments where the client test system lacks direct Internet access.</p>';
     $main .= '<form action="' . $_SERVER['REQUEST_URI'] . '" name="show_local_tests_only" method="post">';
     $main .= '<p><strong>Only Advertise Cached Tests:</strong> <select name="show_local_tests_only"><option value="0">False</option><option value="1" ' . (phoromatic_server::read_setting('show_local_tests_only') ? 'selected="selected"' : null) . '>True</option></select></p>';
     $main .= '<p><input name="submit" value="Update" type="submit" /></p>';
     $main .= '</form>';
     $main .= '<hr /><h1>Rebuild Results/Systems SQLite Tables</h1>';
     $main .= '<p>If you somehow damaged some of your SQLite tables, this option will attempt to rebuild the phoromatic_results_results and phoromatic_results_systems tables.</p>';
     $main .= '<form action="' . $_SERVER['REQUEST_URI'] . '" name="rebuild_results_db" method="post">';
     $main .= '<p><strong>Force Results Table Rebuild:</strong> <select name="rebuild_results_db"><option value="0">False</option><option value="1" ' . (phoromatic_server::read_setting('rebuild_results_db') ? 'selected="selected"' : null) . '>True</option></select></p>';
     $main .= '<p><input name="submit" value="Rebuild Results Table" type="submit" /></p>';
     $main .= '</form>';
     echo phoromatic_webui_header_logged_in();
     echo phoromatic_webui_main($main, phoromatic_webui_right_panel_logged_in());
     echo phoromatic_webui_footer();
 }
    public static function render_page_process($PATH)
    {
        if ($_SESSION['AdminLevel'] > 3) {
            echo phoromatic_error_page('Unauthorized Access', 'You aren\'t an account administrator!');
            return;
        }
        if (isset($_POST['group_name'])) {
            $stmt = phoromatic_server::$db->prepare('UPDATE phoromatic_accounts SET GroupName = :group_name WHERE AccountID = :account_id');
            $stmt->bindValue(':group_name', $_POST['group_name']);
            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
            $result = $stmt->execute();
        }
        if (isset($_POST['username']) && isset($_POST['password']) && isset($_POST['confirm_password']) && isset($_POST['email'])) {
            // REGISTER NEW USER
            if (strlen($_POST['username']) < 4 || strpos($_POST['username'], ' ') !== false) {
                phoromatic_error_page('Oops!', 'Please go back and ensure the supplied username is at least four characters long and contains no spaces.');
                return false;
            }
            if (in_array(strtolower($_POST['username']), array('admin', 'administrator'))) {
                phoromatic_error_page('Oops!', $_POST['username'] . ' is a reserved and common username that may be used for other purposes, please make a different selection.');
                return false;
            }
            if (strlen($_POST['password']) < 6) {
                phoromatic_error_page('Oops!', 'Please go back and ensure the supplied password is at least six characters long.');
                return false;
            }
            if ($_POST['password'] != $_POST['confirm_password']) {
                phoromatic_error_page('Oops!', 'Please go back and ensure the supplied password matches the password confirmation.');
                return false;
            }
            if ($_POST['email'] == null || filter_var($_POST['email'], FILTER_VALIDATE_EMAIL) == false) {
                phoromatic_error_page('Oops!', 'Please enter a valid email address.');
                return false;
            }
            $valid_user_name_chars = '1234567890-_.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
            for ($i = 0; $i < count($_POST['username']); $i++) {
                if (strpos($valid_user_name_chars, substr($_POST['username'], $i, 1)) === false) {
                    phoromatic_error_page('Oops!', 'Please go back and ensure a valid user-name. The character <em>' . substr($_POST['username'], $i, 1) . '</em> is not allowed.');
                    return false;
                }
            }
            $matching_users = phoromatic_server::$db->querySingle('SELECT UserName FROM phoromatic_users WHERE UserName = \'' . SQLite3::escapeString($_POST['username']) . '\'');
            if (!empty($matching_users)) {
                phoromatic_error_page('Oops!', 'The user-name is already taken.');
                return false;
            }
            if (!isset($_POST['admin_level']) || $_POST['admin_level'] == 1 || !is_numeric($_POST['admin_level'])) {
                phoromatic_error_page('Oops!', 'Invalid administration level.');
                return false;
            }
            $stmt = phoromatic_server::$db->prepare('SELECT Salt FROM phoromatic_accounts WHERE AccountID = :account_id');
            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
            $result = $stmt->execute();
            $row = $result->fetchArray();
            $account_salt = $row['Salt'];
            $user_id = pts_strings::random_characters(4, true);
            $salted_password = hash('sha256', $account_salt . $_POST['password']);
            pts_logger::add_to_log($_SERVER['REMOTE_ADDR'] . ' created a new account: ' . $user_id . ' - ' . $_SESSION['AccountID']);
            $stmt = phoromatic_server::$db->prepare('INSERT INTO phoromatic_users (UserID, AccountID, UserName, Email, Password, CreatedOn, LastIP, AdminLevel) VALUES (:user_id, :account_id, :user_name, :email, :password, :current_time, :last_ip, :admin_level)');
            $stmt->bindValue(':user_id', $user_id);
            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
            $stmt->bindValue(':user_name', $_POST['username']);
            $stmt->bindValue(':email', $_POST['email']);
            $stmt->bindValue(':password', $salted_password);
            $stmt->bindValue(':last_ip', $_SERVER['REMOTE_ADDR']);
            $stmt->bindValue(':current_time', phoromatic_server::current_time());
            $stmt->bindValue(':admin_level', $_POST['admin_level']);
            $result = $stmt->execute();
            $stmt = phoromatic_server::$db->prepare('INSERT INTO phoromatic_user_settings (UserID, AccountID) VALUES (:user_id, :account_id)');
            $stmt->bindValue(':user_id', $user_id);
            $stmt->bindValue(':account_id', $_SESSION['AccountID']);
            $result = $stmt->execute();
            phoromatic_add_activity_stream_event('users', $_POST['username'], 'added');
        }
        if ($_SESSION['AdminLevel'] == 1 && isset($_POST['update_user_levels'])) {
            foreach (explode(',', $_POST['update_user_levels']) as $user_id) {
                if (isset($_POST['admin_level_' . $user_id]) && is_numeric($_POST['admin_level_' . $user_id])) {
                    $stmt = phoromatic_server::$db->prepare('UPDATE phoromatic_users SET AdminLevel = :admin_level WHERE AccountID = :account_id AND UserID = :user_id');
                    $stmt->bindValue(':admin_level', $_POST['admin_level_' . $user_id]);
                    $stmt->bindValue(':user_id', $user_id);
                    $stmt->bindValue(':account_id', $_SESSION['AccountID']);
                    $result = $stmt->execute();
                }
            }
        }
        $main = '<h2>Users</h2>
			<p>Users associated with this account. Phoromatic users can be one of several tiers with varying privileges:</p>
			<ol>
				<li><strong>Group Administrator:</strong> The user with full control over the account, the one who originally signed up for the Phoromatic account.</li>
				<li><strong>Administrator:</strong> Additional users created by the group administrator with the same access rights as the group administrator.</li>
				<li><strong>Power Users:</strong> Additional users created by the group administrator with read/write/modify access to all standard Phoromatic functionality, aside from being able to create additional users.</li>
				<li><strong>Viewer:</strong> Additional users created by the group administrator that have access to view data but not to create new schedules, alter system settings, etc.</li>
			</ol>
			<div class="pts_phoromatic_info_box_area">

				<div style="margin: 0 20%;"><form action="' . $_SERVER['REQUEST_URI'] . '" name="edit_user" id="edit_user" method="post">
					<ul>
						<li><h1>All Users</h1></li>';
        $stmt = phoromatic_server::$db->prepare('SELECT * FROM phoromatic_users WHERE AccountID = :account_id ORDER BY UserName ASC');
        $stmt->bindValue(':account_id', $_SESSION['AccountID']);
        $result = $stmt->execute();
        $row = $result->fetchArray();
        $user_ids = array();
        do {
            switch ($row['AdminLevel']) {
                case 1:
                    $level = 'Group Administrator';
                    break;
                case 2:
                    $level = 'Administrator';
                    break;
                case 3:
                    $level = 'Power User';
                    break;
                case 10:
                    $level = 'Viewer';
                    break;
                default:
                    if ($row['AdminLevel'] < 1) {
                        $level = 'Disabled';
                    } else {
                        $level = 'Unknown';
                    }
                    break;
            }
            $main .= '<a href="#"><li>' . $row['UserName'] . '<br /><table><tr><td>';
            if ($row['AdminLevel'] == 1 || $_SESSION['AdminLevel'] != 1) {
                $main .= '<strong>' . $level . '</strong>';
            } else {
                $main .= '<select name="admin_level_' . $row['UserID'] . '">';
                foreach (array($row['AdminLevel'] * -1 => 'Disabled', 2 => 'Administrator', 3 => 'Power User', 10 => 'Viewer') as $level_id => $level_string) {
                    $main .= '<option value="' . $level_id . '"' . ($row['AdminLevel'] == $level_id ? ' selected="selected"' : null) . '>' . $level_string . '</option>';
                }
                $main .= '</select>';
                array_push($user_ids, $row['UserID']);
            }
            $main .= '</td><td>Last Login: ' . (empty($row['LastLogin']) ? 'Never' : date('j F Y H:i', strtotime($row['LastLogin']))) . '</td></tr></table></li></a>';
        } while ($row = $result->fetchArray());
        $main .= '</ul> &nbsp; <input type="hidden" name="update_user_levels" value="' . implode(',', $user_ids) . '" /> <input name="submit" value="Update User Levels" type="submit" /></form>
				</div>
			</div>';
        $main .= '<hr /><form action="' . $_SERVER['REQUEST_URI'] . '" name="add_user" id="add_user" method="post" onsubmit="return validate_new_user();"><h2>Create Additional Account</h2>
			<p>Administrators can create extra accounts to be associated with this account\'s systems, schedules, and test data.</p>
			<h3>User</h3>
			<p><input type="text" name="username" /></p>
			<h3>Password</h3>
			<p><input type="password" name="password" /></p>
			<h3>Confirm Password</h3>
			<p><input type="password" name="confirm_password" /></p>
			<h3>Email</h3>
			<p><input type="text" name="email" /></p>
			<h3>Administration Level</h3>
			<p><select name="admin_level">';
        if ($_SESSION['AdminLevel'] == 1) {
            $main .= '<option value="2">Administrator</option>';
        }
        if ($_SESSION['AdminLevel'] <= 2) {
            $main .= '<option value="3">Power User</option>';
        }
        if ($_SESSION['AdminLevel'] <= 3) {
            $main .= '<option value="10">Viewer</option>';
        }
        $main .= '
			</select></p>
			<p><input name="submit" value="Add User" type="submit" /></p>
			</form>';
        $group_name = phoromatic_account_id_to_group_name($_SESSION['AccountID']);
        $main .= '<hr /><form action="' . $_SERVER['REQUEST_URI'] . '" name="group_name" id="group_name" method="post"><h2>Group Name</h2>
			<p>A group name is an alternative, user-facing name for this set of accounts. The group name feature is primarily useful for being able to better distinguish results between groups when sharing of data within a large organization, etc. The group name is showed next to test results when viewing results from multiple groups/accounts.</p>
			<h3>Group Name</h3>
			<p><input type="text" name="group_name" value="' . $group_name . '" /></p>
			<p><input name="submit" value="Update Group Name" type="submit" /></p>
			</form>';
        echo phoromatic_webui_header_logged_in();
        echo '<div id="pts_phoromatic_main_area">' . $main . '</div>';
        echo phoromatic_webui_footer();
    }