- add package.xml generated by $pecl pickle
[m6w6/ext-http] / http_response_object.c
index 84e40d0ab8aa4522b86dd679ddfb6683ced370c5..93c8f0c82193ca56993cb02928a12f21c017b707 100644 (file)
 #include "php_http_exception_object.h"
 #include "php_http_send_api.h"
 #include "php_http_cache_api.h"
+#include "php_http_headers_api.h"
+
+#ifdef HTTP_HAVE_MHASH
+#      include <mhash.h>
+#endif
+#ifdef HTTP_HAVE_MAGIC
+#      include <magic.h>
+#endif
 
 ZEND_EXTERN_MODULE_GLOBALS(http);
 
@@ -148,6 +156,8 @@ HTTP_EMPTY_ARGS(getRequestBody, 0);
 
 #define http_response_object_declare_default_properties() _http_response_object_declare_default_properties(TSRMLS_C)
 static inline void _http_response_object_declare_default_properties(TSRMLS_D);
+#define http_grab_response_headers _http_grab_response_headers
+static void _http_grab_response_headers(void *data, void *arg TSRMLS_DC);
 
 zend_class_entry *http_response_object_ce;
 zend_function_entry http_response_object_fe[] = {
@@ -217,11 +227,11 @@ static inline void _http_response_object_declare_default_properties(TSRMLS_D)
        DCL_STATIC_PROP(PRIVATE, bool, sent, 0);
        DCL_STATIC_PROP(PRIVATE, bool, catch, 0);
        DCL_STATIC_PROP(PRIVATE, long, mode, -1);
+       DCL_STATIC_PROP(PRIVATE, long, stream, 0);
+       DCL_STATIC_PROP_N(PRIVATE, file);
+       DCL_STATIC_PROP_N(PRIVATE, data);
        DCL_STATIC_PROP(PROTECTED, bool, cache, 0);
        DCL_STATIC_PROP(PROTECTED, bool, gzip, 0);
-       DCL_STATIC_PROP(PROTECTED, long, stream, 0);
-       DCL_STATIC_PROP_N(PROTECTED, file);
-       DCL_STATIC_PROP_N(PROTECTED, data);
        DCL_STATIC_PROP_N(PROTECTED, eTag);
        DCL_STATIC_PROP(PROTECTED, long, lastModified, 0);
        DCL_STATIC_PROP_N(PROTECTED, cacheControl);
@@ -229,7 +239,34 @@ static inline void _http_response_object_declare_default_properties(TSRMLS_D)
        DCL_STATIC_PROP_N(PROTECTED, contentDisposition);
        DCL_STATIC_PROP(PROTECTED, long, bufferSize, HTTP_SENDBUF_SIZE);
        DCL_STATIC_PROP(PROTECTED, double, throttleDelay, 0.0);
-       DCL_STATIC_PROP_N(PROTECTED, headers);
+
+#ifndef WONKY
+       DCL_CONST(long, "ETAG_MD5", HTTP_ETAG_MD5);
+       DCL_CONST(long, "ETAG_SHA1", HTTP_ETAG_SHA1);
+       DCL_CONST(long, "ETAG_CRC32", HTTP_ETAG_CRC32);
+       
+#      ifdef HTTP_HAVE_MHASH
+       {
+               int l, i, c = mhash_count();
+               
+               for (i = 0; i <= c; ++i) {
+                       char const_name[256] = {0};
+                       const char *hash_name = mhash_get_hash_name_static(i);
+                       
+                       if (hash_name) {
+                               l = snprintf(const_name, 255, "ETAG_MHASH_%s", hash_name);
+                               zend_declare_class_constant_long(ce, const_name, l, i TSRMLS_CC);
+                       }
+               }
+       }
+#      endif /* HTTP_HAVE_MHASH */
+#endif /* WONKY */
+}
+
+static void _http_grab_response_headers(void *data, void *arg TSRMLS_DC)
+{
+       phpstr_appendl(PHPSTR(arg), ((sapi_header_struct *)data)->header);
+       phpstr_appends(PHPSTR(arg), HTTP_CRLF);
 }
 
 /* ### USERLAND ### */
