浏览代码

Fixing ZF-1850, ZF-5407: added option to not encode cookies, patch by Michael 'Ray' Rehbein

git-svn-id: http://framework.zend.com/svn/framework/standard/trunk@21018 44c647ce-9c0f-0410-b52a-842ac1e357ba
shahar 16 年之前
父节点
当前提交
c037c1fec4

+ 8 - 0
documentation/manual/en/module_specs/Zend_Http_Client.xml

@@ -170,6 +170,14 @@ $client->setConfig($config);
                             <entry>boolean</entry>
                             <entry><constant>TRUE</constant></entry>
                         </row>
+                        <row>
+                            <entry>encodecookies</entry>
+                            <entry>Whether to pass the cookie value through urlencode/urldecode.
+                            Enabling this breaks support with some web servers.
+                            Disabling this limits the range of values the cookies can contain.</entry>
+                            <entry>boolean</entry>
+                            <entry><constant>TRUE</constant></entry>
+                        </row>
                     </tbody>
                 </tgroup>
             </table>

+ 25 - 1
documentation/manual/en/module_specs/Zend_Http_Cookie-Handling.xml

@@ -95,13 +95,37 @@
 
                 <listitem>
                     <para>
-                        By calling the fromString() static method, with a cookie string as
+                        By calling the fromString($cookieStr, [$refUri, [$encodeValue]]) static method, , with a cookie string as
                         represented in the 'Set-Cookie' <acronym>HTTP</acronym> response header or
                         'Cookie' <acronym>HTTP</acronym> request header. In this case, the cookie
                         value must already be encoded. When the cookie string does not contain a
                         'domain' part, you must provide a reference <acronym>URI</acronym> according
                         to which the cookie's domain and path will be set.
                     </para>
+                    <para>
+                        The <code>fromString</code> method accepts the following parameters:
+                    </para>
+                    <itemizedlist>
+                        <listitem>
+                            <para>
+                            <varname>$cookieStr</varname>: a cookie string as represented in the
+                           'Set-Cookie' <acronym>HTTP</acronym> response header or 'Cookie' 
+                           <acronym>HTTP</acronym> request header (required)
+                            </para>
+                        </listitem>
+                        <listitem>
+                            <para>
+                            <varname>$refUri</varname>: a reference <acronym>URI</acronym> according to which the cookie's domain and path
+                            will be set. (optional, defaults to parsing the value from the $cookieStr)
+                            </para>
+                        </listitem>
+                        <listitem>
+                            <para>
+                            <varname>$encodeValue</varname>: If the value should be passed through urldecode. Also effects the cookie's
+                            behavior when being converted back to a cookie string. (optional, defaults to true)
+                            </para>
+                        </listitem>
+                    </itemizedlist>
                 </listitem>
             </itemizedlist>
 

+ 6 - 3
library/Zend/Http/Client.php

@@ -117,7 +117,8 @@ class Zend_Http_Client
         'keepalive'       => false,
         'storeresponse'   => true,
         'strict'          => true,
-        'output_stream'	  => false,
+        'output_stream'   => false,
+        'encodecookies'   => true,
     );
 
     /**
@@ -640,7 +641,7 @@ class Zend_Http_Client
             return $this;
         }
 
-        if ($value !== null) {
+        if ($value !== null && $this->config['encodecookies']) {
             $value = urlencode($value);
         }
 
@@ -648,7 +649,9 @@ class Zend_Http_Client
             if ($cookie instanceof Zend_Http_Cookie) {
                 $this->cookiejar->addCookie($cookie);
             } elseif (is_string($cookie) && $value !== null) {
-                $cookie = Zend_Http_Cookie::fromString("{$cookie}={$value}", $this->uri);
+                $cookie = Zend_Http_Cookie::fromString("{$cookie}={$value}",
+                                                       $this->uri,
+                                                       $this->config['encodecookies']);
                 $this->cookiejar->addCookie($cookie);
             }
         } else {

+ 26 - 10
library/Zend/Http/Cookie.php

@@ -89,6 +89,13 @@ class Zend_Http_Cookie
     protected $secure;
 
     /**
+     * Whether the cookie value has been encoded/decoded
+     *
+     * @var boolean
+     */
+    protected $encodeValue;
+
+    /**
      * Cookie object constructor
      *
      * @todo Add validation of each one of the parameters (legal domain, etc.)
@@ -258,7 +265,10 @@ class Zend_Http_Cookie
      */
     public function __toString()
     {
-        return $this->name . '=' . urlencode($this->value) . ';';
+        if ($this->encodeValue) {
+            return $this->name . '=' . urlencode($this->value) . ';';
+        }
+        return $this->name . '=' . $this->value . ';';
     }
 
     /**
@@ -266,14 +276,16 @@ class Zend_Http_Cookie
      * (for example the value of the Set-Cookie HTTP header)
      *
      * @param string $cookieStr
-     * @param Zend_Uri_Http|string $ref_uri Reference URI for default values (domain, path)
+     * @param Zend_Uri_Http|string $refUri Reference URI for default values (domain, path)
+     * @param boolean $encodeValue Weither or not the cookie's value should be
+     *                             passed through urlencode/urldecode
      * @return Zend_Http_Cookie A new Zend_Http_Cookie object or false on failure.
      */
