mirror of
https://github.com/php/php-src.git
synced 2024-11-23 18:04:36 +08:00
added litespeed SAPI
This commit is contained in:
parent
457f00b201
commit
52604d2832
2
sapi/litespeed/CREDITS
Normal file
2
sapi/litespeed/CREDITS
Normal file
@ -0,0 +1,2 @@
|
||||
litespeed
|
||||
George Wang
|
3
sapi/litespeed/Makefile.frag
Normal file
3
sapi/litespeed/Makefile.frag
Normal file
@ -0,0 +1,3 @@
|
||||
$(SAPI_LITESPEED_PATH): $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS)
|
||||
$(BUILD_LITESPEED)
|
||||
|
225
sapi/litespeed/README
Normal file
225
sapi/litespeed/README
Normal file
@ -0,0 +1,225 @@
|
||||
Introduction
|
||||
============
|
||||
|
||||
LiteSpeed SAPI module is a dedicated interface for PHP integration with
|
||||
LiteSpeed Web Server. LiteSpeed SAPI has similar architecture to the
|
||||
FastCGI SAPI with there major enhancements: better performance, dynamic
|
||||
spawning and PHP configuration modification through web server
|
||||
configuration and .htaccess files.
|
||||
|
||||
Our simple benchmark test ("hello world") shows that PHP with
|
||||
LiteSpeed SAPI has 30% better performance over PHP with FastCGI SAPI,
|
||||
which is nearly twice the performance that Apache mod_php can deliver.
|
||||
|
||||
A major drawback of FastCGI PHP comparing to Apache mod_php is lacking
|
||||
the flexibilities in PHP configurations. PHP configurations cannot be
|
||||
changed at runtime via configuration files like .htaccess files or web
|
||||
server's virtual host configuration. In shared hosting environment,
|
||||
each hosting account will has its own "open_basedir" overridden in
|
||||
server configuration to enhance server security when mod_php is used.
|
||||
usually, FastCGI PHP is not an option in shared hosting environment
|
||||
due to lacking of this flexibility. LiteSpeed SAPI is carefully designed
|
||||
to address this issue. PHP configurations can be modified the same way
|
||||
as that in mod_php with the the same configuration directives.
|
||||
|
||||
PHP with LiteSpeed SAPI is highly recommended over FastCGI PHP for
|
||||
PHP scripting with LiteSpeed web server.
|
||||
|
||||
|
||||
Building PHP with LiteSpeed SAPI
|
||||
================================
|
||||
|
||||
You need to add "--with-litespeed" to the configure command to build
|
||||
PHP with LiteSpeed SAPI, all other SAPI related configure options
|
||||
should be removed.
|
||||
|
||||
For example:
|
||||
./configure --with-litespeed
|
||||
make
|
||||
|
||||
You should find an executable called 'php' under sapi/litespeed/
|
||||
directory after the compilation succeeds. Copy it to
|
||||
'lsws/fcgi-bin/lsphp' or wherever you prefer, if LiteSpeed web server
|
||||
has been configured to run PHP with LiteSpeed SAPI already, you just
|
||||
need to overwrite the old executable with this one and you are all
|
||||
set.
|
||||
|
||||
Start PHP from command line
|
||||
===========================
|
||||
|
||||
Usually, lsphp is managed by LiteSpeed web server in a single server
|
||||
installation. lsphp can be used in clustered environment with one
|
||||
LiteSpeed web server at the front, load balancing lsphp processes
|
||||
running on multiple backend servers. In such environment, lsphp can be
|
||||
start manually from command with option "-b <socket_address>", socket
|
||||
address can be IPv4, IPv6 or Unix Domain Socket address.
|
||||
for example:
|
||||
|
||||
./lsphp -b [::]:3000
|
||||
|
||||
have lsphp bind to port 3000 on all IPv4 and IPv6 address,
|
||||
|
||||
./lsphp -b *:3000
|
||||
|
||||
have lsphp bind to port 300 on all IPv4 address.
|
||||
|
||||
./lsphp -b 192.168.0.2:3000
|
||||
|
||||
have lsphp bind to address 192.168.0.2:3000.
|
||||
|
||||
./lsphp -b /tmp/lsphp_manual.sock
|
||||
|
||||
have lsphp accept request on Unix domain socket "/tmp/lsphp_manual.sock"
|
||||
|
||||
|
||||
Using LiteSpeed PHP with LiteSpeed Web Server
|
||||
=============================================
|
||||
|
||||
Detailed information about how to configure LiteSpeed web server with
|
||||
PHP support is available from our website, at:
|
||||
|
||||
http://www.litespeedtech.com/docs/HowTo_QA.html
|
||||
|
||||
Usually, PHP support has been configured out of box, you don't need to
|
||||
change it unless you want to change PHP interface from FastCGI to
|
||||
LiteSpeed SAPI or vice versa.
|
||||
|
||||
Brief instructions are as follow:
|
||||
|
||||
1) Login to web administration interface, go to 'Server'->'Ext App' tab,
|
||||
add an external application of type "LSAPI app", "Command" should be
|
||||
set to a shell command that executes the PHP binary you just built.
|
||||
"Instances" should be set to "1". Add "LSAPI_CHILDREN" environment
|
||||
variable to match the value of "Max Connections". More tunable
|
||||
environment variable described below can be added.
|
||||
|
||||
2) Go to 'Server'->'Script Handler' tab, add a script handler
|
||||
configuration: set 'suffix' to 'php', 'Handler Type' to 'LiteSpeed
|
||||
API', 'Handler Name' should be the name of external application
|
||||
just defined.
|
||||
|
||||
|
||||
3) Click 'Apply Changes' link on the top left of the page, then click
|
||||
'graceful restart'. Now PHP is running with LiteSpeed SAPI.
|
||||
|
||||
Tunings
|
||||
-------
|
||||
|
||||
There are a few environment variables that can be tweaked to control the
|
||||
behavior of LSAPI application.
|
||||
|
||||
* LSAPI_CHILDREN or PHP_LSAPI_CHILDREN (default: 0)
|
||||
|
||||
There are two ways to let PHP handle multiple requests concurrently,
|
||||
Server Managed Mode and Self Managed Mode. In Server Managed Mode,
|
||||
LiteSpeed web server dynamically spawn/stop PHP processes, in this mode
|
||||
"Instances" should match "Max Connections" configuration for PHP
|
||||
external application. To start PHP in Self Managed Mode, "Instances"
|
||||
should be set to "1", while "LSAPI_CHILDREN" environment variable should
|
||||
be set to match the value of "Max Connections" and >1. Web Server will
|
||||
start one PHP process, this process will start/stop children PHP processes
|
||||
dynamically based on on demand. If "LSAPI_CHILDREN" <=1, PHP will be
|
||||
started in server managed mode.
|
||||
|
||||
Self Managed Mode is preferred because all PHP processes can share one
|
||||
shared memory block for the opcode cache.
|
||||
|
||||
Usually, there is no need to set value of LSAPI_CHILDREN over 100 in
|
||||
most server environment.
|
||||
|
||||
|
||||
* LSAPI_AVOID_FORK (default: 0)
|
||||
|
||||
LSAPI_AVOID_FORK specifies the policy of the internal process manager in
|
||||
"Self Managed Mode". When set to 0, the internal process manager will stop
|
||||
and start children process on demand to save system resource. This is
|
||||
preferred in a shared hosting environment. When set to 1, the internal
|
||||
process manager will try to avoid freqently stopping and starting children
|
||||
process. This might be preferred in a dedicate hosting environment.
|
||||
|
||||
|
||||
* LSAPI_EXTRA_CHILDREN (default: 1/3 of LSAPI_CHILDREN or 0)
|
||||
|
||||
LSAPI_EXTRA_CHILDREN controls the maximum number of extra children processes
|
||||
can be started when some or all existing children processes are in
|
||||
malfunctioning state. Total number of children processes will be reduced to
|
||||
LSAPI_CHILDREN level as soon as service is back to normal.
|
||||
When LSAPI_AVOID_FORK is set to 0, the default value is 1/3 of
|
||||
LSAPI_CHIDLREN, When LSAPI_AVOID_FORK is set to 1, the default value is 0.
|
||||
|
||||
|
||||
* LSAPI_MAX_REQS or PHP_LSAPI_MAX_REQUESTS (default value: 10000)
|
||||
|
||||
This controls how many requests each child process will handle before
|
||||
it exits automatically. Several PHP functions have been identified
|
||||
having memory leaks. This parameter can help reducing memory usage
|
||||
of leaky PHP functions.
|
||||
|
||||
|
||||
* LSAPI_MAX_IDLE (default value: 300 seconds)
|
||||
|
||||
In Self Managed Mode, LSAPI_MAX_IDLE controls how long a idle child
|
||||
process will wait for a new request before it exits. This option help
|
||||
releasing system resources taken by idle processes.
|
||||
|
||||
|
||||
* LSAPI_MAX_IDLE_CHILDREN
|
||||
(default value: 1/3 of LSAPI_CHILDREN or LSAPI_CHILDREN)
|
||||
|
||||
In Self Managed Mode, LSAI_MAX_IDLE_CHILDREN controls how many idle
|
||||
children processes are allowed. Excessive idle children processes
|
||||
will be killed by the parent process immediately.
|
||||
When LSAPI_AVOID_FORK is set to 0, the default value is 1/3 of
|
||||
LSAPI_CHIDLREN, When LSAPI_AVOID_FORK is set to 1, the default value
|
||||
is LSAPI_CHILDREN.
|
||||
|
||||
|
||||
* LSAPI_MAX_PROCESS_TIME (default value: 300 seconds)
|
||||
|
||||
In Self Managed Mode, LSAPI_MAX_PROCESS_TIME controls the maximum
|
||||
processing time allowed when processing a request. If a child process
|
||||
can not finish processing of a request in the given time period, it
|
||||
will be killed by the parent process. This option can help getting rid
|
||||
of dead or runaway child process.
|
||||
|
||||
|
||||
* LSAPI_PGRP_MAX_IDLE (default value: FOREVER )
|
||||
|
||||
In Self Managed Mode, LSAPI_PGRP_MAX_IDLE controls how long the parent
|
||||
process will wait before exiting when there is no child process.
|
||||
This option help releasing system resources taken by an idle parent
|
||||
process.
|
||||
|
||||
|
||||
* LSAPI_PPID_NO_CHECK
|
||||
|
||||
By default a LSAPI application check the existence of its parent process
|
||||
and exits automatically if the parent process died. This is to reduce
|
||||
orphan process when web server is restarted. However, it is desireable
|
||||
to disable this feature, such as when a LSAPI process was started
|
||||
manually from command line. LSAPI_PPID_NO_CHECK should be set when
|
||||
you want to disable the checking of existence of parent process.
|
||||
When PHP started by "-b" option, it is disabled automatically.
|
||||
|
||||
|
||||
Compatibility with Apache mod_php
|
||||
=================================
|
||||
|
||||
LSAPI PHP supports PHP configuration overridden via web server configuration
|
||||
as well as .htaccess.
|
||||
Since 4.0 release "apache_response_headers" function is supported.
|
||||
|
||||
|
||||
|
||||
Contact
|
||||
=======
|
||||
|
||||
For support questions, please post to our free support forum, at:
|
||||
|
||||
http://www.litespeedtech.com/forum/
|
||||
|
||||
For bug report, please send bug report to bug [at] litespeedtech.com.
|
||||
|
||||
|
||||
|
||||
|
36
sapi/litespeed/config.m4
Normal file
36
sapi/litespeed/config.m4
Normal file
@ -0,0 +1,36 @@
|
||||
dnl
|
||||
dnl $Id$
|
||||
dnl
|
||||
|
||||
AC_MSG_CHECKING(for LiteSpeed support)
|
||||
|
||||
AC_ARG_WITH(litespeed,
|
||||
[ --with-litespeed Build PHP as litespeed module],
|
||||
[
|
||||
PHP_SAPI_LITESPEED=$withval
|
||||
],[
|
||||
PHP_SAPI_LITESPEED=no
|
||||
])
|
||||
|
||||
if test "$PHP_SAPI_LITESPEED" != "no"; then
|
||||
PHP_ADD_MAKEFILE_FRAGMENT($abs_srcdir/sapi/litespeed/Makefile.frag,$abs_srcdir/sapi/litespeed,sapi/litespeed)
|
||||
SAPI_LITESPEED_PATH=sapi/litespeed/php
|
||||
PHP_SUBST(SAPI_LITESPEED_PATH)
|
||||
PHP_SELECT_SAPI(litespeed, program, lsapi_main.c lsapilib.c, "", '$(SAPI_LITESPEED_PATH)')
|
||||
case $host_alias in
|
||||
*darwin*)
|
||||
BUILD_LITESPEED="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_SAPI_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_LITESPEED_PATH)"
|
||||
;;
|
||||
*cygwin*)
|
||||
SAPI_LITESPEED_PATH=sapi/litespeed/php.exe
|
||||
BUILD_LITESPEED="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_SAPI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_LITESPEED_PATH)"
|
||||
;;
|
||||
*)
|
||||
BUILD_LITESPEED="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_SAPI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_LITESPEED_PATH)"
|
||||
;;
|
||||
esac
|
||||
|
||||
PHP_SUBST(BUILD_LITESPEED)
|
||||
fi
|
||||
|
||||
AC_MSG_RESULT($PHP_SAPI_LITESPEED)
|
908
sapi/litespeed/lsapi_main.c
Normal file
908
sapi/litespeed/lsapi_main.c
Normal file
@ -0,0 +1,908 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2007 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available at through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt. |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: George Wang <gwang@litespeedtech.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
|
||||
#include "php.h"
|
||||
#include "SAPI.h"
|
||||
#include "php_main.h"
|
||||
#include "php_ini.h"
|
||||
#include "php_variables.h"
|
||||
#include "zend_highlight.h"
|
||||
#include "zend.h"
|
||||
|
||||
#include "lsapilib.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#if HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#include "win32/php_registry.h"
|
||||
|
||||
#else
|
||||
|
||||
#include <sys/wait.h>
|
||||
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if HAVE_SYS_TYPES_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#endif
|
||||
|
||||
#if HAVE_SIGNAL_H
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#endif
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
|
||||
#define SAPI_LSAPI_MAX_HEADER_LENGTH 2048
|
||||
|
||||
static int lsapi_mode = 1;
|
||||
static char *php_self = "";
|
||||
static char *script_filename = "";
|
||||
static int source_highlight = 0;
|
||||
|
||||
#ifdef ZTS
|
||||
zend_compiler_globals *compiler_globals;
|
||||
zend_executor_globals *executor_globals;
|
||||
php_core_globals *core_globals;
|
||||
sapi_globals_struct *sapi_globals;
|
||||
void ***tsrm_ls;
|
||||
#endif
|
||||
|
||||
zend_module_entry litespeed_module_entry;
|
||||
|
||||
/* {{{ php_lsapi_startup
|
||||
*/
|
||||
static int php_lsapi_startup(sapi_module_struct *sapi_module)
|
||||
{
|
||||
if (php_module_startup(sapi_module, NULL, 0)==FAILURE) {
|
||||
return FAILURE;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
|
||||
/* {{{ sapi_lsapi_ub_write
|
||||
*/
|
||||
static int sapi_lsapi_ub_write(const char *str, uint str_length TSRMLS_DC)
|
||||
{
|
||||
int ret;
|
||||
int remain;
|
||||
if ( lsapi_mode ) {
|
||||
ret = LSAPI_Write( str, str_length );
|
||||
if ( ret < str_length ) {
|
||||
php_handle_aborted_connection();
|
||||
return str_length - ret;
|
||||
}
|
||||
} else {
|
||||
remain = str_length;
|
||||
while( remain > 0 ) {
|
||||
ret = write( 1, str, remain );
|
||||
if ( ret <= 0 ) {
|
||||
php_handle_aborted_connection();
|
||||
return str_length - remain;
|
||||
}
|
||||
str += ret;
|
||||
remain -= ret;
|
||||
}
|
||||
}
|
||||
return str_length;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ sapi_lsapi_flush
|
||||
*/
|
||||
static void sapi_lsapi_flush( void * server_context )
|
||||
{
|
||||
if ( lsapi_mode ) {
|
||||
if ( LSAPI_Flush() == -1) {
|
||||
php_handle_aborted_connection();
|
||||
}
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ sapi_lsapi_deactivate
|
||||
*/
|
||||
static int sapi_lsapi_deactivate(TSRMLS_D)
|
||||
{
|
||||
LSAPI_Finish();
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
|
||||
|
||||
/* {{{ sapi_lsapi_getenv
|
||||
*/
|
||||
static char *sapi_lsapi_getenv( char * name, size_t name_len TSRMLS_DC )
|
||||
{
|
||||
if ( lsapi_mode ) {
|
||||
return LSAPI_GetEnv( name );
|
||||
} else {
|
||||
return getenv( name );
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
|
||||
static int add_variable( const char * pKey, int keyLen, const char * pValue, int valLen,
|
||||
void * arg )
|
||||
{
|
||||
php_register_variable_safe((char *)pKey, (char *)pValue, valLen, (zval *)arg TSRMLS_CC);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* {{{ sapi_lsapi_register_variables
|
||||
*/
|
||||
static void sapi_lsapi_register_variables(zval *track_vars_array TSRMLS_DC)
|
||||
{
|
||||
|
||||
if ( lsapi_mode ) {
|
||||
LSAPI_ForeachHeader( add_variable, track_vars_array );
|
||||
LSAPI_ForeachEnv( add_variable, track_vars_array );
|
||||
php_import_environment_variables(track_vars_array TSRMLS_CC);
|
||||
|
||||
php_register_variable("PHP_SELF", (SG(request_info).request_uri ? SG(request_info).request_uri:""), track_vars_array TSRMLS_CC);
|
||||
} else {
|
||||
php_import_environment_variables(track_vars_array TSRMLS_CC);
|
||||
|
||||
php_register_variable("PHP_SELF", php_self, track_vars_array TSRMLS_CC);
|
||||
php_register_variable("SCRIPT_NAME", php_self, track_vars_array TSRMLS_CC);
|
||||
php_register_variable("SCRIPT_FILENAME", script_filename, track_vars_array TSRMLS_CC);
|
||||
php_register_variable("PATH_TRANSLATED", script_filename, track_vars_array TSRMLS_CC);
|
||||
php_register_variable("DOCUMENT_ROOT", "", track_vars_array TSRMLS_CC);
|
||||
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ sapi_lsapi_read_post
|
||||
*/
|
||||
static int sapi_lsapi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
|
||||
{
|
||||
if ( lsapi_mode ) {
|
||||
return LSAPI_ReadReqBody( buffer, count_bytes );
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
|
||||
|
||||
/* {{{ sapi_lsapi_read_cookies
|
||||
*/
|
||||
static char *sapi_lsapi_read_cookies(TSRMLS_D)
|
||||
{
|
||||
if ( lsapi_mode ) {
|
||||
return LSAPI_GetHeader( H_COOKIE );
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ sapi_lsapi_send_headers
|
||||
*/
|
||||
static int sapi_lsapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
|
||||
{
|
||||
sapi_header_struct *h;
|
||||
zend_llist_position pos;
|
||||
if ( lsapi_mode ) {
|
||||
LSAPI_SetRespStatus( SG(sapi_headers).http_response_code );
|
||||
|
||||
h = zend_llist_get_first_ex(&sapi_headers->headers, &pos);
|
||||
while (h) {
|
||||
if ( h->header_len > 0 ) {
|
||||
LSAPI_AppendRespHeader(h->header, h->header_len);
|
||||
}
|
||||
h = zend_llist_get_next_ex(&sapi_headers->headers, &pos);
|
||||
}
|
||||
if (SG(sapi_headers).send_default_content_type) {
|
||||
char *hd;
|
||||
int len;
|
||||
char headerBuf[SAPI_LSAPI_MAX_HEADER_LENGTH];
|
||||
|
||||
hd = sapi_get_default_content_type(TSRMLS_C);
|
||||
len = snprintf( headerBuf, SAPI_LSAPI_MAX_HEADER_LENGTH - 1,
|
||||
"Content-type: %s", hd );
|
||||
efree(hd);
|
||||
|
||||
LSAPI_AppendRespHeader( headerBuf, len );
|
||||
}
|
||||
}
|
||||
LSAPI_FinalizeRespHeaders();
|
||||
return SAPI_HEADER_SENT_SUCCESSFULLY;
|
||||
|
||||
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ sapi_lsapi_send_headers
|
||||
*/
|
||||
static void sapi_lsapi_log_message(char *message)
|
||||
{
|
||||
int len = strlen( message );
|
||||
LSAPI_Write_Stderr( message, len);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ sapi_module_struct cgi_sapi_module
|
||||
*/
|
||||
static sapi_module_struct lsapi_sapi_module =
|
||||
{
|
||||
"litespeed",
|
||||
"LiteSpeed",
|
||||
|
||||
php_lsapi_startup, /* startup */
|
||||
php_module_shutdown_wrapper, /* shutdown */
|
||||
|
||||
NULL, /* activate */
|
||||
sapi_lsapi_deactivate, /* deactivate */
|
||||
|
||||
sapi_lsapi_ub_write, /* unbuffered write */
|
||||
sapi_lsapi_flush, /* flush */
|
||||
NULL, /* get uid */
|
||||
sapi_lsapi_getenv, /* getenv */
|
||||
|
||||
php_error, /* error handler */
|
||||
|
||||
NULL, /* header handler */
|
||||
sapi_lsapi_send_headers, /* send headers handler */
|
||||
NULL, /* send header handler */
|
||||
|
||||
sapi_lsapi_read_post, /* read POST data */
|
||||
sapi_lsapi_read_cookies, /* read Cookies */
|
||||
|
||||
sapi_lsapi_register_variables, /* register server variables */
|
||||
sapi_lsapi_log_message, /* Log message */
|
||||
|
||||
NULL, /* php.ini path override */
|
||||
NULL, /* block interruptions */
|
||||
NULL, /* unblock interruptions */
|
||||
NULL, /* default post reader */
|
||||
NULL, /* treat data */
|
||||
NULL, /* executable location */
|
||||
|
||||
0, /* php.ini ignore */
|
||||
|
||||
STANDARD_SAPI_MODULE_PROPERTIES
|
||||
|
||||
};
|
||||
/* }}} */
|
||||
|
||||
static int init_request_info( TSRMLS_D )
|
||||
{
|
||||
char * pContentType = LSAPI_GetHeader( H_CONTENT_TYPE );
|
||||
char * pAuth;
|
||||
|
||||
SG(request_info).content_type = pContentType ? pContentType : "";
|
||||
SG(request_info).request_method = LSAPI_GetRequestMethod();
|
||||
SG(request_info).query_string = LSAPI_GetQueryString();
|
||||
SG(request_info).request_uri = LSAPI_GetScriptName();
|
||||
SG(request_info).content_length = LSAPI_GetReqBodyLen();
|
||||
SG(request_info).path_translated = LSAPI_GetScriptFileName();
|
||||
|
||||
/* It is not reset by zend engine, set it to 0. */
|
||||
SG(sapi_headers).http_response_code = 0;
|
||||
|
||||
pAuth = LSAPI_GetHeader( H_AUTHORIZATION );
|
||||
php_handle_auth_data(pAuth TSRMLS_CC);
|
||||
}
|
||||
|
||||
static int lsapi_module_main(int show_source TSRMLS_DC)
|
||||
{
|
||||
zend_file_handle file_handle = {0};
|
||||
|
||||
if (php_request_startup(TSRMLS_C) == FAILURE ) {
|
||||
return -1;
|
||||
}
|
||||
if (show_source) {
|
||||
zend_syntax_highlighter_ini syntax_highlighter_ini;
|
||||
|
||||
php_get_highlight_struct(&syntax_highlighter_ini);
|
||||
highlight_file(SG(request_info).path_translated, &syntax_highlighter_ini TSRMLS_CC);
|
||||
} else {
|
||||
file_handle.type = ZEND_HANDLE_FILENAME;
|
||||
file_handle.handle.fd = 0;
|
||||
file_handle.filename = SG(request_info).path_translated;
|
||||
file_handle.free_filename = 0;
|
||||
file_handle.opened_path = NULL;
|
||||
|
||||
php_execute_script(&file_handle TSRMLS_CC);
|
||||
}
|
||||
zend_try {
|
||||
php_request_shutdown(NULL);
|
||||
} zend_end_try();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int alter_ini( const char * pKey, int keyLen, const char * pValue, int valLen,
|
||||
void * arg )
|
||||
{
|
||||
int type = ZEND_INI_PERDIR;
|
||||
if ( '\001' == *pKey ) {
|
||||
++pKey;
|
||||
if ( *pKey == 4 ) {
|
||||
type = ZEND_INI_SYSTEM;
|
||||
}
|
||||
++pKey;
|
||||
--keyLen;
|
||||
zend_alter_ini_entry((char *)pKey, keyLen,
|
||||
(char *)pValue, valLen,
|
||||
type, PHP_INI_STAGE_ACTIVATE);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void override_ini()
|
||||
{
|
||||
|
||||
LSAPI_ForeachSpecialEnv( alter_ini, NULL );
|
||||
|
||||
}
|
||||
|
||||
static int processReq( TSRMLS_D )
|
||||
{
|
||||
int ret = 0;
|
||||
zend_first_try {
|
||||
/* avoid server_context==NULL checks */
|
||||
SG(server_context) = (void *) 1;
|
||||
|
||||
init_request_info( TSRMLS_C );
|
||||
|
||||
override_ini();
|
||||
|
||||
if ( lsapi_module_main( source_highlight TSRMLS_CC ) == -1 ) {
|
||||
ret = -1;
|
||||
}
|
||||
} zend_end_try();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cli_usage( TSRMLS_D )
|
||||
{
|
||||
static const char * usage =
|
||||
"Usage: php\n"
|
||||
" php -[b|c|h|i|q|s|v|?] [<file>] [args...]\n"
|
||||
" Run in LSAPI mode, only '-b', '-s' and '-c' are effective\n"
|
||||
" Run in Command Line Interpreter mode when parameters are specified\n"
|
||||
"\n"
|
||||
" -b <address:port>|<port> Bind Path for external LSAPI Server mode\n"
|
||||
" -c <path>|<file> Look for php.ini file in this directory\n"
|
||||
" -h This help\n"
|
||||
" -i PHP information\n"
|
||||
" -q Quiet-mode. Suppress HTTP Header output.\n"
|
||||
" -s Display colour syntax highlighted source.\n"
|
||||
" -v Version number\n"
|
||||
" -? This help\n"
|
||||
"\n"
|
||||
" args... Arguments passed to script.\n";
|
||||
php_output_startup();
|
||||
php_output_activate(TSRMLS_C);
|
||||
php_printf( usage );
|
||||
#ifdef PHP_OUTPUT_NEWAPI
|
||||
php_output_end_all(TSRMLS_C);
|
||||
#else
|
||||
php_end_ob_buffers(1 TSRMLS_CC);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int parse_opt( int argc, char * argv[], int *climode,
|
||||
char **php_ini_path, char ** php_bind )
|
||||
{
|
||||
char ** p = &argv[1];
|
||||
char ** argend= &argv[argc];
|
||||
int c;
|
||||
while (( p < argend )&&(**p == '-' )) {
|
||||
c = *((*p)+1);
|
||||
++p;
|
||||
switch( c ) {
|
||||
case 'b':
|
||||
if ( p >= argend ) {
|
||||
fprintf( stderr, "TCP or socket address must be specified following '-b' option.\n");
|
||||
return -1;
|
||||
}
|
||||
*php_bind = *p++;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
if ( p >= argend ) {
|
||||
fprintf( stderr, "<path> or <file> must be specified following '-c' option.\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
*php_ini_path = *p++;
|
||||
break;
|
||||
case 's':
|
||||
source_highlight = 1;
|
||||
break;
|
||||
case 'h':
|
||||
case 'i':
|
||||
case 'q':
|
||||
case 'v':
|
||||
case '?':
|
||||
default:
|
||||
*climode = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( p - argv < argc ) {
|
||||
*climode = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cli_main( int argc, char * argv[] )
|
||||
{
|
||||
|
||||
static const char * ini_defaults[] = {
|
||||
"report_zend_debug", "0",
|
||||
"display_errors", "1",
|
||||
"register_argc_argv", "1",
|
||||
"html_errors", "0",
|
||||
"implicit_flush", "1",
|
||||
"output_buffering", "0",
|
||||
"max_execution_time", "0",
|
||||
NULL
|
||||
};
|
||||
|
||||
const char ** ini;
|
||||
char ** p = &argv[1];
|
||||
char ** argend= &argv[argc];
|
||||
int ret = 0;
|
||||
int c;
|
||||
lsapi_mode = 0; /* enter CLI mode */
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
_fmode = _O_BINARY; /*sets default for file streams to binary */
|
||||
setmode(_fileno(stdin), O_BINARY); /* make the stdio mode be binary */
|
||||
setmode(_fileno(stdout), O_BINARY); /* make the stdio mode be binary */
|
||||
setmode(_fileno(stderr), O_BINARY); /* make the stdio mode be binary */
|
||||
#endif
|
||||
|
||||
zend_first_try {
|
||||
SG(server_context) = (void *) 1;
|
||||
|
||||
zend_uv.html_errors = 0; /* tell the engine we're in non-html mode */
|
||||
CG(in_compilation) = 0; /* not initialized but needed for several options */
|
||||
EG(uninitialized_zval_ptr) = NULL;
|
||||
|
||||
for( ini = ini_defaults; *ini; ini+=2 ) {
|
||||
zend_alter_ini_entry( (char *)*ini, strlen( *ini )+1,
|
||||
(char *)*(ini+1), strlen( *(ini+1) ),
|
||||
PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
|
||||
}
|
||||
|
||||
while (( p < argend )&&(**p == '-' )) {
|
||||
c = *((*p)+1);
|
||||
++p;
|
||||
switch( c ) {
|
||||
case 'q':
|
||||
break;
|
||||
case 'i':
|
||||
if (php_request_startup(TSRMLS_C) != FAILURE) {
|
||||
php_print_info(0xFFFFFFFF TSRMLS_CC);
|
||||
#ifdef PHP_OUTPUT_NEWAPI
|
||||
php_output_end_all(TSRMLS_C);
|
||||
#else
|
||||
php_end_ob_buffers(1 TSRMLS_CC);
|
||||
#endif
|
||||
php_request_shutdown( NULL );
|
||||
}
|
||||
ret = 1;
|
||||
break;
|
||||
case 'v':
|
||||
if (php_request_startup(TSRMLS_C) != FAILURE) {
|
||||
#if ZEND_DEBUG
|
||||
php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
|
||||
#else
|
||||
php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
|
||||
#endif
|
||||
#ifdef PHP_OUTPUT_NEWAPI
|
||||
php_output_end_all(TSRMLS_C);
|
||||
#else
|
||||
php_end_ob_buffers(1 TSRMLS_CC);
|
||||
#endif
|
||||
php_request_shutdown( NULL );
|
||||
}
|
||||
ret = 1;
|
||||
break;
|
||||
case 'c':
|
||||
++p;
|
||||
/* fall through */
|
||||
case 's':
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
case '?':
|
||||
default:
|
||||
cli_usage(TSRMLS_C);
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
if ( !ret ) {
|
||||
if ( *p ) {
|
||||
zend_file_handle file_handle = {0};
|
||||
|
||||
file_handle.type = ZEND_HANDLE_FP;
|
||||
file_handle.handle.fp = VCWD_FOPEN(*p, "rb");
|
||||
|
||||
if ( file_handle.handle.fp ) {
|
||||
script_filename = *p;
|
||||
php_self = *p;
|
||||
|
||||
SG(request_info).path_translated = *p;
|
||||
SG(request_info).argc = argc - (p - argv);
|
||||
SG(request_info).argv = p;
|
||||
|
||||
if (php_request_startup(TSRMLS_C) == FAILURE ) {
|
||||
fclose( file_handle.handle.fp );
|
||||
ret = 2;
|
||||
} else {
|
||||
if (source_highlight) {
|
||||
zend_syntax_highlighter_ini syntax_highlighter_ini;
|
||||
|
||||
php_get_highlight_struct(&syntax_highlighter_ini);
|
||||
highlight_file(SG(request_info).path_translated, &syntax_highlighter_ini TSRMLS_CC);
|
||||
} else {
|
||||
file_handle.filename = *p;
|
||||
file_handle.free_filename = 0;
|
||||
file_handle.opened_path = NULL;
|
||||
|
||||
php_execute_script(&file_handle TSRMLS_CC);
|
||||
}
|
||||
|
||||
php_request_shutdown( NULL );
|
||||
}
|
||||
} else {
|
||||
php_printf("Could not open input file: %s.\n", *p);
|
||||
}
|
||||
} else {
|
||||
cli_usage(TSRMLS_C);
|
||||
}
|
||||
}
|
||||
|
||||
}zend_end_try();
|
||||
|
||||
php_module_shutdown(TSRMLS_C);
|
||||
|
||||
#ifdef ZTS
|
||||
tsrm_shutdown();
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int s_stop;
|
||||
void litespeed_cleanup(int signal)
|
||||
{
|
||||
s_stop = signal;
|
||||
}
|
||||
|
||||
|
||||
void start_children( int children )
|
||||
{
|
||||
struct sigaction act, old_term, old_quit, old_int, old_usr1;
|
||||
int running = 0;
|
||||
int status;
|
||||
pid_t pid;
|
||||
|
||||
/* Create a process group */
|
||||
setsid();
|
||||
|
||||
/* Set up handler to kill children upon exit */
|
||||
act.sa_flags = 0;
|
||||
act.sa_handler = litespeed_cleanup;
|
||||
if( sigaction( SIGTERM, &act, &old_term ) ||
|
||||
sigaction( SIGINT, &act, &old_int ) ||
|
||||
sigaction( SIGUSR1, &act, &old_usr1 ) ||
|
||||
sigaction( SIGQUIT, &act, &old_quit )) {
|
||||
perror( "Can't set signals" );
|
||||
exit( 1 );
|
||||
}
|
||||
s_stop = 0;
|
||||
while( 1 ) {
|
||||
while((!s_stop )&&( running < children )) {
|
||||
pid = fork();
|
||||
switch( pid ) {
|
||||
case 0: /* children process */
|
||||
|
||||
/* don't catch our signals */
|
||||
sigaction( SIGTERM, &old_term, 0 );
|
||||
sigaction( SIGQUIT, &old_quit, 0 );
|
||||
sigaction( SIGINT, &old_int, 0 );
|
||||
sigaction( SIGUSR1, &old_usr1, 0 );
|
||||
return ;
|
||||
case -1:
|
||||
perror( "php (pre-forking)" );
|
||||
exit( 1 );
|
||||
break;
|
||||
default: /* parent process */
|
||||
running++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( s_stop ) {
|
||||
break;
|
||||
}
|
||||
pid = wait( &status );
|
||||
running--;
|
||||
}
|
||||
kill( -getpgrp(), SIGUSR1 );
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include <fcntl.h>
|
||||
int main( int argc, char * argv[] )
|
||||
{
|
||||
int ret;
|
||||
int bindFd;
|
||||
|
||||
char * php_ini_path = NULL;
|
||||
char * php_bind = NULL;
|
||||
char * p;
|
||||
int n;
|
||||
int climode = 0;
|
||||
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#if defined(SIGPIPE) && defined(SIG_IGN)
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ZTS
|
||||
tsrm_startup(1, 1, 0, NULL);
|
||||
#endif
|
||||
|
||||
if (argc > 1 ) {
|
||||
if ( parse_opt( argc, argv, &climode,
|
||||
&php_ini_path, &php_bind ) == -1 ) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if ( climode ) {
|
||||
lsapi_sapi_module.phpinfo_as_text = 1;
|
||||
}
|
||||
sapi_startup(&lsapi_sapi_module);
|
||||
|
||||
#ifdef ZTS
|
||||
compiler_globals = ts_resource(compiler_globals_id);
|
||||
executor_globals = ts_resource(executor_globals_id);
|
||||
core_globals = ts_resource(core_globals_id);
|
||||
sapi_globals = ts_resource(sapi_globals_id);
|
||||
tsrm_ls = ts_resource(0);
|
||||
|
||||
SG(request_info).path_translated = NULL;
|
||||
#endif
|
||||
|
||||
lsapi_sapi_module.executable_location = argv[0];
|
||||
|
||||
if ( php_ini_path ) {
|
||||
lsapi_sapi_module.php_ini_path_override = php_ini_path;
|
||||
}
|
||||
|
||||
if (php_module_startup(&lsapi_sapi_module, &litespeed_module_entry, 1) == FAILURE) {
|
||||
#ifdef ZTS
|
||||
tsrm_shutdown();
|
||||
#endif
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if ( climode ) {
|
||||
return cli_main(argc, argv);
|
||||
}
|
||||
|
||||
|
||||
if ( php_bind ) {
|
||||
bindFd = LSAPI_CreateListenSock( php_bind, 10 );
|
||||
if ( bindFd == -1 ) {
|
||||
fprintf( stderr,
|
||||
"Failed to bind socket [%s]: %s\n", php_bind, strerror( errno ) );
|
||||
exit( 2 );
|
||||
}
|
||||
if ( bindFd != 0 ) {
|
||||
dup2( bindFd, 0 );
|
||||
close( bindFd );
|
||||
}
|
||||
}
|
||||
|
||||
LSAPI_Init();
|
||||
|
||||
LSAPI_Init_Env_Parameters( NULL );
|
||||
|
||||
if ( php_bind ) {
|
||||
LSAPI_No_Check_ppid();
|
||||
}
|
||||
|
||||
while( LSAPI_Prefork_Accept_r( &g_req ) >= 0 ) {
|
||||
ret = processReq(TSRMLS_C);
|
||||
LSAPI_Finish();
|
||||
if ( ret ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
php_module_shutdown(TSRMLS_C);
|
||||
|
||||
#ifdef ZTS
|
||||
tsrm_shutdown();
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* LiteSpeed PHP module starts here */
|
||||
|
||||
|
||||
|
||||
PHP_FUNCTION(litespeed_request_headers);
|
||||
PHP_FUNCTION(litespeed_response_headers);
|
||||
|
||||
PHP_MINFO_FUNCTION(litespeed);
|
||||
|
||||
zend_function_entry litespeed_functions[] = {
|
||||
PHP_FE(litespeed_request_headers, NULL)
|
||||
PHP_FE(litespeed_response_headers, NULL)
|
||||
PHP_FALIAS(getallheaders, litespeed_request_headers, NULL)
|
||||
PHP_FALIAS(apache_request_headers, litespeed_request_headers, NULL)
|
||||
PHP_FALIAS(apache_response_headers, litespeed_response_headers, NULL)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
static PHP_MINIT_FUNCTION(litespeed)
|
||||
{
|
||||
//REGISTER_INI_ENTRIES();
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static PHP_MSHUTDOWN_FUNCTION(litespeed)
|
||||
{
|
||||
//UNREGISTER_INI_ENTRIES();
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
zend_module_entry litespeed_module_entry = {
|
||||
STANDARD_MODULE_HEADER,
|
||||
"litespeed",
|
||||
litespeed_functions,
|
||||
PHP_MINIT(litespeed),
|
||||
PHP_MSHUTDOWN(litespeed),
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NO_VERSION_YET,
|
||||
STANDARD_MODULE_PROPERTIES
|
||||
};
|
||||
|
||||
static int add_associate_array( const char * pKey, int keyLen, const char * pValue, int valLen,
|
||||
void * arg )
|
||||
{
|
||||
add_assoc_string_ex( (zval *)arg, (char *)pKey, keyLen+1, (char *)pValue, 1 );
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* {{{ proto array litespeed_request_headers(void)
|
||||
Fetch all HTTP request headers */
|
||||
PHP_FUNCTION(litespeed_request_headers)
|
||||
{
|
||||
//TODO:
|
||||
if (ZEND_NUM_ARGS() > 0) {
|
||||
WRONG_PARAM_COUNT;
|
||||
}
|
||||
array_init(return_value);
|
||||
|
||||
LSAPI_ForeachOrgHeader( add_associate_array, return_value );
|
||||
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
|
||||
/* {{{ proto array litespeed_response_headers(void)
|
||||
Fetch all HTTP response headers */
|
||||
PHP_FUNCTION(litespeed_response_headers)
|
||||
{
|
||||
sapi_header_struct *h;
|
||||
zend_llist_position pos;
|
||||
char * p;
|
||||
int len;
|
||||
char headerBuf[SAPI_LSAPI_MAX_HEADER_LENGTH];
|
||||
|
||||
if (ZEND_NUM_ARGS() > 0) {
|
||||
WRONG_PARAM_COUNT;
|
||||
}
|
||||
|
||||
if (!&SG(sapi_headers).headers) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
array_init(return_value);
|
||||
|
||||
h = zend_llist_get_first_ex(&SG(sapi_headers).headers, &pos);
|
||||
while (h) {
|
||||
if ( h->header_len > 0 ) {
|
||||
p = strchr( h->header, ':' );
|
||||
len = p - h->header;
|
||||
if (( p )&&( len > 0 )) {
|
||||
memmove( headerBuf, h->header, len );
|
||||
while( len > 0 && (isspace( headerBuf[len-1])) ) {
|
||||
--len;
|
||||
}
|
||||
headerBuf[len] = 0;
|
||||
if ( len ) {
|
||||
while( isspace(*++p));
|
||||
add_assoc_string_ex(return_value, headerBuf, len+1, p, 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
h = zend_llist_get_next_ex(&SG(sapi_headers).headers, &pos);
|
||||
}
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
* vim600: sw=4 ts=4 fdm=marker
|
||||
* vim<600: sw=4 ts=4
|
||||
*/
|
||||
|
||||
|
196
sapi/litespeed/lsapidef.h
Normal file
196
sapi/litespeed/lsapidef.h
Normal file
@ -0,0 +1,196 @@
|
||||
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2007 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available at through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt. |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: George Wang <gwang@litespeedtech.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Copyright (c) 2007, Lite Speed Technologies Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
* Neither the name of the Lite Speed Technologies Inc nor the
|
||||
names of its contributors may be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _LSAPIDEF_H_
|
||||
#define _LSAPIDEF_H_
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#if defined (c_plusplus) || defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
H_ACCEPT = 0,
|
||||
H_ACC_CHARSET,
|
||||
H_ACC_ENCODING,
|
||||
H_ACC_LANG,
|
||||
H_AUTHORIZATION,
|
||||
H_CONNECTION,
|
||||
H_CONTENT_TYPE,
|
||||
H_CONTENT_LENGTH,
|
||||
H_COOKIE,
|
||||
H_COOKIE2,
|
||||
H_HOST,
|
||||
H_PRAGMA,
|
||||
H_REFERER,
|
||||
H_USERAGENT,
|
||||
H_CACHE_CTRL,
|
||||
H_IF_MODIFIED_SINCE,
|
||||
H_IF_MATCH,
|
||||
H_IF_NO_MATCH,
|
||||
H_IF_RANGE,
|
||||
H_IF_UNMOD_SINCE,
|
||||
H_KEEP_ALIVE,
|
||||
H_RANGE,
|
||||
H_X_FORWARDED_FOR,
|
||||
H_VIA,
|
||||
H_TRANSFER_ENCODING
|
||||
|
||||
};
|
||||
#define LSAPI_SOCK_FILENO 0
|
||||
|
||||
#define LSAPI_VERSION_B0 'L'
|
||||
#define LSAPI_VERSION_B1 'S'
|
||||
|
||||
/* Values for m_flag in lsapi_packet_header */
|
||||
#define LSAPI_ENDIAN_LITTLE 0
|
||||
#define LSAPI_ENDIAN_BIG 1
|
||||
#define LSAPI_ENDIAN_BIT 1
|
||||
|
||||
#if defined(__i386__)||defined( __x86_64 )||defined( __x86_64__ )
|
||||
#define LSAPI_ENDIAN LSAPI_ENDIAN_LITTLE
|
||||
#else
|
||||
#define LSAPI_ENDIAN LSAPI_ENDIAN_BIG
|
||||
#endif
|
||||
|
||||
/* Values for m_type in lsapi_packet_header */
|
||||
#define LSAPI_BEGIN_REQUEST 1
|
||||
#define LSAPI_ABORT_REQUEST 2
|
||||
#define LSAPI_RESP_HEADER 3
|
||||
#define LSAPI_RESP_STREAM 4
|
||||
#define LSAPI_RESP_END 5
|
||||
#define LSAPI_STDERR_STREAM 6
|
||||
#define LSAPI_REQ_RECEIVED 7
|
||||
|
||||
|
||||
#define LSAPI_MAX_HEADER_LEN 65535
|
||||
#define LSAPI_MAX_DATA_PACKET_LEN 16384
|
||||
|
||||
#define LSAPI_RESP_HTTP_HEADER_MAX 4096
|
||||
#define LSAPI_PACKET_HEADER_LEN 8
|
||||
|
||||
|
||||
struct lsapi_packet_header
|
||||
{
|
||||
char m_versionB0; /* LSAPI protocol version */
|
||||
char m_versionB1;
|
||||
char m_type;
|
||||
char m_flag;
|
||||
union
|
||||
{
|
||||
int32_t m_iLen; /* include this header */
|
||||
char m_bytes[4];
|
||||
}m_packetLen;
|
||||
};
|
||||
|
||||
/*
|
||||
LSAPI request header packet
|
||||
|
||||
1. struct lsapi_req_header
|
||||
2. struct lsapi_http_header_index
|
||||
3. lsapi_header_offset * unknownHeaders
|
||||
4. org http request header
|
||||
5. request body if available
|
||||
*/
|
||||
|
||||
struct lsapi_req_header
|
||||
{
|
||||
struct lsapi_packet_header m_pktHeader;
|
||||
|
||||
int32_t m_httpHeaderLen;
|
||||
int32_t m_reqBodyLen;
|
||||
int32_t m_scriptFileOff; /* path to the script file. */
|
||||
int32_t m_scriptNameOff; /* decrypted URI, without pathinfo, */
|
||||
int32_t m_queryStringOff; /* Query string inside env */
|
||||
int32_t m_requestMethodOff;
|
||||
int32_t m_cntUnknownHeaders;
|
||||
int32_t m_cntEnv;
|
||||
int32_t m_cntSpecialEnv;
|
||||
} ;
|
||||
|
||||
|
||||
struct lsapi_http_header_index
|
||||
{
|
||||
int16_t m_headerLen[H_TRANSFER_ENCODING+1];
|
||||
int32_t m_headerOff[H_TRANSFER_ENCODING+1];
|
||||
} ;
|
||||
|
||||
struct lsapi_header_offset
|
||||
{
|
||||
int32_t nameOff;
|
||||
int32_t nameLen;
|
||||
int32_t valueOff;
|
||||
int32_t valueLen;
|
||||
} ;
|
||||
|
||||
struct lsapi_resp_info
|
||||
{
|
||||
int32_t m_cntHeaders;
|
||||
int32_t m_status;
|
||||
};
|
||||
|
||||
struct lsapi_resp_header
|
||||
{
|
||||
struct lsapi_packet_header m_pktHeader;
|
||||
struct lsapi_resp_info m_respInfo;
|
||||
};
|
||||
|
||||
#if defined (c_plusplus) || defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
2177
sapi/litespeed/lsapilib.c
Normal file
2177
sapi/litespeed/lsapilib.c
Normal file
File diff suppressed because it is too large
Load Diff
358
sapi/litespeed/lsapilib.h
Normal file
358
sapi/litespeed/lsapilib.h
Normal file
@ -0,0 +1,358 @@
|
||||
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2007 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available at through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt. |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: George Wang <gwang@litespeedtech.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2007, Lite Speed Technologies Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
* Neither the name of the Lite Speed Technologies Inc nor the
|
||||
names of its contributors may be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _LSAPILIB_H_
|
||||
#define _LSAPILIB_H_
|
||||
|
||||
#if defined (c_plusplus) || defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <lsapidef.h>
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
struct LSAPI_key_value_pair
|
||||
{
|
||||
char * pKey;
|
||||
char * pValue;
|
||||
int keyLen;
|
||||
int valLen;
|
||||
};
|
||||
|
||||
|
||||
#define LSAPI_MAX_RESP_HEADERS 100
|
||||
|
||||
typedef struct lsapi_request
|
||||
{
|
||||
int m_fdListen;
|
||||
int m_fd;
|
||||
|
||||
long m_lLastActive;
|
||||
long m_lReqBegin;
|
||||
|
||||
char * m_pReqBuf;
|
||||
int m_reqBufSize;
|
||||
|
||||
char * m_pRespBuf;
|
||||
char * m_pRespBufEnd;
|
||||
char * m_pRespBufPos;
|
||||
|
||||
char * m_pRespHeaderBuf;
|
||||
char * m_pRespHeaderBufEnd;
|
||||
char * m_pRespHeaderBufPos;
|
||||
|
||||
|
||||
struct iovec * m_pIovec;
|
||||
struct iovec * m_pIovecEnd;
|
||||
struct iovec * m_pIovecCur;
|
||||
struct iovec * m_pIovecToWrite;
|
||||
|
||||
struct lsapi_packet_header * m_respPktHeaderEnd;
|
||||
|
||||
struct lsapi_req_header * m_pHeader;
|
||||
struct LSAPI_key_value_pair * m_pEnvList;
|
||||
struct LSAPI_key_value_pair * m_pSpecialEnvList;
|
||||
int m_envListSize;
|
||||
int m_specialEnvListSize;
|
||||
|
||||
struct lsapi_http_header_index * m_pHeaderIndex;
|
||||
struct lsapi_header_offset * m_pUnknownHeader;
|
||||
|
||||
char * m_pScriptFile;
|
||||
char * m_pScriptName;
|
||||
char * m_pQueryString;
|
||||
char * m_pHttpHeader;
|
||||
char * m_pRequestMethod;
|
||||
int m_totalLen;
|
||||
int m_reqState;
|
||||
int m_reqBodyRead;
|
||||
int m_bufProcessed;
|
||||
int m_bufRead;
|
||||
|
||||
struct lsapi_packet_header m_respPktHeader[5];
|
||||
|
||||
struct lsapi_resp_header m_respHeader;
|
||||
short m_respHeaderLen[LSAPI_MAX_RESP_HEADERS];
|
||||
|
||||
}LSAPI_Request;
|
||||
|
||||
extern LSAPI_Request g_req;
|
||||
|
||||
|
||||
/* return: >0 continue, ==0 stop, -1 failed */
|
||||
typedef int (*LSAPI_CB_EnvHandler )( const char * pKey, int keyLen,
|
||||
const char * pValue, int valLen, void * arg );
|
||||
|
||||
|
||||
int LSAPI_Init(void);
|
||||
|
||||
void LSAPI_Stop(void);
|
||||
|
||||
int LSAPI_Is_Listen_r( LSAPI_Request * pReq);
|
||||
|
||||
int LSAPI_InitRequest( LSAPI_Request * pReq, int fd );
|
||||
|
||||
int LSAPI_Accept_r( LSAPI_Request * pReq );
|
||||
|
||||
void LSAPI_Reset_r( LSAPI_Request * pReq );
|
||||
|
||||
int LSAPI_Finish_r( LSAPI_Request * pReq );
|
||||
|
||||
int LSAPI_Release_r( LSAPI_Request * pReq );
|
||||
|
||||
char * LSAPI_GetHeader_r( LSAPI_Request * pReq, int headerIndex );
|
||||
|
||||
int LSAPI_ForeachHeader_r( LSAPI_Request * pReq,
|
||||
LSAPI_CB_EnvHandler fn, void * arg );
|
||||
|
||||
int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq,
|
||||
LSAPI_CB_EnvHandler fn, void * arg );
|
||||
|
||||
int LSAPI_ForeachEnv_r( LSAPI_Request * pReq,
|
||||
LSAPI_CB_EnvHandler fn, void * arg );
|
||||
|
||||
int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq,
|
||||
LSAPI_CB_EnvHandler fn, void * arg );
|
||||
|
||||
char * LSAPI_GetEnv_r( LSAPI_Request * pReq, const char * name );
|
||||
|
||||
|
||||
int LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, int len );
|
||||
|
||||
int LSAPI_ReqBodyGetChar_r( LSAPI_Request * pReq );
|
||||
|
||||
int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, int bufLen, int *getLF );
|
||||
|
||||
|
||||
int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq );
|
||||
|
||||
int LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, int len );
|
||||
|
||||
int LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, int len );
|
||||
|
||||
int LSAPI_Flush_r( LSAPI_Request * pReq );
|
||||
|
||||
int LSAPI_AppendRespHeader_r( LSAPI_Request * pHeader, char * pBuf, int len );
|
||||
|
||||
static inline int LSAPI_SetRespStatus_r( LSAPI_Request * pReq, int code )
|
||||
{
|
||||
if ( !pReq )
|
||||
return -1;
|
||||
pReq->m_respHeader.m_respInfo.m_status = code;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline char * LSAPI_GetQueryString_r( LSAPI_Request * pReq )
|
||||
{
|
||||
if ( pReq )
|
||||
return pReq->m_pQueryString;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static inline char * LSAPI_GetScriptFileName_r( LSAPI_Request * pReq )
|
||||
{
|
||||
if ( pReq )
|
||||
return pReq->m_pScriptFile;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static inline char * LSAPI_GetScriptName_r( LSAPI_Request * pReq )
|
||||
{
|
||||
if ( pReq )
|
||||
return pReq->m_pScriptName;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static inline char * LSAPI_GetRequestMethod_r( LSAPI_Request * pReq)
|
||||
{
|
||||
if ( pReq )
|
||||
return pReq->m_pRequestMethod;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static inline int LSAPI_GetReqBodyLen_r( LSAPI_Request * pReq )
|
||||
{
|
||||
if ( pReq )
|
||||
return pReq->m_pHeader->m_reqBodyLen;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int LSAPI_GetReqBodyRemain_r( LSAPI_Request * pReq )
|
||||
{
|
||||
if ( pReq )
|
||||
return pReq->m_pHeader->m_reqBodyLen - pReq->m_reqBodyRead;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int LSAPI_Is_Listen(void);
|
||||
|
||||
static inline int LSAPI_Accept( void )
|
||||
{ return LSAPI_Accept_r( &g_req ); }
|
||||
|
||||
static inline int LSAPI_Finish(void)
|
||||
{ return LSAPI_Finish_r( &g_req ); }
|
||||
|
||||
static inline char * LSAPI_GetHeader( int headerIndex )
|
||||
{ return LSAPI_GetHeader_r( &g_req, headerIndex ); }
|
||||
|
||||
static inline int LSAPI_ForeachHeader( LSAPI_CB_EnvHandler fn, void * arg )
|
||||
{ return LSAPI_ForeachHeader_r( &g_req, fn, arg ); }
|
||||
|
||||
static inline int LSAPI_ForeachOrgHeader(
|
||||
LSAPI_CB_EnvHandler fn, void * arg )
|
||||
{ return LSAPI_ForeachOrgHeader_r( &g_req, fn, arg ); }
|
||||
|
||||
static inline int LSAPI_ForeachEnv( LSAPI_CB_EnvHandler fn, void * arg )
|
||||
{ return LSAPI_ForeachEnv_r( &g_req, fn, arg ); }
|
||||
|
||||
static inline int LSAPI_ForeachSpecialEnv( LSAPI_CB_EnvHandler fn, void * arg )
|
||||
{ return LSAPI_ForeachSpecialEnv_r( &g_req, fn, arg ); }
|
||||
|
||||
static inline char * LSAPI_GetEnv( const char * name )
|
||||
{ return LSAPI_GetEnv_r( &g_req, name ); }
|
||||
|
||||
static inline char * LSAPI_GetQueryString()
|
||||
{ return LSAPI_GetQueryString_r( &g_req ); }
|
||||
|
||||
static inline char * LSAPI_GetScriptFileName()
|
||||
{ return LSAPI_GetScriptFileName_r( &g_req ); }
|
||||
|
||||
static inline char * LSAPI_GetScriptName()
|
||||
{ return LSAPI_GetScriptName_r( &g_req ); }
|
||||
|
||||
static inline char * LSAPI_GetRequestMethod()
|
||||
{ return LSAPI_GetRequestMethod_r( &g_req ); }
|
||||
|
||||
static inline int LSAPI_GetReqBodyLen()
|
||||
{ return LSAPI_GetReqBodyLen_r( &g_req ); }
|
||||
|
||||
static inline int LSAPI_GetReqBodyRemain()
|
||||
{ return LSAPI_GetReqBodyRemain_r( &g_req ); }
|
||||
|
||||
static inline int LSAPI_ReadReqBody( char * pBuf, int len )
|
||||
{ return LSAPI_ReadReqBody_r( &g_req, pBuf, len ); }
|
||||
|
||||
static inline int LSAPI_ReqBodyGetChar()
|
||||
{ return LSAPI_ReqBodyGetChar_r( &g_req ); }
|
||||
|
||||
static inline int LSAPI_ReqBodyGetLine( char * pBuf, int len, int *getLF )
|
||||
{ return LSAPI_ReqBodyGetLine_r( &g_req, pBuf, len, getLF ); }
|
||||
|
||||
|
||||
|
||||
static inline int LSAPI_FinalizeRespHeaders(void)
|
||||
{ return LSAPI_FinalizeRespHeaders_r( &g_req ); }
|
||||
|
||||
static inline int LSAPI_Write( const char * pBuf, int len )
|
||||
{ return LSAPI_Write_r( &g_req, pBuf, len ); }
|
||||
|
||||
static inline int LSAPI_Write_Stderr( const char * pBuf, int len )
|
||||
{ return LSAPI_Write_Stderr_r( &g_req, pBuf, len ); }
|
||||
|
||||
static inline int LSAPI_Flush()
|
||||
{ return LSAPI_Flush_r( &g_req ); }
|
||||
|
||||
static inline int LSAPI_AppendRespHeader( char * pBuf, int len )
|
||||
{ return LSAPI_AppendRespHeader_r( &g_req, pBuf, len ); }
|
||||
|
||||
static inline int LSAPI_SetRespStatus( int code )
|
||||
{ return LSAPI_SetRespStatus_r( &g_req, code ); }
|
||||
|
||||
int LSAPI_IsRunning(void);
|
||||
|
||||
int LSAPI_CreateListenSock( const char * pBind, int backlog );
|
||||
|
||||
typedef int (*fn_select_t)( int, fd_set *, fd_set *, fd_set *, struct timeval * );
|
||||
|
||||
int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork );
|
||||
|
||||
void LSAPI_Set_Server_fd( int fd );
|
||||
|
||||
int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq );
|
||||
|
||||
void LSAPI_Set_Max_Reqs( int reqs );
|
||||
|
||||
void LSAPI_Set_Max_Idle( int secs );
|
||||
|
||||
void LSAPI_Set_Max_Children( int maxChildren );
|
||||
|
||||
void LSAPI_Set_Max_Idle_Children( int maxIdleChld );
|
||||
|
||||
void LSAPI_Set_Server_Max_Idle_Secs( int serverMaxIdle );
|
||||
|
||||
void LSAPI_Set_Max_Process_Time( int secs );
|
||||
|
||||
void LSAPI_Init_Env_Parameters( fn_select_t fp );
|
||||
|
||||
#if defined (c_plusplus) || defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user