- zval *ztd;
-
-
- PHPWRITE(buf, len);
-
- /* we really only need to flush when throttling is enabled,
- because we push the data as fast as possible anyway if not */
- if ((ztd = get_container_value(ctx->container, ZEND_STRL("throttleDelay") TSRMLS_CC))) {
- double delay;
- zval *ztd_copy = php_http_ztyp(IS_DOUBLE, ztd);
-
- zval_ptr_dtor(&ztd);
- delay = Z_DVAL_P(ztd_copy);
- zval_ptr_dtor(&ztd_copy);
-
- if (delay >= PHP_HTTP_DIFFSEC) {
- if (php_output_get_level(TSRMLS_C)) {
- php_output_flush_all(TSRMLS_C);
- }
- if (!(php_output_get_status(TSRMLS_C) & PHP_OUTPUT_IMPLICITFLUSH)) {
- sapi_flush(TSRMLS_C);
- }
- php_http_sleep(delay);
- }
- }
- }
- return len;
-}
-
-PHP_HTTP_API STATUS php_http_env_send_response(zval *container TSRMLS_DC)
-{
- struct output_ctx ctx = {NULL, container};
- zval *zbody, *zheader, *zrcode, *zversion;
- HashTable ranges;
- php_http_range_status_t range_status;
- php_http_message_body_t *body;
- size_t body_size;
-
- if ( !(zbody = get_container_value(container, ZEND_STRL("body") TSRMLS_CC))
- || !(Z_TYPE_P(zbody) == IS_OBJECT)
- || !instanceof_function(Z_OBJCE_P(zbody), php_http_message_body_class_entry TSRMLS_CC)
- ) {
- if (zbody) {
- zval_ptr_dtor(&zbody);
- }
- return FAILURE;
- }
-
- if ((zrcode = get_container_value(container, ZEND_STRL("responseCode") TSRMLS_CC))) {
- zval *zrcode_copy = php_http_ztyp(IS_LONG, zrcode);
-
- zval_ptr_dtor(&zrcode);
- if (Z_LVAL_P(zrcode_copy) > 0) {
- php_http_env_set_response_code(Z_LVAL_P(zrcode_copy) TSRMLS_CC);
- }
- zval_ptr_dtor(&zrcode_copy);
- }
-
- if ((zversion = get_container_value(container, ZEND_STRL("httpVersion") TSRMLS_CC))) {
- php_http_version_t v;
- zval *zversion_copy = php_http_ztyp(IS_STRING, zversion);
-
- zval_ptr_dtor(&zversion);
- if (Z_STRLEN_P(zversion_copy) && php_http_version_parse(&v, Z_STRVAL_P(zversion_copy) TSRMLS_CC)) {
- php_http_env_set_response_protocol_version(&v TSRMLS_CC);
- php_http_version_dtor(&v);
- }
- zval_ptr_dtor(&zversion_copy);
- }
-
- if ((zheader = get_container_value(container, ZEND_STRL("headers") TSRMLS_CC))) {
- if (Z_TYPE_P(zheader) == IS_ARRAY) {
- zval **val;
- HashPosition pos;
- php_http_array_hashkey_t key = php_http_array_hashkey_init(0);
-
- FOREACH_KEYVAL(pos, zheader, key, val) {
- if (key.type == HASH_KEY_IS_STRING) {
- php_http_env_set_response_header_value(0, key.str, key.len - 1, *val, 1 TSRMLS_CC);
- }
- }
- }
- zval_ptr_dtor(&zheader);
- }
-
- body = ((php_http_message_body_object_t *) zend_object_store_get_object(zbody TSRMLS_CC))->body;
- body_size = php_http_message_body_size(body);
- php_http_env_set_response_header(0, ZEND_STRL("Accept-Ranges: bytes"), 1 TSRMLS_CC);
- zend_hash_init(&ranges, 0, NULL, ZVAL_PTR_DTOR, 0);
- range_status = php_http_env_get_request_ranges(&ranges, body_size TSRMLS_CC);
-
- switch (range_status) {
- case PHP_HTTP_RANGE_ERR:
- zend_hash_destroy(&ranges);
- if (!php_http_env_got_request_header(ZEND_STRL("If-Range") TSRMLS_CC)) {
- char *cr_header_str;
- size_t cr_header_len;
-
- cr_header_len = spprintf(&cr_header_str, 0, "Content-Range: bytes */%zu", body_size);
- php_http_env_set_response_header(416, cr_header_str, cr_header_len, 1 TSRMLS_CC);
- efree(cr_header_str);
- if (zbody) {
- zval_ptr_dtor(&zbody);
- }
- return SUCCESS;
- }
- break;
-
- case PHP_HTTP_RANGE_NO:
- /* send full entity */
- zend_hash_destroy(&ranges);
- break;
-
- case PHP_HTTP_RANGE_OK:
- /* send content-range response */
- if (PHP_HTTP_CACHE_MISS == php_http_env_is_response_cached_by_etag(container, ZEND_STRL("If-Range") TSRMLS_CC)
- || PHP_HTTP_CACHE_MISS == php_http_env_is_response_cached_by_last_modified(container, ZEND_STRL("If-Range") TSRMLS_CC)
- ) {
- /* send full entity */
- zend_hash_destroy(&ranges);
- break;
- }
- if (PHP_HTTP_CACHE_MISS == php_http_env_is_response_cached_by_etag(container, ZEND_STRL("If-Match") TSRMLS_CC)
- || PHP_HTTP_CACHE_MISS == php_http_env_is_response_cached_by_last_modified(container, ZEND_STRL("If-Unmodified-Since") TSRMLS_CC)
- || PHP_HTTP_CACHE_MISS == php_http_env_is_response_cached_by_last_modified(container, ZEND_STRL("Unless-Modified-Since") TSRMLS_CC)
- ) {
- zend_hash_destroy(&ranges);
- php_http_env_set_response_code(412 TSRMLS_CC);
- if (zbody) {
- zval_ptr_dtor(&zbody);
- }
- return SUCCESS;
- }
- if (zend_hash_num_elements(&ranges) == 1) {
- /* single range */
- zval **range, **begin, **end;
-
- if (SUCCESS != zend_hash_index_find(&ranges, 0, (void *) &range)
- || SUCCESS != zend_hash_index_find(Z_ARRVAL_PP(range), 0, (void *) &begin)
- || SUCCESS != zend_hash_index_find(Z_ARRVAL_PP(range), 1, (void *) &end)
- ) {
- /* this should never happen */
- zend_hash_destroy(&ranges);
- php_http_env_set_response_code(500 TSRMLS_CC);
- if (zbody) {
- zval_ptr_dtor(&zbody);
- }
- return FAILURE;
- } else {
- char *cr_header_str;
- size_t cr_header_len;
-
- cr_header_len = spprintf(&cr_header_str, 0, "Content-Range: bytes %ld-%ld/%zu", Z_LVAL_PP(begin), Z_LVAL_PP(end), body_size);
- php_http_env_set_response_header(206, cr_header_str, cr_header_len, 1 TSRMLS_CC);
- efree(cr_header_str);
-
- /* send chunk */
- php_http_message_body_to_callback(body, output, &ctx, Z_LVAL_PP(begin), Z_LVAL_PP(end) - Z_LVAL_PP(begin) + 1);
- output(&ctx, NULL, 0 TSRMLS_CC);
- zend_hash_destroy(&ranges);
- if (zbody) {
- zval_ptr_dtor(&zbody);
- }
- return SUCCESS;
- }
- } else {
- /* send multipart/byte-ranges message */
- HashPosition pos;
- zval **chunk, *zct;
- php_http_buffer_t preface;
- int free_ct = 0;
- char *content_type = "application/octet-stream";
- char boundary[32];
-
- if ((zct = get_container_value(container, ZEND_STRL("contentType") TSRMLS_CC))) {
- zval *zct_copy = php_http_ztyp(IS_STRING, zct);
-
- zval_ptr_dtor(&zct);
- if (Z_STRLEN_P(zct_copy)) {
- content_type = estrndup(Z_STRVAL_P(zct_copy), Z_STRLEN_P(zct_copy));
- free_ct = 1;
- }
-
- zval_ptr_dtor(&zct);
- }
-
- php_http_boundary(boundary, sizeof(boundary));
- php_http_env_set_response_header_format(206, 1 TSRMLS_CC, "Content-Type: multipart/byteranges; boundary=%s", boundary);
-
- php_http_buffer_init(&preface);
- FOREACH_HASH_VAL(pos, &ranges, chunk) {
- zval **begin, **end;
-
- if (IS_ARRAY == Z_TYPE_PP(chunk)
- && SUCCESS == zend_hash_index_find(Z_ARRVAL_PP(chunk), 0, (void *) &begin)
- && IS_LONG == Z_TYPE_PP(begin)
- && SUCCESS == zend_hash_index_find(Z_ARRVAL_PP(chunk), 1, (void *) &end)
- && IS_LONG == Z_TYPE_PP(end)
- ) {
- php_http_buffer_appendf(&preface,
- PHP_HTTP_CRLF
- "--%s" PHP_HTTP_CRLF
- "Content-Type: %s" PHP_HTTP_CRLF
- "Content-Range: bytes %ld-%ld/%zu" PHP_HTTP_CRLF,
- /* - */
- boundary,
- content_type,
- Z_LVAL_PP(begin),
- Z_LVAL_PP(end),
- body_size
- );
- php_http_buffer_fix(&preface);
- output(&ctx, PHP_HTTP_BUFFER_VAL(&preface), PHP_HTTP_BUFFER_LEN(&preface) TSRMLS_CC);
- php_http_buffer_reset(&preface);
-
- php_http_message_body_to_callback(body, output, &ctx, Z_LVAL_PP(begin), Z_LVAL_PP(end) - Z_LVAL_PP(begin) + 1);
- }
- }
- php_http_buffer_appendf(&preface, PHP_HTTP_CRLF "--%s--", boundary);
- php_http_buffer_fix(&preface);
- output(&ctx, PHP_HTTP_BUFFER_VAL(&preface), PHP_HTTP_BUFFER_LEN(&preface) TSRMLS_CC);
- php_http_buffer_dtor(&preface);
- output(&ctx, NULL, 0 TSRMLS_CC);
- zend_hash_destroy(&ranges);
- if (zbody) {
- zval_ptr_dtor(&zbody);
- }
- return SUCCESS;
- }
- break;
- }
-
- switch (php_http_env_is_response_cached_by_etag(container, ZEND_STRL("If-None-Match"))) {
- case PHP_HTTP_CACHE_MISS:
- break;
-
- case PHP_HTTP_CACHE_NO:
- if (PHP_HTTP_CACHE_HIT != php_http_env_is_response_cached_by_last_modified(container, ZEND_STRL("If-Modified-Since"))) {
- break;
- }
-
- case PHP_HTTP_CACHE_HIT:
- php_http_env_set_response_code(304 TSRMLS_CC);
- if (zbody) {
- zval_ptr_dtor(&zbody);
- }
- return SUCCESS;
- }
-
- php_http_message_body_to_callback(body, output, &ctx, 0, 0);
- output(&ctx, NULL, 0 TSRMLS_CC);
-
- if (zbody) {
- zval_ptr_dtor(&zbody);
- }
- return SUCCESS;
-}
-
-static PHP_HTTP_STRLIST(php_http_env_response_status) =
- PHP_HTTP_STRLIST_ITEM("Continue")
- PHP_HTTP_STRLIST_ITEM("Switching Protocols")
- PHP_HTTP_STRLIST_NEXT
- PHP_HTTP_STRLIST_ITEM("OK")
- PHP_HTTP_STRLIST_ITEM("Created")
- PHP_HTTP_STRLIST_ITEM("Accepted")
- PHP_HTTP_STRLIST_ITEM("Non-Authoritative Information")
- PHP_HTTP_STRLIST_ITEM("No Content")
- PHP_HTTP_STRLIST_ITEM("Reset Content")
- PHP_HTTP_STRLIST_ITEM("Partial Content")
- PHP_HTTP_STRLIST_NEXT
- PHP_HTTP_STRLIST_ITEM("Multiple Choices")
- PHP_HTTP_STRLIST_ITEM("Moved Permanently")
- PHP_HTTP_STRLIST_ITEM("Found")
- PHP_HTTP_STRLIST_ITEM("See Other")
- PHP_HTTP_STRLIST_ITEM("Not Modified")
- PHP_HTTP_STRLIST_ITEM("Use Proxy")
- PHP_HTTP_STRLIST_ITEM("(Unused)")
- PHP_HTTP_STRLIST_ITEM("Temporary Redirect")
- PHP_HTTP_STRLIST_NEXT
- PHP_HTTP_STRLIST_ITEM("Bad Request")
- PHP_HTTP_STRLIST_ITEM("Unauthorized")
- PHP_HTTP_STRLIST_ITEM("Payment Required")
- PHP_HTTP_STRLIST_ITEM("Forbidden")
- PHP_HTTP_STRLIST_ITEM("Not Found")
- PHP_HTTP_STRLIST_ITEM("Method Not Allowed")
- PHP_HTTP_STRLIST_ITEM("Not Acceptable")
- PHP_HTTP_STRLIST_ITEM("Proxy Authentication Required")
- PHP_HTTP_STRLIST_ITEM("Request Timeout")
- PHP_HTTP_STRLIST_ITEM("Conflict")
- PHP_HTTP_STRLIST_ITEM("Gone")
- PHP_HTTP_STRLIST_ITEM("Length Required")
- PHP_HTTP_STRLIST_ITEM("Precondition Failed")
- PHP_HTTP_STRLIST_ITEM("Request Entity Too Large")
- PHP_HTTP_STRLIST_ITEM("Request URI Too Long")
- PHP_HTTP_STRLIST_ITEM("Unsupported Media Type")
- PHP_HTTP_STRLIST_ITEM("Requested Range Not Satisfiable")
- PHP_HTTP_STRLIST_ITEM("Expectation Failed")
- PHP_HTTP_STRLIST_NEXT
- PHP_HTTP_STRLIST_ITEM("Internal Server Error")
- PHP_HTTP_STRLIST_ITEM("Not Implemented")
- PHP_HTTP_STRLIST_ITEM("Bad Gateway")
- PHP_HTTP_STRLIST_ITEM("Service Unavailable")
- PHP_HTTP_STRLIST_ITEM("Gateway Timeout")
- PHP_HTTP_STRLIST_ITEM("HTTP Version Not Supported")
- PHP_HTTP_STRLIST_STOP
-;
-
-PHP_HTTP_API const char *php_http_env_get_response_status_for_code(unsigned code)
-{
- return php_http_strlist_find(php_http_env_response_status, 100, code);
-}
-
-zend_class_entry *php_http_env_class_entry;
-
-#define PHP_HTTP_BEGIN_ARGS(method, req_args) PHP_HTTP_BEGIN_ARGS_EX(HttpEnv, method, 0, req_args)
-#define PHP_HTTP_EMPTY_ARGS(method) PHP_HTTP_EMPTY_ARGS_EX(HttpEnv, method, 0)
-#define PHP_HTTP_ENV_ME(method) PHP_ME(HttpEnv, method, PHP_HTTP_ARGS(HttpEnv, method), ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-
-PHP_HTTP_BEGIN_ARGS(getRequestHeader, 0)
- PHP_HTTP_ARG_VAL(header_name, 0)
-PHP_HTTP_END_ARGS;
-
-PHP_HTTP_BEGIN_ARGS(getRequestBody, 0)
- PHP_HTTP_ARG_VAL(body_class_name, 0)
-PHP_HTTP_END_ARGS;
-
-PHP_HTTP_BEGIN_ARGS(getResponseStatusForCode, 1)
- PHP_HTTP_ARG_VAL(code, 0)
-PHP_HTTP_END_ARGS;
-
-PHP_HTTP_BEGIN_ARGS(getResponseHeader, 0)
- PHP_HTTP_ARG_VAL(header_name, 0)
-PHP_HTTP_END_ARGS;
-
-PHP_HTTP_EMPTY_ARGS(getResponseCode);
-
-PHP_HTTP_BEGIN_ARGS(setResponseHeader, 1)
- PHP_HTTP_ARG_VAL(header_name, 0)
- PHP_HTTP_ARG_VAL(header_value, 0)
- PHP_HTTP_ARG_VAL(response_code, 0)
- PHP_HTTP_ARG_VAL(replace_header, 0)
-PHP_HTTP_END_ARGS;
-
-PHP_HTTP_BEGIN_ARGS(setResponseCode, 1)
- PHP_HTTP_ARG_VAL(code, 0)
-PHP_HTTP_END_ARGS;
-
-PHP_HTTP_BEGIN_ARGS(negotiateLanguage, 0)
- PHP_HTTP_ARG_VAL(supported, 0)
- PHP_HTTP_ARG_VAL(result_array, 1)
-PHP_HTTP_END_ARGS;
-
-PHP_HTTP_BEGIN_ARGS(negotiateContentType, 0)
- PHP_HTTP_ARG_VAL(supported, 0)
- PHP_HTTP_ARG_VAL(result_array, 1)
-PHP_HTTP_END_ARGS;
-
-PHP_HTTP_BEGIN_ARGS(negotiateCharset, 0)
- PHP_HTTP_ARG_VAL(supported, 0)
- PHP_HTTP_ARG_VAL(result_array, 1)
-PHP_HTTP_END_ARGS;
-
-PHP_HTTP_BEGIN_ARGS(negotiate, 0)
- PHP_HTTP_ARG_VAL(value, 0)
- PHP_HTTP_ARG_VAL(supported, 0)
- PHP_HTTP_ARG_VAL(result_array, 1)
-PHP_HTTP_END_ARGS;
-
-PHP_HTTP_EMPTY_ARGS(persistentHandlesStat);
-
-PHP_HTTP_BEGIN_ARGS(persistentHandlesClean, 0)
- PHP_HTTP_ARG_VAL(name, 0)
- PHP_HTTP_ARG_VAL(ident, 0)
-PHP_HTTP_END_ARGS;
-
-PHP_HTTP_BEGIN_ARGS(persistentHandlesIdent, 0)
- PHP_HTTP_ARG_VAL(name, 0)
-PHP_HTTP_END_ARGS;
-
-zend_function_entry php_http_env_method_entry[] = {
- PHP_HTTP_ENV_ME(getRequestHeader)
- PHP_HTTP_ENV_ME(getRequestBody)
-
- PHP_HTTP_ENV_ME(getResponseStatusForCode)
-
- PHP_HTTP_ENV_ME(getResponseHeader)
- PHP_HTTP_ENV_ME(getResponseCode)
- PHP_HTTP_ENV_ME(setResponseHeader)
- PHP_HTTP_ENV_ME(setResponseCode)
-
- PHP_HTTP_ENV_ME(negotiateLanguage)
- PHP_HTTP_ENV_ME(negotiateContentType)
- PHP_HTTP_ENV_ME(negotiateCharset)
- PHP_HTTP_ENV_ME(negotiate)
-
- PHP_HTTP_ENV_ME(persistentHandlesStat)
- PHP_HTTP_ENV_ME(persistentHandlesClean)
- PHP_HTTP_ENV_ME(persistentHandlesIdent)
-
- EMPTY_FUNCTION_ENTRY
-};
-
-PHP_METHOD(HttpEnv, getRequestHeader)
-{
- char *header_name_str;
- int header_name_len;
-
- if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!", &header_name_str, &header_name_len)) {
- if (header_name_str && header_name_len) {
- char *header_value = php_http_env_get_request_header(header_name_str, header_name_len TSRMLS_CC);
-
- if (header_value) {
- RETURN_STRING(header_value, 0);
- }
- RETURN_NULL();
- } else {
- array_init(return_value);
- php_http_env_get_request_headers(Z_ARRVAL_P(return_value) TSRMLS_CC);
- return;
- }