File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / sapi / apache_hooks / mod_php5.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:34:35 2012 UTC (12 years, 1 month ago) by misho
Branches: php, MAIN
CVS tags: v5_4_3elwix, v5_4_17p0, HEAD
php 5.4.3+patches

    1: /*
    2:    +----------------------------------------------------------------------+
    3:    | PHP Version 5							  |
    4:    +----------------------------------------------------------------------+
    5:    | Copyright (c) 1997-2012 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			          |
   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:    | Authors: Rasmus Lerdorf <rasmus@php.net>                             |
   16:    | (with helpful hints from Dean Gaudet <dgaudet@arctic.org>	          |
   17:    | PHP 4.0 patches by Zeev Suraski <zeev@zend.com>			  |
   18:    +----------------------------------------------------------------------+
   19:  */
   20: /* $Id: mod_php5.c,v 1.1.1.2 2012/05/29 12:34:35 misho Exp $ */
   21: 
   22: #include "php_apache_http.h"
   23: 
   24: #ifdef NETWARE
   25: #define SIGPIPE SIGINT
   26: #endif
   27: 
   28: #undef shutdown
   29: 
   30: /* {{{ Prototypes
   31:  */
   32: int apache_php_module_main(request_rec *r, int display_source_mode TSRMLS_DC);
   33: static void php_save_umask(void);
   34: static void php_restore_umask(void);
   35: static int sapi_apache_read_post(char *buffer, uint count_bytes TSRMLS_DC);
   36: static char *sapi_apache_read_cookies(TSRMLS_D);
   37: static int sapi_apache_header_handler(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers TSRMLS_DC);
   38: static int sapi_apache_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC);
   39: static int send_php(request_rec *r, int display_source_mode, char *filename);
   40: static int send_parsed_php(request_rec * r);
   41: static int send_parsed_php_source(request_rec * r);
   42: static int php_xbithack_handler(request_rec * r);
   43: static void php_init_handler(server_rec *s, pool *p);
   44: /* }}} */
   45: 
   46: #if MODULE_MAGIC_NUMBER >= 19970728
   47: static void php_child_exit_handler(server_rec *s, pool *p);
   48: #endif
   49: 
   50: #if MODULE_MAGIC_NUMBER > 19961007
   51: #define CONST_PREFIX const
   52: #else
   53: #define CONST_PREFIX
   54: #endif
   55: 
   56: 
   57: typedef struct _sapi_stack {
   58: 		int top, max, persistent;
   59: 		void **elements;
   60: } sapi_stack;
   61: 
   62: typedef struct _php_per_dir_config {
   63: 	HashTable *ini_settings;
   64: 	sapi_stack headers_handlers;
   65: 	sapi_stack auth_handlers;
   66: 	sapi_stack access_handlers;
   67: 	sapi_stack type_handlers;
   68: 	sapi_stack fixup_handlers;
   69: 	sapi_stack logger_handlers;
   70: 	sapi_stack post_read_handlers;
   71: 	sapi_stack response_handlers;
   72: } php_per_dir_config;
   73: 
   74: typedef struct _php_per_server_config {
   75: 	sapi_stack uri_handlers;
   76: 	sapi_stack requires;
   77: } php_per_server_config;
   78: 
   79: 
   80: static CONST_PREFIX char *php_apache_value_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode);
   81: static CONST_PREFIX char *php_apache_value_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1, char *arg2);
   82: static CONST_PREFIX char *php_apache_admin_value_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1, char *arg2);
   83: static CONST_PREFIX char *php_apache_flag_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1, char *arg2);
   84: static CONST_PREFIX char *php_apache_flag_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode);
   85: static CONST_PREFIX char *php_apache_admin_flag_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1, char *arg2);
   86: 
   87: /* ### these should be defined in mod_php5.h or somewhere else */
   88: #define USE_PATH 1
   89: #define IGNORE_URL 2
   90: 
   91: module MODULE_VAR_EXPORT php5_module;
   92: 
   93: int saved_umask;
   94: /* static int setup_env = 0; */
   95: static unsigned char apache_php_initialized;
   96: 
   97: typedef struct _php_per_dir_entry {
   98: 	char *key;
   99: 	char *value;
  100: 	uint key_length;
  101: 	uint value_length;
  102: 	int type;
  103: } php_per_dir_entry;
  104: 
  105: /* some systems are missing these from their header files */
  106: 
  107: /* {{{ zend stack utility functions
  108:  */
  109: 
  110: /* This code is ripped part and parcel from zend_stack.[ch].  Assuming that the
  111:    patch supporting zend_stack_init_ex is applied, all but the bottom two 
  112:    module-specific iterators will be removed
  113:  */
  114: 
  115: int sapi_stack_init_ex(sapi_stack *stack, int persistent)
  116: {
  117: 		stack->top = 0;
  118: 		stack->persistent = persistent;
  119: 		stack->elements = (void **) pemalloc(sizeof(void **) * STACK_BLOCK_SIZE,  persistent);
  120: 		if (!stack->elements) {
  121: 				return FAILURE;
  122: 		} else {
  123: 				stack->max = STACK_BLOCK_SIZE;
  124: 				return SUCCESS;
  125: 		}
  126: }
  127: int sapi_stack_push(sapi_stack *stack, void *element)
  128: {
  129: 		if (stack->top >= stack->max) {		 /* we need to allocate more memory */
  130: 				stack->elements = (void **) perealloc(stack->elements,
  131: 								   (sizeof(void **) * (stack->max += STACK_BLOCK_SIZE)), stack->persistent);
  132: 				if (!stack->elements) {
  133: 						return FAILURE;
  134: 				}
  135: 		}
  136: 		stack->elements[stack->top] = (void *) element;
  137: 		return stack->top++;
  138: }
  139: void* sapi_stack_pop(sapi_stack *stack) {
  140: 	if(stack->top == 0) {
  141: 		return NULL;
  142: 	}
  143: 	else {
  144: 		return stack->elements[--stack->top];
  145: 	}
  146: }
  147: 
  148: int sapi_stack_destroy(sapi_stack *stack)
  149: {
  150: 		return SUCCESS;
  151: }
  152: 
  153: int sapi_stack_apply_with_argument_all(sapi_stack *stack, int type, int (*apply_function)(void *element, void *arg), void *arg)
  154: {
  155: 		int i, retval;   
  156: 
  157: 		switch (type) {				
  158: 				case ZEND_STACK_APPLY_TOPDOWN:
  159: 						for (i=stack->top-1; i>=0; i--) {
  160: 								retval = apply_function(stack->elements[i], arg); 
  161: 						}
  162: 						break;
  163: 				case ZEND_STACK_APPLY_BOTTOMUP:
  164: 						for (i=0; i<stack->top; i++) {		
  165: 								retval = apply_function(stack->elements[i], arg);
  166: 						}	  
  167: 						break;
  168: 		}
  169: 		return retval;
  170: }
  171: 
  172: 
  173: int sapi_stack_apply_with_argument_stop_if_equals(sapi_stack *stack, int type, int (*apply_function)(void *element, void *arg), void *arg, int stopval)
  174: {
  175: 	int i;
  176: 	int ret = DECLINED;
  177: 	switch (type) {
  178: 		case ZEND_STACK_APPLY_TOPDOWN:
  179: 			for (i=stack->top-1; i>=0; i--) {
  180: 				if ((ret = apply_function(stack->elements[i], arg)) == stopval) {
  181: 					break;
  182: 				}
  183: 			}
  184: 			break;
  185: 		case ZEND_STACK_APPLY_BOTTOMUP:
  186: 			for (i=0; i<stack->top; i++) {
  187: 				if ((ret = apply_function(stack->elements[i], arg)) == stopval) {
  188: 					break;
  189: 				}
  190: 			}
  191: 			break;
  192: 	}
  193: 	return ret;
  194: }
  195: 
  196: int sapi_stack_apply_with_argument_stop_if_http_error(sapi_stack *stack, int type, int (*apply_function)(void *element, void *arg), void *arg)
  197: {
  198: 	int i;
  199: 	int ret = DECLINED;
  200: 	switch (type) {
  201: 		case ZEND_STACK_APPLY_TOPDOWN:
  202: 			for (i=stack->top-1; i>=0; i--) {
  203: 				if ((ret = apply_function(stack->elements[i], arg)) > 0) {
  204: 					break;
  205: 				}
  206: 			}
  207: 			break;
  208: 		case ZEND_STACK_APPLY_BOTTOMUP:
  209: 			for (i=0; i<stack->top; i++) {
  210: 				if ((ret = apply_function(stack->elements[i], arg)) > 0) {
  211: 					break;
  212: 				}
  213: 			}
  214: 			break;
  215: 	}
  216: 	return ret;
  217: }
  218: 
  219: void php_handler_stack_destroy(sapi_stack *stack)
  220: {
  221: 	php_handler *ph;
  222: 	while((ph = (php_handler *)sapi_stack_pop(stack)) != NULL) {
  223: 		free(ph->name);
  224: 		free(ph);
  225: 	}
  226: }
  227: /* }}} */ 
  228: 
  229: /* {{{ php_save_umask
  230:  */
  231: static void php_save_umask(void)
  232: {
  233: 	saved_umask = umask(077);
  234: 	umask(saved_umask);
  235: }
  236: /* }}} */
  237: 
  238: /* {{{ sapi_apache_ub_write
  239:  */
  240: static int sapi_apache_ub_write(const char *str, uint str_length TSRMLS_DC)
  241: {
  242: 	int ret=0;
  243: 		
  244: 	if (SG(server_context)) {
  245: 		ret = rwrite(str, str_length, (request_rec *) SG(server_context));
  246: 	}
  247: 	if (ret != str_length) {
  248: 		php_handle_aborted_connection();
  249: 	}
  250: 	return ret;
  251: }
  252: /* }}} */
  253: 
  254: /* {{{ sapi_apache_flush
  255:  */
  256: static void sapi_apache_flush(void *server_context)
  257: {
  258: 	if (server_context) {
  259: #if MODULE_MAGIC_NUMBER > 19970110
  260: 		rflush((request_rec *) server_context);
  261: #else
  262: 		bflush((request_rec *) server_context->connection->client);
  263: #endif
  264: 	}
  265: }
  266: /* }}} */
  267: 
  268: /* {{{ sapi_apache_read_post
  269:  */
  270: static int sapi_apache_read_post(char *buffer, uint count_bytes TSRMLS_DC)
  271: {
  272: 	uint total_read_bytes=0, read_bytes;
  273: 	request_rec *r = (request_rec *) SG(server_context);
  274: 	void (*handler)(int);
  275: 
  276: 	/*
  277: 	 * This handles the situation where the browser sends a Expect: 100-continue header
  278: 	 * and needs to recieve confirmation from the server on whether or not it can send
  279: 	 * the rest of the request. RFC 2616
  280: 	 *
  281: 	 */
  282: 	if (!SG(read_post_bytes) && !ap_should_client_block(r)) {
  283: 		return total_read_bytes;
  284: 	}
  285:  
  286: 	handler = signal(SIGPIPE, SIG_IGN);
  287: 	while (total_read_bytes<count_bytes) {
  288: 		hard_timeout("Read POST information", r); /* start timeout timer */
  289: 		read_bytes = get_client_block(r, buffer+total_read_bytes, count_bytes-total_read_bytes);
  290: 		reset_timeout(r);
  291: 		if (read_bytes<=0) {
  292: 			break;
  293: 		}
  294: 		total_read_bytes += read_bytes;
  295: 	}
  296: 	signal(SIGPIPE, handler);	
  297: 	return total_read_bytes;
  298: }
  299: /* }}} */
  300: 
  301: /* {{{ sapi_apache_read_cookies
  302:  */
  303: static char *sapi_apache_read_cookies(TSRMLS_D)
  304: {
  305: 	return (char *) table_get(((request_rec *) SG(server_context))->subprocess_env, "HTTP_COOKIE");
  306: }
  307: /* }}} */
  308: 
  309: /* {{{ sapi_apache_header_handler
  310:  */
  311: static int sapi_apache_header_handler(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers TSRMLS_DC)
  312: {
  313: 	char *header_name, *header_content, *p;
  314: 	request_rec *r = (request_rec *) SG(server_context);
  315: 	if(!r) {
  316: 		return 0;
  317: 	}
  318: 
  319: 	switch(op) {
  320: 		case SAPI_HEADER_DELETE_ALL:
  321: 			clear_table(r->headers_out);
  322: 			return 0;
  323: 
  324: 		case SAPI_HEADER_DELETE:
  325: 			table_unset(r->headers_out, sapi_header->header);
  326: 			return 0;
  327: 
  328: 		case SAPI_HEADER_ADD:
  329: 		case SAPI_HEADER_REPLACE:
  330: 			header_name = sapi_header->header;
  331: 
  332: 			header_content = p = strchr(header_name, ':');
  333: 			if (!p) {
  334: 				return 0;
  335: 			}
  336: 
  337: 			*p = 0;
  338: 			do {
  339: 				header_content++;
  340: 			} while (*header_content==' ');
  341: 
  342: 			if (!strcasecmp(header_name, "Content-Type")) {
  343: 				r->content_type = pstrdup(r->pool, header_content);
  344: 			} else if (!strcasecmp(header_name, "Set-Cookie")) {
  345: 				table_add(r->headers_out, header_name, header_content);
  346: 			} else if (op == SAPI_HEADER_REPLACE) {
  347: 				table_set(r->headers_out, header_name, header_content);
  348: 			} else {
  349: 				table_add(r->headers_out, header_name, header_content);
  350: 			}
  351: 
  352: 			*p = ':';  /* a well behaved header handler shouldn't change its original arguments */
  353: 
  354: 			return SAPI_HEADER_ADD;
  355: 
  356: 		default:
  357: 			return 0;
  358: 	}
  359: }
  360: /* }}} */
  361: 
  362: /* {{{ sapi_apache_send_headers
  363:  */
  364: static int sapi_apache_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
  365: {
  366: 	if(SG(server_context) == NULL) { /* server_context is not here anymore */
  367: 		return SAPI_HEADER_SEND_FAILED;
  368: 	}
  369: 
  370: 	((request_rec *) SG(server_context))->status = SG(sapi_headers).http_response_code;
  371: 	/* check that we haven't sent headers already, we use our own
  372: 	 * headers_sent since we may send headers at anytime 
  373: 	 */
  374: 	if(!AP(headers_sent)) {
  375: 		send_http_header((request_rec *) SG(server_context));
  376: 		AP(headers_sent) = 1;
  377: 	}
  378: 	return SAPI_HEADER_SENT_SUCCESSFULLY;
  379: }
  380: /* }}} */
  381: 
  382: /* {{{ sapi_apache_register_server_variables
  383:  */
  384: static void sapi_apache_register_server_variables(zval *track_vars_array TSRMLS_DC)
  385: {
  386: 	register int i;
  387: 	array_header *arr = table_elts(((request_rec *) SG(server_context))->subprocess_env);
  388: 	table_entry *elts = (table_entry *) arr->elts;
  389: 	zval **path_translated;
  390: 	HashTable *symbol_table;
  391: 
  392: 	for (i = 0; i < arr->nelts; i++) {
  393: 		char *val;
  394: 
  395: 		if (elts[i].val) {
  396: 			val = elts[i].val;
  397: 		} else {
  398: 			val = "";
  399: 		}
  400: 		php_register_variable(elts[i].key, val, track_vars_array  TSRMLS_CC);
  401: 	}
  402: 
  403: 	/* If PATH_TRANSLATED doesn't exist, copy it from SCRIPT_FILENAME */
  404: 	if (track_vars_array) {
  405: 		symbol_table = track_vars_array->value.ht;
  406: 	} else {
  407: 		symbol_table = NULL;
  408: 	}
  409: 	if (symbol_table
  410: 		&& !zend_hash_exists(symbol_table, "PATH_TRANSLATED", sizeof("PATH_TRANSLATED"))
  411: 		&& zend_hash_find(symbol_table, "SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME"), (void **) &path_translated)==SUCCESS) {
  412: 		php_register_variable("PATH_TRANSLATED", Z_STRVAL_PP(path_translated), track_vars_array TSRMLS_CC);
  413: 	}
  414: 
  415: 	php_register_variable("PHP_SELF", ((request_rec *) SG(server_context))->uri, track_vars_array TSRMLS_CC);
  416: }
  417: /* }}} */
  418: 
  419: /* {{{ php_apache_startup
  420:  */
  421: static int php_apache_startup(sapi_module_struct *sapi_module)
  422: {
  423: 	if (php_module_startup(sapi_module, &apache_module_entry, 1) == FAILURE) {
  424: 		return FAILURE;
  425: 	} else {
  426: 		return SUCCESS;
  427: 	}
  428: }
  429: /* }}} */
  430: 
  431: /* {{{ php_apache_log_message
  432:  */
  433: static void php_apache_log_message(char *message TSRMLS_DC)
  434: {
  435: 	if (SG(server_context)) {
  436: #if MODULE_MAGIC_NUMBER >= 19970831
  437: 		aplog_error(NULL, 0, APLOG_ERR | APLOG_NOERRNO, ((request_rec *) SG(server_context))->server, "%s", message);
  438: #else
  439: 		log_error(message, ((request_rec *) SG(server_context))->server);
  440: #endif
  441: 	} else {
  442: 		fprintf(stderr, "%s", message);
  443: 		fprintf(stderr, "\n");
  444: 	}
  445: }
  446: /* }}} */
  447: 
  448: /* {{{ php_apache_request_shutdown
  449:  */
  450: static void php_apache_request_shutdown(void *dummy)
  451: {
  452: 	TSRMLS_FETCH();
  453: 	AP(current_hook) = AP_CLEANUP;
  454: 	php_output_set_status(PHP_OUTPUT_DISABLED TSRMLS_CC);
  455: 	SG(server_context) = NULL; /* The server context (request) is invalid by the time run_cleanups() is called */
  456: 	if(SG(sapi_started)) {
  457: 		php_request_shutdown(dummy);
  458: 		SG(sapi_started) = 0;
  459: 	}
  460: 	AP(in_request) = 0;
  461: 	if(AP(setup_env)) {
  462: 		AP(setup_env) = 0;
  463: 	}
  464: 	AP(current_hook) = AP_WAITING_FOR_REQUEST;
  465: 	AP(headers_sent) = 0;
  466: }
  467: /* }}} */
  468: 
  469: /* {{{ php_apache_sapi_activate
  470:  */
  471: static int php_apache_sapi_activate(TSRMLS_D)
  472: {
  473: 	request_rec *r = (request_rec *) SG(server_context); 
  474: 
  475: 	/*
  476: 	 * For the Apache module version, this bit of code registers a cleanup
  477: 	 * function that gets triggered when our request pool is destroyed.
  478: 	 * We need this because at any point in our code we can be interrupted
  479: 	 * and that may happen before we have had time to free our memory.
  480: 	 * The php_request_shutdown function needs to free all outstanding allocated
  481: 	 * memory.  
  482: 	 */
  483: 	block_alarms();
  484: 	register_cleanup(r->pool, NULL, php_apache_request_shutdown, php_request_shutdown_for_exec);
  485: 	AP(in_request)=1;
  486: 	unblock_alarms();
  487: 
  488: 	/* Override the default headers_only value - sometimes "GET" requests should actually only
  489: 	 * send headers.
  490: 	 */
  491: 	SG(request_info).headers_only = r->header_only;
  492: 	return SUCCESS;
  493: }
  494: /* }}} */
  495: 
  496: /* {{{ php_apache_get_stat
  497:  */
  498: static struct stat *php_apache_get_stat(TSRMLS_D)
  499: {
  500: 	return &((request_rec *) SG(server_context))->finfo;
  501: }
  502: /* }}} */
  503: 
  504: /* {{{ php_apache_getenv
  505:  */
  506: static char *php_apache_getenv(char *name, size_t name_len TSRMLS_DC)
  507: {
  508: 	return (char *) table_get(((request_rec *) SG(server_context))->subprocess_env, name);
  509: }
  510: /* }}} */
  511: 
  512: /* {{{ sapi_module_struct apache_sapi_module
  513:  */
  514: static sapi_module_struct apache_sapi_module = {
  515: 	"apache",						/* name */
  516: 	"Apache",						/* pretty name */
  517: 									
  518: 	php_apache_startup,				/* startup */
  519: 	php_module_shutdown_wrapper,	/* shutdown */
  520: 
  521: 	php_apache_sapi_activate,		/* activate */
  522: 	NULL,							/* deactivate */
  523: 
  524: 	sapi_apache_ub_write,			/* unbuffered write */
  525: 	sapi_apache_flush,				/* flush */
  526: 	php_apache_get_stat,			/* get uid */
  527: 	php_apache_getenv,				/* getenv */
  528: 
  529: 	php_error,						/* error handler */
  530: 
  531: 	sapi_apache_header_handler,		/* header handler */
  532: 	sapi_apache_send_headers,		/* send headers handler */
  533: 	NULL,							/* send header handler */
  534: 
  535: 	sapi_apache_read_post,			/* read POST data */
  536: 	sapi_apache_read_cookies,		/* read Cookies */
  537: 
  538: 	sapi_apache_register_server_variables,		/* register server variables */
  539: 	php_apache_log_message,			/* Log message */
  540: 	NULL,							/* Get request time */
  541: 	NULL,					/* child terminate */
  542: 
  543: 	NULL,							/* php.ini path override */
  544: 
  545: #ifdef PHP_WIN32
  546: 	NULL,
  547: 	NULL,
  548: #else
  549: 	block_alarms,					/* Block interruptions */
  550: 	unblock_alarms,					/* Unblock interruptions */
  551: #endif
  552: 
  553: 	NULL,                           /* default post reader */
  554: 	NULL,                           /* treat data */
  555: 	NULL,                           /* exe location */
  556: 	0,                              /* ini ignore */
  557: 	NULL
  558: 	
  559: };
  560: /* }}} */
  561: 
  562: /* {{{ php_restore_umask
  563:  */
  564: static void php_restore_umask(void)
  565: {
  566: 	umask(saved_umask);
  567: }
  568: /* }}} */
  569: 
  570: /* {{{ init_request_info
  571:  */
  572: static void init_request_info(TSRMLS_D)
  573: {
  574: 	request_rec *r = ((request_rec *) SG(server_context));
  575: 	char *content_length = (char *) table_get(r->subprocess_env, "CONTENT_LENGTH");
  576: 	const char *authorization=NULL;
  577: 	char *tmp, *tmp_user;
  578: 
  579: 	SG(request_info).query_string = r->args;
  580: 	SG(request_info).path_translated = r->filename;
  581: 	SG(request_info).request_uri = r->uri;
  582: 	SG(request_info).request_method = (char *)r->method;
  583: 	SG(request_info).proto_num = r->proto_num;
  584: 	SG(request_info).content_type = (char *) table_get(r->subprocess_env, "CONTENT_TYPE");
  585: 	SG(request_info).content_length = (content_length ? atol(content_length) : 0);
  586: 	SG(sapi_headers).http_response_code = r->status;
  587: 
  588: 	if (r->headers_in) {
  589: 		authorization = table_get(r->headers_in, "Authorization");
  590: 	}
  591: 
  592: 	SG(request_info).auth_user = NULL;
  593: 	SG(request_info).auth_password = NULL;
  594: 
  595: 	if (authorization && !auth_type(r)) {
  596:         if (!strcasecmp(getword(r->pool, &authorization, ' '), "Basic")) {
  597:             tmp = uudecode(r->pool, authorization);
  598:             tmp_user = getword_nulls_nc(r->pool, &tmp, ':');
  599:             if (tmp_user) {
  600:                 r->connection->user = pstrdup(r->connection->pool, tmp_user);
  601:                 r->connection->ap_auth_type = "Basic";
  602:                 SG(request_info).auth_user = estrdup(tmp_user);
  603:             }
  604:             if (tmp) {
  605:                 SG(request_info).auth_password = estrdup(tmp);
  606:             }
  607: 		} else if  (!strcasecmp(getword(r->pool, &authorization, ' '), "Digest")) {
  608:             r->connection->ap_auth_type = "Digest";
  609:             SG(request_info).auth_digest = estrdup(authorization);
  610: 		}
  611: 	}
  612: }
  613: /* }}} */
  614: 
  615: /* {{{ php_apache_alter_ini_entries
  616:  */
  617: static int php_apache_alter_ini_entries(php_per_dir_entry *per_dir_entry TSRMLS_DC)
  618: {
  619: 	zend_alter_ini_entry(per_dir_entry->key, per_dir_entry->key_length+1, per_dir_entry->value, per_dir_entry->value_length, per_dir_entry->type, PHP_INI_STAGE_ACTIVATE);
  620: 	return 0;
  621: }
  622: /* }}} */
  623: 
  624: /* {{{ php_apache_get_default_mimetype
  625:  */
  626: static char *php_apache_get_default_mimetype(request_rec *r TSRMLS_DC)
  627: {
  628: 	
  629: 	char *mimetype;
  630: 	if (SG(default_mimetype) || SG(default_charset)) {
  631: 		/* Assume output will be of the default MIME type.  Individual
  632: 		   scripts may change this later. */
  633: 		char *tmpmimetype;
  634: 		tmpmimetype = sapi_get_default_content_type(TSRMLS_C);
  635: 		mimetype = pstrdup(r->pool, tmpmimetype);
  636: 		efree(tmpmimetype);
  637: 	} else {
  638: 		mimetype = SAPI_DEFAULT_MIMETYPE "; charset=" SAPI_DEFAULT_CHARSET;
  639: 	}
  640: 	return mimetype;
  641: }
  642: /* }}} */
  643: 
  644: /* {{{ send_php
  645:  */
  646: static int send_php(request_rec *r, int display_source_mode, char *filename)
  647: {
  648: 	int retval;
  649: 	php_per_dir_config *per_dir_conf;
  650: 	TSRMLS_FETCH();
  651: 	if (AP(in_request)) {
  652: 		zend_file_handle fh;
  653: 
  654: 		fh.filename = r->filename;
  655: 		fh.opened_path = NULL;
  656: 		fh.free_filename = 0;
  657: 		fh.type = ZEND_HANDLE_FILENAME;
  658: 
  659: 		zend_execute_scripts(ZEND_INCLUDE TSRMLS_CC, NULL, 1, &fh);
  660: 		return OK;
  661: 	}
  662: 
  663: 	zend_first_try {
  664: 
  665: 		/* Make sure file exists */
  666: 		if (filename == NULL && r->finfo.st_mode == 0) {
  667: 			return DECLINED;
  668: 		}
  669: 
  670: 		per_dir_conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
  671: 		if (per_dir_conf) {
  672: 			zend_hash_apply((HashTable *) per_dir_conf->ini_settings, (apply_func_t) php_apache_alter_ini_entries TSRMLS_CC);
  673: 		}
  674: 
  675: 		/* If PHP parser engine has been turned off with an "engine off"
  676: 		 * directive, then decline to handle this request
  677: 		 */
  678: 		if (!AP(engine)) {
  679: 			r->content_type = php_apache_get_default_mimetype(r TSRMLS_CC);
  680: 			r->allowed |= (1 << METHODS) - 1;
  681: 			zend_try {
  682: 				zend_ini_deactivate(TSRMLS_C);
  683: 			} zend_end_try();
  684: 			return DECLINED;
  685: 		}
  686: 		if (filename == NULL) {
  687: 			filename = r->filename;
  688: 		}
  689: 
  690: 		/* Apache 1.2 has a more complex mechanism for reading POST data */
  691: #if MODULE_MAGIC_NUMBER > 19961007
  692: 		if ((retval = setup_client_block(r, REQUEST_CHUNKED_ERROR))) {
  693: 			zend_try {
  694: 				zend_ini_deactivate(TSRMLS_C);
  695: 			} zend_end_try();
  696: 			return retval;
  697: 		}
  698: #endif
  699: 
  700: 		if (AP(last_modified)) {
  701: #if MODULE_MAGIC_NUMBER < 19970912
  702: 			if ((retval = set_last_modified(r, r->finfo.st_mtime))) {
  703: 				zend_try {
  704: 					zend_ini_deactivate(TSRMLS_C);
  705: 				} zend_end_try();
  706: 				return retval;
  707: 			}
  708: #else
  709: 			update_mtime (r, r->finfo.st_mtime);
  710: 			set_last_modified(r);
  711: 			set_etag(r);
  712: #endif
  713: 		}
  714: 		/* Assume output will be of the default MIME type.  Individual
  715: 		   scripts may change this later in the request. */
  716: 		r->content_type = php_apache_get_default_mimetype(r TSRMLS_CC);
  717: 
  718: 		/* Init timeout */
  719: 		hard_timeout("send", r);
  720: 
  721: 		SG(server_context) = r;
  722: 		
  723: 		php_save_umask();
  724: 		if(!AP(setup_env)) {
  725: 			AP(setup_env) = 1;
  726: 			add_common_vars(r);
  727: 			add_cgi_vars(r);
  728: 		}
  729: 		init_request_info(TSRMLS_C);
  730: 		apache_php_module_main(r, display_source_mode TSRMLS_CC);
  731: 		
  732: 		/* Done, restore umask, turn off timeout, close file and return */
  733: 		php_restore_umask();
  734: 		kill_timeout(r);
  735: 	} zend_end_try();
  736: 
  737: 	return OK;
  738: }
  739: /* }}} */
  740: 
  741: /* {{{ send_parsed_php
  742:  */
  743: static int send_parsed_php(request_rec * r)
  744: {
  745: 	int result = send_php(r, 0, NULL);
  746: 	TSRMLS_FETCH();
  747:  
  748: 	ap_table_setn(r->notes, "mod_php_memory_usage",
  749: 		ap_psprintf(r->pool, "%u", zend_memory_peak_usage(1 TSRMLS_CC)));
  750: 
  751: 	return result;
  752: }
  753: /* }}} */
  754: 
  755: /* {{{ send_parsed_php_source
  756:  */
  757: static int send_parsed_php_source(request_rec * r)
  758: {
  759: 	return send_php(r, 1, NULL);
  760: }
  761: /* }}} */
  762: 
  763: 
  764: /* {{{ destroy_per_dir_entry
  765:  */
  766: static void destroy_per_dir_entry(php_per_dir_entry *per_dir_entry)
  767: {
  768: 	free(per_dir_entry->key);
  769: 	free(per_dir_entry->value);
  770: }
  771: /* }}} */
  772: 
  773: /* {{{ copy_per_dir_entry
  774:  */
  775: static void copy_per_dir_entry(php_per_dir_entry *per_dir_entry)
  776: {
  777: 	php_per_dir_entry tmp = *per_dir_entry;
  778: 
  779: 	per_dir_entry->key = (char *) malloc(tmp.key_length+1);
  780: 	memcpy(per_dir_entry->key, tmp.key, tmp.key_length);
  781: 	per_dir_entry->key[per_dir_entry->key_length] = 0;
  782: 
  783: 	per_dir_entry->value = (char *) malloc(tmp.value_length+1);
  784: 	memcpy(per_dir_entry->value, tmp.value, tmp.value_length);
  785: 	per_dir_entry->value[per_dir_entry->value_length] = 0;
  786: }
  787: /* }}} */
  788: 
  789: /* {{{ should_overwrite_per_dir_entry;
  790: 
  791:  */
  792: static zend_bool should_overwrite_per_dir_entry(HashTable *target_ht, php_per_dir_entry *orig_per_dir_entry, zend_hash_key *hash_key, void *pData)
  793: {
  794: 	php_per_dir_entry *new_per_dir_entry;
  795: 
  796: 	if (zend_hash_find(target_ht, hash_key->arKey, hash_key->nKeyLength, (void **) &new_per_dir_entry)==FAILURE) {
  797: 		return 1; /* does not exist in dest, copy from source */
  798: 	}
  799: 
  800: 	if (new_per_dir_entry->type==PHP_INI_SYSTEM
  801: 		&& orig_per_dir_entry->type!=PHP_INI_SYSTEM) {
  802: 		return 1;
  803: 	} else {
  804: 		return 0;
  805: 	}
  806: }
  807: /* }}} */
  808: /* {{{ php_destroy_per_server_info
  809:  */
  810: static void php_destroy_per_server_info(php_per_server_config *conf)
  811: {
  812: 	php_handler_stack_destroy(&conf->requires);
  813: 	php_handler_stack_destroy(&conf->uri_handlers);
  814: }
  815: /* }}} */
  816: 
  817: /* {{{ php_destroy_per_dir_info
  818:  */
  819: static void php_destroy_per_dir_info(php_per_dir_config *conf) 
  820: {
  821: 	zend_hash_destroy(conf->ini_settings);
  822: 	php_handler_stack_destroy(&conf->response_handlers);
  823: 	php_handler_stack_destroy(&conf->auth_handlers);
  824: 	php_handler_stack_destroy(&conf->access_handlers);
  825: 	php_handler_stack_destroy(&conf->type_handlers);
  826: 	php_handler_stack_destroy(&conf->fixup_handlers);
  827: 	php_handler_stack_destroy(&conf->logger_handlers);
  828: 	php_handler_stack_destroy(&conf->post_read_handlers);
  829: 	php_handler_stack_destroy(&conf->headers_handlers);
  830: 	free(conf->ini_settings);
  831: }
  832: /* }}} */
  833: 
  834: /* {{{ php_create_server
  835:  */
  836: static void *php_create_server(pool *p, char *dummy)
  837: {
  838: 	php_per_server_config *conf;
  839: 	conf = (php_per_server_config *) malloc(sizeof(php_per_server_config));
  840: 	register_cleanup(p, (void *) conf, (void (*)(void *)) php_destroy_per_server_info, (void (*)(void *)) php_destroy_per_server_info);
  841: 	
  842: 	sapi_stack_init_ex(&conf->requires, 1);
  843: 	sapi_stack_init_ex(&conf->uri_handlers, 1);
  844: 	return conf;
  845: }
  846: 	
  847: /* }}} */
  848: 
  849: 
  850: /* {{{ php_create_dir
  851:  */
  852: static void *php_create_dir(pool *p, char *dummy)
  853: {
  854: 	php_per_dir_config *conf;
  855: 	conf = (php_per_dir_config *) malloc(sizeof(php_per_dir_config));
  856: 	conf->ini_settings = (HashTable *) malloc(sizeof(HashTable));
  857: 	zend_hash_init_ex(conf->ini_settings, 5, NULL, (void (*)(void *)) destroy_per_dir_entry, 1, 0);
  858: 	sapi_stack_init_ex(&conf->response_handlers, 1);
  859: 	sapi_stack_init_ex(&conf->headers_handlers, 1);
  860: 	sapi_stack_init_ex(&conf->auth_handlers, 1);
  861: 	sapi_stack_init_ex(&conf->access_handlers, 1);
  862: 	sapi_stack_init_ex(&conf->type_handlers, 1);
  863: 	sapi_stack_init_ex(&conf->fixup_handlers, 1);
  864: 	sapi_stack_init_ex(&conf->logger_handlers, 1);
  865: 	sapi_stack_init_ex(&conf->post_read_handlers, 1);
  866: 	register_cleanup(p, (void *) conf, (void (*)(void *)) php_destroy_per_dir_info, (void (*)(void *)) php_destroy_per_dir_info);
  867: 	
  868: 	return conf;
  869: }
  870: 
  871: /* }}} */
  872: 
  873: /* {{{ php_merge_dir
  874:  */
  875: static void *php_merge_dir(pool *p, void *basev, void *addv)
  876: {
  877: 	php_per_dir_config *a = (php_per_dir_config *) addv;
  878: 	php_per_dir_config *b = (php_per_dir_config *) basev;
  879: 	/* This function *must* return addv, and not modify basev */
  880: 	zend_hash_merge_ex((HashTable *) a->ini_settings, (HashTable *) b->ini_settings, (copy_ctor_func_t) copy_per_dir_entry, sizeof(php_per_dir_entry), (merge_checker_func_t) should_overwrite_per_dir_entry, NULL);
  881: 	a->headers_handlers = (a->headers_handlers.top)?a->headers_handlers:b->headers_handlers;
  882: 	a->auth_handlers = (a->auth_handlers.top)?a->auth_handlers:b->auth_handlers;
  883: 	a->access_handlers = (a->access_handlers.top)?a->access_handlers:b->access_handlers;
  884: 	a->type_handlers = (a->type_handlers.top)?a->type_handlers:b->type_handlers;
  885: 	a->fixup_handlers = (a->fixup_handlers.top)?a->fixup_handlers:b->fixup_handlers;
  886: 	a->logger_handlers = (a->logger_handlers.top)?a->logger_handlers:b->logger_handlers;
  887: 	a->post_read_handlers = (a->post_read_handlers.top)?a->post_read_handlers:b->post_read_handlers;
  888: 	a->response_handlers = (a->response_handlers.top)?a->response_handlers:b->response_handlers;
  889: 	return a;
  890: }
  891: /* }}} */
  892: 
  893: /* {{{ php_apache_value_handler_ex
  894:  */
  895: static CONST_PREFIX char *php_apache_value_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode)
  896: {
  897: 	php_per_dir_entry per_dir_entry;
  898: 
  899: 	if (!apache_php_initialized) {
  900: 		apache_php_initialized = 1;
  901: #ifdef ZTS
  902: 		tsrm_startup(1, 1, 0, NULL);
  903: #endif
  904: 		sapi_startup(&apache_sapi_module);
  905: 		php_apache_startup(&apache_sapi_module);
  906: 	}
  907: 	per_dir_entry.type = mode;
  908: 
  909: 	if (strcasecmp(arg2, "none") == 0) {
  910: 		arg2 = "";
  911: 	}
  912: 
  913: 	per_dir_entry.key_length = strlen(arg1);
  914: 	per_dir_entry.value_length = strlen(arg2);
  915: 
  916: 	per_dir_entry.key = (char *) malloc(per_dir_entry.key_length+1);
  917: 	memcpy(per_dir_entry.key, arg1, per_dir_entry.key_length);
  918: 	per_dir_entry.key[per_dir_entry.key_length] = 0;
  919: 
  920: 	per_dir_entry.value = (char *) malloc(per_dir_entry.value_length+1);
  921: 	memcpy(per_dir_entry.value, arg2, per_dir_entry.value_length);
  922: 	per_dir_entry.value[per_dir_entry.value_length] = 0;
  923: 
  924: 	zend_hash_update(conf, per_dir_entry.key, per_dir_entry.key_length, &per_dir_entry, sizeof(php_per_dir_entry), NULL);
  925: 	return NULL;
  926: }
  927: /* }}} */
  928: 
  929: static CONST_PREFIX char *php_set_server_handler(server_rec *s, char *arg1, long handler_stage, long handler_type)
  930: {
  931: 	php_per_server_config *conf;
  932: 	php_handler *handler;
  933: 	handler = (php_handler *) malloc(sizeof(php_handler));
  934: 	handler->type = handler_type;
  935: 	handler->stage = handler_stage;
  936: 	handler->name = strdup(arg1);
  937: 	conf = get_module_config(s->module_config, &php5_module);
  938: 	switch(handler_stage) {
  939: 		case AP_URI_TRANS:
  940: 			sapi_stack_push(&conf->uri_handlers, handler);
  941: 			break;
  942: 		default:
  943: 			sapi_stack_push(&conf->requires, handler);
  944: 			break;
  945: 	}
  946: 	return NULL;
  947: }
  948: 
  949: static CONST_PREFIX char *php_set_dir_handler(php_per_dir_config *conf, char *arg1, long handler_stage, long handler_type)
  950: {
  951: 	php_handler *handler;
  952: 	handler = (php_handler *) malloc(sizeof(php_handler));
  953: 	handler->type = handler_type;
  954: 	handler->stage = handler_stage;
  955: 	handler->name = strdup(arg1);
  956: 	switch(handler_stage) {
  957: 		case AP_POST_READ:
  958: 			sapi_stack_push(&conf->post_read_handlers, handler);
  959: 			break;
  960: 		case AP_HEADER_PARSE:
  961: 			sapi_stack_push(&conf->headers_handlers, handler);
  962: 			break;
  963: 		case AP_ACCESS_CONTROL:
  964: 			sapi_stack_push(&conf->access_handlers, handler);
  965: 			break;
  966: 		case AP_AUTHENTICATION:
  967: 			sapi_stack_push(&conf->auth_handlers, handler);
  968: 			break;
  969: 		case AP_AUTHORIZATION:
  970: 			break;
  971: 		case AP_TYPE_CHECKING:
  972: 			sapi_stack_push(&conf->type_handlers, handler);
  973: 			break;
  974: 		case AP_FIXUP:
  975: 			sapi_stack_push(&conf->fixup_handlers, handler);
  976: 			break;
  977: 		case AP_RESPONSE:
  978: 			sapi_stack_push(&conf->response_handlers, handler);
  979: 			break;
  980: 		case AP_LOGGING:
  981: 			sapi_stack_push(&conf->logger_handlers, handler);
  982: 			break;
  983: 		default:
  984: 			break;
  985: 	}
  986: 	return NULL;
  987: }
  988: 
  989: /* {{{ php_set_uri_handler 
  990:  */
  991: static CONST_PREFIX char *php_set_uri_handler(cmd_parms *cmd, void *dummy, char *arg1)
  992: {
  993: 	return php_set_server_handler(cmd->server, arg1, AP_URI_TRANS, AP_HANDLER_TYPE_FILE);
  994: }
  995: /* }}} */
  996: 
  997: /* {{{ php_set_uri_handler_code */
  998: static CONST_PREFIX char *php_set_uri_handler_code(cmd_parms *cmd, void *dummy, char *arg1)
  999: {
 1000: 	return php_set_server_handler(cmd->server, arg1, AP_URI_TRANS, AP_HANDLER_TYPE_METHOD);
 1001: }
 1002: /* }}} */
 1003: 
 1004: /* {{{ php_set_header_handler
 1005:  */
 1006: static CONST_PREFIX char *php_set_header_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
 1007: {
 1008: 	return php_set_dir_handler(conf, arg1, AP_HEADER_PARSE, AP_HANDLER_TYPE_FILE);
 1009: }
 1010: static CONST_PREFIX char *php_set_header_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
 1011: {
 1012: 	return php_set_dir_handler(conf, arg1, AP_HEADER_PARSE, AP_HANDLER_TYPE_METHOD);
 1013: }
 1014: /* }}} */
 1015: 
 1016: /* {{{ php_set_auth_handler 
 1017:  */
 1018: static CONST_PREFIX char *php_set_auth_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
 1019: {
 1020: 	return php_set_dir_handler(conf, arg1, AP_AUTHENTICATION, AP_HANDLER_TYPE_FILE);
 1021: }
 1022: static CONST_PREFIX char *php_set_auth_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
 1023: {
 1024: 	return php_set_dir_handler(conf, arg1, AP_AUTHENTICATION, AP_HANDLER_TYPE_METHOD);
 1025: }
 1026: 
 1027: /* }}} */
 1028: 
 1029: /* {{{ php_set_access_handler
 1030:  */
 1031: static CONST_PREFIX char *php_set_access_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
 1032: {
 1033: 	return php_set_dir_handler(conf, arg1, AP_ACCESS_CONTROL, AP_HANDLER_TYPE_FILE);
 1034: }
 1035: static CONST_PREFIX char *php_set_access_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
 1036: {
 1037: 	return php_set_dir_handler(conf, arg1, AP_ACCESS_CONTROL, AP_HANDLER_TYPE_METHOD);
 1038: }
 1039: 
 1040: /* }}} */
 1041: 
 1042: /* {{{ php_set_type_handler
 1043:  */
 1044: static CONST_PREFIX char *php_set_type_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
 1045: {
 1046: 	return php_set_dir_handler(conf, arg1, AP_TYPE_CHECKING, AP_HANDLER_TYPE_FILE);
 1047: }
 1048: static CONST_PREFIX char *php_set_type_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
 1049: {
 1050: 	return php_set_dir_handler(conf, arg1, AP_TYPE_CHECKING, AP_HANDLER_TYPE_METHOD);
 1051: }
 1052: 
 1053: /* }}} */
 1054: 
 1055: /* {{{ php_set_fixup_handler
 1056:  */
 1057: static CONST_PREFIX char *php_set_fixup_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
 1058: {
 1059: 	return php_set_dir_handler(conf, arg1, AP_FIXUP, AP_HANDLER_TYPE_FILE);
 1060: }
 1061: static CONST_PREFIX char *php_set_fixup_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
 1062: {
 1063: 	return php_set_dir_handler(conf, arg1, AP_FIXUP, AP_HANDLER_TYPE_METHOD);
 1064: }
 1065: /* }}} */
 1066: 
 1067: /* {{{ php_set_logger_handler
 1068:  */
 1069: static CONST_PREFIX char *php_set_logger_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
 1070: {
 1071: 	return php_set_dir_handler(conf, arg1, AP_LOGGING, AP_HANDLER_TYPE_FILE);
 1072: }
 1073: static CONST_PREFIX char *php_set_logger_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
 1074: {
 1075: 	return php_set_dir_handler(conf, arg1, AP_LOGGING, AP_HANDLER_TYPE_METHOD);
 1076: }
 1077: 
 1078: /* }}} */ 
 1079: 
 1080: /* {{{ php_set_post_read_handler
 1081:  */
 1082: static CONST_PREFIX char *php_set_post_read_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
 1083: {
 1084: 	return php_set_dir_handler(conf, arg1, AP_POST_READ, AP_HANDLER_TYPE_FILE);
 1085: }
 1086: static CONST_PREFIX char *php_set_post_read_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
 1087: {
 1088: 	return php_set_dir_handler(conf, arg1, AP_POST_READ, AP_HANDLER_TYPE_METHOD);
 1089: }
 1090: 
 1091: 
 1092: /* }}} */
 1093: 
 1094: /* {{{ php_set_require
 1095:  */
 1096: 
 1097: static CONST_PREFIX char *php_set_require(cmd_parms *cmd, void *dummy, char *arg1)
 1098: {
 1099: 	return php_set_server_handler(cmd->server, arg1, 0, AP_HANDLER_TYPE_FILE);
 1100: }
 1101: /* }}} */
 1102: 
 1103: /* {{{ php_set_response_handler
 1104:  */
 1105: static CONST_PREFIX char *php_set_response_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
 1106: {
 1107: 	return php_set_dir_handler(conf, arg1, AP_RESPONSE, AP_HANDLER_TYPE_FILE);
 1108: }
 1109: static CONST_PREFIX char *php_set_response_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1)
 1110: {
 1111: 	return php_set_dir_handler(conf, arg1, AP_RESPONSE, AP_HANDLER_TYPE_METHOD);
 1112: }
 1113: /* }}} */
 1114: 	
 1115: /* {{{ php_apache_value_handler
 1116:  */
 1117: static CONST_PREFIX char *php_apache_value_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1, char *arg2)
 1118: {
 1119: 	return php_apache_value_handler_ex(cmd, conf->ini_settings, arg1, arg2, PHP_INI_PERDIR);
 1120: }
 1121: /* }}} */
 1122: 
 1123: /* {{{ php_apache_admin_value_handler
 1124:  */
 1125: static CONST_PREFIX char *php_apache_admin_value_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1, char *arg2)
 1126: {
 1127: 	return php_apache_value_handler_ex(cmd, conf->ini_settings, arg1, arg2, PHP_INI_SYSTEM);
 1128: }
 1129: /* }}} */
 1130: 
 1131: /* {{{ php_apache_flag_handler_ex
 1132:  */
 1133: static CONST_PREFIX char *php_apache_flag_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode)
 1134: {
 1135: 	char bool_val[2];
 1136: 
 1137: 	if (!strcasecmp(arg2, "On")) {
 1138: 		bool_val[0] = '1';
 1139: 	} else {
 1140: 		bool_val[0] = '0';
 1141: 	}
 1142: 	bool_val[1] = 0;
 1143: 	
 1144: 	return php_apache_value_handler_ex(cmd, conf, arg1, bool_val, mode);
 1145: }
 1146: /* }}} */
 1147: 
 1148: /* {{{ php_apache_flag_handler
 1149:  */
 1150: static CONST_PREFIX char *php_apache_flag_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1, char *arg2)
 1151: {
 1152: 	return php_apache_flag_handler_ex(cmd, conf->ini_settings, arg1, arg2, PHP_INI_PERDIR);
 1153: }
 1154: /* }}} */
 1155: 
 1156: /* {{{ php_apache_admin_flag_handler
 1157:  */
 1158: static CONST_PREFIX char *php_apache_admin_flag_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1, char *arg2)
 1159: {
 1160: 	return php_apache_flag_handler_ex(cmd, conf->ini_settings, arg1, arg2, PHP_INI_SYSTEM);
 1161: }
 1162: /* }}} */
 1163: 
 1164: /* {{{ php_apache_phpini_set
 1165:  */
 1166: static CONST_PREFIX char *php_apache_phpini_set(cmd_parms *cmd, HashTable *conf, char *arg)
 1167: {
 1168: 	if (apache_sapi_module.php_ini_path_override) {
 1169: 		return "Only first PHPINIDir directive honored per configuration tree - subsequent ones ignored";
 1170: 	}
 1171: 	apache_sapi_module.php_ini_path_override = ap_server_root_relative(cmd->pool, arg);
 1172: 	return NULL;
 1173: }
 1174: /* }}} */
 1175: 
 1176: /* {{{ int php_xbithack_handler(request_rec * r)
 1177:  */
 1178: static int php_xbithack_handler(request_rec * r)
 1179: {
 1180: 	php_per_dir_config *conf;
 1181: 	TSRMLS_FETCH();
 1182: 
 1183: 	if (!(r->finfo.st_mode & S_IXUSR)) {
 1184: 		r->allowed |= (1 << METHODS) - 1;
 1185: 		return DECLINED;
 1186: 	}
 1187: 	conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
 1188: 	if (conf) {
 1189: 		zend_hash_apply((HashTable *) conf->ini_settings, (apply_func_t) php_apache_alter_ini_entries TSRMLS_CC);
 1190: 	}
 1191: 	if(!AP(xbithack)) {
 1192: 		r->allowed |= (1 << METHODS) - 1;
 1193: 		zend_try {
 1194: 			zend_ini_deactivate(TSRMLS_C);
 1195: 		} zend_end_try();
 1196: 		return DECLINED;
 1197: 	}
 1198: 	return send_parsed_php(r);
 1199: }
 1200: /* }}} */
 1201: 
 1202: /* {{{ apache_php_module_shutdown_wrapper
 1203:  */
 1204: static void apache_php_module_shutdown_wrapper(void)
 1205: {
 1206: 	apache_php_initialized = 0;
 1207: 	apache_sapi_module.shutdown(&apache_sapi_module);
 1208: 
 1209: #if MODULE_MAGIC_NUMBER >= 19970728
 1210: 	/* This function is only called on server exit if the apache API
 1211: 	 * child_exit handler exists, so shutdown globally 
 1212: 	 */
 1213: 	sapi_shutdown();
 1214: #endif
 1215: 
 1216: #ifdef ZTS
 1217: 	tsrm_shutdown();
 1218: #endif
 1219: }
 1220: /* }}} */
 1221: 
 1222: #if MODULE_MAGIC_NUMBER >= 19970728
 1223: /* {{{ php_child_exit_handler
 1224:  */
 1225: static void php_child_exit_handler(server_rec *s, pool *p)
 1226: {
 1227: /*	apache_php_initialized = 0; */
 1228: 	apache_sapi_module.shutdown(&apache_sapi_module);
 1229: 
 1230: #ifdef ZTS
 1231: 	tsrm_shutdown();
 1232: #endif
 1233: }
 1234: /* }}} */
 1235: #endif
 1236: 
 1237: /* {{{ void php_init_handler(server_rec *s, pool *p)
 1238:  */
 1239: static void php_init_handler(server_rec *s, pool *p)
 1240: {
 1241: 	register_cleanup(p, NULL, (void (*)(void *))apache_php_module_shutdown_wrapper, (void (*)(void *))php_module_shutdown_for_exec);
 1242: 	if (!apache_php_initialized) {
 1243: 		apache_php_initialized = 1;
 1244: #ifdef ZTS
 1245: 		tsrm_startup(1, 1, 0, NULL);
 1246: #endif
 1247: 		sapi_startup(&apache_sapi_module);
 1248: 		php_apache_startup(&apache_sapi_module);
 1249: 	}
 1250: #if MODULE_MAGIC_NUMBER >= 19980527
 1251: 	{
 1252: 		TSRMLS_FETCH();
 1253: 		if (PG(expose_php)) {
 1254: 			ap_add_version_component("PHP/" PHP_VERSION);
 1255: 		}
 1256: 	}
 1257: #endif
 1258: }
 1259: /* }}} */
 1260: 
 1261: static int php_run_hook(php_handler *handler, request_rec *r)
 1262: {
 1263: 	zval *ret = NULL;
 1264: 	php_per_dir_config *conf;
 1265: 
 1266: 	TSRMLS_FETCH();
 1267: 
 1268: 	if(!AP(apache_config_loaded)) {
 1269: 		conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
 1270: 		if (conf)
 1271: 			   zend_hash_apply((HashTable *)conf->ini_settings, (apply_func_t) php_apache_alter_ini_entries TSRMLS_CC);
 1272: 		AP(apache_config_loaded) = 1;
 1273: 	}
 1274: 	if (!handler->name) {
 1275: 		return DECLINED;
 1276: 	}
 1277: 	php_save_umask();
 1278: 	if (!AP(setup_env)) {
 1279: 		AP(setup_env) = 1;
 1280: 		add_common_vars(r);
 1281: 		add_cgi_vars(r);
 1282: 	}
 1283: 	SG(server_context) = r;
 1284: 	init_request_info(TSRMLS_C);
 1285: 	apache_php_module_hook(r, handler, &ret TSRMLS_CC);
 1286: 	php_restore_umask();
 1287: 	kill_timeout(r);
 1288: 	if (ret) {
 1289: 		convert_to_long(ret);
 1290: 		return Z_LVAL_P(ret);
 1291: 	}
 1292: 	return HTTP_INTERNAL_SERVER_ERROR;
 1293: }
 1294:  
 1295: 
 1296: static int php_uri_translation(request_rec *r)
 1297: {	
 1298: 	php_per_server_config *conf;
 1299: 	TSRMLS_FETCH();
 1300: 	AP(current_hook) = AP_URI_TRANS;
 1301: 	conf = (php_per_server_config *) get_module_config(r->server->module_config, &php5_module);
 1302: 	return sapi_stack_apply_with_argument_stop_if_equals(&conf->uri_handlers, 
 1303: 			ZEND_STACK_APPLY_BOTTOMUP, 
 1304: 			(int (*)(void *element, void *)) php_run_hook, r, OK);
 1305: }
 1306: 
 1307: static int php_header_hook(request_rec *r)
 1308: {
 1309: 	php_per_dir_config *conf;
 1310: 	TSRMLS_FETCH();
 1311: 	AP(current_hook) = AP_HEADER_PARSE;
 1312: 	conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
 1313: 	return sapi_stack_apply_with_argument_stop_if_http_error(&conf->headers_handlers,
 1314: 			ZEND_STACK_APPLY_BOTTOMUP,
 1315: 			(int (*)(void *element, void *)) php_run_hook, r);
 1316: }
 1317: 
 1318: static int php_auth_hook(request_rec *r)
 1319: {
 1320: 	php_per_dir_config *conf;
 1321: 	TSRMLS_FETCH();
 1322: 	AP(current_hook) = AP_AUTHENTICATION;
 1323: 	conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
 1324: 	return sapi_stack_apply_with_argument_stop_if_equals(&conf->auth_handlers, 
 1325: 			ZEND_STACK_APPLY_BOTTOMUP, 
 1326: 			(int (*)(void *element, void *)) php_run_hook, r, OK);
 1327: }
 1328: 
 1329: static int php_access_hook(request_rec *r)
 1330: {
 1331: 	php_per_dir_config *conf;
 1332: 	int status = DECLINED;
 1333: 	TSRMLS_FETCH();
 1334: 	AP(current_hook) = AP_ACCESS_CONTROL;
 1335: 	conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
 1336: 	status =  sapi_stack_apply_with_argument_stop_if_http_error(&conf->access_handlers,
 1337: 			ZEND_STACK_APPLY_BOTTOMUP,
 1338: 			(int (*)(void *element, void *)) php_run_hook, r);
 1339: 	return status;
 1340: 
 1341: }
 1342: 
 1343: static int php_type_hook(request_rec *r)
 1344: {
 1345: 	php_per_dir_config *conf;
 1346: 	TSRMLS_FETCH();
 1347: 	AP(current_hook) = AP_TYPE_CHECKING;
 1348: 	conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
 1349: 	return sapi_stack_apply_with_argument_stop_if_equals(&conf->type_handlers,
 1350: 			ZEND_STACK_APPLY_BOTTOMUP,
 1351: 			(int (*)(void *element, void *)) php_run_hook,
 1352: 			r, OK);
 1353: }
 1354: 
 1355: static int php_fixup_hook(request_rec *r)
 1356: {
 1357: 	php_per_dir_config *conf;
 1358: 	TSRMLS_FETCH();
 1359: 	AP(current_hook) = AP_FIXUP;
 1360: 	conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
 1361: 	return sapi_stack_apply_with_argument_stop_if_http_error(&conf->fixup_handlers,
 1362: 			ZEND_STACK_APPLY_BOTTOMUP,
 1363: 			(int (*)(void *element, void *)) php_run_hook,
 1364: 			r);
 1365: }
 1366: 
 1367: static int php_logger_hook(request_rec *r)
 1368: {
 1369: 	php_per_dir_config *conf;
 1370: 	TSRMLS_FETCH();
 1371: 	AP(current_hook) = AP_LOGGING;
 1372: 	conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
 1373: 	return sapi_stack_apply_with_argument_stop_if_http_error(&conf->logger_handlers,
 1374: 			ZEND_STACK_APPLY_BOTTOMUP,
 1375: 			(int (*)(void *element, void *)) php_run_hook,
 1376: 			r);
 1377: }
 1378:  
 1379: static int php_post_read_hook(request_rec *r)
 1380: {
 1381: 	php_per_dir_config *conf;
 1382: 	php_per_server_config *svr;
 1383: 	TSRMLS_FETCH();
 1384: 	AP(current_hook) = AP_POST_READ;
 1385: 	svr = get_module_config(r->server->module_config, &php5_module);
 1386: 	if(ap_is_initial_req(r)) {
 1387: 		sapi_stack_apply_with_argument_all(&svr->requires, ZEND_STACK_APPLY_BOTTOMUP, (int (*)(void *element, void *)) php_run_hook, r);
 1388: 	}
 1389: 	conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
 1390: 	return sapi_stack_apply_with_argument_stop_if_http_error(&conf->post_read_handlers,
 1391: 			ZEND_STACK_APPLY_BOTTOMUP,
 1392: 			(int (*)(void *element, void *)) php_run_hook, r);
 1393: }
 1394: 
 1395: static int php_response_handler(request_rec *r)
 1396: {
 1397: 	php_per_dir_config *conf;
 1398: 	TSRMLS_FETCH();
 1399: 	AP(current_hook) = AP_RESPONSE;
 1400: 	conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module);
 1401: 	return sapi_stack_apply_with_argument_all(&conf->response_handlers, ZEND_STACK_APPLY_BOTTOMUP, (int (*)(void *element, void *)) php_run_hook, r);
 1402: }
 1403: 
 1404: /* {{{ handler_rec php_handlers[]
 1405:  */
 1406: handler_rec php_handlers[] =
 1407: {
 1408: 	{"application/x-httpd-php", send_parsed_php},
 1409: 	{"application/x-httpd-php-source", send_parsed_php_source},
 1410: 	{"text/html", php_xbithack_handler},
 1411: 		{"php-script", php_response_handler},
 1412: 	{NULL}
 1413: };
 1414: /* }}} */
 1415: 
 1416: /* {{{ command_rec php_commands[]
 1417:  */
 1418: command_rec php_commands[] =
 1419: {
 1420: 	{"php_value",		php_apache_value_handler, NULL, OR_OPTIONS, TAKE2, "PHP Value Modifier"},
 1421: 	{"phpUriHandler",		php_set_uri_handler, NULL, RSRC_CONF, TAKE1, "PHP Value Modifier"},
 1422: 	{"phpUriHandlerMethod",		php_set_uri_handler_code, NULL, RSRC_CONF, TAKE1, "PHP Value Modifier"},
 1423: #if MODULE_MAGIC_NUMBER >= 19970103
 1424: 	{"phpHeaderHandler",		php_set_header_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
 1425: 	{"phpHeaderHandlerMethod",		php_set_header_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
 1426: #endif
 1427: 	{"phpAuthHandler",		php_set_auth_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
 1428: 	{"phpAuthHandlerMethod",		php_set_auth_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
 1429: 	{"phpAccessHandler",		php_set_access_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
 1430: 	{"phpAccessHandlerMethod",		php_set_access_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
 1431: 	{"phpTypeHandler",		php_set_type_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
 1432: 	{"phpTypeHandlerMethod",		php_set_type_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
 1433: 	{"phpFixupHandler",		php_set_fixup_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
 1434: 	{"phpFixupHandlerMethod",		php_set_fixup_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
 1435: 	{"phpLoggerHandler",			php_set_logger_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
 1436: 	{"phpLoggerHandlerMethod",		php_set_logger_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
 1437: #if MODULE_MAGIC_NUMBER >= 19970902
 1438: 	{"phpPostReadHandler",		php_set_post_read_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
 1439: 	{"phpPostReadHandlerMethod",		php_set_post_read_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
 1440: 	{"phpRequire",		php_set_require, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
 1441: 	{"phpResponseHandler",		php_set_response_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
 1442: 	{"phpResponseHandlerMethod",		php_set_response_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"},
 1443: #endif
 1444: 	{"php_flag",		php_apache_flag_handler, NULL, OR_OPTIONS, TAKE2, "PHP Flag Modifier"},
 1445: 	{"php_admin_value",	php_apache_admin_value_handler, NULL, ACCESS_CONF|RSRC_CONF, TAKE2, "PHP Value Modifier (Admin)"},
 1446: 	{"php_admin_flag",	php_apache_admin_flag_handler, NULL, ACCESS_CONF|RSRC_CONF, TAKE2, "PHP Flag Modifier (Admin)"},
 1447: 	{"PHPINIDir",       php_apache_phpini_set, NULL, RSRC_CONF, TAKE1, "Directory containing the php.ini file"},
 1448: 	{NULL}
 1449: };
 1450: /* }}} */
 1451: 
 1452: /* {{{ module MODULE_VAR_EXPORT php5_module
 1453:  */
 1454: module MODULE_VAR_EXPORT php5_module =
 1455: {
 1456: 	STANDARD_MODULE_STUFF,
 1457: 	php_init_handler,			/* initializer */
 1458: 	php_create_dir,				/* per-directory config creator */
 1459: 	php_merge_dir,				/* dir merger */
 1460: 	php_create_server,			/* per-server config creator */
 1461: 	NULL, 						/* merge server config */
 1462: 	php_commands,				/* command table */
 1463: 	php_handlers,				/* handlers */
 1464: 	php_uri_translation,		/* filename translation */
 1465: 	NULL,						/* check_user_id */
 1466: 	php_auth_hook,				/* check auth */
 1467: 	php_access_hook,			/* check access */
 1468: 	php_type_hook,				/* type_checker */
 1469: 	php_fixup_hook,				/* fixups */
 1470: 	php_logger_hook				/* logger */
 1471: #if MODULE_MAGIC_NUMBER >= 19970103
 1472: 	, php_header_hook						/* header parser */
 1473: #endif
 1474: #if MODULE_MAGIC_NUMBER >= 19970719
 1475: 	, NULL			 			/* child_init */
 1476: #endif
 1477: #if MODULE_MAGIC_NUMBER >= 19970728
 1478: 	, php_child_exit_handler	/* child_exit */
 1479: #endif
 1480: #if MODULE_MAGIC_NUMBER >= 19970902
 1481: 	, php_post_read_hook						/* post read-request */
 1482: #endif
 1483: };
 1484: /* }}} */
 1485: 
 1486: /*
 1487:  * Local variables:
 1488:  * tab-width: 4
 1489:  * c-basic-offset: 4
 1490:  * End:
 1491:  * vim600: sw=4 ts=4 fdm=marker
 1492:  * vim<600: sw=4 ts=4
 1493:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>