/*
- +----------------------------------------------------------------------+
- | 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$ */
#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"
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);
#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[] = {
};
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 = _http_request_object_clone_obj;
+ return SUCCESS;
}
zend_object_value _http_request_object_new(zend_class_entry *ce TSRMLS_DC)
+{
+ return http_request_object_new_ex(ce, curl_easy_init(), NULL);
+}
+
+zend_object_value _http_request_object_new_ex(zend_class_entry *ce, CURL *ch, http_request_object **ptr TSRMLS_DC)
{
zend_object_value ov;
http_request_object *o;
o = ecalloc(1, sizeof(http_request_object));
o->zo.ce = ce;
- o->ch = curl_easy_init();
+ o->ch = ch;
+
+ if (ptr) {
+ *ptr = o;
+ }
phpstr_init(&o->history);
phpstr_init(&o->request);
return ov;
}
+zend_object_value _http_request_object_clone_obj(zval *this_ptr TSRMLS_DC)
+{
+ zend_object *old_zo;
+ zend_object_value new_ov;
+ http_request_object *new_obj;
+ getObject(http_request_object, old_obj);
+
+ old_zo = zend_objects_get_address(this_ptr TSRMLS_CC);
+ new_ov = http_request_object_new_ex(old_zo->ce, curl_easy_duphandle(old_obj->ch), &new_obj);
+
+ zend_objects_clone_members(&new_obj->zo, new_ov, old_zo, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC);
+ phpstr_append(&new_obj->history, old_obj->history.data, old_obj->history.used);
+ phpstr_append(&new_obj->request, old_obj->request.data, old_obj->request.used);
+ phpstr_append(&new_obj->response, old_obj->response.data, old_obj->response.used);
+
+ return new_ov;
+}
+
static inline void _http_request_object_declare_default_properties(TSRMLS_D)
{
zend_class_entry *ce = http_request_object_ce;
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)));
*resp = convert_to_type(IS_ARRAY, GET_PROP(obj, responseData)),
*info = convert_to_type(IS_ARRAY, GET_PROP(obj, responseInfo));
+ SEP_PROP(&resp);
+ SEP_PROP(&info);
+
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
add_assoc_zval(resp, "headers", headers);
add_assoc_stringl(resp, "body", body, body_len, 0);
+ SET_PROP(obj, responseData, resp);
MAKE_STD_ZVAL(message);
- ZVAL_OBJVAL(message, http_message_object_from_msg(msg));
+ ZVAL_OBJVAL(message, http_message_object_new_ex(http_message_object_ce, msg, NULL));
SET_PROP(obj, responseMessage, message);
zval_ptr_dtor(&message);
}
}
} 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);
}
/* ### 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.
*/
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);
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();
}
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;
}
old_opts = convert_to_type(IS_ARRAY, GET_PROP(obj, options));
-
+ SEP_PROP(&old_opts);
+
if (!opts || !zend_hash_num_elements(Z_ARRVAL_P(opts))) {
zend_hash_clean(Z_ARRVAL_P(old_opts));
+ SET_PROP(obj, options, 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;
} 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;
} 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;
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;
}
}
post = convert_to_type(IS_ARRAY, GET_PROP(obj, postFields));
- zend_hash_clean(Z_ARRVAL_P(post));
+ SEP_PROP(&post);
+ zend_hash_clean(Z_ARRVAL_P(post));
if (post_data && zend_hash_num_elements(Z_ARRVAL_P(post_data))) {
array_copy(post_data, post);
}
+ SET_PROP(obj, postFields, post);
RETURN_TRUE;
}
}
pFiles = convert_to_type(IS_ARRAY, GET_PROP(obj, postFiles));
- zend_hash_clean(Z_ARRVAL_P(pFiles));
+ SEP_PROP(&pFiles);
+ zend_hash_clean(Z_ARRVAL_P(pFiles));
if (files && zend_hash_num_elements(Z_ARRVAL_P(files))) {
array_copy(files, pFiles);
}
+ SET_PROP(obj, postFiles, pFiles);
RETURN_TRUE;
}
SET_EH_THROW_HTTP();
if (msg = http_message_parse(PHPSTR_VAL(&obj->request), PHPSTR_LEN(&obj->request))) {
- RETVAL_OBJVAL(http_message_object_from_msg(msg));
+ RETVAL_OBJVAL(http_message_object_new_ex(http_message_object_ce, msg, NULL));
}
SET_EH_NORMAL();
}
SET_EH_THROW_HTTP();
if (msg = http_message_parse(PHPSTR_VAL(&obj->history), PHPSTR_LEN(&obj->history))) {
- RETVAL_OBJVAL(http_message_object_from_msg(msg));
+ RETVAL_OBJVAL(http_message_object_new_ex(http_message_object_ce, msg, NULL));
}
SET_EH_NORMAL();
}