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(new_str->val, new_str->len);
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(key->val, key->len);
119                    } else {
120                        php_info_print(key->val);
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(url_name->val, url_name->len);
146            php_info_printf("<h2><a name=\"module_%s\">%s</a></h2>\n", url_name->val, 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(string_key->val, string_key->len);
218                } else {
219                    php_info_print(string_key->val);
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;
295    SYSTEM_INFO si;
296    PGNSI pGNSI;
297    PGPI pGPI;
298    BOOL bOsVersionInfoEx;
299    DWORD dwType;
300    char *major = NULL, *sub = NULL, *retval;
301
302    ZeroMemory(&si, sizeof(SYSTEM_INFO));
303    ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
304    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
305
306    if (!(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi))) {
307        return NULL;
308    }
309
310    pGNSI = (PGNSI) GetProcAddress(GetModuleHandle("kernel32.dll"), "GetNativeSystemInfo");
311    if(NULL != pGNSI) {
312        pGNSI(&si);
313    } else {
314        GetSystemInfo(&si);
315    }
316
317    if (VER_PLATFORM_WIN32_NT==osvi.dwPlatformId && osvi.dwMajorVersion >= 6 ) {
318        if (osvi.dwMajorVersion == 6) {
319            if( osvi.dwMinorVersion == 0 ) {
320                if( osvi.wProductType == VER_NT_WORKSTATION ) {
321                    major = "Windows Vista";
322                } else {
323                    major = "Windows Server 2008";
324                }
325            } else if ( osvi.dwMinorVersion == 1 ) {
326                if( osvi.wProductType == VER_NT_WORKSTATION )  {
327                    major = "Windows 7";
328                } else {
329                    major = "Windows Server 2008 R2";
330                }
331            } else if ( osvi.dwMinorVersion == 2 ) {
332                /* could be Windows 8/Windows Server 2012, could be Windows 8.1/Windows Server 2012 R2 */
333                OSVERSIONINFOEX osvi81;
334                DWORDLONG dwlConditionMask = 0;
335                int op = VER_GREATER_EQUAL;
336
337                ZeroMemory(&osvi81, sizeof(OSVERSIONINFOEX));
338                osvi81.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
339                osvi81.dwMajorVersion = 6;
340                osvi81.dwMinorVersion = 3;
341                osvi81.wServicePackMajor = 0;
342
343                VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, op);
344                VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, op);
345                VER_SET_CONDITION(dwlConditionMask, VER_SERVICEPACKMAJOR, op);
346
347                if (VerifyVersionInfo(&osvi81,
348                    VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR,
349                    dwlConditionMask)) {
350                    osvi.dwMinorVersion = 3; /* Windows 8.1/Windows Server 2012 R2 */
351                    if( osvi.wProductType == VER_NT_WORKSTATION )  {
352                        major = "Windows 8.1";
353                    } else {
354                        major = "Windows Server 2012 R2";
355                    }
356                } else {
357                    if( osvi.wProductType == VER_NT_WORKSTATION )  {
358                        major = "Windows 8";
359                    } else {
360                        major = "Windows Server 2012";
361                    }
362                }
363            } else {
364                major = "Unknown Windows version";
365            }
366
367            pGPI = (PGPI) GetProcAddress(GetModuleHandle("kernel32.dll"), "GetProductInfo");
368            pGPI(6, 0, 0, 0, &dwType);
369
370            switch (dwType) {
371                case PRODUCT_ULTIMATE:
372                    sub = "Ultimate Edition";
373                    break;
374                case PRODUCT_HOME_PREMIUM:
375                    sub = "Home Premium Edition";
376                    break;
377                case PRODUCT_HOME_BASIC:
378                    sub = "Home Basic Edition";
379                    break;
380                case PRODUCT_ENTERPRISE:
381                    sub = "Enterprise Edition";
382                    break;
383                case PRODUCT_BUSINESS:
384                    sub = "Business Edition";
385                    break;
386                case PRODUCT_STARTER:
387                    sub = "Starter Edition";
388                    break;
389                case PRODUCT_CLUSTER_SERVER:
390                    sub = "Cluster Server Edition";
391                    break;
392                case PRODUCT_DATACENTER_SERVER:
393                    sub = "Datacenter Edition";
394                    break;
395                case PRODUCT_DATACENTER_SERVER_CORE:
396                    sub = "Datacenter Edition (core installation)";
397                    break;
398                case PRODUCT_ENTERPRISE_SERVER:
399                    sub = "Enterprise Edition";
400                    break;
401                case PRODUCT_ENTERPRISE_SERVER_CORE:
402                    sub = "Enterprise Edition (core installation)";
403                    break;
404                case PRODUCT_ENTERPRISE_SERVER_IA64:
405                    sub = "Enterprise Edition for Itanium-based Systems";
406                    break;
407                case PRODUCT_SMALLBUSINESS_SERVER:
408                    sub = "Small Business Server";
409                    break;
410                case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
411                    sub = "Small Business Server Premium Edition";
412                    break;
413                case PRODUCT_STANDARD_SERVER:
414                    sub = "Standard Edition";
415                    break;
416                case PRODUCT_STANDARD_SERVER_CORE:
417                    sub = "Standard Edition (core installation)";
418                    break;
419                case PRODUCT_WEB_SERVER:
420                    sub = "Web Server Edition";
421                    break;
422            }
423        }
424    } else {
425        return NULL;
426    }
427
428    spprintf(&retval, 0, "%s%s%s%s%s", major, sub?" ":"", sub?sub:"", osvi.szCSDVersion[0] != '\0'?" ":"", osvi.szCSDVersion);
429    return retval;
430}
431/* }}}  */
432
433/* {{{  */
434void php_get_windows_cpu(char *buf, int bufsize)
435{
436    SYSTEM_INFO SysInfo;
437    GetSystemInfo(&SysInfo);
438    switch (SysInfo.wProcessorArchitecture) {
439        case PROCESSOR_ARCHITECTURE_INTEL :
440            snprintf(buf, bufsize, "i%d", SysInfo.dwProcessorType);
441            break;
442        case PROCESSOR_ARCHITECTURE_MIPS :
443            snprintf(buf, bufsize, "MIPS R%d000", SysInfo.wProcessorLevel);
444            break;
445        case PROCESSOR_ARCHITECTURE_ALPHA :
446            snprintf(buf, bufsize, "Alpha %d", SysInfo.wProcessorLevel);
447            break;
448        case PROCESSOR_ARCHITECTURE_PPC :
449            snprintf(buf, bufsize, "PPC 6%02d", SysInfo.wProcessorLevel);
450            break;
451        case PROCESSOR_ARCHITECTURE_IA64 :
452            snprintf(buf, bufsize,  "IA64");
453            break;
454#if defined(PROCESSOR_ARCHITECTURE_IA32_ON_WIN64)
455        case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 :
456            snprintf(buf, bufsize, "IA32");
457            break;
458#endif
459#if defined(PROCESSOR_ARCHITECTURE_AMD64)
460        case PROCESSOR_ARCHITECTURE_AMD64 :
461            snprintf(buf, bufsize, "AMD64");
462            break;
463#endif
464        case PROCESSOR_ARCHITECTURE_UNKNOWN :
465        default:
466            snprintf(buf, bufsize, "Unknown");
467            break;
468    }
469}
470/* }}}  */
471#endif
472
473/* {{{ php_get_uname
474 */
475PHPAPI zend_string *php_get_uname(char mode)
476{
477    char *php_uname;
478    char tmp_uname[256];
479#ifdef PHP_WIN32
480    DWORD dwBuild=0;
481    DWORD dwVersion = GetVersion();
482    DWORD dwWindowsMajorVersion =  (DWORD)(LOBYTE(LOWORD(dwVersion)));
483    DWORD dwWindowsMinorVersion =  (DWORD)(HIBYTE(LOWORD(dwVersion)));
484    DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
485    char ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
486
487    GetComputerName(ComputerName, &dwSize);
488
489    if (mode == 's') {
490        php_uname = "Windows NT";
491    } else if (mode == 'r') {
492        snprintf(tmp_uname, sizeof(tmp_uname), "%d.%d", dwWindowsMajorVersion, dwWindowsMinorVersion);
493        php_uname = tmp_uname;
494    } else if (mode == 'n') {
495        php_uname = ComputerName;
496    } else if (mode == 'v') {
497        char *winver = php_get_windows_name();
498        dwBuild = (DWORD)(HIWORD(dwVersion));
499        if(winver == NULL) {
500            snprintf(tmp_uname, sizeof(tmp_uname), "build %d", dwBuild);
501        } else {
502            snprintf(tmp_uname, sizeof(tmp_uname), "build %d (%s)", dwBuild, winver);
503        }
504        php_uname = tmp_uname;
505        if(winver) {
506            efree(winver);
507        }
508    } else if (mode == 'm') {
509        php_get_windows_cpu(tmp_uname, sizeof(tmp_uname));
510        php_uname = tmp_uname;
511    } else { /* assume mode == 'a' */
512        char *winver = php_get_windows_name();
513        char wincpu[20];
514
515        ZEND_ASSERT(winver != NULL);
516
517        php_get_windows_cpu(wincpu, sizeof(wincpu));
518        dwBuild = (DWORD)(HIWORD(dwVersion));
519
520        /* Windows "version" 6.2 could be Windows 8/Windows Server 2012, but also Windows 8.1/Windows Server 2012 R2 */
521        if (dwWindowsMajorVersion == 6 && dwWindowsMinorVersion == 2) {
522            if (strncmp(winver, "Windows 8.1", 11) == 0 || strncmp(winver, "Windows Server 2012 R2", 22) == 0) {
523                dwWindowsMinorVersion = 3;
524            }
525        }
526
527        snprintf(tmp_uname, sizeof(tmp_uname), "%s %s %d.%d build %d (%s) %s",
528                 "Windows NT", ComputerName,
529                 dwWindowsMajorVersion, dwWindowsMinorVersion, dwBuild, winver?winver:"unknown", wincpu);
530        if(winver) {
531            efree(winver);
532        }
533        php_uname = tmp_uname;
534    }
535#else
536#ifdef HAVE_SYS_UTSNAME_H
537    struct utsname buf;
538    if (uname((struct utsname *)&buf) == -1) {
539        php_uname = PHP_UNAME;
540    } else {
541#ifdef NETWARE
542        if (mode == 's') {
543            php_uname = buf.sysname;
544        } else if (mode == 'r') {
545            snprintf(tmp_uname, sizeof(tmp_uname), "%d.%d.%d",
546                     buf.netware_major, buf.netware_minor, buf.netware_revision);
547            php_uname = tmp_uname;
548        } else if (mode == 'n') {
549            php_uname = buf.servername;
550        } else if (mode == 'v') {
551            snprintf(tmp_uname, sizeof(tmp_uname), "libc-%d.%d.%d #%d",
552                     buf.libmajor, buf.libminor, buf.librevision, buf.libthreshold);
553            php_uname = tmp_uname;
554        } else if (mode == 'm') {
555            php_uname = buf.machine;
556        } else { /* assume mode == 'a' */
557            snprintf(tmp_uname, sizeof(tmp_uname), "%s %s %d.%d.%d libc-%d.%d.%d #%d %s",
558                     buf.sysname, buf.servername,
559                     buf.netware_major, buf.netware_minor, buf.netware_revision,
560                     buf.libmajor, buf.libminor, buf.librevision, buf.libthreshold,
561                     buf.machine);
562            php_uname = tmp_uname;
563        }
564#else
565        if (mode == 's') {
566            php_uname = buf.sysname;
567        } else if (mode == 'r') {
568            php_uname = buf.release;
569        } else if (mode == 'n') {
570            php_uname = buf.nodename;
571        } else if (mode == 'v') {
572            php_uname = buf.version;
573        } else if (mode == 'm') {
574            php_uname = buf.machine;
575        } else { /* assume mode == 'a' */
576            snprintf(tmp_uname, sizeof(tmp_uname), "%s %s %s %s %s",
577                     buf.sysname, buf.nodename, buf.release, buf.version,
578                     buf.machine);
579            php_uname = tmp_uname;
580        }
581#endif /* NETWARE */
582    }
583#else
584    php_uname = PHP_UNAME;
585#endif
586#endif
587    return zend_string_init(php_uname, strlen(php_uname), 0);
588}
589/* }}} */
590
591/* {{{ php_print_info_htmlhead
592 */
593PHPAPI void php_print_info_htmlhead(void)
594{
595    php_info_print("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"DTD/xhtml1-transitional.dtd\">\n");
596    php_info_print("<html xmlns=\"http://www.w3.org/1999/xhtml\">");
597    php_info_print("<head>\n");
598    php_info_print_style();
599    php_info_print("<title>phpinfo()</title>");
600    php_info_print("<meta name=\"ROBOTS\" content=\"NOINDEX,NOFOLLOW,NOARCHIVE\" />");
601    php_info_print("</head>\n");
602    php_info_print("<body><div class=\"center\">\n");
603}
604/* }}} */
605
606/* {{{ module_name_cmp */
607static int module_name_cmp(const void *a, const void *b)
608{
609    Bucket *f = (Bucket *) a;
610    Bucket *s = (Bucket *) b;
611
612    return strcasecmp(((zend_module_entry *)Z_PTR(f->val))->name,
613                  ((zend_module_entry *)Z_PTR(s->val))->name);
614}
615/* }}} */
616
617/* {{{ php_print_info
618 */
619PHPAPI void php_print_info(int flag)
620{
621    char **env, *tmp1, *tmp2;
622    zend_string *php_uname;
623
624    if (!sapi_module.phpinfo_as_text) {
625        php_print_info_htmlhead();
626    } else {
627        php_info_print("phpinfo()\n");
628    }
629
630    if (flag & PHP_INFO_GENERAL) {
631        char *zend_version = get_zend_version();
632        char temp_api[10];
633
634        php_uname = php_get_uname('a');
635
636        if (!sapi_module.phpinfo_as_text) {
637            php_info_print_box_start(1);
638        }
639
640        if (!sapi_module.phpinfo_as_text) {
641            time_t the_time;
642            struct tm *ta, tmbuf;
643
644            the_time = time(NULL);
645            ta = php_localtime_r(&the_time, &tmbuf);
646
647            php_info_print("<a href=\"http://www.php.net/\"><img border=\"0\" src=\"");
648            if (ta && (ta->tm_mon==3) && (ta->tm_mday==1)) {
649                php_info_print(PHP_EGG_LOGO_DATA_URI "\" alt=\"PHP logo\" /></a>");
650            } else {
651                php_info_print(PHP_LOGO_DATA_URI "\" alt=\"PHP logo\" /></a>");
652            }
653        }
654
655        if (!sapi_module.phpinfo_as_text) {
656            php_info_printf("<h1 class=\"p\">PHP Version %s</h1>\n", PHP_VERSION);
657        } else {
658            php_info_print_table_row(2, "PHP Version", PHP_VERSION);
659        }
660        php_info_print_box_end();
661        php_info_print_table_start();
662        php_info_print_table_row(2, "System", php_uname->val);
663        php_info_print_table_row(2, "Build Date", __DATE__ " " __TIME__);
664#ifdef COMPILER
665        php_info_print_table_row(2, "Compiler", COMPILER);
666#endif
667#ifdef ARCHITECTURE
668        php_info_print_table_row(2, "Architecture", ARCHITECTURE);
669#endif
670#ifdef CONFIGURE_COMMAND
671        php_info_print_table_row(2, "Configure Command", CONFIGURE_COMMAND );
672#endif
673
674        if (sapi_module.pretty_name) {
675            php_info_print_table_row(2, "Server API", sapi_module.pretty_name );
676        }
677
678#ifdef VIRTUAL_DIR
679        php_info_print_table_row(2, "Virtual Directory Support", "enabled" );
680#else
681        php_info_print_table_row(2, "Virtual Directory Support", "disabled" );
682#endif
683
684        php_info_print_table_row(2, "Configuration File (php.ini) Path", PHP_CONFIG_FILE_PATH);
685        php_info_print_table_row(2, "Loaded Configuration File", php_ini_opened_path ? php_ini_opened_path : "(none)");
686        php_info_print_table_row(2, "Scan this dir for additional .ini files", php_ini_scanned_path ? php_ini_scanned_path : "(none)");
687        php_info_print_table_row(2, "Additional .ini files parsed", php_ini_scanned_files ? php_ini_scanned_files : "(none)");
688
689        snprintf(temp_api, sizeof(temp_api), "%d", PHP_API_VERSION);
690        php_info_print_table_row(2, "PHP API", temp_api);
691
692        snprintf(temp_api, sizeof(temp_api), "%d", ZEND_MODULE_API_NO);
693        php_info_print_table_row(2, "PHP Extension", temp_api);
694
695        snprintf(temp_api, sizeof(temp_api), "%d", ZEND_EXTENSION_API_NO);
696        php_info_print_table_row(2, "Zend Extension", temp_api);
697
698        php_info_print_table_row(2, "Zend Extension Build", ZEND_EXTENSION_BUILD_ID);
699        php_info_print_table_row(2, "PHP Extension Build", ZEND_MODULE_BUILD_ID);
700
701#if ZEND_DEBUG
702        php_info_print_table_row(2, "Debug Build", "yes" );
703#else
704        php_info_print_table_row(2, "Debug Build", "no" );
705#endif
706
707#ifdef ZTS
708        php_info_print_table_row(2, "Thread Safety", "enabled" );
709#else
710        php_info_print_table_row(2, "Thread Safety", "disabled" );
711#endif
712
713#ifdef ZEND_SIGNALS
714        php_info_print_table_row(2, "Zend Signal Handling", "enabled" );
715#else
716        php_info_print_table_row(2, "Zend Signal Handling", "disabled" );
717#endif
718
719        php_info_print_table_row(2, "Zend Memory Manager", is_zend_mm() ? "enabled" : "disabled" );
720
721        {
722            const zend_multibyte_functions *functions = zend_multibyte_get_functions();
723            char *descr;
724            if (functions) {
725                spprintf(&descr, 0, "provided by %s", functions->provider_name);
726            } else {
727                descr = estrdup("disabled");
728            }
729            php_info_print_table_row(2, "Zend Multibyte Support", descr);
730            efree(descr);
731        }
732
733#if HAVE_IPV6
734        php_info_print_table_row(2, "IPv6 Support", "enabled" );
735#else
736        php_info_print_table_row(2, "IPv6 Support", "disabled" );
737#endif
738
739#if HAVE_DTRACE
740        php_info_print_table_row(2, "DTrace Support", "enabled" );
741#else
742        php_info_print_table_row(2, "DTrace Support", "disabled" );
743#endif
744
745        php_info_print_stream_hash("PHP Streams",  php_stream_get_url_stream_wrappers_hash());
746        php_info_print_stream_hash("Stream Socket Transports", php_stream_xport_get_hash());
747        php_info_print_stream_hash("Stream Filters", php_get_stream_filters_hash());
748
749        php_info_print_table_end();
750
751        /* Zend Engine */
752        php_info_print_box_start(0);
753        if (!sapi_module.phpinfo_as_text) {
754            php_info_print("<a href=\"http://www.zend.com/\"><img border=\"0\" src=\"");
755            php_info_print(ZEND_LOGO_DATA_URI "\" alt=\"Zend logo\" /></a>\n");
756        }
757        php_info_print("This program makes use of the Zend Scripting Language Engine:");
758        php_info_print(!sapi_module.phpinfo_as_text?"<br />":"\n");
759        if (sapi_module.phpinfo_as_text) {
760            php_info_print(zend_version);
761        } else {
762            zend_html_puts(zend_version, strlen(zend_version));
763        }
764        php_info_print_box_end();
765        zend_string_free(php_uname);
766    }
767
768    zend_ini_sort_entries();
769
770    if (flag & PHP_INFO_CONFIGURATION) {
771        php_info_print_hr();
772        if (!sapi_module.phpinfo_as_text) {
773            php_info_print("<h1>Configuration</h1>\n");
774        } else {
775            SECTION("Configuration");
776        }
777        if (!(flag & PHP_INFO_MODULES)) {
778            SECTION("PHP Core");
779            display_ini_entries(NULL);
780        }
781    }
782
783    if (flag & PHP_INFO_MODULES) {
784        HashTable sorted_registry;
785
786        zend_hash_init(&sorted_registry, zend_hash_num_elements(&module_registry), NULL, NULL, 1);
787        zend_hash_copy(&sorted_registry, &module_registry, NULL);
788        zend_hash_sort(&sorted_registry, module_name_cmp, 0);
789
790        zend_hash_apply(&sorted_registry, _display_module_info_func);
791
792        SECTION("Additional Modules");
793        php_info_print_table_start();
794        php_info_print_table_header(1, "Module Name");
795        zend_hash_apply(&sorted_registry, _display_module_info_def);
796        php_info_print_table_end();
797
798        zend_hash_destroy(&sorted_registry);
799    }
800
801    if (flag & PHP_INFO_ENVIRONMENT) {
802        SECTION("Environment");
803        php_info_print_table_start();
804        php_info_print_table_header(2, "Variable", "Value");
805        for (env=environ; env!=NULL && *env !=NULL; env++) {
806            tmp1 = estrdup(*env);
807            if (!(tmp2=strchr(tmp1,'='))) { /* malformed entry? */
808                efree(tmp1);
809                continue;
810            }
811            *tmp2 = 0;
812            tmp2++;
813            php_info_print_table_row(2, tmp1, tmp2);
814            efree(tmp1);
815        }
816        php_info_print_table_end();
817    }
818
819    if (flag & PHP_INFO_VARIABLES) {
820        zval *data;
821
822        SECTION("PHP Variables");
823
824        php_info_print_table_start();
825        php_info_print_table_header(2, "Variable", "Value");
826        if ((data = zend_hash_str_find(&EG(symbol_table), "PHP_SELF", sizeof("PHP_SELF")-1)) != NULL && Z_TYPE_P(data) == IS_STRING) {
827            php_info_print_table_row(2, "PHP_SELF", Z_STRVAL_P(data));
828        }
829        if ((data = zend_hash_str_find(&EG(symbol_table), "PHP_AUTH_TYPE", sizeof("PHP_AUTH_TYPE")-1)) != NULL && Z_TYPE_P(data) == IS_STRING) {
830            php_info_print_table_row(2, "PHP_AUTH_TYPE", Z_STRVAL_P(data));
831        }
832        if ((data = zend_hash_str_find(&EG(symbol_table), "PHP_AUTH_USER", sizeof("PHP_AUTH_USER")-1)) != NULL && Z_TYPE_P(data) == IS_STRING) {
833            php_info_print_table_row(2, "PHP_AUTH_USER", Z_STRVAL_P(data));
834        }
835        if ((data = zend_hash_str_find(&EG(symbol_table), "PHP_AUTH_PW", sizeof("PHP_AUTH_PW")-1)) != NULL && Z_TYPE_P(data) == IS_STRING) {
836            php_info_print_table_row(2, "PHP_AUTH_PW", Z_STRVAL_P(data));
837        }
838        php_print_gpcse_array(ZEND_STRL("_REQUEST"));
839        php_print_gpcse_array(ZEND_STRL("_GET"));
840        php_print_gpcse_array(ZEND_STRL("_POST"));
841        php_print_gpcse_array(ZEND_STRL("_FILES"));
842        php_print_gpcse_array(ZEND_STRL("_COOKIE"));
843        php_print_gpcse_array(ZEND_STRL("_SERVER"));
844        php_print_gpcse_array(ZEND_STRL("_ENV"));
845        php_info_print_table_end();
846    }
847
848
849    if ((flag & PHP_INFO_CREDITS) && !sapi_module.phpinfo_as_text) {
850        php_info_print_hr();
851        php_print_credits(PHP_CREDITS_ALL & ~PHP_CREDITS_FULLPAGE);
852    }
853
854    if (flag & PHP_INFO_LICENSE) {
855        if (!sapi_module.phpinfo_as_text) {
856            SECTION("PHP License");
857            php_info_print_box_start(0);
858            php_info_print("<p>\n");
859            php_info_print("This program is free software; you can redistribute it and/or modify ");
860            php_info_print("it under the terms of the PHP License as published by the PHP Group ");
861            php_info_print("and included in the distribution in the file:  LICENSE\n");
862            php_info_print("</p>\n");
863            php_info_print("<p>");
864            php_info_print("This program is distributed in the hope that it will be useful, ");
865            php_info_print("but WITHOUT ANY WARRANTY; without even the implied warranty of ");
866            php_info_print("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
867            php_info_print("</p>\n");
868            php_info_print("<p>");
869            php_info_print("If you did not receive a copy of the PHP license, or have any questions about ");
870            php_info_print("PHP licensing, please contact license@php.net.\n");
871            php_info_print("</p>\n");
872            php_info_print_box_end();
873        } else {
874            php_info_print("\nPHP License\n");
875            php_info_print("This program is free software; you can redistribute it and/or modify\n");
876            php_info_print("it under the terms of the PHP License as published by the PHP Group\n");
877            php_info_print("and included in the distribution in the file:  LICENSE\n");
878            php_info_print("\n");
879            php_info_print("This program is distributed in the hope that it will be useful,\n");
880            php_info_print("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
881            php_info_print("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
882            php_info_print("\n");
883            php_info_print("If you did not receive a copy of the PHP license, or have any\n");
884            php_info_print("questions about PHP licensing, please contact license@php.net.\n");
885        }
886    }
887
888    if (!sapi_module.phpinfo_as_text) {
889        php_info_print("</div></body></html>");
890    }
891}
892/* }}} */
893
894PHPAPI void php_info_print_table_start(void) /* {{{ */
895{
896    if (!sapi_module.phpinfo_as_text) {
897        php_info_print("<table>\n");
898    } else {
899        php_info_print("\n");
900    }
901}
902/* }}} */
903
904PHPAPI void php_info_print_table_end(void) /* {{{ */
905{
906    if (!sapi_module.phpinfo_as_text) {
907        php_info_print("</table>\n");
908    }
909
910}
911/* }}} */
912
913PHPAPI void php_info_print_box_start(int flag) /* {{{ */
914{
915    php_info_print_table_start();
916    if (flag) {
917        if (!sapi_module.phpinfo_as_text) {
918            php_info_print("<tr class=\"h\"><td>\n");
919        }
920    } else {
921        if (!sapi_module.phpinfo_as_text) {
922            php_info_print("<tr class=\"v\"><td>\n");
923        } else {
924            php_info_print("\n");
925        }
926    }
927}
928/* }}} */
929
930PHPAPI void php_info_print_box_end(void) /* {{{ */
931{
932    if (!sapi_module.phpinfo_as_text) {
933        php_info_print("</td></tr>\n");
934    }
935    php_info_print_table_end();
936}
937/* }}} */
938
939PHPAPI void php_info_print_hr(void) /* {{{ */
940{
941    if (!sapi_module.phpinfo_as_text) {
942        php_info_print("<hr />\n");
943    } else {
944        php_info_print("\n\n _______________________________________________________________________\n\n");
945    }
946}
947/* }}} */
948
949PHPAPI void php_info_print_table_colspan_header(int num_cols, char *header) /* {{{ */
950{
951    int spaces;
952
953    if (!sapi_module.phpinfo_as_text) {
954        php_info_printf("<tr class=\"h\"><th colspan=\"%d\">%s</th></tr>\n", num_cols, header );
955    } else {
956        spaces = (int)(74 - strlen(header));
957        php_info_printf("%*s%s%*s\n", (int)(spaces/2), " ", header, (int)(spaces/2), " ");
958    }
959}
960/* }}} */
961
962/* {{{ php_info_print_table_header
963 */
964PHPAPI void php_info_print_table_header(int num_cols, ...)
965{
966    int i;
967    va_list row_elements;
968    char *row_element;
969
970    va_start(row_elements, num_cols);
971    if (!sapi_module.phpinfo_as_text) {
972        php_info_print("<tr class=\"h\">");
973    }
974    for (i=0; i<num_cols; i++) {
975        row_element = va_arg(row_elements, char *);
976        if (!row_element || !*row_element) {
977            row_element = " ";
978        }
979        if (!sapi_module.phpinfo_as_text) {
980            php_info_print("<th>");
981            php_info_print(row_element);
982            php_info_print("</th>");
983        } else {
984            php_info_print(row_element);
985            if (i < num_cols-1) {
986                php_info_print(" => ");
987            } else {
988                php_info_print("\n");
989            }
990        }
991    }
992    if (!sapi_module.phpinfo_as_text) {
993        php_info_print("</tr>\n");
994    }
995
996    va_end(row_elements);
997}
998/* }}} */
999
1000/* {{{ php_info_print_table_row_internal
1001 */
1002static void php_info_print_table_row_internal(int num_cols,
1003        const char *value_class, va_list row_elements)
1004{
1005    int i;
1006    char *row_element;
1007
1008    if (!sapi_module.phpinfo_as_text) {
1009        php_info_print("<tr>");
1010    }
1011    for (i=0; i<num_cols; i++) {
1012        if (!sapi_module.phpinfo_as_text) {
1013            php_info_printf("<td class=\"%s\">",
1014               (i==0 ? "e" : value_class )
1015            );
1016        }
1017        row_element = va_arg(row_elements, char *);
1018        if (!row_element || !*row_element) {
1019            if (!sapi_module.phpinfo_as_text) {
1020                php_info_print( "<i>no value</i>" );
1021            } else {
1022                php_info_print( " " );
1023            }
1024        } else {
1025            if (!sapi_module.phpinfo_as_text) {
1026                php_info_print_html_esc(row_element, strlen(row_element));
1027            } else {
1028                php_info_print(row_element);
1029                if (i < num_cols-1) {
1030                    php_info_print(" => ");
1031                }
1032            }
1033        }
1034        if (!sapi_module.phpinfo_as_text) {
1035            php_info_print(" </td>");
1036        } else if (i == (num_cols - 1)) {
1037            php_info_print("\n");
1038        }
1039    }
1040    if (!sapi_module.phpinfo_as_text) {
1041        php_info_print("</tr>\n");
1042    }
1043}
1044/* }}} */
1045
1046/* {{{ php_info_print_table_row
1047 */
1048PHPAPI void php_info_print_table_row(int num_cols, ...)
1049{
1050    va_list row_elements;
1051
1052    va_start(row_elements, num_cols);
1053    php_info_print_table_row_internal(num_cols, "v", row_elements);
1054    va_end(row_elements);
1055}
1056/* }}} */
1057
1058/* {{{ php_info_print_table_row_ex
1059 */
1060PHPAPI void php_info_print_table_row_ex(int num_cols, const char *value_class,
1061        ...)
1062{
1063    va_list row_elements;
1064
1065    va_start(row_elements, value_class);
1066    php_info_print_table_row_internal(num_cols, value_class, row_elements);
1067    va_end(row_elements);
1068}
1069/* }}} */
1070
1071/* {{{ register_phpinfo_constants
1072 */
1073void register_phpinfo_constants(INIT_FUNC_ARGS)
1074{
1075    REGISTER_LONG_CONSTANT("INFO_GENERAL", PHP_INFO_GENERAL, CONST_PERSISTENT|CONST_CS);
1076    REGISTER_LONG_CONSTANT("INFO_CREDITS", PHP_INFO_CREDITS, CONST_PERSISTENT|CONST_CS);
1077    REGISTER_LONG_CONSTANT("INFO_CONFIGURATION", PHP_INFO_CONFIGURATION, CONST_PERSISTENT|CONST_CS);
1078    REGISTER_LONG_CONSTANT("INFO_MODULES", PHP_INFO_MODULES, CONST_PERSISTENT|CONST_CS);
1079    REGISTER_LONG_CONSTANT("INFO_ENVIRONMENT", PHP_INFO_ENVIRONMENT, CONST_PERSISTENT|CONST_CS);
1080    REGISTER_LONG_CONSTANT("INFO_VARIABLES", PHP_INFO_VARIABLES, CONST_PERSISTENT|CONST_CS);
1081    REGISTER_LONG_CONSTANT("INFO_LICENSE", PHP_INFO_LICENSE, CONST_PERSISTENT|CONST_CS);
1082    REGISTER_LONG_CONSTANT("INFO_ALL", PHP_INFO_ALL, CONST_PERSISTENT|CONST_CS);
1083    REGISTER_LONG_CONSTANT("CREDITS_GROUP", PHP_CREDITS_GROUP, CONST_PERSISTENT|CONST_CS);
1084    REGISTER_LONG_CONSTANT("CREDITS_GENERAL",   PHP_CREDITS_GENERAL, CONST_PERSISTENT|CONST_CS);
1085    REGISTER_LONG_CONSTANT("CREDITS_SAPI",  PHP_CREDITS_SAPI, CONST_PERSISTENT|CONST_CS);
1086    REGISTER_LONG_CONSTANT("CREDITS_MODULES",   PHP_CREDITS_MODULES, CONST_PERSISTENT|CONST_CS);
1087    REGISTER_LONG_CONSTANT("CREDITS_DOCS",  PHP_CREDITS_DOCS, CONST_PERSISTENT|CONST_CS);
1088    REGISTER_LONG_CONSTANT("CREDITS_FULLPAGE",  PHP_CREDITS_FULLPAGE, CONST_PERSISTENT|CONST_CS);
1089    REGISTER_LONG_CONSTANT("CREDITS_QA",    PHP_CREDITS_QA, CONST_PERSISTENT|CONST_CS);
1090    REGISTER_LONG_CONSTANT("CREDITS_ALL",   PHP_CREDITS_ALL, CONST_PERSISTENT|CONST_CS);
1091}
1092/* }}} */
1093
1094/* {{{ proto void phpinfo([int what])
1095   Output a page of useful information about PHP and the current request */
1096PHP_FUNCTION(phpinfo)
1097{
1098    zend_long flag = PHP_INFO_ALL;
1099
1100    if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &flag) == FAILURE) {
1101        return;
1102    }
1103
1104    /* Andale!  Andale!  Yee-Hah! */
1105    php_output_start_default();
1106    php_print_info((int)flag);
1107    php_output_end();
1108
1109    RETURN_TRUE;
1110}
1111
1112/* }}} */
1113
1114/* {{{ proto string phpversion([string extension])
1115   Return the current PHP version */
1116PHP_FUNCTION(phpversion)
1117{
1118    char *ext_name = NULL;
1119    size_t ext_name_len = 0;
1120
1121    if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &ext_name, &ext_name_len) == FAILURE) {
1122        return;
1123    }
1124
1125    if (!ext_name) {
1126        RETURN_STRING(PHP_VERSION);
1127    } else {
1128        const char *version;
1129        version = zend_get_module_version(ext_name);
1130        if (version == NULL) {
1131            RETURN_FALSE;
1132        }
1133        RETURN_STRING(version);
1134    }
1135}
1136/* }}} */
1137
1138/* {{{ proto void phpcredits([int flag])
1139   Prints the list of people who've contributed to the PHP project */
1140PHP_FUNCTION(phpcredits)
1141{
1142    zend_long flag = PHP_CREDITS_ALL;
1143
1144    if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &flag) == FAILURE) {
1145        return;
1146    }
1147
1148    php_print_credits((int)flag);
1149    RETURN_TRUE;
1150}
1151/* }}} */
1152
1153/* {{{ proto string php_sapi_name(void)
1154   Return the current SAPI module name */
1155PHP_FUNCTION(php_sapi_name)
1156{
1157    if (zend_parse_parameters_none() == FAILURE) {
1158        return;
1159    }
1160
1161    if (sapi_module.name) {
1162        RETURN_STRING(sapi_module.name);
1163    } else {
1164        RETURN_FALSE;
1165    }
1166}
1167
1168/* }}} */
1169
1170/* {{{ proto string php_uname(void)
1171   Return information about the system PHP was built on */
1172PHP_FUNCTION(php_uname)
1173{
1174    char *mode = "a";
1175    size_t modelen = sizeof("a")-1;
1176
1177    if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &mode, &modelen) == FAILURE) {
1178        return;
1179    }
1180    RETURN_STR(php_get_uname(*mode));
1181}
1182
1183/* }}} */
1184
1185/* {{{ proto string php_ini_scanned_files(void)
1186   Return comma-separated string of .ini files parsed from the additional ini dir */
1187PHP_FUNCTION(php_ini_scanned_files)
1188{
1189    if (zend_parse_parameters_none() == FAILURE) {
1190        return;
1191    }
1192
1193    if (strlen(PHP_CONFIG_FILE_SCAN_DIR) && php_ini_scanned_files) {
1194        RETURN_STRING(php_ini_scanned_files);
1195    } else {
1196        RETURN_FALSE;
1197    }
1198}
1199/* }}} */
1200
1201/* {{{ proto string php_ini_loaded_file(void)
1202   Return the actual loaded ini filename */
1203PHP_FUNCTION(php_ini_loaded_file)
1204{
1205    if (zend_parse_parameters_none() == FAILURE) {
1206        return;
1207    }
1208
1209    if (php_ini_opened_path) {
1210        RETURN_STRING(php_ini_opened_path);
1211    } else {
1212        RETURN_FALSE;
1213    }
1214}
1215/* }}} */
1216
1217/*
1218 * Local variables:
1219 * tab-width: 4
1220 * c-basic-offset: 4
1221 * End:
1222 * vim600: sw=4 ts=4 fdm=marker
1223 * vim<600: sw=4 ts=4
1224 */
1225