mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Revert "Refactor CLI SAPI php_cli_server_client struct to use zend_string (#8522)"
This reverts commit 9b19d90432
.
This has broken the ZEND_RC_DEBUG build.
This commit is contained in:
parent
96838129ea
commit
82d407b7e0
5 changed files with 142 additions and 243 deletions
|
@ -164,15 +164,19 @@ typedef struct php_cli_server_client {
|
|||
php_socket_t sock;
|
||||
struct sockaddr *addr;
|
||||
socklen_t addr_len;
|
||||
zend_string *addr_str;
|
||||
char *addr_str;
|
||||
size_t addr_str_len;
|
||||
php_http_parser parser;
|
||||
bool request_read;
|
||||
zend_string *current_header_name;
|
||||
zend_string *current_header_value;
|
||||
unsigned int request_read:1;
|
||||
char *current_header_name;
|
||||
size_t current_header_name_len;
|
||||
unsigned int current_header_name_allocated:1;
|
||||
char *current_header_value;
|
||||
size_t current_header_value_len;
|
||||
enum { HEADER_NONE=0, HEADER_FIELD, HEADER_VALUE } last_header_element;
|
||||
size_t post_read_offset;
|
||||
php_cli_server_request request;
|
||||
bool content_sender_initialized;
|
||||
unsigned int content_sender_initialized:1;
|
||||
php_cli_server_content_sender content_sender;
|
||||
int file_fd;
|
||||
} php_cli_server_client;
|
||||
|
@ -266,10 +270,9 @@ static bool php_cli_server_get_system_time(char *buf) {
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Destructor for php_cli_server_request->headers, this frees header value */
|
||||
static void cli_header_value_dtor(zval *zv) /* {{{ */
|
||||
static void char_ptr_dtor_p(zval *zv) /* {{{ */
|
||||
{
|
||||
zend_string_release_ex(Z_STR_P(zv), /* persistent */ true);
|
||||
pefree(Z_PTR_P(zv), 1);
|
||||
} /* }}} */
|
||||
|
||||
static char *get_last_error(void) /* {{{ */
|
||||
|
@ -347,19 +350,19 @@ static void append_http_status_line(smart_str *buffer, int protocol_version, int
|
|||
|
||||
static void append_essential_headers(smart_str* buffer, php_cli_server_client *client, bool persistent) /* {{{ */
|
||||
{
|
||||
zval *val;
|
||||
char *val;
|
||||
struct timeval tv = {0};
|
||||
|
||||
if (NULL != (val = zend_hash_str_find(&client->request.headers, "host", sizeof("host")-1))) {
|
||||
if (NULL != (val = zend_hash_str_find_ptr(&client->request.headers, "host", sizeof("host")-1))) {
|
||||
smart_str_appends_ex(buffer, "Host: ", persistent);
|
||||
smart_str_append_ex(buffer, Z_STR_P(val), persistent);
|
||||
smart_str_appends_ex(buffer, val, persistent);
|
||||
smart_str_appends_ex(buffer, "\r\n", persistent);
|
||||
}
|
||||
|
||||
if (!gettimeofday(&tv, NULL)) {
|
||||
zend_string *dt = php_format_date("D, d M Y H:i:s", sizeof("D, d M Y H:i:s") - 1, tv.tv_sec, 0);
|
||||
smart_str_appends_ex(buffer, "Date: ", persistent);
|
||||
smart_str_append_ex(buffer, dt, persistent);
|
||||
smart_str_appends_ex(buffer, dt->val, persistent);
|
||||
smart_str_appends_ex(buffer, " GMT\r\n", persistent);
|
||||
zend_string_release_ex(dt, 0);
|
||||
}
|
||||
|
@ -381,6 +384,9 @@ static const char *get_mime_type(const php_cli_server *server, const char *ext,
|
|||
PHP_FUNCTION(apache_request_headers) /* {{{ */
|
||||
{
|
||||
php_cli_server_client *client;
|
||||
HashTable *headers;
|
||||
zend_string *key;
|
||||
char *value;
|
||||
zval tmp;
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
|
@ -388,10 +394,14 @@ PHP_FUNCTION(apache_request_headers) /* {{{ */
|
|||
}
|
||||
|
||||
client = SG(server_context);
|
||||
headers = &client->request.headers_original_case;
|
||||
|
||||
/* Need to copy the HashTable */
|
||||
ZVAL_ARR(&tmp,&client->request.headers_original_case);
|
||||
RETURN_COPY(&tmp);
|
||||
array_init_size(return_value, zend_hash_num_elements(headers));
|
||||
|
||||
ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(headers, key, value) {
|
||||
ZVAL_STRING(&tmp, value);
|
||||
zend_symtable_update(Z_ARRVAL_P(return_value), key, &tmp);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -564,11 +574,11 @@ static int sapi_cli_server_send_headers(sapi_headers_struct *sapi_headers) /* {{
|
|||
static char *sapi_cli_server_read_cookies(void) /* {{{ */
|
||||
{
|
||||
php_cli_server_client *client = SG(server_context);
|
||||
zval *val;
|
||||
if (NULL == (val = zend_hash_str_find(&client->request.headers, "cookie", sizeof("cookie")-1))) {
|
||||
char *val;
|
||||
if (NULL == (val = zend_hash_str_find_ptr(&client->request.headers, "cookie", sizeof("cookie")-1))) {
|
||||
return NULL;
|
||||
}
|
||||
return Z_STRVAL_P(val);
|
||||
return val;
|
||||
} /* }}} */
|
||||
|
||||
static size_t sapi_cli_server_read_post(char *buf, size_t count_bytes) /* {{{ */
|
||||
|
@ -598,12 +608,8 @@ static void sapi_cli_server_register_variable(zval *track_vars_array, const char
|
|||
}
|
||||
} /* }}} */
|
||||
|
||||
/* The entry zval will always contain a zend_string* */
|
||||
static int sapi_cli_server_register_entry_cb(zval *entry, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */ {
|
||||
static int sapi_cli_server_register_entry_cb(char **entry, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */ {
|
||||
zval *track_vars_array = va_arg(args, zval *);
|
||||
|
||||
ZEND_ASSERT(Z_TYPE_P(entry) == IS_STRING);
|
||||
|
||||
if (hash_key->key) {
|
||||
char *real_key, *key;
|
||||
uint32_t i;
|
||||
|
@ -617,10 +623,9 @@ static int sapi_cli_server_register_entry_cb(zval *entry, int num_args, va_list
|
|||
}
|
||||
spprintf(&real_key, 0, "%s_%s", "HTTP", key);
|
||||
if (strcmp(key, "CONTENT_TYPE") == 0 || strcmp(key, "CONTENT_LENGTH") == 0) {
|
||||
// TODO make a version specialized for zend_string?
|
||||
sapi_cli_server_register_variable(track_vars_array, key, Z_STRVAL_P(entry));
|
||||
sapi_cli_server_register_variable(track_vars_array, key, *entry);
|
||||
}
|
||||
sapi_cli_server_register_variable(track_vars_array, real_key, Z_STRVAL_P(entry));
|
||||
sapi_cli_server_register_variable(track_vars_array, real_key, *entry);
|
||||
efree(key);
|
||||
efree(real_key);
|
||||
}
|
||||
|
@ -635,9 +640,9 @@ static void sapi_cli_server_register_variables(zval *track_vars_array) /* {{{ */
|
|||
sapi_cli_server_register_variable(track_vars_array, "DOCUMENT_ROOT", client->server->document_root);
|
||||
{
|
||||
char *tmp;
|
||||
if ((tmp = strrchr(ZSTR_VAL(client->addr_str), ':'))) {
|
||||
if ((tmp = strrchr(client->addr_str, ':'))) {
|
||||
char addr[64], port[8];
|
||||
const char *addr_start = ZSTR_VAL(client->addr_str), *addr_end = tmp;
|
||||
const char *addr_start = client->addr_str, *addr_end = tmp;
|
||||
if (addr_start[0] == '[') addr_start++;
|
||||
if (addr_end[-1] == ']') addr_end--;
|
||||
|
||||
|
@ -648,7 +653,7 @@ static void sapi_cli_server_register_variables(zval *track_vars_array) /* {{{ */
|
|||
sapi_cli_server_register_variable(track_vars_array, "REMOTE_ADDR", addr);
|
||||
sapi_cli_server_register_variable(track_vars_array, "REMOTE_PORT", port);
|
||||
} else {
|
||||
sapi_cli_server_register_variable(track_vars_array, "REMOTE_ADDR", ZSTR_VAL(client->addr_str));
|
||||
sapi_cli_server_register_variable(track_vars_array, "REMOTE_ADDR", client->addr_str);
|
||||
}
|
||||
}
|
||||
{
|
||||
|
@ -1147,8 +1152,7 @@ static void php_cli_server_log_response(php_cli_server_client *client, int statu
|
|||
#endif
|
||||
|
||||
/* basic */
|
||||
spprintf(&basic_buf, 0, "%s [%d]: %s %s", ZSTR_VAL(client->addr_str), status,
|
||||
php_http_method_str(client->request.request_method), client->request.request_uri);
|
||||
spprintf(&basic_buf, 0, "%s [%d]: %s %s", client->addr_str, status, php_http_method_str(client->request.request_method), client->request.request_uri);
|
||||
if (!basic_buf) {
|
||||
return;
|
||||
}
|
||||
|
@ -1335,8 +1339,7 @@ static void php_cli_server_request_ctor(php_cli_server_request *req) /* {{{ */
|
|||
req->path_info_len = 0;
|
||||
req->query_string = NULL;
|
||||
req->query_string_len = 0;
|
||||
zend_hash_init(&req->headers, 0, NULL, cli_header_value_dtor, 1);
|
||||
/* No destructor is registered as the value pointed by is the same as for &req->headers */
|
||||
zend_hash_init(&req->headers, 0, NULL, char_ptr_dtor_p, 1);
|
||||
zend_hash_init(&req->headers_original_case, 0, NULL, NULL, 1);
|
||||
req->content = NULL;
|
||||
req->content_len = 0;
|
||||
|
@ -1370,7 +1373,7 @@ static void php_cli_server_request_dtor(php_cli_server_request *req) /* {{{ */
|
|||
|
||||
static void php_cli_server_request_translate_vpath(php_cli_server_request *request, const char *document_root, size_t document_root_len) /* {{{ */
|
||||
{
|
||||
zend_stat_t sb = {0};
|
||||
zend_stat_t sb;
|
||||
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 *p = buf, *prev_path = NULL, *q, *vpath;
|
||||
|
@ -1619,53 +1622,56 @@ static int php_cli_server_client_read_request_on_fragment(php_http_parser *parse
|
|||
|
||||
static void php_cli_server_client_save_header(php_cli_server_client *client)
|
||||
{
|
||||
/* Wrap header value in a zval to add is to the HashTable which acts as an array */
|
||||
zval tmp;
|
||||
ZVAL_STR(&tmp, client->current_header_value);
|
||||
/* strip off the colon */
|
||||
zend_string *lc_header_name = zend_string_tolower_ex(client->current_header_name, /* persistent */ true);
|
||||
|
||||
/* Add the wrapped zend_string to the HashTable */
|
||||
zend_hash_add(&client->request.headers, lc_header_name, &tmp);
|
||||
zend_hash_add(&client->request.headers_original_case, client->current_header_name, &tmp);
|
||||
|
||||
zend_string_release_ex(lc_header_name, /* persistent */ true);
|
||||
zend_string *orig_header_name = zend_string_init(client->current_header_name, client->current_header_name_len, 1);
|
||||
zend_string *lc_header_name = zend_string_alloc(client->current_header_name_len, 1);
|
||||
zend_str_tolower_copy(ZSTR_VAL(lc_header_name), client->current_header_name, client->current_header_name_len);
|
||||
GC_MAKE_PERSISTENT_LOCAL(orig_header_name);
|
||||
GC_MAKE_PERSISTENT_LOCAL(lc_header_name);
|
||||
zend_hash_add_ptr(&client->request.headers, lc_header_name, client->current_header_value);
|
||||
zend_hash_add_ptr(&client->request.headers_original_case, orig_header_name, client->current_header_value);
|
||||
zend_string_release_ex(lc_header_name, 1);
|
||||
zend_string_release_ex(orig_header_name, 1);
|
||||
|
||||
if (client->current_header_name_allocated) {
|
||||
pefree(client->current_header_name, 1);
|
||||
client->current_header_name_allocated = 0;
|
||||
}
|
||||
client->current_header_name = NULL;
|
||||
client->current_header_name_len = 0;
|
||||
client->current_header_value = NULL;
|
||||
}
|
||||
|
||||
static zend_string* cli_concat_persistent_zstr_with_char(zend_string *old_str, const char *at, size_t length)
|
||||
{
|
||||
/* Assert that there is only one reference to the string, as then zend_string_extends()
|
||||
* will reallocate it such that we do not need to release the old value. */
|
||||
ZEND_ASSERT(GC_REFCOUNT(old_str) == 1);
|
||||
/* Previous element was part of header value, append content to it */
|
||||
size_t old_length = ZSTR_LEN(old_str);
|
||||
zend_string *str = zend_string_extend(old_str, old_length + length, /* persistent */ true);
|
||||
memcpy(ZSTR_VAL(str) + old_length, at, length);
|
||||
// Null terminate
|
||||
ZSTR_VAL(str)[ZSTR_LEN(str)] = '\0';
|
||||
return str;
|
||||
client->current_header_value_len = 0;
|
||||
}
|
||||
|
||||
static int php_cli_server_client_read_request_on_header_field(php_http_parser *parser, const char *at, size_t length)
|
||||
{
|
||||
php_cli_server_client *client = parser->data;
|
||||
switch (client->last_header_element) {
|
||||
case HEADER_VALUE:
|
||||
/* Save previous header before creating new one */
|
||||
php_cli_server_client_save_header(client);
|
||||
ZEND_FALLTHROUGH;
|
||||
case HEADER_NONE:
|
||||
/* Create new header field */
|
||||
client->current_header_name = zend_string_init(at, length, /* persistent */ true);
|
||||
break;
|
||||
case HEADER_FIELD: {
|
||||
/* Append header name to the previous value of it */
|
||||
client->current_header_name = cli_concat_persistent_zstr_with_char(client->current_header_name, at, length);
|
||||
break;
|
||||
case HEADER_VALUE:
|
||||
php_cli_server_client_save_header(client);
|
||||
ZEND_FALLTHROUGH;
|
||||
case HEADER_NONE:
|
||||
client->current_header_name = (char *)at;
|
||||
client->current_header_name_len = length;
|
||||
break;
|
||||
case HEADER_FIELD:
|
||||
if (client->current_header_name_allocated) {
|
||||
size_t new_length = client->current_header_name_len + length;
|
||||
client->current_header_name = perealloc(client->current_header_name, new_length + 1, 1);
|
||||
memcpy(client->current_header_name + client->current_header_name_len, at, length);
|
||||
client->current_header_name[new_length] = '\0';
|
||||
client->current_header_name_len = new_length;
|
||||
} else {
|
||||
size_t new_length = client->current_header_name_len + length;
|
||||
char* field = pemalloc(new_length + 1, 1);
|
||||
memcpy(field, client->current_header_name, client->current_header_name_len);
|
||||
memcpy(field + client->current_header_name_len, at, length);
|
||||
field[new_length] = '\0';
|
||||
client->current_header_name = field;
|
||||
client->current_header_name_len = new_length;
|
||||
client->current_header_name_allocated = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
client->last_header_element = HEADER_FIELD;
|
||||
|
@ -1676,19 +1682,23 @@ static int php_cli_server_client_read_request_on_header_value(php_http_parser *p
|
|||
{
|
||||
php_cli_server_client *client = parser->data;
|
||||
switch (client->last_header_element) {
|
||||
case HEADER_FIELD:
|
||||
/* Previous element was the header field, create the header value */
|
||||
client->current_header_value = zend_string_init(at, length, /* persistent */ true);
|
||||
break;
|
||||
case HEADER_VALUE: {
|
||||
/* Append header value to the previous value of it */
|
||||
client->current_header_value = cli_concat_persistent_zstr_with_char(client->current_header_value, at, length);
|
||||
break;
|
||||
case HEADER_FIELD:
|
||||
client->current_header_value = pestrndup(at, length, 1);
|
||||
client->current_header_value_len = length;
|
||||
break;
|
||||
case HEADER_VALUE:
|
||||
{
|
||||
size_t new_length = client->current_header_value_len + length;
|
||||
client->current_header_value = perealloc(client->current_header_value, new_length + 1, 1);
|
||||
memcpy(client->current_header_value + client->current_header_value_len, at, length);
|
||||
client->current_header_value[new_length] = '\0';
|
||||
client->current_header_value_len = new_length;
|
||||
}
|
||||
case HEADER_NONE:
|
||||
/* Cannot happen as a header field must have been found before */
|
||||
assert(0);
|
||||
break;
|
||||
break;
|
||||
case HEADER_NONE:
|
||||
// can't happen
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
client->last_header_element = HEADER_VALUE;
|
||||
return 0;
|
||||
|
@ -1701,11 +1711,11 @@ static int php_cli_server_client_read_request_on_headers_complete(php_http_parse
|
|||
case HEADER_NONE:
|
||||
break;
|
||||
case HEADER_FIELD:
|
||||
/* Previous element was the header field, set it's value to an empty string */
|
||||
client->current_header_value = ZSTR_EMPTY_ALLOC();
|
||||
client->current_header_value = pemalloc(1, 1);
|
||||
*client->current_header_value = '\0';
|
||||
client->current_header_value_len = 0;
|
||||
ZEND_FALLTHROUGH;
|
||||
case HEADER_VALUE:
|
||||
/* Save last header value */
|
||||
php_cli_server_client_save_header(client);
|
||||
break;
|
||||
}
|
||||
|
@ -1745,7 +1755,7 @@ static int php_cli_server_client_read_request_on_message_complete(php_http_parse
|
|||
}
|
||||
}
|
||||
}
|
||||
client->request_read = true;
|
||||
client->request_read = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1806,7 +1816,12 @@ static int php_cli_server_client_read_request(php_cli_server_client *client, cha
|
|||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (client->current_header_name) {
|
||||
char *header_name = safe_pemalloc(client->current_header_name_len, 1, 1, 1);
|
||||
memmove(header_name, client->current_header_name, client->current_header_name_len);
|
||||
client->current_header_name = header_name;
|
||||
client->current_header_name_allocated = 1;
|
||||
}
|
||||
return client->request_read ? 1: 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
@ -1851,7 +1866,7 @@ static size_t php_cli_server_client_send_through(php_cli_server_client *client,
|
|||
|
||||
static void php_cli_server_client_populate_request_info(const php_cli_server_client *client, sapi_request_info *request_info) /* {{{ */
|
||||
{
|
||||
zval *val;
|
||||
char *val;
|
||||
|
||||
request_info->request_method = php_http_method_str(client->request.request_method);
|
||||
request_info->proto_num = client->request.protocol_version;
|
||||
|
@ -1860,8 +1875,8 @@ static void php_cli_server_client_populate_request_info(const php_cli_server_cli
|
|||
request_info->query_string = client->request.query_string;
|
||||
request_info->content_length = client->request.content_len;
|
||||
request_info->auth_user = request_info->auth_password = request_info->auth_digest = NULL;
|
||||
if (NULL != (val = zend_hash_str_find(&client->request.headers, "content-type", sizeof("content-type")-1))) {
|
||||
request_info->content_type = Z_STRVAL_P(val);
|
||||
if (NULL != (val = zend_hash_str_find_ptr(&client->request.headers, "content-type", sizeof("content-type")-1))) {
|
||||
request_info->content_type = val;
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
|
@ -1876,26 +1891,29 @@ static void php_cli_server_client_ctor(php_cli_server_client *client, php_cli_se
|
|||
client->sock = client_sock;
|
||||
client->addr = addr;
|
||||
client->addr_len = addr_len;
|
||||
{
|
||||
zend_string *addr_str = 0;
|
||||
|
||||
// TODO To prevent the reallocation need to retrieve a persistent string
|
||||
// Create a new php_network_populate_name_from_sockaddr_ex() API with a persistent flag?
|
||||
zend_string *tmp_addr = NULL;
|
||||
php_network_populate_name_from_sockaddr(addr, addr_len, &tmp_addr, NULL, 0);
|
||||
client->addr_str = zend_string_dup(tmp_addr, /* persistent */ true);
|
||||
zend_string_release_ex(tmp_addr, /* persistent */ false);
|
||||
|
||||
php_network_populate_name_from_sockaddr(addr, addr_len, &addr_str, NULL, 0);
|
||||
client->addr_str = pestrndup(ZSTR_VAL(addr_str), ZSTR_LEN(addr_str), 1);
|
||||
client->addr_str_len = ZSTR_LEN(addr_str);
|
||||
zend_string_release_ex(addr_str, 0);
|
||||
}
|
||||
php_http_parser_init(&client->parser, PHP_HTTP_REQUEST);
|
||||
client->request_read = false;
|
||||
client->request_read = 0;
|
||||
|
||||
client->last_header_element = HEADER_NONE;
|
||||
client->current_header_name = NULL;
|
||||
client->current_header_name_len = 0;
|
||||
client->current_header_name_allocated = 0;
|
||||
client->current_header_value = NULL;
|
||||
client->current_header_value_len = 0;
|
||||
|
||||
client->post_read_offset = 0;
|
||||
|
||||
php_cli_server_request_ctor(&client->request);
|
||||
|
||||
client->content_sender_initialized = false;
|
||||
client->content_sender_initialized = 0;
|
||||
client->file_fd = -1;
|
||||
} /* }}} */
|
||||
|
||||
|
@ -1907,19 +1925,15 @@ static void php_cli_server_client_dtor(php_cli_server_client *client) /* {{{ */
|
|||
client->file_fd = -1;
|
||||
}
|
||||
pefree(client->addr, 1);
|
||||
zend_string_release_ex(client->addr_str, /* persistent */ true);
|
||||
|
||||
pefree(client->addr_str, 1);
|
||||
if (client->content_sender_initialized) {
|
||||
/* Headers must be set if we reached the content initialisation */
|
||||
assert(client->current_header_name == NULL);
|
||||
assert(client->current_header_value == NULL);
|
||||
php_cli_server_content_sender_dtor(&client->content_sender);
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
static void php_cli_server_close_connection(php_cli_server *server, php_cli_server_client *client) /* {{{ */
|
||||
{
|
||||
php_cli_server_logf(PHP_CLI_SERVER_LOG_MESSAGE, "%s Closing", ZSTR_VAL(client->addr_str));
|
||||
php_cli_server_logf(PHP_CLI_SERVER_LOG_MESSAGE, "%s Closing", client->addr_str);
|
||||
|
||||
zend_hash_index_del(&server->clients, client->sock);
|
||||
} /* }}} */
|
||||
|
@ -1933,7 +1947,7 @@ static zend_result php_cli_server_send_error_page(php_cli_server *server, php_cl
|
|||
assert(status_string && content_template);
|
||||
|
||||
php_cli_server_content_sender_ctor(&client->content_sender);
|
||||
client->content_sender_initialized = true;
|
||||
client->content_sender_initialized = 1;
|
||||
|
||||
escaped_request_uri = php_escape_html_entities_ex((const unsigned char *) client->request.request_uri, client->request.request_uri_len, 0, ENT_QUOTES, NULL, /* double_encode */ 0, /* quiet */ 0);
|
||||
|
||||
|
@ -2069,7 +2083,7 @@ static zend_result php_cli_server_begin_send_static(php_cli_server *server, php_
|
|||
}
|
||||
|
||||
php_cli_server_content_sender_ctor(&client->content_sender);
|
||||
client->content_sender_initialized = true;
|
||||
client->content_sender_initialized = 1;
|
||||
client->file_fd = fd;
|
||||
|
||||
{
|
||||
|
@ -2111,10 +2125,10 @@ static zend_result php_cli_server_begin_send_static(php_cli_server *server, php_
|
|||
/* }}} */
|
||||
|
||||
static zend_result php_cli_server_request_startup(php_cli_server *server, php_cli_server_client *client) { /* {{{ */
|
||||
zval *auth;
|
||||
char *auth;
|
||||
php_cli_server_client_populate_request_info(client, &SG(request_info));
|
||||
if (NULL != (auth = zend_hash_str_find(&client->request.headers, "authorization", sizeof("authorization")-1))) {
|
||||
php_handle_auth_data(Z_STRVAL_P(auth));
|
||||
if (NULL != (auth = zend_hash_str_find_ptr(&client->request.headers, "authorization", sizeof("authorization")-1))) {
|
||||
php_handle_auth_data(auth);
|
||||
}
|
||||
SG(sapi_headers).http_response_code = 200;
|
||||
if (FAILURE == php_request_startup()) {
|
||||
|
@ -2501,9 +2515,9 @@ static zend_result php_cli_server_recv_event_read_request(php_cli_server *server
|
|||
if (errstr) {
|
||||
if (strcmp(errstr, php_cli_server_request_error_unexpected_eof) == 0 && client->parser.state == s_start_req) {
|
||||
php_cli_server_logf(PHP_CLI_SERVER_LOG_MESSAGE,
|
||||
"%s Closed without sending a request; it was probably just an unused speculative preconnection", ZSTR_VAL(client->addr_str));
|
||||
"%s Closed without sending a request; it was probably just an unused speculative preconnection", client->addr_str);
|
||||
} else {
|
||||
php_cli_server_logf(PHP_CLI_SERVER_LOG_ERROR, "%s Invalid request (%s)", ZSTR_VAL(client->addr_str), errstr);
|
||||
php_cli_server_logf(PHP_CLI_SERVER_LOG_ERROR, "%s Invalid request (%s)", client->addr_str, errstr);
|
||||
}
|
||||
efree(errstr);
|
||||
}
|
||||
|
@ -2591,7 +2605,7 @@ static zend_result php_cli_server_do_event_for_each_fd_callback(void *_params, p
|
|||
|
||||
php_cli_server_client_ctor(client, server, client_sock, sa, socklen);
|
||||
|
||||
php_cli_server_logf(PHP_CLI_SERVER_LOG_MESSAGE, "%s Accepted", ZSTR_VAL(client->addr_str));
|
||||
php_cli_server_logf(PHP_CLI_SERVER_LOG_MESSAGE, "%s Accepted", client->addr_str);
|
||||
|
||||
zend_hash_index_update_ptr(&server->clients, client_sock, client);
|
||||
|
||||
|
@ -2710,7 +2724,7 @@ int do_cli_server(int argc, char **argv) /* {{{ */
|
|||
}
|
||||
|
||||
if (document_root) {
|
||||
zend_stat_t sb = {0};
|
||||
zend_stat_t sb;
|
||||
|
||||
if (php_sys_stat(document_root, &sb)) {
|
||||
fprintf(stderr, "Directory %s does not exist.\n", document_root);
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
--TEST--
|
||||
Close request before server sends a response
|
||||
--SKIPIF--
|
||||
<?php
|
||||
include "skipif.inc";
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
include "php_cli_server.inc";
|
||||
php_cli_server_start();
|
||||
|
||||
$fd = stream_socket_client("tcp://" . PHP_CLI_SERVER_ADDRESS);
|
||||
fwrite($fd, "GET /index.php HTTP/1.0\r\nHost: hello");
|
||||
fclose($fd);
|
||||
|
||||
?>
|
||||
===DONE===
|
||||
--EXPECT--
|
||||
===DONE===
|
|
@ -1,42 +0,0 @@
|
|||
--TEST--
|
||||
Server processing multiple request at the same time
|
||||
--SKIPIF--
|
||||
<?php
|
||||
include "skipif.inc";
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
include "php_cli_server.inc";
|
||||
php_cli_server_start();
|
||||
|
||||
$fd = stream_socket_client("tcp://" . PHP_CLI_SERVER_ADDRESS);
|
||||
fwrite($fd, "GET /index.php HTTP/1.0\r\nHost: hello");
|
||||
|
||||
$fd2 = stream_socket_client("tcp://" . PHP_CLI_SERVER_ADDRESS);
|
||||
fwrite($fd2, "GET /index.php HTTP/1.0\r\nConnection: close\r\n\r\n");
|
||||
|
||||
stream_copy_to_stream($fd2, STDOUT);
|
||||
|
||||
fwrite($fd, "\r\n\r\n");
|
||||
stream_copy_to_stream($fd, STDOUT);
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
?>
|
||||
===DONE===
|
||||
--EXPECTF--
|
||||
HTTP/1.0 200 OK
|
||||
Date: %s
|
||||
Connection: close
|
||||
X-Powered-By: %s
|
||||
Content-type: text/html; charset=UTF-8
|
||||
|
||||
Hello worldHTTP/1.0 200 OK
|
||||
Host: hello
|
||||
Date: %s
|
||||
Connection: close
|
||||
X-Powered-By: %s
|
||||
Content-type: text/html; charset=UTF-8
|
||||
|
||||
Hello world
|
||||
===DONE===
|
|
@ -28,40 +28,37 @@ function php_cli_server_start(
|
|||
$cmd[] = $router;
|
||||
}
|
||||
|
||||
$output_file = tempnam(sys_get_temp_dir(), 'cli_server_output');
|
||||
$output_file_fd = fopen($output_file, 'ab');
|
||||
if ($output_file_fd === false) {
|
||||
die(sprintf("Failed opening output file %s\n", $output_file));
|
||||
}
|
||||
|
||||
$descriptorspec = array(
|
||||
0 => STDIN,
|
||||
1 => $output_file_fd,
|
||||
2 => $output_file_fd,
|
||||
1 => STDOUT,
|
||||
2 => ['pipe', 'w'],
|
||||
);
|
||||
$handle = proc_open($cmd, $descriptorspec, $pipes, $doc_root, null, array("suppress_errors" => true));
|
||||
|
||||
// First, wait for the dev server to declare itself ready.
|
||||
$bound = null;
|
||||
stream_set_blocking($pipes[2], false);
|
||||
for ($i = 0; $i < 60; $i++) {
|
||||
usleep(50000); // 50ms per try
|
||||
$status = proc_get_status($handle);
|
||||
if (empty($status['running'])) {
|
||||
echo "Server failed to start\n";
|
||||
printf("Server output:\n%s\n", file_get_contents($output_file));
|
||||
echo "Server is not running\n";
|
||||
proc_terminate($handle);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$output = file_get_contents($output_file);
|
||||
if (preg_match('@PHP \S* Development Server \(https?://(.*?:\d+)\) started@', $output, $matches)) {
|
||||
$bound = $matches[1];
|
||||
break;
|
||||
while (($line = fgets($pipes[2])) !== false) {
|
||||
if (preg_match('@PHP \S* Development Server \(https?://(.*?:\d+)\) started@', $line, $matches)) {
|
||||
$bound = $matches[1];
|
||||
// Now that we've identified the listen address, close STDERR.
|
||||
// Otherwise the pipe may clog up with unread log messages.
|
||||
fclose($pipes[2]);
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($bound === null) {
|
||||
echo "Server did not output startup message";
|
||||
printf("Server output:\n%s\n", file_get_contents($output_file));
|
||||
proc_terminate($handle);
|
||||
exit(1);
|
||||
}
|
||||
|
@ -76,7 +73,7 @@ function php_cli_server_start(
|
|||
$fp = @fsockopen("tcp://$bound");
|
||||
// Failure, the server is no longer running
|
||||
if (!($status && $status['running'])) {
|
||||
$error = sprintf("Server stopped\nServer output:\n%s\n", file_get_contents($output_file));
|
||||
$error = "Server is not running\n";
|
||||
break;
|
||||
}
|
||||
// Success, Connected to servers
|
||||
|
@ -93,14 +90,8 @@ function php_cli_server_start(
|
|||
}
|
||||
|
||||
register_shutdown_function(
|
||||
function($handle) use($router, $doc_root, $output_file) {
|
||||
function($handle) use($router, $doc_root) {
|
||||
proc_terminate($handle);
|
||||
$status = proc_get_status($handle);
|
||||
if ($status['exitcode'] !== -1 && $status['exitcode'] !== 0
|
||||
&& !($status['exitcode'] === 255 && PHP_OS_FAMILY == 'Windows')) {
|
||||
printf("Server exited with non-zero status: %d\n", $status['exitcode']);
|
||||
printf("Server output:\n%s\n", file_get_contents($output_file));
|
||||
}
|
||||
@unlink(__DIR__ . "/{$router}");
|
||||
@rmdir($doc_root);
|
||||
},
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
--TEST--
|
||||
Check PHP file body is executed
|
||||
--SKIPIF--
|
||||
<?php
|
||||
include "skipif.inc";
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
include "php_cli_server.inc";
|
||||
php_cli_server_start(<<<'PHP'
|
||||
header('Bar-Foo: Foo');
|
||||
echo "Hello world\n";
|
||||
var_dump(true);
|
||||
PHP
|
||||
);
|
||||
|
||||
$host = PHP_CLI_SERVER_HOSTNAME;
|
||||
$fp = php_cli_server_connect();
|
||||
|
||||
if(fwrite($fp, <<<HEADER
|
||||
GET / HTTP/1.1
|
||||
Host: {$host}
|
||||
Foo-Bar: Bar
|
||||
|
||||
|
||||
HEADER
|
||||
)) {
|
||||
while (!feof($fp)) {
|
||||
echo fgets($fp);
|
||||
}
|
||||
}
|
||||
|
||||
fclose($fp);
|
||||
?>
|
||||
--EXPECTF--
|
||||
HTTP/1.1 200 OK
|
||||
Host: %s
|
||||
Date: %s
|
||||
Connection: close
|
||||
X-Powered-By: %s
|
||||
Bar-Foo: Foo
|
||||
Content-type: text/html; charset=UTF-8
|
||||
|
||||
Hello world
|
||||
bool(true)
|
Loading…
Add table
Add a link
Reference in a new issue