PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 27.7
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v27.7
28.6 28.5 28.4 28.3 28.2 28.1 28.0 27.9 27.8 27.7 27.6 27.5 trunk 18.0 18.1 18.2 18.3 18.4 18.4.1 18.5 18.5.1 18.6 18.7 18.8 18.9 All 130 releases
wordpress-seo / vendor_prefixed / guzzlehttp / guzzle / src / Cookie / CookieJar.php

CookieJar.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI 27.7, at vendor_prefixed/guzzlehttp/guzzle/src/Cookie/CookieJar.php

241 lines 9.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace YoastSEO_Vendor\GuzzleHttp\Cookie;
4
5 use YoastSEO_Vendor\Psr\Http\Message\RequestInterface;
6 use YoastSEO_Vendor\Psr\Http\Message\ResponseInterface;
7 /**
8 * Cookie jar that stores cookies as an array
9 */
10 class CookieJar implements \YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJarInterface
11 {
12 /**
13 * @var SetCookie[] Loaded cookie data
14 */
15 private $cookies = [];
16 /**
17 * @var bool
18 */
19 private $strictMode;
20 /**
21 * @param bool $strictMode Set to true to throw exceptions when invalid
22 * cookies are added to the cookie jar.
23 * @param array $cookieArray Array of SetCookie objects or a hash of
24 * arrays that can be used with the SetCookie
25 * constructor
26 */
27 public function __construct(bool $strictMode = \false, array $cookieArray = [])
28 {
29 $this->strictMode = $strictMode;
30 foreach ($cookieArray as $cookie) {
31 if (!$cookie instanceof \YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie) {
32 $cookie = new \YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie($cookie);
33 }
34 $this->setCookie($cookie);
35 }
36 }
37 /**
38 * Create a new Cookie jar from an associative array and domain.
39 *
40 * @param array $cookies Cookies to create the jar from
41 * @param string $domain Domain to set the cookies to
42 */
43 public static function fromArray(array $cookies, string $domain) : self
44 {
45 $cookieJar = new self();
46 foreach ($cookies as $name => $value) {
47 $cookieJar->setCookie(new \YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie(['Domain' => $domain, 'Name' => $name, 'Value' => $value, 'Discard' => \true]));
48 }
49 return $cookieJar;
50 }
51 /**
52 * Evaluate if this cookie should be persisted to storage
53 * that survives between requests.
54 *
55 * @param SetCookie $cookie Being evaluated.
56 * @param bool $allowSessionCookies If we should persist session cookies
57 */
58 public static function shouldPersist(\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie, bool $allowSessionCookies = \false) : bool
59 {
60 if ($cookie->getExpires() || $allowSessionCookies) {
61 if (!$cookie->getDiscard()) {
62 return \true;
63 }
64 }
65 return \false;
66 }
67 /**
68 * Finds and returns the cookie based on the name
69 *
70 * @param string $name cookie name to search for
71 *
72 * @return SetCookie|null cookie that was found or null if not found
73 */
74 public function getCookieByName(string $name) : ?\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie
75 {
76 foreach ($this->cookies as $cookie) {
77 if ($cookie->getName() !== null && \strcasecmp($cookie->getName(), $name) === 0) {
78 return $cookie;
79 }
80 }
81 return null;
82 }
83 public function toArray() : array
84 {
85 return \array_map(static function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) : array {
86 return $cookie->toArray();
87 }, $this->getIterator()->getArrayCopy());
88 }
89 public function clear(?string $domain = null, ?string $path = null, ?string $name = null) : void
90 {
91 if (!$domain) {
92 $this->cookies = [];
93 return;
94 } elseif (!$path) {
95 $this->cookies = \array_filter($this->cookies, static function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) use($domain) : bool {
96 return !$cookie->matchesDomain($domain);
97 });
98 } elseif (!$name) {
99 $this->cookies = \array_filter($this->cookies, static function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) use($path, $domain) : bool {
100 return !($cookie->matchesPath($path) && $cookie->matchesDomain($domain));
101 });
102 } else {
103 $this->cookies = \array_filter($this->cookies, static function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) use($path, $domain, $name) {
104 return !($cookie->getName() == $name && $cookie->matchesPath($path) && $cookie->matchesDomain($domain));
105 });
106 }
107 }
108 public function clearSessionCookies() : void
109 {
110 $this->cookies = \array_filter($this->cookies, static function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) : bool {
111 return !$cookie->getDiscard() && $cookie->getExpires();
112 });
113 }
114 public function setCookie(\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) : bool
115 {
116 // If the name string is empty (but not 0), ignore the set-cookie
117 // string entirely.
118 $name = $cookie->getName();
119 if (!$name && $name !== '0') {
120 return \false;
121 }
122 // Only allow cookies with set and valid domain, name, value
123 $result = $cookie->validate();
124 if ($result !== \true) {
125 if ($this->strictMode) {
126 throw new \RuntimeException('Invalid cookie: ' . $result);
127 }
128 $this->removeCookieIfEmpty($cookie);
129 return \false;
130 }
131 // Resolve conflicts with previously set cookies
132 foreach ($this->cookies as $i => $c) {
133 // Two cookies are identical, when their path, and domain are
134 // identical.
135 if ($c->getPath() != $cookie->getPath() || $c->getDomain() != $cookie->getDomain() || $c->getName() != $cookie->getName()) {
136 continue;
137 }
138 // The previously set cookie is a discard cookie and this one is
139 // not so allow the new cookie to be set
140 if (!$cookie->getDiscard() && $c->getDiscard()) {
141 unset($this->cookies[$i]);
142 continue;
143 }
144 // If the new cookie's expiration is further into the future, then
145 // replace the old cookie
146 if ($cookie->getExpires() > $c->getExpires()) {
147 unset($this->cookies[$i]);
148 continue;
149 }
150 // If the value has changed, we better change it
151 if ($cookie->getValue() !== $c->getValue()) {
152 unset($this->cookies[$i]);
153 continue;
154 }
155 // The cookie exists, so no need to continue
156 return \false;
157 }
158 $this->cookies[] = $cookie;
159 return \true;
160 }
161 public function count() : int
162 {
163 return \count($this->cookies);
164 }
165 /**
166 * @return \ArrayIterator<int, SetCookie>
167 */
168 public function getIterator() : \ArrayIterator
169 {
170 return new \ArrayIterator(\array_values($this->cookies));
171 }
172 public function extractCookies(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) : void
173 {
174 if ($cookieHeader = $response->getHeader('Set-Cookie')) {
175 foreach ($cookieHeader as $cookie) {
176 $sc = \YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie::fromString($cookie);
177 if (!$sc->getDomain()) {
178 $sc->setDomain($request->getUri()->getHost());
179 }
180 if (0 !== \strpos($sc->getPath(), '/')) {
181 $sc->setPath($this->getCookiePathFromRequest($request));
182 }
183 if (!$sc->matchesDomain($request->getUri()->getHost())) {
184 continue;
185 }
186 // Note: At this point `$sc->getDomain()` being a public suffix should
187 // be rejected, but we don't want to pull in the full PSL dependency.
188 $this->setCookie($sc);
189 }
190 }
191 }
192 /**
193 * Computes cookie path following RFC 6265 section 5.1.4
194 *
195 * @see https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.4
196 */
197 private function getCookiePathFromRequest(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request) : string
198 {
199 $uriPath = $request->getUri()->getPath();
200 if ('' === $uriPath) {
201 return '/';
202 }
203 if (0 !== \strpos($uriPath, '/')) {
204 return '/';
205 }
206 if ('/' === $uriPath) {
207 return '/';
208 }
209 $lastSlashPos = \strrpos($uriPath, '/');
210 if (0 === $lastSlashPos || \false === $lastSlashPos) {
211 return '/';
212 }
213 return \substr($uriPath, 0, $lastSlashPos);
214 }
215 public function withCookieHeader(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface
216 {
217 $values = [];
218 $uri = $request->getUri();
219 $scheme = $uri->getScheme();
220 $host = $uri->getHost();
221 $path = $uri->getPath() ?: '/';
222 foreach ($this->cookies as $cookie) {
223 if ($cookie->matchesPath($path) && $cookie->matchesDomain($host) && !$cookie->isExpired() && (!$cookie->getSecure() || $scheme === 'https')) {
224 $values[] = $cookie->getName() . '=' . $cookie->getValue();
225 }
226 }
227 return $values ? $request->withHeader('Cookie', \implode('; ', $values)) : $request;
228 }
229 /**
230 * If a cookie already exists and the server asks to set it again with a
231 * null value, the cookie must be deleted.
232 */
233 private function removeCookieIfEmpty(\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) : void
234 {
235 $cookieValue = $cookie->getValue();
236 if ($cookieValue === null || $cookieValue === '') {
237 $this->clear($cookie->getDomain(), $cookie->getPath(), $cookie->getName());
238 }
239 }
240 }
241