PluginProbe
Media Cloud Sync / 1.3.11
Media Cloud Sync v1.3.11
1.4.1 1.4.0 1.3.12 1.3.11 1.3.10 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.2.0 1.2.10 1.2.11 1.2.12 1.2.13 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 All 35 releases
media-cloud-sync / includes / sdk / s3 / GuzzleHttp / Psr7 / MessageTrait.php

MessageTrait.php in Media Cloud Sync 1.3.11, at includes/sdk/s3/GuzzleHttp/Psr7/MessageTrait.php

210 lines 7.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare (strict_types=1);
4 namespace Dudlewebs\WPMCS\s3\GuzzleHttp\Psr7;
5
6 use Dudlewebs\WPMCS\s3\Psr\Http\Message\MessageInterface;
7 use Dudlewebs\WPMCS\s3\Psr\Http\Message\StreamInterface;
8 /**
9 * Trait implementing functionality common to requests and responses.
10 */
11 trait MessageTrait
12 {
13 /** @var string[][] Map of all registered headers, as original name => array of values */
14 private $headers = [];
15 /** @var string[] Map of lowercase header name => original name at registration */
16 private $headerNames = [];
17 /** @var string */
18 private $protocol = '1.1';
19 /** @var StreamInterface|null */
20 private $stream;
21 public function getProtocolVersion() : string
22 {
23 return $this->protocol;
24 }
25 public function withProtocolVersion($version) : MessageInterface
26 {
27 if ($this->protocol === $version) {
28 return $this;
29 }
30 $new = clone $this;
31 $new->protocol = $version;
32 return $new;
33 }
34 public function getHeaders() : array
35 {
36 return $this->headers;
37 }
38 public function hasHeader($header) : bool
39 {
40 return isset($this->headerNames[\strtolower($header)]);
41 }
42 public function getHeader($header) : array
43 {
44 $header = \strtolower($header);
45 if (!isset($this->headerNames[$header])) {
46 return [];
47 }
48 $header = $this->headerNames[$header];
49 return $this->headers[$header];
50 }
51 public function getHeaderLine($header) : string
52 {
53 return \implode(', ', $this->getHeader($header));
54 }
55 public function withHeader($header, $value) : MessageInterface
56 {
57 $this->assertHeader($header);
58 $value = $this->normalizeHeaderValue($value);
59 $normalized = \strtolower($header);
60 $new = clone $this;
61 if (isset($new->headerNames[$normalized])) {
62 unset($new->headers[$new->headerNames[$normalized]]);
63 }
64 $new->headerNames[$normalized] = $header;
65 $new->headers[$header] = $value;
66 return $new;
67 }
68 public function withAddedHeader($header, $value) : MessageInterface
69 {
70 $this->assertHeader($header);
71 $value = $this->normalizeHeaderValue($value);
72 $normalized = \strtolower($header);
73 $new = clone $this;
74 if (isset($new->headerNames[$normalized])) {
75 $header = $this->headerNames[$normalized];
76 $new->headers[$header] = \array_merge($this->headers[$header], $value);
77 } else {
78 $new->headerNames[$normalized] = $header;
79 $new->headers[$header] = $value;
80 }
81 return $new;
82 }
83 public function withoutHeader($header) : MessageInterface
84 {
85 $normalized = \strtolower($header);
86 if (!isset($this->headerNames[$normalized])) {
87 return $this;
88 }
89 $header = $this->headerNames[$normalized];
90 $new = clone $this;
91 unset($new->headers[$header], $new->headerNames[$normalized]);
92 return $new;
93 }
94 public function getBody() : StreamInterface
95 {
96 if (!$this->stream) {
97 $this->stream = Utils::streamFor('');
98 }
99 return $this->stream;
100 }
101 public function withBody(StreamInterface $body) : MessageInterface
102 {
103 if ($body === $this->stream) {
104 return $this;
105 }
106 $new = clone $this;
107 $new->stream = $body;
108 return $new;
109 }
110 /**
111 * @param (string|string[])[] $headers
112 */
113 private function setHeaders(array $headers) : void
114 {
115 $this->headerNames = $this->headers = [];
116 foreach ($headers as $header => $value) {
117 // Numeric array keys are converted to int by PHP.
118 $header = (string) $header;
119 $this->assertHeader($header);
120 $value = $this->normalizeHeaderValue($value);
121 $normalized = \strtolower($header);
122 if (isset($this->headerNames[$normalized])) {
123 $header = $this->headerNames[$normalized];
124 $this->headers[$header] = \array_merge($this->headers[$header], $value);
125 } else {
126 $this->headerNames[$normalized] = $header;
127 $this->headers[$header] = $value;
128 }
129 }
130 }
131 /**
132 * @param mixed $value
133 *
134 * @return string[]
135 */
136 private function normalizeHeaderValue($value) : array
137 {
138 if (!\is_array($value)) {
139 return $this->trimAndValidateHeaderValues([$value]);
140 }
141 return $this->trimAndValidateHeaderValues($value);
142 }
143 /**
144 * Trims whitespace from the header values.
145 *
146 * Spaces and tabs ought to be excluded by parsers when extracting the field value from a header field.
147 *
148 * header-field = field-name ":" OWS field-value OWS
149 * OWS = *( SP / HTAB )
150 *
151 * @param mixed[] $values Header values
152 *
153 * @return string[] Trimmed header values
154 *
155 * @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.4
156 */
157 private function trimAndValidateHeaderValues(array $values) : array
158 {
159 return \array_map(function ($value) {
160 if (!\is_scalar($value) && null !== $value) {
161 throw new \InvalidArgumentException(\sprintf('Header value must be scalar or null but %s provided.', \is_object($value) ? \get_class($value) : \gettype($value)));
162 }
163 $trimmed = \trim((string) $value, " \t");
164 $this->assertValue($trimmed);
165 return $trimmed;
166 }, \array_values($values));
167 }
168 /**
169 * @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2
170 *
171 * @param mixed $header
172 */
173 private function assertHeader($header) : void
174 {
175 if (!\is_string($header)) {
176 throw new \InvalidArgumentException(\sprintf('Header name must be a string but %s provided.', \is_object($header) ? \get_class($header) : \gettype($header)));
177 }
178 if (!\preg_match('/^[a-zA-Z0-9\'`#$%&*+.^_|~!-]+$/D', $header)) {
179 throw new \InvalidArgumentException(\sprintf('"%s" is not valid header name.', $header));
180 }
181 }
182 /**
183 * @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2
184 *
185 * field-value = *( field-content / obs-fold )
186 * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
187 * field-vchar = VCHAR / obs-text
188 * VCHAR = %x21-7E
189 * obs-text = %x80-FF
190 * obs-fold = CRLF 1*( SP / HTAB )
191 */
192 private function assertValue(string $value) : void
193 {
194 // The regular expression intentionally does not support the obs-fold production, because as
195 // per RFC 7230#3.2.4:
196 //
197 // A sender MUST NOT generate a message that includes
198 // line folding (i.e., that has any field-value that contains a match to
199 // the obs-fold rule) unless the message is intended for packaging
200 // within the message/http media type.
201 //
202 // Clients must not send a request with line folding and a server sending folded headers is
203 // likely very rare. Line folding is a fairly obscure feature of HTTP/1.1 and thus not accepting
204 // folding is not likely to break any legitimate use case.
205 if (!\preg_match('/^[\\x20\\x09\\x21-\\x7E\\x80-\\xFF]*$/D', $value)) {
206 throw new \InvalidArgumentException(\sprintf('"%s" is not valid header value.', $value));
207 }
208 }
209 }
210