drop support for version2 cookies
authorgggeek <giunta.gaetano@gmail.com>
Wed, 25 Jan 2023 17:27:55 +0000 (17:27 +0000)
committergggeek <giunta.gaetano@gmail.com>
Wed, 25 Jan 2023 17:27:55 +0000 (17:27 +0000)
NEWS.md
src/Helper/Http.php

diff --git a/NEWS.md b/NEWS.md
index 5923099..727ec34 100644 (file)
--- a/NEWS.md
+++ b/NEWS.md
 
 * improved: the `XMLParser` accepts more options in its constructor (see phpdocs for details)
 
+* improved: dropped support for parsing cookie headers which follow the obsolete "version 2" specification
+
 * improved: removed usage of `extension_loaded` in favour of `function_exists` when checking for mbstring. This allows
   for mbstring functions to be polyfilled
 
index a10c64f..971ca42 100644 (file)
@@ -156,54 +156,47 @@ class Http
         $ar = preg_split("/\r?\n/", trim(substr($data, 0, $pos)));
 
         foreach ($ar as $line) {
-            // take care of multi-line headers and cookies
+            // take care of (multi-line) headers and cookies
             $arr = explode(':', $line, 2);
             if (count($arr) > 1) {
+                /// @todo according to https://www.rfc-editor.org/rfc/rfc7230#section-3.2.4, we should reject with error
+                ///       400 any messages where a space is present between the header name and colon
                 $headerName = strtolower(trim($arr[0]));
-                /// @todo some other headers (the ones that allow a CSV list of values) do allow many values to be
-                ///       passed using multiple header lines.
-                ///       We should add content to $xmlrpc->_xh['headers'][$headerName] instead of replacing it for those...
-                /// @todo should we drop support for rfc2965 (set-cookie2) cookies? It has been obsoleted since 2011
-                if ($headerName == 'set-cookie' || $headerName == 'set-cookie2') {
-                    if ($headerName == 'set-cookie2') {
-                        // version 2 cookies:
-                        // there could be many cookies on one line, comma separated
-                        $cookies = explode(',', $arr[1]);
+                if ($headerName == 'set-cookie') {
+                    $cookie = $arr[1];
+                    // glue together all received cookies, using a comma to separate them (same as php does with getallheaders())
+                    if (isset($httpResponse['headers'][$headerName])) {
+                        $httpResponse['headers'][$headerName] .= ', ' . trim($cookie);
                     } else {
-                        $cookies = array($arr[1]);
+                        $httpResponse['headers'][$headerName] = trim($cookie);
                     }
-                    foreach ($cookies as $cookie) {
-                        // glue together all received cookies, using a comma to separate them (same as php does with getallheaders())
-                        if (isset($httpResponse['headers'][$headerName])) {
-                            $httpResponse['headers'][$headerName] .= ', ' . trim($cookie);
-                        } else {
-                            $httpResponse['headers'][$headerName] = trim($cookie);
-                        }
-                        // parse cookie attributes, in case user wants to correctly honour them
-                        // feature creep: only allow rfc-compliant cookie attributes?
-                        // @todo support for server sending multiple time cookie with same name, but using different PATHs
-                        $cookie = explode(';', $cookie);
-                        foreach ($cookie as $pos => $val) {
-                            $val = explode('=', $val, 2);
-                            $tag = trim($val[0]);
-                            $val = isset($val[1]) ? trim($val[1]) : '';
-                            /// @todo with version 1 cookies, we should strip leading and trailing " chars
-                            if ($pos == 0) {
-                                $cookiename = $tag;
-                                $httpResponse['cookies'][$tag] = array();
-                                $httpResponse['cookies'][$cookiename]['value'] = urldecode($val);
-                            } else {
-                                if ($tag != 'value') {
-                                    $httpResponse['cookies'][$cookiename][$tag] = $val;
-                                }
+                    // parse cookie attributes, in case user wants to correctly honour them
+                    // @todo support for server sending multiple time cookie with same name, but using different PATHs
+                    $cookie = explode(';', $cookie);
+                    foreach ($cookie as $pos => $val) {
+                        $val = explode('=', $val, 2);
+                        $tag = trim($val[0]);
+                        $val = isset($val[1]) ? trim($val[1]) : '';
+                        if ($pos === 0) {
+                            $cookieName = $tag;
+                            // if present, we have strip leading and trailing " chars from $val
+                            if (preg_match('/^"(.*)"$/', $val, $matches)) {
+                                $val = $matches[1];
                             }
+                            $httpResponse['cookies'][$cookieName] = array('value' => urldecode($val));
+                        } else {
+                            $httpResponse['cookies'][$cookieName][$tag] = $val;
                         }
                     }
                 } else {
+                    /// @todo some other headers (the ones that allow a CSV list of values) do allow many values to be
+                    ///       passed using multiple header lines.
+                    ///       We should add content to $xmlrpc->_xh['headers'][$headerName] instead of replacing it for those...
                     $httpResponse['headers'][$headerName] = trim($arr[1]);
                 }
             } elseif (isset($headerName)) {
-                /// @todo version1 cookies might span multiple lines, thus breaking the parsing above
+                /// @todo improve this: 1. check that the line starts with a space or tab; 2. according to
+                ///       https://www.rfc-editor.org/rfc/rfc7230#section-3.2.4, we should flat out refuse these messages
                 $httpResponse['headers'][$headerName] .= ' ' . trim($line);
             }
         }