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_5_2/main - SAPI.c
Test: PHP Code Coverage
Date: 2009-11-19 Instrumented lines: 465
Code covered: 65.6 % Executed lines: 305
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5

Generated at Thu, 19 Nov 2009 08:20:28 +0000 (5 days ago)

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