diff --git a/cgi_main.c b/cgi_main.c new file mode 100644 index 00000000000..4d4ab20a47a --- /dev/null +++ b/cgi_main.c @@ -0,0 +1,332 @@ +#include "php.h" +#include "php_globals.h" + +#include "SAPI.h" + +#include +#include "php.h" +#ifdef MSVC5 +#include "win32/time.h" +#include "win32/signal.h" +#include +#else +#include "build-defs.h" +#endif +#if HAVE_SYS_TIME_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_SIGNAL_H +#include +#endif +#if HAVE_SETLOCALE +#include +#endif +#include "zend.h" +#include "php_ini.h" +#include "php_globals.h" +#include "main.h" +#include "fopen-wrappers.h" +#include "ext/standard/php3_standard.h" +#include "snprintf.h" +#if WIN32|WINNT +#include +#include +#include "win32/syslog.h" +#include "win32/php_registry.h" +#else +#include +#endif + +#include "zend_compile.h" +#include "zend_execute.h" +#include "zend_highlight.h" +#include "zend_indent.h" + +#if USE_SAPI +#include "serverapi/sapi.h" +void *gLock; +#ifndef THREAD_SAFE +struct sapi_request_info *sapi_rqst; +#endif +#endif + +#if MSVC5 || !defined(HAVE_GETOPT) +#include "getopt.h" +#endif + +extern char *php3_ini_path; + +#define PHP_MODE_STANDARD 1 +#define PHP_MODE_HIGHLIGHT 2 +#define PHP_MODE_INDENT 3 + + + +static int zend_cgibin_ub_write(const char *str, uint str_length) +{ + return fwrite(str, 1, str_length, stdout); +} + + +sapi_functions_struct sapi_functions = { + zend_cgibin_ub_write +}; + + +int main(int argc, char *argv[]) +{ + int cgi = 0, c, i, len; + zend_file_handle file_handle; + char *s; +/* temporary locals */ + char *_cgi_filename=NULL; + int _cgi_started=0; + int behavior=PHP_MODE_STANDARD; +#if SUPPORT_INTERACTIVE + int interactive=0; +#endif +/* end of temporary locals */ +#ifdef ZTS + zend_compiler_globals *compiler_globals; + zend_executor_globals *executor_globals; + php_core_globals *core_globals; +#endif + + +#ifndef ZTS + if (setjmp(EG(bailout))!=0) { + return -1; + } +#endif + +#if WIN32|WINNT + _fmode = _O_BINARY; /*sets default for file streams to binary */ + setmode(_fileno(stdin), O_BINARY); /* make the stdio mode be binary */ + setmode(_fileno(stdout), O_BINARY); /* make the stdio mode be binary */ + setmode(_fileno(stderr), O_BINARY); /* make the stdio mode be binary */ +#endif + + + /* Make sure we detect we are a cgi - a bit redundancy here, + but the default case is that we have to check only the first one. */ + if (getenv("SERVER_SOFTWARE") + || getenv("SERVER_NAME") + || getenv("GATEWAY_INTERFACE") + || getenv("REQUEST_METHOD")) { + cgi = 1; + if (argc > 1) + request_info.php_argv0 = strdup(argv[1]); + else request_info.php_argv0 = NULL; +#if FORCE_CGI_REDIRECT + if (!getenv("REDIRECT_STATUS")) { + PUTS("Security Alert! PHP CGI cannot be accessed directly.\n\ +\n\ +

This PHP CGI binary was compiled with force-cgi-redirect enabled. This\n\ +means that a page will only be served up if the REDIRECT_STATUS CGI variable is\n\ +set. This variable is set, for example, by Apache's Action directive redirect.\n\ +

