re-enable the factory
[m6w6/ext-http] / php_http_client.c
index 5d77693fafd0b6196945ae94fa4c35b3011171f2..9c4589b922de9ad3dedcf5869d17b9e0caefba92 100644 (file)
@@ -132,27 +132,22 @@ PHP_HTTP_API STATUS php_http_client_getopt(php_http_client_t *h, php_http_client
 #define PHP_HTTP_CLIENT_ALIAS(method, func)    PHP_HTTP_STATIC_ME_ALIAS(method, func, PHP_HTTP_ARGS(HttpClient, method))
 #define PHP_HTTP_CLIENT_MALIAS(me, al, vis)    ZEND_FENTRY(me, ZEND_MN(HttpClient_##al), PHP_HTTP_ARGS(HttpClient, al), vis)
 
+PHP_HTTP_BEGIN_ARGS(__construct, 0)
+       PHP_HTTP_ARG_ARR(options, 1, 0)
+PHP_HTTP_END_ARGS;
+
 PHP_HTTP_EMPTY_ARGS(getOptions);
 PHP_HTTP_BEGIN_ARGS(setOptions, 0)
-       PHP_HTTP_ARG_VAL(options, 0)
+       PHP_HTTP_ARG_ARR(options, 1, 0)
 PHP_HTTP_END_ARGS;
 
 PHP_HTTP_EMPTY_ARGS(getSslOptions);
 PHP_HTTP_BEGIN_ARGS(setSslOptions, 0)
-       PHP_HTTP_ARG_VAL(ssl_options, 0)
+       PHP_HTTP_ARG_ARR(ssl_options, 1, 0)
 PHP_HTTP_END_ARGS;
 
 PHP_HTTP_BEGIN_ARGS(addSslOptions, 0)
-       PHP_HTTP_ARG_VAL(ssl_optins, 0)
-PHP_HTTP_END_ARGS;
-
-PHP_HTTP_EMPTY_ARGS(getHeaders);
-PHP_HTTP_BEGIN_ARGS(setHeaders, 0)
-       PHP_HTTP_ARG_VAL(headers, 0)
-PHP_HTTP_END_ARGS;
-
-PHP_HTTP_BEGIN_ARGS(addHeaders, 1)
-       PHP_HTTP_ARG_VAL(headers, 0)
+       PHP_HTTP_ARG_ARR(ssl_options, 1, 0)
 PHP_HTTP_END_ARGS;
 
 PHP_HTTP_EMPTY_ARGS(getCookies);
@@ -170,8 +165,8 @@ PHP_HTTP_BEGIN_ARGS(resetCookies, 0)
 PHP_HTTP_END_ARGS;
 PHP_HTTP_EMPTY_ARGS(flushCookies);
 
-PHP_HTTP_EMPTY_ARGS(getMessageClass);
-PHP_HTTP_BEGIN_ARGS(setMessageClass, 1)
+PHP_HTTP_EMPTY_ARGS(getResponseMessageClass);
+PHP_HTTP_BEGIN_ARGS(setResponseMessageClass, 1)
        PHP_HTTP_ARG_VAL(message_class_name, 0)
 PHP_HTTP_END_ARGS;
 
@@ -179,6 +174,12 @@ PHP_HTTP_EMPTY_ARGS(getResponseMessage);
 PHP_HTTP_EMPTY_ARGS(getRequestMessage);
 PHP_HTTP_EMPTY_ARGS(getHistory);
 PHP_HTTP_EMPTY_ARGS(clearHistory);
+
+PHP_HTTP_BEGIN_ARGS(setRequest, 1)
+       PHP_HTTP_ARG_OBJ(http\\Client\\Request, request, 1)
+PHP_HTTP_END_ARGS;
+PHP_HTTP_EMPTY_ARGS(getRequest);
+
 PHP_HTTP_BEGIN_ARGS(send, 1)
        PHP_HTTP_ARG_VAL(request, 0)
 PHP_HTTP_END_ARGS;
@@ -199,6 +200,7 @@ PHP_HTTP_END_ARGS;
 
 zend_class_entry *php_http_client_class_entry;
 zend_function_entry php_http_client_method_entry[] = {
+       PHP_HTTP_CLIENT_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
        PHP_HTTP_CLIENT_ME(getObservers, ZEND_ACC_PUBLIC)
        PHP_HTTP_CLIENT_ME(notify, ZEND_ACC_PUBLIC)
        PHP_HTTP_CLIENT_ME(attach, ZEND_ACC_PUBLIC)
@@ -220,6 +222,8 @@ zend_function_entry php_http_client_method_entry[] = {
        PHP_HTTP_CLIENT_ME(resetCookies, ZEND_ACC_PUBLIC)
        PHP_HTTP_CLIENT_ME(flushCookies, ZEND_ACC_PUBLIC)
 
+       PHP_HTTP_CLIENT_ME(setRequest, ZEND_ACC_PUBLIC)
+       PHP_HTTP_CLIENT_ME(getRequest, ZEND_ACC_PUBLIC)
        PHP_HTTP_CLIENT_ME(send, ZEND_ACC_PUBLIC)
 
        PHP_HTTP_CLIENT_ME(getResponseMessage, ZEND_ACC_PUBLIC)
@@ -227,8 +231,8 @@ zend_function_entry php_http_client_method_entry[] = {
        PHP_HTTP_CLIENT_ME(getHistory, ZEND_ACC_PUBLIC)
        PHP_HTTP_CLIENT_ME(clearHistory, ZEND_ACC_PUBLIC)
 
-       PHP_HTTP_CLIENT_ME(getMessageClass, ZEND_ACC_PUBLIC)
-       PHP_HTTP_CLIENT_ME(setMessageClass, ZEND_ACC_PUBLIC)
+       PHP_HTTP_CLIENT_ME(getResponseMessageClass, ZEND_ACC_PUBLIC)
+       PHP_HTTP_CLIENT_ME(setResponseMessageClass, ZEND_ACC_PUBLIC)
 
        EMPTY_FUNCTION_ENTRY
 };
@@ -336,7 +340,7 @@ static inline void php_http_client_object_check_request_content_type(zval *this_
 static inline zend_object_value php_http_client_object_message(zval *this_ptr, php_http_message_t *msg TSRMLS_DC)
 {
        zend_object_value ov;
-       zval *zcn = zend_read_property(php_http_client_class_entry, getThis(), ZEND_STRL("messageClass"), 0 TSRMLS_CC);
+       zval *zcn = zend_read_property(php_http_client_class_entry, getThis(), ZEND_STRL("responseMessageClass"), 0 TSRMLS_CC);
        zend_class_entry *class_entry;
 
        if (Z_STRLEN_P(zcn)
@@ -348,12 +352,26 @@ static inline zend_object_value php_http_client_object_message(zval *this_ptr, p
        }
 }
 
-STATUS php_http_client_object_handle_request(zval *zclient, zval *zreq TSRMLS_DC)
+STATUS php_http_client_object_handle_request(zval *zclient, zval **zreq TSRMLS_DC)
 {
        php_http_client_object_t *obj = zend_object_store_get_object(zclient TSRMLS_CC);
        php_http_client_progress_t *progress;
        zval *zoptions;
 
+       /* do we have a valid request? */
+       if (*zreq) {
+               /* remember the request */
+               zend_update_property(php_http_client_class_entry, zclient, ZEND_STRL("request"), *zreq TSRMLS_CC);
+       } else {
+               /* maybe a request is already set */
+               *zreq = zend_read_property(php_http_client_class_entry, zclient, ZEND_STRL("request"), 0 TSRMLS_CC);
+
+               if (Z_TYPE_PP(zreq) != IS_OBJECT || !instanceof_function(Z_OBJCE_PP(zreq), php_http_client_request_class_entry TSRMLS_CC)) {
+                       php_http_error(HE_WARNING, PHP_HTTP_E_CLIENT, "The client does not have a valid request set");
+                       return FAILURE;
+               }
+       }
+
        /* reset request handle */
        php_http_client_reset(obj->client);
 
@@ -513,7 +531,7 @@ STATUS php_http_client_object_handle_response(zval *zclient TSRMLS_DC)
 
                /* update the actual request message */
                MAKE_STD_ZVAL(message);
-               ZVAL_OBJVAL(message, php_http_client_object_message(zclient, php_http_message_copy_ex(msg, NULL, 0) TSRMLS_CC), 0);
+               ZVAL_OBJVAL(message, php_http_message_object_new_ex(php_http_message_class_entry, php_http_message_copy_ex(msg, NULL, 0), NULL TSRMLS_CC), 0);
                zend_update_property(php_http_client_class_entry, zclient, ZEND_STRL("requestMessage"), message TSRMLS_CC);
                zval_ptr_dtor(&message);
        }
@@ -614,6 +632,62 @@ static int apply_pretty_key(void *pDest TSRMLS_DC, int num_args, va_list args, z
        return ZEND_HASH_APPLY_KEEP;
 }
 
+static void php_http_client_object_set_options(INTERNAL_FUNCTION_PARAMETERS)
+{
+       php_http_array_hashkey_t key = php_http_array_hashkey_init(0);
+       HashPosition pos;
+       zval *opts = NULL, *old_opts, *new_opts, *add_opts, **opt;
+
+       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!/", &opts)) {
+               RETURN_FALSE;
+       }
+
+       MAKE_STD_ZVAL(new_opts);
+       array_init(new_opts);
+
+       if (!opts || !zend_hash_num_elements(Z_ARRVAL_P(opts))) {
+               zend_update_property(php_http_client_class_entry, getThis(), ZEND_STRL("options"), new_opts TSRMLS_CC);
+               zval_ptr_dtor(&new_opts);
+       } else {
+               MAKE_STD_ZVAL(add_opts);
+               array_init(add_opts);
+               /* some options need extra attention -- thus cannot use array_merge() directly */
+               FOREACH_KEYVAL(pos, opts, key, opt) {
+                       if (key.type == HASH_KEY_IS_STRING) {
+#define KEYMATCH(k, s) ((sizeof(s)==k.len) && !strcasecmp(k.str, s))
+                               if (KEYMATCH(key, "ssl")) {
+                                       zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "addssloptions", NULL, *opt);
+                               } else if (KEYMATCH(key, "cookies")) {
+                                       zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "addcookies", NULL, *opt);
+                               } else if (KEYMATCH(key, "recordHistory")) {
+                                       zend_update_property(php_http_client_class_entry, getThis(), ZEND_STRL("recordHistory"), *opt TSRMLS_CC);
+                               } else if (KEYMATCH(key, "responseMessageClass")) {
+                                       zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "setmessageclass", NULL, *opt);
+                               } else if (Z_TYPE_PP(opt) == IS_NULL) {
+                                       old_opts = zend_read_property(php_http_client_class_entry, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC);
+                                       if (Z_TYPE_P(old_opts) == IS_ARRAY) {
+                                               zend_symtable_del(Z_ARRVAL_P(old_opts), key.str, key.len);
+                                       }
+                               } else {
+                                       Z_ADDREF_P(*opt);
+                                       add_assoc_zval_ex(add_opts, key.str, key.len, *opt);
+                               }
+                       }
+               }
+
+               old_opts = zend_read_property(php_http_client_class_entry, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC);
+               if (Z_TYPE_P(old_opts) == IS_ARRAY) {
+                       array_copy(Z_ARRVAL_P(old_opts), Z_ARRVAL_P(new_opts));
+               }
+               array_join(Z_ARRVAL_P(add_opts), Z_ARRVAL_P(new_opts), 0, 0);
+               zend_update_property(php_http_client_class_entry, getThis(), ZEND_STRL("options"), new_opts TSRMLS_CC);
+               zval_ptr_dtor(&new_opts);
+               zval_ptr_dtor(&add_opts);
+       }
+
+       RETVAL_ZVAL(getThis(), 1, 0);
+}
+
 static inline void php_http_client_object_set_options_subr(INTERNAL_FUNCTION_PARAMETERS, char *key, size_t len, int overwrite, int prettify_keys)
 {
        zval *old_opts, *new_opts, *opts = NULL, **entry = NULL;
@@ -673,6 +747,19 @@ static inline void php_http_client_object_get_options_subr(INTERNAL_FUNCTION_PAR
        }
 }
 
+PHP_METHOD(HttpClient, __construct)
+{
+       with_error_handling(EH_THROW, php_http_exception_class_entry) {
+               zval *os;
+
+               MAKE_STD_ZVAL(os);
+               object_init_ex(os, spl_ce_SplObjectStorage);
+               zend_update_property(php_http_client_class_entry, getThis(), ZEND_STRL("observers"), os TSRMLS_CC);
+               zval_ptr_dtor(&os);
+
+               php_http_client_object_set_options(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+       } end_error_handling();
+}
 
 PHP_METHOD(HttpClient, getObservers)
 {
@@ -796,58 +883,7 @@ PHP_METHOD(HttpClient, getTransferInfo)
 
 PHP_METHOD(HttpClient, setOptions)
 {
-       php_http_array_hashkey_t key = php_http_array_hashkey_init(0);
-       HashPosition pos;
-       zval *opts = NULL, *old_opts, *new_opts, *add_opts, **opt;
-
-       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!/", &opts)) {
-               RETURN_FALSE;
-       }
-
-       MAKE_STD_ZVAL(new_opts);
-       array_init(new_opts);
-
-       if (!opts || !zend_hash_num_elements(Z_ARRVAL_P(opts))) {
-               zend_update_property(php_http_client_class_entry, getThis(), ZEND_STRL("options"), new_opts TSRMLS_CC);
-               zval_ptr_dtor(&new_opts);
-       } else {
-               MAKE_STD_ZVAL(add_opts);
-               array_init(add_opts);
-               /* some options need extra attention -- thus cannot use array_merge() directly */
-               FOREACH_KEYVAL(pos, opts, key, opt) {
-                       if (key.type == HASH_KEY_IS_STRING) {
-#define KEYMATCH(k, s) ((sizeof(s)==k.len) && !strcasecmp(k.str, s))
-                               if (KEYMATCH(key, "ssl")) {
-                                       zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "addssloptions", NULL, *opt);
-                               } else if (KEYMATCH(key, "cookies")) {
-                                       zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "addcookies", NULL, *opt);
-                               } else if (KEYMATCH(key, "recordHistory")) {
-                                       zend_update_property(php_http_client_class_entry, getThis(), ZEND_STRL("recordHistory"), *opt TSRMLS_CC);
-                               } else if (KEYMATCH(key, "messageClass")) {
-                                       zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "setmessageclass", NULL, *opt);
-                               } else if (Z_TYPE_PP(opt) == IS_NULL) {
-                                       old_opts = zend_read_property(php_http_client_class_entry, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC);
-                                       if (Z_TYPE_P(old_opts) == IS_ARRAY) {
-                                               zend_symtable_del(Z_ARRVAL_P(old_opts), key.str, key.len);
-                                       }
-                               } else {
-                                       Z_ADDREF_P(*opt);
-                                       add_assoc_zval_ex(add_opts, key.str, key.len, *opt);
-                               }
-                       }
-               }
-
-               old_opts = zend_read_property(php_http_client_class_entry, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC);
-               if (Z_TYPE_P(old_opts) == IS_ARRAY) {
-                       array_copy(Z_ARRVAL_P(old_opts), Z_ARRVAL_P(new_opts));
-               }
-               array_join(Z_ARRVAL_P(add_opts), Z_ARRVAL_P(new_opts), 0, 0);
-               zend_update_property(php_http_client_class_entry, getThis(), ZEND_STRL("options"), new_opts TSRMLS_CC);
-               zval_ptr_dtor(&new_opts);
-               zval_ptr_dtor(&add_opts);
-       }
-
-       RETVAL_ZVAL(getThis(), 1, 0);
+       php_http_client_object_set_options(INTERNAL_FUNCTION_PARAM_PASSTHRU);
 }
 
 PHP_METHOD(HttpClient, getOptions)
