PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LTP GCOV extension - code coverage report
Current view: directory - var/php_gcov/PHP_HEAD/main - SAPI.c
Test: PHP Code Coverage
Date: 2009-11-23 Instrumented lines: 470
Code covered: 75.7 % Executed lines: 356
Legend: not executed executed

       1                 : /* 
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 6                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2009 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 through the world-wide-web at the following url:           |
      10                 :    | http://www.php.net/license/3_01.txt                                  |
      11                 :    | If you did not receive a copy of the PHP license and are unable to   |
      12                 :    | obtain it through the world-wide-web, please send a note to          |
      13                 :    | license@php.net so we can mail you a copy immediately.               |
      14                 :    +----------------------------------------------------------------------+
      15                 :    | Original design:  Shane Caraveo <shane@caraveo.com>                  |
      16                 :    | Authors: Andi Gutmans <andi@zend.com>                                |
      17                 :    |          Zeev Suraski <zeev@zend.com>                                |
      18                 :    +----------------------------------------------------------------------+
      19                 : */
      20                 : 
      21                 : /* $Id: SAPI.c 290761 2009-11-14 22:42:08Z jani $ */
      22                 : 
      23                 : #include <ctype.h>
      24                 : #include <sys/stat.h>
      25                 : 
      26                 : #include "php.h"
      27                 : #include "SAPI.h"
      28                 : #include "php_variables.h"
      29                 : #include "php_ini.h"
      30                 : #include "ext/standard/php_string.h"
      31                 : #include "ext/standard/pageinfo.h"
      32                 : #ifdef ZTS
      33                 : #include "TSRM.h"
      34                 : #endif
      35                 : #ifdef HAVE_SYS_TIME_H
      36                 : #include <sys/time.h>
      37                 : #endif
      38                 : 
      39                 : #include "rfc1867.h"
      40                 : 
      41                 : #ifdef PHP_WIN32
      42                 : #define STRCASECMP stricmp
      43                 : #else
      44                 : #define STRCASECMP strcasecmp
      45                 : #endif
      46                 : 
      47                 : #include "php_content_types.h"
      48                 : 
      49                 : #ifdef ZTS
      50                 : SAPI_API int sapi_globals_id;
      51                 : #else
      52                 : sapi_globals_struct sapi_globals;
      53                 : #endif
      54                 : 
      55                 : static void sapi_globals_ctor(sapi_globals_struct *sapi_globals TSRMLS_DC)
      56           17007 : {
      57           17007 :         memset(sapi_globals, 0, sizeof(*sapi_globals));
      58           17007 :         zend_hash_init_ex(&sapi_globals->known_post_content_types, 5, NULL, NULL, 1, 0);
      59           17007 :         php_setup_sapi_content_types(TSRMLS_C);
      60           17007 : }
      61                 : 
      62                 : static void sapi_globals_dtor(sapi_globals_struct *sapi_globals TSRMLS_DC)
      63           17039 : {
      64           17039 :         zend_hash_destroy(&sapi_globals->known_post_content_types);
      65           17039 : }
      66                 : 
      67                 : /* True globals (no need for thread safety) */
      68                 : SAPI_API sapi_module_struct sapi_module;
      69                 : 
      70                 : SAPI_API void sapi_startup(sapi_module_struct *sf)
      71           17007 : {
      72           17007 :         sf->ini_entries = NULL;
      73           17007 :         sapi_module = *sf;
      74                 : 
      75                 : #ifdef ZTS
      76                 :         ts_allocate_id(&sapi_globals_id, sizeof(sapi_globals_struct), (ts_allocate_ctor) sapi_globals_ctor, (ts_allocate_dtor) sapi_globals_dtor);
      77                 : #else
      78           17007 :         sapi_globals_ctor(&sapi_globals);
      79                 : #endif
      80                 : 
      81           17007 :         virtual_cwd_startup(); /* Could use shutdown to free the main cwd but it would just slow it down for CGI */
      82                 : 
      83                 : #ifdef PHP_WIN32
      84                 :         tsrm_win32_startup();
      85                 : #endif
      86                 : 
      87                 :         reentrancy_startup();
      88           17007 : }
      89                 : 
      90                 : SAPI_API void sapi_shutdown(void)
      91           17039 : {
      92                 : #ifdef ZTS
      93                 :         ts_free_id(sapi_globals_id);
      94                 : #else
      95           17039 :         sapi_globals_dtor(&sapi_globals);
      96                 : #endif
      97                 : 
      98                 :         reentrancy_shutdown();
      99                 : 
     100           17039 :         virtual_cwd_shutdown();
     101                 : 
     102                 : #ifdef PHP_WIN32
     103                 :         tsrm_win32_shutdown();
     104                 : #endif
     105           17039 : }
     106                 : 
     107                 : SAPI_API void sapi_free_header(sapi_header_struct *sapi_header)
     108           35001 : {
     109           35001 :         efree(sapi_header->header);
     110           35001 : }
     111                 : 
     112                 : SAPI_API void sapi_handle_post(void *arg TSRMLS_DC)
     113              49 : {
     114              49 :         if (SG(request_info).post_entry && SG(request_info).content_type_dup) {
     115                 :                 /*
     116                 :                  * We need to re-populate post_data from the stored raw POST data in case we had
     117                 :                  * any before, so that the handler can get to it.
     118                 :                  */
     119              48 :                 if (SG(request_info).post_data == NULL && SG(request_info).raw_post_data != NULL) {
     120               0 :                         SG(request_info).post_data = estrndup(SG(request_info).raw_post_data, SG(request_info).raw_post_data_length);
     121                 :                 }
     122              48 :                 SG(request_info).post_entry->post_handler(SG(request_info).content_type_dup, arg TSRMLS_CC);
     123              48 :                 if (SG(request_info).post_data) {
     124              17 :                         efree(SG(request_info).post_data);
     125              17 :                         SG(request_info).post_data = NULL;
     126                 :                 }
     127                 : #if 0 /* UTODO see if this works */
     128                 :                 efree(SG(request_info).content_type_dup);
     129                 :                 SG(request_info).content_type_dup = NULL;
     130                 : #endif
     131                 :         }
     132              49 : }
     133                 : 
     134                 : static void sapi_read_post_data(TSRMLS_D)
     135              58 : {
     136                 :         sapi_post_entry *post_entry;
     137              58 :         uint content_type_length = strlen(SG(request_info).content_type);
     138              58 :         char *content_type = estrndup(SG(request_info).content_type, content_type_length);
     139                 :         char *p;
     140              58 :         char oldchar=0;
     141              58 :         void (*post_reader_func)(TSRMLS_D) = NULL;
     142                 : 
     143                 :         /* dedicated implementation for increased performance:
     144                 :          * - Make the content type lowercase
     145                 :          * - Trim descriptive data, stay with the content-type only
     146                 :          */
     147            1599 :         for (p=content_type; p<content_type+content_type_length; p++) {
     148            1541 :                 switch (*p) {
     149                 :                         case ';':
     150                 :                         case ',':
     151                 :                         case ' ':
     152              26 :                                 content_type_length = p-content_type;
     153              26 :                                 oldchar = *p;
     154              26 :                                 *p = 0;
     155              26 :                                 break;
     156                 :                         default:
     157            1515 :                                 *p = tolower(*p);
     158                 :                                 break;
     159                 :                 }
     160                 :         }
     161                 : 
     162                 :         /* now try to find an appropriate POST content handler */
     163              58 :         if (zend_hash_find(&SG(known_post_content_types), content_type, content_type_length + 1, (void **) &post_entry) == SUCCESS) {
     164                 :                 /* found one, register it for use */
     165              57 :                 SG(request_info).post_entry = post_entry;
     166              57 :                 post_reader_func = post_entry->post_reader;
     167                 :         } else {
     168                 :                 /* fallback */
     169               1 :                 SG(request_info).post_entry = NULL;
     170               1 :                 if (!sapi_module.default_post_reader) {
     171                 :                         /* no default reader ? */
     172               0 :                         SG(request_info).content_type_dup = NULL;
     173               0 :                         sapi_module.sapi_error(E_WARNING, "Unsupported content type:  '%s'", content_type);
     174               0 :                         return;
     175                 :                 }
     176                 :         }
     177              58 :         if (oldchar) {
     178              26 :                 *(p-1) = oldchar;
     179                 :         }
     180                 : 
     181              58 :         SG(request_info).content_type_dup = content_type;
     182                 : 
     183              58 :         if (post_reader_func) {
     184              30 :                 post_reader_func(TSRMLS_C);
     185                 :         }
     186                 : 
     187              58 :         if (sapi_module.default_post_reader) {
     188              58 :                 sapi_module.default_post_reader(TSRMLS_C);
     189                 :         }
     190                 : }
     191                 : 
     192                 : SAPI_API SAPI_POST_READER_FUNC(sapi_read_standard_form_data)
     193              31 : {
     194                 :         int read_bytes;
     195              31 :         int allocated_bytes=SAPI_POST_BLOCK_SIZE+1;
     196                 : 
     197              31 :         if (SG(request_info).content_length > SG(post_max_size)) {
     198               1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "POST Content-Length of %ld bytes exceeds the limit of %ld bytes", SG(request_info).content_length, SG(post_max_size));
     199               1 :                 return;
     200                 :         }
     201              30 :         SG(request_info).post_data = emalloc(allocated_bytes);
     202                 : 
     203                 :         for (;;) {
     204              30 :                 read_bytes = sapi_module.read_post(SG(request_info).post_data+SG(read_post_bytes), SAPI_POST_BLOCK_SIZE TSRMLS_CC);
     205              30 :                 if (read_bytes<=0) {
     206               0 :                         break;
     207                 :                 }
     208              30 :                 SG(read_post_bytes) += read_bytes;
     209              30 :                 if (SG(read_post_bytes) > SG(post_max_size)) {
     210               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Actual POST length does not match Content-Length, and exceeds %ld bytes", SG(post_max_size));
     211               0 :                         break;
     212                 :                 }
     213              30 :                 if (read_bytes < SAPI_POST_BLOCK_SIZE) {
     214              30 :                         break;
     215                 :                 }
     216               0 :                 if (SG(read_post_bytes)+SAPI_POST_BLOCK_SIZE >= allocated_bytes) {
     217               0 :                         allocated_bytes = SG(read_post_bytes)+SAPI_POST_BLOCK_SIZE+1;
     218               0 :                         SG(request_info).post_data = erealloc(SG(request_info).post_data, allocated_bytes);
     219                 :                 }
     220               0 :         }
     221              30 :         SG(request_info).post_data[SG(read_post_bytes)] = 0; /* terminating NULL */
     222              30 :         SG(request_info).post_data_length = SG(read_post_bytes);
     223                 : }
     224                 : 
     225                 : /* {{{ sapi_update_default_charset */
     226                 : SAPI_API void sapi_update_default_charset(TSRMLS_D)
     227           33731 : {
     228           33731 :         const char *canonical_name = NULL;
     229           33731 :         UErrorCode status = U_ZERO_ERROR;
     230                 : 
     231           33731 :         canonical_name = ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status);
     232                 :         /*
     233                 :          * UTODO handle NULL return which signifies that MIME standard has no
     234                 :          * name for this converter
     235                 :          */
     236           33731 :         SG(default_charset) = (char *)ucnv_getStandardName(canonical_name, "MIME", &status);
     237           33731 : }
     238                 : /* }}} */
     239                 : 
     240                 : SAPI_API char *sapi_get_default_content_type(TSRMLS_D)
     241           16738 : {
     242                 :         char *mimetype, *charset, *content_type;
     243                 : 
     244           16738 :         mimetype = SG(default_mimetype) ? SG(default_mimetype) : SAPI_DEFAULT_MIMETYPE;
     245                 :         /*
     246                 :          * Apache SAPI may invoke this function directly, before php_request_startup() is
     247                 :          * called, so we need to update the default charset explicitly.
     248                 :          */
     249           16738 :         sapi_update_default_charset(TSRMLS_C);
     250           16738 :         charset = SG(default_charset) ? SG(default_charset) : SAPI_DEFAULT_CHARSET;
     251                 : 
     252           33476 :         if (strncasecmp(mimetype, "text/", 5) == 0 && *charset) {
     253           16738 :                 int len = strlen(mimetype) + sizeof("; charset=") + strlen(charset); /* sizeof() includes \0 */
     254           16738 :                 content_type = emalloc(len);
     255           16738 :                 snprintf(content_type, len, "%s; charset=%s", mimetype, charset);
     256                 :         } else {
     257               0 :                 content_type = estrdup(mimetype);
     258                 :         }
     259           16738 :         return content_type;
     260                 : }
     261                 : 
     262                 : SAPI_API void sapi_get_default_content_type_header(sapi_header_struct *default_header TSRMLS_DC)
     263           16738 : {
     264           16738 :         char *default_content_type = sapi_get_default_content_type(TSRMLS_C);
     265           16738 :         int default_content_type_len = strlen(default_content_type);
     266                 : 
     267           16738 :         default_header->header_len = (sizeof("Content-type: ")-1) + default_content_type_len;
     268           16738 :         default_header->header = emalloc(default_header->header_len+1);
     269           16738 :         memcpy(default_header->header, "Content-type: ", sizeof("Content-type: "));
     270           16738 :         memcpy(default_header->header+sizeof("Content-type: ")-1, default_content_type, default_content_type_len);
     271           16738 :         default_header->header[default_header->header_len] = 0;
     272           16738 :         efree(default_content_type);
     273           16738 : }
     274                 : 
     275                 : /*
     276                 :  * Add charset on content-type header if the MIME type starts with
     277                 :  * "text/", the default_charset directive is not empty and
     278                 :  * there is not already a charset option in there.
     279                 :  *
     280                 :  * If "mimetype" is non-NULL, it should point to a pointer allocated
     281                 :  * with emalloc(). If a charset is added, the string will be
     282                 :  * re-allocated and the new length is returned. If mimetype is
     283                 :  * unchanged, 0 is returned.
     284                 :  *
     285                 :  */
     286                 : SAPI_API size_t sapi_apply_default_charset(char **mimetype, size_t len TSRMLS_DC)
     287           16919 : {
     288                 :         char *charset, *newtype;
     289                 :         size_t newlen;
     290                 : 
     291           16919 :         charset = SG(default_charset) ? SG(default_charset) : SAPI_DEFAULT_CHARSET;
     292                 : 
     293           16919 :         if (*mimetype != NULL) {
     294           16919 :                 if (*charset && strncmp(*mimetype, "text/", 5) == 0 && strstr(*mimetype, "charset=") == NULL) {
     295              12 :                         newlen = len + (sizeof(";charset=")-1) + strlen(charset);
     296              12 :                         newtype = emalloc(newlen + 1);
     297              12 :                         PHP_STRLCPY(newtype, *mimetype, newlen + 1, len);
     298              12 :                         strlcat(newtype, ";charset=", newlen + 1);
     299              12 :                         strlcat(newtype, charset, newlen + 1);
     300              12 :                         efree(*mimetype);
     301              12 :                         *mimetype = newtype;
     302              12 :                         return newlen;
     303                 :                 }
     304                 :         }
     305           16907 :         return 0;
     306                 : }
     307                 : 
     308                 : SAPI_API void sapi_activate_headers_only(TSRMLS_D)
     309               0 : {
     310               0 :         if (SG(request_info).headers_read == 1) {
     311               0 :                 return;
     312                 :         }
     313               0 :         SG(request_info).headers_read = 1;
     314               0 :         zend_llist_init(&SG(sapi_headers).headers, sizeof(sapi_header_struct), (void (*)(void *)) sapi_free_header, 0);
     315               0 :         SG(sapi_headers).send_default_content_type = 1;
     316                 : 
     317                 :         /* SG(sapi_headers).http_response_code = 200; */
     318               0 :         SG(sapi_headers).http_status_line = NULL;
     319               0 :         SG(sapi_headers).mimetype = NULL;
     320               0 :         SG(read_post_bytes) = 0;
     321               0 :         SG(request_info).post_data = NULL;
     322               0 :         SG(request_info).raw_post_data = NULL;
     323               0 :         SG(request_info).current_user = NULL;
     324               0 :         SG(request_info).current_user_length = 0;
     325               0 :         SG(request_info).no_headers = 0;
     326               0 :         SG(request_info).post_entry = NULL;
     327               0 :         SG(global_request_time) = 0;
     328                 : 
     329                 :         /*
     330                 :          * It's possible to override this general case in the activate() callback,
     331                 :          * if necessary.
     332                 :          */
     333               0 :         if (SG(request_info).request_method && !strcmp(SG(request_info).request_method, "HEAD")) {
     334               0 :                 SG(request_info).headers_only = 1;
     335                 :         } else {
     336               0 :                 SG(request_info).headers_only = 0;
     337                 :         }
     338               0 :         if (SG(server_context)) {
     339               0 :                 SG(request_info).cookie_data = sapi_module.read_cookies(TSRMLS_C);
     340               0 :                 if (sapi_module.activate) {
     341               0 :                         sapi_module.activate(TSRMLS_C);
     342                 :                 }
     343                 :         }
     344               0 :         if (sapi_module.input_filter_init ) {
     345               0 :                 sapi_module.input_filter_init(TSRMLS_C);
     346                 :         }
     347                 : }
     348                 : 
     349                 : /*
     350                 :  * Called from php_request_startup() for every request.
     351                 :  */
     352                 : 
     353                 : SAPI_API void sapi_activate(TSRMLS_D)
     354           34000 : {
     355           34000 :         zend_llist_init(&SG(sapi_headers).headers, sizeof(sapi_header_struct), (void (*)(void *)) sapi_free_header, 0);
     356           34000 :         SG(sapi_headers).send_default_content_type = 1;
     357                 : 
     358                 :         /*
     359                 :         SG(sapi_headers).http_response_code = 200;
     360                 :         */
     361           34000 :         SG(sapi_headers).http_status_line = NULL;
     362           34000 :         SG(sapi_headers).mimetype = NULL;
     363           34000 :         SG(headers_sent) = 0;
     364           34000 :         SG(read_post_bytes) = 0;
     365           34000 :         SG(request_info).post_data = NULL;
     366           34000 :         SG(request_info).raw_post_data = NULL;
     367           34000 :         SG(request_info).current_user = NULL;
     368           34000 :         SG(request_info).current_user_length = 0;
     369           34000 :         SG(request_info).no_headers = 0;
     370           34000 :         SG(request_info).post_entry = NULL;
     371           34000 :         SG(request_info).proto_num = 1000; /* Default to HTTP 1.0 */
     372           34000 :         SG(global_request_time) = 0;
     373                 : 
     374                 :         /* It's possible to override this general case in the activate() callback, if
     375                 :          * necessary.
     376                 :          */
     377           34000 :         if (SG(request_info).request_method && !strcmp(SG(request_info).request_method, "HEAD")) {
     378               0 :                 SG(request_info).headers_only = 1;
     379                 :         } else {
     380           34000 :                 SG(request_info).headers_only = 0;
     381                 :         }
     382           34000 :         SG(rfc1867_uploaded_files) = NULL;
     383           34000 :         SG(rfc1867_vars) = NULL;
     384           34000 :         SG(rfc1867_files_vars) = NULL;
     385                 : 
     386                 :         /* handle request mehtod */
     387           34000 :         if (SG(server_context)) {
     388             325 :                 if (SG(request_info).request_method) {
     389             225 :                         if (!strcmp(SG(request_info).request_method, "POST") &&
     390                 :                                 (SG(request_info).content_type)
     391                 :                         ) {
     392                 :                                 /* HTTP POST -> may contain form data to be read into variables
     393                 :                                  * depending on content type given */
     394              58 :                                 sapi_read_post_data(TSRMLS_C);
     395                 :                         } else {
     396                 :                                 /* Any other method with content payload will fill
     397                 :                                  * $HTTP_RAW_POST_DATA if enabled by always_populate_raw_post_data
     398                 :                                  * it is up to the webserver to decide whether to allow a method or not */
     399             109 :                                 SG(request_info).content_type_dup = NULL;
     400             109 :                                 if (sapi_module.default_post_reader) {
     401             109 :                                         sapi_module.default_post_reader(TSRMLS_C);
     402                 :                                 }
     403                 :                         }
     404                 :                 } else {
     405             158 :                         SG(request_info).content_type_dup = NULL;
     406                 :                 }
     407                 : 
     408                 :                 /* Cookies */
     409             325 :                 SG(request_info).cookie_data = sapi_module.read_cookies(TSRMLS_C);
     410             325 :                 if (sapi_module.activate) {
     411             325 :                         sapi_module.activate(TSRMLS_C);
     412                 :                 }
     413                 :         }
     414           34000 :         if (sapi_module.input_filter_init ) {
     415           16993 :                 sapi_module.input_filter_init(TSRMLS_C);
     416                 :         }
     417           34000 : }
     418                 : 
     419                 : static void sapi_send_headers_free(TSRMLS_D)
     420           50954 : {
     421           50954 :         if (SG(sapi_headers).http_status_line) {
     422             144 :                 efree(SG(sapi_headers).http_status_line);
     423             144 :                 SG(sapi_headers).http_status_line = NULL;
     424                 :         }
     425           50954 : }
     426                 : 
     427                 : SAPI_API void sapi_deactivate(TSRMLS_D)
     428           34046 : {
     429           34046 :         zend_llist_destroy(&SG(sapi_headers).headers);
     430           34046 :         if (SG(request_info).post_data) {
     431              13 :                 efree(SG(request_info).post_data);
     432           34033 :         } else if (SG(server_context)) {
     433             309 :                 if (sapi_module.read_post) {
     434                 :                         /* make sure we've consumed all request input data */
     435                 :                         char dummy[SAPI_POST_BLOCK_SIZE];
     436                 :                         int read_bytes;
     437                 : 
     438             622 :                         while((read_bytes = sapi_module.read_post(dummy, sizeof(dummy)-1 TSRMLS_CC)) > 0) {
     439               4 :                                 SG(read_post_bytes) += read_bytes;
     440                 :                         }
     441                 :                 }
     442                 :         }
     443           34046 :         if (SG(request_info).raw_post_data) {
     444              30 :                 efree(SG(request_info).raw_post_data);
     445                 :         }
     446           34046 :         if (SG(request_info).auth_user) {
     447               0 :                 efree(SG(request_info).auth_user);
     448                 :         }
     449           34046 :         if (SG(request_info).auth_password) {
     450               0 :                 efree(SG(request_info).auth_password);
     451                 :         }
     452           34046 :         if (SG(request_info).auth_digest) {
     453               0 :                 efree(SG(request_info).auth_digest);
     454                 :         }
     455           34046 :         if (SG(request_info).content_type_dup) {
     456              58 :                 efree(SG(request_info).content_type_dup);
     457                 :         }
     458           34046 :         if (SG(request_info).current_user) {
     459              18 :                 efree(SG(request_info).current_user);
     460                 :         }
     461           34046 :         if (sapi_module.deactivate) {
     462           34046 :                 sapi_module.deactivate(TSRMLS_C);
     463                 :         }
     464           34046 :         if (SG(rfc1867_uploaded_files)) {
     465              24 :                 destroy_uploaded_files_hash(TSRMLS_C);
     466                 :         }
     467           34046 :         if (SG(rfc1867_vars)) {
     468              24 :                 zend_hash_destroy(SG(rfc1867_vars));
     469              24 :                 FREE_HASHTABLE(SG(rfc1867_vars));
     470                 :         }
     471           34046 :         if (SG(rfc1867_files_vars)) {
     472              24 :                 zend_hash_destroy(SG(rfc1867_files_vars));
     473              24 :                 FREE_HASHTABLE(SG(rfc1867_files_vars));
     474                 :         }
     475           34046 :         if (SG(sapi_headers).mimetype) {
     476           16909 :                 efree(SG(sapi_headers).mimetype);
     477           16909 :                 SG(sapi_headers).mimetype = NULL;
     478                 :         }
     479           34046 :         sapi_send_headers_free(TSRMLS_C);
     480           34046 :         SG(sapi_started) = 0;
     481           34046 :         SG(headers_sent) = 0;
     482           34046 :         SG(request_info).headers_read = 0;
     483           34046 :         SG(global_request_time) = 0;
     484           34046 : }
     485                 : 
     486                 : SAPI_API void sapi_initialize_empty_request(TSRMLS_D)
     487           17007 : {
     488           17007 :         SG(server_context) = NULL;
     489           17007 :         SG(request_info).request_method = NULL;
     490           17007 :         SG(request_info).auth_digest = SG(request_info).auth_user = SG(request_info).auth_password = NULL;
     491           17007 :         SG(request_info).content_type_dup = NULL;
     492           17007 : }
     493                 : 
     494                 : static int sapi_extract_response_code(const char *header_line)
     495             144 : {
     496             144 :         int code = 200;
     497                 :         const char *ptr;
     498                 : 
     499            1296 :         for (ptr = header_line; *ptr; ptr++) {
     500            1296 :                 if (*ptr == ' ' && *(ptr + 1) != ' ') {
     501             144 :                         code = atoi(ptr + 1);
     502             144 :                         break;
     503                 :                 }
     504                 :         }
     505                 : 
     506             144 :         return code;
     507                 : }
     508                 : 
     509                 : static void sapi_update_response_code(int ncode TSRMLS_DC)
     510             145 : {
     511                 :         /* if the status code did not change, we do not want
     512                 :          * to change the status line, and no need to change the code */
     513             145 :         if (SG(sapi_headers).http_response_code == ncode) {
     514               0 :                 return;
     515                 :         }
     516                 : 
     517             145 :         if (SG(sapi_headers).http_status_line) {
     518               0 :                 efree(SG(sapi_headers).http_status_line);
     519               0 :                 SG(sapi_headers).http_status_line = NULL;
     520                 :         }
     521             145 :         SG(sapi_headers).http_response_code = ncode;
     522                 : }
     523                 : 
     524                 : static int sapi_find_matching_header(void *element1, void *element2)
     525             161 : {
     526             161 :         int len = strlen((char*)element2);
     527             161 :         return strncasecmp(((sapi_header_struct*)element1)->header, (char*)element2, len) == 0 && ((sapi_header_struct*)element1)->header[len] == ':';
     528                 : }
     529                 : 
     530                 : SAPI_API int sapi_add_header_ex(char *header_line, uint header_line_len, zend_bool duplicate, zend_bool replace TSRMLS_DC)
     531           35598 : {
     532           35598 :         sapi_header_line ctr = {0};
     533                 :         int r;
     534                 : 
     535           35598 :         ctr.line = header_line;
     536           35598 :         ctr.line_len = header_line_len;
     537                 : 
     538           35598 :         r = sapi_header_op(replace ? SAPI_HEADER_REPLACE : SAPI_HEADER_ADD, &ctr TSRMLS_CC);
     539                 : 
     540           35598 :         if (!duplicate) {
     541           16955 :                 efree(header_line);
     542                 :         }
     543           35598 :         return r;
     544                 : }
     545                 : 
     546                 : SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg TSRMLS_DC)
     547           35707 : {
     548                 :         int retval;
     549                 :         sapi_header_struct sapi_header;
     550                 :         char *colon_offset;
     551           35707 :         long myuid = 0L;
     552                 :         char *header_line;
     553                 :         uint header_line_len;
     554                 :         int http_response_code;
     555                 : 
     556           35707 :         if (SG(headers_sent) && !SG(request_info).no_headers) {
     557             550 :                 char *output_start_filename = php_output_get_start_filename(TSRMLS_C);
     558             550 :                 int output_start_lineno = php_output_get_start_lineno(TSRMLS_C);
     559                 : 
     560             550 :                 if (output_start_filename) {
     561             549 :                         sapi_module.sapi_error(E_WARNING, "Cannot modify header information - headers already sent by (output started at %s:%d)", output_start_filename, output_start_lineno);
     562                 :                 } else {
     563               1 :                         sapi_module.sapi_error(E_WARNING, "Cannot modify header information - headers already sent");
     564                 :                 }
     565             550 :                 return FAILURE;
     566                 :         }
     567                 : 
     568           35157 :         switch (op) {
     569                 :         case SAPI_HEADER_SET_STATUS:
     570               0 :                 sapi_update_response_code((int)(zend_intptr_t) arg TSRMLS_CC);
     571               0 :                 return SUCCESS;
     572                 : 
     573                 :         case SAPI_HEADER_ADD:
     574                 :         case SAPI_HEADER_REPLACE:
     575                 :         case SAPI_HEADER_DELETE: {
     576           35155 :                 sapi_header_line *p = arg;
     577                 : 
     578           35155 :                 if (!p->line || !p->line_len) {
     579               1 :                         return FAILURE;
     580                 :                 }
     581           35154 :                 header_line = p->line;
     582           35154 :                 header_line_len = p->line_len;
     583           35154 :                 http_response_code = p->response_code;
     584                 :                 break;
     585                 :         }
     586                 : 
     587                 :         case SAPI_HEADER_DELETE_ALL:
     588               2 :                 if (sapi_module.header_handler) {
     589               0 :                         sapi_module.header_handler(&sapi_header, op, &SG(sapi_headers) TSRMLS_CC);
     590                 :                 }
     591               2 :                 zend_llist_clean(&SG(sapi_headers).headers);
     592               2 :                 return SUCCESS;
     593                 : 
     594                 :         default:
     595               0 :                 return FAILURE;
     596                 :         }
     597                 : 
     598           35154 :         header_line = estrndup(header_line, header_line_len);
     599                 : 
     600                 :         /* cut of trailing spaces, linefeeds and carriage-returns */
     601           70308 :         while(header_line_len && isspace(header_line[header_line_len-1])) {
     602               0 :                 header_line[--header_line_len] = '\0';
     603                 :         }
     604           35154 :         if (op == SAPI_HEADER_DELETE) {
     605               5 :                 if (strchr(header_line, ':')) {
     606               3 :                         efree(header_line);
     607               3 :                         sapi_module.sapi_error(E_WARNING, "Header to delete may not contain colon.");
     608               3 :                         return FAILURE;
     609                 :                 }
     610                 :         } else {
     611                 :                 /* new line safety check */
     612           35149 :                 char *s = header_line, *e = header_line + header_line_len, *p;
     613           70298 :                 while (s < e && (p = memchr(s, '\n', (e - s)))) {
     614               0 :                         if (*(p + 1) == ' ' || *(p + 1) == '\t') {
     615               0 :                                 s = p + 1;
     616               0 :                                 continue;
     617                 :                         }
     618               0 :                         efree(header_line);
     619               0 :                         sapi_module.sapi_error(E_WARNING, "Header may not contain more than a single header, new line detected.");
     620               0 :                         return FAILURE;
     621                 :                 }
     622                 :         }
     623                 : 
     624           35151 :         sapi_header.header = header_line;
     625           35151 :         sapi_header.header_len = header_line_len;
     626                 : 
     627           35151 :         if (op == SAPI_HEADER_DELETE) {
     628               2 :                 if (sapi_module.header_handler) {
     629               0 :                         sapi_module.header_handler(&sapi_header, op, &SG(sapi_headers) TSRMLS_CC);
     630                 :                 }
     631               2 :                 zend_llist_del_element(&SG(sapi_headers).headers, sapi_header.header, (int(*)(void*, void*))sapi_find_matching_header);
     632               2 :                 sapi_free_header(&sapi_header);
     633               2 :                 return SUCCESS;
     634                 :         }
     635                 : 
     636                 :         /* Check the header for a few cases that we have special support for in SAPI */
     637           35149 :         if (header_line_len >= 5 && !strncasecmp(header_line, "HTTP/", 5)) {
     638                 :                 /* filter out the response code */
     639             144 :                 sapi_update_response_code(sapi_extract_response_code(header_line) TSRMLS_CC);
     640                 :                 /* sapi_update_response_code doesn't free the status line if the code didn't change */
     641             144 :                 if (SG(sapi_headers).http_status_line) {
     642               0 :                         efree(SG(sapi_headers).http_status_line);
     643                 :                 }
     644             144 :                 SG(sapi_headers).http_status_line = header_line;
     645             144 :                 return SUCCESS;
     646                 :         } else {
     647           35005 :                 colon_offset = strchr(header_line, ':');
     648           35005 :                 if (colon_offset) {
     649           35004 :                         *colon_offset = 0;
     650           35004 :                         if (!STRCASECMP(header_line, "Content-Type")) {
     651           16919 :                                 char *ptr = colon_offset+1, *mimetype = NULL, *newheader;
     652           16919 :                                 size_t len = header_line_len - (ptr - header_line), newlen;
     653           50757 :                                 while (*ptr == ' ') {
     654           16919 :                                         ptr++;
     655           16919 :                                         len--;
     656                 :                                 }
     657                 : 
     658                 :                                 /* Disable possible output compression for images */
     659           16919 :                                 if (!strncmp(ptr, "image/", sizeof("image/")-1)) {
     660               4 :                                         zend_alter_ini_entry("zlib.output_compression", sizeof("zlib.output_compression"), "0", sizeof("0") - 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
     661                 :                                 }
     662                 : 
     663           16919 :                                 mimetype = estrdup(ptr);
     664           16919 :                                 newlen = sapi_apply_default_charset(&mimetype, len TSRMLS_CC);
     665           16919 :                                 if (!SG(sapi_headers).mimetype){
     666           16908 :                                         SG(sapi_headers).mimetype = estrdup(mimetype);
     667                 :                                 }
     668                 : 
     669           16919 :                                 if (newlen != 0) {
     670              12 :                                         newlen += sizeof("Content-type: ");
     671              12 :                                         newheader = emalloc(newlen);
     672              12 :                                         PHP_STRLCPY(newheader, "Content-type: ", newlen, sizeof("Content-type: ")-1);
     673              12 :                                         strlcat(newheader, mimetype, newlen);
     674              12 :                                         sapi_header.header = newheader;
     675              12 :                                         sapi_header.header_len = newlen - 1;
     676              12 :                                         efree(header_line);
     677                 :                                 }
     678           16919 :                                 efree(mimetype);
     679           16919 :                                 SG(sapi_headers).send_default_content_type = 0;
     680           18085 :                         } else if (!STRCASECMP(header_line, "Location")) {
     681              12 :                                 if ((SG(sapi_headers).http_response_code < 300 ||
     682                 :                                         SG(sapi_headers).http_response_code > 307) &&
     683                 :                                         SG(sapi_headers).http_response_code != 201) {
     684                 :                                         /* Return a Found Redirect if one is not already specified */
     685               0 :                                         if (http_response_code) { /* user specified redirect code */
     686               0 :                                                 sapi_update_response_code(http_response_code TSRMLS_CC);
     687               0 :                                         } else if (SG(request_info).proto_num > 1000 &&
     688                 :                                                 SG(request_info).request_method && 
     689                 :                                                 strcmp(SG(request_info).request_method, "HEAD") &&
     690                 :                                                 strcmp(SG(request_info).request_method, "GET")
     691                 :                                         ) {
     692               0 :                                                 sapi_update_response_code(303 TSRMLS_CC);
     693                 :                                         } else {
     694               0 :                                                 sapi_update_response_code(302 TSRMLS_CC);
     695                 :                                         }
     696                 :                                 }
     697           18073 :                         } else if (!STRCASECMP(header_line, "WWW-Authenticate")) { /* HTTP Authentication */
     698                 : 
     699               0 :                                 sapi_update_response_code(401 TSRMLS_CC); /* authentication-required */
     700                 : 
     701               0 :                                 myuid = php_getuid();
     702               0 :                                 efree(header_line);
     703               0 :                                 sapi_header.header_len = spprintf(&sapi_header.header, 0, "WWW-Authenticate: Basic realm=\"%ld\"", myuid);
     704                 :                         }
     705           35004 :                         if (sapi_header.header==header_line) {
     706           34992 :                                 *colon_offset = ':';
     707                 :                         }
     708                 :                 }
     709                 :         }
     710           35005 :         if (http_response_code) {
     711               1 :                 sapi_update_response_code(http_response_code TSRMLS_CC);
     712                 :         }
     713           35005 :         if (sapi_module.header_handler) {
     714           34413 :                 retval = sapi_module.header_handler(&sapi_header, op, &SG(sapi_headers) TSRMLS_CC);
     715                 :         } else {
     716             592 :                 retval = SAPI_HEADER_ADD;
     717                 :         }
     718           35005 :         if (retval & SAPI_HEADER_ADD) {
     719                 :                 /* in replace mode first remove the header if it already exists in the headers llist */
     720             592 :                 if (op == SAPI_HEADER_REPLACE) {
     721             417 :                         colon_offset = strchr(sapi_header.header, ':');
     722             417 :                         if (colon_offset) {
     723                 :                                 char sav;
     724             417 :                                 sav = *colon_offset;
     725             417 :                                 *colon_offset = 0;
     726             417 :                                 zend_llist_del_element(&SG(sapi_headers).headers, sapi_header.header, (int(*)(void*, void*))sapi_find_matching_header);
     727             417 :                                 *colon_offset = sav;
     728                 :                         }
     729                 :                 }
     730                 : 
     731             592 :                 zend_llist_add_element(&SG(sapi_headers).headers, (void *) &sapi_header);
     732                 :         } else {
     733           34413 :                 sapi_free_header(&sapi_header);
     734                 :         }
     735           35005 :         return SUCCESS;
     736                 : }
     737                 : 
     738                 : SAPI_API int sapi_send_headers(TSRMLS_D)
     739           28371 : {
     740                 :         int retval;
     741           28371 :         int ret = FAILURE;
     742                 : 
     743           28371 :         if (SG(headers_sent) || SG(request_info).no_headers) {
     744           11463 :                 return SUCCESS;
     745                 :         }
     746                 : 
     747                 :         /* Success-oriented. We set headers_sent to 1 here to avoid an infinite loop
     748                 :          * in case of an error situation. */
     749           16908 :         if (SG(sapi_headers).send_default_content_type && sapi_module.send_headers) {
     750                 :                 sapi_header_struct default_header;
     751           16738 :                 sapi_get_default_content_type_header(&default_header TSRMLS_CC);
     752           16738 :                 sapi_add_header_ex(default_header.header, default_header.header_len, 0, 0 TSRMLS_CC);
     753                 :         }
     754                 : 
     755           16908 :         SG(headers_sent) = 1;
     756                 : 
     757           16908 :         if (sapi_module.send_headers) {
     758           16908 :                 retval = sapi_module.send_headers(&SG(sapi_headers) TSRMLS_CC);
     759                 :         } else {
     760               0 :                 retval = SAPI_HEADER_DO_SEND;
     761                 :         }
     762                 : 
     763           16908 :         switch (retval) {
     764                 :                 case SAPI_HEADER_SENT_SUCCESSFULLY:
     765           16908 :                         ret = SUCCESS;
     766           16908 :                         break;
     767                 :                 case SAPI_HEADER_DO_SEND: {
     768                 :                                 sapi_header_struct http_status_line;
     769                 :                                 char buf[255];
     770                 : 
     771               0 :                                 if (SG(sapi_headers).http_status_line) {
     772               0 :                                         http_status_line.header = SG(sapi_headers).http_status_line;
     773               0 :                                         http_status_line.header_len = strlen(SG(sapi_headers).http_status_line);
     774                 :                                 } else {
     775               0 :                                         http_status_line.header = buf;
     776               0 :                                         http_status_line.header_len = slprintf(buf, sizeof(buf), "HTTP/1.0 %d X", SG(sapi_headers).http_response_code);
     777                 :                                 }
     778               0 :                                 sapi_module.send_header(&http_status_line, SG(server_context) TSRMLS_CC);
     779                 :                         }
     780               0 :                         zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t) sapi_module.send_header, SG(server_context) TSRMLS_CC);
     781               0 :                         if (SG(sapi_headers).send_default_content_type) {
     782                 :                                 sapi_header_struct default_header;
     783                 : 
     784               0 :                                 sapi_get_default_content_type_header(&default_header TSRMLS_CC);
     785               0 :                                 sapi_module.send_header(&default_header, SG(server_context) TSRMLS_CC);
     786               0 :                                 sapi_free_header(&default_header);
     787                 :                         }
     788               0 :                         sapi_module.send_header(NULL, SG(server_context) TSRMLS_CC);
     789               0 :                         ret = SUCCESS;
     790               0 :                         break;
     791                 :                 case SAPI_HEADER_SEND_FAILED:
     792               0 :                         SG(headers_sent) = 0;
     793               0 :                         ret = FAILURE;
     794                 :                         break;
     795                 :         }
     796           16908 :         sapi_send_headers_free(TSRMLS_C);
     797                 : 
     798           16908 :         return ret;
     799                 : }
     800                 : 
     801                 : SAPI_API int sapi_register_post_entries(sapi_post_entry *post_entries TSRMLS_DC)
     802           34017 : {
     803           34017 :         sapi_post_entry *p=post_entries;
     804                 : 
     805          119055 :         while (p->content_type) {
     806           68031 :                 if (sapi_register_post_entry(p TSRMLS_CC) == FAILURE) {
     807           17010 :                         return FAILURE;
     808                 :                 }
     809           51021 :                 p++;
     810                 :         }
     811           17007 :         return SUCCESS;
     812                 : }
     813                 : 
     814                 : SAPI_API int sapi_register_post_entry(sapi_post_entry *post_entry TSRMLS_DC)
     815           68031 : {
     816           68031 :         if (SG(sapi_started) && EG(in_execution)) {
     817               0 :                 return FAILURE;
     818                 :         }
     819                 : 
     820           68031 :         return zend_hash_add(&SG(known_post_content_types), post_entry->content_type, post_entry->content_type_len + 1, (void *) post_entry, sizeof(sapi_post_entry), NULL);
     821                 : }
     822                 : 
     823                 : SAPI_API void sapi_unregister_post_entry(sapi_post_entry *post_entry TSRMLS_DC)
     824           17007 : {
     825           17007 :         if (SG(sapi_started) && EG(in_execution)) {
     826               0 :                 return;
     827                 :         }
     828           17007 :         zend_hash_del(&SG(known_post_content_types), post_entry->content_type, post_entry->content_type_len+1);
     829                 : }
     830                 : 
     831                 : SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(TSRMLS_D))
     832           17007 : {
     833                 :         TSRMLS_FETCH();
     834           17007 :         if (SG(sapi_started) && EG(in_execution)) {
     835               0 :                 return FAILURE;
     836                 :         }
     837           17007 :         sapi_module.default_post_reader = default_post_reader;
     838           17007 :         return SUCCESS;
     839                 : }
     840                 : 
     841                 : SAPI_API int sapi_register_treat_data(void (*treat_data)(int arg, char *str, zval *destArray TSRMLS_DC))
     842           34014 : {
     843                 :         TSRMLS_FETCH();
     844           34014 :         if (SG(sapi_started) && EG(in_execution)) {
     845               0 :                 return FAILURE;
     846                 :         }
     847           34014 :         sapi_module.treat_data = treat_data;
     848           34014 :         return SUCCESS;
     849                 : }
     850                 : 
     851                 : SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC), unsigned int (*input_filter_init)(TSRMLS_D))
     852           34014 : {
     853                 :         TSRMLS_FETCH();
     854           34014 :         if (SG(sapi_started) && EG(in_execution)) {
     855               0 :                 return FAILURE;
     856                 :         }
     857           34014 :         sapi_module.input_filter = input_filter;
     858           34014 :         sapi_module.input_filter_init = input_filter_init;
     859           34014 :         return SUCCESS;
     860                 : }
     861                 : 
     862                 : SAPI_API int sapi_flush(TSRMLS_D)
     863          992530 : {
     864          992530 :         if (sapi_module.flush) {
     865          992530 :                 sapi_module.flush(SG(server_context));
     866          992530 :                 return SUCCESS;
     867                 :         } else {
     868               0 :                 return FAILURE;
     869                 :         }
     870                 : }
     871                 : 
     872                 : SAPI_API struct stat *sapi_get_stat(TSRMLS_D)
     873              22 : {
     874              22 :         if (sapi_module.get_stat) {
     875               0 :                 return sapi_module.get_stat(TSRMLS_C);
     876                 :         } else {
     877              22 :                 if (!SG(request_info).path_translated || (VCWD_STAT(SG(request_info).path_translated, &SG(global_stat)) == -1)) {
     878               0 :                         return NULL;
     879                 :                 }
     880              22 :                 return &SG(global_stat);
     881                 :         }
     882                 : }
     883                 : 
     884                 : SAPI_API char *sapi_getenv(char *name, size_t name_len TSRMLS_DC)
     885           25418 : {
     886           25418 :         if (sapi_module.getenv) {
     887               6 :                 char *value, *tmp = sapi_module.getenv(name, name_len TSRMLS_CC);
     888                 : 
     889               6 :                 if (tmp) {
     890               6 :                         value = estrdup(tmp);
     891                 :                 } else {
     892               0 :                         return NULL;
     893                 :                 }
     894               6 :                 sapi_module.input_filter(PARSE_ENV, name, &value, strlen(value), NULL TSRMLS_CC);
     895               6 :                 return value;
     896                 :         }
     897           25412 :         return NULL;
     898                 : }
     899                 : 
     900                 : SAPI_API int sapi_get_fd(int *fd TSRMLS_DC)
     901               0 : {
     902               0 :         if (sapi_module.get_fd) {
     903               0 :                 return sapi_module.get_fd(fd TSRMLS_CC);
     904                 :         } else {
     905               0 :                 return FAILURE;
     906                 :         }
     907                 : }
     908                 : 
     909                 : SAPI_API int sapi_force_http_10(TSRMLS_D)
     910               0 : {
     911               0 :         if (sapi_module.force_http_10) {
     912               0 :                 return sapi_module.force_http_10(TSRMLS_C);
     913                 :         } else {
     914               0 :                 return FAILURE;
     915                 :         }
     916                 : }
     917                 : 
     918                 : SAPI_API int sapi_get_target_uid(uid_t *obj TSRMLS_DC)
     919               0 : {
     920               0 :         if (sapi_module.get_target_uid) {
     921               0 :                 return sapi_module.get_target_uid(obj TSRMLS_CC);
     922                 :         } else {
     923               0 :                 return FAILURE;
     924                 :         }
     925                 : }
     926                 : 
     927                 : SAPI_API int sapi_get_target_gid(gid_t *obj TSRMLS_DC)
     928               0 : {
     929               0 :         if (sapi_module.get_target_gid) {
     930               0 :                 return sapi_module.get_target_gid(obj TSRMLS_CC);
     931                 :         } else {
     932               0 :                 return FAILURE;
     933                 :         }
     934                 : }
     935                 : 
     936                 : SAPI_API time_t sapi_get_request_time(TSRMLS_D)
     937           16735 : {
     938           16735 :         if (SG(global_request_time)) {
     939               0 :                 return SG(global_request_time);
     940                 :         }
     941           16735 :         if (sapi_module.get_request_time && SG(server_context)) {
     942               0 :                 SG(global_request_time) = sapi_module.get_request_time(TSRMLS_C);
     943                 :         } else {
     944           16735 :                 SG(global_request_time) = time(0);
     945                 :         }
     946           16735 :         return SG(global_request_time);
     947                 : }
     948                 : 
     949                 : SAPI_API void sapi_terminate_process(TSRMLS_D)
     950               0 : {
     951               0 :         if (sapi_module.terminate_process) {
     952               0 :                 sapi_module.terminate_process(TSRMLS_C);
     953                 :         }
     954               0 : }
     955                 : 
     956                 : /*
     957                 :  * Local variables:
     958                 :  * tab-width: 4
     959                 :  * c-basic-offset: 4
     960                 :  * End:
     961                 :  * vim600: sw=4 ts=4 fdm=marker
     962                 :  * vim<600: sw=4 ts=4
     963                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Mon, 23 Nov 2009 17:39:46 +0000 (36 hours ago)

Copyright © 2005-2009 The PHP Group
All rights reserved.