19#define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
38#include "apr_strings.h"
40#include "util_filter.h"
42#include "http_config.h"
43#include "http_request.h"
45#include "http_protocol.h"
48#include "util_script.h"
60#define PHP_MAGIC_TYPE "application/x-httpd-php"
61#define PHP_SOURCE_MAGIC_TYPE "application/x-httpd-php-source"
62#define PHP_SCRIPT "php-script"
66#if defined(PHP_WIN32) && defined(ZTS)
71php_apache_sapi_ub_write(
const char *str,
size_t str_length)
76 ctx =
SG(server_context);
79 if (ap_rwrite(str, str_length, r) < 0) {
92 ctx =
SG(server_context);
96 apr_table_unset(ctx->
r->headers_out, sapi_header->
header);
100 apr_table_clear(ctx->
r->headers_out);
116 }
while (*
val ==
' ');
126 if (APR_SUCCESS != apr_strtoff(&clen,
val, (
char **)
NULL, 10)) {
129 clen = (apr_off_t) strtol(
val, (
char **)
NULL, 10);
132 ap_set_content_length(ctx->
r, clen);
134 apr_table_set(ctx->
r->headers_out, sapi_header->
header,
val);
136 apr_table_add(ctx->
r->headers_out, sapi_header->
header,
val);
152 const char *sline =
SG(sapi_headers).http_status_line;
154 ctx->
r->status =
SG(sapi_headers).http_response_code;
158 if (sline &&
strlen(sline) > 12 &&
strncmp(sline,
"HTTP/1.", 7) == 0 && sline[8] ==
' ') {
159 ctx->
r->status_line = apr_pstrdup(ctx->
r->pool, sline + 9);
160 ctx->
r->proto_num = 1000 + (sline[7]-
'0');
161 if ((sline[7]-
'0') == 0) {
162 apr_table_set(ctx->
r->subprocess_env,
"force-response-1.0",
"true");
171 ap_set_content_type(ctx->
r, apr_pstrdup(ctx->
r->pool, ctx->
content_type));
179php_apache_sapi_read_post(
char *
buf,
size_t count_bytes)
181 apr_size_t
len, tlen=0;
184 apr_bucket_brigade *brigade;
197 while ((
status = ap_get_brigade(r->input_filters, brigade, AP_MODE_READBYTES, APR_BLOCK_READ,
len)) == APR_SUCCESS) {
198 apr_brigade_flatten(brigade,
buf, &
len);
199 apr_brigade_cleanup(brigade);
201 if (tlen == count_bytes || !
len) {
205 len = count_bytes - tlen;
208 if (
status != APR_SUCCESS) {
216php_apache_sapi_get_stat(
void)
221 ctx->
finfo.st_uid = 0;
222 ctx->
finfo.st_gid = 0;
224 ctx->
finfo.st_uid = ctx->
r->finfo.user;
225 ctx->
finfo.st_gid = ctx->
r->finfo.group;
227 ctx->
finfo.st_dev = ctx->
r->finfo.device;
228 ctx->
finfo.st_ino = ctx->
r->finfo.inode;
229 ctx->
finfo.st_atime = apr_time_sec(ctx->
r->finfo.atime);
230 ctx->
finfo.st_mtime = apr_time_sec(ctx->
r->finfo.mtime);
231 ctx->
finfo.st_ctime = apr_time_sec(ctx->
r->finfo.ctime);
232 ctx->
finfo.st_size = ctx->
r->finfo.size;
233 ctx->
finfo.st_nlink = ctx->
r->finfo.nlink;
239php_apache_sapi_read_cookies(
void)
242 const char *http_cookie;
244 http_cookie = apr_table_get(ctx->
r->headers_in,
"cookie");
247 return (
char *) http_cookie;
251php_apache_sapi_getenv(
const char *
name,
size_t name_len)
260 env_var = apr_table_get(ctx->
r->subprocess_env,
name);
262 return (
char *) env_var;
266php_apache_sapi_register_variables(
zval *track_vars_array)
269 const apr_array_header_t *arr = apr_table_elts(ctx->
r->subprocess_env);
288php_apache_sapi_flush(
void *server_context)
293 ctx = server_context;
297 if (!server_context) {
305 r->status =
SG(sapi_headers).http_response_code;
308 if (ap_rflush(r) < 0 || r->connection->aborted) {
313static void php_apache_sapi_log_message(
const char *
msg,
int syslog_type_int)
316 int aplog_type = APLOG_ERR;
318 ctx =
SG(server_context);
320 switch (syslog_type_int) {
321#if LOG_EMERG != LOG_CRIT
323 aplog_type = APLOG_EMERG;
326#if LOG_ALERT != LOG_CRIT
328 aplog_type = APLOG_ALERT;
332 aplog_type = APLOG_CRIT;
335 aplog_type = APLOG_ERR;
338 aplog_type = APLOG_WARNING;
341 aplog_type = APLOG_NOTICE;
343#if LOG_INFO != LOG_NOTICE
345 aplog_type = APLOG_INFO;
348#if LOG_NOTICE != LOG_DEBUG
350 aplog_type = APLOG_DEBUG;
356 ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, 0,
NULL,
"%s",
msg);
358 ap_log_rerror(APLOG_MARK, aplog_type, 0, ctx->
r,
"%s",
msg);
362static void php_apache_sapi_log_message_ex(
const char *
msg, request_rec *r)
365 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
msg, r->filename);
367 php_apache_sapi_log_message(
msg, -1);
371static zend_result php_apache_sapi_get_request_time(
double *request_time)
378 *request_time = ((double) ctx->
r->request_time) / 1000000.0;
399 php_apache_sapi_ub_write,
400 php_apache_sapi_flush,
401 php_apache_sapi_get_stat,
402 php_apache_sapi_getenv,
406 php_apache_sapi_header_handler,
407 php_apache_sapi_send_headers,
410 php_apache_sapi_read_post,
411 php_apache_sapi_read_cookies,
413 php_apache_sapi_register_variables,
414 php_apache_sapi_log_message,
415 php_apache_sapi_get_request_time,
421static apr_status_t php_apache_server_shutdown(
void *tmp)
423 apache2_sapi_module.shutdown(&apache2_sapi_module);
431static apr_status_t php_apache_child_shutdown(
void *tmp)
433 apache2_sapi_module.shutdown(&apache2_sapi_module);
434#if defined(ZTS) && !defined(PHP_WIN32)
440static void php_apache_add_version(apr_pool_t *
p)
442 if (
PG(expose_php)) {
447static int php_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp)
452 ap_mpm_query(AP_MPMQ_IS_THREADED, &threaded_mpm);
454 ap_log_error(APLOG_MARK, APLOG_CRIT, 0, 0,
"Apache is running a threaded MPM, but your PHP Module is not compiled to be threadsafe. You need to recompile PHP.");
465php_apache_server_startup(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *
s)
468 const char *userdata_key =
"apache2hook_post_config";
472 apr_pool_userdata_get(&
data, userdata_key,
s->process->pool);
479 apr_pool_userdata_set((
const void *)1, userdata_key, apr_pool_cleanup_null,
s->process->pool);
488 int expected_threads;
489 if (ap_mpm_query(AP_MPMQ_MAX_THREADS, &expected_threads) != APR_SUCCESS) {
490 expected_threads = 1;
493 php_tsrm_startup_ex(expected_threads);
502 if (apache2_sapi_module.startup(&apache2_sapi_module) !=
SUCCESS) {
505 apr_pool_cleanup_register(pconf,
NULL, php_apache_server_shutdown, apr_pool_cleanup_null);
506 php_apache_add_version(pconf);
511static apr_status_t php_server_context_cleanup(
void *data_)
518static int php_apache_request_ctor(request_rec *r,
php_struct *ctx)
520 char *content_length;
523 SG(sapi_headers).http_response_code = !r->status ? HTTP_OK : r->status;
524 SG(request_info).content_type = apr_table_get(r->headers_in,
"Content-Type");
525 SG(request_info).query_string = apr_pstrdup(r->pool, r->args);
526 SG(request_info).request_method = r->method;
527 SG(request_info).proto_num = r->proto_num;
528 SG(request_info).request_uri = apr_pstrdup(r->pool, r->uri);
529 SG(request_info).path_translated = apr_pstrdup(r->pool, r->filename);
530 r->no_local_copy = 1;
532 content_length = (
char *) apr_table_get(r->headers_in,
"Content-Length");
533 if (content_length) {
534 SG(request_info).content_length =
ZEND_ATOL(content_length);
536 SG(request_info).content_length = 0;
539 apr_table_unset(r->headers_out,
"Content-Length");
540 apr_table_unset(r->headers_out,
"Last-Modified");
541 apr_table_unset(r->headers_out,
"Expires");
542 apr_table_unset(r->headers_out,
"ETag");
544 auth = apr_table_get(r->headers_in,
"Authorization");
547 if (
SG(request_info).auth_user ==
NULL && r->user) {
548 SG(request_info).auth_user =
estrdup(r->user);
551 ctx->
r->user = apr_pstrdup(ctx->
r->pool,
SG(request_info).auth_user);
556static void php_apache_request_dtor(request_rec *r)
561static void php_apache_ini_dtor(request_rec *r, request_rec *
p)
563 if (
strcmp(r->protocol,
"INCLUDED")) {
579 apr_pool_cleanup_run(r->pool, (
void *)&
SG(server_context), php_server_context_cleanup);
583static int php_handler(request_rec *r)
587 apr_bucket_brigade *
volatile brigade;
590 request_rec *
volatile parent_req =
NULL;
593 (
void)ts_resource(0);
599#define PHPAP_INI_OFF php_apache_ini_dtor(r, parent_req);
601 conf = ap_get_module_config(r->per_dir_config, &
php_module);
604 ctx =
SG(server_context);
607 ctx =
SG(server_context) = apr_pcalloc(r->pool,
sizeof(*ctx));
612 apr_pool_cleanup_register(r->pool, (
void *)&
SG(server_context), php_server_context_cleanup, apr_pool_cleanup_null);
623 if (!
AP2(xbithack) ||
strcmp(r->handler,
"text/html") || !(r->finfo.protection & APR_UEXECUTE)) {
631 if (r->used_path_info == AP_REQ_REJECT_PATH_INFO
632 && r->path_info && r->path_info[0]) {
634 return HTTP_NOT_FOUND;
643 if (r->finfo.filetype == 0) {
644 php_apache_sapi_log_message_ex(
"script '%s' not found or unable to stat", r);
646 return HTTP_NOT_FOUND;
648 if (r->finfo.filetype == APR_DIR) {
649 php_apache_sapi_log_message_ex(
"attempt to invoke directory '%s' as script", r);
651 return HTTP_FORBIDDEN;
655 if (r->main ==
NULL ||
657 r->subprocess_env != r->main->subprocess_env
660 ap_add_common_vars(r);
667 brigade = apr_brigade_create(r->pool, r->connection->bucket_alloc);
668 ctx =
SG(server_context);
671 if (php_apache_request_ctor(r, ctx)!=
SUCCESS) {
678 if (parent_req && parent_req->handler &&
682 if (php_apache_request_ctor(r, ctx)!=
SUCCESS) {
693 if (parent_req && parent_req->status != HTTP_OK && parent_req->status != 413 &&
strcmp(r->protocol,
"INCLUDED")) {
701 if (
AP2(last_modified)) {
702 ap_update_mtime(r, r->finfo.mtime);
703 ap_set_last_modified(r);
723 apr_table_set(r->notes,
"mod_php_memory_usage",
730 php_apache_request_dtor(r);
732 apr_brigade_cleanup(brigade);
733 bucket = apr_bucket_eos_create(r->connection->bucket_alloc);
734 APR_BRIGADE_INSERT_TAIL(brigade, bucket);
736 rv = ap_pass_brigade(r->output_filters, brigade);
737 if (
rv != APR_SUCCESS || r->connection->aborted) {
742 apr_brigade_cleanup(brigade);
743 apr_pool_cleanup_run(r->pool, (
void *)&
SG(server_context), php_server_context_cleanup);
751static void php_apache_child_init(apr_pool_t *pchild, server_rec *
s)
753 apr_pool_cleanup_register(pchild,
NULL, php_apache_child_shutdown, apr_pool_cleanup_null);
757static void php_apache_signal_init(apr_pool_t *pchild, server_rec *
s)
765 ap_hook_pre_config(php_pre_config,
NULL,
NULL, APR_HOOK_MIDDLE);
766 ap_hook_post_config(php_apache_server_startup,
NULL,
NULL, APR_HOOK_MIDDLE);
767 ap_hook_handler(php_handler,
NULL,
NULL, APR_HOOK_MIDDLE);
769 ap_hook_child_init(php_apache_signal_init,
NULL,
NULL, APR_HOOK_MIDDLE);
771 ap_hook_child_init(php_apache_child_init,
NULL,
NULL, APR_HOOK_MIDDLE);
SAPI_API char * sapi_get_default_content_type(void)
SAPI_API sapi_module_struct sapi_module
SAPI_API int sapi_send_headers(void)
SAPI_API void sapi_startup(sapi_module_struct *sf)
SAPI_API void sapi_shutdown(void)
#define SAPI_HEADER_SENT_SUCCESSFULLY
#define STANDARD_SAPI_MODULE_PROPERTIES
struct _sapi_module_struct sapi_module_struct
void apply_config(void *dummy)
ZEND_API void php_get_highlight_struct(zend_syntax_highlighter_ini *syntax_highlighter_ini)
strchr(string $haystack, string $needle, bool $before_needle=false)
headers_sent(&$filename=null, &$line=null)
zend_ffi_ctype_name_buf buf
foreach($dp as $el) foreach( $dp as $el) if( $pass2< 2) echo ""
void php_request_shutdown(void *dummy)
zend_result php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_module)
PHPAPI void php_handle_aborted_connection(void)
PHPAPI bool php_execute_script(zend_file_handle *primary_file)
zend_result php_request_startup(void)
PHPAPI int php_handle_auth_data(const char *auth)
int php_module_shutdown_wrapper(sapi_module_struct *sapi_globals)
char * apache2_php_ini_path_override
#define APR_ARRAY_FOREACH_CLOSE()
#define APR_ARRAY_FOREACH_OPEN(arr, key, val)
zend_module_entry php_apache_module
unsigned char key[REFLECTION_KEY_LEN]
PHPAPI void php_register_variable_safe(const char *var, const char *strval, size_t str_len, zval *track_vars_array)
#define PHP_SOURCE_MAGIC_TYPE
void php_ap2_register_hook(apr_pool_t *p)
apr_bucket_brigade * brigade
ZEND_API zend_result zend_execute_scripts(int type, zval *retval, int file_count,...)
#define ZEND_TSRMLS_CACHE_UPDATE()
#define ZEND_TSRMLS_CACHE_DEFINE()
ZEND_API size_t zend_memory_peak_usage(bool real_usage)
strncmp(string $string1, string $string2, int $length)
strcmp(string $string1, string $string2)
ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle)
#define strcasecmp(s1, s2)
ZEND_API void(ZEND_FASTCALL *zend_touch_vm_stack_data)(void *vm_stack_data)
#define ZEND_HASH_MAP_FOREACH_STR_KEY(ht, _key)
#define ZEND_HASH_FOREACH_END()
ZEND_API zend_result highlight_file(const char *filename, zend_syntax_highlighter_ini *syntax_highlighter_ini)
zend_syntax_highlighter_ini syntax_highlighter_ini
struct _zend_syntax_highlighter_ini zend_syntax_highlighter_ini
ZEND_API void zend_ini_deactivate(void)
ZEND_API zend_result zend_restore_ini_entry(zend_string *name, int stage)
#define ZEND_INI_STAGE_SHUTDOWN
struct _zend_file_handle zend_file_handle
struct _zend_string zend_string
struct _zend_module_entry zend_module_entry
#define zend_signal_startup()
#define zend_signal_init()
ZEND_API void zend_stream_init_filename(zend_file_handle *handle, const char *filename)
struct _zend_array HashTable
ZEND_RESULT_CODE zend_result