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