xref: /PHP-5.3/sapi/litespeed/lsapi_main.c (revision babeca35)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 5                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2013 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 at 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    | Author: George Wang <gwang@litespeedtech.com>                        |
16    +----------------------------------------------------------------------+
17 */
18 
19 /* $Id$ */
20 
21 #include "php.h"
22 #include "SAPI.h"
23 #include "php_main.h"
24 #include "php_ini.h"
25 #include "php_variables.h"
26 #include "zend_highlight.h"
27 #include "zend.h"
28 
29 #include "lsapilib.h"
30 
31 #include <stdio.h>
32 
33 #if HAVE_STDLIB_H
34 #include <stdlib.h>
35 #endif
36 
37 #if HAVE_UNISTD_H
38 #include <unistd.h>
39 #endif
40 
41 #ifdef PHP_WIN32
42 
43 #include <io.h>
44 #include <fcntl.h>
45 #include "win32/php_registry.h"
46 
47 #else
48 
49 #include <sys/wait.h>
50 
51 #endif
52 
53 #include <sys/stat.h>
54 
55 #if HAVE_SYS_TYPES_H
56 
57 #include <sys/types.h>
58 
59 #endif
60 
61 #if HAVE_SIGNAL_H
62 
63 #include <signal.h>
64 
65 #endif
66 
67 #include <sys/socket.h>
68 #include <arpa/inet.h>
69 #include <netinet/in.h>
70 
71 
72 #define SAPI_LSAPI_MAX_HEADER_LENGTH 2048
73 
74 static int  lsapi_mode       = 1;
75 static char *php_self        = "";
76 static char *script_filename = "";
77 static int  source_highlight = 0;
78 static char * argv0 = NULL;
79 static int  engine = 1;
80 #ifdef ZTS
81 zend_compiler_globals    *compiler_globals;
82 zend_executor_globals    *executor_globals;
83 php_core_globals         *core_globals;
84 sapi_globals_struct      *sapi_globals;
85 void ***tsrm_ls;
86 #endif
87 
88 zend_module_entry litespeed_module_entry;
89 
90 /* {{{ php_lsapi_startup
91  */
php_lsapi_startup(sapi_module_struct * sapi_module)92 static int php_lsapi_startup(sapi_module_struct *sapi_module)
93 {
94     if (php_module_startup(sapi_module, NULL, 0)==FAILURE) {
95         return FAILURE;
96     }
97     argv0 = sapi_module->executable_location;
98     return SUCCESS;
99 }
100 /* }}} */
101 
102 /* {{{ sapi_lsapi_ini_defaults */
103 
104 /* overwriteable ini defaults must be set in sapi_cli_ini_defaults() */
105 #define INI_DEFAULT(name,value)\
106     ZVAL_STRING(tmp, value, 0);\
107     zend_hash_update(configuration_hash, name, sizeof(name), tmp, sizeof(zval), (void**)&entry);\
108     Z_STRVAL_P(entry) = zend_strndup(Z_STRVAL_P(entry), Z_STRLEN_P(entry))
109 
sapi_lsapi_ini_defaults(HashTable * configuration_hash)110 static void sapi_lsapi_ini_defaults(HashTable *configuration_hash)
111 {
112     zval *tmp, *entry;
113 
114 #if PHP_MAJOR_VERSION > 4
115 /*
116     MAKE_STD_ZVAL(tmp);
117 
118     INI_DEFAULT("register_long_arrays", "0");
119 
120     FREE_ZVAL(tmp);
121 */
122 #endif
123 
124 }
125 /* }}} */
126 
127 
128 /* {{{ sapi_lsapi_ub_write
129  */
sapi_lsapi_ub_write(const char * str,uint str_length TSRMLS_DC)130 static int sapi_lsapi_ub_write(const char *str, uint str_length TSRMLS_DC)
131 {
132     int ret;
133     int remain;
134     if ( lsapi_mode ) {
135         ret  = LSAPI_Write( str, str_length );
136         if ( ret < str_length ) {
137             php_handle_aborted_connection();
138             return str_length - ret;
139         }
140     } else {
141         remain = str_length;
142         while( remain > 0 ) {
143             ret = write( 1, str, remain );
144             if ( ret <= 0 ) {
145                 php_handle_aborted_connection();
146                 return str_length - remain;
147             }
148             str += ret;
149             remain -= ret;
150         }
151     }
152     return str_length;
153 }
154 /* }}} */
155 
156 
157 /* {{{ sapi_lsapi_flush
158  */
sapi_lsapi_flush(void * server_context)159 static void sapi_lsapi_flush( void * server_context )
160 {
161     if ( lsapi_mode ) {
162         if ( LSAPI_Flush() == -1) {
163             php_handle_aborted_connection();
164         }
165     }
166 }
167 /* }}} */
168 
169 
170 /* {{{ sapi_lsapi_deactivate
171  */
sapi_lsapi_deactivate(TSRMLS_D)172 static int sapi_lsapi_deactivate(TSRMLS_D)
173 {
174     if ( SG(request_info).path_translated )
175     {
176         efree( SG(request_info).path_translated );
177     }
178 
179     return SUCCESS;
180 }
181 /* }}} */
182 
183 
184 
185 
186 /* {{{ sapi_lsapi_getenv
187  */
sapi_lsapi_getenv(char * name,size_t name_len TSRMLS_DC)188 static char *sapi_lsapi_getenv( char * name, size_t name_len TSRMLS_DC )
189 {
190     if ( lsapi_mode ) {
191         return LSAPI_GetEnv( name );
192     } else {
193         return getenv( name );
194     }
195 }
196 /* }}} */
197 
198 
199 /*
200 static int add_variable( const char * pKey, int keyLen, const char * pValue, int valLen,
201                          void * arg )
202 {
203     php_register_variable_safe((char *)pKey, (char *)pValue, valLen, (zval *)arg TSRMLS_CC);
204     return 1;
205 }
206 */
207 
add_variable(const char * pKey,int keyLen,const char * pValue,int valLen,void * arg)208 static int add_variable( const char * pKey, int keyLen, const char * pValue, int valLen,
209                          void * arg )
210 {
211     zval * gpc_element, **gpc_element_p;
212     HashTable * symtable1 = Z_ARRVAL_P((zval * )arg);
213     register char * pKey1 = (char *)pKey;
214 
215     MAKE_STD_ZVAL(gpc_element);
216     Z_STRLEN_P( gpc_element ) = valLen;
217     Z_STRVAL_P( gpc_element ) = estrndup(pValue, valLen);
218     Z_TYPE_P( gpc_element ) = IS_STRING;
219 #if PHP_MAJOR_VERSION > 4
220     zend_symtable_update( symtable1, pKey1, keyLen + 1, &gpc_element, sizeof( zval *), (void **) &gpc_element_p );
221 #else
222     zend_hash_update( symtable1, pKey1, keyLen + 1, &gpc_element, sizeof( zval *), (void **) &gpc_element_p );
223 #endif
224     return 1;
225 }
226 
227 
228 #if ((PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || PHP_MAJOR_VERSION < 5)
add_variable_magic_quote(const char * pKey,int keyLen,const char * pValue,int valLen,void * arg)229 static int add_variable_magic_quote( const char * pKey, int keyLen, const char * pValue, int valLen,
230                          void * arg )
231 {
232     zval * gpc_element, **gpc_element_p;
233     HashTable * symtable1 = Z_ARRVAL_P((zval * )arg);
234     register char * pKey1 = (char *)pKey;
235 
236     MAKE_STD_ZVAL(gpc_element);
237     Z_STRLEN_P( gpc_element ) = valLen;
238     Z_STRVAL_P( gpc_element ) = php_addslashes((char *)pValue, valLen, &Z_STRLEN_P( gpc_element ), 0 );
239     Z_TYPE_P( gpc_element ) = IS_STRING;
240 #if PHP_MAJOR_VERSION > 4
241     zend_symtable_update( symtable1, pKey1, keyLen + 1, &gpc_element, sizeof( zval *), (void **) &gpc_element_p );
242 #else
243     zend_hash_update( symtable1, pKey1, keyLen + 1, &gpc_element, sizeof( zval *), (void **) &gpc_element_p );
244 #endif
245     return 1;
246 }
247 
248 #endif
249 
250 /* {{{ sapi_lsapi_register_variables
251  */
sapi_lsapi_register_variables(zval * track_vars_array TSRMLS_DC)252 static void sapi_lsapi_register_variables(zval *track_vars_array TSRMLS_DC)
253 {
254     char * php_self = "";
255     if ( lsapi_mode ) {
256         if ( (SG(request_info).request_uri ) )
257             php_self = (SG(request_info).request_uri );
258 
259 #if ((PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || PHP_MAJOR_VERSION < 5)
260         if (!PG(magic_quotes_gpc)) {
261 #endif
262             LSAPI_ForeachHeader( add_variable, track_vars_array );
263             LSAPI_ForeachEnv( add_variable, track_vars_array );
264             add_variable("PHP_SELF", 8, php_self, strlen( php_self ), track_vars_array );
265 #if ((PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || PHP_MAJOR_VERSION < 5)
266         } else {
267             LSAPI_ForeachHeader( add_variable_magic_quote, track_vars_array );
268             LSAPI_ForeachEnv( add_variable_magic_quote, track_vars_array );
269             add_variable_magic_quote("PHP_SELF", 8, php_self, strlen( php_self ), track_vars_array );
270         }
271 #endif
272         php_import_environment_variables(track_vars_array TSRMLS_CC);
273     } else {
274         php_import_environment_variables(track_vars_array TSRMLS_CC);
275 
276         php_register_variable("PHP_SELF", php_self, track_vars_array TSRMLS_CC);
277         php_register_variable("SCRIPT_NAME", php_self, track_vars_array TSRMLS_CC);
278         php_register_variable("SCRIPT_FILENAME", script_filename, track_vars_array TSRMLS_CC);
279         php_register_variable("PATH_TRANSLATED", script_filename, track_vars_array TSRMLS_CC);
280         php_register_variable("DOCUMENT_ROOT", "", track_vars_array TSRMLS_CC);
281 
282     }
283 }
284 /* }}} */
285 
286 
287 /* {{{ sapi_lsapi_read_post
288  */
sapi_lsapi_read_post(char * buffer,uint count_bytes TSRMLS_DC)289 static int sapi_lsapi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
290 {
291     if ( lsapi_mode ) {
292         return LSAPI_ReadReqBody( buffer, count_bytes );
293     } else {
294         return 0;
295     }
296 }
297 /* }}} */
298 
299 
300 
301 
302 /* {{{ sapi_lsapi_read_cookies
303  */
sapi_lsapi_read_cookies(TSRMLS_D)304 static char *sapi_lsapi_read_cookies(TSRMLS_D)
305 {
306     if ( lsapi_mode ) {
307         return LSAPI_GetHeader( H_COOKIE );
308     } else {
309         return NULL;
310     }
311 }
312 /* }}} */
313 
314 
315 /* {{{ sapi_lsapi_send_headers
316  */
sapi_lsapi_send_headers(sapi_headers_struct * sapi_headers TSRMLS_DC)317 static int sapi_lsapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
318 {
319     sapi_header_struct  *h;
320     zend_llist_position pos;
321     if ( lsapi_mode ) {
322         LSAPI_SetRespStatus( SG(sapi_headers).http_response_code );
323 
324         h = zend_llist_get_first_ex(&sapi_headers->headers, &pos);
325         while (h) {
326             if ( h->header_len > 0 ) {
327                 LSAPI_AppendRespHeader(h->header, h->header_len);
328             }
329             h = zend_llist_get_next_ex(&sapi_headers->headers, &pos);
330         }
331         if (SG(sapi_headers).send_default_content_type) {
332             char    *hd;
333             int     len;
334             char    headerBuf[SAPI_LSAPI_MAX_HEADER_LENGTH];
335 
336             hd = sapi_get_default_content_type(TSRMLS_C);
337             len = snprintf( headerBuf, SAPI_LSAPI_MAX_HEADER_LENGTH - 1,
338                             "Content-type: %s", hd );
339             efree(hd);
340 
341             LSAPI_AppendRespHeader( headerBuf, len );
342         }
343     }
344     LSAPI_FinalizeRespHeaders();
345     return SAPI_HEADER_SENT_SUCCESSFULLY;
346 
347 
348 }
349 /* }}} */
350 
351 
352 /* {{{ sapi_lsapi_send_headers
353  */
sapi_lsapi_log_message(char * message TSRMLS_DC)354 static void sapi_lsapi_log_message(char *message TSRMLS_DC)
355 {
356     int len = strlen( message );
357     LSAPI_Write_Stderr( message, len);
358 }
359 /* }}} */
360 
361 
362 /* {{{ sapi_module_struct cgi_sapi_module
363  */
364 static sapi_module_struct lsapi_sapi_module =
365 {
366     "litespeed",
367     "LiteSpeed V5.5",
368 
369     php_lsapi_startup,              /* startup */
370     php_module_shutdown_wrapper,    /* shutdown */
371 
372     NULL,                           /* activate */
373     sapi_lsapi_deactivate,          /* deactivate */
374 
375     sapi_lsapi_ub_write,            /* unbuffered write */
376     sapi_lsapi_flush,               /* flush */
377     NULL,                           /* get uid */
378     sapi_lsapi_getenv,              /* getenv */
379 
380     php_error,                      /* error handler */
381 
382     NULL,                           /* header handler */
383     sapi_lsapi_send_headers,        /* send headers handler */
384     NULL,                           /* send header handler */
385 
386     sapi_lsapi_read_post,           /* read POST data */
387     sapi_lsapi_read_cookies,        /* read Cookies */
388 
389     sapi_lsapi_register_variables,  /* register server variables */
390     sapi_lsapi_log_message,         /* Log message */
391 
392     NULL,                           /* php.ini path override */
393     NULL,                           /* block interruptions */
394     NULL,                           /* unblock interruptions */
395     NULL,                           /* default post reader */
396     NULL,                           /* treat data */
397     NULL,                           /* executable location */
398 
399     0,                              /* php.ini ignore */
400 
401     STANDARD_SAPI_MODULE_PROPERTIES
402 
403 };
404 /* }}} */
405 
init_request_info(TSRMLS_D)406 static int init_request_info( TSRMLS_D )
407 {
408     char * pContentType = LSAPI_GetHeader( H_CONTENT_TYPE );
409     char * pAuth;
410 
411     SG(request_info).content_type = pContentType ? pContentType : "";
412     SG(request_info).request_method = LSAPI_GetRequestMethod();
413     SG(request_info).query_string = LSAPI_GetQueryString();
414     SG(request_info).request_uri = LSAPI_GetScriptName();
415     SG(request_info).content_length = LSAPI_GetReqBodyLen();
416     SG(request_info).path_translated = estrdup( LSAPI_GetScriptFileName());
417 
418     /* It is not reset by zend engine, set it to 0. */
419     SG(sapi_headers).http_response_code = 0;
420 
421     pAuth = LSAPI_GetHeader( H_AUTHORIZATION );
422     php_handle_auth_data(pAuth TSRMLS_CC);
423 }
424 
425 static char s_cur_chdir[4096] = "";
426 
lsapi_chdir_primary_script(zend_file_handle * file_handle)427 static int lsapi_chdir_primary_script( zend_file_handle * file_handle )
428 {
429 #if PHP_MAJOR_VERSION > 4
430     char * p;
431     char ch;
432 
433     SG(options) |= SAPI_OPTION_NO_CHDIR;
434     getcwd( s_cur_chdir, sizeof( s_cur_chdir ) );
435 
436     p = strrchr( file_handle->filename, '/' );
437     if ( *p )
438     {
439         *p = 0;
440         if ( strcmp( file_handle->filename, s_cur_chdir ) != 0 ) {
441             chdir( file_handle->filename );
442         }
443         *p++ = '/';
444         ch = *p;
445         *p = 0;
446         if ( !CWDG(cwd).cwd ||
447              ( strcmp( file_handle->filename, CWDG(cwd).cwd ) != 0 ) ) {
448             CWDG(cwd).cwd_length = p - file_handle->filename;
449             CWDG(cwd).cwd = (char *) realloc(CWDG(cwd).cwd, CWDG(cwd).cwd_length+1);
450             memmove( CWDG(cwd).cwd, file_handle->filename, CWDG(cwd).cwd_length+1 );
451         }
452         *p = ch;
453     }
454     /* virtual_file_ex(&CWDG(cwd), file_handle->filename, NULL, CWD_REALPATH); */
455 #else
456     VCWD_CHDIR_FILE( file_handle->filename );
457 #endif
458     return 0;
459 }
460 
lsapi_fopen_primary_script(zend_file_handle * file_handle)461 static int lsapi_fopen_primary_script( zend_file_handle * file_handle )
462 {
463     FILE * fp;
464     char * p;
465     fp = fopen( SG(request_info).path_translated, "rb" );
466     if ( !fp )
467     {
468         return -1;
469     }
470     file_handle->type = ZEND_HANDLE_FP;
471     file_handle->handle.fp = fp;
472     file_handle->filename = SG(request_info).path_translated;
473     file_handle->free_filename = 0;
474     file_handle->opened_path = NULL;
475 
476     lsapi_chdir_primary_script( file_handle );
477 
478     return 0;
479 }
480 
lsapi_execute_script(zend_file_handle * file_handle TSRMLS_DC)481 static int lsapi_execute_script( zend_file_handle * file_handle TSRMLS_DC)
482 {
483     char *p;
484     int len;
485     file_handle->type = ZEND_HANDLE_FILENAME;
486     file_handle->handle.fd = 0;
487     file_handle->filename = SG(request_info).path_translated;
488     file_handle->free_filename = 0;
489     file_handle->opened_path = NULL;
490 
491     p = argv0;
492     *p++ = ':';
493     len = strlen( SG(request_info).path_translated );
494     if ( len > 45 )
495         len = len - 45;
496     else
497         len = 0;
498     memccpy( p, SG(request_info).path_translated + len, 0, 46 );
499 
500     php_execute_script(file_handle TSRMLS_CC);
501     return 0;
502 
503 }
504 
505 
lsapi_module_main(int show_source TSRMLS_DC)506 static int lsapi_module_main(int show_source TSRMLS_DC)
507 {
508     zend_file_handle file_handle = {0};
509 
510     if (php_request_startup(TSRMLS_C) == FAILURE ) {
511         return -1;
512     }
513     if (show_source) {
514         zend_syntax_highlighter_ini syntax_highlighter_ini;
515 
516         php_get_highlight_struct(&syntax_highlighter_ini);
517         highlight_file(SG(request_info).path_translated, &syntax_highlighter_ini TSRMLS_CC);
518     } else {
519         lsapi_execute_script( &file_handle TSRMLS_CC);
520     }
521     zend_try {
522         php_request_shutdown(NULL);
523         *argv0 = 0;
524     } zend_end_try();
525     return 0;
526 }
527 
528 
alter_ini(const char * pKey,int keyLen,const char * pValue,int valLen,void * arg)529 static int alter_ini( const char * pKey, int keyLen, const char * pValue, int valLen,
530                 void * arg )
531 {
532     int type = ZEND_INI_PERDIR;
533     if ( '\001' == *pKey ) {
534         ++pKey;
535         if ( *pKey == 4 ) {
536             type = ZEND_INI_SYSTEM;
537         }
538         ++pKey;
539         --keyLen;
540         if (( keyLen == 7 )&&( strncasecmp( pKey, "engine", 6 )== 0 ))
541         {
542             if ( *pValue == '0' )
543                 engine = 0;
544         }
545         else
546             zend_alter_ini_entry((char *)pKey, keyLen,
547                              (char *)pValue, valLen,
548                              type, PHP_INI_STAGE_ACTIVATE);
549     }
550     return 1;
551 }
552 
553 
override_ini()554 static void override_ini()
555 {
556 
557     LSAPI_ForeachSpecialEnv( alter_ini, NULL );
558 
559 }
560 
processReq(TSRMLS_D)561 static int processReq( TSRMLS_D )
562 {
563     int ret = 0;
564     zend_first_try {
565         /* avoid server_context==NULL checks */
566         SG(server_context) = (void *) 1;
567 
568         engine = 1;
569         override_ini();
570 
571         if ( engine ) {
572             init_request_info( TSRMLS_C );
573 
574             if ( lsapi_module_main( source_highlight TSRMLS_CC ) == -1 ) {
575                 ret = -1;
576             }
577         } else {
578             LSAPI_AppendRespHeader( "status: 403", 11 );
579             LSAPI_AppendRespHeader( "content-type: text/html", 23 );
580             LSAPI_Write( "Forbidden: PHP engine is disable.\n", 34 );
581         }
582     } zend_end_try();
583     return ret;
584 }
585 
cli_usage(TSRMLS_D)586 static void cli_usage( TSRMLS_D )
587 {
588     static const char * usage =
589         "Usage: php\n"
590         "      php -[b|c|h|i|q|s|v|?] [<file>] [args...]\n"
591         "  Run in LSAPI mode, only '-b', '-s' and '-c' are effective\n"
592         "  Run in Command Line Interpreter mode when parameters are specified\n"
593         "\n"
594         "  -b <address:port>|<port> Bind Path for external LSAPI Server mode\n"
595         "  -c <path>|<file> Look for php.ini file in this directory\n"
596         "  -h    This help\n"
597         "  -i    PHP information\n"
598         "  -q    Quiet-mode.  Suppress HTTP Header output.\n"
599         "  -s    Display colour syntax highlighted source.\n"
600         "  -v    Version number\n"
601         "  -?    This help\n"
602         "\n"
603         "  args...    Arguments passed to script.\n";
604     php_output_startup();
605     php_output_activate(TSRMLS_C);
606     php_printf( usage );
607 #ifdef PHP_OUTPUT_NEWAPI
608     php_output_end_all(TSRMLS_C);
609 #else
610     php_end_ob_buffers(1 TSRMLS_CC);
611 #endif
612 }
613 
parse_opt(int argc,char * argv[],int * climode,char ** php_ini_path,char ** php_bind)614 static int parse_opt( int argc, char * argv[], int *climode,
615                         char **php_ini_path, char ** php_bind )
616 {
617     char ** p = &argv[1];
618     char ** argend= &argv[argc];
619     int c;
620     while (( p < argend )&&(**p == '-' )) {
621         c = *((*p)+1);
622         ++p;
623         switch( c ) {
624         case 'b':
625             if ( p >= argend ) {
626                 fprintf( stderr, "TCP or socket address must be specified following '-b' option.\n");
627                 return -1;
628             }
629             *php_bind = *p++;
630             break;
631 
632         case 'c':
633             if ( p >= argend ) {
634                 fprintf( stderr, "<path> or <file> must be specified following '-c' option.\n");
635 
636                 return -1;
637             }
638             *php_ini_path = *p++;
639             break;
640         case 's':
641             source_highlight = 1;
642             break;
643         case 'h':
644         case 'i':
645         case 'q':
646         case 'v':
647         case '?':
648         default:
649             *climode = 1;
650             break;
651         }
652     }
653     if ( p - argv < argc ) {
654         *climode = 1;
655     }
656     return 0;
657 }
658 
cli_main(int argc,char * argv[])659 static int cli_main( int argc, char * argv[] )
660 {
661 
662     static const char * ini_defaults[] = {
663         "report_zend_debug",    "0",
664         "display_errors",       "1",
665         "register_argc_argv",   "1",
666         "html_errors",          "0",
667         "implicit_flush",       "1",
668         "output_buffering",     "0",
669         "max_execution_time",   "0",
670         "max_input_time",       "-1",
671         NULL
672     };
673 
674     const char ** ini;
675     char ** p = &argv[1];
676     char ** argend= &argv[argc];
677     int ret = 0;
678     int c;
679     lsapi_mode = 0;        /* enter CLI mode */
680 
681 #ifdef PHP_WIN32
682     _fmode = _O_BINARY;            /*sets default for file streams to binary */
683     setmode(_fileno(stdin), O_BINARY);    /* make the stdio mode be binary */
684     setmode(_fileno(stdout), O_BINARY);   /* make the stdio mode be binary */
685     setmode(_fileno(stderr), O_BINARY);   /* make the stdio mode be binary */
686 #endif
687 
688     zend_first_try     {
689         SG(server_context) = (void *) 1;
690 
691         zend_uv.html_errors = 0; /* tell the engine we're in non-html mode */
692         CG(in_compilation) = 0; /* not initialized but needed for several options */
693         EG(uninitialized_zval_ptr) = NULL;
694 
695         for( ini = ini_defaults; *ini; ini+=2 ) {
696             zend_alter_ini_entry( (char *)*ini, strlen( *ini )+1,
697                                 (char *)*(ini+1), strlen( *(ini+1) ),
698                                 PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
699         }
700 
701         while (( p < argend )&&(**p == '-' )) {
702             c = *((*p)+1);
703             ++p;
704             switch( c ) {
705             case 'q':
706                 break;
707             case 'i':
708                 if (php_request_startup(TSRMLS_C) != FAILURE) {
709                     php_print_info(0xFFFFFFFF TSRMLS_CC);
710 #ifdef PHP_OUTPUT_NEWAPI
711                     php_output_end_all(TSRMLS_C);
712 #else
713                     php_end_ob_buffers(1 TSRMLS_CC);
714 #endif
715                     php_request_shutdown( NULL );
716                 }
717                 ret = 1;
718                 break;
719             case 'v':
720                 if (php_request_startup(TSRMLS_C) != FAILURE) {
721 #if ZEND_DEBUG
722                     php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2014 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
723 #else
724                     php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2014 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
725 #endif
726 #ifdef PHP_OUTPUT_NEWAPI
727                     php_output_end_all(TSRMLS_C);
728 #else
729                     php_end_ob_buffers(1 TSRMLS_CC);
730 #endif
731                     php_request_shutdown( NULL );
732                 }
733                 ret = 1;
734                 break;
735             case 'c':
736                 ++p;
737             /* fall through */
738             case 's':
739                 break;
740 
741             case 'h':
742             case '?':
743             default:
744                 cli_usage(TSRMLS_C);
745                 ret = 1;
746                 break;
747 
748             }
749         }
750         if ( !ret ) {
751             if ( *p ) {
752                 zend_file_handle file_handle = {0};
753 
754                 file_handle.type = ZEND_HANDLE_FP;
755                 file_handle.handle.fp = VCWD_FOPEN(*p, "rb");
756 
757                 if ( file_handle.handle.fp ) {
758                     script_filename = *p;
759                     php_self = *p;
760 
761                     SG(request_info).path_translated = estrdup(*p);
762                     SG(request_info).argc = argc - (p - argv);
763                     SG(request_info).argv = p;
764 
765                     if (php_request_startup(TSRMLS_C) == FAILURE ) {
766                         fclose( file_handle.handle.fp );
767                         ret = 2;
768                     } else {
769                         if (source_highlight) {
770                             zend_syntax_highlighter_ini syntax_highlighter_ini;
771 
772                             php_get_highlight_struct(&syntax_highlighter_ini);
773                             highlight_file(SG(request_info).path_translated, &syntax_highlighter_ini TSRMLS_CC);
774                         } else {
775                             file_handle.filename = *p;
776                             file_handle.free_filename = 0;
777                             file_handle.opened_path = NULL;
778 
779                             php_execute_script(&file_handle TSRMLS_CC);
780                         }
781 
782                         php_request_shutdown( NULL );
783                     }
784                 } else {
785                     php_printf("Could not open input file: %s.\n", *p);
786                 }
787             } else {
788                 cli_usage(TSRMLS_C);
789             }
790         }
791 
792     }zend_end_try();
793 
794     php_module_shutdown(TSRMLS_C);
795 
796 #ifdef ZTS
797     tsrm_shutdown();
798 #endif
799     return ret;
800 }
801 
802 static int s_stop;
litespeed_cleanup(int signal)803 void litespeed_cleanup(int signal)
804 {
805     s_stop = signal;
806 }
807 
808 
start_children(int children)809 void start_children( int children )
810 {
811     struct sigaction act, old_term, old_quit, old_int, old_usr1;
812     int running = 0;
813     int status;
814     pid_t pid;
815 
816     /* Create a process group */
817     setsid();
818 
819     /* Set up handler to kill children upon exit */
820     act.sa_flags = 0;
821     act.sa_handler = litespeed_cleanup;
822     if( sigaction( SIGTERM, &act, &old_term ) ||
823         sigaction( SIGINT,  &act, &old_int  ) ||
824         sigaction( SIGUSR1, &act, &old_usr1 ) ||
825         sigaction( SIGQUIT, &act, &old_quit )) {
826         perror( "Can't set signals" );
827         exit( 1 );
828     }
829     s_stop = 0;
830     while( 1 ) {
831         while((!s_stop )&&( running < children )) {
832             pid = fork();
833             switch( pid ) {
834             case 0: /* children process */
835 
836                 /* don't catch our signals */
837                 sigaction( SIGTERM, &old_term, 0 );
838                 sigaction( SIGQUIT, &old_quit, 0 );
839                 sigaction( SIGINT,  &old_int,  0 );
840                 sigaction( SIGUSR1, &old_usr1, 0 );
841                 return ;
842             case -1:
843                 perror( "php (pre-forking)" );
844                 exit( 1 );
845                 break;
846             default: /* parent process */
847                 running++;
848                 break;
849             }
850         }
851         if ( s_stop ) {
852             break;
853         }
854         pid = wait( &status );
855         running--;
856     }
857     kill( -getpgrp(), SIGUSR1 );
858     exit( 0 );
859 }
860 
861 
862 
863 #include <fcntl.h>
main(int argc,char * argv[])864 int main( int argc, char * argv[] )
865 {
866     int ret;
867     int bindFd;
868 
869     char * php_ini_path = NULL;
870     char * php_bind     = NULL;
871     char * p;
872     int n;
873     int climode = 0;
874     struct timeval tv_req_begin;
875     struct timeval tv_req_end;
876     int slow_script_msec = 0;
877     char time_buf[40];
878 
879 #ifdef HAVE_SIGNAL_H
880 #if defined(SIGPIPE) && defined(SIG_IGN)
881     signal(SIGPIPE, SIG_IGN);
882 #endif
883 #endif
884 
885 #ifdef ZTS
886     tsrm_startup(1, 1, 0, NULL);
887 #endif
888 
889     if (argc > 1 ) {
890         if ( parse_opt( argc, argv, &climode,
891                 &php_ini_path, &php_bind ) == -1 ) {
892             return 1;
893         }
894     }
895     if ( climode ) {
896         lsapi_sapi_module.phpinfo_as_text = 1;
897     }
898     argv0 = argv[0] + strlen( argv[0] );
899     sapi_startup(&lsapi_sapi_module);
900 
901 #ifdef ZTS
902     compiler_globals = ts_resource(compiler_globals_id);
903     executor_globals = ts_resource(executor_globals_id);
904     core_globals = ts_resource(core_globals_id);
905     sapi_globals = ts_resource(sapi_globals_id);
906     tsrm_ls = ts_resource(0);
907 
908     SG(request_info).path_translated = NULL;
909 #endif
910 
911     lsapi_sapi_module.executable_location = argv[0];
912 
913     if ( php_ini_path ) {
914         lsapi_sapi_module.php_ini_path_override = php_ini_path;
915     }
916 
917 
918     lsapi_sapi_module.ini_defaults = sapi_lsapi_ini_defaults;
919 
920     if (php_module_startup(&lsapi_sapi_module, &litespeed_module_entry, 1) == FAILURE) {
921 #ifdef ZTS
922         tsrm_shutdown();
923 #endif
924         return FAILURE;
925     }
926 
927     if ( climode ) {
928         return cli_main(argc, argv);
929     }
930 
931     if ( php_bind ) {
932         bindFd = LSAPI_CreateListenSock( php_bind, 10 );
933         if ( bindFd == -1 ) {
934             fprintf( stderr,
935                      "Failed to bind socket [%s]: %s\n", php_bind, strerror( errno ) );
936             exit( 2 );
937         }
938         if ( bindFd != 0 ) {
939             dup2( bindFd, 0 );
940             close( bindFd );
941         }
942     }
943 
944     LSAPI_Init();
945 
946     LSAPI_Init_Env_Parameters( NULL );
947 
948     slow_script_msec = LSAPI_Get_Slow_Req_Msecs();
949 
950     if ( php_bind ) {
951         LSAPI_No_Check_ppid();
952     }
953 
954     while( LSAPI_Prefork_Accept_r( &g_req ) >= 0 ) {
955         if ( slow_script_msec ) {
956             gettimeofday( &tv_req_begin, NULL );
957         }
958         ret = processReq(TSRMLS_C);
959         if ( slow_script_msec ) {
960             gettimeofday( &tv_req_end, NULL );
961             n = ((long) tv_req_end.tv_sec - tv_req_begin.tv_sec ) * 1000
962                 + (tv_req_end.tv_usec - tv_req_begin.tv_usec) / 1000;
963             if ( n > slow_script_msec )
964             {
965                 strftime( time_buf, 30, "%d/%b/%Y:%H:%M:%S", localtime( &tv_req_end.tv_sec ) );
966                 fprintf( stderr, "[%s] Slow PHP script: %d ms\n  URL: %s %s\n  Query String: %s\n  Script: %s\n",
967                          time_buf, n,  LSAPI_GetRequestMethod(),
968                          LSAPI_GetScriptName(), LSAPI_GetQueryString(),
969                          LSAPI_GetScriptFileName() );
970 
971             }
972         }
973         LSAPI_Finish();
974         if ( ret ) {
975             break;
976         }
977     }
978     php_module_shutdown(TSRMLS_C);
979 
980 #ifdef ZTS
981     tsrm_shutdown();
982 #endif
983     return ret;
984 }
985 
986 
987 /*   LiteSpeed PHP module starts here */
988 
989 #if PHP_MAJOR_VERSION > 4
990 
991 /* {{{ arginfo */
992 ZEND_BEGIN_ARG_INFO(arginfo_litespeed__void, 0)
993 ZEND_END_ARG_INFO()
994 /* }}} */
995 
996 #else
997 #define arginfo_litespeed__void NULL
998 #endif
999 
1000 PHP_FUNCTION(litespeed_request_headers);
1001 PHP_FUNCTION(litespeed_response_headers);
1002 
1003 PHP_MINFO_FUNCTION(litespeed);
1004 
1005 zend_function_entry litespeed_functions[] = {
1006     PHP_FE(litespeed_request_headers,     arginfo_litespeed__void)
1007     PHP_FE(litespeed_response_headers,     arginfo_litespeed__void)
1008     PHP_FALIAS(getallheaders,             litespeed_request_headers,     arginfo_litespeed__void)
1009     PHP_FALIAS(apache_request_headers,     litespeed_request_headers,     arginfo_litespeed__void)
1010     PHP_FALIAS(apache_response_headers, litespeed_response_headers, arginfo_litespeed__void)
1011     {NULL, NULL, NULL}
1012 };
1013 
PHP_MINIT_FUNCTION(litespeed)1014 static PHP_MINIT_FUNCTION(litespeed)
1015 {
1016     /* REGISTER_INI_ENTRIES(); */
1017     return SUCCESS;
1018 }
1019 
1020 
PHP_MSHUTDOWN_FUNCTION(litespeed)1021 static PHP_MSHUTDOWN_FUNCTION(litespeed)
1022 {
1023     /* UNREGISTER_INI_ENTRIES(); */
1024     return SUCCESS;
1025 }
1026 
1027 zend_module_entry litespeed_module_entry = {
1028     STANDARD_MODULE_HEADER,
1029     "litespeed",
1030     litespeed_functions,
1031     PHP_MINIT(litespeed),
1032     PHP_MSHUTDOWN(litespeed),
1033     NULL,
1034     NULL,
1035     NULL,
1036     NO_VERSION_YET,
1037     STANDARD_MODULE_PROPERTIES
1038 };
1039 
add_associate_array(const char * pKey,int keyLen,const char * pValue,int valLen,void * arg)1040 static int add_associate_array( const char * pKey, int keyLen, const char * pValue, int valLen,
1041                          void * arg )
1042 {
1043     add_assoc_string_ex( (zval *)arg, (char *)pKey, keyLen+1, (char *)pValue, 1 );
1044     return 1;
1045 }
1046 
1047 
1048 /* {{{ proto array litespeed_request_headers(void)
1049    Fetch all HTTP request headers */
PHP_FUNCTION(litespeed_request_headers)1050 PHP_FUNCTION(litespeed_request_headers)
1051 {
1052     /* TODO: */
1053     if (ZEND_NUM_ARGS() > 0) {
1054         WRONG_PARAM_COUNT;
1055     }
1056     array_init(return_value);
1057 
1058     if ( lsapi_mode )
1059         LSAPI_ForeachOrgHeader( add_associate_array, return_value );
1060 
1061 }
1062 /* }}} */
1063 
1064 
1065 
1066 /* {{{ proto array litespeed_response_headers(void)
1067    Fetch all HTTP response headers */
PHP_FUNCTION(litespeed_response_headers)1068 PHP_FUNCTION(litespeed_response_headers)
1069 {
1070     sapi_header_struct  *h;
1071     zend_llist_position pos;
1072     char *       p;
1073     int          len;
1074     char         headerBuf[SAPI_LSAPI_MAX_HEADER_LENGTH];
1075 
1076     if (ZEND_NUM_ARGS() > 0) {
1077         WRONG_PARAM_COUNT;
1078     }
1079 
1080     if (!&SG(sapi_headers).headers) {
1081         RETURN_FALSE;
1082     }
1083     array_init(return_value);
1084 
1085     h = zend_llist_get_first_ex(&SG(sapi_headers).headers, &pos);
1086     while (h) {
1087         if ( h->header_len > 0 ) {
1088             p = strchr( h->header, ':' );
1089             len = p - h->header;
1090             if (( p )&&( len > 0 )) {
1091                 memmove( headerBuf, h->header, len );
1092                 while( len > 0 && (isspace( headerBuf[len-1])) ) {
1093                     --len;
1094                 }
1095                 headerBuf[len] = 0;
1096                 if ( len ) {
1097                     while( isspace(*++p));
1098                     add_assoc_string_ex(return_value, headerBuf, len+1, p, 1 );
1099                 }
1100             }
1101         }
1102         h = zend_llist_get_next_ex(&SG(sapi_headers).headers, &pos);
1103     }
1104 }
1105 
1106 /* }}} */
1107 
1108 
1109 /*
1110  * Local variables:
1111  * tab-width: 4
1112  * c-basic-offset: 4
1113  * End:
1114  * vim600: sw=4 ts=4 fdm=marker
1115  * vim<600: sw=4 ts=4
1116  */
1117 
1118 
1119