- add package.xml generated by $pecl pickle
[m6w6/ext-http] / http_request_object.c
index 1ed0e2c154d71d12c14dc69bd47a825f01238927..9c5e902db0f7dce7d376697fe78ab582237886e9 100644 (file)
@@ -126,6 +126,15 @@ HTTP_BEGIN_ARGS(addPostFile, 0, 2)
        HTTP_ARG_VAL(content_type, 0)
 HTTP_END_ARGS;
 
+HTTP_EMPTY_ARGS(getRawPostData, 0);
+HTTP_BEGIN_ARGS(setRawPostData, 0, 0)
+       HTTP_ARG_VAL(raw_post_data, 0)
+HTTP_END_ARGS;
+
+HTTP_BEGIN_ARGS(addRawPostData, 0, 1)
+       HTTP_ARG_VAL(raw_post_data, 0)
+HTTP_END_ARGS;
+
 HTTP_EMPTY_ARGS(getPutFile, 0);
 HTTP_BEGIN_ARGS(setPutFile, 0, 0)
        HTTP_ARG_VAL(filename, 0)
@@ -244,6 +253,10 @@ zend_function_entry http_request_object_fe[] = {
        HTTP_REQUEST_ME(setPostFields, ZEND_ACC_PUBLIC)
        HTTP_REQUEST_ME(getPostFields, ZEND_ACC_PUBLIC)
        HTTP_REQUEST_ME(addPostFields, ZEND_ACC_PUBLIC)
+       
+       HTTP_REQUEST_ME(setRawPostData, ZEND_ACC_PUBLIC)
+       HTTP_REQUEST_ME(getRawPostData, ZEND_ACC_PUBLIC)
+       HTTP_REQUEST_ME(addRawPostData, ZEND_ACC_PUBLIC)
 
        HTTP_REQUEST_ME(setPostFiles, ZEND_ACC_PUBLIC)
        HTTP_REQUEST_ME(addPostFile, ZEND_ACC_PUBLIC)
@@ -283,45 +296,6 @@ static zend_object_handlers http_request_object_handlers;
 void _http_request_object_init(INIT_FUNC_ARGS)
 {
        HTTP_REGISTER_CLASS_EX(HttpRequest, http_request_object, NULL, 0);
-
-       /* HTTP/1.1 */
-       HTTP_LONG_CONSTANT("HTTP_GET", HTTP_GET);
-       HTTP_LONG_CONSTANT("HTTP_HEAD", HTTP_HEAD);
-       HTTP_LONG_CONSTANT("HTTP_POST", HTTP_POST);
-       HTTP_LONG_CONSTANT("HTTP_PUT", HTTP_PUT);
-       HTTP_LONG_CONSTANT("HTTP_DELETE", HTTP_DELETE);
-       HTTP_LONG_CONSTANT("HTTP_OPTIONS", HTTP_OPTIONS);
-       HTTP_LONG_CONSTANT("HTTP_TRACE", HTTP_TRACE);
-       HTTP_LONG_CONSTANT("HTTP_CONNECT", HTTP_CONNECT);
-       /* WebDAV - RFC 2518 */
-       HTTP_LONG_CONSTANT("HTTP_PROPFIND", HTTP_PROPFIND);
-       HTTP_LONG_CONSTANT("HTTP_PROPPATCH", HTTP_PROPPATCH);
-       HTTP_LONG_CONSTANT("HTTP_MKCOL", HTTP_MKCOL);
-       HTTP_LONG_CONSTANT("HTTP_COPY", HTTP_COPY);
-       HTTP_LONG_CONSTANT("HTTP_MOVE", HTTP_MOVE);
-       HTTP_LONG_CONSTANT("HTTP_LOCK", HTTP_LOCK);
-       HTTP_LONG_CONSTANT("HTTP_UNLOCK", HTTP_UNLOCK);
-       /* WebDAV Versioning - RFC 3253 */
-       HTTP_LONG_CONSTANT("HTTP_VERSION_CONTROL", HTTP_VERSION_CONTROL);
-       HTTP_LONG_CONSTANT("HTTP_REPORT", HTTP_REPORT);
-       HTTP_LONG_CONSTANT("HTTP_CHECKOUT", HTTP_CHECKOUT);
-       HTTP_LONG_CONSTANT("HTTP_CHECKIN", HTTP_CHECKIN);
-       HTTP_LONG_CONSTANT("HTTP_UNCHECKOUT", HTTP_UNCHECKOUT);
-       HTTP_LONG_CONSTANT("HTTP_MKWORKSPACE", HTTP_MKWORKSPACE);
-       HTTP_LONG_CONSTANT("HTTP_UPDATE", HTTP_UPDATE);
-       HTTP_LONG_CONSTANT("HTTP_LABEL", HTTP_LABEL);
-       HTTP_LONG_CONSTANT("HTTP_MERGE", HTTP_MERGE);
-       HTTP_LONG_CONSTANT("HTTP_BASELINE_CONTROL", HTTP_BASELINE_CONTROL);
-       HTTP_LONG_CONSTANT("HTTP_MKACTIVITY", HTTP_MKACTIVITY);
-       /* WebDAV Access Control - RFC 3744 */
-       HTTP_LONG_CONSTANT("HTTP_ACL", HTTP_ACL);
-
-
-#      if LIBCURL_VERSION_NUM >= 0x070a05
-       HTTP_LONG_CONSTANT("HTTP_AUTH_BASIC", CURLAUTH_BASIC);
-       HTTP_LONG_CONSTANT("HTTP_AUTH_DIGEST", CURLAUTH_DIGEST);
-       HTTP_LONG_CONSTANT("HTTP_AUTH_NTLM", CURLAUTH_NTLM);
-#      endif /* LIBCURL_VERSION_NUM */
 }
 
 zend_object_value _http_request_object_new(zend_class_entry *ce TSRMLS_DC)
@@ -332,7 +306,6 @@ zend_object_value _http_request_object_new(zend_class_entry *ce TSRMLS_DC)
        o = ecalloc(1, sizeof(http_request_object));
        o->zo.ce = ce;
        o->ch = curl_easy_init();
-       o->pool = NULL;
 
        phpstr_init(&o->history);
        phpstr_init(&o->request);
@@ -364,10 +337,58 @@ static inline void _http_request_object_declare_default_properties(TSRMLS_D)
 
        DCL_PROP(PROTECTED, string, url, "");
        DCL_PROP(PROTECTED, string, contentType, "");
+       DCL_PROP(PROTECTED, string, rawPostData, "");
        DCL_PROP(PROTECTED, string, queryData, "");
        DCL_PROP(PROTECTED, string, putFile, "");
 
        DCL_PROP(PUBLIC, bool, recordHistory, 1);
+
+#ifndef WONKY
+       /*
+        * Request Method Constants
+        */
+       /* HTTP/1.1 */
+       DCL_CONST(long, "METH_GET", HTTP_GET);
+       DCL_CONST(long, "METH_HEAD", HTTP_HEAD);
+       DCL_CONST(long, "METH_POST", HTTP_POST);
+       DCL_CONST(long, "METH_PUT", HTTP_PUT);
+       DCL_CONST(long, "METH_DELETE", HTTP_DELETE);
+       DCL_CONST(long, "METH_OPTIONS", HTTP_OPTIONS);
+       DCL_CONST(long, "METH_TRACE", HTTP_TRACE);
+       DCL_CONST(long, "METH_CONNECT", HTTP_CONNECT);
+       /* WebDAV - RFC 2518 */
+       DCL_CONST(long, "METH_PROPFIND", HTTP_PROPFIND);
+       DCL_CONST(long, "METH_PROPPATCH", HTTP_PROPPATCH);
+       DCL_CONST(long, "METH_MKCOL", HTTP_MKCOL);
+       DCL_CONST(long, "METH_COPY", HTTP_COPY);
+       DCL_CONST(long, "METH_MOVE", HTTP_MOVE);
+       DCL_CONST(long, "METH_LOCK", HTTP_LOCK);
+       DCL_CONST(long, "METH_UNLOCK", HTTP_UNLOCK);
+       /* WebDAV Versioning - RFC 3253 */
+       DCL_CONST(long, "METH_VERSION_CONTROL", HTTP_VERSION_CONTROL);
+       DCL_CONST(long, "METH_REPORT", HTTP_REPORT);
+       DCL_CONST(long, "METH_CHECKOUT", HTTP_CHECKOUT);
+       DCL_CONST(long, "METH_CHECKIN", HTTP_CHECKIN);
+       DCL_CONST(long, "METH_UNCHECKOUT", HTTP_UNCHECKOUT);
+       DCL_CONST(long, "METH_MKWORKSPACE", HTTP_MKWORKSPACE);
+       DCL_CONST(long, "METH_UPDATE", HTTP_UPDATE);
+       DCL_CONST(long, "METH_LABEL", HTTP_LABEL);
+       DCL_CONST(long, "METH_MERGE", HTTP_MERGE);
+       DCL_CONST(long, "METH_BASELINE_CONTROL", HTTP_BASELINE_CONTROL);
+       DCL_CONST(long, "METH_MKACTIVITY", HTTP_MKACTIVITY);
+       /* WebDAV Access Control - RFC 3744 */
+       DCL_CONST(long, "METH_ACL", HTTP_ACL);
+
+       /*
+        * Auth Constants
+        */
+#      if LIBCURL_VERSION_NUM >= 0x070a05
+       DCL_CONST(long, "AUTH_BASIC", CURLAUTH_BASIC);
+       DCL_CONST(long, "AUTH_DIGEST", CURLAUTH_DIGEST);
+       DCL_CONST(long, "AUTH_NTLM", CURLAUTH_NTLM);
+       DCL_CONST(long, "AUTH_ANY", CURLAUTH_ANY);
+#      endif /* LIBCURL_VERSION_NUM */
+#endif /* WONKY */
 }
 
 void _http_request_object_free(zend_object *object TSRMLS_DC)
