Back to index

php5  5.3.10
Classes | Defines | Functions | Variables
thttpd.c File Reference
#include "php.h"
#include "SAPI.h"
#include "php_main.h"
#include "php_thttpd.h"
#include "php_variables.h"
#include "version.h"
#include "php_ini.h"
#include "zend_highlight.h"
#include "ext/standard/php_smart_str.h"
#include <sys/time.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <stdlib.h>
#include <unistd.h>

Go to the source code of this file.

Classes

struct  php_thttpd_globals

Defines

#define PHP_SYS_CALL(x)   do { x } while (n == -1 && errno == EINTR)
#define TG(v)   (thttpd_globals.v)
#define COMBINE_HEADERS   64
#define ADD_VEC(str, l)   vec[n].iov_base=str;len += (vec[n].iov_len=l); n++
#define VEC_BASE()   struct iovec vec[COMBINE_HEADERS]
#define VEC_FREE()   do {} while (0)
#define ADD_VEC_S(str)   ADD_VEC((str), sizeof(str)-1)
#define CL_TOKEN   "Content-length: "
#define CN_TOKEN   "Connection: "
#define KA_DO   "Connection: keep-alive\r\n"
#define KA_NO   "Connection: close\r\n"
#define DEF_CT   "Content-Type: text/html\r\n"
#define SIZEOF_UNCONSUMED_BYTES()   (TG(hc)->read_idx - TG(hc)->checked_idx)
#define CONSUME_BYTES(n)   do { TG(hc)->checked_idx += (n); } while (0)
#define BUF_SIZE   512
#define ADD_STRING_EX(name, buf)   php_register_variable(name, buf, track_vars_array TSRMLS_CC)
#define ADD_STRING(name)   ADD_STRING_EX((name), buf)
#define CONDADD(name, field)

Functions

static int sapi_thttpd_ub_write (const char *str, uint str_length TSRMLS_DC)
static int do_writev (struct iovec *vec, int nvec, int len TSRMLS_DC)
static int sapi_thttpd_send_headers (sapi_headers_struct *sapi_headers TSRMLS_DC)
static int sapi_thttpd_read_post (char *buffer, uint count_bytes TSRMLS_DC)
static char * sapi_thttpd_read_cookies (TSRMLS_D)
static void sapi_thttpd_register_variables (zval *track_vars_array TSRMLS_DC)
static PHP_MINIT_FUNCTION (thttpd)
static int php_thttpd_startup (sapi_module_struct *sapi_module)
static int sapi_thttpd_get_fd (int *nfd TSRMLS_DC)
static void thttpd_module_main (int show_source TSRMLS_DC)
static void thttpd_request_ctor (TSRMLS_D)
static void thttpd_request_dtor (TSRMLS_D)
static off_t thttpd_real_php_request (httpd_conn *hc, int show_source TSRMLS_DC)
off_t thttpd_php_request (httpd_conn *hc, int show_source)
void thttpd_register_on_close (void(*arg)(int))
void thttpd_closed_conn (int fd)
int thttpd_get_fd (void)
void thttpd_set_dont_close (void)
void thttpd_php_init (void)
void thttpd_php_shutdown (void)

Variables

static php_thttpd_globals thttpd_globals
static zend_module_entry php_thttpd_module
static sapi_module_struct thttpd_sapi_module

Define Documentation

#define ADD_STRING (   name)    ADD_STRING_EX((name), buf)

Definition at line 270 of file thttpd.c.

#define ADD_STRING_EX (   name,
  buf 
)    php_register_variable(name, buf, track_vars_array TSRMLS_CC)

Definition at line 268 of file thttpd.c.

#define ADD_VEC (   str,
  l 
)    vec[n].iov_base=str;len += (vec[n].iov_len=l); n++

Definition at line 160 of file thttpd.c.

#define ADD_VEC_S (   str)    ADD_VEC((str), sizeof(str)-1)

Definition at line 165 of file thttpd.c.

#define BUF_SIZE   512

Definition at line 267 of file thttpd.c.

#define CL_TOKEN   "Content-length: "

Definition at line 167 of file thttpd.c.

#define CN_TOKEN   "Connection: "

Definition at line 168 of file thttpd.c.

#define COMBINE_HEADERS   64

Definition at line 98 of file thttpd.c.

