- relicense with a BSD style license
[m6w6/ext-http] / http_request_object.c
index cbb8b2be93b0810b521c174a54b9c597021b8898..aef84e9de495ba9494c44d94806203a3f00618bd 100644 (file)
@@ -1,16 +1,13 @@
 /*
-   +----------------------------------------------------------------------+
-   | PECL :: http                                                         |
-   +----------------------------------------------------------------------+
-   | This source file is subject to version 3.0 of the PHP license, that  |
-   | is bundled with this package in the file LICENSE, and is available   |
-   | through the world-wide-web at http://www.php.net/license/3_0.txt.    |
-   | If you did not receive a copy of the PHP license and are unable to   |
-   | obtain it through the world-wide-web, please send a note to          |
-   | license@php.net so we can mail you a copy immediately.               |
-   +----------------------------------------------------------------------+
-   | Copyright (c) 2004-2005 Michael Wallner <mike@php.net>               |
-   +----------------------------------------------------------------------+
+    +--------------------------------------------------------------------+
+    | PECL :: http                                                       |
+    +--------------------------------------------------------------------+
+    | Redistribution and use in source and binary forms, with or without |
+    | modification, are permitted provided that the conditions mentioned |
+    | in the accompanying LICENSE file are met.                          |
+    +--------------------------------------------------------------------+
+    | Copyright (c) 2004-2005, Michael Wallner <mike@php.net>            |
+    +--------------------------------------------------------------------+
 */
 
 /* $Id$ */
@@ -23,6 +20,8 @@
 
 #if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL)
 
+#include "zend_interfaces.h"
+
 #include "php_http_std_defs.h"
 #include "php_http_request_object.h"
 #include "php_http_request_api.h"
@@ -52,6 +51,7 @@ HTTP_EMPTY_ARGS(__destruct, 0);
 HTTP_BEGIN_ARGS(__construct, 0, 0)
        HTTP_ARG_VAL(url, 0)
        HTTP_ARG_VAL(method, 0)
+       HTTP_ARG_VAL(options, 0)
 HTTP_END_ARGS;
 
 HTTP_EMPTY_ARGS(getOptions, 0);
@@ -219,6 +219,8 @@ HTTP_END_ARGS;
 
 #define http_request_object_declare_default_properties() _http_request_object_declare_default_properties(TSRMLS_C)
 static inline void _http_request_object_declare_default_properties(TSRMLS_D);
+#define http_request_object_clone_obj _http_request_object_clone_obj
+static inline zend_object_value _http_request_object_clone_obj(zval *object TSRMLS_DC);
 
 zend_class_entry *http_request_object_ce;
 zend_function_entry http_request_object_fe[] = {
@@ -295,9 +297,11 @@ zend_function_entry http_request_object_fe[] = {
 };
 static zend_object_handlers http_request_object_handlers;
 
-void _http_request_object_init(INIT_FUNC_ARGS)
+PHP_MINIT_FUNCTION(http_request_object)
 {
        HTTP_REGISTER_CLASS_EX(HttpRequest, http_request_object, NULL, 0);
+       http_request_object_handlers.clone_obj = NULL;
+       return SUCCESS;
 }
 
 zend_object_value _http_request_object_new(zend_class_entry *ce TSRMLS_DC)
@@ -424,10 +428,7 @@ STATUS _http_request_object_requesthandler(http_request_object *obj, zval *this_
        if (!body) {
                return FAILURE;
        }
-       if ((!obj->ch) && (!(obj->ch = curl_easy_init()))) {
-               http_error(HE_WARNING, HTTP_E_REQUEST, "Could not initilaize curl");
-               return FAILURE;
-       }
+       HTTP_CHECK_CURL_INIT(obj->ch, curl_easy_init(), return FAILURE);
 
        URL = convert_to_type_ex(IS_STRING, GET_PROP(obj, url));
        // HTTP_URI_MAXLEN+1 long char *
@@ -504,13 +505,13 @@ STATUS _http_request_object_requesthandler(http_request_object *obj, zval *this_
        if (status == SUCCESS) {
                zval *qdata = convert_to_type_ex(IS_STRING, GET_PROP(obj, queryData));
                
-               if (Z_STRLEN_P(qdata) && (strlen(request_uri) < HTTP_URI_MAXLEN)) {
+               if (Z_STRLEN_P(qdata)) {
                        if (!strchr(request_uri, '?')) {
-                               strcat(request_uri, "?");
+                               strlcat(request_uri, "?", HTTP_URI_MAXLEN);
                        } else {
-                               strcat(request_uri, "&");
+                               strlcat(request_uri, "&", HTTP_URI_MAXLEN);
                        }
-                       strncat(request_uri, Z_STRVAL_P(qdata), HTTP_URI_MAXLEN - strlen(request_uri));
+                       strlcat(request_uri, Z_STRVAL_P(qdata), HTTP_URI_MAXLEN);
                }
                
                status = http_request_init(obj->ch, Z_LVAL_P(meth), request_uri, body, Z_ARRVAL_P(GET_PROP(obj, options)));
@@ -618,7 +619,7 @@ static inline void _http_request_object_set_options_subr(INTERNAL_FUNCTION_PARAM
                        }
                }
        } else if (new_options && zend_hash_num_elements(Z_ARRVAL_P(new_options))) {
-               zval_add_ref(&new_options);
+               ZVAL_ADDREF(new_options);
                add_assoc_zval(opts, key, new_options);
        }
 
@@ -649,13 +650,14 @@ static inline void _http_request_get_options_subr(INTERNAL_FUNCTION_PARAMETERS,
 
 /* ### USERLAND ### */
 
-/* {{{ proto void HttpRequest::__construct([string url[, int request_method = HTTP_METH_GET]])
+/* {{{ proto void HttpRequest::__construct([string url[, int request_method = HTTP_METH_GET[, array options]]])
  *
  * Instantiate a new HttpRequest object.
  * 
  * Accepts a string as optional parameter containing the target request url.
  * Additianally accepts an optional int parameter specifying the request method
- * to use.
+ * to use and an associative array as optional third parameter which will be
+ * passed to HttpRequest::setOptions(). 
  * 
  * Throws HttpException.
  */
@@ -664,10 +666,11 @@ PHP_METHOD(HttpRequest, __construct)
        char *URL = NULL;
        int URL_len;
        long meth = -1;
+       zval *options = NULL;
        getObject(http_request_object, obj);
 
        SET_EH_THROW_HTTP();
-       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sl", &URL, &URL_len, &meth)) {
+       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sla", &URL, &URL_len, &meth, &options)) {
                INIT_PARR(obj, options);
                INIT_PARR(obj, responseInfo);
                INIT_PARR(obj, responseData);
@@ -680,6 +683,9 @@ PHP_METHOD(HttpRequest, __construct)
                if (meth > -1) {
                        UPD_PROP(obj, long, method, meth);
                }
+               if (options) {
+                       zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "setoptions", NULL, options);
+               }
        }
        SET_EH_NORMAL();
 }
@@ -720,7 +726,7 @@ PHP_METHOD(HttpRequest, setOptions)
        zval *opts = NULL, *old_opts, **opt;
        getObject(http_request_object, obj);
 
-       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a/!", &opts)) {
+       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!", &opts)) {
                RETURN_FALSE;
        }
        
