* like array("header" => "value")
* - cookies: array, list of cookies as associative array
* like array("cookie" => "value")
+ * - encodecookies: bool, whether to urlencode the cookies (default: true)
+ * - resetcookies: bool, wheter to reset the cookies
* - cookiestore: string, path to a file where cookies are/will be stored
* - resume: int, byte offset to start the download from;
* if the server supports ranges
HTTP_BEGIN_ARGS(prepend, 1)
HTTP_ARG_OBJ(HttpMessage, message, 0)
HTTP_END_ARGS;
+HTTP_EMPTY_ARGS(reverse);
#define http_message_object_declare_default_properties() _http_message_object_declare_default_properties(TSRMLS_C)
static inline void _http_message_object_declare_default_properties(TSRMLS_D);
HTTP_MESSAGE_ME(detach, ZEND_ACC_PUBLIC)
HTTP_MESSAGE_ME(prepend, ZEND_ACC_PUBLIC)
+ HTTP_MESSAGE_ME(reverse, ZEND_ACC_PUBLIC)
EMPTY_FUNCTION_ENTRY
};
{
NO_ARGS {
long i;
- http_message *msg;
getObject(http_message_object, obj);
- for (i = 0, msg = obj->message; msg; msg = msg->parent, ++i);
+ http_message_count(i, obj->message);
RETURN_LONG(i);
}
}
}
/* }}} */
+/* {{{ proto HttpMessage HttpMessage::reverse()
+ *
+ * Reorders the message chain in reverse order.
+ *
+ * Returns the most parent HttpMessage object.
+ */
+PHP_METHOD(HttpMessage, reverse)
+{
+ int i;
+ getObject(http_message_object, obj);
+
+ NO_ARGS;
+
+ /* count */
+ http_message_count(i, obj->message);
+
+ if (i > 1) {
+ zval o;
+ zend_object_value *ovalues = NULL;
+ http_message_object **objects = NULL;
+ int last = i - 1;
+
+ objects = ecalloc(i, sizeof(http_message_object *));
+ ovalues = ecalloc(i, sizeof(zend_object_value));
+
+ /* we are the first message */
+ objects[0] = obj;
+ ovalues[0] = getThis()->value.obj;
+
+ /* fetch parents */
+ INIT_PZVAL(&o);
+ o.type = IS_OBJECT;
+ for (i = 1; obj->parent.handle; ++i) {
+ o.value.obj = obj->parent;
+ ovalues[i] = o.value.obj;
+ objects[i] = obj = zend_object_store_get_object(&o TSRMLS_CC);
+ }
+
+ /* reorder parents */
+ for (last = --i; i; --i) {
+ objects[i]->message->parent = objects[i-1]->message;
+ objects[i]->parent = ovalues[i-1];
+ }
+ objects[0]->message->parent = NULL;
+ objects[0]->parent.handle = 0;
+ objects[0]->parent.handlers = NULL;
+
+ /* add ref (why?) */
+ Z_OBJ_ADDREF_P(getThis());
+ RETVAL_OBJVAL(ovalues[last], 1);
+
+ efree(objects);
+ efree(ovalues);
+ } else {
+ RETURN_ZVAL(getThis(), 1, 0);
+ }
+}
+/* }}} */
+
/* {{{ proto void HttpMessage::rewind(void)
*
* Implements Iterator.
if ((zoption = http_request_option(request, options, "cookies", IS_ARRAY))) {
phpstr_dtor(&request->_cache.cookies);
if (zend_hash_num_elements(Z_ARRVAL_P(zoption))) {
- if (SUCCESS == http_urlencode_hash_recursive(HASH_OF(zoption), &request->_cache.cookies, "; ", sizeof("; ")-1, NULL, 0)) {
+ zval *urlenc_cookies = NULL;
+ /* check whether cookies should not be urlencoded; default is to urlencode them */
+ if ((!(urlenc_cookies = http_request_option(request, options, "encodecookies", IS_BOOL))) || Z_BVAL_P(urlenc_cookies)) {
+ if (SUCCESS == http_urlencode_hash_recursive(HASH_OF(zoption), &request->_cache.cookies, "; ", lenof("; "), NULL, 0)) {
+ phpstr_fix(&request->_cache.cookies);
+ HTTP_CURL_OPT(CURLOPT_COOKIE, request->_cache.cookies.data);
+ }
+ } else {
+ HashPosition pos;
+ zval *cookie_val = NULL;
+ char *cookie_key = NULL;
+ ulong cookie_idx;
+
+ FOREACH_KEY(pos, zoption, cookie_key, cookie_idx) {
+ if (cookie_key) {
+ zval **cookie_val;
+ if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_P(zoption), (void **) &cookie_val, &pos)) {
+ zval *val = zval_copy(IS_STRING, *cookie_val);
+ phpstr_appendf(&request->_cache.cookies, "%s=%s; ", cookie_key, Z_STRVAL_P(val));
+ zval_free(&val);
+ }
+
+ /* reset */
+ cookie_key = NULL;
+ }
+ }
+
phpstr_fix(&request->_cache.cookies);
- HTTP_CURL_OPT(CURLOPT_COOKIE, request->_cache.cookies.data);
+ if (PHPSTR_LEN(&request->_cache.cookies)) {
+ HTTP_CURL_OPT(CURLOPT_COOKIE, PHPSTR_VAL(&request->_cache.cookies));
+ }
}
}
}
return NULL;
}
+#define http_message_count(c, m) \
+{ \
+ http_message *__tmp_msg = (m); \
+ for (c = 0; __tmp_msg; __tmp_msg = __tmp_msg->parent, ++(c)); \
+}
+
#define http_message_parse(m, l) http_message_parse_ex(NULL, (m), (l))
#define http_message_parse_ex(h, m, l) _http_message_parse_ex((h), (m), (l) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC)
#define http_message_parse_rel(h, m, l) _http_message_parse_ex((h), (m), (l) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC TSRMLS_CC)
PHP_METHOD(HttpMessage, detach);
PHP_METHOD(HttpMessage, prepend);
+PHP_METHOD(HttpMessage, reverse);
#endif
#endif
--- /dev/null
+--TEST--
+HttpMessage::reverse()
+--SKIPIF--
+<?php
+include 'skip.inc';
+checkver(5);
+?>
+--FILE--
+<?php
+echo "-TEST\n";
+$s = "GET /first HTTP/1.1\nHTTP/1.1 200 Ok-first\nGET /second HTTP/1.1\nHTTP/1.1 200 Ok-second\nGET /third HTTP/1.1\nHTTP/1.1 200 Ok-third\n";
+echo HttpMessage::fromString($s)->toString(true);
+echo "===\n";
+echo HttpMessage::fromString($s)->reverse()->toString(true);
+
+$m = new HttpMessage($s);
+$r = $m->reverse();
+unset($m);
+var_dump($r->count());
+echo $r->toString(true);
+
+echo "Done\n";
+?>
+--EXPECTF--
+%sTEST
+GET /first HTTP/1.1
+HTTP/1.1 200 Ok-first
+GET /second HTTP/1.1
+HTTP/1.1 200 Ok-second
+GET /third HTTP/1.1
+HTTP/1.1 200 Ok-third
+===
+HTTP/1.1 200 Ok-third
+GET /third HTTP/1.1
+HTTP/1.1 200 Ok-second
+GET /second HTTP/1.1
+HTTP/1.1 200 Ok-first
+GET /first HTTP/1.1
+int(6)
+HTTP/1.1 200 Ok-third
+GET /third HTTP/1.1
+HTTP/1.1 200 Ok-second
+GET /second HTTP/1.1
+HTTP/1.1 200 Ok-first
+GET /first HTTP/1.1
+Done
--- /dev/null
+--TEST--
+urlencoded cookies
+--SKIPIF--
+<?php
+include 'skip.inc';
+checkver(5);
+skipif(!http_support(HTTP_SUPPORT_REQUESTS), "need request support");
+?>
+--FILE--
+<?php
+echo "-TEST\n";
+
+$cookies = array("name" => "val=ue");
+
+$r = new HttpRequest("http://dev.iworks.at/.print_request.php", HTTP_METH_GET, array("cookies" => $cookies));
+$r->recordHistory = true;
+$r->send();
+$r->setOptions(array('encodecookies' => false));
+$r->send();
+echo $r->getHistory()->toString(true);
+
+echo "Done\n";
+?>
+--EXPECTF--
+%sTEST
+HTTP/1.1 200 OK
+%s
+
+Array
+(
+ [name] => val=ue
+)
+
+GET /.print_request.php HTTP/1.1
+User-Agent: %s
+Host: dev.iworks.at
+Accept: */*
+Cookie: name=val%3Due
+HTTP/1.1 200 OK
+%s
+
+Array
+(
+ [name] => val=ue
+)
+
+GET /.print_request.php HTTP/1.1
+User-Agent: %s
+Host: dev.iworks.at
+Accept: */*
+Cookie: name=val=ue;
+Done