PluginProbe
Media Cloud Sync / 1.2.13
Media Cloud Sync v1.2.13
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.2.13, at includes/sdk/s3/GuzzleHttp/Psr7/MessageTrait.php

213 lines 7.5 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 if (\count($value) === 0) {
142 throw new \InvalidArgumentException('Header value can not be an empty array.');
143 }
144 return $this->trimAndValidateHeaderValues($value);
145 }
146 /**
147 * Trims whitespace from the header values.
148 *
149 * Spaces and tabs ought to be excluded by parsers when extracting the field value from a header field.
150 *
151 * header-field = field-name ":" OWS field-value OWS
152 * OWS = *( SP / HTAB )
153 *
154 * @param mixed[] $values Header values
155 *
156 * @return string[] Trimmed header values
157 *
158 * @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.4
159 */
160 private function trimAndValidateHeaderValues(array $values) : array
161 {
162 return \array_map(function ($value) {
163 if (!\is_scalar($value) && null !== $value) {
164 throw new \InvalidArgumentException(\sprintf('Header value must be scalar or null but %s provided.', \is_object($value) ? \get_class($value) : \gettype($value)));
165 }
166 $trimmed = \trim((string) $value, " \t");
167 $this->assertValue($trimmed);
168 return $trimmed;
169 }, \array_values($values));
170 }
171 /**
172 * @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2
173 *
174 * @param mixed $header
175 */
176 private function assertHeader($header) : void
177 {
178 if (!\is_string($header)) {
179 throw new \InvalidArgumentException(\sprintf('Header name must be a string but %s provided.', \is_object($header) ? \get_class($header) : \gettype($header)));
180 }
181 if (!\preg_match('/^[a-zA-Z0-9\'`#$%&*+.^_|~!-]+$/D', $header)) {
182 throw new \InvalidArgumentException(\sprintf('"%s" is not valid header name.', $header));
183 }
184 }
185 /**
186 * @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2
187 *
188 * field-value = *( field-content / obs-fold )
189 * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
190 * field-vchar = VCHAR / obs-text
191 * VCHAR = %x21-7E
192 * obs-text = %x80-FF
193 * obs-fold = CRLF 1*( SP / HTAB )
194 */
195 private function assertValue(string $value) : void
196 {
197 // The regular expression intentionally does not support the obs-fold production, because as
198 // per RFC 7230#3.2.4:
199 //
200 // A sender MUST NOT generate a message that includes
201 // line folding (i.e., that has any field-value that contains a match to
202 // the obs-fold rule) unless the message is intended for packaging
203 // within the message/http media type.
204 //
205 // Clients must not send a request with line folding and a server sending folded headers is
206 // likely very rare. Line folding is a fairly obscure feature of HTTP/1.1 and thus not accepting
207 // folding is not likely to break any legitimate use case.
208 if (!\preg_match('/^[\\x20\\x09\\x21-\\x7E\\x80-\\xFF]*$/D', $value)) {
209 throw new \InvalidArgumentException(\sprintf('"%s" is not valid header value.', $value));
210 }
211 }
212 }
213