CVE-2022-0157 (published 2022-01-10T16:15Z)

phoronix-test-suite is vulnerable to Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

Severity: LOW
CVSS v2 base score: 3.5 (AV:N/AC:M/Au:S/C:N/I:P/A:N)
CVSS v3 base score: 5.4, MEDIUM (CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N)

Weakness information:
cwe_id: CWE-79
cwe_name: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
extended_description: 
            Cross-site scripting (XSS) vulnerabilities occur when:
            
               Untrusted data enters a web application, typically from a web request.
               The web application dynamically generates a web page that contains this untrusted data.
               During page generation, the application does not prevent the data from containing content that is executable by a web browser, such as JavaScript, HTML tags, HTML attributes, mouse events, Flash, ActiveX, etc.
               A victim visits the generated web page through a web browser, which contains malicious script that was injected using the untrusted data.
               Since the script comes from a web page that was sent by the web server, the victim's web browser executes the malicious script in the context of the web server's domain.
               This effectively violates the intention of the web browser's same-origin policy, which states that scripts in one domain should not be able to access resources or run code in a different domain.
            
            There are three main kinds of XSS:
            
               
                  Type 1: Reflected XSS (or Non-Persistent) - 
         			The server reads data directly from the HTTP request and reflects it back in the HTTP response. Reflected XSS exploits occur when an attacker causes a victim to supply dangerous content to a vulnerable web application, which is then reflected back to the victim and executed by the web browser. The most common mechanism for delivering malicious content is to include it as a parameter in a URL that is posted publicly or e-mailed directly to the victim. URLs constructed in this manner constitute the core of many phishing schemes, whereby an attacker convinces a victim to visit a URL that refers to a vulnerable site. After the site reflects the attacker's content back to the victim, the content is executed by the victim's browser.
               
                  Type 2: Stored XSS (or Persistent) - 
               The application stores dangerous data in a database, message forum, visitor log, or other trusted data store. At a later time, the dangerous data is subsequently read back into the application and included in dynamic content. From an attacker's perspective, the optimal place to inject malicious content is in an area that is displayed to either many users or particularly interesting users. Interesting users typically have elevated privileges in the application or interact with sensitive data that is valuable to the attacker. If one of these users executes malicious content, the attacker may be able to perform privileged operations on behalf of the user or gain access to sensitive data belonging to the user. For example, the attacker might inject XSS into a log message, which might not be handled properly when an administrator views the logs.
            
               
                  Type 0: DOM-Based XSS - 
               In DOM-based XSS, the client performs the injection of XSS into the page; in the other types, the server performs the injection. DOM-based XSS generally involves server-controlled, trusted script that is sent to the client, such as Javascript that performs sanity checks on a form before the user submits it. If the server-supplied script processes user-supplied data and then injects it back into the web page (such as with dynamic HTML), then DOM-based XSS is possible.
            
            
            Once the malicious script is injected, the attacker can perform a variety of malicious activities. The attacker could transfer private information, such as cookies that may include session information, from the victim's machine to the attacker. The attacker could send malicious requests to a web site on behalf of the victim, which could be especially dangerous to the site if the victim has administrator privileges to manage that site. Phishing attacks could be used to emulate trusted web sites and trick the victim into entering a password, allowing the attacker to compromise the victim's account on that web site. Finally, the script could exploit a vulnerability in the web browser itself possibly taking over the victim's machine, sometimes referred to as "drive-by hacking."
            In many cases, the attack can be launched without the victim even being aware of it. Even with careful users, attackers frequently use a variety of methods to encode the malicious portion of the attack, such as URL encoding or Unicode, so the request looks less suspicious.
         
         

Fix information:
repo_url: https://github.com/phoronix-test-suite/phoronix-test-suite
commit_details: repo_url: https://github.com/phoronix-test-suite/phoronix-test-suite
author: Michael Larabel
author_date: 2022-01-08 04:47:20-06:00
msg: phodevi: Input sanitization updates for Phoromatic Server

Also other code formatting / cleanups while reviewing the code...
repository: repo_url: https://github.com/phoronix-test-suite/phoronix-test-suite
repo_name: phoronix-test-suite/phoronix-test-suite
description: The Phoronix Test Suite open-source, cross-platform automated testing/benchmarking software.
repo_language: PHP
owner: phoronix-test-suite
file_changes: filename: ChangeLog
change_type: ModificationType.MODIFY
diff: @@ -1,5 +1,9 @@
 PHORONIX TEST SUITE CHANGE-LOG
 
+Phoronix Test Suite (Git)
+
+phodevi: Input sanitization updates for Phoromatic Server
+
 Phoronix Test Suite 10.8.0
 25 December 2021
 

programming_language: Markdown
filename: pts_env.php
change_type: ModificationType.MODIFY
diff: @@ -650,7 +650,7 @@ class pts_env
 				}
 				if(!empty($v) && $v !== 0)
 				{
-					$posted[$var] = $v;
+					$posted[$var] = pts_strings::sanitize($v);
 				}
 			}
 		}

