version 1.1.1.1, 2012/05/29 12:34:35
|
version 1.1.1.4, 2014/06/15 20:04:02
|
Line 2
|
Line 2
|
+----------------------------------------------------------------------+ |
+----------------------------------------------------------------------+ |
| PHP Version 5 | |
| PHP Version 5 | |
+----------------------------------------------------------------------+ |
+----------------------------------------------------------------------+ |
| Copyright (c) 1997-2012 The PHP Group | | | Copyright (c) 1997-2014 The PHP Group | |
+----------------------------------------------------------------------+ |
+----------------------------------------------------------------------+ |
| This source file is subject to version 3.01 of the PHP license, | |
| This source file is subject to version 3.01 of the PHP license, | |
| that is bundled with this package in the file LICENSE, and is | |
| that is bundled with this package in the file LICENSE, and is | |
Line 20
|
Line 20
|
/* $Id$ */ |
/* $Id$ */ |
|
|
#include <stdio.h> |
#include <stdio.h> |
|
#include <stdlib.h> |
#include <fcntl.h> |
#include <fcntl.h> |
#include <assert.h> |
#include <assert.h> |
|
|
#ifdef PHP_WIN32 |
#ifdef PHP_WIN32 |
#include <process.h> | # include <process.h> |
#include <io.h> | # include <io.h> |
#include "win32/time.h" | # include "win32/time.h" |
#include "win32/signal.h" | # include "win32/signal.h" |
#include "win32/php_registry.h" | # include "win32/php_registry.h" |
| # include <sys/timeb.h> |
#else |
#else |
# include "php_config.h" |
# include "php_config.h" |
#endif |
#endif |
Line 98
|
Line 100
|
#include "ext/standard/html.h" |
#include "ext/standard/html.h" |
#include "ext/standard/url.h" /* for php_url_decode() */ |
#include "ext/standard/url.h" /* for php_url_decode() */ |
#include "ext/standard/php_string.h" /* for php_dirname() */ |
#include "ext/standard/php_string.h" /* for php_dirname() */ |
#include "ext/standard/info.h" /* for php_info_print_style() */ |
|
#include "php_network.h" |
#include "php_network.h" |
|
|
#include "php_http_parser.h" |
#include "php_http_parser.h" |
Line 117 typedef struct php_cli_server_poller {
|
Line 118 typedef struct php_cli_server_poller {
|
} php_cli_server_poller; |
} php_cli_server_poller; |
|
|
typedef struct php_cli_server_request { |
typedef struct php_cli_server_request { |
enum php_http_method request_method; | enum php_http_method request_method; |
int protocol_version; |
int protocol_version; |
char *request_uri; |
char *request_uri; |
size_t request_uri_len; |
size_t request_uri_len; |
Line 174 typedef struct php_cli_server_client {
|
Line 175 typedef struct php_cli_server_client {
|
php_cli_server_request request; |
php_cli_server_request request; |
unsigned int content_sender_initialized:1; |
unsigned int content_sender_initialized:1; |
php_cli_server_content_sender content_sender; |
php_cli_server_content_sender content_sender; |
php_cli_server_buffer capture_buffer; |
|
unsigned int capturing:1; |
|
int file_fd; |
int file_fd; |
} php_cli_server_client; |
} php_cli_server_client; |
|
|
Line 194 typedef struct php_cli_server {
|
Line 193 typedef struct php_cli_server {
|
HashTable clients; |
HashTable clients; |
} php_cli_server; |
} php_cli_server; |
|
|
typedef struct php_cli_server_http_reponse_status_code_pair { | typedef struct php_cli_server_http_response_status_code_pair { |
int code; |
int code; |
const char *str; |
const char *str; |
} php_cli_server_http_reponse_status_code_pair; | } php_cli_server_http_response_status_code_pair; |
|
|
typedef struct php_cli_server_ext_mime_type_pair { |
typedef struct php_cli_server_ext_mime_type_pair { |
const char *ext; |
const char *ext; |
const char *mime_type; |
const char *mime_type; |
} php_cli_server_ext_mime_type_pair; |
} php_cli_server_ext_mime_type_pair; |
|
|
static php_cli_server_http_reponse_status_code_pair status_map[] = { | static php_cli_server_http_response_status_code_pair status_map[] = { |
{ 100, "Continue" }, |
{ 100, "Continue" }, |
{ 101, "Switching Protocols" }, |
{ 101, "Switching Protocols" }, |
{ 200, "OK" }, |
{ 200, "OK" }, |
Line 239 static php_cli_server_http_reponse_status_code_pair st
|
Line 238 static php_cli_server_http_reponse_status_code_pair st
|
{ 415, "Unsupported Media Type" }, |
{ 415, "Unsupported Media Type" }, |
{ 416, "Requested Range Not Satisfiable" }, |
{ 416, "Requested Range Not Satisfiable" }, |
{ 417, "Expectation Failed" }, |
{ 417, "Expectation Failed" }, |
|
{ 428, "Precondition Required" }, |
|
{ 429, "Too Many Requests" }, |
|
{ 431, "Request Header Fields Too Large" }, |
{ 500, "Internal Server Error" }, |
{ 500, "Internal Server Error" }, |
{ 501, "Not Implemented" }, |
{ 501, "Not Implemented" }, |
{ 502, "Bad Gateway" }, |
{ 502, "Bad Gateway" }, |
{ 503, "Service Unavailable" }, |
{ 503, "Service Unavailable" }, |
{ 504, "Gateway Timeout" }, |
{ 504, "Gateway Timeout" }, |
{ 505, "HTTP Version Not Supported" }, |
{ 505, "HTTP Version Not Supported" }, |
|
{ 511, "Network Authentication Required" }, |
}; |
}; |
|
|
static php_cli_server_http_reponse_status_code_pair template_map[] = { | static php_cli_server_http_response_status_code_pair template_map[] = { |
{ 400, "<h1 class=\"h\">%s</h1><p>Your browser sent a request that this server could not understand.</p>" }, | { 400, "<h1>%s</h1><p>Your browser sent a request that this server could not understand.</p>" }, |
{ 404, "<h1 class=\"h\">%s</h1><p>The requested resource %s was not found on this server.</p>" }, | { 404, "<h1>%s</h1><p>The requested resource %s was not found on this server.</p>" }, |
{ 500, "<h1 class=\"h\">%s</h1><p>The server is temporality unavaiable.</p>" } | { 500, "<h1>%s</h1><p>The server is temporarily unavailable.</p>" }, |
| { 501, "<h1>%s</h1><p>Request method not supported.</p>" } |
}; |
}; |
|
|
static php_cli_server_ext_mime_type_pair mime_type_map[] = { |
static php_cli_server_ext_mime_type_pair mime_type_map[] = { |
|
{ "html", "text/html" }, |
|
{ "htm", "text/html" }, |
|
{ "js", "text/javascript" }, |
|
{ "css", "text/css" }, |
{ "gif", "image/gif" }, |
{ "gif", "image/gif" }, |
{ "png", "image/png" }, |
|
{ "jpe", "image/jpeg" }, |
|
{ "jpg", "image/jpeg" }, |
{ "jpg", "image/jpeg" }, |
{ "jpeg", "image/jpeg" }, |
{ "jpeg", "image/jpeg" }, |
{ "css", "text/css" }, | { "jpe", "image/jpeg" }, |
{ "html", "text/html" }, | { "png", "image/png" }, |
| { "svg", "image/svg+xml" }, |
{ "txt", "text/plain" }, |
{ "txt", "text/plain" }, |
{ "js", "text/javascript" }, | { "webm", "video/webm" }, |
| { "ogv", "video/ogg" }, |
| { "ogg", "audio/ogg" }, |
{ NULL, NULL } |
{ NULL, NULL } |
}; |
}; |
|
|
Line 276 static void php_cli_server_log_response(php_cli_server
|
Line 285 static void php_cli_server_log_response(php_cli_server
|
|
|
ZEND_DECLARE_MODULE_GLOBALS(cli_server); |
ZEND_DECLARE_MODULE_GLOBALS(cli_server); |
|
|
|
/* {{{ static char php_cli_server_css[] |
|
* copied from ext/standard/info.c |
|
*/ |
|
static const char php_cli_server_css[] = "<style>\n" \ |
|
"body { background-color: #ffffff; color: #000000; }\n" \ |
|
"h1 { font-family: sans-serif; font-size: 150%; background-color: #9999cc; font-weight: bold; color: #000000; margin-top: 0;}\n" \ |
|
"</style>\n"; |
|
/* }}} */ |
|
|
|
#ifdef PHP_WIN32 |
|
int php_cli_server_get_system_time(char *buf) { |
|
struct _timeb system_time; |
|
errno_t err; |
|
|
|
if (buf == NULL) { |
|
return -1; |
|
} |
|
|
|
_ftime(&system_time); |
|
err = ctime_s(buf, 52, &(system_time.time) ); |
|
if (err) { |
|
return -1; |
|
} |
|
return 0; |
|
} |
|
#else |
|
int php_cli_server_get_system_time(char *buf) { |
|
struct timeval tv; |
|
struct tm tm; |
|
|
|
gettimeofday(&tv, NULL); |
|
|
|
/* TODO: should be checked for NULL tm/return vaue */ |
|
php_localtime_r(&tv.tv_sec, &tm); |
|
php_asctime_r(&tm, buf); |
|
return 0; |
|
} |
|
#endif |
|
|
static void char_ptr_dtor_p(char **p) /* {{{ */ |
static void char_ptr_dtor_p(char **p) /* {{{ */ |
{ |
{ |
pefree(*p, 1); |
pefree(*p, 1); |
Line 286 static char *get_last_error() /* {{{ */
|
Line 334 static char *get_last_error() /* {{{ */
|
return pestrdup(strerror(errno), 1); |
return pestrdup(strerror(errno), 1); |
} /* }}} */ |
} /* }}} */ |
|
|
|
static int status_comp(const void *a, const void *b) /* {{{ */ |
|
{ |
|
const php_cli_server_http_response_status_code_pair *pa = (const php_cli_server_http_response_status_code_pair *) a; |
|
const php_cli_server_http_response_status_code_pair *pb = (const php_cli_server_http_response_status_code_pair *) b; |
|
|
|
if (pa->code < pb->code) { |
|
return -1; |
|
} else if (pa->code > pb->code) { |
|
return 1; |
|
} |
|
|
|
return 0; |
|
} /* }}} */ |
|
|
static const char *get_status_string(int code) /* {{{ */ |
static const char *get_status_string(int code) /* {{{ */ |
{ |
{ |
size_t e = (sizeof(status_map) / sizeof(php_cli_server_http_reponse_status_code_pair)); | php_cli_server_http_response_status_code_pair needle, *result = NULL; |
size_t s = 0; | |
|
|
while (e != s) { | needle.code = code; |
size_t c = MIN((e + s + 1) / 2, e - 1); | needle.str = NULL; |
int d = status_map[c].code; | |
if (d > code) { | result = bsearch(&needle, status_map, sizeof(status_map) / sizeof(needle), sizeof(needle), status_comp); |
e = c; | |
} else if (d < code) { | if (result) { |
s = c; | return result->str; |
} else { | |
return status_map[c].str; | |
} | |
} |
} |
return NULL; | |
| /* Returning NULL would require complicating append_http_status_line() to |
| * not segfault in that case, so let's just return a placeholder, since RFC |
| * 2616 requires a reason phrase. This is basically what a lot of other Web |
| * servers do in this case anyway. */ |
| return "Unknown Status Code"; |
} /* }}} */ |
} /* }}} */ |
|
|
static const char *get_template_string(int code) /* {{{ */ |
static const char *get_template_string(int code) /* {{{ */ |
{ |
{ |
size_t e = (sizeof(template_map) / sizeof(php_cli_server_http_reponse_status_code_pair)); | size_t e = (sizeof(template_map) / sizeof(php_cli_server_http_response_status_code_pair)); |
size_t s = 0; |
size_t s = 0; |
|
|
while (e != s) { |
while (e != s) { |
Line 345 static void append_essential_headers(smart_str* buffer
|
Line 408 static void append_essential_headers(smart_str* buffer
|
{ |
{ |
{ |
{ |
char **val; |
char **val; |
if (SUCCESS == zend_hash_find(&client->request.headers, "Host", sizeof("Host"), (void**)&val)) { | if (SUCCESS == zend_hash_find(&client->request.headers, "host", sizeof("host"), (void**)&val)) { |
smart_str_appendl_ex(buffer, "Host", sizeof("Host") - 1, persistent); |
smart_str_appendl_ex(buffer, "Host", sizeof("Host") - 1, persistent); |
smart_str_appendl_ex(buffer, ": ", sizeof(": ") - 1, persistent); |
smart_str_appendl_ex(buffer, ": ", sizeof(": ") - 1, persistent); |
smart_str_appends_ex(buffer, *val, persistent); |
smart_str_appends_ex(buffer, *val, persistent); |
Line 425 static int sapi_cli_server_ub_write(const char *str, u
|
Line 488 static int sapi_cli_server_ub_write(const char *str, u
|
if (!client) { |
if (!client) { |
return 0; |
return 0; |
} |
} |
if (client->capturing) { | return php_cli_server_client_send_through(client, str, str_length); |
php_cli_server_chunk *chunk = php_cli_server_chunk_heap_new_self_contained(str_length); | |
if (!chunk) { | |
zend_bailout(); | |
} | |
memmove(chunk->data.heap.p, str, str_length); | |
php_cli_server_buffer_append(&client->capture_buffer, chunk); | |
return str_length; | |
} else { | |
return php_cli_server_client_send_through(client, str, str_length); | |
} | |
} /* }}} */ |
} /* }}} */ |
|
|
static void sapi_cli_server_flush(void *server_context) /* {{{ */ |
static void sapi_cli_server_flush(void *server_context) /* {{{ */ |
Line 470 static int sapi_cli_server_send_headers(sapi_headers_s
|
Line 523 static int sapi_cli_server_send_headers(sapi_headers_s
|
sapi_header_struct *h; |
sapi_header_struct *h; |
zend_llist_position pos; |
zend_llist_position pos; |
|
|
if (client == NULL || client->capturing || SG(request_info).no_headers) { | if (client == NULL || SG(request_info).no_headers) { |
return SAPI_HEADER_SENT_SUCCESSFULLY; |
return SAPI_HEADER_SENT_SUCCESSFULLY; |
} |
} |
|
|
Line 505 static char *sapi_cli_server_read_cookies(TSRMLS_D) /*
|
Line 558 static char *sapi_cli_server_read_cookies(TSRMLS_D) /*
|
{ |
{ |
php_cli_server_client *client = SG(server_context); |
php_cli_server_client *client = SG(server_context); |
char **val; |
char **val; |
if (FAILURE == zend_hash_find(&client->request.headers, "Cookie", sizeof("Cookie"), (void**)&val)) { | if (FAILURE == zend_hash_find(&client->request.headers, "cookie", sizeof("cookie"), (void**)&val)) { |
return NULL; |
return NULL; |
} |
} |
return *val; |
return *val; |
Line 533 static void sapi_cli_server_register_variable(zval *tr
|
Line 586 static void sapi_cli_server_register_variable(zval *tr
|
} |
} |
} /* }}} */ |
} /* }}} */ |
|
|
static int sapi_cli_server_register_entry_cb(char **entry TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */ { | static int sapi_cli_server_register_entry_cb(char **entry TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */ { |
zval *track_vars_array = va_arg(args, zval *); |
zval *track_vars_array = va_arg(args, zval *); |
if (hash_key->nKeyLength) { |
if (hash_key->nKeyLength) { |
char *real_key, *key; |
char *real_key, *key; |
Line 573 static void sapi_cli_server_register_variables(zval *t
|
Line 626 static void sapi_cli_server_register_variables(zval *t
|
} else { |
} else { |
sapi_cli_server_register_variable(track_vars_array, "REMOTE_ADDR", client->addr_str TSRMLS_CC); |
sapi_cli_server_register_variable(track_vars_array, "REMOTE_ADDR", client->addr_str TSRMLS_CC); |
} |
} |
} | } |
{ |
{ |
char *tmp; |
char *tmp; |
spprintf(&tmp, 0, "PHP %s Development Server", PHP_VERSION); |
spprintf(&tmp, 0, "PHP %s Development Server", PHP_VERSION); |
Line 624 static void sapi_cli_server_register_variables(zval *t
|
Line 677 static void sapi_cli_server_register_variables(zval *t
|
|
|
static void sapi_cli_server_log_message(char *msg TSRMLS_DC) /* {{{ */ |
static void sapi_cli_server_log_message(char *msg TSRMLS_DC) /* {{{ */ |
{ |
{ |
struct timeval tv; |
|
struct tm tm; |
|
char buf[52]; |
char buf[52]; |
gettimeofday(&tv, NULL); | |
php_localtime_r(&tv.tv_sec, &tm); | if (php_cli_server_get_system_time(buf) != 0) { |
php_asctime_r(&tm, buf); | memmove(buf, "unknown time, can't be fetched", sizeof("unknown time, can't be fetched")); |
{ | } else { |
size_t l = strlen(buf); |
size_t l = strlen(buf); |
if (l > 0) { |
if (l > 0) { |
buf[l - 1] = '\0'; |
buf[l - 1] = '\0'; |
Line 671 sapi_module_struct cli_server_sapi_module = {
|
Line 722 sapi_module_struct cli_server_sapi_module = {
|
sapi_cli_server_log_message, /* Log message */ |
sapi_cli_server_log_message, /* Log message */ |
NULL, /* Get request time */ |
NULL, /* Get request time */ |
NULL, /* Child terminate */ |
NULL, /* Child terminate */ |
| |
STANDARD_SAPI_MODULE_PROPERTIES |
STANDARD_SAPI_MODULE_PROPERTIES |
}; /* }}} */ |
}; /* }}} */ |
|
|
Line 708 static void php_cli_server_poller_remove(php_cli_serve
|
Line 759 static void php_cli_server_poller_remove(php_cli_serve
|
if (fd == poller->max_fd) { |
if (fd == poller->max_fd) { |
while (fd > 0) { |
while (fd > 0) { |
fd--; |
fd--; |
if (((unsigned int *)&poller->rfds)[fd / (8 * sizeof(unsigned int))] || ((unsigned int *)&poller->wfds)[fd / (8 * sizeof(unsigned int))]) { | if (PHP_SAFE_FD_ISSET(fd, &poller->rfds) || PHP_SAFE_FD_ISSET(fd, &poller->wfds)) { |
break; |
break; |
} |
} |
fd -= fd % (8 * sizeof(unsigned int)); |
|
} |
} |
poller->max_fd = fd; |
poller->max_fd = fd; |
} |
} |
Line 768 static int php_cli_server_poller_iter_on_active(php_cl
|
Line 818 static int php_cli_server_poller_iter_on_active(php_cl
|
} |
} |
} |
} |
} |
} |
| |
#else |
#else |
php_socket_t fd = 0; | php_socket_t fd; |
const php_socket_t max_fd = poller->max_fd; |
const php_socket_t max_fd = poller->max_fd; |
const unsigned int *pr = (unsigned int *)&poller->active.rfds, | |
*pw = (unsigned int *)&poller->active.wfds, | for (fd=0 ; fd<=max_fd ; fd++) { |
*e = pr + (max_fd + (8 * sizeof(unsigned int)) - 1) / (8 * sizeof(unsigned int)); | if (PHP_SAFE_FD_ISSET(fd, &poller->active.rfds)) { |
unsigned int mask; | if (SUCCESS != callback(opaque, fd, POLLIN)) { |
while (pr < e && fd <= max_fd) { | retval = FAILURE; |
for (mask = 1; mask; mask <<= 1, fd++) { | } |
int events = (*pr & mask ? POLLIN: 0) | (*pw & mask ? POLLOUT: 0); | |
if (events) { | |
if (SUCCESS != callback(opaque, fd, events)) { | |
retval = FAILURE; | |
} | |
} | |
} |
} |
pr++; | if (PHP_SAFE_FD_ISSET(fd, &poller->active.wfds)) { |
pw++; | if (SUCCESS != callback(opaque, fd, POLLOUT)) { |
| retval = FAILURE; |
| } |
| } |
} |
} |
#endif |
#endif |
return retval; |
return retval; |
Line 956 static int php_cli_server_content_sender_send(php_cli_
|
Line 1003 static int php_cli_server_content_sender_send(php_cli_
|
} else if (nbytes_sent == chunk->data.immortal.len) { |
} else if (nbytes_sent == chunk->data.immortal.len) { |
php_cli_server_chunk_dtor(chunk); |
php_cli_server_chunk_dtor(chunk); |
pefree(chunk, 1); |
pefree(chunk, 1); |
sender->buffer.first = next; | sender->buffer.first = next; |
if (!next) { |
if (!next) { |
sender->buffer.last = NULL; |
sender->buffer.last = NULL; |
} |
} |
Line 1277 static void php_cli_server_request_translate_vpath(php
|
Line 1324 static void php_cli_server_request_translate_vpath(php
|
struct stat sb; |
struct stat sb; |
static const char *index_files[] = { "index.php", "index.html", NULL }; |
static const char *index_files[] = { "index.php", "index.html", NULL }; |
char *buf = safe_pemalloc(1, request->vpath_len, 1 + document_root_len + 1 + sizeof("index.html"), 1); |
char *buf = safe_pemalloc(1, request->vpath_len, 1 + document_root_len + 1 + sizeof("index.html"), 1); |
char *p = buf, *prev_patch = 0, *q, *vpath; | char *p = buf, *prev_path = NULL, *q, *vpath; |
size_t prev_patch_len; | size_t prev_path_len = 0; |
int is_static_file = 0; |
int is_static_file = 0; |
|
|
if (!buf) { |
if (!buf) { |
Line 1327 static void php_cli_server_request_translate_vpath(php
|
Line 1374 static void php_cli_server_request_translate_vpath(php
|
file++; |
file++; |
} |
} |
if (!*file || is_static_file) { |
if (!*file || is_static_file) { |
if (prev_patch) { | if (prev_path) { |
pefree(prev_patch, 1); | pefree(prev_path, 1); |
} |
} |
pefree(buf, 1); |
pefree(buf, 1); |
return; |
return; |
} |
} |
} |
} |
break; /* regular file */ |
break; /* regular file */ |
} | } |
if (prev_patch) { | if (prev_path) { |
pefree(prev_patch, 1); | pefree(prev_path, 1); |
*q = DEFAULT_SLASH; |
*q = DEFAULT_SLASH; |
} |
} |
while (q > buf && *(--q) != DEFAULT_SLASH); |
while (q > buf && *(--q) != DEFAULT_SLASH); |
prev_patch_len = p - q; | prev_path_len = p - q; |
prev_patch = pestrndup(q, prev_patch_len, 1); | prev_path = pestrndup(q, prev_path_len, 1); |
*q = '\0'; |
*q = '\0'; |
} |
} |
if (prev_patch) { | if (prev_path) { |
request->path_info_len = prev_patch_len; | request->path_info_len = prev_path_len; |
#ifdef PHP_WIN32 |
#ifdef PHP_WIN32 |
while (prev_patch_len--) { | while (prev_path_len--) { |
if (prev_patch[prev_patch_len] == '\\') { | if (prev_path[prev_path_len] == '\\') { |
prev_patch[prev_patch_len] = '/'; | prev_path[prev_path_len] = '/'; |
} |
} |
} |
} |
#endif |
#endif |
request->path_info = prev_patch; | request->path_info = prev_path; |
pefree(request->vpath, 1); |
pefree(request->vpath, 1); |
request->vpath = pestrndup(vpath, q - vpath, 1); |
request->vpath = pestrndup(vpath, q - vpath, 1); |
request->vpath_len = q - vpath; |
request->vpath_len = q - vpath; |
Line 1374 static void php_cli_server_request_translate_vpath(php
|
Line 1421 static void php_cli_server_request_translate_vpath(php
|
if (request->vpath[i] == '\\') { |
if (request->vpath[i] == '\\') { |
request->vpath[i] = '/'; |
request->vpath[i] = '/'; |
} |
} |
} | } |
} |
} |
#endif |
#endif |
request->sb = sb; |
request->sb = sb; |
Line 1442 static void normalize_vpath(char **retval, size_t *ret
|
Line 1489 static void normalize_vpath(char **retval, size_t *ret
|
} |
} |
} |
} |
} |
} |
| |
*decoded_vpath_end = '\0'; |
*decoded_vpath_end = '\0'; |
*retval = decoded_vpath; |
*retval = decoded_vpath; |
*retval_len = decoded_vpath_end - decoded_vpath; |
*retval_len = decoded_vpath_end - decoded_vpath; |
Line 1509 static int php_cli_server_client_read_request_on_heade
|
Line 1556 static int php_cli_server_client_read_request_on_heade
|
return 1; |
return 1; |
} |
} |
{ |
{ |
char *header_name = client->current_header_name; | char *header_name = zend_str_tolower_dup(client->current_header_name, client->current_header_name_len); |
size_t header_name_len = client->current_header_name_len; | zend_hash_add(&client->request.headers, header_name, client->current_header_name_len + 1, &value, sizeof(char *), NULL); |
char c = header_name[header_name_len]; | efree(header_name); |
header_name[header_name_len] = '\0'; | |
zend_hash_add(&client->request.headers, header_name, header_name_len + 1, &value, sizeof(char *), NULL); | |
header_name[header_name_len] = c; | |
} |
} |
|
|
if (client->current_header_name_allocated) { |
if (client->current_header_name_allocated) { |
Line 1545 static int php_cli_server_client_read_request_on_body(
|
Line 1589 static int php_cli_server_client_read_request_on_body(
|
} |
} |
client->request.content_len = 0; |
client->request.content_len = 0; |
} |
} |
|
client->request.content = perealloc(client->request.content, client->request.content_len + length, 1); |
memmove(client->request.content + client->request.content_len, at, length); |
memmove(client->request.content + client->request.content_len, at, length); |
client->request.content_len += length; |
client->request.content_len += length; |
return 0; |
return 0; |
Line 1608 static int php_cli_server_client_read_request(php_cli_
|
Line 1653 static int php_cli_server_client_read_request(php_cli_
|
client->parser.data = client; |
client->parser.data = client; |
nbytes_consumed = php_http_parser_execute(&client->parser, &settings, buf, nbytes_read); |
nbytes_consumed = php_http_parser_execute(&client->parser, &settings, buf, nbytes_read); |
if (nbytes_consumed != nbytes_read) { |
if (nbytes_consumed != nbytes_read) { |
*errstr = estrdup("Malformed HTTP request"); | if (buf[0] & 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) { |
| *errstr = estrdup("Unsupported SSL request"); |
| } else { |
| *errstr = estrdup("Malformed HTTP request"); |
| } |
return -1; |
return -1; |
} |
} |
if (client->current_header_name) { |
if (client->current_header_name) { |
Line 1668 static void php_cli_server_client_populate_request_inf
|
Line 1717 static void php_cli_server_client_populate_request_inf
|
request_info->post_data = client->request.content; |
request_info->post_data = client->request.content; |
request_info->content_length = request_info->post_data_length = client->request.content_len; |
request_info->content_length = request_info->post_data_length = client->request.content_len; |
request_info->auth_user = request_info->auth_password = request_info->auth_digest = NULL; |
request_info->auth_user = request_info->auth_password = request_info->auth_digest = NULL; |
if (SUCCESS == zend_hash_find(&client->request.headers, "Content-Type", sizeof("Content-Type"), (void**)&val)) { | if (SUCCESS == zend_hash_find(&client->request.headers, "content-type", sizeof("content-type"), (void**)&val)) { |
request_info->content_type = *val; |
request_info->content_type = *val; |
} |
} |
} /* }}} */ |
} /* }}} */ |
Line 1677 static void destroy_request_info(sapi_request_info *re
|
Line 1726 static void destroy_request_info(sapi_request_info *re
|
{ |
{ |
} /* }}} */ |
} /* }}} */ |
|
|
static void php_cli_server_client_begin_capture(php_cli_server_client *client) /* {{{ */ |
|
{ |
|
php_cli_server_buffer_ctor(&client->capture_buffer); |
|
client->capturing = 1; |
|
} /* }}} */ |
|
|
|
static void php_cli_server_client_end_capture(php_cli_server_client *client) /* {{{ */ |
|
{ |
|
client->capturing = 0; |
|
php_cli_server_buffer_dtor(&client->capture_buffer); |
|
} /* }}} */ |
|
|
|
static int php_cli_server_client_ctor(php_cli_server_client *client, php_cli_server *server, int client_sock, struct sockaddr *addr, socklen_t addr_len TSRMLS_DC) /* {{{ */ |
static int php_cli_server_client_ctor(php_cli_server_client *client, php_cli_server *server, int client_sock, struct sockaddr *addr, socklen_t addr_len TSRMLS_DC) /* {{{ */ |
{ |
{ |
client->server = server; |
client->server = server; |
Line 1713 static int php_cli_server_client_ctor(php_cli_server_c
|
Line 1750 static int php_cli_server_client_ctor(php_cli_server_c
|
return FAILURE; |
return FAILURE; |
} |
} |
client->content_sender_initialized = 0; |
client->content_sender_initialized = 0; |
client->capturing = 0; |
|
client->file_fd = -1; |
client->file_fd = -1; |
return SUCCESS; |
return SUCCESS; |
} /* }}} */ |
} /* }}} */ |
Line 1730 static void php_cli_server_client_dtor(php_cli_server_
|
Line 1766 static void php_cli_server_client_dtor(php_cli_server_
|
if (client->content_sender_initialized) { |
if (client->content_sender_initialized) { |
php_cli_server_content_sender_dtor(&client->content_sender); |
php_cli_server_content_sender_dtor(&client->content_sender); |
} |
} |
if (client->capturing) { |
|
php_cli_server_buffer_dtor(&client->capture_buffer); |
|
} |
|
} /* }}} */ |
} /* }}} */ |
|
|
static void php_cli_server_close_connection(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) /* {{{ */ |
static void php_cli_server_close_connection(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) /* {{{ */ |
Line 1758 static int php_cli_server_send_error_page(php_cli_serv
|
Line 1791 static int php_cli_server_send_error_page(php_cli_serv
|
escaped_request_uri = php_escape_html_entities_ex((unsigned char *)client->request.request_uri, client->request.request_uri_len, &escaped_request_uri_len, 0, ENT_QUOTES, NULL, 0 TSRMLS_CC); |
escaped_request_uri = php_escape_html_entities_ex((unsigned char *)client->request.request_uri, client->request.request_uri_len, &escaped_request_uri_len, 0, ENT_QUOTES, NULL, 0 TSRMLS_CC); |
|
|
{ |
{ |
static const char prologue_template[] = "<html><head><title>%d %s</title>"; | static const char prologue_template[] = "<!doctype html><html><head><title>%d %s</title>"; |
php_cli_server_chunk *chunk = php_cli_server_chunk_heap_new_self_contained(strlen(prologue_template) + 3 + strlen(status_string) + 1); |
php_cli_server_chunk *chunk = php_cli_server_chunk_heap_new_self_contained(strlen(prologue_template) + 3 + strlen(status_string) + 1); |
if (!chunk) { |
if (!chunk) { |
goto fail; |
goto fail; |
Line 1768 static int php_cli_server_send_error_page(php_cli_serv
|
Line 1801 static int php_cli_server_send_error_page(php_cli_serv
|
php_cli_server_buffer_append(&client->content_sender.buffer, chunk); |
php_cli_server_buffer_append(&client->content_sender.buffer, chunk); |
} |
} |
{ |
{ |
int err = 0; | php_cli_server_chunk *chunk = php_cli_server_chunk_immortal_new(php_cli_server_css, sizeof(php_cli_server_css) - 1); |
zval *style = NULL; | if (!chunk) { |
zend_try { | |
if (!SG(sapi_started)) { | |
php_output_activate(TSRMLS_C); | |
} | |
php_output_start_user(NULL, 0, PHP_OUTPUT_HANDLER_STDFLAGS TSRMLS_CC); | |
php_info_print_style(TSRMLS_C); | |
MAKE_STD_ZVAL(style); | |
php_output_get_contents(style TSRMLS_CC); | |
php_output_discard(TSRMLS_C); | |
if (!SG(sapi_started)) { | |
static int (*send_header_func)(sapi_headers_struct * TSRMLS_DC); | |
send_header_func = sapi_module.send_headers; | |
/* we don't want the header to be sent now */ | |
sapi_module.send_headers = sapi_cli_server_discard_headers; | |
php_output_deactivate(TSRMLS_C); | |
sapi_module.send_headers = send_header_func; | |
} | |
if (style && Z_STRVAL_P(style)) { | |
char *block = pestrndup(Z_STRVAL_P(style), Z_STRLEN_P(style), 1); | |
php_cli_server_chunk *chunk = php_cli_server_chunk_heap_new(block, block, Z_STRLEN_P(style)); | |
if (!chunk) { | |
zval_ptr_dtor(&style); | |
goto fail; | |
} | |
php_cli_server_buffer_append(&client->content_sender.buffer, chunk); | |
zval_ptr_dtor(&style); | |
} else { | |
err = 1; | |
} | |
} zend_catch { | |
err = 1; | |
} zend_end_try(); | |
if (err) { | |
goto fail; |
goto fail; |
} |
} |
|
php_cli_server_buffer_append(&client->content_sender.buffer, chunk); |
} |
} |
{ |
{ |
static const char template[] = "</head><body>"; |
static const char template[] = "</head><body>"; |
Line 1846 static int php_cli_server_send_error_page(php_cli_serv
|
Line 1847 static int php_cli_server_send_error_page(php_cli_serv
|
smart_str_append_generic_ex(&buffer, php_cli_server_buffer_size(&client->content_sender.buffer), 1, size_t, _unsigned); |
smart_str_append_generic_ex(&buffer, php_cli_server_buffer_size(&client->content_sender.buffer), 1, size_t, _unsigned); |
smart_str_appendl_ex(&buffer, "\r\n", 2, 1); |
smart_str_appendl_ex(&buffer, "\r\n", 2, 1); |
smart_str_appendl_ex(&buffer, "\r\n", 2, 1); |
smart_str_appendl_ex(&buffer, "\r\n", 2, 1); |
| |
chunk = php_cli_server_chunk_heap_new(buffer.c, buffer.c, buffer.len); |
chunk = php_cli_server_chunk_heap_new(buffer.c, buffer.c, buffer.len); |
if (!chunk) { |
if (!chunk) { |
smart_str_free_ex(&buffer, 1); |
smart_str_free_ex(&buffer, 1); |
Line 1864 static int php_cli_server_send_error_page(php_cli_serv
|
Line 1865 static int php_cli_server_send_error_page(php_cli_serv
|
return SUCCESS; |
return SUCCESS; |
|
|
fail: |
fail: |
|
if (errstr) { |
|
pefree(errstr, 1); |
|
} |
efree(escaped_request_uri); |
efree(escaped_request_uri); |
return FAILURE; |
return FAILURE; |
} /* }}} */ |
} /* }}} */ |
Line 1948 static int php_cli_server_begin_send_static(php_cli_se
|
Line 1952 static int php_cli_server_begin_send_static(php_cli_se
|
} |
} |
/* }}} */ |
/* }}} */ |
|
|
static int php_cli_server_request_startup(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) { /* {{{ */ | static int php_cli_server_request_startup(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) { /* {{{ */ |
char **auth; |
char **auth; |
php_cli_server_client_populate_request_info(client, &SG(request_info)); |
php_cli_server_client_populate_request_info(client, &SG(request_info)); |
if (SUCCESS == zend_hash_find(&client->request.headers, "Authorization", sizeof("Authorization"), (void**)&auth)) { | if (SUCCESS == zend_hash_find(&client->request.headers, "authorization", sizeof("authorization"), (void**)&auth)) { |
php_handle_auth_data(*auth TSRMLS_CC); |
php_handle_auth_data(*auth TSRMLS_CC); |
} |
} |
SG(sapi_headers).http_response_code = 200; |
SG(sapi_headers).http_response_code = 200; |
Line 1973 static int php_cli_server_request_shutdown(php_cli_ser
|
Line 1977 static int php_cli_server_request_shutdown(php_cli_ser
|
SG(server_context) = NULL; |
SG(server_context) = NULL; |
SG(rfc1867_uploaded_files) = NULL; |
SG(rfc1867_uploaded_files) = NULL; |
return SUCCESS; |
return SUCCESS; |
} | } |
/* }}} */ | /* }}} */ |
|
|
static int php_cli_server_dispatch_router(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) /* {{{ */ |
static int php_cli_server_dispatch_router(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) /* {{{ */ |
{ |
{ |
Line 2033 static int php_cli_server_dispatch(php_cli_server *ser
|
Line 2037 static int php_cli_server_dispatch(php_cli_server *ser
|
destroy_request_info(&SG(request_info)); |
destroy_request_info(&SG(request_info)); |
return SUCCESS; |
return SUCCESS; |
} |
} |
} | } |
|
|
if (server->router) { |
if (server->router) { |
if (!php_cli_server_dispatch_router(server, client TSRMLS_CC)) { |
if (!php_cli_server_dispatch_router(server, client TSRMLS_CC)) { |
Line 2047 static int php_cli_server_dispatch(php_cli_server *ser
|
Line 2051 static int php_cli_server_dispatch(php_cli_server *ser
|
|| SUCCESS != php_cli_server_send_error_page(server, client, 500 TSRMLS_CC)) { |
|| SUCCESS != php_cli_server_send_error_page(server, client, 500 TSRMLS_CC)) { |
php_cli_server_request_shutdown(server, client TSRMLS_CC); |
php_cli_server_request_shutdown(server, client TSRMLS_CC); |
return SUCCESS; |
return SUCCESS; |
} | } |
} else { |
} else { |
if (server->router) { |
if (server->router) { |
static int (*send_header_func)(sapi_headers_struct * TSRMLS_DC); |
static int (*send_header_func)(sapi_headers_struct * TSRMLS_DC); |
send_header_func = sapi_module.send_headers; |
send_header_func = sapi_module.send_headers; |
/* we don't want the header to be sent now */ | /* do not generate default content type header */ |
| SG(sapi_headers).send_default_content_type = 0; |
| /* we don't want headers to be sent */ |
sapi_module.send_headers = sapi_cli_server_discard_headers; |
sapi_module.send_headers = sapi_cli_server_discard_headers; |
php_request_shutdown(0); |
php_request_shutdown(0); |
sapi_module.send_headers = send_header_func; |
sapi_module.send_headers = send_header_func; |
|
SG(sapi_headers).send_default_content_type = 1; |
SG(rfc1867_uploaded_files) = NULL; |
SG(rfc1867_uploaded_files) = NULL; |
} | } |
if (SUCCESS != php_cli_server_begin_send_static(server, client TSRMLS_CC)) { |
if (SUCCESS != php_cli_server_begin_send_static(server, client TSRMLS_CC)) { |
php_cli_server_close_connection(server, client TSRMLS_CC); |
php_cli_server_close_connection(server, client TSRMLS_CC); |
} |
} |
Line 2219 static int php_cli_server_recv_event_read_request(php_
|
Line 2226 static int php_cli_server_recv_event_read_request(php_
|
efree(errstr); |
efree(errstr); |
php_cli_server_close_connection(server, client TSRMLS_CC); |
php_cli_server_close_connection(server, client TSRMLS_CC); |
return FAILURE; |
return FAILURE; |
|
} else if (status == 1 && client->request.request_method == PHP_HTTP_NOT_IMPLEMENTED) { |
|
return php_cli_server_send_error_page(server, client, 501 TSRMLS_CC); |
} else if (status == 1) { |
} else if (status == 1) { |
php_cli_server_poller_remove(&server->poller, POLLIN, client->sock); |
php_cli_server_poller_remove(&server->poller, POLLIN, client->sock); |
php_cli_server_dispatch(server, client TSRMLS_CC); |
php_cli_server_dispatch(server, client TSRMLS_CC); |
Line 2339 static void php_cli_server_do_event_for_each_fd(php_cl
|
Line 2348 static void php_cli_server_do_event_for_each_fd(php_cl
|
static int php_cli_server_do_event_loop(php_cli_server *server TSRMLS_DC) /* {{{ */ |
static int php_cli_server_do_event_loop(php_cli_server *server TSRMLS_DC) /* {{{ */ |
{ |
{ |
int retval = SUCCESS; |
int retval = SUCCESS; |
while (server->is_running) { | while (server->is_running) { |
static const struct timeval tv = { 1, 0 }; |
static const struct timeval tv = { 1, 0 }; |
int n = php_cli_server_poller_poll(&server->poller, &tv); |
int n = php_cli_server_poller_poll(&server->poller, &tv); |
if (n > 0) { |
if (n > 0) { |
Line 2428 int do_cli_server(int argc, char **argv TSRMLS_DC) /*
|
Line 2437 int do_cli_server(int argc, char **argv TSRMLS_DC) /*
|
sapi_module.phpinfo_as_text = 0; |
sapi_module.phpinfo_as_text = 0; |
|
|
{ |
{ |
struct timeval tv; |
|
struct tm tm; |
|
char buf[52]; |
char buf[52]; |
gettimeofday(&tv, NULL); | |
php_localtime_r(&tv.tv_sec, &tm); | if (php_cli_server_get_system_time(buf) != 0) { |
php_asctime_r(&tm, buf); | memmove(buf, "unknown time, can't be fetched", sizeof("unknown time, can't be fetched")); |
| } |
| |
printf("PHP %s Development Server started at %s" |
printf("PHP %s Development Server started at %s" |
"Listening on %s\n" | "Listening on http://%s\n" |
"Document root is %s\n" |
"Document root is %s\n" |
"Press Ctrl-C to quit.\n", |
"Press Ctrl-C to quit.\n", |
PHP_VERSION, buf, server_bind_address, document_root); |
PHP_VERSION, buf, server_bind_address, document_root); |