@@ -976,38 +1012,54 @@ PHP_METHOD(HttpClient, clearHistory)
        RETVAL_ZVAL(getThis(), 1, 0);
 }
 
-PHP_METHOD(HttpClient, getMessageClass)
+PHP_METHOD(HttpClient, getResponseMessageClass)
 {
        if (SUCCESS == zend_parse_parameters_none()) {
-               RETURN_PROP(php_http_client_class_entry, "messageClass");
+               RETURN_PROP(php_http_client_class_entry, "responseMessageClass");
        }
        RETURN_FALSE;
 }
 
-PHP_METHOD(HttpClient, setMessageClass)
+PHP_METHOD(HttpClient, setResponseMessageClass)
 {
        char *cn;
        int cl;
 
        if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &cn, &cl)) {
-               zend_update_property_stringl(php_http_client_class_entry, getThis(), ZEND_STRL("messageClass"), cn, cl TSRMLS_CC);
+               zend_update_property_stringl(php_http_client_class_entry, getThis(), ZEND_STRL("responseMessageClass"), cn, cl TSRMLS_CC);
        }
        RETVAL_ZVAL(getThis(), 1, 0);
 }
 
+PHP_METHOD(HttpClient, setRequest)
+{
+       zval *zreq = NULL;
+
+       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zreq, php_http_client_request_class_entry)) {
+               zend_update_property(php_http_client_class_entry, getThis(), ZEND_STRL("request"), zreq TSRMLS_CC);
+       }
+       RETURN_ZVAL(getThis(), 1, 0);
+}
+
+PHP_METHOD(HttpClient, getRequest)
+{
+       if (SUCCESS == zend_parse_parameters_none()) {
+               RETURN_PROP(php_http_client_class_entry, "request");
+       }
+}
+
 PHP_METHOD(HttpClient, send)
 {
-       zval *zreq;
+       zval *zreq = NULL;
 
        RETVAL_FALSE;
 
        with_error_handling(EH_THROW, php_http_exception_class_entry) {
-               if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zreq, php_http_client_request_class_entry)) {
-                       if (SUCCESS == php_http_client_object_handle_request(getThis(), zreq TSRMLS_CC)) {
+               if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O!", &zreq, php_http_client_request_class_entry)) {
+                       if (SUCCESS == php_http_client_object_handle_request(getThis(), &zreq TSRMLS_CC)) {
                                php_http_client_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
                                php_http_message_object_t *req = zend_object_store_get_object(zreq TSRMLS_CC);
 
-                               zend_update_property(php_http_client_class_entry, getThis(), ZEND_STRL("request"), zreq TSRMLS_CC);
                                php_http_client_exec(obj->client, req->message);
 
                                if (SUCCESS == php_http_client_object_handle_response(getThis() TSRMLS_CC)) {
@@ -1031,7 +1083,7 @@ PHP_MINIT_FUNCTION(http_client)
 
        zend_class_implements(php_http_client_class_entry TSRMLS_CC, 2, spl_ce_SplSubject, php_http_client_interface_class_entry);
 
-       zend_declare_property_string(php_http_client_class_entry, ZEND_STRL("messageClass"), "", ZEND_ACC_PRIVATE TSRMLS_CC);
+       zend_declare_property_string(php_http_client_class_entry, ZEND_STRL("responseMessageClass"), "", ZEND_ACC_PRIVATE TSRMLS_CC);
        zend_declare_property_null(php_http_client_class_entry, ZEND_STRL("observers"), ZEND_ACC_PRIVATE TSRMLS_CC);
        zend_declare_property_null(php_http_client_class_entry, ZEND_STRL("options"), ZEND_ACC_PRIVATE TSRMLS_CC);
        zend_declare_property_null(php_http_client_class_entry, ZEND_STRL("transferInfo"), ZEND_ACC_PRIVATE TSRMLS_CC);