@@ -241,34 +278,41 @@ PHP_METHOD(HttpResponse, setHeader)
        zend_bool replace = 1;
        char *name;
        int name_len = 0;
-       zval *value = NULL, *headers, **header;
+       zval *value = NULL;
 
        if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz/!|b", &name, &name_len, &value, &replace)) {
                RETURN_FALSE;
        }
+       if (SG(headers_sent)) {
+               http_error(HE_WARNING, HTTP_E_HEADER, "Cannot add another header when headers have already been sent");
+               RETURN_FALSE;
+       }
        if (!name_len) {
                http_error(HE_WARNING, HTTP_E_HEADER, "Cannot send anonymous headers");
                RETURN_FALSE;
        }
 
-       headers = convert_to_type(IS_ARRAY, GET_STATIC_PROP(headers));
-
        /* delete header if value == null */
        if (!value || Z_TYPE_P(value) == IS_NULL) {
-               RETURN_SUCCESS(zend_hash_del(Z_ARRVAL_P(headers), name, name_len + 1));
+               RETURN_SUCCESS(http_send_header_ex(name, name_len, "", 0, replace, NULL));
        }
-
+       /* send multiple header if replace is false and value is an array */
+       if (!replace && Z_TYPE_P(value) == IS_ARRAY) {
+               zval **data;
+               
+               FOREACH_VAL(value, data) {
+                       convert_to_string_ex(data);
+                       if (SUCCESS != http_send_header_ex(name, name_len, Z_STRVAL_PP(data), Z_STRLEN_PP(data), 0, NULL)) {
+                               RETURN_FALSE;
+                       }
+               }
+               RETURN_TRUE;
+       }
+       /* send standard header */
        if (Z_TYPE_P(value) != IS_STRING) {
                convert_to_string_ex(&value);
        }
-
-       /* convert old header to an array and add new one if header exists and replace == false */
-       if (replace || (SUCCESS != zend_hash_find(Z_ARRVAL_P(headers), name, name_len + 1, (void **) &header))) {
-               RETURN_SUCCESS(add_assoc_stringl_ex(headers, name, name_len + 1, Z_STRVAL_P(value), Z_STRLEN_P(value), 1));
-       } else {
-               convert_to_array(*header);
-               RETURN_SUCCESS(add_next_index_stringl(*header, Z_STRVAL_P(value), Z_STRLEN_P(value), 1));
-       }
+       RETURN_SUCCESS(http_send_header_ex(name, name_len, Z_STRVAL_P(value), Z_STRLEN_P(value), replace, NULL));
 }
 /* }}} */
 
@@ -278,22 +322,34 @@ PHP_METHOD(HttpResponse, getHeader)
 {
        char *name = NULL;
        int name_len = 0;
-       zval *headers, **header;
+       phpstr headers;
        
        if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name, &name_len)) {
                RETURN_FALSE;
        }
        
-       headers = convert_to_type_ex(IS_ARRAY, GET_STATIC_PROP(headers));
+       phpstr_init(&headers);
+       zend_llist_apply_with_argument(&SG(sapi_headers).headers, http_grab_response_headers, &headers TSRMLS_CC);
+       phpstr_fix(&headers);
        
-       if (!name || !name_len) {
-               array_init(return_value);
-               array_copy(headers, return_value);
-       } else if (SUCCESS == zend_hash_find(Z_ARRVAL_P(headers), name, name_len + 1, (void **) &header)) {
-               RETURN_ZVAL(*header, 1, 0);
+       if (name && name_len) {
+               zval **header;
+               HashTable headers_ht;
+               
+               zend_hash_init(&headers_ht, sizeof(zval *), NULL, ZVAL_PTR_DTOR, 0);
+               if (    (SUCCESS == http_parse_headers_ex(PHPSTR_VAL(&headers), &headers_ht, 1)) &&
+                               (SUCCESS == zend_hash_find(&headers_ht, name, name_len + 1, (void **) &header))) {
+                       RETVAL_ZVAL(*header, 1, 0);
+               } else {
+                       RETVAL_NULL();
+               }
+               zend_hash_destroy(&headers_ht);
        } else {
-               RETURN_NULL();
+               array_init(return_value);
+               http_parse_headers_ex(PHPSTR_VAL(&headers), Z_ARRVAL_P(return_value), 1);
        }
+       
+       phpstr_dtor(&headers);
 }
 /* }}} */
 