@@ -406,13 +427,13 @@ STATUS _http_request_object_requesthandler(http_request_object *obj, zval *this_
                return FAILURE;
        }
 
-       URL = GET_PROP(obj, url);
+       URL = convert_to_type_ex(IS_STRING, GET_PROP(obj, url));
        // HTTP_URI_MAXLEN+1 long char *
        if (!(request_uri = http_absolute_uri_ex(Z_STRVAL_P(URL), Z_STRLEN_P(URL), NULL, 0, NULL, 0, 0))) {
                return FAILURE;
        }
        
-       meth = GET_PROP(obj, method);
+       meth = convert_to_type_ex(IS_LONG, GET_PROP(obj, method));
        switch (Z_LVAL_P(meth))
        {
                case HTTP_GET:
@@ -438,12 +459,48 @@ STATUS _http_request_object_requesthandler(http_request_object *obj, zval *this_
 
                case HTTP_POST:
                default:
-                       status = http_request_body_fill(body, Z_ARRVAL_P(GET_PROP(obj, postFields)), Z_ARRVAL_P(GET_PROP(obj, postFiles)));
+               {
+                       /* check for raw post data */
+                       zval *raw_data = convert_to_type_ex(IS_STRING, GET_PROP(obj, rawPostData));
+                       
+                       if (Z_STRLEN_P(raw_data)) {
+                               zval *ctype = convert_to_type_ex(IS_STRING, GET_PROP(obj, contentType));
+                               
+                               if (Z_STRLEN_P(ctype)) {
+                                       zval **headers, *opts = GET_PROP(obj, options);
+                                       
+                                       convert_to_array(opts);
+                                       
+                                       if (SUCCESS == zend_hash_find(Z_ARRVAL_P(opts), "headers", sizeof("headers"), (void **) &headers)) {
+                                               zval **ct_header;
+                                               
+                                               convert_to_array(*headers);
+                                               /* only override if not already set */
+                                               if (SUCCESS != zend_hash_find(Z_ARRVAL_PP(headers), "Content-Type", sizeof("Content-Type"), (void **) &ct_header)) {
+                                                       add_assoc_stringl(*headers, "Content-Type", Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
+                                               }
+                                       } else {
+                                               zval *headers;
+                                               
+                                               MAKE_STD_ZVAL(headers);
+                                               array_init(headers);
+                                               add_assoc_stringl(headers, "Content-Type", Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
+                                               add_assoc_zval(opts, "headers", headers);
+                                       }
+                               }
+                               
+                               body->type = HTTP_REQUEST_BODY_CSTRING;
+                               body->data = estrndup(Z_STRVAL_P(raw_data), Z_STRLEN_P(raw_data));
+                               body->size = Z_STRLEN_P(raw_data);
+                       } else {
+                               status = http_request_body_fill(body, Z_ARRVAL_P(GET_PROP(obj, postFields)), Z_ARRVAL_P(GET_PROP(obj, postFiles)));
+                       }
+               }
                break;
        }
        
        if (status == SUCCESS) {
-               zval *qdata = GET_PROP(obj, queryData);
+               zval *qdata = convert_to_type_ex(IS_STRING, GET_PROP(obj, queryData));
                
                if (Z_STRLEN_P(qdata) && (strlen(request_uri) < HTTP_URI_MAXLEN)) {
                        if (!strchr(request_uri, '?')) {
@@ -481,15 +538,10 @@ STATUS _http_request_object_responsehandler(http_request_object *obj, zval *this
                char *body;
                size_t body_len;
                zval *headers, *message,
-                       *resp = GET_PROP(obj, responseData),
-                       *info = GET_PROP(obj, responseInfo),
-                       *hist = GET_PROP(obj, recordHistory);
+                       *resp = convert_to_type(IS_ARRAY, GET_PROP(obj, responseData)),
+                       *info = convert_to_type(IS_ARRAY, GET_PROP(obj, responseInfo));
 
-               /* should we record history? */
-               if (Z_TYPE_P(hist) != IS_BOOL) {
-                       convert_to_boolean(hist);
-               }
-               if (Z_LVAL_P(hist)) {
+               if (zval_is_true(GET_PROP(obj, recordHistory))) {
                        /* we need to act like a zipper, as we'll receive
                         * the requests and the responses in separate chains
                         * for redirects
@@ -549,9 +601,10 @@ static inline void _http_request_object_set_options_subr(INTERNAL_FUNCTION_PARAM
                RETURN_FALSE;
        }
 
-       opts = GET_PROP(obj, options);
+       opts = convert_to_type(IS_ARRAY, GET_PROP(obj, options));
 
        if (SUCCESS == zend_hash_find(Z_ARRVAL_P(opts), key, len, (void **) &options)) {
+               convert_to_array(*options);
                if (overwrite) {
                        zend_hash_clean(Z_ARRVAL_PP(options));
                }
@@ -580,11 +633,12 @@ static inline void _http_request_get_options_subr(INTERNAL_FUNCTION_PARAMETERS,
                zval *opts, **options;
                getObject(http_request_object, obj);
 
-               opts = GET_PROP(obj, options);
+               opts = convert_to_type_ex(IS_ARRAY, GET_PROP(obj, options));
 
                array_init(return_value);
 
                if (SUCCESS == zend_hash_find(Z_ARRVAL_P(opts), key, len, (void **) &options)) {
+                       convert_to_array(*options);
                        array_copy(*options, return_value);
                }
        }
@@ -614,7 +668,7 @@ PHP_METHOD(HttpRequest, __construct)
                INIT_PARR(obj, postFiles);
 
                if (URL) {
-                       UPD_PROP(obj, string, url, URL);
+                       UPD_STRL(obj, url, URL, URL_len);
                }
                if (meth > -1) {
                        UPD_PROP(obj, long, method, meth);
@@ -657,7 +711,7 @@ PHP_METHOD(HttpRequest, setOptions)
                RETURN_FALSE;
        }
        
-       old_opts = GET_PROP(obj, options);
+       old_opts = convert_to_type(IS_ARRAY, GET_PROP(obj, options));
 
        if (!opts || !zend_hash_num_elements(Z_ARRVAL_P(opts))) {
                zend_hash_clean(Z_ARRVAL_P(old_opts));
@@ -670,26 +724,32 @@ PHP_METHOD(HttpRequest, setOptions)
                        if (!strcmp(key, "headers")) {
                                zval **headers;
                                if (SUCCESS == zend_hash_find(Z_ARRVAL_P(old_opts), "headers", sizeof("headers"), (void **) &headers)) {
+                                       convert_to_array(*opt);
+                                       convert_to_array(*headers);
                                        array_merge(*opt, *headers);
                                        continue;
                                }
                        } else if (!strcmp(key, "cookies")) {
                                zval **cookies;
                                if (SUCCESS == zend_hash_find(Z_ARRVAL_P(old_opts), "cookies", sizeof("cookies"), (void **) &cookies)) {
+                                       convert_to_array(*opt);
+                                       convert_to_array(*cookies);
                                        array_merge(*opt, *cookies);
                                        continue;
                                }
                        } else if (!strcmp(key, "ssl")) {
                                zval **ssl;
                                if (SUCCESS == zend_hash_find(Z_ARRVAL_P(old_opts), "ssl", sizeof("ssl"), (void **) &ssl)) {
+                                       convert_to_array(*opt);
+                                       convert_to_array(*ssl);
                                        array_merge(*opt, *ssl);
                                        continue;
                                }
-                       }else if ((!strcasecmp(key, "url")) || (!strcasecmp(key, "uri"))) {
+                       } else if ((!strcasecmp(key, "url")) || (!strcasecmp(key, "uri"))) {
                                if (Z_TYPE_PP(opt) != IS_STRING) {
                                        convert_to_string_ex(opt);
                                }
-                               UPD_PROP(obj, string, url, Z_STRVAL_PP(opt));
+                               UPD_STRL(obj, url, Z_STRVAL_PP(opt), Z_STRLEN_PP(opt));
                                continue;
                        } else if (!strcmp(key, "method")) {
                                if (Z_TYPE_PP(opt) != IS_LONG) {
@@ -723,7 +783,7 @@ PHP_METHOD(HttpRequest, getOptions)
                zval *opts;
                getObject(http_request_object, obj);
 
-               opts = GET_PROP(obj, options);
+               opts = convert_to_type_ex(IS_ARRAY, GET_PROP(obj, options));
                array_init(return_value);
                array_copy(opts, return_value);
        }
@@ -833,7 +893,7 @@ PHP_METHOD(HttpRequest, setUrl)
                RETURN_FALSE;
        }
 
-       UPD_PROP(obj, string, url, URL);
+       UPD_STRL(obj, url, URL, URL_len);
        RETURN_TRUE;
 }
 /* }}} */
@@ -847,11 +907,10 @@ PHP_METHOD(HttpRequest, getUrl)
        NO_ARGS;
 
        IF_RETVAL_USED {
-               zval *URL;
                getObject(http_request_object, obj);
+               zval *URL = GET_PROP(obj, url);
 
-               URL = GET_PROP(obj, url);
-               RETURN_STRINGL(Z_STRVAL_P(URL), Z_STRLEN_P(URL), 1);
+               RETURN_ZVAL(URL, 1, 0);
        }
 }
 /* }}} */
@@ -884,11 +943,10 @@ PHP_METHOD(HttpRequest, getMethod)
        NO_ARGS;
 
        IF_RETVAL_USED {
-               zval *meth;
                getObject(http_request_object, obj);
-
-               meth = GET_PROP(obj, method);
-               RETURN_LONG(Z_LVAL_P(meth));
+               zval *meth = GET_PROP(obj, method);
+               
+               RETURN_ZVAL(meth, 1, 0);
        }
 }
 /* }}} */
@@ -913,7 +971,7 @@ PHP_METHOD(HttpRequest, setContentType)
                RETURN_FALSE;
        }
 
-       UPD_PROP(obj, string, contentType, ctype);
+       UPD_STRL(obj, contentType, ctype, ct_len);
        RETURN_TRUE;
 }
 /* }}} */
@@ -927,11 +985,10 @@ PHP_METHOD(HttpRequest, getContentType)
        NO_ARGS;
 
        IF_RETVAL_USED {
-               zval *ctype;
                getObject(http_request_object, obj);
-
-               ctype = GET_PROP(obj, contentType);
-               RETURN_STRINGL(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
+               zval *ctype = GET_PROP(obj, contentType);
+               
+               RETURN_ZVAL(ctype, 1, 0);
        }
 }
 /* }}} */
@@ -952,7 +1009,7 @@ PHP_METHOD(HttpRequest, setQueryData)
        }
 
        if ((!qdata) || Z_TYPE_P(qdata) == IS_NULL) {
-               UPD_PROP(obj, string, queryData, "");
+               UPD_STRL(obj, queryData, "", 0);
        } else if ((Z_TYPE_P(qdata) == IS_ARRAY) || (Z_TYPE_P(qdata) == IS_OBJECT)) {
                char *query_data = NULL;
                
@@ -963,8 +1020,8 @@ PHP_METHOD(HttpRequest, setQueryData)
                UPD_PROP(obj, string, queryData, query_data);
                efree(query_data);
        } else {
-               convert_to_string(qdata);
-               UPD_PROP(obj, string, queryData, Z_STRVAL_P(qdata));
+               convert_to_string_ex(&qdata);
+               UPD_STRL(obj, queryData, Z_STRVAL_P(qdata), Z_STRLEN_P(qdata));
        }
        RETURN_TRUE;
 }
@@ -979,11 +1036,10 @@ PHP_METHOD(HttpRequest, getQueryData)
        NO_ARGS;
 
        IF_RETVAL_USED {
-               zval *qdata;
                getObject(http_request_object, obj);
-
-               qdata = GET_PROP(obj, queryData);
-               RETURN_STRINGL(Z_STRVAL_P(qdata), Z_STRLEN_P(qdata), 1);
+               zval *qdata = convert_to_type_ex(IS_STRING, GET_PROP(obj, queryData));
+               
+               RETURN_ZVAL(qdata, 1, 0);
        }
 }
 /* }}} */
@@ -997,19 +1053,20 @@ PHP_METHOD(HttpRequest, addQueryData)
 {
        zval *qdata, *old_qdata;
        char *query_data = NULL;
+       size_t query_data_len = 0;
        getObject(http_request_object, obj);
 
        if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &qdata)) {
                RETURN_FALSE;
        }
 
-       old_qdata = GET_PROP(obj, queryData);
+       old_qdata = convert_to_type_ex(IS_STRING, GET_PROP(obj, queryData));
 
-       if (SUCCESS != http_urlencode_hash_ex(HASH_OF(qdata), 1, Z_STRVAL_P(old_qdata), Z_STRLEN_P(old_qdata), &query_data, NULL)) {
+       if (SUCCESS != http_urlencode_hash_ex(HASH_OF(qdata), 1, Z_STRVAL_P(old_qdata), Z_STRLEN_P(old_qdata), &query_data, &query_data_len)) {
                RETURN_FALSE;
        }
 
-       UPD_PROP(obj, string, queryData, query_data);
+       UPD_STRL(obj, queryData, query_data, query_data_len);
        efree(query_data);
 
        RETURN_TRUE;
@@ -1030,7 +1087,7 @@ PHP_METHOD(HttpRequest, addPostFields)
                RETURN_FALSE;
        }
 
-       post = GET_PROP(obj, postFields);
+       post = convert_to_type(IS_ARRAY, GET_PROP(obj, postFields));
        array_merge(post_data, post);
 
        RETURN_TRUE;
@@ -1052,7 +1109,7 @@ PHP_METHOD(HttpRequest, setPostFields)
                RETURN_FALSE;
        }
 