programming_language: PHP
filename: pts_phoroql.php
change_type: ModificationType.MODIFY
diff: @@ -22,7 +22,7 @@
 
 class pts_phoroql
 {
-	public static function evaluate_search_tree($tree, $join = 'AND', $callback)
+	public static function evaluate_search_tree($tree, $join = 'AND', $callback = '')
 	{
 		$matches = false;
 

programming_language: PHP
filename: pts_result_viewer_embed.php
change_type: ModificationType.MODIFY
diff: @@ -3,8 +3,8 @@
 /*
 	Phoronix Test Suite
 	URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
-	Copyright (C) 2018 - 2020, Phoronix Media
-	Copyright (C) 2018 - 2020, Michael Larabel
+	Copyright (C) 2018 - 2022, Phoronix Media
+	Copyright (C) 2018 - 2022, Michael Larabel
 
 	This program is free software; you can redistribute it and/or modify
 	it under the terms of the GNU General Public License as published by
@@ -119,8 +119,8 @@ class pts_result_viewer_embed
 		$html_options = self::get_html_options_markup($result_file, $_REQUEST, $this->result_public_id, $this->can_delete_results);
 		self::process_request_to_attributes($_REQUEST, $result_file, $extra_attributes);
 		$PAGE .= self::get_html_sort_bar($result_file, $_REQUEST);
-		$PAGE .= '<h1 id="result_file_title" placeholder="Title">' . $result_file->get_title() . '</h1>';
-		$PAGE .= '<p id="result_file_desc" placeholder="Description">' . str_replace(PHP_EOL, '<br />', $result_file->get_description()) . '</p>';
+		$PAGE .= '<h1 id="result_file_title" placeholder="Title">' . pts_strings::sanitize($result_file->get_title()) . '</h1>';
+		$PAGE .= '<p id="result_file_desc" placeholder="Description">' . str_replace(PHP_EOL, '<br />', pts_strings::sanitize($result_file->get_description())) . '</p>';
 		$PAGE .= '<div id="result-settings">';
 		if($this->can_modify_results)
 		{
@@ -412,8 +412,6 @@ class pts_result_viewer_embed
 				}
 			}
 
-			// $PAGE .= $res . '<br />';
-
 			//
 			// DISPLAY LOGS
 			//
@@ -430,7 +428,6 @@ class pts_result_viewer_embed
 				$button_area .= ' <button onclick="javascript:display_install_logs_for_result_object(\'' . $this->result_public_id . '\', \'' . $i . '\'); return false;">View Test Installation Logs</button> ';
 			}
 
-
 			//
 			// EDITING / DELETE OPTIONS
 			//
@@ -452,12 +449,12 @@ class pts_result_viewer_embed
 				}
 				else
 				{
-					$PAGE .= '<div id="update_annotation_' . $i . '" contentEditable="true">' . $result_object->get_annotation() . '</div> <input type="submit" value="Update Annotation" onclick="javascript:update_annotation_for_result_object(\'' . $this->result_public_id . '\', \'' . $i . '\'); return false;">';
+					$PAGE .= '<div id="update_annotation_' . $i . '" contentEditable="true">' . pts_strings::sanitize($result_object->get_annotation()) . '</div> <input type="submit" value="Update Annotation" onclick="javascript:update_annotation_for_result_object(\'' . $this->result_public_id . '\', \'' . $i . '\'); return false;">';
 				}
 			}
 			else
 			{
-				$PAGE .= '<p class="mini">' . $result_object->get_annotation() . '</p>';
+				$PAGE .= '<p class="mini">' . pts_strings::sanitize($result_object->get_annotation()) . '</p>';
 			}
 			if($button_area != null)
 			{
@@ -1023,7 +1020,6 @@ class pts_result_viewer_embed
 	}
 	public static function process_result_modify_pre_render(&$result_file, $can_modify_results = false, $can_delete_results = false)
 	{
-
 		if(!isset($_REQUEST['modify']) || ($can_modify_results == false && $can_delete_results == false))
 		{
 			return;

programming_language: PHP
filename: phoromatic_account_activity.php
change_type: ModificationType.MODIFY
diff: @@ -20,7 +20,6 @@
 	along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
-
 class phoromatic_account_activity implements pts_webui_interface
 {
 	public static function page_title()
@@ -37,9 +36,7 @@ class phoromatic_account_activity implements pts_webui_interface
 	}
 	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();
@@ -122,7 +119,6 @@ class phoromatic_account_activity implements pts_webui_interface
 						$main .= ': ' . $id_link_format;
 
 					$main .= '<br />' . PHP_EOL;
-
 				}
 
 				//$main .= '<p>' .  $row['ActivityCreator'] . ' ' . $row['ActivityCreatorType'] . ' ' . $row['ActivityEvent'] . ' ' . $row['ActivityEventID'] . ' ' . $row['ActivityEventType'] . '</p>';

programming_language: PHP
filename: phoromatic_admin.php
change_type: ModificationType.MODIFY
diff: @@ -3,8 +3,8 @@
 /*
 	Phoronix Test Suite
 	URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
-	Copyright (C) 2014 - 2018, Phoronix Media
-	Copyright (C) 2014 - 2018, Michael Larabel
+	Copyright (C) 2014 - 2022, Phoronix Media
+	Copyright (C) 2014 - 2022, Michael Larabel
 
 	This program is free software; you can redistribute it and/or modify
 	it under the terms of the GNU General Public License as published by
@@ -20,7 +20,6 @@
 	along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
-
 class phoromatic_admin implements pts_webui_interface
 {
 	public static function page_title()
@@ -71,10 +70,12 @@ class phoromatic_admin implements pts_webui_interface
 		}
 		else if(isset($_POST['register_username']) && isset($_POST['register_password']) && isset($_POST['register_password_confirm']) && isset($_POST['register_email']))
 		{
+			phoromatic_quit_if_invalid_input_found(array('register_username', 'register_password', 'register_password_confirm', 'register_email', 'seed_accountid'));
 			$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));
 		}
 		else if(isset($_POST['email_all_subject']) && isset($_POST['email_all_message']) && !empty($_POST['email_all_message']))
 		{
+			phoromatic_quit_if_invalid_input_found(array('email_all_subject', 'email_all_message'));
 			$stmt = phoromatic_server::$db->prepare('SELECT * FROM phoromatic_users ORDER BY UserName ASC');
 			$result = $stmt->execute();
 
@@ -207,7 +208,6 @@ class phoromatic_admin implements pts_webui_interface
 		<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)

programming_language: PHP
filename: phoromatic_admin_config.php
change_type: ModificationType.MODIFY
diff: @@ -20,7 +20,6 @@
 	along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
-
 class phoromatic_admin_config implements pts_webui_interface
 {
 	public static function page_title()

programming_language: PHP
filename: phoromatic_admin_data.php
change_type: ModificationType.MODIFY
diff: @@ -20,7 +20,6 @@
 	along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
-
 class phoromatic_admin_data implements pts_webui_interface
 {
 	public static function page_title()
@@ -144,7 +143,7 @@ class phoromatic_admin_data implements pts_webui_interface
 		$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>';
+			$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_server::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++;
 
 		}
@@ -154,7 +153,6 @@ class phoromatic_admin_data implements pts_webui_interface
 		}
 		$main .= '</ul></div>';
 		$main .= '</div>';
-
 		$main .= '<hr /><h1>Schedules</h1>';
 		$main .= '<h2>Active Test Schedules</h2>';
 		$main .= '<div class="pts_phoromatic_info_box_area">
@@ -173,12 +171,11 @@ class phoromatic_admin_data implements pts_webui_interface
 						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>';
+							$main .= '<a onclick=""><li>' . $row['Title'] . '<br /><table><tr><td>' . phoromatic_server::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>
@@ -196,7 +193,7 @@ class phoromatic_admin_data implements pts_webui_interface
 						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>';
+							$main .= '<a onclick=""><li>' . $row['Title'] . '<br /><table><tr><td>' . phoromatic_server::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());
 					}
@@ -219,7 +216,7 @@ class phoromatic_admin_data implements pts_webui_interface
 						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>';
+							$main .= '<a onclick=""><li>' . $row['Trigger'] . '<br /><table><tr><td>' . $row['TriggeredOn'] . '</td><td>' . phoromatic_server::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());
 					}
@@ -245,7 +242,7 @@ class phoromatic_admin_data implements pts_webui_interface
 					{
 						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>';
+							$main .= '<a onclick=""><li>' . $row['Title'] . '<br /><table><tr><td>' . phoromatic_server::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());
@@ -255,7 +252,6 @@ class phoromatic_admin_data implements pts_webui_interface
 			$main .= '</ul></div>';
 			$main .= '<h2>Inactive Systems</h2>
 			<div class="pts_phoromatic_info_box_area">
-
 					<ul>
 						<li><h1>Inactive Systems</h1></li>';
 
@@ -272,7 +268,7 @@ class phoromatic_admin_data implements pts_webui_interface
 					{
 						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>';
+							$main .= '<a onclick=""><li>' . $row['Title'] . '<br /><table><tr><td>' . phoromatic_server::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());

programming_language: PHP
filename: phoromatic_benchmark.php
change_type: ModificationType.MODIFY
diff: @@ -3,8 +3,8 @@
 /*
 	Phoronix Test Suite
 	URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
-	Copyright (C) 2015 - 2021, Phoronix Media
-	Copyright (C) 2015 - 2021, Michael Larabel
+	Copyright (C) 2015 - 2022, Phoronix Media
+	Copyright (C) 2015 - 2022, Michael Larabel
 
 	This program is free software; you can redistribute it and/or modify
 	it under the terms of the GNU General Public License as published by
@@ -20,7 +20,6 @@
 	along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
-
 class phoromatic_benchmark implements pts_webui_interface
 {
 	public static function page_title()
@@ -141,7 +140,6 @@ class phoromatic_benchmark implements pts_webui_interface
 				}
 
 				$main .= '</ol>';
-
 				if(!empty($row['EnvironmentVariables']))
 				{
 					$main .= '<hr /><h1>Environment</h1><ol>';
@@ -152,7 +150,6 @@ class phoromatic_benchmark implements pts_webui_interface
 					}
 					$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;">';
@@ -236,7 +233,7 @@ class phoromatic_benchmark implements pts_webui_interface
 					$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>';
+						$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_server::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++;
 
 					}
@@ -338,10 +335,8 @@ class phoromatic_benchmark implements pts_webui_interface
 				}
 			}
 
-			$main = '
-			<h2>' . ($is_new ? 'Create' : 'Edit') . ' A Benchmark</h2>
+			$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 = array();
 			foreach(pts_file_io::glob(phoromatic_server::phoromatic_account_suite_path($_SESSION['AccountID']) . '*/suite-definition.xml') as $xml_path)
 			{
@@ -384,7 +379,6 @@ class phoromatic_benchmark implements pts_webui_interface
 				$stmt->bindValue(':account_id', $_SESSION['AccountID']);
 				$result = $stmt->execute();
 
-
 				if(!$is_new)
 				{
 					$e_schedule['RunTargetSystems'] = explode(',', $e_schedule['RunTargetSystems']);

programming_language: PHP
filename: phoromatic_build_suite.php
change_type: ModificationType.MODIFY
diff: @@ -3,8 +3,8 @@
 /*
 	Phoronix Test Suite
 	URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
-	Copyright (C) 2015 - 2018, Phoronix Media
-	Copyright (C) 2015 - 2018, Michael Larabel
+	Copyright (C) 2015 - 2022, Phoronix Media
+	Copyright (C) 2015 - 2022, Michael Larabel
 
 	This program is free software; you can redistribute it and/or modify
 	it under the terms of the GNU General Public License as published by
@@ -20,7 +20,6 @@
 	along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
-
 class phoromatic_build_suite implements pts_webui_interface
 {
 	public static function page_title()
@@ -39,6 +38,7 @@ class phoromatic_build_suite implements pts_webui_interface
 	{
 		if(isset($_POST['suite_title']))
 		{
+			phoromatic_quit_if_invalid_input_found(array('suite_title', 'test_add', 'suite_version', 'suite_description'));
 			if(strlen($_POST['suite_title']) < 3)
 			{
 				echo '<h2>Suite title must be at least three characters.</h2>';
@@ -58,6 +58,7 @@ class phoromatic_build_suite implements pts_webui_interface
 				{
 					if(strpos($i, $test_prefix) !== false && substr($i, -9) != '_selected')
 					{
+						phoromatic_quit_if_invalid_input_found(array($i, $i . '_selected'));
 						if(strpos($v, '||') !== false)
 						{
 							$opts = explode('||', $v);
@@ -128,7 +129,6 @@ class phoromatic_build_suite implements pts_webui_interface
 		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)
 		{
 			$suite = null;
@@ -195,7 +195,6 @@ class phoromatic_build_suite implements pts_webui_interface
 			$main .= pts_web_embed::cookie_checkbox_option_helper('list_show_all_test_versions', 'Show all available test profile versions.');
 			$main .= '<p align="right"><input name="submit" value="' . ($suite->get_title() != null ? 'Edit' : 'Create') .' Suite" type="submit" onclick="return pts_rmm_validate_suite();" /></p>';
 		}
-
 		echo '<div id="pts_phoromatic_main_area">' . $main . '</div>';
 		echo phoromatic_webui_footer();
 	}

programming_language: PHP
filename: phoromatic_caches.php
change_type: ModificationType.MODIFY
diff: @@ -20,7 +20,6 @@
 	along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
-
 class phoromatic_caches implements pts_webui_interface
 {
 	public static function page_title()

programming_language: PHP
filename: phoromatic_component_table.php
change_type: ModificationType.MODIFY
diff: @@ -20,7 +20,6 @@
 	along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
-
 class phoromatic_component_table implements pts_webui_interface
 {
 	public static function page_title()

programming_language: PHP
filename: phoromatic_create_test.php
change_type: ModificationType.MODIFY
diff: @@ -20,7 +20,6 @@
 	along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
-
 class phoromatic_create_test implements pts_webui_interface
 {
 	public static function page_title()
@@ -89,7 +88,6 @@ class phoromatic_create_test implements pts_webui_interface
 				pts_validation::generate_test_profile_file_templates($tp_identifier, $tp_path);
 				header('Location: /?create_test/' . $tp_identifier . '-' . $tp->get_test_profile_version());
 			}
-
 		}
 		if(isset($_POST['dc_select_item']))
 		{
@@ -141,7 +139,6 @@ class phoromatic_create_test implements pts_webui_interface
 			}
 		}
 
-
 		return true;
 	}
 	public static function render_page_process($PATH)
@@ -153,7 +150,6 @@ class phoromatic_create_test implements pts_webui_interface
 		}
 
 		$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);
@@ -175,7 +171,6 @@ class phoromatic_create_test implements pts_webui_interface
 			}
 
 			$main .= '<form action="?create_test/' . $tp->get_identifier() . '" name="create_test" id="create_test" method="post" enctype="multipart/form-data"><input type="hidden" name="tp_update" value="' . $tp->get_identifier() . '" />';
-
 			foreach(pts_file_io::glob($tp->get_resource_dir() . '/*') as $file)
 			{
 				$file_name = basename($file);

programming_language: PHP
filename: phoromatic_dashboard.php
change_type: ModificationType.MODIFY
diff: @@ -20,7 +20,6 @@
 	along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
-
 class phoromatic_dashboard implements pts_webui_interface
 {
 	public static function page_title()
@@ -38,7 +37,6 @@ class phoromatic_dashboard implements pts_webui_interface
 	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();

programming_language: PHP
filename: phoromatic_local_suites.php
change_type: ModificationType.MODIFY
diff: @@ -20,7 +20,6 @@
 	along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
-
 class phoromatic_local_suites implements pts_webui_interface
 {
 	public static function page_title()
@@ -60,9 +59,9 @@ class phoromatic_local_suites implements pts_webui_interface
 			$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 .= '<a name="' . $id . '"></a><h1>' . pts_strings::sanitize($test_suite->get_title()) . ' [' . $id . ']</h1>';
+			$main .= '<p><strong>' . pts_strings::sanitize($test_suite->get_maintainer()) . '</strong></p>';
+			$main .= '<p><em>' . pts_strings::sanitize($test_suite->get_description()) . '</em></p>';
 			if(!PHOROMATIC_USER_IS_VIEWER)
 			{
 				$main .= '<p><a href="?build_suite/' . $id . '">Edit Suite</a> - <a href="?local_suites/delete/' . $id . '">Delete Suite</a></p>';

programming_language: PHP
filename: phoromatic_logs.php
change_type: ModificationType.MODIFY
diff: @@ -20,7 +20,6 @@
 	along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
-
 class phoromatic_logs implements pts_webui_interface
 {
 	public static function page_title()

programming_language: PHP
filename: phoromatic_main.php
change_type: ModificationType.MODIFY
diff: @@ -20,7 +20,6 @@
 	along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
-
 class phoromatic_main implements pts_webui_interface
 {
 	public static function page_title()
@@ -156,13 +155,11 @@ class phoromatic_main implements pts_webui_interface
 		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">';
@@ -215,7 +212,6 @@ class phoromatic_main implements pts_webui_interface
 			$main .= '</div>';
 		}
 		$main .= '</div>';
-
 		$main .= '</div>';
 
 		echo '<div id="pts_phoromatic_main_area">' . $main . '</div>';

programming_language: PHP
filename: phoromatic_maintenance_table.php
change_type: ModificationType.MODIFY
diff: @@ -20,7 +20,6 @@
 	along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
-
 class phoromatic_maintenance_table implements pts_webui_interface
 {
 	public static function page_title()
@@ -89,10 +88,7 @@ class phoromatic_maintenance_table implements pts_webui_interface
 
 				$main .= '<td>' . $c . '</td>';
 			}
-
 			$main .= '</tr>';
-
-
 		}
 		$main .= '</table></div>';
 

programming_language: PHP
filename: phoromatic_password.php
change_type: ModificationType.MODIFY
diff: @@ -20,7 +20,6 @@
 	along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
-
 class phoromatic_password implements pts_webui_interface
 {
 	public static function page_title()

programming_language: PHP
filename: phoromatic_r_add_test_build_suite_details.php
change_type: ModificationType.MODIFY
diff: @@ -3,8 +3,8 @@
 /*
 	Phoronix Test Suite
 	URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
-	Copyright (C) 2014 - 2021, Phoronix Media
-	Copyright (C) 2014 - 2021, Michael Larabel
+	Copyright (C) 2014 - 2022, Phoronix Media
+	Copyright (C) 2014 - 2022, Michael Larabel
 
 	This program is free software; you can redistribute it and/or modify
 	it under the terms of the GNU General Public License as published by
@@ -20,7 +20,6 @@
 	along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
-
 class phoromatic_r_add_test_build_suite_details implements pts_webui_interface
 {
 	public static function page_title()
@@ -37,6 +36,7 @@ class phoromatic_r_add_test_build_suite_details implements pts_webui_interface
 	}
 	public static function render_page_process($PATH)
 	{
+		phoromatic_quit_if_invalid_input_found(array('tp'));
 		$test_profile = new pts_test_profile($_GET['tp']);
 		$name = $test_profile->get_title();
 		$description = $test_profile->get_description();

programming_language: PHP
filename: phoromatic_r_basic_suite_details.php
change_type: ModificationType.MODIFY
diff: @@ -20,7 +20,6 @@
 	along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
-
 class phoromatic_r_basic_suite_details implements pts_webui_interface
 {
 	public static function page_title()

programming_language: PHP
filename: phoromatic_result.php
change_type: ModificationType.MODIFY
diff: @@ -3,8 +3,8 @@
 /*
 	Phoronix Test Suite
 	URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
-	Copyright (C) 2008 - 2021, Phoronix Media
-	Copyright (C) 2008 - 2021, Michael Larabel
+	Copyright (C) 2008 - 2022, Phoronix Media
+	Copyright (C) 2008 - 2022, Michael Larabel
 
 	This program is free software; you can redistribute it and/or modify
 	it under the terms of the GNU General Public License as published by
@@ -121,7 +121,7 @@ class phoromatic_result implements pts_webui_interface
 			$result_file_title = null;
 			if(count($system_types) == 1)
 			{
-				$result_file_title = phoromatic_system_id_to_name($system_types[0]) . ' Tests';
+				$result_file_title = phoromatic_server::system_id_to_name($system_types[0]) . ' Tests';
 			}
 
 			if(!empty($tickets) && $tickets[0] != null)
@@ -180,19 +180,19 @@ class phoromatic_result implements pts_webui_interface
 							$system_name = null;
 							break;
 						case 'SYSTEM_NAME':
-							$system_name = phoromatic_system_id_to_name($row['SystemID']);
+							$system_name = phoromatic_server::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'];
+							$system_name = phoromatic_server::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'];
+							$system_name = phoromatic_server::system_id_to_name($row['SystemID']) . ' - ' . phoromatic_schedule_id_to_name($row['ScheduleID']) . ' - ' . $row['Trigger'];
 					}
 
 					if($system_name == null)
@@ -205,11 +205,11 @@ class phoromatic_result implements pts_webui_interface
 						}
 					}
 
-					if(($replacement = phoromatic_system_id_to_name($row['SystemID'])) != null)
+					if(($replacement = phoromatic_server::system_id_to_name($row['SystemID'])) != null)
 					{
 						$system_name = str_replace('.SYSTEM', $replacement, $system_name);
 					}
-					if(($replacement = phoromatic_account_id_to_group_name($row['AccountID'])) != null)
+					if(($replacement = phoromatic_server::account_id_to_group_name($row['AccountID'])) != null)
 					{
 						$system_name = str_replace('.GROUP', $replacement, $system_name);
 					}
@@ -328,7 +328,7 @@ class phoromatic_result implements pts_webui_interface
 
 				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="checkbox" value="' . $row['PPRID'] . '" name="compare_results" /> ' . $row['Title'] . '<br /><em>' . phoromatic_server::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>';

programming_language: PHP
filename: phoromatic_results.php
change_type: ModificationType.MODIFY
diff: @@ -3,8 +3,8 @@
 /*
 	Phoronix Test Suite
 	URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
-	Copyright (C) 2008 - 2018, Phoronix Media
-	Copyright (C) 2008 - 2018, Michael Larabel
+	Copyright (C) 2008 - 2022, Phoronix Media
+	Copyright (C) 2008 - 2022, Michael Larabel
 
 	This program is free software; you can redistribute it and/or modify
 	it under the terms of the GNU General Public License as published by
@@ -20,7 +20,6 @@
 	along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
-
 class phoromatic_results implements pts_webui_interface
 {
 	public static function page_title()
@@ -37,152 +36,216 @@ class phoromatic_results implements pts_webui_interface
 	}
 	public static function render_page_process($PATH)
 	{
-			echo phoromatic_webui_header_logged_in();
-			$main = null;
+		echo phoromatic_webui_header_logged_in();
+		$main = null;
 
-			if(!PHOROMATIC_USER_IS_VIEWER && isset($PATH[0]) && $PATH[0] == 'delete')
-			{
-				$pprids = explode(',', $PATH[1]);
+		if(!PHOROMATIC_USER_IS_VIEWER && isset($PATH[0]) && $PATH[0] == 'delete')
+		{
+			$pprids = explode(',', $PATH[1]);
 
-				foreach($pprids as $pprid)
+			foreach($pprids as $pprid)
+			{
+				$stmt = phoromatic_server::$db->prepare('SELECT * FROM phoromatic_results WHERE AccountID = :account_id AND PPRID = :pprid LIMIT 1');
+				$stmt->bindValue(':account_id', $_SESSION['AccountID']);
+				$stmt->bindValue(':pprid', $pprid);
+				$result = $stmt->execute();
+				if($result && ($row = $result->fetchArray()))
 				{
-					$stmt = phoromatic_server::$db->prepare('SELECT * FROM phoromatic_results WHERE AccountID = :account_id AND PPRID = :pprid LIMIT 1');
-					$stmt->bindValue(':account_id', $_SESSION['AccountID']);
-					$stmt->bindValue(':pprid', $pprid);
-					$result = $stmt->execute();
-					if($result && ($row = $result->fetchArray()))
+					$composite_xml = phoromatic_server::phoromatic_account_result_path($_SESSION['AccountID'], $row['UploadID']) . 'composite.xml';
+					if(is_file($composite_xml))
 					{
-						$composite_xml = phoromatic_server::phoromatic_account_result_path($_SESSION['AccountID'], $row['UploadID']) . 'composite.xml';
-						if(is_file($composite_xml))
-						{
-							unlink($composite_xml);
-						}
-
-						pts_file_io::delete(phoromatic_server::phoromatic_account_result_path($_SESSION['AccountID'], $row['UploadID']), null, true);
-
-						$stmt = phoromatic_server::$db->prepare('DELETE FROM phoromatic_results_results WHERE AccountID = :account_id AND UploadID = :upload_id');
-						$stmt->bindValue(':account_id', $_SESSION['AccountID']);
-						$stmt->bindValue(':upload_id', $row['UploadID']);
-						$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', $_SESSION['AccountID']);
-						$stmt->bindValue(':upload_id', $row['UploadID']);
-						$result = $stmt->execute();
-
-
+						unlink($composite_xml);
 					}
 
-					$stmt = phoromatic_server::$db->prepare('DELETE FROM phoromatic_results WHERE AccountID = :account_id AND PPRID = :pprid');
+					pts_file_io::delete(phoromatic_server::phoromatic_account_result_path($_SESSION['AccountID'], $row['UploadID']), null, true);
+					$stmt = phoromatic_server::$db->prepare('DELETE FROM phoromatic_results_results WHERE AccountID = :account_id AND UploadID = :upload_id');
 					$stmt->bindValue(':account_id', $_SESSION['AccountID']);
-					$stmt->bindValue(':pprid', $pprid);
+					$stmt->bindValue(':upload_id', $row['UploadID']);
 					$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);
+					$stmt = phoromatic_server::$db->prepare('DELETE FROM phoromatic_results_systems WHERE AccountID = :account_id AND UploadID = :upload_id');
+					$stmt->bindValue(':account_id', $_SESSION['AccountID']);
+					$stmt->bindValue(':upload_id', $row['UploadID']);
+					$result = $stmt->execute();
 				}
+
+				$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)
+		if($main == null)
+		{
+			phoromatic_quit_if_invalid_input_found(array('result_limit', 'containing_tests', 'time_end', 'time_start', 'search', 'containing_hardware', 'containing_software'));
+			if(isset($_POST['result_limit']))
 			{
-				if(isset($_POST['result_limit']))
+				if(is_numeric($_POST['result_limit']) && $_POST['result_limit'] > 9)
 				{
-					if(is_numeric($_POST['result_limit']) && $_POST['result_limit'] > 9)
-					{
-						$result_limit = $_POST['result_limit'];
-					}
-					else
-					{
-						$result_limit = 0;
-					}
+					$result_limit = $_POST['result_limit'];
 				}
 				else
 				{
-					$result_limit = 100;
+					$result_limit = 0;
+				}
+			}
+			else
+			{
+				$result_limit = 100;
+			}
+			$min_date = strtotime(phoromatic_server::account_created_on($_SESSION['AccountID']));
+			$default_start_date = max($min_date, strtotime('-1 year'));
+			$min_date = date('Y-m-d', $min_date);
+			$time_start = strtotime(isset($_POST['time_start']) && !empty($_POST['time_start']) ? $_POST['time_start'] : $min_date);
+			if(empty($time_start))
+			{
+				$time_start = strtotime($min_date);
+			}
+			$time_end = strtotime((isset($_POST['time_end']) && !empty($_POST['time_end']) ? $_POST['time_end'] : date('Y-m-d')) . ' 23:59:59');
+			if(empty($time_end))
+			{
+				$time_end = strtotime(date('Y-m-d') . ' 23:59:59');
+			}
+			$main .= '<form action="' . $_SERVER['REQUEST_URI'] . '" method="post"><div style="text-align: left; font-weight: bold;">Results From <input id="time_start" name="time_start" type="date" required pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}" min="' . $min_date . '" value="' . (isset($_POST['time_start']) ? $_POST['time_start'] : date('Y-m-d', $default_start_date)) . '" max="' . date('Y-m-d') . '" /> To  <input id="time_end" name="time_end" type="date" required pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}" min="' . $min_date . '" value="' . (isset($_POST['time_end']) ? $_POST['time_end'] : date('Y-m-d')) . '" max="' . date('Y-m-d') . '" /> &nbsp; With Tests: <input type="text" name="containing_tests" id="containing_tests" value="' . (isset($_POST['containing_tests']) ? $_POST['containing_tests'] : null) . '" /> With Hardware: <input type="text" name="containing_hardware" id="containing_hardware" value="' . (isset($_POST['containing_hardware']) ? $_POST['containing_hardware'] : null) . '" /> With System Software: <input type="text" name="containing_software" id="containing_software" value="' . (isset($_POST['containing_software']) ? $_POST['containing_software'] : null) . '" /> Search For <input type="text" name="search" id="search_for" value="' . (isset($_POST['search']) ? $_POST['search'] : null) . '" /> Limit Results To <select id="result_limit" name="result_limit">';
+			for($i = 100; $i <= 500; $i += 100)
+			{
+				$main .= '<option value="' . $i . '"' . ($result_limit == $i ? ' selected="selected"' : null) . '>' . $i . '</option>';
+			}
+			$main .= '<option value=""' . (isset($_POST['result_limit']) && empty($result_limit) ? ' selected="selected"' : null) . '>No Limit</option>';
+			$main .= '</select> &nbsp; <input type="button" value="Reset" onclick="phoromatic_clear_results_search_fields();" />';
+			$main .= ' &nbsp; <input type="submit" value="Update" /></div></form>';
+			$main .= '<p style="font-size: 90%;">** <em>AND</em>, <em>OR</em>, and <em>NOT</em> search operators supported for tests/hardware/software search fields. **</p>';
+			$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)))');
+			if(isset($_POST['containing_hardware']) && !empty($_POST['containing_hardware']))
+			{
+				$hw_advanced_query = stripos($_POST['containing_hardware'], ' AND ') !== false || stripos($_POST['containing_hardware'], ' OR ') !== false || stripos($_POST['containing_hardware'], ' NOT ') !== false;
+				if($hw_advanced_query || true)
+				{
+					$hw_advanced_query = pts_phoroql::search_query_to_tree($_POST['containing_hardware']);
 				}
-				$min_date = strtotime(phoromatic_server::account_created_on($_SESSION['AccountID']));
-				$default_start_date = max($min_date, strtotime('-1 year'));
-				$min_date = date('Y-m-d', $min_date);
-				$time_start = strtotime(isset($_POST['time_start']) && !empty($_POST['time_start']) ? $_POST['time_start'] : $min_date);
-				if(empty($time_start))
+				else
 				{
-					$time_start = strtotime($min_date);
+					$search_for .= ' AND UploadID IN (SELECT UploadID FROM phoromatic_results_systems WHERE AccountID = :account_id AND Hardware LIKE :containing_hardware)';
 				}
-				$time_end = strtotime((isset($_POST['time_end']) && !empty($_POST['time_end']) ? $_POST['time_end'] : date('Y-m-d')) . ' 23:59:59');
-				if(empty($time_end))
+			}
+			if(isset($_POST['containing_software']) && !empty($_POST['containing_software']))
+			{
+				$sw_advanced_query = strpos($_POST['containing_software'], ' AND ') !== false || strpos($_POST['containing_software'], ' OR ') !== false || strpos($_POST['containing_software'], ' NOT ') !== false;
+				if($sw_advanced_query || true)
 				{
-					$time_end = strtotime(date('Y-m-d') . ' 23:59:59');
+					$sw_advanced_query = pts_phoroql::search_query_to_tree($_POST['containing_software']);
 				}
-				$main .= '<form action="' . $_SERVER['REQUEST_URI'] . '" method="post"><div style="text-align: left; font-weight: bold;">Results From <input id="time_start" name="time_start" type="date" required pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}" min="' . $min_date . '" value="' . (isset($_POST['time_start']) ? $_POST['time_start'] : date('Y-m-d', $default_start_date)) . '" max="' . date('Y-m-d') . '" /> To  <input id="time_end" name="time_end" type="date" required pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}" min="' . $min_date . '" value="' . (isset($_POST['time_end']) ? $_POST['time_end'] : date('Y-m-d')) . '" max="' . date('Y-m-d') . '" /> &nbsp; With Tests: <input type="text" name="containing_tests" id="containing_tests" value="' . (isset($_POST['containing_tests']) ? $_POST['containing_tests'] : null) . '" /> With Hardware: <input type="text" name="containing_hardware" id="containing_hardware" value="' . (isset($_POST['containing_hardware']) ? $_POST['containing_hardware'] : null) . '" /> With System Software: <input type="text" name="containing_software" id="containing_software" value="' . (isset($_POST['containing_software']) ? $_POST['containing_software'] : null) . '" /> Search For <input type="text" name="search" id="search_for" value="' . (isset($_POST['search']) ? $_POST['search'] : null) . '" /> Limit Results To <select id="result_limit" name="result_limit">';
-				for($i = 100; $i <= 500; $i += 100)
+				else
 				{
-					$main .= '<option value="' . $i . '"' . ($result_limit == $i ? ' selected="selected"' : null) . '>' . $i . '</option>';
+					$search_for .= ' AND UploadID IN (SELECT UploadID FROM phoromatic_results_systems WHERE AccountID = :account_id AND Software LIKE :containing_software)';
 				}
-				$main .= '<option value=""' . (isset($_POST['result_limit']) && empty($result_limit) ? ' selected="selected"' : null) . '>No Limit</option>';
+			}
+			$main .= '<div style="margin: 0 5%;"><ul style="max-height: 100%;"><li><h1>Recent Test Results</h1></li>';
 
-				$main .= '</select> &nbsp; <input type="button" value="Reset" onclick="phoromatic_clear_results_search_fields();" />';
-				$main .= ' &nbsp; <input type="submit" value="Update" /></div></form>';
-				$main .= '<p style="font-size: 90%;">** <em>AND</em>, <em>OR</em>, and <em>NOT</em> search operators supported for tests/hardware/software search fields. **</p>';
-				$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)))');
-				if(isset($_POST['containing_hardware']) && !empty($_POST['containing_hardware']))
+			if(isset($PATH[1]) && $PATH[0] == 'hash')
+			{
+				// Find matching comparison hashes
+				$stmt = phoromatic_server::$db->prepare('SELECT Title, SystemID, ScheduleID, PPRID, UploadTime, TimesViewed, AccountID, UploadID FROM phoromatic_results WHERE AccountID = :account_id ' . $search_for. ' AND ComparisonHash = :comparison_hash ORDER BY UploadTime DESC');
+				$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, AccountID, UploadID FROM phoromatic_results WHERE AccountID = :account_id ' . $search_for. ' AND BenchmarkTicketID = :ticket_id ORDER BY UploadTime DESC');
+				$stmt->bindValue(':ticket_id', $PATH[1]);
+			}
+			else
+			{
+				$stmt = phoromatic_server::$db->prepare('SELECT Title, SystemID, ScheduleID, PPRID, UploadTime, TimesViewed, AccountID, UploadID FROM phoromatic_results WHERE AccountID = :account_id ' . $search_for. ' ORDER BY UploadTime DESC');
+			}
+
+			$stmt->bindValue(':account_id', $_SESSION['AccountID']);
+			$stmt->bindValue(':search', (isset($_POST['search']) ? '%' . $_POST['search'] . '%' : null));
+			$stmt->bindValue(':containing_hardware', (isset($_POST['containing_hardware']) ? '%' . $_POST['containing_hardware'] . '%' : null));
+			$stmt->bindValue(':containing_software', (isset($_POST['containing_software']) ? '%' . $_POST['containing_software'] . '%' : null));
+			$test_result_result = $stmt->execute();
+			$results = 0;
+			$containing_tests = isset($_POST['containing_tests']) ? $_POST['containing_tests'] : null;
+			if(!empty($containing_tests))
+			{
+				$containing_tests = pts_phoroql::search_query_to_tree($containing_tests);
+			}
+
+			while($test_result_row = $test_result_result->fetchArray())
+			{
+				if(strtotime($test_result_row['UploadTime']) > $time_end)
 				{
-					$hw_advanced_query = stripos($_POST['containing_hardware'], ' AND ') !== false || stripos($_POST['containing_hardware'], ' OR ') !== false || stripos($_POST['containing_hardware'], ' NOT ') !== false;
-					if($hw_advanced_query || true)
-					{
-						$hw_advanced_query = pts_phoroql::search_query_to_tree($_POST['containing_hardware']);
-					}
-					else
-					{
-						$search_for .= ' AND UploadID IN (SELECT UploadID FROM phoromatic_results_systems WHERE AccountID = :account_id AND Hardware LIKE :containing_hardware)';
-					}
+					continue;
 				}
-				if(isset($_POST['containing_software']) && !empty($_POST['containing_software']))
+				if(strtotime($test_result_row['UploadTime']) < $time_start)
 				{
-					$sw_advanced_query = strpos($_POST['containing_software'], ' AND ') !== false || strpos($_POST['containing_software'], ' OR ') !== false || strpos($_POST['containing_software'], ' NOT ') !== false;
-					if($sw_advanced_query || true)
-					{
-						$sw_advanced_query = pts_phoroql::search_query_to_tree($_POST['containing_software']);
-					}
-					else
-					{
-						$search_for .= ' AND UploadID IN (SELECT UploadID FROM phoromatic_results_systems WHERE AccountID = :account_id AND Software LIKE :containing_software)';
-					}
+					//break;
 				}
-				$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')
+				if(!empty($result_limit) && $result_limit > 1 && $result_limit == $results)
 				{
-					// Find matching comparison hashes
-					$stmt = phoromatic_server::$db->prepare('SELECT Title, SystemID, ScheduleID, PPRID, UploadTime, TimesViewed, AccountID, UploadID FROM phoromatic_results WHERE AccountID = :account_id ' . $search_for. ' AND ComparisonHash = :comparison_hash ORDER BY UploadTime DESC');
-					$stmt->bindValue(':comparison_hash', $PATH[1]);
+					break;
 				}
-				else if(isset($PATH[1]) && $PATH[0] == 'ticket')
+
+				$composite_xml = phoromatic_server::phoromatic_account_result_path($test_result_row['AccountID'], $test_result_row['UploadID']) . 'composite.xml';
+				$result_file = new pts_result_file($composite_xml);
+
+				if(isset($_POST['containing_hardware']) && !empty($_POST['containing_hardware']) && $hw_advanced_query)
 				{
-					// Find matching ticket results
-					$stmt = phoromatic_server::$db->prepare('SELECT Title, SystemID, ScheduleID, PPRID, UploadTime, TimesViewed, AccountID, UploadID FROM phoromatic_results WHERE AccountID = :account_id ' . $search_for. ' AND BenchmarkTicketID = :ticket_id ORDER BY UploadTime DESC');
-					$stmt->bindValue(':ticket_id', $PATH[1]);
+					//if(!$result_file->contains_system_hardware($_POST['containing_hardware']))
+					if(!pts_phoroql::evaluate_search_tree($hw_advanced_query, 'AND', array($result_file, 'contains_system_hardware')))
+					{
+						continue;
+					}
 				}
-				else
+				if(isset($_POST['containing_software']) && !empty($_POST['containing_software']) && $sw_advanced_query)
 				{
-					$stmt = phoromatic_server::$db->prepare('SELECT Title, SystemID, ScheduleID, PPRID, UploadTime, TimesViewed, AccountID, UploadID FROM phoromatic_results WHERE AccountID = :account_id ' . $search_for. ' ORDER BY UploadTime DESC');
+					if(!pts_phoroql::evaluate_search_tree($sw_advanced_query, 'AND', array($result_file, 'contains_system_software')))
+					{
+						continue;
+					}
 				}
-
-				$stmt->bindValue(':account_id', $_SESSION['AccountID']);
-				$stmt->bindValue(':search', (isset($_POST['search']) ? '%' . $_POST['search'] . '%' : null));
-				$stmt->bindValue(':containing_hardware', (isset($_POST['containing_hardware']) ? '%' . $_POST['containing_hardware'] . '%' : null));
-				$stmt->bindValue(':containing_software', (isset($_POST['containing_software']) ? '%' . $_POST['containing_software'] . '%' : null));
-				$test_result_result = $stmt->execute();
-				$results = 0;
-				$containing_tests = isset($_POST['containing_tests']) ? $_POST['containing_tests'] : null;
 				if(!empty($containing_tests))
 				{
-					$containing_tests = pts_phoroql::search_query_to_tree($containing_tests);
+					if(!pts_phoroql::evaluate_search_tree($containing_tests, 'AND', array($result_file, 'contains_test')))
+					{
+						continue;
+					}
 				}
 
-				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_server::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, UploadID FROM phoromatic_results WHERE ' . $result_share_opt . ' AND AccountID != :account_id ' . $search_for. ' ORDER BY UploadTime DESC');
+			$stmt->bindValue(':account_id', $_SESSION['AccountID']);
+			$stmt->bindValue(':search', (isset($_POST['search']) ? '%' . $_POST['search'] . '%' : null));
+			$stmt->bindValue(':containing_hardware', (isset($_POST['containing_hardware']) ? '%' . $_POST['containing_hardware'] . '%' : null));
+			$stmt->bindValue(':containing_software', (isset($_POST['containing_software']) ? '%' . $_POST['containing_software'] . '%' : 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 .= '<ul style="max-height: 100%;"><li><h1>Results Shared By Other Groups</h1></li>';
+				$results = 0;
+				do
 				{
 					if(strtotime($test_result_row['UploadTime']) > $time_end)
 					{
@@ -215,7 +278,6 @@ class phoromatic_results implements pts_webui_interface
 							continue;
 						}
 					}
-
 					if(!empty($containing_tests))
 					{
 						if(!pts_phoroql::evaluate_search_tree($containing_tests, 'AND', array($result_file, 'contains_test')))
@@ -224,84 +286,16 @@ class phoromatic_results implements pts_webui_interface
 						}
 					}
 
-					$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>';
+					$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_server::account_id_to_group_name($test_result_row['AccountID']) . '</strong></td><td>' . phoromatic_server::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>';
-				}
-				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>';
-				}
+				while($test_result_row = $test_result_result->fetchArray());
 				$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, UploadID FROM phoromatic_results WHERE ' . $result_share_opt . ' AND AccountID != :account_id ' . $search_for. ' ORDER BY UploadTime DESC');
-				$stmt->bindValue(':account_id', $_SESSION['AccountID']);
-				$stmt->bindValue(':search', (isset($_POST['search']) ? '%' . $_POST['search'] . '%' : null));
-				$stmt->bindValue(':containing_hardware', (isset($_POST['containing_hardware']) ? '%' . $_POST['containing_hardware'] . '%' : null));
-				$stmt->bindValue(':containing_software', (isset($_POST['containing_software']) ? '%' . $_POST['containing_software'] . '%' : 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 .= '<ul style="max-height: 100%;"><li><h1>Results Shared By Other Groups</h1></li>';
-					$results = 0;
-					do
-					{
-						if(strtotime($test_result_row['UploadTime']) > $time_end)
-						{
-							continue;
-						}
-						if(strtotime($test_result_row['UploadTime']) < $time_start)
-						{
-							//break;
-						}
-						if(!empty($result_limit) && $result_limit > 1 && $result_limit == $results)
-						{
-							break;
-						}
-
-						$composite_xml = phoromatic_server::phoromatic_account_result_path($test_result_row['AccountID'], $test_result_row['UploadID']) . 'composite.xml';
-						$result_file = new pts_result_file($composite_xml);
-
-						if(isset($_POST['containing_hardware']) && !empty($_POST['containing_hardware']) && $hw_advanced_query)
-						{
-							//if(!$result_file->contains_system_hardware($_POST['containing_hardware']))
-							if(!pts_phoroql::evaluate_search_tree($hw_advanced_query, 'AND', array($result_file, 'contains_system_hardware')))
-							{
-								continue;
-							}
-						}
-						if(isset($_POST['containing_software']) && !empty($_POST['containing_software']) && $sw_advanced_query)
-						{
-							if(!pts_phoroql::evaluate_search_tree($sw_advanced_query, 'AND', array($result_file, 'contains_system_software')))
-							{
-								continue;
-							}
-						}
-
-						if(!empty($containing_tests))
-						{
-							if(!pts_phoroql::evaluate_search_tree($containing_tests, 'AND', array($result_file, 'contains_test')))
-							{
-								continue;
-							}
-						}
-
-						$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);
-			echo phoromatic_webui_footer();
+		echo phoromatic_webui_main($main);
+		echo phoromatic_webui_footer();
 	}
 }
 

programming_language: PHP
filename: phoromatic_sched.php
change_type: ModificationType.MODIFY
diff: @@ -3,8 +3,8 @@
 /*
 	Phoronix Test Suite
 	URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
-	Copyright (C) 2014 - 2017, Phoronix Media
-	Copyright (C) 2014 - 2017, Michael Larabel
+	Copyright (C) 2014 - 2022, Phoronix Media
+	Copyright (C) 2014 - 2022, Michael Larabel
 
 	This program is free software; you can redistribute it and/or modify
 	it under the terms of the GNU General Public License as published by
@@ -20,7 +20,6 @@
 	along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
-
 class phoromatic_sched implements pts_webui_interface
 {
 	public static function page_title()
@@ -236,53 +235,53 @@ class phoromatic_sched implements pts_webui_interface
 <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();
-			}
+		<p><select name="schedule_hour" id="schedule_hour">';
 
-			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">';
+		if(!$is_new)
+		{
+			$run_at = explode('.', $e_schedule['RunAt']);
+			$days_active = !empty($e_schedule['ActiveOn']) ? explode(',', $e_schedule['ActiveOn']) : array();
+		}
 
-			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>';
-			}
+		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><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 .= '</select> <select name="schedule_minute" id="schedule_minute">';
 
-			$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. One-time benchmarking can also be setup via the <a href="?benchmark">Run A Benchmark</a> page.</h3></td>
-</tr>
-</table>';
+		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 .= (empty($env_var_edit) ? '<p><a id="env_var_options_show" onclick="javascript:document.getElementById(\'env_var_options\').style.display = \'block\'; javascript:document.getElementById(\'env_var_options_show\').style.display = \'none\'; ">Advanced Options</a></p> <div id="env_var_options" style="display: none;">' : '<div id="env_var_options">') . '<p>The advanced options require the Phoromatic clients be on the latest Phoronix Test Suite (10.8 or newer / Git). See the Phoronix Test Suite documentation for more information on these environment variables / advanced options.</p>' . pts_env::get_html_options('phoromatic', $env_var_edit) . '</div>';
+		$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 align="right"><input name="submit" value="' . ($is_new ? 'Create' : 'Edit') . ' Schedule" type="submit" onclick="return pts_rmm_validate_schedule();" /></p>
+		$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. One-time benchmarking can also be setup via the <a href="?benchmark">Run A Benchmark</a> page.</h3></td>
+			</tr>
+			</table>';
+
+		$main .= (empty($env_var_edit) ? '<p><a id="env_var_options_show" onclick="javascript:document.getElementById(\'env_var_options\').style.display = \'block\'; javascript:document.getElementById(\'env_var_options_show\').style.display = \'none\'; ">Advanced Options</a></p> <div id="env_var_options" style="display: none;">' : '<div id="env_var_options">') . '<p>The advanced options require the Phoromatic clients be on the latest Phoronix Test Suite (10.8 or newer / Git). See the Phoronix Test Suite documentation for more information on these environment variables / advanced options.</p>' . pts_env::get_html_options('phoromatic', $env_var_edit) . '</div>';
+
+		$main .= '<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);
-			echo phoromatic_webui_footer();
+		echo phoromatic_webui_main($main);
+		echo phoromatic_webui_footer();
 	}
 }
 

programming_language: PHP
filename: phoromatic_schedules.php
change_type: ModificationType.MODIFY
diff: @@ -3,8 +3,8 @@
 /*
 	Phoronix Test Suite
 	URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
-	Copyright (C) 2008 - 2018, Phoronix Media
-	Copyright (C) 2008 - 2018, Michael Larabel
+	Copyright (C) 2008 - 2022, Phoronix Media
+	Copyright (C) 2008 - 2022, Michael Larabel
 
 	This program is free software; you can redistribute it and/or modify
 	it under the terms of the GNU General Public License as published by
@@ -20,7 +20,6 @@
 	along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
-
 class phoromatic_schedules implements pts_webui_interface
 {
 	public static function page_title()
@@ -55,12 +54,12 @@ class phoromatic_schedules implements pts_webui_interface
 			}
 			else
 			{
-
 				if(!PHOROMATIC_USER_IS_VIEWER)
 				{
 
 					if(isset($_POST['add_to_schedule_select_test']))
 					{
+						phoromatic_quit_if_invalid_input_found(array('add_to_schedule_select_test'));
 						$name = $_POST['add_to_schedule_select_test'];
 						$args = array();
 						$args_name = array();
@@ -69,6 +68,7 @@ class phoromatic_schedules implements pts_webui_interface
 						{
 							if(substr($i, 0, 12) == 'test_option_' && substr($i, -9) != '_selected')
 							{
+								phoromatic_quit_if_invalid_input_found(array($i, $i . '_selected'));
 								array_push($args, $v);
 								array_push($args_name, $_POST[$i . '_selected']);
 							}
@@ -175,7 +175,6 @@ class phoromatic_schedules implements pts_webui_interface
 					}
 				}
 
-
 				$main .= '<h1>' . $row['Title'] . '</h1>';
 				$main .= '<h3>' . $row['Description'] . '</h3>';
 				switch($row['RunPriority'])
@@ -248,15 +247,15 @@ class phoromatic_schedules implements pts_webui_interface
 				}
 				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>';
+					$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 />';
@@ -426,8 +425,6 @@ class phoromatic_schedules implements pts_webui_interface
 					$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]);
@@ -446,7 +443,7 @@ class phoromatic_schedules implements pts_webui_interface
 						{
 							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>';
+						$main .= '<a href="?result/' . $test_result_row['PPRID'] . '"><li>' . $test_result_row['Title'] . '<br /><table><tr><td>' . phoromatic_server::system_id_to_name($test_result_row['SystemID']) . '</td><td>' . phoromatic_user_friendly_timedate($test_result_row['UploadTime']) .  '</td></tr></table></li></a>';
 						$results++;
 
 					}
@@ -489,116 +486,110 @@ class phoromatic_schedules implements pts_webui_interface
 
 
 		$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>';
+		<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 .= '<div class="pts_phoromatic_info_box_area">
-					<ul>
-						<li><h1>Active Test Schedules</h1></li>';
+		$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());
-					}
+		$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 .= '</ul>
+		</div>';
 
-			$main .= '<hr /><h2>Schedule Overview</h2>';
-			$week = array('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday');
+		$main .= '<hr /><h2>Schedule Overview</h2>';
+		$week = array('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday');
 
-			foreach($week as $i => $day)
+		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())
 			{
-				$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)
 				{
-					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 />';
+					$main .= '<h3>' . $day . '</h3>' . PHP_EOL . '<p>';
+					$has_matched = true;
 				}
-
-				if($has_matched)
-					$main .= '</p>' . PHP_EOL;
-
+				$main .= '<em>' . $row['RunAt'] . '</em> <a href="?schedules/' . $row['ScheduleID'] . '">' . $row['Title'] . '</a>';
+				//$main .= $row['RunTargetSystems'] . ' ' . $row['RunTargetGroups'];
+				$main .= '<br />';
 			}
 
-			$main .= '<div class="pts_phoromatic_info_box_area">
-					<ul>
-						<li><h1>Deactivated Test Schedules</h1></li>';
+			if($has_matched)
+				$main .= '</p>' . PHP_EOL;
+		}
 
-					$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();
+		$main .= '<div class="pts_phoromatic_info_box_area">
+				<ul>
+				<li><h1>Deactivated Test Schedules</h1></li>';
 
-					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());
-					}
+		$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 .= '</ul>
+		</div>';
 
-			echo '<div id="pts_phoromatic_main_area">' . $main . '</div>';
-			echo phoromatic_webui_footer();
+		echo '<div id="pts_phoromatic_main_area">' . $main . '</div>';
+		echo phoromatic_webui_footer();
 	}
 }
 

programming_language: PHP
filename: phoromatic_search.php
change_type: ModificationType.MODIFY
diff: @@ -3,8 +3,8 @@
 /*
 	Phoronix Test Suite
 	URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
-	Copyright (C) 2014 - 2018, Phoronix Media
-	Copyright (C) 2014 - 2018, Michael Larabel
+	Copyright (C) 2014 - 2022, Phoronix Media
+	Copyright (C) 2014 - 2022, Michael Larabel
 
 	This program is free software; you can redistribute it and/or modify
 	it under the terms of the GNU General Public License as published by
@@ -20,7 +20,6 @@
 	along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
-
 class phoromatic_search implements pts_webui_interface
 {
 	public static function page_title()
@@ -178,8 +177,7 @@ class phoromatic_search implements pts_webui_interface
 	}
 	public static function render_page_process($PATH)
 	{
-		$search_query = $_REQUEST['search'];
-
+		$search_query = pts_strings::sanitize($_REQUEST['search']);
 		$main = null;
 
 		if(strlen($search_query) < 4)

programming_language: PHP
filename: phoromatic_settings.php
change_type: ModificationType.MODIFY
diff: @@ -20,7 +20,6 @@
 	along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
-
 class phoromatic_settings implements pts_webui_interface
 {
 	public static function page_title()

programming_language: PHP
filename: phoromatic_system_claim.php
change_type: ModificationType.MODIFY
diff: @@ -3,8 +3,8 @@
 /*
 	Phoronix Test Suite
 	URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
-	Copyright (C) 2008 - 2015, Phoronix Media
-	Copyright (C) 2008 - 2015, Michael Larabel
+	Copyright (C) 2008 - 2022, Phoronix Media
+	Copyright (C) 2008 - 2022, Michael Larabel
 
 	This program is free software; you can redistribute it and/or modify
 	it under the terms of the GNU General Public License as published by
@@ -20,7 +20,6 @@
 	along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
-
 class phoromatic_system_claim implements pts_webui_interface
 {
 	public static function page_title()
@@ -43,36 +42,36 @@ class phoromatic_system_claim implements pts_webui_interface
 		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(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(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;
@@ -88,8 +87,8 @@ echo "' . phoromatic_web_socket_server_addr() . '" > $PHORO_FILE_PATH/modules-da
 			{
 				$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(':ip_address', pts_strings::simple($_POST['ip_claim']));
+				$stmt->bindValue(':mac_address', pts_strings::simple($_POST['mac_claim']));
 				$stmt->bindValue(':creation_time', phoromatic_server::current_time());
 				$result = $stmt->execute();
 			}
@@ -98,8 +97,8 @@ echo "' . phoromatic_web_socket_server_addr() . '" > $PHORO_FILE_PATH/modules-da
 				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(':ip_address', pts_strings::simple($ipc));
+				$stmt->bindValue(':mac_address', pts_strings::simple($macc));
 				$stmt->bindValue(':creation_time', phoromatic_server::current_time());
 				$result = $stmt->execute();
 			}

programming_language: PHP
filename: phoromatic_systems.php
change_type: ModificationType.MODIFY
diff: @@ -3,8 +3,8 @@
 /*
 	Phoronix Test Suite
 	URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
-	Copyright (C) 2008 - 2021, Phoronix Media
-	Copyright (C) 2008 - 2021, Michael Larabel
+	Copyright (C) 2008 - 2022, Phoronix Media
+	Copyright (C) 2008 - 2022, Michael Larabel
 
 	This program is free software; you can redistribute it and/or modify
 	it under the terms of the GNU General Public License as published by
@@ -42,11 +42,12 @@ class phoromatic_systems implements pts_webui_interface
 
 		if(!PHOROMATIC_USER_IS_VIEWER && !empty($PATH[0]) && isset($_POST['system_title']) && !empty($_POST['system_title']) && isset($_POST['system_description']) && isset($_POST['system_state']))
 		{
+			phoromatic_quit_if_invalid_input_found(array('system_title', 'system_description', '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(':title', pts_strings::simple($_POST['system_title']));
+			$stmt->bindValue(':description', pts_strings::sanitize($_POST['system_description']));
 			$stmt->bindValue(':state', $_POST['system_state']);
 			$stmt->bindValue(':block_power_offs', $_POST['block_power_offs']);
 			$stmt->execute();
@@ -383,7 +384,7 @@ class phoromatic_systems implements pts_webui_interface
 							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>';
+						$main .= '<a href="?result/' . $test_result_row['PPRID'] . '"><li>' . $test_result_row['Title'] . '<br /><table><tr><td>' . phoromatic_server::system_id_to_name($test_result_row['SystemID']) . '</td><td>' . phoromatic_user_friendly_timedate($test_result_row['UploadTime']) .  '</td></tr></table></li></a>';
 						$results++;
 
 					}
@@ -471,6 +472,8 @@ class phoromatic_systems implements pts_webui_interface
 
 				if($group)
 				{
+					phoromatic_quit_if_invalid_input_found(array('new_group'));
+					$group = pts_strings::simple($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);
@@ -529,18 +532,19 @@ class phoromatic_systems implements pts_webui_interface
 			}
 			else if(!PHOROMATIC_USER_IS_VIEWER && isset($_POST['remove_group']))
 			{
+				$remove_group = pts_strings::sanitize($_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->bindValue(':group_name', $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 = phoromatic_server::$db->prepare('SELECT SystemID, Groups FROM phoromatic_systems WHERE AccountID = :account_id AND Groups LIKE \'%#' . $remove_group . '#%\'');
 				$stmt->bindValue(':account_id', $_SESSION['AccountID']);
 				$result = $stmt->execute();
 				while($row = $result->fetchArray())
 				{
-					$revised_groups = str_replace('#' . $_POST['remove_group'] . '#', '', $row['Groups']);
+					$revised_groups = str_replace('#' . $remove_group . '#', '', $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']);
@@ -555,7 +559,7 @@ class phoromatic_systems implements pts_webui_interface
 				$stmt = phoromatic_server::$db->prepare('UPDATE phoromatic_systems SET State = :state WHERE AccountID = :account_id AND (julianday() - julianday(LastCommunication)) > :inactive_days_before_removal');
 				$stmt->bindValue(':account_id', $_SESSION['AccountID']);
 				$stmt->bindValue(':state', -1);
-				$stmt->bindValue(':inactive_days_before_removal', $_POST['remove_inactive_systems']);
+				$stmt->bindValue(':inactive_days_before_removal', pts_strings::sanitize($_POST['remove_inactive_systems']));
 				$stmt->execute();
 			}
 
@@ -571,8 +575,8 @@ class phoromatic_systems implements pts_webui_interface
 				<p><button onclick="javascript:window.location.replace(\'?system_claim\');">Add Via SSH Or IP/MAC Claim</button></p>';
 
 			}
-			$main .= '<hr />
 
+			$main .= '<hr />
 			<h2>Systems</h2>
 			<div class="pts_phoromatic_info_box_area">
 
@@ -639,7 +643,6 @@ class phoromatic_systems implements pts_webui_interface
 				$main .= '</ul>';
 			}
 
-
 			$main .= '</div>';
 
 			if(!PHOROMATIC_USER_IS_VIEWER)
@@ -730,9 +733,7 @@ class phoromatic_systems implements pts_webui_interface
 					}
 
 					$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)
@@ -740,9 +741,7 @@ class phoromatic_systems implements pts_webui_interface
 						$main .= '<option value="' . $group . '">' . $group . '</option>';
 					}
 					$main .= '</select> <input name="submit" value="Remove Group" type="submit" /></form></p>';
-
 					$main .= '<hr /><h2>Retire Inactive Systems</h2><p>This option will soft-delete systems that have not communicated with this Phoromatic Server in more than one week (7 days).</p>';
-
 					$main .= '<p><form action="' . $_SERVER['REQUEST_URI'] . '" name="remove_inactive" method="post"><input type="hidden" name="remove_inactive_systems" value="7" /><input name="submit" value="Remove Inactive Systems" type="submit" /></form></p>';
 				}
 			}

programming_language: PHP
filename: phoromatic_testing.php
change_type: ModificationType.MODIFY
diff: @@ -3,8 +3,8 @@
 /*
 	Phoronix Test Suite
 	URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
-	Copyright (C) 2016, Phoronix Media
-	Copyright (C) 2016, Michael Larabel
+	Copyright (C) 2016 - 2022, Phoronix Media
+	Copyright (C) 2016 - 2022, Michael Larabel
 
 	This program is free software; you can redistribute it and/or modify
 	it under the terms of the GNU General Public License as published by
@@ -20,7 +20,6 @@
 	along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
-
 class phoromatic_testing implements pts_webui_interface
 {
 	public static function page_title()
@@ -43,97 +42,94 @@ class phoromatic_testing implements pts_webui_interface
 		$main = '<h1>Phoromatic Testing Options</h1><h2>Test Schedules</h2>
 			<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)
+		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
 			{
-				$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>';
+				$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>Current Schedules</h2>';
+		$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)
+		{
 			$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>';
-
-			$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)
-			{
-				$main .= '<div class="pts_phoromatic_info_box_area">
-						<ul>
-							<li><h1>Active Benchmark Tickets</h1></li>';
+				<ul>
+				<li><h1>Active Benchmark Tickets</h1></li>';
 
-				$row = $result->fetchArray();
+			$row = $result->fetchArray();
 
-				if(!empty($row))
-				{
-					do
-					{
-						$main .= '<a href="?benchmark/' . $row['TicketID'] . '"><li>' . $row['Title'] . '</li></a>';
-					}
-					while($row = $result->fetchArray());
-				}
-				else
+			if(!empty($row))
+			{
+				do
 				{
-					$main .= '<li class="light" style="text-align: center;">No Tickets Found</li>';	
+					$main .= '<a href="?benchmark/' . $row['TicketID'] . '"><li>' . $row['Title'] . '</li></a>';
 				}
+				while($row = $result->fetchArray());
 			}
-			$main .= '</ul>
-			</div>';
-
-			if(!PHOROMATIC_USER_IS_VIEWER)
+			else
 			{
-				$main .= '
-				<hr />
-				<h2>Run A Benchmark</h2>
-				<p><a href="?benchmark">Run a benchmark</a> is the area where you can run a one-time benchmark on selected system(s) and is also where to go for setting up a stress-run benchmark.</p>
-				<hr />
-				<h2>Create A Suite</h2>
-				<p><a href="?build_suite">Build a suite</a>, which is a collection of predefined test profiles.</p>
-				<hr />
-				<h2>View Local Suites</h2>
-				<p><a href="?local_suites">See local suites</a> available for your benchmarking needs.</p>';
+				$main .= '<li class="light" style="text-align: center;">No Tickets Found</li>';	
 			}
-
-
-			echo '<div id="pts_phoromatic_main_area">' . $main . '</div>';
-			echo phoromatic_webui_footer();
+		}
+		$main .= '</ul>
+		</div>';
+
+		if(!PHOROMATIC_USER_IS_VIEWER)
+		{
+			$main .= '
+			<hr />
+			<h2>Run A Benchmark</h2>
+			<p><a href="?benchmark">Run a benchmark</a> is the area where you can run a one-time benchmark on selected system(s) and is also where to go for setting up a stress-run benchmark.</p>
+			<hr />
+			<h2>Create A Suite</h2>
+			<p><a href="?build_suite">Build a suite</a>, which is a collection of predefined test profiles.</p>
+			<hr />
+			<h2>View Local Suites</h2>
+			<p><a href="?local_suites">See local suites</a> available for your benchmarking needs.</p>';
+		}
+
+		echo '<div id="pts_phoromatic_main_area">' . $main . '</div>';
+		echo phoromatic_webui_footer();
 	}
 }
 

programming_language: PHP
filename: phoromatic_tests.php
change_type: ModificationType.MODIFY
diff: @@ -20,7 +20,6 @@
 	along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
-
 class phoromatic_tests implements pts_webui_interface
 {
 	public static function page_title()

programming_language: PHP
filename: phoromatic_tracker.php
change_type: ModificationType.MODIFY
diff: @@ -177,7 +177,6 @@ class phoromatic_tracker implements pts_webui_interface
 						while($row = $result->fetchArray());
 					}
 
-
 			$main .= '</ul>
 			</div>';
 			$right = null;

programming_language: PHP
filename: phoromatic_users.php
change_type: ModificationType.MODIFY
diff: @@ -3,8 +3,8 @@
 /*
 	Phoronix Test Suite
 	URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
-	Copyright (C) 2014 - 2015, Phoronix Media
-	Copyright (C) 2014 - 2015, Michael Larabel
+	Copyright (C) 2014 - 2022, Phoronix Media
+	Copyright (C) 2014 - 2022, Michael Larabel
 
 	This program is free software; you can redistribute it and/or modify
 	it under the terms of the GNU General Public License as published by
@@ -20,7 +20,6 @@
 	along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
-
 class phoromatic_users implements pts_webui_interface
 {
 	public static function page_title()
@@ -45,13 +44,15 @@ class phoromatic_users implements pts_webui_interface
 
 		if(isset($_POST['group_name']))
 		{
+			phoromatic_quit_if_invalid_input_found(array('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(':group_name', pts_strings::simple($_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']))
 		{
+			phoromatic_quit_if_invalid_input_found(array('username', 'email'));
 			// REGISTER NEW USER
 			if(strlen($_POST['username']) < 4 || strpos($_POST['username'], ' ') !== false)
 			{
@@ -240,7 +241,7 @@ class phoromatic_users implements pts_webui_interface
 			<p><input name="submit" value="Add User" type="submit" /></p>
 			</form>';
 
-		$group_name = phoromatic_account_id_to_group_name($_SESSION['AccountID']);
+		$group_name = phoromatic_server::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>

programming_language: PHP
filename: phoromatic_welcome.php
change_type: ModificationType.MODIFY
diff: @@ -3,8 +3,8 @@
 /*
 	Phoronix Test Suite
 	URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
-	Copyright (C) 2008 - 2015, Phoronix Media
-	Copyright (C) 2008 - 2015, Michael Larabel
+	Copyright (C) 2008 - 2022, Phoronix Media
+	Copyright (C) 2008 - 2022, Michael Larabel
 
 	This program is free software; you can redistribute it and/or modify
 	it under the terms of the GNU General Public License as published by
@@ -20,7 +20,6 @@
 	along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
-
 class phoromatic_welcome implements pts_webui_interface
 {
 	public static function page_title()
@@ -42,6 +41,7 @@ class phoromatic_welcome implements pts_webui_interface
 
 		if($account_creation_enabled && isset($_POST['register_username']) && isset($_POST['register_password']) && isset($_POST['register_password_confirm']) && isset($_POST['register_email']))
 		{
+			phoromatic_quit_if_invalid_input_found(array('register_username', '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));
 
 			if($new_account)
@@ -60,6 +60,7 @@ class phoromatic_welcome implements pts_webui_interface
 		}
 		else if(isset($_POST['username']) && isset($_POST['password']) && strtolower($_POST['username']) == 'rootadmin')
 		{
+			phoromatic_quit_if_invalid_input_found(array('username'));
 			$admin_pw = phoromatic_server::read_setting('root_admin_pw');
 			if(empty($admin_pw))
 			{
@@ -94,6 +95,7 @@ class phoromatic_welcome implements pts_webui_interface
 		}
 		else if(isset($_POST['username']) && isset($_POST['password']))
 		{
+			phoromatic_quit_if_invalid_input_found(array('username'));
 			$matching_user = phoromatic_server::$db->querySingle('SELECT UserName, Password, AccountID, UserID, AdminLevel, CreatedOn FROM phoromatic_users WHERE UserName = \'' . SQLite3::escapeString($_POST['username']) . '\'', true);
 			if(!empty($matching_user))
 			{
@@ -223,8 +225,7 @@ class phoromatic_welcome implements pts_webui_interface
 			else
 			{
 
-				$box .= '
-							<p id="register_link"><a onclick="javascript:document.getElementById(\'register\').style.display = \'block\'; document.getElementById(\'register_link\').style.display = \'none\';">Create A New Account</a></p>
+				$box .= '<p id="register_link"><a onclick="javascript:document.getElementById(\'register\').style.display = \'block\'; document.getElementById(\'register_link\').style.display = \'none\';">Create A New Account</a></p>
 			<div style="display: none;" id="register">
 
 
@@ -252,11 +253,9 @@ class phoromatic_welcome implements pts_webui_interface
 						<li class="label_input_wrapper">
 							<input type="submit" value="Create Account" />
 						</li>
-
 					</ul>
 
 					</form></div>';
-
 			}
 			$box .= '<hr />
 			<h1>View Public Results</h1>

programming_language: PHP
filename: phoromatic_functions.php
change_type: ModificationType.MODIFY
diff: @@ -3,8 +3,8 @@
 /*
 	Phoronix Test Suite
 	URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
-	Copyright (C) 2013 - 2020, Phoronix Media
-	Copyright (C) 2013 - 2020, Michael Larabel
+	Copyright (C) 2013 - 2022, Phoronix Media
+	Copyright (C) 2013 - 2022, Michael Larabel
 
 	This program is free software; you can redistribute it and/or modify
 	it under the terms of the GNU General Public License as published by
@@ -23,6 +23,34 @@
 define('PHOROMATIC_SERVER_WEB_INTERFACE', true);
 define('PAGE_LOAD_START_TIME', microtime(true));
 
+function phoromatic_quit_if_invalid_input_found($input_keys = null)
+{
+	if(empty($input_keys))
+	{
+		// Check them all if not being selective about what keys to check
+		$input_keys = array_keys($_REQUEST);
+	}
+	// backup as to sanitization and stripping elsewhere, safeguard namely check for things like < for fields that shouldn't have it
+	// plus a few simple backups as safeguards for words that really have no legit relevance within Phoromatic...
+
+	foreach(array('<', 'document.write', '../', 'onerror', 'onload', 'alert(') as $invalid_string)
+	{
+		foreach($input_keys as $key)
+		{
+			if(isset($_REQUEST[$key]) && !empty($_REQUEST[$key]))
+			{
+				foreach(pts_arrays::to_array($_REQUEST[$key]) as $val_to_check)
+				{
+					if(stripos($val_to_check, $invalid_string) !== false)
+					{
+						echo '<strong>Exited due to invalid input ( ' . $invalid_string . ') attempted:</strong> ' . htmlspecialchars($val_to_check);
+						exit;
+					}
+				}
+			}
+		}
+	}
+}
 function phoromatic_annotate_entry($type, $id, $secondary_id)
 {
 	$annotate_hash = sha1($id . $secondary_id);
@@ -64,7 +92,6 @@ function phoromatic_annotate_entry($type, $id, $secondary_id)
 	$stmt->bindValue(':secondary_id', $secondary_id);
 	$result = $stmt->execute();
 	$row = $result->fetchArray();
-
 	$output = null;
 
 	if($row)
@@ -164,7 +191,7 @@ function phoromatic_webui_header($left_items, $right = null)
 	{
 		$ret .= '<ul id="pts_phoromatic_info">';
 		$ret .= '<li><a class="ph_date" href="#">' . date('H:i T - j F') . '</a></li>';
-		$group_name = phoromatic_account_id_to_group_name($_SESSION['AccountID']);
+		$group_name = phoromatic_server::account_id_to_group_name($_SESSION['AccountID']);
 		if($group_name != null)
 		{
 			$ret .= '<li><a href="#">' . $group_name . '</a></li>';
@@ -211,6 +238,11 @@ function phoromatic_webui_header($left_items, $right = null)
 }
 function phoromatic_get_posted_var($name, $default_value = null)
 {
+	if(isset($_POST[$name]))
+	{
+		phoromatic_quit_if_invalid_input_found(array($name));
+	}
+
 	return isset($_POST[$name]) ? $_POST[$name] : null;
 }
 function phoromatic_webui_main($main, $right = null)
@@ -467,7 +499,7 @@ function phoromatic_webui_right_panel_logged_in($add = null)
 		$row = $result->fetchArray();
 		$activity_count = $row['ActivityCount'];
 
-		$group_name = phoromatic_account_id_to_group_name($_SESSION['AccountID']);
+		$group_name = phoromatic_server::account_id_to_group_name($_SESSION['AccountID']);
 		if($group_name != null)
 		{
 			$group_name = '<strong>' . $group_name . '</strong><br />';
@@ -539,10 +571,8 @@ function phoromatic_web_socket_server_addr()
 function phoromatic_error_page($title, $description)
 {
 	echo phoromatic_webui_header(array(''), '');
-
 	$box = '<h1>' . $title . '</h1>
-		<h2>' . $description . '</h2>
-		<p>To fix this error, try <a onclick="javascript:window.history.back();">returning to the previous page</a>. Still having problems? Consider <a href="https://github.com/phoronix-test-suite/phoronix-test-suite/issues?state=open">opening a GitHub issue report</a>; commercial support customers should contact Phoronix Media.</p><hr /><hr />';
+		<h2>' . $description . '</h2>';
 	echo phoromatic_webui_box($box);
 	echo phoromatic_webui_footer();
 }
@@ -573,10 +603,6 @@ function phoromatic_systems_needing_attention()
 
 	return $main;
 }
-function phoromatic_system_id_to_name($system_id, $aid = false)
-{
-	return phoromatic_server::system_id_to_name($system_id, $aid);
-}
 function phoromatic_oldest_result_for_schedule($schedule_id)
 {
 	static $old_time;
@@ -609,11 +635,6 @@ function phoromatic_schedule_id_to_name($schedule_id)
 
 	return $schedule_names[$schedule_id];
 }
-function phoromatic_account_id_to_group_name($account_id)
-{
-	// XXX deprecated
-	return phoromatic_server::account_id_to_group_name($account_id);
-}
 function create_new_phoromatic_account($register_username, $register_password, $register_password_confirm, $register_email, $seed_accountid = null)
 {
 	// REGISTER NEW USER

programming_language: PHP
filename: phoromatic.php
change_type: ModificationType.MODIFY
diff: @@ -195,7 +195,7 @@ if(empty($result))
 	$stmt->bindValue(':gsid', $GSID);
 	$stmt->bindValue(':access_ip', $_SERVER['REMOTE_ADDR']);
 	$stmt->bindValue(':local_ip', $LOCAL_IP);
-	$stmt->bindValue(':title', $HOSTNAME);
+	$stmt->bindValue(':title', pts_strings::simple($HOSTNAME));
 	$stmt->bindValue(':current_time', phoromatic_server::current_time());
 	$stmt->bindValue(':machine_self_id', $PTS_MACHINE_SELF_ID);
 	$stmt->bindValue(':core_version', $CLIENT_CORE_VERSION);
@@ -244,7 +244,7 @@ if(strtotime($result['LastCommunication']) < (time() - 300))
 	$stmt = phoromatic_server::$db->prepare('UPDATE phoromatic_systems SET LastIP = :access_ip, LocalIP = :local_ip, LastCommunication = :current_time, Hardware = :client_hardware, Software = :client_software, SystemProperties = :phodevi_properties, ClientVersion = :client_version, MachineSelfID = :machine_self_id, NetworkMAC = :network_mac, NetworkWakeOnLAN = :network_wol, CoreVersion = :core_version WHERE AccountID = :account_id AND SystemID = :system_id');
 	$stmt->bindValue(':account_id', $ACCOUNT_ID);
 	$stmt->bindValue(':system_id', SYSTEM_ID);
-	$stmt->bindValue(':client_hardware', $CLIENT_HARDWARE);
+	$stmt->bindValue(':client_hardware', pts_strings::simple($CLIENT_HARDWARE));
 	$stmt->bindValue(':client_software', $CLIENT_SOFTWARE);
 	$stmt->bindValue(':phodevi_properties', $PHODEVI_PROPERTIES);
 	$stmt->bindValue(':client_version', $CLIENT_VERSION);

programming_language: PHP
filename: public.php
change_type: ModificationType.MODIFY
diff: @@ -3,8 +3,8 @@
 /*
 	Phoronix Test Suite
 	URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
-	Copyright (C) 2008 - 2021, Phoronix Media
-	Copyright (C) 2008 - 2021, Michael Larabel
+	Copyright (C) 2008 - 2022, Phoronix Media
+	Copyright (C) 2008 - 2022, Michael Larabel
 
 	This program is free software; you can redistribute it and/or modify
 	it under the terms of the GNU General Public License as published by
@@ -130,19 +130,19 @@ if(!empty($result_ids))
 				$system_name = null;
 				break;
 			case 'SYSTEM_NAME':
-				$system_name = phoromatic_system_id_to_name($row['SystemID'], $row['AccountID']);
+				$system_name = phoromatic_server::system_id_to_name($row['SystemID'], $row['AccountID']);
 				break;
 			case 'TRIGGER':
 				$system_name = $row['Trigger'];
 				break;
 			case 'TRIGGER_AND_SYSTEM':
-				$system_name = phoromatic_system_id_to_name($row['SystemID'], $row['AccountID']) . ': ' . $row['Trigger'];
+				$system_name = phoromatic_server::system_id_to_name($row['SystemID'], $row['AccountID']) . ': ' . $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'], $row['AccountID']) . ' - ' . phoromatic_schedule_id_to_name($row['ScheduleID']) . ' - ' . $row['Trigger'];
+				$system_name = phoromatic_server::system_id_to_name($row['SystemID'], $row['AccountID']) . ' - ' . phoromatic_schedule_id_to_name($row['ScheduleID']) . ' - ' . $row['Trigger'];
 		}
 
 		$rf = new pts_result_file($composite_xml);
@@ -155,53 +155,11 @@ if(!empty($result_ids))
 	$result_file->merge($result_files, $attributes);
 	$extra_attributes = array();
 
-	$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',
-		);
-	foreach($attribute_options as $web_var => $attr_var)
-	{
-		if(isset($_REQUEST[$web_var]))
-		{
-			$extra_attributes[$attr_var] = true;
-		}
-	}
-
-	if(isset($_POST['transpose_comparison']))
-	{
-		$result_file->invert_multi_way_invert();
-	}
-	$intent = null;
-	$main .= '<h1>' . $result_file->get_title() . '</h1>';
-	$main .= '<p>' . $result_file->get_description() . '</p>';
-	$main .= phoromatic_annotate_entry('RESULT', implode(',', $result_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(',', $result_ids), $result_object->get_comparison_hash(true, false));
-		$main .= '<p style="text-align: center; overflow: auto;">';
-		$main .= pts_render::render_graph_inline_embed($result_object, $result_file, $extra_attributes);
-		$main .= '</p>';
-	}
-	$main .= '</div>';
+	$embed = new pts_result_viewer_embed($result_file);
+	$embed->show_html_result_table(false);
+	$embed->show_test_metadata_helper(false);
+	$embed->include_page_print_only_helpers(false);
+	$main .= $embed->get_html();
 }
 else
 {
@@ -285,7 +243,7 @@ else
 			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(\'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>';
+		$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_server::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)

programming_language: PHP