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