1<?php
2
3/*
4	Phoronix Test Suite
5	URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
6	Copyright (C) 2008 - 2021, Phoronix Media
7	Copyright (C) 2008 - 2021, Michael Larabel
8	pts-core.php: To boot-strap the Phoronix Test Suite start-up
9
10	This program is free software; you can redistribute it and/or modify
11	it under the terms of the GNU General Public License as published by
12	the Free Software Foundation; either version 3 of the License, or
13	(at your option) any later version.
14
15	This program is distributed in the hope that it will be useful,
16	but WITHOUT ANY WARRANTY; without even the implied warranty of
17	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18	GNU General Public License for more details.
19
20	You should have received a copy of the GNU General Public License
21	along with this program. If not, see <http://www.gnu.org/licenses/>.
22*/
23
24class pts_core
25{
26	public static function init()
27	{
28		//set_time_limit(0);
29		pts_define_directories(); // Define directories
30
31		pts_define('PTS_INIT_TIME', time());
32
33		if(!defined('PHP_VERSION_ID'))
34		{
35			$php_version = explode('.', PHP_VERSION);
36			pts_define('PHP_VERSION_ID', ($php_version[0] * 10000 + $php_version[1] * 100 + $php_version[2]));
37		}
38	}
39	public static function user_home_directory()
40	{
41		// Gets the system user's home directory
42		static $userhome = null;
43
44		if($userhome == null)
45		{
46			if(function_exists('posix_getpwuid') && function_exists('posix_getuid'))
47			{
48				$userinfo = posix_getpwuid(posix_getuid());
49				$userhome = $userinfo['dir'];
50			}
51			else if(($home = pts_client::read_env('HOME')))
52			{
53				$userhome = $home;
54			}
55			else if(($home = pts_client::read_env('HOMEPATH')))
56			{
57				$userhome = pts_client::read_env('HOMEDRIVE') . $home;
58			}
59			else if(PTS_IS_DAEMONIZED_SERVER_PROCESS)
60			{
61				$userhome = PTS_USER_PATH;
62			}
63			else if(substr(__FILE__, 0, 6) == '/home/')
64			{
65				$home_dir = substr(__FILE__, 0, strpos(__FILE__, '/', 7)) . '/';
66				if(is_dir($home_dir) && is_dir($home_dir . '.phoronix-test-suite'))
67				{
68					$userhome = $home_dir;
69				}
70			}
71			else
72			{
73				if(!is_writable('/'))
74				{
75					echo PHP_EOL . 'ERROR: Cannot find home directory.' . PHP_EOL;
76				}
77				$userhome = null;
78			}
79
80			$userhome = pts_strings::add_trailing_slash($userhome);
81		}
82
83		return $userhome;
84	}
85	public static function codename($full_string = false)
86	{
87		$codename = ucwords(strtolower(PTS_CODENAME));
88
89		return ($full_string ? 'PhoronixTestSuite/' : null) . $codename;
90	}
91	public static function program_title()
92	{
93		// First argument was originally $show_codename, but no longer used/honored
94		return 'Phoronix Test Suite v' . PTS_VERSION;
95	}
96}
97function pts_define($name, $value = null)
98{
99	static $defines;
100
101	if($name === -1)
102	{
103		return $defines;
104	}
105	else if(isset($defines[$name]))
106	{
107		return false;
108	}
109
110	$defines[$name] = $value;
111	define($name, $value);
112}
113function pts_define_directories()
114{
115	// User's home directory for storing results, module files, test installations, etc.
116	pts_define('PTS_CORE_PATH', PTS_PATH . 'pts-core/');
117
118	if(is_dir(PTS_PATH . 'ob-cache/'))
119	{
120		pts_define('PTS_INTERNAL_OB_CACHE', PTS_PATH . 'ob-cache/');
121	}
122	else
123	{
124		pts_define('PTS_INTERNAL_OB_CACHE', false);
125	}
126
127	pts_define('PTS_IS_DAEMONIZED_SERVER_PROCESS', PTS_IS_CLIENT && is_writable('/var/lib/') && is_writable('/etc') ? true : false);
128
129	if(($user_path_override = getenv('PTS_USER_PATH_OVERRIDE')) != false && is_dir($user_path_override))
130	{
131		pts_define('PTS_USER_PATH', $user_path_override);
132	}
133
134	if(PTS_IS_DAEMONIZED_SERVER_PROCESS)
135	{
136		if(!is_dir('/var/cache/phoronix-test-suite/'))
137		{
138			mkdir('/var/cache/phoronix-test-suite/');
139		}
140
141		pts_define('PTS_USER_PATH', '/var/lib/phoronix-test-suite/');
142		pts_define('PTS_CORE_STORAGE', PTS_USER_PATH . 'core.pt2so');
143		pts_define('PTS_DOWNLOAD_CACHE_PATH', '/var/cache/phoronix-test-suite/download-cache/');
144		pts_define('PTS_OPENBENCHMARKING_SCRATCH_PATH', '/var/cache/phoronix-test-suite/openbenchmarking.org/');
145		pts_define('PTS_TEST_PROFILE_PATH', PTS_USER_PATH . 'test-profiles/');
146		pts_define('PTS_TEST_SUITE_PATH', PTS_USER_PATH . 'test-suites/');
147	}
148	else if(PTS_IS_CLIENT)
149	{
150		/* if(!is_dir(pts_core::user_home_directory() . '.phoronix-test-suite') && stripos(PHP_OS, 'win') !== false && getenv('AppData'))
151		{
152			pts_define('PTS_USER_PATH', getenv('AppData') . DIRECTORY_SEPARATOR . 'phoronix-test-suite' . DIRECTORY_SEPARATOR);
153		}
154		else
155		{ */
156			pts_define('PTS_USER_PATH', pts_core::user_home_directory() . '.phoronix-test-suite' . DIRECTORY_SEPARATOR);
157		//}
158		pts_define('PTS_CORE_STORAGE', PTS_USER_PATH . 'core.pt2so');
159		pts_define('PTS_DOWNLOAD_CACHE_PATH', PTS_USER_PATH . 'download-cache/');
160		pts_define('PTS_OPENBENCHMARKING_SCRATCH_PATH', PTS_USER_PATH . 'openbenchmarking.org/');
161		pts_define('PTS_TEST_PROFILE_PATH', PTS_USER_PATH . 'test-profiles/');
162		pts_define('PTS_TEST_SUITE_PATH', PTS_USER_PATH . 'test-suites/');
163	}
164	else if(defined('PTS_STORAGE_PATH'))
165	{
166		// e.g. OpenBenchmarking.org
167		pts_define('PTS_OPENBENCHMARKING_SCRATCH_PATH', PTS_STORAGE_PATH . 'openbenchmarking.org/');
168		pts_define('PTS_TEST_PROFILE_PATH', PTS_STORAGE_PATH . 'test-profiles/');
169		pts_define('PTS_TEST_SUITE_PATH', PTS_STORAGE_PATH . 'test-suites/');
170	}
171	else if(defined('PATH_TO_PHOROMATIC_STORAGE'))
172	{
173		pts_define('PTS_OPENBENCHMARKING_SCRATCH_PATH', PATH_TO_PHOROMATIC_STORAGE . 'openbenchmarking.org/');
174		pts_define('PTS_TEST_PROFILE_PATH', PATH_TO_PHOROMATIC_STORAGE . 'test-profiles/');
175		pts_define('PTS_TEST_SUITE_PATH', PATH_TO_PHOROMATIC_STORAGE . 'test-suites/');
176	}
177
178	// Misc Locations
179	pts_define('PTS_CORE_STATIC_PATH', PTS_CORE_PATH . 'static/');
180
181	if(is_dir('/usr/local/share/phoronix-test-suite/'))
182	{
183		pts_define('PTS_SHARE_PATH', '/usr/local/share/phoronix-test-suite/');
184	}
185	else if(is_dir('/usr/share/'))
186	{
187		pts_define('PTS_SHARE_PATH', '/usr/share/phoronix-test-suite/');
188		if(is_writable('/usr/share') && !is_dir(PTS_SHARE_PATH))
189		{
190			mkdir(PTS_SHARE_PATH);
191		}
192	}
193	else
194	{
195		pts_define('PTS_SHARE_PATH', false);
196	}
197
198	// Fallbacks below for dynamic result viewer
199	if(!defined('PTS_TEST_SUITE_PATH') && defined('PTS_INTERNAL_OB_CACHE') && is_dir(PTS_INTERNAL_OB_CACHE . 'test-suites/'))
200	{
201		pts_define('PTS_TEST_SUITE_PATH', PTS_INTERNAL_OB_CACHE . 'test-suites/');
202	}
203
204	if(!defined('PTS_TEST_PROFILE_PATH') && defined('PTS_INTERNAL_OB_CACHE') && is_dir(PTS_INTERNAL_OB_CACHE . 'test-profiles/'))
205	{
206		pts_define('PTS_TEST_PROFILE_PATH', PTS_INTERNAL_OB_CACHE . 'test-profiles/');
207	}
208
209	if(!defined('PTS_OPENBENCHMARKING_SCRATCH_PATH') && defined('PTS_INTERNAL_OB_CACHE') && is_dir(PTS_INTERNAL_OB_CACHE . 'openbenchmarking.org/'))
210	{
211		pts_define('PTS_OPENBENCHMARKING_SCRATCH_PATH', PTS_INTERNAL_OB_CACHE . 'openbenchmarking.org/');
212	}
213}
214function pts_needed_extensions()
215{
216	return array(
217		// Required? - The Check If In Place - Name - Description
218		// Required extesnions denoted by 1 at [0]
219		array(1, extension_loaded('dom'), 'DOM', 'The Document Object Model is required for XML operations.'),
220		array(1, extension_loaded('zip') || extension_loaded('zlib'), 'ZIP', 'ZIP support is required for file compression.'),
221		array(1, function_exists('json_decode'), 'JSON', 'JSON support is required for OpenBenchmarking.org.'),
222		array(1, function_exists('simplexml_load_string'), 'SimpleXML', 'SimpleXML is required for XML operations.'),
223		// Optional but recommended extensions
224		array(0, extension_loaded('openssl'), 'OpenSSL', 'OpenSSL support is recommended to support HTTPS traffic.'),
225		array(0, extension_loaded('gd'), 'GD', 'The GD library is recommended for improved graph rendering.'),
226		array(0, extension_loaded('zlib'), 'Zlib', 'The Zlib extension can be used for greater file compression.'),
227		array(0, function_exists('bzcompress'), 'Bzip2', 'The bzcompress/bzip2 support can be used for greater file compression.'),
228		array(0, extension_loaded('sqlite3'), 'SQLite3', 'SQLite3 is required when running a Phoromatic server.'),
229		array(0, function_exists('pcntl_fork'), 'PCNTL', 'PCNTL is highly recommended as it is required by some tests.'),
230		array(0, function_exists('posix_getpwuid'), 'POSIX', 'POSIX support is highly recommended.'),
231		array(0, function_exists('curl_init'), 'CURL', 'CURL is recommended for an enhanced download experience.'),
232		array(0, function_exists('socket_create_listen'), 'Sockets', 'Sockets is needed when running the Phoromatic Server.'),
233		array(0, function_exists('readline'), 'Readline', 'Readline support is useful for tab-based auto-completion support.'),
234		);
235}
236function pts_version_codenames()
237{
238	// Lots of inspiration for codenames often from Norwegian municipalities
239	// https://en.wikipedia.org/wiki/List_of_municipalities_of_Norway
240	return array(
241		// Sør-Trøndelag - Norway
242		'1.0' => 'Trondheim',
243		'1.2' => 'Malvik',
244		'1.4' => 'Orkdal',
245		'1.6' => 'Tydal',
246		'1.8' => 'Selbu',
247		// Troms - Norway
248		'2.0' => 'Sandtorg',
249		'2.2' => 'Bardu',
250		'2.4' => 'Lenvik',
251		'2.6' => 'Lyngen',
252		'2.8' => 'Torsken',
253		// Aust-Agder - Norway
254		'2.9' => 'Iveland', // early PTS3 development work
255		'3.0' => 'Iveland',
256		'3.2' => 'Grimstad',
257		'3.4' => 'Lillesand',
258		'3.6' => 'Arendal',
259		'3.8' => 'Bygland',
260		// Rogaland - Norway
261		'4.0' => 'Suldal',
262		'4.2' => 'Randaberg',
263		'4.4' => 'Forsand',
264		'4.6' => 'Utsira',
265		'4.8' => 'Sokndal',
266		// Tulskaya oblast / Tula Oblast region - Russia
267		'5.0' => 'Plavsk',
268		'5.2' => 'Khanino',
269		'5.4' => 'Lipki',
270		'5.6' => 'Dedilovo',
271		'5.8' => 'Belev',
272		// Finnmark - Norway
273		'6.0' => 'Hammerfest',
274		'6.2' => 'Gamvik',
275		'6.4' => 'Hasvik',
276		'6.6' => 'Loppa',
277		'6.8' => 'Tana',
278		// Hedmark - Norway
279		'7.0' => 'Ringsaker',
280		'7.2' => 'Trysil',
281		'7.4' => 'Tynset',
282		'7.6' => 'Alvdal',
283		'7.8' => 'Folldal',
284		// Østfold - Norway
285		'8.0' => 'Aremark',
286		'8.2' => 'Rakkestad',
287		'8.4' => 'Skiptvet',
288		'8.6' => 'Spydeberg',
289		'8.8' => 'Hvaler',
290		// Akershus - Norway
291		'9.0' => 'Asker',
292		'9.2' => 'Hurdal',
293		'9.4' => 'Vestby',
294		'9.6' => 'Nittedal',
295		'9.8' => 'Nesodden',
296		//  Senja Municipality in Troms og Finnmark - Norway
297		'10.0' => 'Finnsnes',
298		'10.2' => 'Harstad',
299		'10.4' => 'Ibestad',
300		'10.6' => 'Tjeldsund',
301		'10.8' => 'Nesseby',
302		);
303}
304
305pts_define('PTS_VERSION', '10.6.1');
306pts_define('PTS_CORE_VERSION', 10610);
307pts_define('PTS_RELEASE_DATE', '20211010');
308pts_define('PTS_CODENAME', 'Tjeldsund');
309
310pts_define('PTS_IS_CLIENT', (defined('PTS_MODE') && strstr(PTS_MODE, 'CLIENT') !== false));
311pts_define('PTS_IS_WEB_CLIENT', (defined('PTS_MODE') && PTS_MODE == 'WEB_CLIENT'));
312pts_define('PTS_IS_DEV_BUILD', (substr(PTS_VERSION, -2, 1) == 'm'));
313
314if(!defined('PTS_PATH'))
315{
316	pts_define('PTS_PATH', dirname(dirname(__FILE__)) . '/');
317}
318
319pts_define('PTS_PHP_VERSION', phpversion());
320
321if(PTS_IS_CLIENT || defined('PTS_AUTO_LOAD_OBJECTS'))
322{
323	function pts_build_dir_php_list($dir, &$files)
324	{
325		if($dh = opendir($dir))
326		{
327			while(($file = readdir($dh)) !== false)
328			{
329				if($file != '.' && $file != '..')
330				{
331					if(is_dir($dir . '/' . $file) && ((PTS_IS_CLIENT || defined('PTS_AUTO_LOAD_ALL_OBJECTS')) || $file != 'client'))
332					{
333						// The client folder should contain classes exclusively used by the client
334						pts_build_dir_php_list($dir . '/' . $file, $files);
335					}
336					else if(substr($file, -4) == '.php')
337					{
338						$files[substr($file, 0, -4)] = $dir . '/' . $file;
339					}
340				}
341			}
342		}
343		closedir($dh);
344	}
345	function pts_auto_load_class($to_load)
346	{
347		static $obj_files = null;
348
349		if($obj_files == null)
350		{
351			pts_build_dir_php_list(PTS_PATH . 'pts-core/objects', $obj_files);
352		}
353
354		if(isset($obj_files[$to_load]))
355		{
356			include($obj_files[$to_load]);
357			unset($obj_files[$to_load]);
358		}
359
360		return class_exists($to_load, false);
361	}
362	spl_autoload_register('pts_auto_load_class');
363}
364if(PTS_IS_CLIENT && ini_get('date.timezone') == null)
365{
366	$tz = null;
367
368	// timezone_name_from_abbr was added in PHP 5.1.3. pre-5.2 really isn't supported by PTS, but don't at least error out here but let it get to proper checks...
369	if(is_executable('/bin/date') && function_exists('timezone_name_from_abbr'))
370	{
371		$tz = timezone_name_from_abbr(trim(shell_exec('date +%Z 2> /dev/null')));
372	}
373	else if(strtoupper(substr(PHP_OS, 0, 3)) == 'WIN')
374	{
375		$tz = trim(shell_exec('powershell "(Get-TimeZone).BaseUtcOffset.Hours"'));
376		$tz = is_numeric($tz) ? timezone_name_from_abbr('', ($tz * 60 * 60), 0) : null;
377	}
378
379	if($tz == null || !in_array($tz, timezone_identifiers_list()))
380	{
381		$tz = 'UTC';
382	}
383
384	date_default_timezone_set($tz);
385}
386
387?>
388