-       post = GET_PROP(obj, postFields);
+       post = convert_to_type(IS_ARRAY, GET_PROP(obj, postFields));
        zend_hash_clean(Z_ARRVAL_P(post));
        
        if (post_data && zend_hash_num_elements(Z_ARRVAL_P(post_data))) {
@@ -1072,16 +1129,89 @@ PHP_METHOD(HttpRequest, getPostFields)
        NO_ARGS;
 
        IF_RETVAL_USED {
-               zval *post_data;
                getObject(http_request_object, obj);
-
-               post_data = GET_PROP(obj, postFields);
+               zval *post_data = convert_to_type_ex(IS_ARRAY, GET_PROP(obj, postFields));
+               
                array_init(return_value);
                array_copy(post_data, return_value);
        }
 }
 /* }}} */
 
+/* {{{ proto bool HttpRequest::setRawPostData([string raw_post_data])
+ *
+ * Set raw post data to send.  Don't forget to specify a content type.
+ * Affects only POST requests.
+ */
+PHP_METHOD(HttpRequest, setRawPostData)
+{
+       char *raw_data = NULL;
+       int data_len = 0;
+       getObject(http_request_object, obj);
+       
+       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &raw_data, &data_len)) {
+               RETURN_FALSE;
+       }
+       
+       if (!raw_data) {
+               raw_data = "";
+       }
+       
+       UPD_STRL(obj, rawPostData, raw_data, data_len);
+       RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool HttpRequest::addRawPostData(string raw_post_data)
+ *
+ * Add raw post data.
+ * Affects only POST requests.
+ */
+PHP_METHOD(HttpRequest, addRawPostData)
+{
+       char *raw_data, *new_data;
+       int data_len;
+       getObject(http_request_object, obj);
+       
+       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &raw_data, &data_len)) {
+               RETURN_FALSE;
+       }
+       
+       if (data_len) {
+               zval *zdata = convert_to_type_ex(IS_STRING, GET_PROP(obj, rawPostData));
+               
+               new_data = emalloc(Z_STRLEN_P(zdata) + data_len + 1);
+               new_data[Z_STRLEN_P(zdata) + data_len] = '\0';
+               
+               if (Z_STRLEN_P(zdata)) {
+                       memcpy(new_data, Z_STRVAL_P(zdata), Z_STRLEN_P(zdata));
+               }
+               
+               memcpy(new_data + Z_STRLEN_P(zdata), raw_data, data_len);
+               UPD_STRL(obj, rawPostData, new_data, Z_STRLEN_P(zdata) + data_len);
+       }
+       
+       RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto string HttpRequest::getRawPostData()
+ *
+ * Get previously set raw post data.
+ */
+PHP_METHOD(HttpRequest, getRawPostData)
+{
+       NO_ARGS;
+       
+       IF_RETVAL_USED {
+               getObject(http_request_object, obj);
+               zval *raw_data = convert_to_type_ex(IS_STRING, GET_PROP(obj, rawPostData));
+               
+               RETURN_ZVAL(raw_data, 1, 0);
+       }
+}
+/* }}} */
+
 /* {{{ proto bool HttpRequest::addPostFile(string name, string file[, string content_type = "application/x-octetstream"])
  *
  * Add a file to the POST request.
@@ -1115,7 +1245,7 @@ PHP_METHOD(HttpRequest, addPostFile)
        add_assoc_stringl(entry, "type", type, type_len, 1);
        add_assoc_stringl(entry, "file", file, file_len, 1);
 
-       files  = GET_PROP(obj, postFiles);
+       files = convert_to_type(IS_ARRAY, GET_PROP(obj, postFiles));
        add_next_index_zval(files, entry);
 
        RETURN_TRUE;
@@ -1137,7 +1267,7 @@ PHP_METHOD(HttpRequest, setPostFiles)
                RETURN_FALSE;
        }
 
-       pFiles = GET_PROP(obj, postFiles);
+       pFiles = convert_to_type(IS_ARRAY, GET_PROP(obj, postFiles));
        zend_hash_clean(Z_ARRVAL_P(pFiles));
        
        if (files && zend_hash_num_elements(Z_ARRVAL_P(files))) {
@@ -1157,10 +1287,8 @@ PHP_METHOD(HttpRequest, getPostFiles)
        NO_ARGS;
 
        IF_RETVAL_USED {
-               zval *files;
                getObject(http_request_object, obj);
-
-               files = GET_PROP(obj, postFiles);
+               zval *files = convert_to_type_ex(IS_ARRAY, GET_PROP(obj, postFiles));
 
                array_init(return_value);
                array_copy(files, return_value);
@@ -1183,7 +1311,7 @@ PHP_METHOD(HttpRequest, setPutFile)
                RETURN_FALSE;
        }
 
-       UPD_PROP(obj, string, putFile, file);
+       UPD_STRL(obj, putFile, file, file_len);
        RETURN_TRUE;
 }
 /* }}} */
