xref: /PHP-8.4/ext/standard/info.c (revision 390088bf)
1 /*
2    +----------------------------------------------------------------------+
3    | Copyright (c) The PHP Group                                          |
4    +----------------------------------------------------------------------+
5    | This source file is subject to version 3.01 of the PHP license,      |
6    | that is bundled with this package in the file LICENSE, and is        |
7    | available through the world-wide-web at the following url:           |
8    | https://www.php.net/license/3_01.txt                                 |
9    | If you did not receive a copy of the PHP license and are unable to   |
10    | obtain it through the world-wide-web, please send a note to          |
11    | license@php.net so we can mail you a copy immediately.               |
12    +----------------------------------------------------------------------+
13    | Authors: Rasmus Lerdorf <rasmus@php.net>                             |
14    |          Zeev Suraski <zeev@php.net>                                 |
15    |          Colin Viebrock <colin@viebrock.ca>                          |
16    +----------------------------------------------------------------------+
17 */
18 
19 #include "php.h"
20 #include "php_ini.h"
21 #include "php_globals.h"
22 #include "ext/standard/head.h"
23 #include "ext/standard/html.h"
24 #include "info.h"
25 #include "credits.h"
26 #include "css.h"
27 #include "SAPI.h"
28 #include <time.h>
29 #include "php_main.h"
30 #include "zend_globals.h"		/* needs ELS */
31 #include "zend_extensions.h"
32 #include "zend_highlight.h"
33 #ifdef HAVE_SYS_UTSNAME_H
34 #include <sys/utsname.h>
35 #endif
36 #include "url.h"
37 
38 #ifdef PHP_WIN32
39 # include "winver.h"
40 #endif
41 
42 #define SECTION(name)	if (!sapi_module.phpinfo_as_text) { \
43 							php_info_print("<h2>" name "</h2>\n"); \
44 						} else { \
45 							php_info_print_table_start(); \
46 							php_info_print_table_header(1, name); \
47 							php_info_print_table_end(); \
48 						} \
49 
50 PHPAPI extern char *php_ini_opened_path;
51 PHPAPI extern char *php_ini_scanned_path;
52 PHPAPI extern char *php_ini_scanned_files;
53 
php_info_print_html_esc(const char * str,size_t len)54 static ZEND_COLD size_t php_info_print_html_esc(const char *str, size_t len) /* {{{ */
55 {
56 	size_t written;
57 	zend_string *new_str;
58 
59 	new_str = php_escape_html_entities((const unsigned char *) str, len, 0, ENT_QUOTES, "utf-8");
60 	written = php_output_write(ZSTR_VAL(new_str), ZSTR_LEN(new_str));
61 	zend_string_free(new_str);
62 	return written;
63 }
64 /* }}} */
65 
php_info_printf(const char * fmt,...)66 static ZEND_COLD size_t php_info_printf(const char *fmt, ...) /* {{{ */
67 {
68 	char *buf;
69 	size_t len, written;
70 	va_list argv;
71 
72 	va_start(argv, fmt);
73 	len = vspprintf(&buf, 0, fmt, argv);
74 	va_end(argv);
75 
76 	written = php_output_write(buf, len);
77 	efree(buf);
78 	return written;
79 }
80 /* }}} */
81 
php_info_print(const char * str)82 static zend_always_inline size_t php_info_print(const char *str) /* {{{ */
83 {
84 	return php_output_write(str, strlen(str));
85 }
86 /* }}} */
87 
php_info_print_stream_hash(const char * name,HashTable * ht)88 static ZEND_COLD void php_info_print_stream_hash(const char *name, HashTable *ht) /* {{{ */
89 {
90 	zend_string *key;
91 
92 	if (ht) {
93 		if (zend_hash_num_elements(ht)) {
94 			int first = 1;
95 
96 			if (!sapi_module.phpinfo_as_text) {
97 				php_info_printf("<tr><td class=\"e\">Registered %s</td><td class=\"v\">", name);
98 			} else {
99 				php_info_printf("\nRegistered %s => ", name);
100 			}
101 
102 			if (!HT_IS_PACKED(ht)) {
103 				ZEND_HASH_MAP_FOREACH_STR_KEY(ht, key) {
104 					if (key) {
105 						if (first) {
106 							first = 0;
107 						} else {
108 							php_info_print(", ");
109 						}
110 						if (!sapi_module.phpinfo_as_text) {
111 							php_info_print_html_esc(ZSTR_VAL(key), ZSTR_LEN(key));
112 						} else {
113 							php_info_print(ZSTR_VAL(key));
114 						}
115 					}
116 				} ZEND_HASH_FOREACH_END();
117 			}
118 
119 			if (!sapi_module.phpinfo_as_text) {
120 				php_info_print("</td></tr>\n");
121 			}
122 		} else {
123 			char reg_name[128];
124 			snprintf(reg_name, sizeof(reg_name), "Registered %s", name);
125 			php_info_print_table_row(2, reg_name, "none registered");
126 		}
127 	} else {
128 		php_info_print_table_row(2, name, "disabled");
129 	}
130 }
131 /* }}} */
132 
php_info_print_module(zend_module_entry * zend_module)133 PHPAPI ZEND_COLD void php_info_print_module(zend_module_entry *zend_module) /* {{{ */
134 {
135 	if (zend_module->info_func || zend_module->version) {
136 		if (!sapi_module.phpinfo_as_text) {
137 			zend_string *url_name = php_url_encode(zend_module->name, strlen(zend_module->name));
138 
139 			zend_str_tolower(ZSTR_VAL(url_name), ZSTR_LEN(url_name));
140 			php_info_printf("<h2><a name=\"module_%s\" href=\"#module_%s\">%s</a></h2>\n", ZSTR_VAL(url_name), ZSTR_VAL(url_name), zend_module->name);
141 
142 			efree(url_name);
143 		} else {
144 			php_info_print_table_start();
145 			php_info_print_table_header(1, zend_module->name);
146 			php_info_print_table_end();
147 		}
148 		if (zend_module->info_func) {
149 			zend_module->info_func(zend_module);
150 		} else {
151 			php_info_print_table_start();
152 			php_info_print_table_row(2, "Version", zend_module->version);
153 			php_info_print_table_end();
154 			DISPLAY_INI_ENTRIES();
155 		}
156 	} else {
157 		if (!sapi_module.phpinfo_as_text) {
158 			php_info_printf("<tr><td class=\"v\">%s</td></tr>\n", zend_module->name);
159 		} else {
160 			php_info_printf("%s\n", zend_module->name);
161 		}
162 	}
163 }
164 /* }}} */
165 
166 /* {{{ php_print_gpcse_array */
php_print_gpcse_array(char * name,size_t name_length)167 static ZEND_COLD void php_print_gpcse_array(char *name, size_t name_length)
168 {
169 	zval *data, *tmp;
170 	zend_string *string_key;
171 	zend_ulong num_key;
172 	zend_string *key;
173 
174 	key = zend_string_init(name, name_length, 0);
175 	zend_is_auto_global(key);
176 
177 	if ((data = zend_hash_find_deref(&EG(symbol_table), key)) != NULL && (Z_TYPE_P(data) == IS_ARRAY)) {
178 		ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(data), num_key, string_key, tmp) {
179 			if (!sapi_module.phpinfo_as_text) {
180 				php_info_print("<tr>");
181 				php_info_print("<td class=\"e\">");
182 			}
183 
184 			php_info_print("$");
185 			php_info_print(name);
186 			php_info_print("['");
187 
188 			if (string_key != NULL) {
189 				if (!sapi_module.phpinfo_as_text) {
190 					php_info_print_html_esc(ZSTR_VAL(string_key), ZSTR_LEN(string_key));
191 				} else {
192 					php_info_print(ZSTR_VAL(string_key));
193 				}
194 			} else {
195 				php_info_printf(ZEND_ULONG_FMT, num_key);
196 			}
197 			php_info_print("']");
198 			if (!sapi_module.phpinfo_as_text) {
199 				php_info_print("</td><td class=\"v\">");
200 			} else {
201 				php_info_print(" => ");
202 			}
203 			ZVAL_DEREF(tmp);
204 			if (Z_TYPE_P(tmp) == IS_ARRAY) {
205 				if (!sapi_module.phpinfo_as_text) {
206 					zend_string *str = zend_print_zval_r_to_str(tmp, 0);
207 					php_info_print("<pre>");
208 					php_info_print_html_esc(ZSTR_VAL(str), ZSTR_LEN(str));
209 					php_info_print("</pre>");
210 					zend_string_release_ex(str, 0);
211 				} else {
212 					zend_print_zval_r(tmp, 0);
213 				}
214 			} else {
215 				zend_string *tmp2;
216 				zend_string *str = zval_get_tmp_string(tmp, &tmp2);
217 
218 				if (!sapi_module.phpinfo_as_text) {
219 					if (ZSTR_LEN(str) == 0) {
220 						php_info_print("<i>no value</i>");
221 					} else {
222 						php_info_print_html_esc(ZSTR_VAL(str), ZSTR_LEN(str));
223 					}
224 				} else {
225 					php_info_print(ZSTR_VAL(str));
226 				}
227 
228 				zend_tmp_string_release(tmp2);
229 			}
230 			if (!sapi_module.phpinfo_as_text) {
231 				php_info_print("</td></tr>\n");
232 			} else {
233 				php_info_print("\n");
234 			}
235 		} ZEND_HASH_FOREACH_END();
236 	}
237 	zend_string_efree(key);
238 }
239 /* }}} */
240 
241 /* {{{ php_info_print_style */
php_info_print_style(void)242 PHPAPI ZEND_COLD void ZEND_COLD php_info_print_style(void)
243 {
244 	php_info_printf("<style type=\"text/css\">\n");
245 	php_info_print_css();
246 	php_info_printf("</style>\n");
247 }
248 /* }}} */
249 
250 #ifdef PHP_WIN32
251 /* {{{  */
252 
php_get_windows_name()253 static char* php_get_windows_name()
254 {
255 	OSVERSIONINFOEX osvi = EG(windows_version_info);
256 	SYSTEM_INFO si;
257 	DWORD dwType;
258 	const char *major = NULL, *sub = NULL;
259 
260 	ZeroMemory(&si, sizeof(SYSTEM_INFO));
261 
262 	GetNativeSystemInfo(&si);
263 
264 	if (VER_PLATFORM_WIN32_NT==osvi.dwPlatformId && osvi.dwMajorVersion >= 10) {
265 		if (osvi.dwMajorVersion == 10) {
266 			if (osvi.dwMinorVersion == 0) {
267 				if (osvi.wProductType == VER_NT_WORKSTATION) {
268 					if (osvi.dwBuildNumber >= 22000) {
269 						major = "Windows 11";
270 					} else {
271 						major = "Windows 10";
272 					}
273 				} else {
274 					if (osvi.dwBuildNumber >= 20348) {
275 						major = "Windows Server 2022";
276 					} else if (osvi.dwBuildNumber >= 19042) {
277 						major = "Windows Server, version 20H2";
278 					} else if (osvi.dwBuildNumber >= 19041) {
279 						major = "Windows Server, version 2004";
280 					} else if (osvi.dwBuildNumber >= 18363) {
281 						major = "Windows Server, version 1909";
282 					} else if (osvi.dwBuildNumber >= 18362) {
283 						major = "Windows Server, version 1903";
284 					} else if (osvi.dwBuildNumber >= 17763) {
285 						// could also be Windows Server, version 1809, but there's no easy way to tell
286 						major = "Windows Server 2019";
287 					} else if (osvi.dwBuildNumber >= 17134) {
288 						major = "Windows Server, version 1803";
289 					} else if (osvi.dwBuildNumber >= 16299) {
290 						major = "Windows Server, version 1709";
291 					} else {
292 						major = "Windows Server 2016";
293 					}
294 				}
295 			}
296 		}
297 	} else if (VER_PLATFORM_WIN32_NT==osvi.dwPlatformId && osvi.dwMajorVersion >= 6) {
298 		if (osvi.dwMajorVersion == 6) {
299 			ZEND_ASSERT(osvi.dwMinorVersion >= 2);
300 			if (osvi.dwMinorVersion == 2) {
301 				/* could be Windows 8/Windows Server 2012, could be Windows 8.1/Windows Server 2012 R2 */
302 				/* XXX and one more X - the above comment is true if no manifest is used for two cases:
303 					- if the PHP build doesn't use the correct manifest
304 					- if PHP DLL loaded under some binary that doesn't use the correct manifest
305 
306 					So keep the handling here as is for now, even if we know 6.2 is win8 and nothing else, and think about an improvement. */
307 				OSVERSIONINFOEX osvi81;
308 				DWORDLONG dwlConditionMask = 0;
309 				int op = VER_GREATER_EQUAL;
310 
311 				ZeroMemory(&osvi81, sizeof(OSVERSIONINFOEX));
312 				osvi81.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
313 				osvi81.dwMajorVersion = 6;
314 				osvi81.dwMinorVersion = 3;
315 				osvi81.wServicePackMajor = 0;
316 
317 				VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, op);
318 				VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, op);
319 				VER_SET_CONDITION(dwlConditionMask, VER_SERVICEPACKMAJOR, op);
320 
321 				if (VerifyVersionInfo(&osvi81,
322 					VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR,
323 					dwlConditionMask)) {
324 					osvi.dwMinorVersion = 3; /* Windows 8.1/Windows Server 2012 R2 */
325 					if (osvi.wProductType == VER_NT_WORKSTATION)  {
326 						major = "Windows 8.1";
327 					} else {
328 						major = "Windows Server 2012 R2";
329 					}
330 				} else {
331 					if (osvi.wProductType == VER_NT_WORKSTATION)  {
332 						major = "Windows 8";
333 					} else {
334 						major = "Windows Server 2012";
335 					}
336 				}
337 			} else if (osvi.dwMinorVersion == 3) {
338 				if (osvi.wProductType == VER_NT_WORKSTATION)  {
339 					major = "Windows 8.1";
340 				} else {
341 					major = "Windows Server 2012 R2";
342 				}
343 			} else {
344 				major = "Unknown Windows version";
345 			}
346 
347 			/* No return value check, as it can only fail if the input parameters are broken (which we manually supply) */
348 			GetProductInfo(6, 0, 0, 0, &dwType);
349 
350 			switch (dwType) {
351 				case PRODUCT_ULTIMATE:
352 					sub = "Ultimate Edition";
353 					break;
354 				case PRODUCT_HOME_BASIC:
355 					sub = "Home Basic Edition";
356 					break;
357 				case PRODUCT_HOME_PREMIUM:
358 					sub = "Home Premium Edition";
359 					break;
360 				case PRODUCT_ENTERPRISE:
361 					sub = "Enterprise Edition";
362 					break;
363 				case PRODUCT_HOME_BASIC_N:
364 					sub = "Home Basic N Edition";
365 					break;
366 				case PRODUCT_BUSINESS:
367 					if ((osvi.dwMajorVersion > 6) || (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion > 0)) {
368 						sub = "Professional Edition";
369 					} else {
370 						sub = "Business Edition";
371 					}
372 					break;
373 				case PRODUCT_STANDARD_SERVER:
374 					sub = "Standard Edition";
375 					break;
376 				case PRODUCT_DATACENTER_SERVER:
377 					sub = "Datacenter Edition";
378 					break;
379 				case PRODUCT_SMALLBUSINESS_SERVER:
380 					sub = "Small Business Server";
381 					break;
382 				case PRODUCT_ENTERPRISE_SERVER:
383 					sub = "Enterprise Edition";
384 					break;
385 				case PRODUCT_STARTER:
386 					if ((osvi.dwMajorVersion > 6) || (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion > 0)) {
387 						sub = "Starter N Edition";
388 					} else {
389 					    sub = "Starter Edition";
390 					}
391 					break;
392 				case PRODUCT_DATACENTER_SERVER_CORE:
393 					sub = "Datacenter Edition (core installation)";
394 					break;
395 				case PRODUCT_STANDARD_SERVER_CORE:
396 					sub = "Standard Edition (core installation)";
397 					break;
398 				case PRODUCT_ENTERPRISE_SERVER_CORE:
399 					sub = "Enterprise Edition (core installation)";
400 					break;
401 				case PRODUCT_ENTERPRISE_SERVER_IA64:
402 					sub = "Enterprise Edition for Itanium-based Systems";
403 					break;
404 				case PRODUCT_BUSINESS_N:
405 					if ((osvi.dwMajorVersion > 6) || (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion > 0)) {
406 						sub = "Professional N Edition";
407 					} else {
408 						sub = "Business N Edition";
409 					}
410 					break;
411 				case PRODUCT_WEB_SERVER:
412 					sub = "Web Server Edition";
413 					break;
414 				case PRODUCT_CLUSTER_SERVER:
415 					sub = "HPC Edition";
416 					break;
417 				case PRODUCT_HOME_SERVER:
418 					sub = "Storage Server Essentials Edition";
419 					break;
420 				case PRODUCT_STORAGE_EXPRESS_SERVER:
421 					sub = "Storage Server Express Edition";
422 					break;
423 				case PRODUCT_STORAGE_STANDARD_SERVER:
424 					sub = "Storage Server Standard Edition";
425 					break;
426 				case PRODUCT_STORAGE_WORKGROUP_SERVER:
427 					sub = "Storage Server Workgroup Edition";
428 					break;
429 				case PRODUCT_STORAGE_ENTERPRISE_SERVER:
430 					sub = "Storage Server Enterprise Edition";
431 					break;
432 				case PRODUCT_SERVER_FOR_SMALLBUSINESS:
433 					sub = "Essential Server Solutions Edition";
434 					break;
435 				case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
436 					sub = "Small Business Server Premium Edition";
437 					break;
438 				case PRODUCT_HOME_PREMIUM_N:
439 					sub = "Home Premium N Edition";
440 					break;
441 				case PRODUCT_ENTERPRISE_N:
442 					sub = "Enterprise N Edition";
443 					break;
444 				case PRODUCT_ULTIMATE_N:
445 					sub = "Ultimate N Edition";
446 					break;
447 				case PRODUCT_WEB_SERVER_CORE:
448 					sub = "Web Server Edition (core installation)";
449 					break;
450 				case PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT:
451 					sub = "Essential Business Server Management Server Edition";
452 					break;
453 				case PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY:
454 					sub = "Essential Business Server Management Security Edition";
455 					break;
456 				case PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING:
457 					sub = "Essential Business Server Management Messaging Edition";
458 					break;
459 				case PRODUCT_SERVER_FOUNDATION:
460 					sub = "Foundation Edition";
461 					break;
462 				case PRODUCT_HOME_PREMIUM_SERVER:
463 					sub = "Home Server 2011 Edition";
464 					break;
465 				case PRODUCT_SERVER_FOR_SMALLBUSINESS_V:
466 					sub = "Essential Server Solutions Edition (without Hyper-V)";
467 					break;
468 				case PRODUCT_STANDARD_SERVER_V:
469 					sub = "Standard Edition (without Hyper-V)";
470 					break;
471 				case PRODUCT_DATACENTER_SERVER_V:
472 					sub = "Datacenter Edition (without Hyper-V)";
473 					break;
474 				case PRODUCT_ENTERPRISE_SERVER_V:
475 					sub = "Enterprise Edition (without Hyper-V)";
476 					break;
477 				case PRODUCT_DATACENTER_SERVER_CORE_V:
478 					sub = "Datacenter Edition (core installation, without Hyper-V)";
479 					break;
480 				case PRODUCT_STANDARD_SERVER_CORE_V:
481 					sub = "Standard Edition (core installation, without Hyper-V)";
482 					break;
483 				case PRODUCT_ENTERPRISE_SERVER_CORE_V:
484 					sub = "Enterprise Edition (core installation, without Hyper-V)";
485 					break;
486 				case PRODUCT_HYPERV:
487 					sub = "Hyper-V Server";
488 					break;
489 				case PRODUCT_STORAGE_EXPRESS_SERVER_CORE:
490 					sub = "Storage Server Express Edition (core installation)";
491 					break;
492 				case PRODUCT_STORAGE_STANDARD_SERVER_CORE:
493 					sub = "Storage Server Standard Edition (core installation)";
494 					break;
495 				case PRODUCT_STORAGE_WORKGROUP_SERVER_CORE:
496 					sub = "Storage Server Workgroup Edition (core installation)";
497 					break;
498 				case PRODUCT_STORAGE_ENTERPRISE_SERVER_CORE:
499 					sub = "Storage Server Enterprise Edition (core installation)";
500 					break;
501 				case PRODUCT_STARTER_N:
502 					sub = "Starter N Edition";
503 					break;
504 				case PRODUCT_PROFESSIONAL:
505 					sub = "Professional Edition";
506 					break;
507 				case PRODUCT_PROFESSIONAL_N:
508 					sub = "Professional N Edition";
509 					break;
510 				case PRODUCT_SB_SOLUTION_SERVER:
511 					sub = "Small Business Server 2011 Essentials Edition";
512 					break;
513 				case PRODUCT_SERVER_FOR_SB_SOLUTIONS:
514 					sub = "Server For SB Solutions Edition";
515 					break;
516 				case PRODUCT_STANDARD_SERVER_SOLUTIONS:
517 					sub = "Solutions Premium Edition";
518 					break;
519 				case PRODUCT_STANDARD_SERVER_SOLUTIONS_CORE:
520 					sub = "Solutions Premium Edition (core installation)";
521 					break;
522 				case PRODUCT_SB_SOLUTION_SERVER_EM:
523 					sub = "Server For SB Solutions EM Edition";
524 					break;
525 				case PRODUCT_SERVER_FOR_SB_SOLUTIONS_EM:
526 					sub = "Server For SB Solutions EM Edition";
527 					break;
528 				case PRODUCT_SOLUTION_EMBEDDEDSERVER:
529 					sub = "MultiPoint Server Edition";
530 					break;
531 				case PRODUCT_ESSENTIALBUSINESS_SERVER_MGMT:
532 					sub = "Essential Server Solution Management Edition";
533 					break;
534 				case PRODUCT_ESSENTIALBUSINESS_SERVER_ADDL:
535 					sub = "Essential Server Solution Additional Edition";
536 					break;
537 				case PRODUCT_ESSENTIALBUSINESS_SERVER_MGMTSVC:
538 					sub = "Essential Server Solution Management SVC Edition";
539 					break;
540 				case PRODUCT_ESSENTIALBUSINESS_SERVER_ADDLSVC:
541 					sub = "Essential Server Solution Additional SVC Edition";
542 					break;
543 				case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM_CORE:
544 					sub = "Small Business Server Premium Edition (core installation)";
545 					break;
546 				case PRODUCT_CLUSTER_SERVER_V:
547 					sub = "Hyper Core V Edition";
548 					break;
549 				case PRODUCT_STARTER_E:
550 					sub = "Hyper Core V Edition";
551 					break;
552 				case PRODUCT_ENTERPRISE_EVALUATION:
553 					sub = "Enterprise Edition (evaluation installation)";
554 					break;
555 				case PRODUCT_MULTIPOINT_STANDARD_SERVER:
556 					sub = "MultiPoint Server Standard Edition (full installation)";
557 					break;
558 				case PRODUCT_MULTIPOINT_PREMIUM_SERVER:
559 					sub = "MultiPoint Server Premium Edition (full installation)";
560 					break;
561 				case PRODUCT_STANDARD_EVALUATION_SERVER:
562 					sub = "Standard Edition (evaluation installation)";
563 					break;
564 				case PRODUCT_DATACENTER_EVALUATION_SERVER:
565 					sub = "Datacenter Edition (evaluation installation)";
566 					break;
567 				case PRODUCT_ENTERPRISE_N_EVALUATION:
568 					sub = "Enterprise N Edition (evaluation installation)";
569 					break;
570 				case PRODUCT_STORAGE_WORKGROUP_EVALUATION_SERVER:
571 					sub = "Storage Server Workgroup Edition (evaluation installation)";
572 					break;
573 				case PRODUCT_STORAGE_STANDARD_EVALUATION_SERVER:
574 					sub = "Storage Server Standard Edition (evaluation installation)";
575 					break;
576 				case PRODUCT_CORE_N:
577 					sub = "Windows 8 N Edition";
578 					break;
579 				case PRODUCT_CORE_COUNTRYSPECIFIC:
580 					sub = "Windows 8 China Edition";
581 					break;
582 				case PRODUCT_CORE_SINGLELANGUAGE:
583 					sub = "Windows 8 Single Language Edition";
584 					break;
585 				case PRODUCT_CORE:
586 					sub = "Windows 8 Edition";
587 					break;
588 				case PRODUCT_PROFESSIONAL_WMC:
589 					sub = "Professional with Media Center Edition";
590 					break;
591 			}
592 		}
593 	} else {
594 		ZEND_UNREACHABLE();
595 	}
596 
597 	char *retval;
598 	spprintf(&retval, 0, "%s%s%s%s%s", major, sub?" ":"", sub?sub:"", osvi.szCSDVersion[0] != '\0'?" ":"", osvi.szCSDVersion);
599 	return retval;
600 }
601 /* }}}  */
602 
603 /* {{{  */
php_get_windows_cpu(char * buf,size_t bufsize)604 static void php_get_windows_cpu(char *buf, size_t bufsize)
605 {
606 	SYSTEM_INFO SysInfo;
607 	GetSystemInfo(&SysInfo);
608 	switch (SysInfo.wProcessorArchitecture) {
609 		case PROCESSOR_ARCHITECTURE_INTEL :
610 			snprintf(buf, bufsize, "i%d", SysInfo.dwProcessorType);
611 			break;
612 		case PROCESSOR_ARCHITECTURE_MIPS :
613 			snprintf(buf, bufsize, "MIPS R%d000", SysInfo.wProcessorLevel);
614 			break;
615 		case PROCESSOR_ARCHITECTURE_ALPHA :
616 			snprintf(buf, bufsize, "Alpha %d", SysInfo.wProcessorLevel);
617 			break;
618 		case PROCESSOR_ARCHITECTURE_PPC :
619 			snprintf(buf, bufsize, "PPC 6%02d", SysInfo.wProcessorLevel);
620 			break;
621 		case PROCESSOR_ARCHITECTURE_IA64 :
622 			snprintf(buf, bufsize,  "IA64");
623 			break;
624 #if defined(PROCESSOR_ARCHITECTURE_IA32_ON_WIN64)
625 		case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 :
626 			snprintf(buf, bufsize, "IA32");
627 			break;
628 #endif
629 #if defined(PROCESSOR_ARCHITECTURE_AMD64)
630 		case PROCESSOR_ARCHITECTURE_AMD64 :
631 			snprintf(buf, bufsize, "AMD64");
632 			break;
633 #endif
634 #if defined(PROCESSOR_ARCHITECTURE_ARM64)
635 		case PROCESSOR_ARCHITECTURE_ARM64 :
636 			snprintf(buf, bufsize, "ARM64");
637 			break;
638 #endif
639 		case PROCESSOR_ARCHITECTURE_UNKNOWN :
640 		default:
641 			snprintf(buf, bufsize, "Unknown");
642 			break;
643 	}
644 }
645 /* }}}  */
646 #endif
647 
php_is_valid_uname_mode(char mode)648 static inline bool php_is_valid_uname_mode(char mode) {
649 	return mode == 'a' || mode == 'm' || mode == 'n' || mode == 'r' || mode == 's' || mode == 'v';
650 }
651 
652 /* {{{ php_get_uname */
php_get_uname(char mode)653 PHPAPI zend_string *php_get_uname(char mode)
654 {
655 	char *php_uname;
656 
657 	ZEND_ASSERT(php_is_valid_uname_mode(mode));
658 #ifdef PHP_WIN32
659 	char tmp_uname[256];
660 	DWORD dwBuild=0;
661 	DWORD dwVersion = GetVersion();
662 	DWORD dwWindowsMajorVersion =  (DWORD)(LOBYTE(LOWORD(dwVersion)));
663 	DWORD dwWindowsMinorVersion =  (DWORD)(HIBYTE(LOWORD(dwVersion)));
664 	DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
665 	char ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
666 
667 	GetComputerName(ComputerName, &dwSize);
668 
669 	if (mode == 's') {
670 		php_uname = "Windows NT";
671 	} else if (mode == 'r') {
672 		return strpprintf(0, "%d.%d", dwWindowsMajorVersion, dwWindowsMinorVersion);
673 	} else if (mode == 'n') {
674 		php_uname = ComputerName;
675 	} else if (mode == 'v') {
676 		char *winver = php_get_windows_name();
677 		dwBuild = (DWORD)(HIWORD(dwVersion));
678 
679 		ZEND_ASSERT(winver != NULL);
680 
681 		zend_string *build_with_version = strpprintf(0, "build %d (%s)", dwBuild, winver);
682 		efree(winver);
683 		return build_with_version;
684 	} else if (mode == 'm') {
685 		php_get_windows_cpu(tmp_uname, sizeof(tmp_uname));
686 		php_uname = tmp_uname;
687 	} else { /* assume mode == 'a' */
688 		char *winver = php_get_windows_name();
689 		char wincpu[20];
690 
691 		ZEND_ASSERT(winver != NULL);
692 
693 		php_get_windows_cpu(wincpu, sizeof(wincpu));
694 		dwBuild = (DWORD)(HIWORD(dwVersion));
695 
696 		/* Windows "version" 6.2 could be Windows 8/Windows Server 2012, but also Windows 8.1/Windows Server 2012 R2 */
697 		if (dwWindowsMajorVersion == 6 && dwWindowsMinorVersion == 2) {
698 			if (strncmp(winver, "Windows 8.1", strlen("Windows 8.1")) == 0 || strncmp(winver, "Windows Server 2012 R2", strlen("Windows Server 2012 R2")) == 0) {
699 				dwWindowsMinorVersion = 3;
700 			}
701 		}
702 
703 		zend_string *build_with_all_info = strpprintf(0, "%s %s %d.%d build %d (%s) %s",
704 			"Windows NT", ComputerName, dwWindowsMajorVersion, dwWindowsMinorVersion, dwBuild,
705 			winver ? winver: "unknown", wincpu);
706 		efree(winver);
707 		return build_with_all_info;
708 	}
709 #else
710 #ifdef HAVE_SYS_UTSNAME_H
711 	struct utsname buf;
712 	if (uname((struct utsname *)&buf) == -1) {
713 		php_uname = PHP_UNAME;
714 	} else {
715 		if (mode == 's') {
716 			php_uname = buf.sysname;
717 		} else if (mode == 'r') {
718 			php_uname = buf.release;
719 		} else if (mode == 'n') {
720 			php_uname = buf.nodename;
721 		} else if (mode == 'v') {
722 			php_uname = buf.version;
723 		} else if (mode == 'm') {
724 			php_uname = buf.machine;
725 		} else { /* assume mode == 'a' */
726 			return strpprintf(0, "%s %s %s %s %s", buf.sysname, buf.nodename, buf.release, buf.version, buf.machine);
727 		}
728 	}
729 #else
730 	php_uname = PHP_UNAME;
731 #endif
732 #endif
733 	return zend_string_init(php_uname, strlen(php_uname), 0);
734 }
735 /* }}} */
736 
737 /* {{{ php_print_info_htmlhead */
php_print_info_htmlhead(void)738 PHPAPI ZEND_COLD void php_print_info_htmlhead(void)
739 {
740 	php_info_print("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"DTD/xhtml1-transitional.dtd\">\n");
741 	php_info_print("<html xmlns=\"http://www.w3.org/1999/xhtml\">");
742 	php_info_print("<head>\n");
743 	php_info_print_style();
744 	php_info_printf("<title>PHP %s - phpinfo()</title>", PHP_VERSION);
745 	php_info_print("<meta name=\"ROBOTS\" content=\"NOINDEX,NOFOLLOW,NOARCHIVE\" />");
746 	php_info_print("</head>\n");
747 	php_info_print("<body><div class=\"center\">\n");
748 }
749 /* }}} */
750 
751 /* {{{ module_name_cmp */
module_name_cmp(Bucket * f,Bucket * s)752 static int module_name_cmp(Bucket *f, Bucket *s)
753 {
754 	return strcasecmp(((zend_module_entry *)Z_PTR(f->val))->name,
755 				  ((zend_module_entry *)Z_PTR(s->val))->name);
756 }
757 /* }}} */
758 
759 /* {{{ php_print_info */
php_print_info(int flag)760 PHPAPI ZEND_COLD void php_print_info(int flag)
761 {
762 	char **env, *tmp1, *tmp2;
763 	zend_string *php_uname;
764 
765 	if (!sapi_module.phpinfo_as_text) {
766 		php_print_info_htmlhead();
767 	} else {
768 		php_info_print("phpinfo()\n");
769 	}
770 
771 	if (flag & PHP_INFO_GENERAL) {
772 		const char *zend_version = get_zend_version();
773 		char temp_api[10];
774 
775 		php_uname = php_get_uname('a');
776 
777 		if (!sapi_module.phpinfo_as_text) {
778 			php_info_print_box_start(1);
779 		}
780 
781 		if (!sapi_module.phpinfo_as_text) {
782 	        time_t the_time;
783 	        struct tm *ta, tmbuf;
784 
785 	        the_time = time(NULL);
786 	        ta = php_localtime_r(&the_time, &tmbuf);
787 
788 			php_info_print("<a href=\"https://www.php.net/\"><img src=\"");
789 	        if (ta && (ta->tm_mon==3) && (ta->tm_mday==1)) {
790 		        php_info_print(PHP_EGG_LOGO_DATA_URI "\" alt=\"PHP logo\" /></a>");
791 	        } else {
792 		        php_info_print(PHP_LOGO_DATA_URI "\" alt=\"PHP logo\" /></a>");
793 			}
794 		}
795 
796 		if (!sapi_module.phpinfo_as_text) {
797 			php_info_printf("<h1 class=\"p\">PHP Version %s</h1>\n", PHP_VERSION);
798 		} else {
799 			php_info_print_table_row(2, "PHP Version", PHP_VERSION);
800 		}
801 		php_info_print_box_end();
802 		php_info_print_table_start();
803 		php_info_print_table_row(2, "System", ZSTR_VAL(php_uname));
804 		php_info_print_table_row(2, "Build Date", __DATE__ " " __TIME__);
805 #ifdef PHP_BUILD_SYSTEM
806 		php_info_print_table_row(2, "Build System", PHP_BUILD_SYSTEM);
807 #endif
808 #ifdef PHP_BUILD_PROVIDER
809 		php_info_print_table_row(2, "Build Provider", PHP_BUILD_PROVIDER);
810 #endif
811 #ifdef PHP_BUILD_COMPILER
812 		php_info_print_table_row(2, "Compiler", PHP_BUILD_COMPILER);
813 #endif
814 #ifdef PHP_BUILD_ARCH
815 		php_info_print_table_row(2, "Architecture", PHP_BUILD_ARCH);
816 #endif
817 #ifdef CONFIGURE_COMMAND
818 		php_info_print_table_row(2, "Configure Command", CONFIGURE_COMMAND );
819 #endif
820 
821 		if (sapi_module.pretty_name) {
822 			php_info_print_table_row(2, "Server API", sapi_module.pretty_name );
823 		}
824 
825 #ifdef VIRTUAL_DIR
826 		php_info_print_table_row(2, "Virtual Directory Support", "enabled" );
827 #else
828 		php_info_print_table_row(2, "Virtual Directory Support", "disabled" );
829 #endif
830 
831 		php_info_print_table_row(2, "Configuration File (php.ini) Path", PHP_CONFIG_FILE_PATH);
832 		php_info_print_table_row(2, "Loaded Configuration File", php_ini_opened_path ? php_ini_opened_path : "(none)");
833 		php_info_print_table_row(2, "Scan this dir for additional .ini files", php_ini_scanned_path ? php_ini_scanned_path : "(none)");
834 		php_info_print_table_row(2, "Additional .ini files parsed", php_ini_scanned_files ? php_ini_scanned_files : "(none)");
835 
836 		snprintf(temp_api, sizeof(temp_api), "%d", PHP_API_VERSION);
837 		php_info_print_table_row(2, "PHP API", temp_api);
838 
839 		snprintf(temp_api, sizeof(temp_api), "%d", ZEND_MODULE_API_NO);
840 		php_info_print_table_row(2, "PHP Extension", temp_api);
841 
842 		snprintf(temp_api, sizeof(temp_api), "%d", ZEND_EXTENSION_API_NO);
843 		php_info_print_table_row(2, "Zend Extension", temp_api);
844 
845 		php_info_print_table_row(2, "Zend Extension Build", ZEND_EXTENSION_BUILD_ID);
846 		php_info_print_table_row(2, "PHP Extension Build", ZEND_MODULE_BUILD_ID);
847 
848 		snprintf(temp_api, sizeof(temp_api), "%d bits", SIZEOF_ZEND_LONG * 8);
849 		php_info_print_table_row(2, "PHP Integer Size", temp_api);
850 
851 #if ZEND_DEBUG
852 		php_info_print_table_row(2, "Debug Build", "yes" );
853 #else
854 		php_info_print_table_row(2, "Debug Build", "no" );
855 #endif
856 
857 #ifdef ZTS
858 		php_info_print_table_row(2, "Thread Safety", "enabled" );
859 		php_info_print_table_row(2, "Thread API", tsrm_api_name() );
860 #else
861 		php_info_print_table_row(2, "Thread Safety", "disabled" );
862 #endif
863 
864 #ifdef ZEND_SIGNALS
865 		php_info_print_table_row(2, "Zend Signal Handling", "enabled" );
866 #else
867 		php_info_print_table_row(2, "Zend Signal Handling", "disabled" );
868 #endif
869 
870 		php_info_print_table_row(2, "Zend Memory Manager", is_zend_mm() ? "enabled" : "disabled" );
871 
872 		{
873 			const zend_multibyte_functions *functions = zend_multibyte_get_functions();
874 			char *descr;
875 			if (functions) {
876 				spprintf(&descr, 0, "provided by %s", functions->provider_name);
877 			} else {
878 				descr = estrdup("disabled");
879 			}
880 			php_info_print_table_row(2, "Zend Multibyte Support", descr);
881 			efree(descr);
882 		}
883 
884 #ifdef ZEND_MAX_EXECUTION_TIMERS
885 		php_info_print_table_row(2, "Zend Max Execution Timers", "enabled" );
886 #else
887 		php_info_print_table_row(2, "Zend Max Execution Timers", "disabled" );
888 #endif
889 
890 #ifdef HAVE_IPV6
891 		php_info_print_table_row(2, "IPv6 Support", "enabled" );
892 #else
893 		php_info_print_table_row(2, "IPv6 Support", "disabled" );
894 #endif
895 
896 #ifdef HAVE_DTRACE
897 		php_info_print_table_row(2, "DTrace Support", (zend_dtrace_enabled ? "enabled" : "available, disabled"));
898 #else
899 		php_info_print_table_row(2, "DTrace Support", "disabled" );
900 #endif
901 
902 		php_info_print_stream_hash("PHP Streams",  php_stream_get_url_stream_wrappers_hash());
903 		php_info_print_stream_hash("Stream Socket Transports", php_stream_xport_get_hash());
904 		php_info_print_stream_hash("Stream Filters", php_get_stream_filters_hash());
905 
906 		php_info_print_table_end();
907 
908 		/* Zend Engine */
909 		php_info_print_box_start(0);
910 		if (!sapi_module.phpinfo_as_text) {
911 			php_info_print("<a href=\"https://www.zend.com/\"><img src=\"");
912 			php_info_print(ZEND_LOGO_DATA_URI "\" alt=\"Zend logo\" /></a>\n");
913 		}
914 		php_info_print("This program makes use of the Zend Scripting Language Engine:");
915 		php_info_print(!sapi_module.phpinfo_as_text?"<br />":"\n");
916 		if (sapi_module.phpinfo_as_text) {
917 			php_info_print(zend_version);
918 		} else {
919 			zend_html_puts(zend_version, strlen(zend_version));
920 		}
921 		php_info_print_box_end();
922 		zend_string_free(php_uname);
923 	}
924 
925 	zend_ini_sort_entries();
926 
927 	if (flag & PHP_INFO_CONFIGURATION) {
928 		php_info_print_hr();
929 		if (!sapi_module.phpinfo_as_text) {
930 			php_info_print("<h1>Configuration</h1>\n");
931 		} else {
932 			SECTION("Configuration");
933 		}
934 		if (!(flag & PHP_INFO_MODULES)) {
935 			SECTION("PHP Core");
936 			display_ini_entries(NULL);
937 		}
938 	}
939 
940 	if (flag & PHP_INFO_MODULES) {
941 		HashTable sorted_registry;
942 		zend_module_entry *module;
943 
944 		zend_hash_init(&sorted_registry, zend_hash_num_elements(&module_registry), NULL, NULL, 1);
945 		zend_hash_copy(&sorted_registry, &module_registry, NULL);
946 		zend_hash_sort(&sorted_registry, module_name_cmp, 0);
947 
948 		ZEND_HASH_MAP_FOREACH_PTR(&sorted_registry, module) {
949 			if (module->info_func || module->version) {
950 				php_info_print_module(module);
951 			}
952 		} ZEND_HASH_FOREACH_END();
953 
954 		SECTION("Additional Modules");
955 		php_info_print_table_start();
956 		php_info_print_table_header(1, "Module Name");
957 		ZEND_HASH_MAP_FOREACH_PTR(&sorted_registry, module) {
958 			if (!module->info_func && !module->version) {
959 				php_info_print_module(module);
960 			}
961 		} ZEND_HASH_FOREACH_END();
962 		php_info_print_table_end();
963 
964 		zend_hash_destroy(&sorted_registry);
965 	}
966 
967 	if (flag & PHP_INFO_ENVIRONMENT) {
968 		SECTION("Environment");
969 		php_info_print_table_start();
970 		php_info_print_table_header(2, "Variable", "Value");
971 		tsrm_env_lock();
972 		for (env=environ; env!=NULL && *env !=NULL; env++) {
973 			tmp1 = estrdup(*env);
974 			if (!(tmp2=strchr(tmp1,'='))) { /* malformed entry? */
975 				efree(tmp1);
976 				continue;
977 			}
978 			*tmp2 = 0;
979 			tmp2++;
980 			php_info_print_table_row(2, tmp1, tmp2);
981 			efree(tmp1);
982 		}
983 		tsrm_env_unlock();
984 		php_info_print_table_end();
985 	}
986 
987 	if (flag & PHP_INFO_VARIABLES) {
988 		zval *data;
989 
990 		SECTION("PHP Variables");
991 
992 		php_info_print_table_start();
993 		php_info_print_table_header(2, "Variable", "Value");
994 		if ((data = zend_hash_str_find(&EG(symbol_table), "PHP_SELF", sizeof("PHP_SELF")-1)) != NULL && Z_TYPE_P(data) == IS_STRING) {
995 			php_info_print_table_row(2, "PHP_SELF", Z_STRVAL_P(data));
996 		}
997 		if ((data = zend_hash_str_find(&EG(symbol_table), "PHP_AUTH_TYPE", sizeof("PHP_AUTH_TYPE")-1)) != NULL && Z_TYPE_P(data) == IS_STRING) {
998 			php_info_print_table_row(2, "PHP_AUTH_TYPE", Z_STRVAL_P(data));
999 		}
1000 		if ((data = zend_hash_str_find(&EG(symbol_table), "PHP_AUTH_USER", sizeof("PHP_AUTH_USER")-1)) != NULL && Z_TYPE_P(data) == IS_STRING) {
1001 			php_info_print_table_row(2, "PHP_AUTH_USER", Z_STRVAL_P(data));
1002 		}
1003 		if ((data = zend_hash_str_find(&EG(symbol_table), "PHP_AUTH_PW", sizeof("PHP_AUTH_PW")-1)) != NULL && Z_TYPE_P(data) == IS_STRING) {
1004 			php_info_print_table_row(2, "PHP_AUTH_PW", Z_STRVAL_P(data));
1005 		}
1006 		php_print_gpcse_array(ZEND_STRL("_REQUEST"));
1007 		php_print_gpcse_array(ZEND_STRL("_GET"));
1008 		php_print_gpcse_array(ZEND_STRL("_POST"));
1009 		php_print_gpcse_array(ZEND_STRL("_FILES"));
1010 		php_print_gpcse_array(ZEND_STRL("_COOKIE"));
1011 		php_print_gpcse_array(ZEND_STRL("_SERVER"));
1012 		php_print_gpcse_array(ZEND_STRL("_ENV"));
1013 		php_info_print_table_end();
1014 	}
1015 
1016 
1017 	if (flag & PHP_INFO_CREDITS) {
1018 		php_info_print_hr();
1019 		php_print_credits(PHP_CREDITS_ALL & ~PHP_CREDITS_FULLPAGE);
1020 	}
1021 
1022 	if (flag & PHP_INFO_LICENSE) {
1023 		if (!sapi_module.phpinfo_as_text) {
1024 			SECTION("PHP License");
1025 			php_info_print_box_start(0);
1026 			php_info_print("<p>\n");
1027 			php_info_print("This program is free software; you can redistribute it and/or modify ");
1028 			php_info_print("it under the terms of the PHP License as published by the PHP Group ");
1029 			php_info_print("and included in the distribution in the file:  LICENSE\n");
1030 			php_info_print("</p>\n");
1031 			php_info_print("<p>");
1032 			php_info_print("This program is distributed in the hope that it will be useful, ");
1033 			php_info_print("but WITHOUT ANY WARRANTY; without even the implied warranty of ");
1034 			php_info_print("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
1035 			php_info_print("</p>\n");
1036 			php_info_print("<p>");
1037 			php_info_print("If you did not receive a copy of the PHP license, or have any questions about ");
1038 			php_info_print("PHP licensing, please contact license@php.net.\n");
1039 			php_info_print("</p>\n");
1040 			php_info_print_box_end();
1041 		} else {
1042 			php_info_print("\nPHP License\n");
1043 			php_info_print("This program is free software; you can redistribute it and/or modify\n");
1044 			php_info_print("it under the terms of the PHP License as published by the PHP Group\n");
1045 			php_info_print("and included in the distribution in the file:  LICENSE\n");
1046 			php_info_print("\n");
1047 			php_info_print("This program is distributed in the hope that it will be useful,\n");
1048 			php_info_print("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
1049 			php_info_print("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
1050 			php_info_print("\n");
1051 			php_info_print("If you did not receive a copy of the PHP license, or have any\n");
1052 			php_info_print("questions about PHP licensing, please contact license@php.net.\n");
1053 		}
1054 	}
1055 
1056 	if (!sapi_module.phpinfo_as_text) {
1057 		php_info_print("</div></body></html>");
1058 	}
1059 }
1060 /* }}} */
1061 
php_info_print_table_start(void)1062 PHPAPI ZEND_COLD void php_info_print_table_start(void) /* {{{ */
1063 {
1064 	if (!sapi_module.phpinfo_as_text) {
1065 		php_info_print("<table>\n");
1066 	} else {
1067 		php_info_print("\n");
1068 	}
1069 }
1070 /* }}} */
1071 
php_info_print_table_end(void)1072 PHPAPI ZEND_COLD void php_info_print_table_end(void) /* {{{ */
1073 {
1074 	if (!sapi_module.phpinfo_as_text) {
1075 		php_info_print("</table>\n");
1076 	}
1077 
1078 }
1079 /* }}} */
1080 
php_info_print_box_start(int flag)1081 PHPAPI ZEND_COLD void php_info_print_box_start(int flag) /* {{{ */
1082 {
1083 	php_info_print_table_start();
1084 	if (flag) {
1085 		if (!sapi_module.phpinfo_as_text) {
1086 			php_info_print("<tr class=\"h\"><td>\n");
1087 		}
1088 	} else {
1089 		if (!sapi_module.phpinfo_as_text) {
1090 			php_info_print("<tr class=\"v\"><td>\n");
1091 		} else {
1092 			php_info_print("\n");
1093 		}
1094 	}
1095 }
1096 /* }}} */
1097 
php_info_print_box_end(void)1098 PHPAPI ZEND_COLD void php_info_print_box_end(void) /* {{{ */
1099 {
1100 	if (!sapi_module.phpinfo_as_text) {
1101 		php_info_print("</td></tr>\n");
1102 	}
1103 	php_info_print_table_end();
1104 }
1105 /* }}} */
1106 
php_info_print_hr(void)1107 PHPAPI ZEND_COLD void php_info_print_hr(void) /* {{{ */
1108 {
1109 	if (!sapi_module.phpinfo_as_text) {
1110 		php_info_print("<hr />\n");
1111 	} else {
1112 		php_info_print("\n\n _______________________________________________________________________\n\n");
1113 	}
1114 }
1115 /* }}} */
1116 
php_info_print_table_colspan_header(int num_cols,const char * header)1117 PHPAPI ZEND_COLD void php_info_print_table_colspan_header(int num_cols, const char *header) /* {{{ */
1118 {
1119 	int spaces;
1120 
1121 	if (!sapi_module.phpinfo_as_text) {
1122 		php_info_printf("<tr class=\"h\"><th colspan=\"%d\">%s</th></tr>\n", num_cols, header );
1123 	} else {
1124 		spaces = (int)(74 - strlen(header));
1125 		php_info_printf("%*s%s%*s\n", (int)(spaces/2), " ", header, (int)(spaces/2), " ");
1126 	}
1127 }
1128 /* }}} */
1129 
1130 /* {{{ php_info_print_table_header */
php_info_print_table_header(int num_cols,...)1131 PHPAPI ZEND_COLD void php_info_print_table_header(int num_cols, ...)
1132 {
1133 	int i;
1134 	va_list row_elements;
1135 	char *row_element;
1136 
1137 	va_start(row_elements, num_cols);
1138 	if (!sapi_module.phpinfo_as_text) {
1139 		php_info_print("<tr class=\"h\">");
1140 	}
1141 	for (i=0; i<num_cols; i++) {
1142 		row_element = va_arg(row_elements, char *);
1143 		if (!row_element || !*row_element) {
1144 			row_element = " ";
1145 		}
1146 		if (!sapi_module.phpinfo_as_text) {
1147 			php_info_print("<th>");
1148 			php_info_print(row_element);
1149 			php_info_print("</th>");
1150 		} else {
1151 			php_info_print(row_element);
1152 			if (i < num_cols-1) {
1153 				php_info_print(" => ");
1154 			} else {
1155 				php_info_print("\n");
1156 			}
1157 		}
1158 	}
1159 	if (!sapi_module.phpinfo_as_text) {
1160 		php_info_print("</tr>\n");
1161 	}
1162 
1163 	va_end(row_elements);
1164 }
1165 /* }}} */
1166 
1167 /* {{{ php_info_print_table_row_internal */
php_info_print_table_row_internal(int num_cols,const char * value_class,va_list row_elements)1168 static ZEND_COLD void php_info_print_table_row_internal(int num_cols,
1169 		const char *value_class, va_list row_elements)
1170 {
1171 	int i;
1172 	char *row_element;
1173 
1174 	if (!sapi_module.phpinfo_as_text) {
1175 		php_info_print("<tr>");
1176 	}
1177 	for (i=0; i<num_cols; i++) {
1178 		if (!sapi_module.phpinfo_as_text) {
1179 			php_info_printf("<td class=\"%s\">",
1180 			   (i==0 ? "e" : value_class )
1181 			);
1182 		}
1183 		row_element = va_arg(row_elements, char *);
1184 		if (!row_element || !*row_element) {
1185 			if (!sapi_module.phpinfo_as_text) {
1186 				php_info_print( "<i>no value</i>" );
1187 			} else {
1188 				php_info_print( " " );
1189 			}
1190 		} else {
1191 			if (!sapi_module.phpinfo_as_text) {
1192 				php_info_print_html_esc(row_element, strlen(row_element));
1193 			} else {
1194 				php_info_print(row_element);
1195 				if (i < num_cols-1) {
1196 					php_info_print(" => ");
1197 				}
1198 			}
1199 		}
1200 		if (!sapi_module.phpinfo_as_text) {
1201 			php_info_print(" </td>");
1202 		} else if (i == (num_cols - 1)) {
1203 			php_info_print("\n");
1204 		}
1205 	}
1206 	if (!sapi_module.phpinfo_as_text) {
1207 		php_info_print("</tr>\n");
1208 	}
1209 }
1210 /* }}} */
1211 
1212 /* {{{ php_info_print_table_row */
php_info_print_table_row(int num_cols,...)1213 PHPAPI ZEND_COLD void php_info_print_table_row(int num_cols, ...)
1214 {
1215 	va_list row_elements;
1216 
1217 	va_start(row_elements, num_cols);
1218 	php_info_print_table_row_internal(num_cols, "v", row_elements);
1219 	va_end(row_elements);
1220 }
1221 /* }}} */
1222 
1223 /* {{{ php_info_print_table_row_ex */
php_info_print_table_row_ex(int num_cols,const char * value_class,...)1224 PHPAPI ZEND_COLD void php_info_print_table_row_ex(int num_cols, const char *value_class,
1225 		...)
1226 {
1227 	va_list row_elements;
1228 
1229 	va_start(row_elements, value_class);
1230 	php_info_print_table_row_internal(num_cols, value_class, row_elements);
1231 	va_end(row_elements);
1232 }
1233 /* }}} */
1234 
1235 /* {{{ Output a page of useful information about PHP and the current request */
PHP_FUNCTION(phpinfo)1236 PHP_FUNCTION(phpinfo)
1237 {
1238 	zend_long flag = PHP_INFO_ALL;
1239 
1240 	ZEND_PARSE_PARAMETERS_START(0, 1)
1241 		Z_PARAM_OPTIONAL
1242 		Z_PARAM_LONG(flag)
1243 	ZEND_PARSE_PARAMETERS_END();
1244 
1245 	/* Andale!  Andale!  Yee-Hah! */
1246 	php_output_start_default();
1247 	php_print_info((int)flag);
1248 	php_output_end();
1249 
1250 	RETURN_TRUE;
1251 }
1252 
1253 /* }}} */
1254 
1255 /* {{{ Return the current PHP version */
PHP_FUNCTION(phpversion)1256 PHP_FUNCTION(phpversion)
1257 {
1258 	char *ext_name = NULL;
1259 	size_t ext_name_len = 0;
1260 
1261 	ZEND_PARSE_PARAMETERS_START(0, 1)
1262 		Z_PARAM_OPTIONAL
1263 		Z_PARAM_STRING_OR_NULL(ext_name, ext_name_len)
1264 	ZEND_PARSE_PARAMETERS_END();
1265 
1266 	if (!ext_name) {
1267 		RETURN_STRING(PHP_VERSION);
1268 	} else {
1269 		const char *version;
1270 		version = zend_get_module_version(ext_name);
1271 		if (version == NULL) {
1272 			RETURN_FALSE;
1273 		}
1274 		RETURN_STRING(version);
1275 	}
1276 }
1277 /* }}} */
1278 
1279 /* {{{ Prints the list of people who've contributed to the PHP project */
PHP_FUNCTION(phpcredits)1280 PHP_FUNCTION(phpcredits)
1281 {
1282 	zend_long flag = PHP_CREDITS_ALL;
1283 
1284 	ZEND_PARSE_PARAMETERS_START(0, 1)
1285 		Z_PARAM_OPTIONAL
1286 		Z_PARAM_LONG(flag)
1287 	ZEND_PARSE_PARAMETERS_END();
1288 
1289 	php_print_credits((int)flag);
1290 	RETURN_TRUE;
1291 }
1292 /* }}} */
1293 
1294 /* {{{ Return the current SAPI module name */
PHP_FUNCTION(php_sapi_name)1295 PHP_FUNCTION(php_sapi_name)
1296 {
1297 	ZEND_PARSE_PARAMETERS_NONE();
1298 
1299 	if (sapi_module.name) {
1300 		RETURN_STRING(sapi_module.name);
1301 	} else {
1302 		RETURN_FALSE;
1303 	}
1304 }
1305 
1306 /* }}} */
1307 
1308 /* {{{ Return information about the system PHP was built on */
PHP_FUNCTION(php_uname)1309 PHP_FUNCTION(php_uname)
1310 {
1311 	char *mode_str = "a";
1312 	size_t modelen = sizeof("a")-1;
1313 
1314 	ZEND_PARSE_PARAMETERS_START(0, 1)
1315 		Z_PARAM_OPTIONAL
1316 		Z_PARAM_STRING(mode_str, modelen)
1317 	ZEND_PARSE_PARAMETERS_END();
1318 
1319 	if (modelen != 1) {
1320 		zend_argument_value_error(1, "must be a single character");
1321 		RETURN_THROWS();
1322 	}
1323 
1324 	char mode = *mode_str;
1325 	if (!php_is_valid_uname_mode(mode)) {
1326 		zend_argument_value_error(1, "must be one of \"a\", \"m\", \"n\", \"r\", \"s\", or \"v\"");
1327 		RETURN_THROWS();
1328 	}
1329 
1330 	RETURN_STR(php_get_uname(mode));
1331 }
1332 
1333 /* }}} */
1334 
1335 /* {{{ Return comma-separated string of .ini files parsed from the additional ini dir */
PHP_FUNCTION(php_ini_scanned_files)1336 PHP_FUNCTION(php_ini_scanned_files)
1337 {
1338 	ZEND_PARSE_PARAMETERS_NONE();
1339 
1340 	if (php_ini_scanned_files) {
1341 		RETURN_STRING(php_ini_scanned_files);
1342 	} else {
1343 		RETURN_FALSE;
1344 	}
1345 }
1346 /* }}} */
1347 
1348 /* {{{ Return the actual loaded ini filename */
PHP_FUNCTION(php_ini_loaded_file)1349 PHP_FUNCTION(php_ini_loaded_file)
1350 {
1351 	ZEND_PARSE_PARAMETERS_NONE();
1352 
1353 	if (php_ini_opened_path) {
1354 		RETURN_STRING(php_ini_opened_path);
1355 	} else {
1356 		RETURN_FALSE;
1357 	}
1358 }
1359 /* }}} */
1360