mirror of
https://github.com/php/php-src.git
synced 2024-09-22 18:37:25 +00:00
*** empty log message ***
This commit is contained in:
parent
8eb8850c90
commit
532a79aa52
@ -89,183 +89,6 @@
|
||||
#define HTTP_HEADER_CONTENT_LENGTH 16
|
||||
#define HTTP_HEADER_TYPE 32
|
||||
|
||||
/* 8 hexits plus \r\n\0 */
|
||||
#define HTTP_CHUNK_SIZE_MAXLEN 11
|
||||
#define HTTP_CHUNKED_ENCODING_BUFFER_LEN (HTTP_CHUNK_SIZE_MAXLEN + 1)
|
||||
|
||||
typedef struct _php_http_chunked_encoding_data {
|
||||
int is_persistent;
|
||||
size_t chunk_remaining;
|
||||
char chunksize_buffer[HTTP_CHUNKED_ENCODING_BUFFER_LEN];
|
||||
char *chunksize_buffer_pos;
|
||||
} php_http_chunked_encoding_data;
|
||||
|
||||
static php_stream_filter_status_t php_http_chunked_encoding_filter(
|
||||
php_stream *stream,
|
||||
php_stream_filter *thisfilter,
|
||||
php_stream_bucket_brigade *buckets_in,
|
||||
php_stream_bucket_brigade *buckets_out,
|
||||
size_t *bytes_consumed,
|
||||
int flags
|
||||
TSRMLS_DC)
|
||||
{
|
||||
php_stream_bucket *bucket;
|
||||
php_http_chunked_encoding_data *data = (php_http_chunked_encoding_data*)thisfilter->abstract;
|
||||
size_t consumed = 0;
|
||||
char *buf;
|
||||
size_t buflen;
|
||||
|
||||
while (buckets_in->head) {
|
||||
char *e = NULL;
|
||||
size_t chunk_remaining;
|
||||
|
||||
bucket = buckets_in->head;
|
||||
php_stream_bucket_unlink(bucket TSRMLS_CC);
|
||||
|
||||
buf = bucket->buf;
|
||||
buflen = bucket->buflen;
|
||||
|
||||
continue_bucket:
|
||||
|
||||
if (data->chunk_remaining > 0) {
|
||||
if ((data->chunk_remaining > buflen) && (bucket->buf == buf)) {
|
||||
/* This bucket is smaller than our remaining chunksize,
|
||||
Pass it on unmolested */
|
||||
consumed += buflen;
|
||||
data->chunk_remaining -= buflen;
|
||||
php_stream_bucket_append(buckets_out, bucket TSRMLS_CC);
|
||||
|
||||
/* Next bucket please */
|
||||
continue;
|
||||
} else if (data->chunk_remaining > buflen) {
|
||||
php_stream_bucket *newbucket;
|
||||
char *newbuf;
|
||||
|
||||
/* Previously split bucket can be used en toto */
|
||||
consumed += buflen;
|
||||
data->chunk_remaining -= buflen;
|
||||
|
||||
newbuf = estrndup(buf, buflen);
|
||||
newbucket = php_stream_bucket_new(stream, newbuf, buflen, 1, stream->is_persistent TSRMLS_CC);
|
||||
php_stream_bucket_append(buckets_out, newbucket TSRMLS_CC);
|
||||
php_stream_bucket_delref(bucket TSRMLS_CC);
|
||||
/* Next bucket please */
|
||||
continue;
|
||||
} else {
|
||||
php_stream_bucket *newbucket;
|
||||
char *newbuf;
|
||||
|
||||
/* Consume enough of this bucket to satisfy the current chunk */
|
||||
newbuf = pemalloc(data->chunk_remaining, stream->is_persistent);
|
||||
memcpy(newbuf, buf, data->chunk_remaining);
|
||||
|
||||
newbucket = php_stream_bucket_new(stream, newbuf, data->chunk_remaining, 1, stream->is_persistent TSRMLS_CC);
|
||||
php_stream_bucket_append(buckets_out, newbucket TSRMLS_CC);
|
||||
buf += data->chunk_remaining;
|
||||
buflen -= data->chunk_remaining;
|
||||
consumed += data->chunk_remaining;
|
||||
data->chunk_remaining = 0;
|
||||
/* Fall Through */
|
||||
}
|
||||
}
|
||||
|
||||
while (buflen > 0 && (*buf == '\r' || *buf == '\n')) {
|
||||
buf++;
|
||||
buflen--;
|
||||
}
|
||||
|
||||
if (buflen <= 0) {
|
||||
php_stream_bucket_delref(bucket TSRMLS_CC);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((data->chunksize_buffer_pos - data->chunksize_buffer) < HTTP_CHUNK_SIZE_MAXLEN) {
|
||||
/* Copy buf into chunksize_buffer */
|
||||
if ((HTTP_CHUNKED_ENCODING_BUFFER_LEN - (data->chunksize_buffer_pos - data->chunksize_buffer)) > buflen) {
|
||||
/* Possible split chunklen */
|
||||
memcpy(data->chunksize_buffer_pos, buf, buflen);
|
||||
memset(data->chunksize_buffer_pos + buflen, 0, HTTP_CHUNK_SIZE_MAXLEN - buflen - (data->chunksize_buffer_pos - data->chunksize_buffer));
|
||||
chunk_remaining = strtoul(data->chunksize_buffer, &e, 16);
|
||||
/* Skip whitespace */
|
||||
while ((*e == ' ') && (e < (data->chunksize_buffer + HTTP_CHUNK_SIZE_MAXLEN))) e++;
|
||||
if (*e != '\r') {
|
||||
if (!((*e >= '0' && *e <= '9') ||
|
||||
(*e >= 'a' && *e <= 'f') ||
|
||||
(*e >= 'A' && *e <= 'F'))) {
|
||||
/* Unexpected character */
|
||||
return PSFS_ERR_FATAL;
|
||||
}
|
||||
|
||||
/* Not enough data to know the chunksize yet */
|
||||
php_stream_bucket_delref(bucket TSRMLS_CC);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
memcpy(data->chunksize_buffer_pos, buf, HTTP_CHUNK_SIZE_MAXLEN - (data->chunksize_buffer_pos - data->chunksize_buffer));
|
||||
chunk_remaining = strtoul(data->chunksize_buffer, &e, 16);
|
||||
/* Skip whitespace */
|
||||
while ((*e == ' ') && (e < (data->chunksize_buffer + HTTP_CHUNK_SIZE_MAXLEN))) e++;
|
||||
if (*e != '\r') {
|
||||
/* Invalid chunksize */
|
||||
return PSFS_ERR_FATAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data->chunk_remaining = chunk_remaining;
|
||||
/* Skip past the chunksize itself */
|
||||
buf += (e - data->chunksize_buffer) + sizeof("\r\n") - 1;
|
||||
buflen -= (e - data->chunksize_buffer) + sizeof("\r\n") - 1;
|
||||
consumed += (e - data->chunksize_buffer) + sizeof("\r\n") - 1;
|
||||
memset(data->chunksize_buffer, 0, sizeof(data->chunksize_buffer));
|
||||
data->chunksize_buffer_pos = data->chunksize_buffer;
|
||||
|
||||
if (buflen > 0) {
|
||||
goto continue_bucket;
|
||||
}
|
||||
php_stream_bucket_delref(bucket TSRMLS_CC);
|
||||
}
|
||||
|
||||
if (bytes_consumed) {
|
||||
*bytes_consumed = consumed;
|
||||
}
|
||||
|
||||
if (consumed > 0) {
|
||||
return PSFS_PASS_ON;
|
||||
}
|
||||
|
||||
return PSFS_FEED_ME;
|
||||
}
|
||||
|
||||
static void php_http_chunked_encoding_dtor(php_stream_filter *thisfilter TSRMLS_DC)
|
||||
{
|
||||
if (thisfilter && thisfilter->abstract) {
|
||||
php_http_chunked_encoding_data *data = (php_http_chunked_encoding_data*)thisfilter->abstract;
|
||||
|
||||
pefree(data, data->is_persistent);
|
||||
thisfilter->abstract = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static php_stream_filter_ops php_http_chunked_encoding_filter_ops = {
|
||||
php_http_chunked_encoding_filter,
|
||||
php_http_chunked_encoding_dtor,
|
||||
"http.chunked.decode"
|
||||
};
|
||||
|
||||
static php_stream_filter *php_http_chunked_encoding_filter_create(const char *filtername, zval *filterparams, int persistent TSRMLS_DC)
|
||||
{
|
||||
php_http_chunked_encoding_data *data;
|
||||
|
||||
data = pemalloc(sizeof(php_http_chunked_encoding_data), persistent);
|
||||
data->chunk_remaining = 0;
|
||||
data->is_persistent = persistent;
|
||||
memset(data->chunksize_buffer, 0, sizeof(data->chunksize_buffer));
|
||||
data->chunksize_buffer_pos = data->chunksize_buffer;
|
||||
|
||||
return php_stream_filter_alloc(&php_http_chunked_encoding_filter_ops, data, persistent);
|
||||
}
|
||||
|
||||
php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context, int redirect_max, int header_init STREAMS_DC TSRMLS_DC)
|
||||
{
|
||||
php_stream *stream = NULL;
|
||||
@ -288,7 +111,6 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path,
|
||||
int transport_len, have_header = 0, request_fulluri = 0;
|
||||
char *protocol_version = NULL;
|
||||
int protocol_version_len = 3; /* Default: "1.0" */
|
||||
int autofilter_chunked_encoding = 0;
|
||||
|
||||
if (redirect_max < 1) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Circular redirect, aborting.");
|
||||
@ -669,9 +491,6 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path,
|
||||
} else if (!strncasecmp(http_header_line, "Content-Length: ", 16)) {
|
||||
file_size = atoi(http_header_line + 16);
|
||||
php_stream_notify_file_size(context, file_size, http_header_line, 0);
|
||||
} else if ((strncasecmp(http_header_line, "Transfer-Encoding: ", sizeof("Transfer-Encoding: ") - 1) == 0) &&
|
||||
(strstr(http_header_line + sizeof("Transfer-Encoding: ") - 1, "chunked") != NULL)) {
|
||||
autofilter_chunked_encoding = 1;
|
||||
}
|
||||
|
||||
if (http_header_line[0] == '\0') {
|
||||
@ -792,17 +611,6 @@ out:
|
||||
* the stream */
|
||||
stream->position = 0;
|
||||
|
||||
if (autofilter_chunked_encoding) {
|
||||
php_stream_filter *filter;
|
||||
|
||||
filter = php_http_chunked_encoding_filter_create("http.chunked.decode", NULL, stream->is_persistent TSRMLS_CC);
|
||||
if (!filter) {
|
||||
/* Never actually happens */
|
||||
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Unable to apply chunked content decoding");
|
||||
} else {
|
||||
php_stream_filter_append(&stream->readfilters, filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return stream;
|
||||
|
Loading…
Reference in New Issue
Block a user