@@ -447,10 +503,9 @@ PHP_METHOD(HttpResponse, getContentType)
 }
 /* }}} */
 
-/* {{{ proto static string HttpResponse::guessContentType(string magic_file[, long magic_mode])
+/* {{{ proto static string HttpResponse::guessContentType(string magic_file[, long magic_mode = MAGIC_MIME])
  *
  * Attempts to guess the content type of supplied payload through libmagic.
- * See docs/KnownIssues.txt! 
  */
 PHP_METHOD(HttpResponse, guessContentType)
 {
@@ -460,6 +515,9 @@ PHP_METHOD(HttpResponse, guessContentType)
        
        RETVAL_NULL();
        
+#ifdef HTTP_HAVE_MAGIC
+       magic_mode = MAGIC_MIME;
+       
        SET_EH_THROW_HTTP();
        if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &magic_file, &magic_file_len, &magic_mode)) {
                switch (Z_LVAL_P(GET_STATIC_PROP(mode))) {
@@ -490,6 +548,9 @@ PHP_METHOD(HttpResponse, guessContentType)
                }
        }
        SET_EH_NORMAL();
+#else
+       http_error(HE_THROW, HTTP_E_RUNTIME, "Cannot guess Content-Type; libmagic not available");
+#endif
 }
 /* }}} */
 
@@ -831,7 +892,7 @@ PHP_METHOD(HttpResponse, getFile)
  */
 PHP_METHOD(HttpResponse, send)
 {
-       zval *sent, *headers;
+       zval *sent;
        zend_bool clean_ob = 1;
 
        if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &clean_ob)) {
@@ -878,33 +939,6 @@ PHP_METHOD(HttpResponse, send)
                php_end_ob_buffers(0 TSRMLS_CC);
        }
 
-       /* custom headers */
-       headers = GET_STATIC_PROP(headers);
-       if (Z_TYPE_P(headers) == IS_ARRAY) {
-               char *name = NULL;
-               ulong idx = 0;
-               zval **value;
-
-               FOREACH_KEYVAL(headers, name, idx, value) {
-                       if (name) {
-                               if (Z_TYPE_PP(value) == IS_ARRAY) {
-                                       zend_bool first = 1;
-                                       zval **data;
-
-                                       FOREACH_VAL(*value, data) {
-                                               convert_to_string_ex(data);
-                                               http_send_header_ex(name, strlen(name), Z_STRVAL_PP(data), Z_STRLEN_PP(data), first, NULL);
-                                               first = 0;
-                                       }
-                               } else {
-                                       convert_to_string_ex(value);
-                                       http_send_header_ex(name, strlen(name), Z_STRVAL_PP(value), Z_STRLEN_PP(value), 1, NULL);
-                               }
-                               name = NULL;
-                       }
-               }
-       }
-
        /* gzip */
        if (zval_is_true(GET_STATIC_PROP(gzip))) {
                php_start_ob_buffer_named("ob_gzhandler", 0, 0 TSRMLS_CC);
@@ -998,14 +1032,9 @@ PHP_METHOD(HttpResponse, send)
  */
 PHP_METHOD(HttpResponse, capture)
 {
-       zval do_catch;
-
        NO_ARGS;
 
-       INIT_PZVAL(&do_catch);
-       ZVAL_LONG(&do_catch, 1);
-
-       SET_STATIC_PROP(catch, &do_catch);
+       UPD_STATIC_PROP(long, catch, 1);
 
        php_end_ob_buffers(0 TSRMLS_CC);
        php_start_ob_buffer(NULL, 0, 0 TSRMLS_CC);