You may disable this restriction by recompiling the PHP binary with the\n\ +--disable-force-cgi-redirect switch. If you do this and you have your PHP CGI\n\ +binary accessible somewhere in your web tree, people will be able to circumvent\n\ +.htaccess security by loading files through the PHP parser. A good way around\n\ +this is to define doc_root in your php3.ini file to something other than your\n\ +top-level DOCUMENT_ROOT. This way you can separate the part of your web space\n\n\ +which uses PHP from the normal part using .htaccess security. If you do not have\n\ +any .htaccess restrictions anywhere on your site you can leave doc_root undefined.\n\ +\n"); + + /* remove that detailed explanation some time */ + + return FAILURE; + } +#endif /* FORCE_CGI_REDIRECT */ + } + + if (php3_module_startup()==FAILURE) { + return FAILURE; + } +#ifdef ZTS + compiler_globals = ts_resource(compiler_globals_id); + executor_globals = ts_resource(executor_globals_id); + core_globals = ts_resource(core_globals_id); +#endif + + CG(extended_info) = 0; + + if (!cgi) { /* never execute the arguments if you are a CGI */ + request_info.php_argv0 = NULL; + while ((c = getopt(argc, argv, "c:qvisnaeh?vf:")) != -1) { + switch (c) { + case 'f': + if (!_cgi_started){ + if (php3_request_startup(CLS_C ELS_CC PLS_CC)==FAILURE) { + php3_module_shutdown(); + return FAILURE; + } + } + _cgi_started=1; + _cgi_filename = estrdup(optarg); + /* break missing intentionally */ + case 'q': + php3_noheader(); + break; + case 'v': + if (!_cgi_started) { + if (php3_request_startup(CLS_C ELS_CC PLS_CC)==FAILURE) { + php3_module_shutdown(); + return FAILURE; + } + } + php3_printf("%s\n", PHP_VERSION); + exit(1); + break; + case 'i': + if (!_cgi_started) { + if (php3_request_startup(CLS_C ELS_CC PLS_CC)==FAILURE) { + php3_module_shutdown(); + return FAILURE; + } + } + _cgi_started=1; + php3_TreatHeaders(); + _php3_info(); + exit(1); + break; + case 's': + behavior=PHP_MODE_HIGHLIGHT; + break; + case 'n': + behavior=PHP_MODE_INDENT; + break; + case 'c': + php3_ini_path = strdup(optarg); /* intentional leak */ + break; + case 'a': +#if SUPPORT_INTERACTIVE + printf("Interactive mode enabled\n\n"); + interactive=1; +#else + printf("Interactive mode not supported!\n\n"); +#endif + break; + case 'e': + CG(extended_info) = 1; + break; + case 'h': + case '?': + php3_noheader(); + zend_output_startup(); + _php3_usage(argv[0]); + exit(1); + break; + default: + break; + } + } + } /* not cgi */ + +#if SUPPORT_INTERACTIVE + EG(interactive) = interactive; +#endif + + if (!_cgi_started) { + if (php3_request_startup(CLS_C ELS_CC PLS_CC)==FAILURE) { + php3_module_shutdown(); + return FAILURE; + } + } + file_handle.filename = "-"; + file_handle.type = ZEND_HANDLE_FP; + file_handle.handle.fp = stdin; + if (_cgi_filename) { + request_info.filename = _cgi_filename; + } + + php3_TreatHeaders(); + + if (!cgi) { + if (!request_info.query_string) { + for (i = optind, len = 0; i < argc; i++) + len += strlen(argv[i]) + 1; + + s = malloc(len + 1); /* leak - but only for command line version, so ok */ + *s = '\0'; /* we are pretending it came from the environment */ + for (i = optind, len = 0; i < argc; i++) { + strcat(s, argv[i]); + if (i < (argc - 1)) + strcat(s, "+"); + } + request_info.query_string = s; + } + if (!request_info.filename && argc > optind) + request_info.filename = argv[optind]; + } + /* If for some reason the CGI interface is not setting the + PATH_TRANSLATED correctly, request_info.filename is NULL. + We still call php3_fopen_for_parser, because if you set doc_root + or user_dir configuration directives, PATH_INFO is used to construct + the filename as a side effect of php3_fopen_for_parser. + */ + if (cgi || request_info.filename) { + file_handle.filename = request_info.filename; + file_handle.handle.fp = php3_fopen_for_parser(); + } + + if (cgi && !file_handle.handle.fp) { + PUTS("No input file specified.\n"); +#if 0 /* this is here for debuging under windows */ + if (argc) { + i = 0; + php3_printf("\nargc %d\n",argc); + while (i <= argc) { + php3_printf("%s\n",argv[i]); + i++; + } + } +#endif + php3_request_shutdown((void *) 0); + php3_module_shutdown(); + return FAILURE; + } else if (file_handle.handle.fp && file_handle.handle.fp!=stdin) { + /* #!php support */ + c = fgetc(file_handle.handle.fp); + if (c == '#') { + while (c != 10 && c != 13) { + c = fgetc(file_handle.handle.fp); /* skip to end of line */ + } + CG(zend_lineno)++; + } else { + rewind(file_handle.handle.fp); + } + } + + switch (behavior) { + case PHP_MODE_STANDARD: + php3_parse(&file_handle CLS_CC ELS_CC PLS_CC); + break; + case PHP_MODE_HIGHLIGHT: { + zend_syntax_highlighter_ini syntax_highlighter_ini; + + if (open_file_for_scanning(&file_handle CLS_CC)==SUCCESS) { + php_get_highlight_struct(&syntax_highlighter_ini); + zend_highlight(&syntax_highlighter_ini); + fclose(file_handle.handle.fp); + } + return 0; + } + break; + case PHP_MODE_INDENT: + open_file_for_scanning(&file_handle CLS_CC); + zend_indent(); + fclose(file_handle.handle.fp); + return 0; + break; + } + + php3_header(); /* Make sure headers have been sent */ + php3_request_shutdown((void *) 0); + php3_module_shutdown(); + return SUCCESS; +} diff --git a/sapi.c b/sapi.c new file mode 100644 index 00000000000..d04c051727e --- /dev/null +++ b/sapi.c @@ -0,0 +1,16 @@ +#include "SAPI.h" +#include "TSRM.h" + + +#ifdef ZTS +int sapi_globals_id; +#endif + + +void sapi_startup() +{ +#ifdef ZTS + sapi_globals_id = ts_allocate_id(sizeof(sapi_globals_struct), NULL, NULL); +#endif +} + diff --git a/sapi.h b/sapi.h new file mode 100644 index 00000000000..de6af839d15 --- /dev/null +++ b/sapi.h @@ -0,0 +1,37 @@ +#ifndef _NEW_SAPI_H +#define _NEW_SAPI_H + +typedef struct { + int (*ub_write)(const char *str, unsigned int str_length); +} sapi_functions_struct; + +extern sapi_functions_struct sapi_functions; /* true global */ + + +typedef struct { + void *server_context; +} sapi_globals_struct; + + +void sapi_startup(); + +#ifdef ZTS +# define SLS_D sapi_globals_struct *sapi_globals +# define SLS_DC , SLS_D +# define SLS_C sapi_globals +# define SLS_CC , SLS_C +# define SG(v) (sapi_globals->v) +# define SLS_FETCH() sapi_globals_struct *sapi_globals = ts_resource(sapi_globals_id) +extern int sapi_globals_id; +#else +# define SLS_D +# define SLS_DC +# define SLS_C +# define SLS_CC +# define SG(v) (sapi_globals.v) +# define SLS_FETCH() +extern ZEND_API sapi_globals_struct sapi_globals; +#endif + + +#endif /* _NEW_SAPI_H */ \ No newline at end of file