@@ -1197,11 +1325,10 @@ PHP_METHOD(HttpRequest, getPutFile)
        NO_ARGS;
 
        IF_RETVAL_USED {
-               zval *putfile;
                getObject(http_request_object, obj);
-
-               putfile = GET_PROP(obj, putFile);
-               RETVAL_STRINGL(Z_STRVAL_P(putfile), Z_STRLEN_P(putfile), 1);
+               zval *putfile = convert_to_type_ex(IS_STRING, GET_PROP(obj, putFile));
+               
+               RETURN_ZVAL(putfile, 1, 0);
        }
 }
 /* }}} */
@@ -1215,10 +1342,9 @@ PHP_METHOD(HttpRequest, getResponseData)
        NO_ARGS;
 
        IF_RETVAL_USED {
-               zval *data;
                getObject(http_request_object, obj);
-
-               data = GET_PROP(obj, responseData);
+               zval *data = convert_to_type_ex(IS_ARRAY, GET_PROP(obj, responseData));
+               
                array_init(return_value);
                array_copy(data, return_value);
        }
@@ -1241,16 +1367,16 @@ PHP_METHOD(HttpRequest, getResponseHeader)
                        RETURN_FALSE;
                }
 
-               data = GET_PROP(obj, responseData);
+               data = convert_to_type_ex(IS_ARRAY, GET_PROP(obj, responseData));
                if (SUCCESS != zend_hash_find(Z_ARRVAL_P(data), "headers", sizeof("headers"), (void **) &headers)) {
                        RETURN_FALSE;
                }