-    public static function fromString($cookieStr, $ref_uri = null)
+    public static function fromString($cookieStr, $refUri = null, $encodeValue = true)
     {
         // Set default values
-        if (is_string($ref_uri)) {
-            $ref_uri = Zend_Uri_Http::factory($ref_uri);
+        if (is_string($refUri)) {
+            $refUri = Zend_Uri_Http::factory($refUri);
         }
 
         $name    = '';
@@ -290,12 +302,14 @@ class Zend_Http_Cookie
         // Get the name and value of the cookie
         list($name, $value) = explode('=', trim(array_shift($parts)), 2);
         $name  = trim($name);
-        $value = urldecode(trim($value));
+        if ($encodeValue) {
+            $value = urldecode(trim($value));
+        }
 
         // Set default domain and path
-        if ($ref_uri instanceof Zend_Uri_Http) {
-            $domain = $ref_uri->getHost();
-            $path = $ref_uri->getPath();
+        if ($refUri instanceof Zend_Uri_Http) {
+            $domain = $refUri->getHost();
+            $path = $refUri->getPath();
             $path = substr($path, 0, strrpos($path, '/'));
         }
 
@@ -342,7 +356,9 @@ class Zend_Http_Cookie
         }
 
         if ($name !== '') {
-            return new self($name, $value, $domain, $expires, $path, $secure);
+            $ret = new self($name, $value, $domain, $expires, $path, $secure);
+            $ret->encodeValue = ($encodeValue) ? true : false;
+            return $ret;
         } else {
             return false;
         }

+ 2 - 1
tests/Zend/Http/Client/StaticTest.php

@@ -608,7 +608,8 @@ class Zend_Http_Client_StaticTest_Mock extends Zend_Http_Client
         'keepalive'       => false,
         'storeresponse'   => true,
         'strict'          => true,
-        'output_stream'	  => false,
+        'output_stream'   => false,
+        'encodecookies'   => true,
     );
 }
 

+ 43 - 0
tests/Zend/Http/CookieTest.php

@@ -93,6 +93,48 @@ class Zend_Http_CookieTest extends PHPUnit_Framework_TestCase
     }
 
     /**
+     * Make sure we get the correct value if it was set through fromString()
+     *
+     * @param        string $value
+     * @dataProvider validCookieValueProvider
+     */
+    public function testGetRawValueFromString($val)
+    {
+        // Because ';' has special meaning in the cookie, strip it out for this test.
+        $val = str_replace(';', '', $val);
+        $cookie = Zend_Http_Cookie::fromString('cookie=' . $val . '; domain=example.com', null, false);
+        $this->assertEquals($val, $cookie->getValue());
+    }
+
+    /**
+     * Make sure we get the correct value if it was set through fromString()
+     *
+     * @param        string $value
+     * @dataProvider validCookieValueProvider
+     */
+    public function testGetRawValueFromStringToString($val)
+    {
+        // Because ';' has special meaning in the cookie, strip it out for this test.
+        $val = str_replace(';', '', $val);
+        $cookie = Zend_Http_Cookie::fromString('cookie=' . $val . '; domain=example.com', null, false);
+        $this->assertEquals('cookie=' . $val . ';', (string)$cookie);
+    }
+
+    /**
+     * Make sure we get the correct value if it was set through fromString()
+     *
+     * @param        string $value
+     * @dataProvider validCookieValueProvider
+     */
+    public function testGetValueFromStringEncodedToString($val)
+    {
+        // Because ';' has special meaning in the cookie, strip it out for this test.
+        $val = str_replace(';', '', $val);
+        $cookie = Zend_Http_Cookie::fromString('cookie=' . $val . '; domain=example.com', null, true);
+        $this->assertEquals('cookie=' . urlencode($val) . ';', (string)$cookie);
+    }
+
+    /**
      * Make sure we get the correct domain when it's set in the cookie string
      *
      * @dataProvider validCookieWithInfoProvider
@@ -443,6 +485,7 @@ class Zend_Http_CookieTest extends PHPUnit_Framework_TestCase
             array('space cookie'),
             array('!@#$%^*&()* ][{}?;'),
             array("line\n\rbreaks"),
+            array("0000j8CydACPu_-J9bE8uTX91YU:12a83ks4k"), // value from: Alexander Cheshchevik's comment on issue: ZF-1850
 
             // Long cookie value - 2kb
             array(str_repeat(md5(time()), 64))