root/sapi/litespeed/lsapi_main.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. php_lsapi_startup
  2. sapi_lsapi_ini_defaults
  3. sapi_lsapi_ub_write
  4. sapi_lsapi_flush
  5. sapi_lsapi_deactivate
  6. sapi_lsapi_getenv
  7. add_variable
  8. litespeed_php_import_environment_variables
  9. sapi_lsapi_register_variables
  10. sapi_lsapi_read_post
  11. sapi_lsapi_read_cookies
  12. sapi_lsapi_send_headers
  13. sapi_lsapi_log_message
  14. init_request_info
  15. lsapi_chdir_primary_script
  16. lsapi_fopen_primary_script
  17. lsapi_execute_script
  18. lsapi_module_main
  19. alter_ini
  20. override_ini
  21. processReq
  22. cli_usage
  23. parse_opt
  24. cli_main
  25. litespeed_cleanup
  26. start_children
  27. setArgv0
  28. main
  29. PHP_MINIT_FUNCTION
  30. PHP_MSHUTDOWN_FUNCTION
  31. add_associate_array
  32. PHP_FUNCTION
  33. PHP_FUNCTION
  34. PHP_FUNCTION

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

/* [<][>][^][v][top][bottom][index][help] */