PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 2.4.4
Booking for Appointments and Events Calendar – Amelia v2.4.4
2.4.4 2.4.3 2.4.2 2.4.1 2.4 trunk 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 1.2.22 1.2.23 1.2.24 1.2.25 1.2.26 1.2.27 1.2.28 1.2.29 1.2.3 1.2.30 1.2.31 1.2.32 1.2.33 1.2.34 1.2.35 1.2.36 1.2.37 1.2.38 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.1.3 2.2 2.2.1 2.3
ameliabooking / vendor / php-http / message / src / Cookie.php
ameliabooking / vendor / php-http / message / src Last commit date
Authentication 6 months ago Builder 6 months ago Decorator 6 months ago Encoding 6 months ago Exception 2 years ago Formatter 6 months ago MessageFactory 6 months ago RequestMatcher 6 months ago Stream 6 months ago StreamFactory 6 months ago UriFactory 6 months ago Authentication.php 6 months ago Cookie.php 2 years ago CookieJar.php 2 years ago CookieUtil.php 2 years ago Exception.php 2 years ago Formatter.php 6 months ago RequestMatcher.php 6 months ago filters.php 7 years ago
Cookie.php
527 lines
1 <?php
2
3 namespace AmeliaHttp\Message;
4
5 /**
6 * Cookie Value Object.
7 *
8 * @author Márk Sági-Kazár <mark.sagikazar@gmail.com>
9 *
10 * @see http://tools.ietf.org/search/rfc6265
11 */
12 final class Cookie
13 {
14 /**
15 * @var string
16 */
17 private $name;
18
19 /**
20 * @var string|null
21 */
22 private $value;
23
24 /**
25 * @var int|null
26 */
27 private $maxAge;
28
29 /**
30 * @var string|null
31 */
32 private $domain;
33
34 /**
35 * @var string
36 */
37 private $path;
38
39 /**
40 * @var bool
41 */
42 private $secure;
43
44 /**
45 * @var bool
46 */
47 private $httpOnly;
48
49 /**
50 * Expires attribute is HTTP 1.0 only and should be avoided.
51 *
52 * @var \DateTime|null
53 */
54 private $expires;
55
56 /**
57 * @param string $name
58 * @param string|null $value
59 * @param int|null $maxAge
60 * @param string|null $domain
61 * @param string|null $path
62 * @param bool $secure
63 * @param bool $httpOnly
64 * @param \DateTime|null $expires Expires attribute is HTTP 1.0 only and should be avoided.
65 *
66 * @throws \InvalidArgumentException If name, value or max age is not valid.
67 */
68 public function __construct(
69 $name,
70 $value = null,
71 $maxAge = null,
72 $domain = null,
73 $path = null,
74 $secure = false,
75 $httpOnly = false,
76 \DateTime $expires = null
77 ) {
78 $this->validateName($name);
79 $this->validateValue($value);
80 $this->validateMaxAge($maxAge);
81
82 $this->name = $name;
83 $this->value = $value;
84 $this->maxAge = $maxAge;
85 $this->expires = $expires;
86 $this->domain = $this->normalizeDomain($domain);
87 $this->path = $this->normalizePath($path);
88 $this->secure = (bool) $secure;
89 $this->httpOnly = (bool) $httpOnly;
90 }
91
92 /**
93 * Creates a new cookie without any attribute validation.
94 *
95 * @param string $name
96 * @param string|null $value
97 * @param int $maxAge
98 * @param string|null $domain
99 * @param string|null $path
100 * @param bool $secure
101 * @param bool $httpOnly
102 * @param \DateTime|null $expires Expires attribute is HTTP 1.0 only and should be avoided.
103 */
104 public static function createWithoutValidation(
105 $name,
106 $value = null,
107 $maxAge = null,
108 $domain = null,
109 $path = null,
110 $secure = false,
111 $httpOnly = false,
112 \DateTime $expires = null
113 ) {
114 $cookie = new self('name', null, null, $domain, $path, $secure, $httpOnly, $expires);
115 $cookie->name = $name;
116 $cookie->value = $value;
117 $cookie->maxAge = $maxAge;
118
119 return $cookie;
120 }
121
122 /**
123 * Returns the name.
124 *
125 * @return string
126 */
127 public function getName()
128 {
129 return $this->name;
130 }
131
132 /**
133 * Returns the value.
134 *
135 * @return string|null
136 */
137 public function getValue()
138 {
139 return $this->value;
140 }
141
142 /**
143 * Checks if there is a value.
144 *
145 * @return bool
146 */
147 public function hasValue()
148 {
149 return isset($this->value);
150 }
151
152 /**
153 * Sets the value.
154 *
155 * @param string|null $value
156 *
157 * @return Cookie
158 */
159 public function withValue($value)
160 {
161 $this->validateValue($value);
162
163 $new = clone $this;
164 $new->value = $value;
165
166 return $new;
167 }
168
169 /**
170 * Returns the max age.
171 *
172 * @return int|null
173 */
174 public function getMaxAge()
175 {
176 return $this->maxAge;
177 }
178
179 /**
180 * Checks if there is a max age.
181 *
182 * @return bool
183 */
184 public function hasMaxAge()
185 {
186 return isset($this->maxAge);
187 }
188
189 /**
190 * Sets the max age.
191 *
192 * @param int|null $maxAge
193 *
194 * @return Cookie
195 */
196 public function withMaxAge($maxAge)
197 {
198 $this->validateMaxAge($maxAge);
199
200 $new = clone $this;
201 $new->maxAge = $maxAge;
202
203 return $new;
204 }
205
206 /**
207 * Returns the expiration time.
208 *
209 * @return \DateTime|null
210 */
211 public function getExpires()
212 {
213 return $this->expires;
214 }
215
216 /**
217 * Checks if there is an expiration time.
218 *
219 * @return bool
220 */
221 public function hasExpires()
222 {
223 return isset($this->expires);
224 }
225
226 /**
227 * Sets the expires.
228 *
229 * @param \DateTime|null $expires
230 *
231 * @return Cookie
232 */
233 public function withExpires(\DateTime $expires = null)
234 {
235 $new = clone $this;
236 $new->expires = $expires;
237
238 return $new;
239 }
240
241 /**
242 * Checks if the cookie is expired.
243 *
244 * @return bool
245 */
246 public function isExpired()
247 {
248 return isset($this->expires) and $this->expires < new \DateTime();
249 }
250
251 /**
252 * Returns the domain.
253 *
254 * @return string|null
255 */
256 public function getDomain()
257 {
258 return $this->domain;
259 }
260
261 /**
262 * Checks if there is a domain.
263 *
264 * @return bool
265 */
266 public function hasDomain()
267 {
268 return isset($this->domain);
269 }
270
271 /**
272 * Sets the domain.
273 *
274 * @param string|null $domain
275 *
276 * @return Cookie
277 */
278 public function withDomain($domain)
279 {
280 $new = clone $this;
281 $new->domain = $this->normalizeDomain($domain);
282
283 return $new;
284 }
285
286 /**
287 * Checks whether this cookie is meant for this domain.
288 *
289 * @see http://tools.ietf.org/html/rfc6265#section-5.1.3
290 *
291 * @param string $domain
292 *
293 * @return bool
294 */
295 public function matchDomain($domain)
296 {
297 // Domain is not set or exact match
298 if (!$this->hasDomain() || 0 === strcasecmp($domain, $this->domain)) {
299 return true;
300 }
301
302 // Domain is not an IP address
303 if (filter_var($domain, FILTER_VALIDATE_IP)) {
304 return false;
305 }
306
307 return (bool) preg_match(sprintf('/\b%s$/i', preg_quote($this->domain)), $domain);
308 }
309
310 /**
311 * Returns the path.
312 *
313 * @return string
314 */
315 public function getPath()
316 {
317 return $this->path;
318 }
319
320 /**
321 * Sets the path.
322 *
323 * @param string|null $path
324 *
325 * @return Cookie
326 */
327 public function withPath($path)
328 {
329 $new = clone $this;
330 $new->path = $this->normalizePath($path);
331
332 return $new;
333 }
334
335 /**
336 * Checks whether this cookie is meant for this path.
337 *
338 * @see http://tools.ietf.org/html/rfc6265#section-5.1.4
339 *
340 * @param string $path
341 *
342 * @return bool
343 */
344 public function matchPath($path)
345 {
346 return $this->path === $path || (0 === strpos($path, rtrim($this->path, '/').'/'));
347 }
348
349 /**
350 * Checks whether this cookie may only be sent over HTTPS.
351 *
352 * @return bool
353 */
354 public function isSecure()
355 {
356 return $this->secure;
357 }
358
359 /**
360 * Sets whether this cookie should only be sent over HTTPS.
361 *
362 * @param bool $secure
363 *
364 * @return Cookie
365 */
366 public function withSecure($secure)
367 {
368 $new = clone $this;
369 $new->secure = (bool) $secure;
370
371 return $new;
372 }
373
374 /**
375 * Check whether this cookie may not be accessed through Javascript.
376 *
377 * @return bool
378 */
379 public function isHttpOnly()
380 {
381 return $this->httpOnly;
382 }
383
384 /**
385 * Sets whether this cookie may not be accessed through Javascript.
386 *
387 * @param bool $httpOnly
388 *
389 * @return Cookie
390 */
391 public function withHttpOnly($httpOnly)
392 {
393 $new = clone $this;
394 $new->httpOnly = (bool) $httpOnly;
395
396 return $new;
397 }
398
399 /**
400 * Checks if this cookie represents the same cookie as $cookie.
401 *
402 * This does not compare the values, only name, domain and path.
403 *
404 * @param Cookie $cookie
405 *
406 * @return bool
407 */
408 public function match(self $cookie)
409 {
410 return $this->name === $cookie->name && $this->domain === $cookie->domain and $this->path === $cookie->path;
411 }
412
413 /**
414 * Validates cookie attributes.
415 *
416 * @return bool
417 */
418 public function isValid()
419 {
420 try {
421 $this->validateName($this->name);
422 $this->validateValue($this->value);
423 $this->validateMaxAge($this->maxAge);
424 } catch (\InvalidArgumentException $e) {
425 return false;
426 }
427
428 return true;
429 }
430
431 /**
432 * Validates the name attribute.
433 *
434 * @see http://tools.ietf.org/search/rfc2616#section-2.2
435 *
436 * @param string $name
437 *
438 * @throws \InvalidArgumentException If the name is empty or contains invalid characters.
439 */
440 private function validateName($name)
441 {
442 if (strlen($name) < 1) {
443 throw new \InvalidArgumentException('The name cannot be empty');
444 }
445
446 // Name attribute is a token as per spec in RFC 2616
447 if (preg_match('/[\x00-\x20\x22\x28-\x29\x2C\x2F\x3A-\x40\x5B-\x5D\x7B\x7D\x7F]/', $name)) {
448 throw new \InvalidArgumentException(sprintf('The cookie name "%s" contains invalid characters.', $name));
449 }
450 }
451
452 /**
453 * Validates a value.
454 *
455 * @see http://tools.ietf.org/html/rfc6265#section-4.1.1
456 *
457 * @param string|null $value
458 *
459 * @throws \InvalidArgumentException If the value contains invalid characters.
460 */
461 private function validateValue($value)
462 {
463 if (isset($value)) {
464 if (preg_match('/[^\x21\x23-\x2B\x2D-\x3A\x3C-\x5B\x5D-\x7E]/', $value)) {
465 throw new \InvalidArgumentException(sprintf('The cookie value "%s" contains invalid characters.', $value));
466 }
467 }
468 }
469
470 /**
471 * Validates a Max-Age attribute.
472 *
473 * @param int|null $maxAge
474 *
475 * @throws \InvalidArgumentException If the Max-Age is not an empty or integer value.
476 */
477 private function validateMaxAge($maxAge)
478 {
479 if (isset($maxAge)) {
480 if (!is_int($maxAge)) {
481 throw new \InvalidArgumentException('Max-Age must be integer');
482 }
483 }
484 }
485
486 /**
487 * Remove the leading '.' and lowercase the domain as per spec in RFC 6265.
488 *
489 * @see http://tools.ietf.org/html/rfc6265#section-4.1.2.3
490 * @see http://tools.ietf.org/html/rfc6265#section-5.1.3
491 * @see http://tools.ietf.org/html/rfc6265#section-5.2.3
492 *
493 * @param string|null $domain
494 *
495 * @return string
496 */
497 private function normalizeDomain($domain)
498 {
499 if (isset($domain)) {
500 $domain = ltrim(strtolower($domain), '.');
501 }
502
503 return $domain;
504 }
505
506 /**
507 * Processes path as per spec in RFC 6265.
508 *
509 * @see http://tools.ietf.org/html/rfc6265#section-5.1.4
510 * @see http://tools.ietf.org/html/rfc6265#section-5.2.4
511 *
512 * @param string|null $path
513 *
514 * @return string
515 */
516 private function normalizePath($path)
517 {
518 $path = rtrim($path, '/');
519
520 if (empty($path) or '/' !== substr($path, 0, 1)) {
521 $path = '/';
522 }
523
524 return $path;
525 }
526 }
527