Skip to content

Commit 4985aea

Browse files
committed
Convert php_cli_server_client->current_header_value to zend_string
1 parent 6f7d773 commit 4985aea

File tree

2 files changed

+85
-37
lines changed

2 files changed

+85
-37
lines changed

sapi/cli/php_cli_server.c

Lines changed: 40 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,7 @@ typedef struct php_cli_server_client {
168168
php_http_parser parser;
169169
unsigned int request_read:1;
170170
zend_string *current_header_name;
171-
char *current_header_value;
172-
size_t current_header_value_len;
171+
zend_string *current_header_value;
173172
enum { HEADER_NONE=0, HEADER_FIELD, HEADER_VALUE } last_header_element;
174173
size_t post_read_offset;
175174
php_cli_server_request request;
@@ -347,19 +346,19 @@ static void append_http_status_line(smart_str *buffer, int protocol_version, int
347346

348347
static void append_essential_headers(smart_str* buffer, php_cli_server_client *client, bool persistent) /* {{{ */
349348
{
350-
char *val;
349+
zend_string *val;
351350
struct timeval tv = {0};
352351

353352
if (NULL != (val = zend_hash_str_find_ptr(&client->request.headers, "host", sizeof("host")-1))) {
354353
smart_str_appends_ex(buffer, "Host: ", persistent);
355-
smart_str_appends_ex(buffer, val, persistent);
354+
smart_str_append_ex(buffer, val, persistent);
356355
smart_str_appends_ex(buffer, "\r\n", persistent);
357356
}
358357

359358
if (!gettimeofday(&tv, NULL)) {
360359
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);
361360
smart_str_appends_ex(buffer, "Date: ", persistent);
362-
smart_str_appends_ex(buffer, dt->val, persistent);
361+
smart_str_append_ex(buffer, dt, persistent);
363362
smart_str_appends_ex(buffer, " GMT\r\n", persistent);
364363
zend_string_release_ex(dt, 0);
365364
}
@@ -383,7 +382,7 @@ PHP_FUNCTION(apache_request_headers) /* {{{ */
383382
php_cli_server_client *client;
384383
HashTable *headers;
385384
zend_string *key;
386-
char *value;
385+
zend_string *value;
387386
zval tmp;
388387

389388
if (zend_parse_parameters_none() == FAILURE) {
@@ -396,7 +395,8 @@ PHP_FUNCTION(apache_request_headers) /* {{{ */
396395
array_init_size(return_value, zend_hash_num_elements(headers));
397396

398397
ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(headers, key, value) {
399-
ZVAL_STRING(&tmp, value);
398+
// TODO There must be a better way
399+
ZVAL_STRING(&tmp, ZSTR_VAL(value));
400400
zend_symtable_update(Z_ARRVAL_P(return_value), key, &tmp);
401401
} ZEND_HASH_FOREACH_END();
402402
}
@@ -571,11 +571,11 @@ static int sapi_cli_server_send_headers(sapi_headers_struct *sapi_headers) /* {{
571571
static char *sapi_cli_server_read_cookies(void) /* {{{ */
572572
{
573573
php_cli_server_client *client = SG(server_context);
574-
char *val;
574+
zend_string *val;
575575
if (NULL == (val = zend_hash_str_find_ptr(&client->request.headers, "cookie", sizeof("cookie")-1))) {
576576
return NULL;
577577
}
578-
return val;
578+
return ZSTR_VAL(val);
579579
} /* }}} */
580580

581581
static size_t sapi_cli_server_read_post(char *buf, size_t count_bytes) /* {{{ */
@@ -605,7 +605,7 @@ static void sapi_cli_server_register_variable(zval *track_vars_array, const char
605605
}
606606
} /* }}} */
607607

608-
static int sapi_cli_server_register_entry_cb(char **entry, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */ {
608+
static int sapi_cli_server_register_entry_cb(zend_string **entry, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */ {
609609
zval *track_vars_array = va_arg(args, zval *);
610610
if (hash_key->key) {
611611
char *real_key, *key;
@@ -620,9 +620,10 @@ static int sapi_cli_server_register_entry_cb(char **entry, int num_args, va_list
620620
}
621621
spprintf(&real_key, 0, "%s_%s", "HTTP", key);
622622
if (strcmp(key, "CONTENT_TYPE") == 0 || strcmp(key, "CONTENT_LENGTH") == 0) {
623-
sapi_cli_server_register_variable(track_vars_array, key, *entry);
623+
// TODO make a version specialized for zend_string?
624+
sapi_cli_server_register_variable(track_vars_array, key, ZSTR_VAL(*entry));
624625
}
625-
sapi_cli_server_register_variable(track_vars_array, real_key, *entry);
626+
sapi_cli_server_register_variable(track_vars_array, real_key, ZSTR_VAL(*entry));
626627
efree(key);
627628
efree(real_key);
628629
}
@@ -1629,20 +1630,22 @@ static void php_cli_server_client_save_header(php_cli_server_client *client)
16291630

16301631
client->current_header_name = NULL;
16311632
client->current_header_value = NULL;
1632-
client->current_header_value_len = 0;
16331633
}
16341634

16351635
static int php_cli_server_client_read_request_on_header_field(php_http_parser *parser, const char *at, size_t length)
16361636
{
16371637
php_cli_server_client *client = parser->data;
16381638
switch (client->last_header_element) {
16391639
case HEADER_VALUE:
1640+
/* Save previous header before creating new one */
16401641
php_cli_server_client_save_header(client);
16411642
ZEND_FALLTHROUGH;
16421643
case HEADER_NONE:
1644+
/* Create new header field */
16431645
client->current_header_name = zend_string_init(at, length, /* persistent */ false);
16441646
break;
16451647
case HEADER_FIELD: {
1648+
/* Append header field */
16461649
zend_string *field = zend_string_concat2(
16471650
ZSTR_VAL(client->current_header_name), ZSTR_LEN(client->current_header_name), at, length);
16481651
// Free previous
@@ -1659,23 +1662,24 @@ static int php_cli_server_client_read_request_on_header_value(php_http_parser *p
16591662
{
16601663
php_cli_server_client *client = parser->data;
16611664
switch (client->last_header_element) {
1662-
case HEADER_FIELD:
1663-
client->current_header_value = pestrndup(at, length, 1);
1664-
client->current_header_value_len = length;
1665-
break;
1666-
case HEADER_VALUE:
1667-
{
1668-
size_t new_length = client->current_header_value_len + length;
1669-
client->current_header_value = perealloc(client->current_header_value, new_length + 1, 1);
1670-
memcpy(client->current_header_value + client->current_header_value_len, at, length);
1671-
client->current_header_value[new_length] = '\0';
1672-
client->current_header_value_len = new_length;
1665+
case HEADER_FIELD:
1666+
/* Previous element was the header field, create the header value */
1667+
client->current_header_value = zend_string_init(at, length, /* persistent */ true);
1668+
break;
1669+
case HEADER_VALUE: {
1670+
/* Previous element was part of header value, append content to it */
1671+
size_t old_length = ZSTR_LEN(client->current_header_value);
1672+
// TODO Release old value?
1673+
client->current_header_value = zend_string_extend(client->current_header_value, old_length + length, /* persistent */ true);
1674+
memcpy(ZSTR_VAL(client->current_header_value) + old_length, at, length);
1675+
// Null terminate
1676+
ZSTR_VAL(client->current_header_value)[ZSTR_LEN(client->current_header_value)] = '\0';
1677+
break;
16731678
}
1674-
break;
1675-
case HEADER_NONE:
1676-
// can't happen
1677-
assert(0);
1678-
break;
1679+
case HEADER_NONE:
1680+
/* Cannot happen as a header field must have been found before */
1681+
assert(0);
1682+
break;
16791683
}
16801684
client->last_header_element = HEADER_VALUE;
16811685
return 0;
@@ -1688,11 +1692,11 @@ static int php_cli_server_client_read_request_on_headers_complete(php_http_parse
16881692
case HEADER_NONE:
16891693
break;
16901694
case HEADER_FIELD:
1691-
client->current_header_value = pemalloc(1, 1);
1692-
*client->current_header_value = '\0';
1693-
client->current_header_value_len = 0;
1695+
/* Previous element was the header field, set it's value to an empty string */
1696+
client->current_header_value = ZSTR_EMPTY_ALLOC();
16941697
ZEND_FALLTHROUGH;
16951698
case HEADER_VALUE:
1699+
/* Save last header value */
16961700
php_cli_server_client_save_header(client);
16971701
break;
16981702
}
@@ -1838,7 +1842,7 @@ static size_t php_cli_server_client_send_through(php_cli_server_client *client,
18381842

18391843
static void php_cli_server_client_populate_request_info(const php_cli_server_client *client, sapi_request_info *request_info) /* {{{ */
18401844
{
1841-
char *val;
1845+
zend_string *val;
18421846

18431847
request_info->request_method = php_http_method_str(client->request.request_method);
18441848
request_info->proto_num = client->request.protocol_version;
@@ -1848,7 +1852,7 @@ static void php_cli_server_client_populate_request_info(const php_cli_server_cli
18481852
request_info->content_length = client->request.content_len;
18491853
request_info->auth_user = request_info->auth_password = request_info->auth_digest = NULL;
18501854
if (NULL != (val = zend_hash_str_find_ptr(&client->request.headers, "content-type", sizeof("content-type")-1))) {
1851-
request_info->content_type = val;
1855+
request_info->content_type = ZSTR_VAL(val);
18521856
}
18531857
} /* }}} */
18541858

@@ -1876,7 +1880,6 @@ static void php_cli_server_client_ctor(php_cli_server_client *client, php_cli_se
18761880
client->last_header_element = HEADER_NONE;
18771881
client->current_header_name = NULL;
18781882
client->current_header_value = NULL;
1879-
client->current_header_value_len = 0;
18801883

18811884
client->post_read_offset = 0;
18821885

@@ -2095,10 +2098,10 @@ static zend_result php_cli_server_begin_send_static(php_cli_server *server, php_
20952098
/* }}} */
20962099

20972100
static zend_result php_cli_server_request_startup(php_cli_server *server, php_cli_server_client *client) { /* {{{ */
2098-
char *auth;
2101+
zend_string *auth;
20992102
php_cli_server_client_populate_request_info(client, &SG(request_info));
21002103
if (NULL != (auth = zend_hash_str_find_ptr(&client->request.headers, "authorization", sizeof("authorization")-1))) {
2101-
php_handle_auth_data(auth);
2104+
php_handle_auth_data(ZSTR_VAL(auth));
21022105
}
21032106
SG(sapi_headers).http_response_code = 200;
21042107
if (FAILURE == php_request_startup()) {
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
--TEST--
2+
Check PHP file body is executed
3+
--SKIPIF--
4+
<?php
5+
include "skipif.inc";
6+
?>
7+
--FILE--
8+
<?php
9+
include "php_cli_server.inc";
10+
php_cli_server_start(<<<'PHP'
11+
header('Bar-Foo: Foo');
12+
echo "Hello world\n";
13+
var_dump(true);
14+
PHP
15+
);
16+
17+
$host = PHP_CLI_SERVER_HOSTNAME;
18+
$fp = php_cli_server_connect();
19+
20+
if(fwrite($fp, <<<HEADER
21+
GET / HTTP/1.1
22+
Host: {$host}
23+
Foo-Bar: Bar
24+
25+
26+
HEADER
27+
)) {
28+
while (!feof($fp)) {
29+
echo fgets($fp);
30+
}
31+
}
32+
33+
fclose($fp);
34+
?>
35+
--EXPECTF--
36+
HTTP/1.1 200 OK
37+
Host: %s
38+
Date: %s
39+
Connection: close
40+
X-Powered-By: %s
41+
Bar-Foo: Foo
42+
Content-type: text/html; charset=UTF-8
43+
44+
Hello world
45+
bool(true)

0 commit comments

Comments
 (0)