-
+               convert_to_array_ex(headers);
                if (!header_len || !header_name) {
                        array_init(return_value);
                        array_copy(*headers, return_value);
                } else if (SUCCESS == zend_hash_find(Z_ARRVAL_PP(headers), pretty_key(header_name, header_len, 1, 1), header_len + 1, (void **) &header)) {
-                       RETURN_STRINGL(Z_STRVAL_PP(header), Z_STRLEN_PP(header), 1);
+                       RETURN_ZVAL(*header, 1, 0);
                } else {
                        RETURN_FALSE;
                }
@@ -1276,12 +1402,13 @@ PHP_METHOD(HttpRequest, getResponseCookie)
 
                array_init(return_value);
 
-               data = GET_PROP(obj, responseData);
+               data = convert_to_type_ex(IS_ARRAY, GET_PROP(obj, responseData));
                if (SUCCESS == zend_hash_find(Z_ARRVAL_P(data), "headers", sizeof("headers"), (void **) &headers)) {
                        ulong idx = 0;
                        char *key = NULL;
                        zval **header = NULL;
 
+                       convert_to_array_ex(headers);
                        FOREACH_HASH_KEYVAL(Z_ARRVAL_PP(headers), key, idx, header) {
                                if (key && !strcasecmp(key, "Set-Cookie")) {
                                        /* several cookies? */
@@ -1315,9 +1442,11 @@ PHP_METHOD(HttpRequest, getResponseCookie)
                                                }
                                        } else {
                                                zval *cookie_hash;
+                                               
                                                MAKE_STD_ZVAL(cookie_hash);
                                                array_init(cookie_hash);
-
+                                               convert_to_string_ex(header);
+                                               
                                                if (SUCCESS == http_parse_cookie(Z_STRVAL_PP(header), Z_ARRVAL_P(cookie_hash))) {
                                                        if (!cookie_len) {
                                                                add_next_index_zval(return_value, cookie_hash);
@@ -1356,12 +1485,13 @@ PHP_METHOD(HttpRequest, getResponseBody)
        NO_ARGS;
 
        IF_RETVAL_USED {
-               zval *data, **body;
+               zval **body;
                getObject(http_request_object, obj);
-
-               data = GET_PROP(obj, responseData);
+               zval *data = convert_to_type_ex(IS_ARRAY, GET_PROP(obj, responseData));
+               
                if (SUCCESS == zend_hash_find(Z_ARRVAL_P(data), "body", sizeof("body"), (void **) &body)) {
-                       RETURN_STRINGL(Z_STRVAL_PP(body), Z_STRLEN_PP(body), 1);
+                       convert_to_string_ex(body);
+                       RETURN_ZVAL(*body, 1, 0);
                } else {
                        RETURN_FALSE;
                }
@@ -1378,11 +1508,10 @@ PHP_METHOD(HttpRequest, getResponseCode)
        NO_ARGS;
 
        IF_RETVAL_USED {
-               zval *code;
                getObject(http_request_object, obj);
-
-               code = GET_PROP(obj, responseCode);
-               RETURN_LONG(Z_LVAL_P(code));
+               zval *code = convert_to_type_ex(IS_LONG, GET_PROP(obj, responseCode));
+               
+               RETURN_ZVAL(code, 1, 0);
        }
 }
 /* }}} */
@@ -1404,7 +1533,7 @@ PHP_METHOD(HttpRequest, getResponseInfo)
                        RETURN_FALSE;
                }
 
-               info = GET_PROP(obj, responseInfo);
+               info = convert_to_type_ex(IS_ARRAY, GET_PROP(obj, responseInfo));
 
                if (info_len && info_name) {
                        if (SUCCESS == zend_hash_find(Z_ARRVAL_P(info), pretty_key(info_name, info_len, 0, 0), info_len + 1, (void **) &infop)) {