Merge branch '5.4' into 5.5
authorTim Düsterhus <duesterhus@woltlab.com>
Fri, 3 Jun 2022 10:08:33 +0000 (12:08 +0200)
committerTim Düsterhus <duesterhus@woltlab.com>
Fri, 3 Jun 2022 10:08:33 +0000 (12:08 +0200)
1  2 
wcfsetup/install/files/lib/system/request/RequestHandler.class.php

index 74a676b1aad5bee58c07e1b15f4ba4ecd8b7750e,ce60de99787e481605f2cdd48a1e0f8308f99847..329db08bcd408e03930d56e27033a4eb3ce998a6
@@@ -129,90 -139,6 +129,89 @@@ class RequestHandler extends SingletonF
          }
      }
  
 +    /**
 +     * Splits the given array of cache-control values at commas, while properly
 +     * taking into account that each value might itself contain commas within a
 +     * quoted string.
 +     */
 +    private function splitCacheControl(array $values): \Iterator
 +    {
 +        foreach ($values as $value) {
 +            $isQuoted = false;
 +            $result = '';
 +
 +            for ($i = 0, $len = \strlen($value); $i < $len; $i++) {
 +                $char = $value[$i];
 +                if (!$isQuoted && $char === ',') {
 +                    yield \trim($result);
 +
 +                    $isQuoted = false;
 +                    $result = '';
 +
 +                    continue;
 +                }
 +
 +                if ($isQuoted && $char === '\\') {
 +                    $result .= $char;
 +                    $i++;
 +
 +                    if ($i < $len) {
 +                        $result .= $value[$i];
 +
 +                        continue;
 +                    }
 +                }
 +
 +                if ($char === '"') {
 +                    $isQuoted = !$isQuoted;
 +                }
 +
 +                $result .= $char;
 +            }
 +
 +            if ($result !== '') {
 +                yield \trim($result);
 +            }
 +        }
 +    }
 +
 +    /**
 +     * @since 5.5
 +     */
 +    private function sendPsr7Response(ResponseInterface $response)
 +    {
 +        // Storing responses in a shared cache is unsafe, because they all contain session specific information.
 +        // Add the 'private' value to the cache-control header and remove any 'public' value.
 +        $cacheControl = [
 +            'private',
 +        ];
 +        foreach ($this->splitCacheControl($response->getHeader('cache-control')) as $value) {
 +            [$field] = \explode('=', $value, 2);
 +
 +            // Prevent duplication of the 'private' field.
 +            if ($field === 'private') {
 +                continue;
 +            }
 +
 +            // Drop the 'public' field.
 +            if ($field === 'public') {
 +                continue;
 +            }
 +
 +            $cacheControl[] = $value;
 +        }
 +
 +        $response = $response->withHeader(
 +            'cache-control',
 +            // Manually imploding the fields is not required as per strict reading of the HTTP standard,
 +            // but having duplicate 'cache-control' headers in the response certainly looks odd.
 +            \implode(', ', $cacheControl)
 +        );
 +
 +        $emitter = new SapiEmitter();
 +        $emitter->emit($response);
 +    }
 +
      /**
       * Builds a new request.
       *