#define CONDADD (   name,
  field 
)
Value:
if (TG(hc)->field[0]) {                                                      \
              php_register_variable(#name, TG(hc)->field, track_vars_array TSRMLS_CC); \
       }
#define CONSUME_BYTES (   n)    do { TG(hc)->checked_idx += (n); } while (0)

Definition at line 245 of file thttpd.c.

#define DEF_CT   "Content-Type: text/html\r\n"

Definition at line 171 of file thttpd.c.

#define KA_DO   "Connection: keep-alive\r\n"

Definition at line 169 of file thttpd.c.

#define KA_NO   "Connection: close\r\n"

Definition at line 170 of file thttpd.c.

#define PHP_SYS_CALL (   x)    do { x } while (n == -1 && errno == EINTR)

Definition at line 53 of file thttpd.c.

#define SIZEOF_UNCONSUMED_BYTES ( )    (TG(hc)->read_idx - TG(hc)->checked_idx)

Definition at line 244 of file thttpd.c.

#define TG (   v)    (thttpd_globals.v)

Definition at line 64 of file thttpd.c.

#define VEC_BASE ( )    struct iovec vec[COMBINE_HEADERS]

Definition at line 161 of file thttpd.c.

#define VEC_FREE ( )    do {} while (0)

Definition at line 162 of file thttpd.c.


Function Documentation

static int do_writev ( struct iovec *  vec,
int  nvec,
int len  TSRMLS_DC 
) [static]

Definition at line 106 of file thttpd.c.

{
       int n;

       assert(nvec <= IOV_MAX);

       if (TG(sbuf).c == 0) {
              PHP_SYS_CALL(n = writev(TG(hc)->conn_fd, vec, nvec););

              if (n == -1) {
                     if (errno == EAGAIN) {
                            n = 0;
                     } else {
                            php_handle_aborted_connection();
                     }
              }


              TG(hc)->bytes_sent += n;
       } else {
              n = 0;
       }

       if (n < len) {
              int i;

              /* merge all unwritten data into sbuf */
              for (i = 0; i < nvec; vec++, i++) {
                     /* has this vector been written completely? */
                     if (n >= vec->iov_len) {
                            /* yes, proceed */
                            n -= vec->iov_len;
                            continue;
                     }

                     if (n > 0) {
                            /* adjust vector */
                            vec->iov_base = (char *) vec->iov_base + n;
                            vec->iov_len -= n;
                            n = 0;
                     }

                     smart_str_appendl_ex(&TG(sbuf), vec->iov_base, vec->iov_len, 1);
              }
       }
       
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PHP_MINIT_FUNCTION ( thttpd  ) [static]

Definition at line 334 of file thttpd.c.

{
       return SUCCESS;
}
static int php_thttpd_startup ( sapi_module_struct *  sapi_module) [static]

Definition at line 352 of file thttpd.c.

{
#if PHP_API_VERSION >= 20020918
       if (php_module_startup(sapi_module, &php_thttpd_module, 1) == FAILURE) {
#else
       if (php_module_startup(sapi_module) == FAILURE
                     || zend_startup_module(&php_thttpd_module) == FAILURE) {
#endif
              return FAILURE;
       }
       return SUCCESS;
}

Here is the call graph for this function:

static int sapi_thttpd_get_fd ( int *nfd  TSRMLS_DC) [static]

Definition at line 365 of file thttpd.c.

{
       if (nfd) *nfd = TG(hc)->conn_fd;
       return SUCCESS;
}
static char* sapi_thttpd_read_cookies ( TSRMLS_D  ) [static]

Definition at line 262 of file thttpd.c.

{
       return TG(hc)->cookie;
}
static int sapi_thttpd_read_post ( char *  buffer,
uint count_bytes  TSRMLS_DC 
) [static]

Definition at line 248 of file thttpd.c.

{
       size_t read_bytes = 0;

       if (TG(unconsumed_length) > 0) {
              read_bytes = MIN(TG(unconsumed_length), count_bytes);
              memcpy(buffer, TG(hc)->read_buf + TG(hc)->checked_idx, read_bytes);
              TG(unconsumed_length) -= read_bytes;
              CONSUME_BYTES(read_bytes);
       }
       
       return read_bytes;
}
static void sapi_thttpd_register_variables ( zval *track_vars_array  TSRMLS_DC) [static]

Definition at line 272 of file thttpd.c.

{
       char buf[BUF_SIZE + 1];
       char *p;

       php_register_variable("PHP_SELF", SG(request_info).request_uri, track_vars_array TSRMLS_CC);
       php_register_variable("SERVER_SOFTWARE", SERVER_SOFTWARE, track_vars_array TSRMLS_CC);
       php_register_variable("GATEWAY_INTERFACE", "CGI/1.1", track_vars_array TSRMLS_CC);
       php_register_variable("REQUEST_METHOD", (char *) SG(request_info).request_method, track_vars_array TSRMLS_CC);
       php_register_variable("REQUEST_URI", SG(request_info).request_uri, track_vars_array TSRMLS_CC);
       php_register_variable("PATH_TRANSLATED", SG(request_info).path_translated, track_vars_array TSRMLS_CC);

       if (TG(hc)->one_one) {
              php_register_variable("SERVER_PROTOCOL", "HTTP/1.1", track_vars_array TSRMLS_CC);
       } else {
              php_register_variable("SERVER_PROTOCOL", "HTTP/1.0", track_vars_array TSRMLS_CC);
       }

       p = httpd_ntoa(&TG(hc)->client_addr);     
       
       ADD_STRING_EX("REMOTE_ADDR", p);
       ADD_STRING_EX("REMOTE_HOST", p);

       ADD_STRING_EX("SERVER_PORT",
                     smart_str_print_long(buf + sizeof(buf) - 1,
                            TG(hc)->hs->port));

       buf[0] = '/';
       memcpy(buf + 1, TG(hc)->pathinfo, strlen(TG(hc)->pathinfo) + 1);
       ADD_STRING("PATH_INFO");

       buf[0] = '/';
       memcpy(buf + 1, TG(hc)->origfilename, strlen(TG(hc)->origfilename) + 1);
       ADD_STRING("SCRIPT_NAME");

#define CONDADD(name, field)                                                 \
       if (TG(hc)->field[0]) {                                                      \
              php_register_variable(#name, TG(hc)->field, track_vars_array TSRMLS_CC); \
       }

       CONDADD(QUERY_STRING, query);
       CONDADD(HTTP_HOST, hdrhost);
       CONDADD(HTTP_REFERER, referer);
       CONDADD(HTTP_USER_AGENT, useragent);
       CONDADD(HTTP_ACCEPT, accept);
       CONDADD(HTTP_ACCEPT_LANGUAGE, acceptl);
       CONDADD(HTTP_ACCEPT_ENCODING, accepte);
       CONDADD(HTTP_COOKIE, cookie);
       CONDADD(CONTENT_TYPE, contenttype);
       CONDADD(REMOTE_USER, remoteuser);
       CONDADD(SERVER_PROTOCOL, protocol);

       if (TG(hc)->contentlength != -1) {
              ADD_STRING_EX("CONTENT_LENGTH",
                            smart_str_print_long(buf + sizeof(buf) - 1, 
                                   TG(hc)->contentlength));
       }

       if (TG(hc)->authorization[0])
              php_register_variable("AUTH_TYPE", "Basic", track_vars_array TSRMLS_CC);
}

Here is the call graph for this function:

static int sapi_thttpd_send_headers ( sapi_headers_struct *sapi_headers  TSRMLS_DC) [static]

Definition at line 173 of file thttpd.c.

{
       char buf[1024], *p;
       VEC_BASE();
       int n = 0;
       zend_llist_position pos;
       sapi_header_struct *h;
       size_t len = 0;
       
       if (!SG(sapi_headers).http_status_line) {
              ADD_VEC_S("HTTP/1.1 ");
              p = smart_str_print_long(buf+sizeof(buf)-1, 
                            SG(sapi_headers).http_response_code);
              ADD_VEC(p, strlen(p));
              ADD_VEC_S(" HTTP\r\n");
       } else {
              ADD_VEC(SG(sapi_headers).http_status_line, 
                            strlen(SG(sapi_headers).http_status_line));
              ADD_VEC("\r\n", 2);
       }
       TG(hc)->status = SG(sapi_headers).http_response_code;

       if (SG(sapi_headers).send_default_content_type) {
              ADD_VEC(DEF_CT, strlen(DEF_CT));
       }

       h = zend_llist_get_first_ex(&sapi_headers->headers, &pos);
       while (h) {
              
              switch (h->header[0]) {
                     case 'c': case 'C':
                            if (!TG(seen_cl) && strncasecmp(h->header, CL_TOKEN, sizeof(CL_TOKEN)-1) == 0) {
                                   TG(seen_cl) = 1;
                            } else if (!TG(seen_cn) && strncasecmp(h->header, CN_TOKEN, sizeof(CN_TOKEN)-1) == 0) {
                                   TG(seen_cn) = 1;
                            }
              }

              ADD_VEC(h->header, h->header_len);
#ifndef SERIALIZE_HEADERS
              if (n >= COMBINE_HEADERS - 1) {
                     len = do_writev(vec, n, len TSRMLS_CC);
                     n = 0;
              }
#endif
              ADD_VEC("\r\n", 2);
              
              h = zend_llist_get_next_ex(&sapi_headers->headers, &pos);
       }

       if (TG(seen_cl) && !TG(seen_cn) && TG(hc)->do_keep_alive) {
              ADD_VEC(KA_DO, sizeof(KA_DO)-1);
       } else {
              TG(hc)->do_keep_alive = 0;
              ADD_VEC(KA_NO, sizeof(KA_NO)-1);
       }
              
       ADD_VEC("\r\n", 2);

#ifdef SERIALIZE_HEADERS
       sapi_thttpd_ub_write(vec_str.c, vec_str.len TSRMLS_CC);
#else                
       do_writev(vec, n, len TSRMLS_CC);
#endif

       VEC_FREE();

       return SAPI_HEADER_SENT_SUCCESSFULLY;
}

Here is the call graph for this function:

static int sapi_thttpd_ub_write ( const char *  str,
uint str_length  TSRMLS_DC 
) [static]

Definition at line 67 of file thttpd.c.

{
       int n;
       uint sent = 0;
       
       if (TG(sbuf).c != 0) {
              smart_str_appendl_ex(&TG(sbuf), str, str_length, 1);
              return str_length;
       }
       
       while (str_length > 0) {
              PHP_SYS_CALL(n = send(TG(hc)->conn_fd, str, str_length, 0););

              if (n == -1) {
                     if (errno == EAGAIN) {
                            smart_str_appendl_ex(&TG(sbuf), str, str_length, 1);

                            return sent + str_length;
                     } else
                            php_handle_aborted_connection();
              }

              TG(hc)->bytes_sent += n;
              str += n;
              sent += n;
              str_length -= n;
       }

       return sent;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void thttpd_closed_conn ( int  fd)

Definition at line 715 of file thttpd.c.

{
       TSRMLS_FETCH();
       if (TG(on_close)) TG(on_close)(fd);
}
int thttpd_get_fd ( void  )

Definition at line 721 of file thttpd.c.

{
       TSRMLS_FETCH();
       return TG(hc)->conn_fd;
}
static void thttpd_module_main ( int show_source  TSRMLS_DC) [static]

Definition at line 410 of file thttpd.c.

{
       zend_file_handle file_handle;

       if (php_request_startup(TSRMLS_C) == FAILURE) {
              return;
       }
       
       if (show_source) {
              zend_syntax_highlighter_ini syntax_highlighter_ini;

              php_get_highlight_struct(&syntax_highlighter_ini);
              highlight_file(SG(request_info).path_translated, &syntax_highlighter_ini TSRMLS_CC);
       } else {
              file_handle.type = ZEND_HANDLE_FILENAME;
              file_handle.filename = SG(request_info).path_translated;
              file_handle.free_filename = 0;
              file_handle.opened_path = NULL;

              php_execute_script(&file_handle TSRMLS_CC);
       }
       
       php_request_shutdown(NULL);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void thttpd_php_init ( void  )

Definition at line 736 of file thttpd.c.

{
       char *ini;

#ifdef ZTS
       tsrm_startup(1, 1, 0, NULL);
       ts_allocate_id(&thttpd_globals_id, sizeof(php_thttpd_globals), NULL, NULL);
       qr_lock = tsrm_mutex_alloc();
       thttpd_register_on_close(remove_dead_conn);
#endif

       if ((ini = getenv("PHP_INI_PATH"))) {
              thttpd_sapi_module.php_ini_path_override = ini;
       }

       sapi_startup(&thttpd_sapi_module);
       thttpd_sapi_module.startup(&thttpd_sapi_module);
       
       {
              TSRMLS_FETCH();

              SG(server_context) = (void *) 1;
       }
}

Here is the call graph for this function:

off_t thttpd_php_request ( httpd_conn *  hc,
int  show_source 
)

Definition at line 699 of file thttpd.c.

{
#ifdef ZTS
       queue_request(hc);
#else
       TSRMLS_FETCH();
       return thttpd_real_php_request(hc, show_source TSRMLS_CC);
#endif
}

Here is the call graph for this function:

void thttpd_php_shutdown ( void  )

Definition at line 761 of file thttpd.c.

{
       TSRMLS_FETCH();

       if (SG(server_context) != NULL) {
              thttpd_sapi_module.shutdown(&thttpd_sapi_module);
              sapi_shutdown();
#ifdef ZTS
              tsrm_shutdown();
#endif
       }
}

Here is the call graph for this function:

static off_t thttpd_real_php_request ( httpd_conn *  hc,
int show_source  TSRMLS_DC 
) [static]

Definition at line 656 of file thttpd.c.

{
       TG(hc) = hc;
       hc->bytes_sent = 0;

       if (hc->contentlength != -1) {
              hc->should_linger = 1;
              hc->do_keep_alive = 0;
       }
       
       if (hc->contentlength != -1
                     && SIZEOF_UNCONSUMED_BYTES() < hc->contentlength) {
              hc->read_body_into_mem = 1;
              return 0;
       }
       
       thttpd_request_ctor(TSRMLS_C);

       thttpd_module_main(show_source TSRMLS_CC);

       /* disable kl, if no content-length was seen or Connection: was set */
       if (TG(seen_cl) == 0 || TG(seen_cn) == 1) {
              TG(hc)->do_keep_alive = 0;
       }
       
       if (TG(sbuf).c != 0) {
              if (TG(hc)->response)
                     free(TG(hc)->response);
              
              TG(hc)->response = TG(sbuf).c;
              TG(hc)->responselen = TG(sbuf).len;
              TG(hc)->maxresponse = TG(sbuf).a;

              TG(sbuf).c = 0;
              TG(sbuf).len = 0;
              TG(sbuf).a = 0;
       }

       thttpd_request_dtor(TSRMLS_C);

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void thttpd_register_on_close ( void(*)(int arg)

Definition at line 709 of file thttpd.c.

{
       TSRMLS_FETCH();
       TG(on_close) = arg;
}

Here is the caller graph for this function:

static void thttpd_request_ctor ( TSRMLS_D  ) [static]

Definition at line 435 of file thttpd.c.

{
       smart_str s = {0};

       TG(seen_cl) = 0;
       TG(seen_cn) = 0;
       TG(sbuf).c = 0;
       SG(request_info).query_string = TG(hc)->query?strdup(TG(hc)->query):NULL;

       smart_str_appends_ex(&s, TG(hc)->hs->cwd, 1);
       smart_str_appends_ex(&s, TG(hc)->expnfilename, 1);
       smart_str_0(&s);
       SG(request_info).path_translated = s.c;
       
       s.c = NULL;
       smart_str_appendc_ex(&s, '/', 1);
       smart_str_appends_ex(&s, TG(hc)->origfilename, 1);
       smart_str_0(&s);
       SG(request_info).request_uri = s.c;
       SG(request_info).request_method = httpd_method_str(TG(hc)->method);
       if (TG(hc)->one_one) SG(request_info).proto_num = 1001;
       else SG(request_info).proto_num = 1000;
       SG(sapi_headers).http_response_code = 200;
       if (TG(hc)->contenttype)
              SG(request_info).content_type = strdup(TG(hc)->contenttype);
       SG(request_info).content_length = TG(hc)->contentlength == -1 ? 0
              : TG(hc)->contentlength;

       TG(unconsumed_length) = SG(request_info).content_length;
       
       php_handle_auth_data(TG(hc)->authorization TSRMLS_CC);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void thttpd_request_dtor ( TSRMLS_D  ) [static]

Definition at line 468 of file thttpd.c.

{
       smart_str_free_ex(&TG(sbuf), 1);
       if (SG(request_info).query_string)
              free(SG(request_info).query_string);
       free(SG(request_info).request_uri);
       free(SG(request_info).path_translated);
       if (SG(request_info).content_type)
              free(SG(request_info).content_type);
}

Here is the caller graph for this function:

void thttpd_set_dont_close ( void  )

Definition at line 727 of file thttpd.c.

{
       TSRMLS_FETCH();
#ifndef PREMIUM_THTTPD
       TG(hc)->file_address = (char *) 1;
#endif
}

Variable Documentation

zend_module_entry php_thttpd_module [static]
Initial value:

Definition at line 339 of file thttpd.c.

Definition at line 63 of file thttpd.c.

sapi_module_struct thttpd_sapi_module [static]

Definition at line 371 of file thttpd.c.