@@ -730,14 +736,14 @@ PHP_METHOD(HttpRequest, setOptions)
                zend_hash_clean(Z_ARRVAL_P(old_opts));
                RETURN_TRUE;
        }
-
+       
        /* some options need extra attention -- thus cannot use array_merge() directly */
        FOREACH_KEYVAL(opts, key, idx, opt) {
                if (key) {
                        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_ex(opt);
                                        convert_to_array(*headers);
                                        array_merge(*opt, *headers);
                                        continue;
@@ -745,7 +751,7 @@ PHP_METHOD(HttpRequest, setOptions)
                        } 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_ex(opt);
                                        convert_to_array(*cookies);
                                        array_merge(*opt, *cookies);
                                        continue;
@@ -753,7 +759,7 @@ PHP_METHOD(HttpRequest, setOptions)
                        } 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_ex(opt);
                                        convert_to_array(*ssl);
                                        array_merge(*opt, *ssl);
                                        continue;
@@ -772,13 +778,14 @@ PHP_METHOD(HttpRequest, setOptions)
                                continue;
                        }
 
-                       zval_add_ref(opt);
+                       ZVAL_ADDREF(*opt);
                        add_assoc_zval(old_opts, key, *opt);
 
                        /* reset */
                        key = NULL;
                }
        }
+       SET_PROP(obj, options, old_opts);
 
        RETURN_TRUE;
 }
@@ -1033,11 +1040,7 @@ PHP_METHOD(HttpRequest, setContentType)
                RETURN_FALSE;
        }
 
-       if (!strchr(ctype, '/')) {
-               http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Content-Type '%s' doesn't seem to contain a primary and a secondary part", ctype);
-               RETURN_FALSE;
-       }
-
+       HTTP_CHECK_CONTENT_TYPE(ctype, RETURN_FALSE);
        UPD_STRL(obj, contentType, ctype, ct_len);
        RETURN_TRUE;
 }
@@ -1341,10 +1344,7 @@ PHP_METHOD(HttpRequest, addPostFile)
        }
 
        if (type_len) {
-               if (!strchr(type, '/')) {
-                       http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Content-Type '%s' doesn't seem to contain a primary and a secondary part", type);
-                       RETURN_FALSE;
-               }
+               HTTP_CHECK_CONTENT_TYPE(type, RETURN_FALSE);
        } else {
                type = "application/x-octetstream";
                type_len = sizeof("application/x-octetstream") - 1;