- add 'encodecookies' request option (defaults to true) and test
authorMichael Wallner <mike@php.net>
Fri, 10 Feb 2006 16:58:51 +0000 (16:58 +0000)
committerMichael Wallner <mike@php.net>
Fri, 10 Feb 2006 16:58:51 +0000 (16:58 +0000)
- add HttpMessage::reverse() and test

http_functions.c
http_message_object.c
http_request_api.c
php_http_message_api.h
php_http_message_object.h
tests/HttpMessage_007.phpt [new file with mode: 0644]
tests/request_cookies.phpt [new file with mode: 0644]

index 907ee92c5033643f0dd6b058bf3757af7bd820b3..225019dc52f26924d85e94be508e59ab51d372ad 100644 (file)
@@ -1207,6 +1207,8 @@ PHP_FUNCTION(http_match_request_header)
  *                      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
index d275004a3b7669cfa8820bfb6841243544c032f6..5345b26112a0540cf804b159de2d8c513c25612b 100644 (file)
@@ -121,6 +121,7 @@ HTTP_EMPTY_ARGS(detach);
 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);
@@ -176,6 +177,7 @@ zend_function_entry http_message_object_fe[] = {
        
        HTTP_MESSAGE_ME(detach, ZEND_ACC_PUBLIC)
        HTTP_MESSAGE_ME(prepend, ZEND_ACC_PUBLIC)
+       HTTP_MESSAGE_ME(reverse, ZEND_ACC_PUBLIC)
 
        EMPTY_FUNCTION_ENTRY
 };
@@ -1241,10 +1243,9 @@ PHP_METHOD(HttpMessage, count)
 {
        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);
        }
 }
@@ -1368,6 +1369,65 @@ PHP_METHOD(HttpMessage, prepend)
 }
 /* }}} */
 
+/* {{{ 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.
index 308212c5120a51646e6642679c1455ff796fc737..dc83d236fa83e38fcf7c9786673c7bb3367a024b 100644 (file)
@@ -650,9 +650,37 @@ PHP_HTTP_API STATUS _http_request_prepare(http_request *request, HashTable *opti
        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));
+                               }
                        }
                }
        }
index cf942567d371411cabcb44aef8781ae4611ccdd1..8e9084135792c197b393228cbc7bbf9ebf0a5070 100644 (file)
@@ -62,6 +62,12 @@ static inline zval *_http_message_header_ex(http_message *msg, char *key_str, si
        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)
index 62760f70111817cd9f81b6671d89e968d191dd50..3545b4542f26de2dd4f901e09cfce22b3fb52b63 100644 (file)
@@ -106,6 +106,7 @@ PHP_METHOD(HttpMessage, fromString);
 
 PHP_METHOD(HttpMessage, detach);
 PHP_METHOD(HttpMessage, prepend);
+PHP_METHOD(HttpMessage, reverse);
 
 #endif
 #endif
diff --git a/tests/HttpMessage_007.phpt b/tests/HttpMessage_007.phpt
new file mode 100644 (file)
index 0000000..f74e956
--- /dev/null
@@ -0,0 +1,46 @@
+--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
diff --git a/tests/request_cookies.phpt b/tests/request_cookies.phpt
new file mode 100644 (file)
index 0000000..ef99125
--- /dev/null
@@ -0,0 +1,52 @@
+--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