|  | 
|  | 1 | +<?php | 
|  | 2 | + | 
|  | 3 | +/* | 
|  | 4 | + * (c) Fabien Potencier <[email protected]> | 
|  | 5 | + * | 
|  | 6 | + * For the full copyright and license information, please view the LICENSE | 
|  | 7 | + * file that was distributed with this source code. | 
|  | 8 | + */ | 
|  | 9 | + | 
|  | 10 | +namespace FriendsOfPHP\WellKnownImplementations\Internal; | 
|  | 11 | + | 
|  | 12 | +use FriendsOfPHP\WellKnownImplementations\WellKnownPsr7Stream; | 
|  | 13 | +use FriendsOfPHP\WellKnownImplementations\WellKnownPsr7UploadedFile; | 
|  | 14 | +use Psr\Http\Message\ServerRequestInterface; | 
|  | 15 | +use Psr\Http\Message\UploadedFileInterface; | 
|  | 16 | +use Psr\Http\Message\UriInterface; | 
|  | 17 | + | 
|  | 18 | +/** | 
|  | 19 | + * Helps provide portability accross PSR-7 implementations. | 
|  | 20 | + * | 
|  | 21 | + * The code in this class is inspired by the "nyholm/psr7", "guzzlehttp/psr7" | 
|  | 22 | + * and "symfony/http-foundation" packages, all licenced under MIT. | 
|  | 23 | + * | 
|  | 24 | + * Copyright (c) 2015 Michael Dowling <[email protected]> | 
|  | 25 | + * Copyright (c) 2015 Márk Sági-Kazár <[email protected]> | 
|  | 26 | + * Copyright (c) 2015 Graham Campbell <[email protected]> | 
|  | 27 | + * Copyright (c) 2016 Tobias Schultze <[email protected]> | 
|  | 28 | + * Copyright (c) 2016 George Mponos <[email protected]> | 
|  | 29 | + * Copyright (c) 2016-2018 Tobias Nyholm <[email protected]> | 
|  | 30 | + * | 
|  | 31 | + * @internal | 
|  | 32 | + */ | 
|  | 33 | +class Psr7Helper | 
|  | 34 | +{ | 
|  | 35 | +    /** | 
|  | 36 | +     * @param string|resource $content | 
|  | 37 | +     * | 
|  | 38 | +     * @return resource | 
|  | 39 | +     */ | 
|  | 40 | +    public static function toResource($content, ?string $mode) | 
|  | 41 | +    { | 
|  | 42 | +        if (\is_resource($content)) { | 
|  | 43 | +            return $content; | 
|  | 44 | +        } | 
|  | 45 | + | 
|  | 46 | +        if (null === $mode) { | 
|  | 47 | +            $h = fopen('php://temp', 'r+'); | 
|  | 48 | +            fwrite($h, $content); | 
|  | 49 | +            rewind($h); | 
|  | 50 | + | 
|  | 51 | +            return $h; | 
|  | 52 | +        } | 
|  | 53 | + | 
|  | 54 | +        if ('' === $content) { | 
|  | 55 | +            throw new \RuntimeException('Path cannot be empty'); | 
|  | 56 | +        } | 
|  | 57 | + | 
|  | 58 | +        if (false === $h = @fopen($content, $mode)) { | 
|  | 59 | +            if ('' === $mode || false === \in_array($mode[0], ['r', 'w', 'a', 'x', 'c'], true)) { | 
|  | 60 | +                throw new \InvalidArgumentException(sprintf('The mode "%s" is invalid.', $mode)); | 
|  | 61 | +            } | 
|  | 62 | + | 
|  | 63 | +            throw new \RuntimeException(sprintf('The file "%s" cannot be opened: %s', $content, error_get_last()['message'] ?? '')); | 
|  | 64 | +        } | 
|  | 65 | + | 
|  | 66 | +        return $h; | 
|  | 67 | +    } | 
|  | 68 | + | 
|  | 69 | +    public static function buildServerRequestFromGlobals(ServerRequestInterface $request, array $server, array $files): ServerRequestInterface | 
|  | 70 | +    { | 
|  | 71 | +        $request = $request | 
|  | 72 | +            ->withProtocolVersion(isset($server['SERVER_PROTOCOL']) ? str_replace('HTTP/', '', $server['SERVER_PROTOCOL']) : '1.1') | 
|  | 73 | +            ->withUploadedFiles(self::normalizeFiles($files)); | 
|  | 74 | + | 
|  | 75 | +        $headers = []; | 
|  | 76 | +        foreach ($server as $key => $value) { | 
|  | 77 | +            if (0 === strpos($key, 'HTTP_')) { | 
|  | 78 | +                $key = substr($key, 5); | 
|  | 79 | +            } elseif (!\in_array($key, ['CONTENT_TYPE', 'CONTENT_LENGTH', 'CONTENT_MD5'], true)) { | 
|  | 80 | +                continue; | 
|  | 81 | +            } | 
|  | 82 | +            $key = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $key)))); | 
|  | 83 | + | 
|  | 84 | +            $headers[$key] = $value; | 
|  | 85 | +        } | 
|  | 86 | + | 
|  | 87 | +        if (!isset($headers['Authorization'])) { | 
|  | 88 | +            if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) { | 
|  | 89 | +                $headers['Authorization'] = $_SERVER['REDIRECT_HTTP_AUTHORIZATION']; | 
|  | 90 | +            } elseif (isset($_SERVER['PHP_AUTH_USER'])) { | 
|  | 91 | +                $headers['Authorization'] = 'Basic '.base64_encode($_SERVER['PHP_AUTH_USER'].':'.($_SERVER['PHP_AUTH_PW'] ?? '')); | 
|  | 92 | +            } elseif (isset($_SERVER['PHP_AUTH_DIGEST'])) { | 
|  | 93 | +                $headers['Authorization'] = $_SERVER['PHP_AUTH_DIGEST']; | 
|  | 94 | +            } | 
|  | 95 | +        } | 
|  | 96 | + | 
|  | 97 | +        foreach ($headers as $key => $value) { | 
|  | 98 | +            try { | 
|  | 99 | +                $request = $request->withHeader($key, $value); | 
|  | 100 | +            } catch (\InvalidArgumentException $e) { | 
|  | 101 | +                // ignore invalid headers | 
|  | 102 | +            } | 
|  | 103 | + | 
|  | 104 | +        } | 
|  | 105 | + | 
|  | 106 | +        return $request; | 
|  | 107 | +    } | 
|  | 108 | + | 
|  | 109 | +    public static function buildUriFromGlobals(UriInterface $uri, array $server): UriInterface | 
|  | 110 | +    { | 
|  | 111 | +        $uri = $uri->withScheme(!empty($server['HTTPS']) && 'off' !== strtolower($server['HTTPS']) ? 'https' : 'http'); | 
|  | 112 | + | 
|  | 113 | +        $hasPort = false; | 
|  | 114 | +        if (isset($server['HTTP_HOST'])) { | 
|  | 115 | +            $parts = parse_url('http://'.$server['HTTP_HOST']); | 
|  | 116 | + | 
|  | 117 | +            if ($parts['host'] ?? false) { | 
|  | 118 | +                $uri = $uri->withHost($parts['host']); | 
|  | 119 | +            } | 
|  | 120 | + | 
|  | 121 | +            if ($parts['port'] ?? false) { | 
|  | 122 | +                $hasPort = true; | 
|  | 123 | +                $uri = $uri->withPort($parts['port']); | 
|  | 124 | +            } | 
|  | 125 | +        } elseif (isset($server['SERVER_NAME'])) { | 
|  | 126 | +            $uri = $uri->withHost($server['SERVER_NAME']); | 
|  | 127 | +        } elseif (isset($server['SERVER_ADDR'])) { | 
|  | 128 | +            $uri = $uri->withHost($server['SERVER_ADDR']); | 
|  | 129 | +        } | 
|  | 130 | + | 
|  | 131 | +        if (!$hasPort && isset($server['SERVER_PORT'])) { | 
|  | 132 | +            $uri = $uri->withPort($server['SERVER_PORT']); | 
|  | 133 | +        } | 
|  | 134 | + | 
|  | 135 | +        $hasQuery = false; | 
|  | 136 | +        if (isset($server['REQUEST_URI'])) { | 
|  | 137 | +            $requestUriParts = explode('?', $server['REQUEST_URI'], 2); | 
|  | 138 | +            $uri = $uri->withPath($requestUriParts[0]); | 
|  | 139 | +            if (isset($requestUriParts[1])) { | 
|  | 140 | +                $hasQuery = true; | 
|  | 141 | +                $uri = $uri->withQuery($requestUriParts[1]); | 
|  | 142 | +            } | 
|  | 143 | +        } | 
|  | 144 | + | 
|  | 145 | +        if (!$hasQuery && isset($server['QUERY_STRING'])) { | 
|  | 146 | +            $uri = $uri->withQuery($server['QUERY_STRING']); | 
|  | 147 | +        } | 
|  | 148 | + | 
|  | 149 | +        return $uri; | 
|  | 150 | +    } | 
|  | 151 | + | 
|  | 152 | +    public static function normalizeFiles(array $files): array | 
|  | 153 | +    { | 
|  | 154 | +        $normalized = []; | 
|  | 155 | + | 
|  | 156 | +        foreach ($files as $key => $value) { | 
|  | 157 | +            if ($value instanceof UploadedFileInterface) { | 
|  | 158 | +                $normalized[$key] = $value; | 
|  | 159 | +            } elseif (!\is_array($value)) { | 
|  | 160 | +                continue; | 
|  | 161 | +            } elseif (!isset($value['tmp_name'])) { | 
|  | 162 | +                $normalized[$key] = self::normalizeFiles($value); | 
|  | 163 | +            } elseif (\is_array($value['tmp_name'])) { | 
|  | 164 | +                foreach ($value['tmp_name'] as $k => $v) { | 
|  | 165 | +                    $file = new WellKnownPsr7Stream($value['tmp_name'][$k], 'r'); | 
|  | 166 | +                    $normalized[$key][$k] = new WellKnownPsr7UploadedFile($file, $value['size'][$k], $value['error'][$k], $value['name'][$k], $value['type'][$k]); | 
|  | 167 | +                } | 
|  | 168 | +            } else { | 
|  | 169 | +                $file = new WellKnownPsr7Stream($value['tmp_name'], 'r'); | 
|  | 170 | +                $normalized[$key] = new WellKnownPsr7UploadedFile($file, $value['size'], $value['error'], $value['name'], $value['type']); | 
|  | 171 | +            } | 
|  | 172 | +        } | 
|  | 173 | + | 
|  | 174 | +        return $normalized; | 
|  | 175 | +    } | 
|  | 176 | +} | 
0 commit comments