X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-http;a=blobdiff_plain;f=http_send_api.c;h=41ba3058e556d1089853ecf3e2d670ce10696531;hp=44b29a51a39abd3c7c1be30fba938dc6abb1eabf;hb=bb6571e22d14c87114eb729145be2e7b87ebea42;hpb=9d8cf5d730afef90ea9dcabc606d732e52e15306 diff --git a/http_send_api.c b/http_send_api.c index 44b29a5..41ba305 100644 --- a/http_send_api.c +++ b/http_send_api.c @@ -27,6 +27,7 @@ #include "php_http.h" #include "php_http_std_defs.h" #include "php_http_api.h" +#include "php_http_date_api.h" #include "php_http_send_api.h" #include "php_http_headers_api.h" #include "php_http_date_api.h" @@ -124,8 +125,12 @@ static STATUS _http_send_chunk(const void *data, size_t begin, size_t end, http_ /* {{{ STATUS http_send_status_header(int, char *) */ PHP_HTTP_API STATUS _http_send_status_header(int status, const char *header TSRMLS_DC) { - sapi_header_line h = {(char *) header, strlen(header), status}; - return sapi_header_op(SAPI_HEADER_REPLACE, &h TSRMLS_CC); + STATUS ret; + sapi_header_line h = {(char *) header, header ? strlen(header) : 0, status}; + if (SUCCESS != (ret = sapi_header_op(SAPI_HEADER_REPLACE, &h TSRMLS_CC))) { + http_error_ex(E_WARNING, HTTP_E_HEADER, "Could not send header: %s (%d)", header, status); + } + return ret; } /* }}} */ @@ -154,8 +159,7 @@ PHP_HTTP_API STATUS _http_send_etag(const char *etag, size_t etag_len TSRMLS_DC) char *etag_header; if (!etag_len){ - php_error_docref(NULL TSRMLS_CC,E_ERROR, - "Attempt to send empty ETag (previous: %s)\n", HTTP_G(etag)); + http_error_ex(E_WARNING, HTTP_E_HEADER, "Attempt to send empty ETag (previous: %s)\n", HTTP_G(etag)); return FAILURE; } @@ -167,9 +171,7 @@ PHP_HTTP_API STATUS _http_send_etag(const char *etag, size_t etag_len TSRMLS_DC) etag_header = ecalloc(1, sizeof("ETag: \"\"") + etag_len); sprintf(etag_header, "ETag: \"%s\"", etag); - if (SUCCESS != (status = http_send_header(etag_header))) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't send '%s' header", etag_header); - } + status = http_send_header(etag_header); efree(etag_header); return status; } @@ -182,10 +184,7 @@ PHP_HTTP_API STATUS _http_send_cache_control(const char *cache_control, size_t c char *cc_header = ecalloc(1, sizeof("Cache-Control: ") + cc_len); sprintf(cc_header, "Cache-Control: %s", cache_control); - if (SUCCESS != (status = http_send_header(cc_header))) { - php_error_docref(NULL TSRMLS_CC, E_NOTICE, - "Could not send '%s' header", cc_header); - } + status = http_send_header(cc_header); efree(cc_header); return status; } @@ -198,9 +197,7 @@ PHP_HTTP_API STATUS _http_send_content_type(const char *content_type, size_t ct_ char *ct_header; if (!strchr(content_type, '/')) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, - "Content-Type '%s' doesn't seem to consist of a primary and a secondary part", - content_type); + http_error_ex(E_WARNING, HTTP_E_PARAM, "Content-Type '%s' doesn't seem to consist of a primary and a secondary part", content_type); return FAILURE; } @@ -212,11 +209,7 @@ PHP_HTTP_API STATUS _http_send_content_type(const char *content_type, size_t ct_ ct_header = ecalloc(1, sizeof("Content-Type: ") + ct_len); sprintf(ct_header, "Content-Type: %s", content_type); - - if (SUCCESS != (status = http_send_header(ct_header))) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, - "Couldn't send '%s' header", ct_header); - } + status = http_send_header(ct_header); efree(ct_header); return status; } @@ -236,9 +229,7 @@ PHP_HTTP_API STATUS _http_send_content_disposition(const char *filename, size_t sprintf(cd_header, "Content-Disposition: attachment; filename=\"%s\"", filename); } - if (SUCCESS != (status = http_send_header(cd_header))) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't send '%s' header", cd_header); - } + status = http_send_header(cd_header); efree(cd_header); return status; } @@ -335,12 +326,13 @@ PHP_HTTP_API STATUS _http_send(const void *data_ptr, size_t data_size, http_send /* stop on-the-fly etag generation */ if (cache_etag = HTTP_G(etag_started)) { - /* interrupt */ + /* interrupt ob_etaghandler */ HTTP_G(etag_started) = 0; - /* never ever use the output to compute the ETag if http_send() is used */ - php_end_ob_buffers(0 TSRMLS_CC); } + /* enable partial dl and resume */ + http_send_header("Accept-Ranges: bytes"); + zend_hash_init(&ranges, 0, NULL, ZVAL_PTR_DTOR, 0); range_status = http_get_request_ranges(&ranges, data_size); @@ -352,8 +344,8 @@ PHP_HTTP_API STATUS _http_send(const void *data_ptr, size_t data_size, http_send /* Range Request - only send ranges if entity hasn't changed */ if ( range_status == RANGE_OK && - http_etag_match_ex("HTTP_IF_MATCH", HTTP_G(etag), 0) && - http_modified_match_ex("HTTP_IF_UNMODIFIED_SINCE", HTTP_G(lmod), 0)) { + http_match_etag_ex("HTTP_IF_MATCH", HTTP_G(etag), 0) && + http_match_last_modified_ex("HTTP_IF_UNMODIFIED_SINCE", HTTP_G(lmod), 0)) { STATUS result = http_send_ranges(&ranges, data_ptr, data_size, data_mode); zend_hash_destroy(&ranges); return result; @@ -364,24 +356,23 @@ PHP_HTTP_API STATUS _http_send(const void *data_ptr, size_t data_size, http_send /* send 304 Not Modified if etag matches */ if (cache_etag) { char *etag = NULL; - int etag_match = 0; if (!(etag = http_etag(data_ptr, data_size, data_mode))) { return FAILURE; } - - http_send_etag(etag, 32); - etag_match = http_etag_match("HTTP_IF_NONE_MATCH", etag); - efree(etag); - - if (etag_match) { - return http_send_status(304); + if (SUCCESS != http_send_etag(etag, 32)) { + efree(etag); + return FAILURE; + } + if (http_match_etag("HTTP_IF_NONE_MATCH", etag)) { + return http_cache_exit_ex(etag, 1, 1); } + efree(etag); } /* send 304 Not Modified if last modified matches */ - if (http_modified_match("HTTP_IF_MODIFIED_SINCE", HTTP_G(lmod))) { - return http_send_status(304); + if (http_match_last_modified("HTTP_IF_MODIFIED_SINCE", HTTP_G(lmod))) { + return http_cache_exit_ex(http_date(HTTP_G(lmod)), 0, 1); } /* send full entity */