run:R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
1.86 KB
2026-03-11 16:18:52
R W Run
3.17 KB
2026-03-11 16:18:52
R W Run
3.03 KB
2026-03-11 16:18:52
R W Run
2.41 KB
2026-03-11 16:18:52
R W Run
1.67 KB
2026-03-11 16:18:52
R W Run
2.09 KB
2026-03-11 16:18:52
R W Run
31.39 KB
2026-03-11 16:18:52
R W Run
355 By
2026-03-11 16:18:52
R W Run
18.94 KB
2026-03-11 16:18:52
R W Run
8.31 KB
2026-03-11 16:18:52
R W Run
33.99 KB
2026-03-11 16:18:52
R W Run
128.54 KB
2026-03-11 16:18:52
R W Run
16.31 KB
2026-03-11 16:18:52
R W Run
68.16 KB
2026-03-11 16:18:52
R W Run
34.05 KB
2026-03-11 16:18:52
R W Run
1.75 KB
2026-03-11 16:18:52
R W Run
7.71 KB
2026-03-11 16:18:52
R W Run
447 By
2026-03-11 16:18:52
R W Run
2.31 KB
2026-03-11 16:18:52
R W Run
29.64 KB
2026-03-11 16:18:52
R W Run
125.05 KB
2026-03-11 16:18:52
R W Run
23.18 KB
2026-03-11 16:18:52
R W Run
error_log
📄IRI.php
1<?php
2
3// SPDX-FileCopyrightText: 2004-2023 Ryan Parman, Sam Sneddon, Ryan McCue
4// SPDX-FileCopyrightText: 2008 Steve Minutillo
5// SPDX-License-Identifier: BSD-3-Clause
6
7declare(strict_types=1);
8
9namespace SimplePie;
10
11/**
12 * IRI parser/serialiser/normaliser
13 *
14 * @property ?string $scheme
15 * @property ?string $userinfo
16 * @property ?string $host
17 * @property ?int $port
18 * @property-write int|string|null $port
19 * @property ?string $authority
20 * @property string $path
21 * @property ?string $query
22 * @property ?string $fragment
23 */
24class IRI
25{
26 /**
27 * Scheme
28 *
29 * @var ?string
30 */
31 protected $scheme = null;
32
33 /**
34 * User Information
35 *
36 * @var ?string
37 */
38 protected $iuserinfo = null;
39
40 /**
41 * ihost
42 *
43 * @var ?string
44 */
45 protected $ihost = null;
46
47 /**
48 * Port
49 *
50 * @var ?int
51 */
52 protected $port = null;
53
54 /**
55 * ipath
56 *
57 * @var string
58 */
59 protected $ipath = '';
60
61 /**
62 * iquery
63 *
64 * @var ?string
65 */
66 protected $iquery = null;
67
68 /**
69 * ifragment
70 *
71 * @var ?string
72 */
73 protected $ifragment = null;
74
75 /**
76 * Normalization database
77 *
78 * Each key is the scheme, each value is an array with each key as the IRI
79 * part and value as the default value for that part.
80 *
81 * @var array<string, array<string, mixed>>
82 */
83 protected $normalization = [
84 'acap' => [
85 'port' => 674
86 ],
87 'dict' => [
88 'port' => 2628
89 ],
90 'file' => [
91 'ihost' => 'localhost'
92 ],
93 'http' => [
94 'port' => 80,
95 'ipath' => '/'
96 ],
97 'https' => [
98 'port' => 443,
99 'ipath' => '/'
100 ],
101 ];
102
103 /**
104 * Return the entire IRI when you try and read the object as a string
105 *
106 * @return string
107 */
108 public function __toString()
109 {
110 return (string) $this->get_iri();
111 }
112
113 /**
114 * Overload __set() to provide access via properties
115 *
116 * @param string $name Property name
117 * @param mixed $value Property value
118 * @return void
119 */
120 public function __set(string $name, $value)
121 {
122 $callable = [$this, 'set_' . $name];
123 if (is_callable($callable)) {
124 call_user_func($callable, $value);
125 } elseif (
126 $name === 'iauthority'
127 || $name === 'iuserinfo'
128 || $name === 'ihost'
129 || $name === 'ipath'
130 || $name === 'iquery'
131 || $name === 'ifragment'
132 ) {
133 call_user_func([$this, 'set_' . substr($name, 1)], $value);
134 }
135 }
136
137 /**
138 * Overload __get() to provide access via properties
139 *
140 * @param string $name Property name
141 * @return mixed
142 */
143 public function __get(string $name)
144 {
145 // isset() returns false for null, we don't want to do that
146 // Also why we use array_key_exists below instead of isset()
147 $props = get_object_vars($this);
148
149 if (
150 $name === 'iri' ||
151 $name === 'uri' ||
152 $name === 'iauthority' ||
153 $name === 'authority'
154 ) {
155 $return = $this->{"get_$name"}();
156 } elseif (array_key_exists($name, $props)) {
157 $return = $this->$name;
158 }
159 // host -> ihost
160 elseif (array_key_exists($prop = 'i' . $name, $props)) {
161 $name = $prop;
162 $return = $this->$prop;
163 }
164 // ischeme -> scheme
165 elseif (($prop = substr($name, 1)) && array_key_exists($prop, $props)) {
166 $name = $prop;
167 $return = $this->$prop;
168 } else {
169 trigger_error('Undefined property: ' . get_class($this) . '::' . $name, E_USER_NOTICE);
170 $return = null;
171 }
172
173 if ($return === null && isset($this->scheme, $this->normalization[$this->scheme][$name])) {
174 return $this->normalization[$this->scheme][$name];
175 }
176
177 return $return;
178 }
179
180 /**
181 * Overload __isset() to provide access via properties
182 *
183 * @param string $name Property name
184 * @return bool
185 */
186 public function __isset(string $name)
187 {
188 return method_exists($this, 'get_' . $name) || isset($this->$name);
189 }
190
191 /**
192 * Overload __unset() to provide access via properties
193 *
194 * @param string $name Property name
195 * @return void
196 */
197 public function __unset(string $name)
198 {
199 $callable = [$this, 'set_' . $name];
200 if (is_callable($callable)) {
201 call_user_func($callable, '');
202 }
203 }
204
205 /**
206 * Create a new IRI object, from a specified string
207 *
208 * @param string|null $iri
209 */
210 public function __construct(?string $iri = null)
211 {
212 $this->set_iri($iri);
213 }
214
215 /**
216 * Clean up
217 * @return void
218 */
219 public function __destruct()
220 {
221 $this->set_iri(null, true);
222 $this->set_path(null, true);
223 $this->set_authority(null, true);
224 }
225
226 /**
227 * Create a new IRI object by resolving a relative IRI
228 *
229 * Returns false if $base is not absolute, otherwise an IRI.
230 *
231 * @param IRI|string $base (Absolute) Base IRI
232 * @param IRI|string $relative Relative IRI
233 * @return IRI|false
234 */
235 public static function absolutize($base, $relative)
236 {
237 if (!($relative instanceof IRI)) {
238 $relative = new IRI($relative);
239 }
240 if (!$relative->is_valid()) {
241 return false;
242 } elseif ($relative->scheme !== null) {
243 return clone $relative;
244 } else {
245 if (!($base instanceof IRI)) {
246 $base = new IRI($base);
247 }
248 if ($base->scheme !== null && $base->is_valid()) {
249 if ($relative->get_iri() !== '') {
250 if ($relative->iuserinfo !== null || $relative->ihost !== null || $relative->port !== null) {
251 $target = clone $relative;
252 $target->scheme = $base->scheme;
253 } else {
254 $target = new IRI();
255 $target->scheme = $base->scheme;
256 $target->iuserinfo = $base->iuserinfo;
257 $target->ihost = $base->ihost;
258 $target->port = $base->port;
259 if ($relative->ipath !== '') {
260 if ($relative->ipath[0] === '/') {
261 $target->ipath = $relative->ipath;
262 } elseif (($base->iuserinfo !== null || $base->ihost !== null || $base->port !== null) && $base->ipath === '') {
263 $target->ipath = '/' . $relative->ipath;
264 } elseif (($last_segment = strrpos($base->ipath, '/')) !== false) {
265 $target->ipath = substr($base->ipath, 0, $last_segment + 1) . $relative->ipath;
266 } else {
267 $target->ipath = $relative->ipath;
268 }
269 $target->ipath = $target->remove_dot_segments($target->ipath);
270 $target->iquery = $relative->iquery;
271 } else {
272 $target->ipath = $base->ipath;
273 if ($relative->iquery !== null) {
274 $target->iquery = $relative->iquery;
275 } elseif ($base->iquery !== null) {
276 $target->iquery = $base->iquery;
277 }
278 }
279 $target->ifragment = $relative->ifragment;
280 }
281 } else {
282 $target = clone $base;
283 $target->ifragment = null;
284 }
285 $target->scheme_normalization();
286 return $target;
287 }
288
289 return false;
290 }
291 }
292
293 /**
294 * Parse an IRI into scheme/authority/path/query/fragment segments
295 *
296 * @param string $iri
297 * @return array{
298 * scheme: string|null,
299 * authority: string|null,
300 * path: string,
301 * query: string|null,
302 * fragment: string|null,
303 * }|false
304 */
305 protected function parse_iri(string $iri)
306 {
307 $iri = trim($iri, "\x20\x09\x0A\x0C\x0D");
308 if (preg_match('/^(?:(?P<scheme>[^:\/?#]+):)?(:?\/\/(?P<authority>[^\/?#]*))?(?P<path>[^?#]*)(?:\?(?P<query>[^#]*))?(?:#(?P<fragment>.*))?$/', $iri, $match, \PREG_UNMATCHED_AS_NULL)) {
309 // TODO: Remove once we require PHP ≥ 7.4.
310 $match['query'] = $match['query'] ?? null;
311 $match['fragment'] = $match['fragment'] ?? null;
312 return $match;
313 }
314
315 // This can occur when a paragraph is accidentally parsed as a URI
316 return false;
317 }
318
319 /**
320 * Remove dot segments from a path
321 *
322 * @param string $input
323 * @return string
324 */
325 protected function remove_dot_segments(string $input)
326 {
327 $output = '';
328 while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..') {
329 // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
330 if (strpos($input, '../') === 0) {
331 $input = substr($input, 3);
332 } elseif (strpos($input, './') === 0) {
333 $input = substr($input, 2);
334 }
335 // B: if the input buffer begins with a prefix of "/./" or "/.", where "." is a complete path segment, then replace that prefix with "/" in the input buffer; otherwise,
336 elseif (strpos($input, '/./') === 0) {
337 $input = substr($input, 2);
338 } elseif ($input === '/.') {
339 $input = '/';
340 }
341 // C: if the input buffer begins with a prefix of "/../" or "/..", where ".." is a complete path segment, then replace that prefix with "/" in the input buffer and remove the last segment and its preceding "/" (if any) from the output buffer; otherwise,
342 elseif (strpos($input, '/../') === 0) {
343 $input = substr($input, 3);
344 $output = substr_replace($output, '', intval(strrpos($output, '/')));
345 } elseif ($input === '/..') {
346 $input = '/';
347 $output = substr_replace($output, '', intval(strrpos($output, '/')));
348 }
349 // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
350 elseif ($input === '.' || $input === '..') {
351 $input = '';
352 }
353 // E: move the first path segment in the input buffer to the end of the output buffer, including the initial "/" character (if any) and any subsequent characters up to, but not including, the next "/" character or the end of the input buffer
354 elseif (($pos = strpos($input, '/', 1)) !== false) {
355 $output .= substr($input, 0, $pos);
356 $input = substr_replace($input, '', 0, $pos);
357 } else {
358 $output .= $input;
359 $input = '';
360 }
361 }
362 return $output . $input;
363 }
364
365 /**
366 * Replace invalid character with percent encoding
367 *
368 * @param string $string Input string
369 * @param string $extra_chars Valid characters not in iunreserved or
370 * iprivate (this is ASCII-only)
371 * @param bool $iprivate Allow iprivate
372 * @return string
373 */
374 protected function replace_invalid_with_pct_encoding(string $string, string $extra_chars, bool $iprivate = false)
375 {
376 // Normalize as many pct-encoded sections as possible
377 $string = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', [$this, 'remove_iunreserved_percent_encoded'], $string);
378 \assert(\is_string($string), "For PHPStan: Should not occur, the regex is valid");
379
380 // Replace invalid percent characters
381 $string = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $string);
382 \assert(\is_string($string), "For PHPStan: Should not occur, the regex is valid");
383
384 // Add unreserved and % to $extra_chars (the latter is safe because all
385 // pct-encoded sections are now valid).
386 $extra_chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~%';
387
388 // Now replace any bytes that aren't allowed with their pct-encoded versions
389 $position = 0;
390 $strlen = strlen($string);
391 while (($position += strspn($string, $extra_chars, $position)) < $strlen) {
392 $value = ord($string[$position]);
393 $character = 0;
394
395 // Start position
396 $start = $position;
397
398 // By default we are valid
399 $valid = true;
400
401 // No one byte sequences are valid due to the while.
402 // Two byte sequence:
403 if (($value & 0xE0) === 0xC0) {
404 $character = ($value & 0x1F) << 6;
405 $length = 2;
406 $remaining = 1;
407 }
408 // Three byte sequence:
409 elseif (($value & 0xF0) === 0xE0) {
410 $character = ($value & 0x0F) << 12;
411 $length = 3;
412 $remaining = 2;
413 }
414 // Four byte sequence:
415 elseif (($value & 0xF8) === 0xF0) {
416 $character = ($value & 0x07) << 18;
417 $length = 4;
418 $remaining = 3;
419 }
420 // Invalid byte:
421 else {
422 $valid = false;
423 $length = 1;
424 $remaining = 0;
425 }
426
427 if ($remaining) {
428 if ($position + $length <= $strlen) {
429 for ($position++; $remaining; $position++) {
430 $value = ord($string[$position]);
431
432 // Check that the byte is valid, then add it to the character:
433 if (($value & 0xC0) === 0x80) {
434 $character |= ($value & 0x3F) << (--$remaining * 6);
435 }
436 // If it is invalid, count the sequence as invalid and reprocess the current byte:
437 else {
438 $valid = false;
439 $position--;
440 break;
441 }
442 }
443 } else {
444 $position = $strlen - 1;
445 $valid = false;
446 }
447 }
448
449 // Percent encode anything invalid or not in ucschar
450 if (
451 // Invalid sequences
452 !$valid
453 // Non-shortest form sequences are invalid
454 || $length > 1 && $character <= 0x7F
455 || $length > 2 && $character <= 0x7FF
456 || $length > 3 && $character <= 0xFFFF
457 // Outside of range of ucschar codepoints
458 // Noncharacters
459 || ($character & 0xFFFE) === 0xFFFE
460 || $character >= 0xFDD0 && $character <= 0xFDEF
461 || (
462 // Everything else not in ucschar
463 $character > 0xD7FF && $character < 0xF900
464 || $character < 0xA0
465 || $character > 0xEFFFD
466 )
467 && (
468 // Everything not in iprivate, if it applies
469 !$iprivate
470 || $character < 0xE000
471 || $character > 0x10FFFD
472 )
473 ) {
474 // If we were a character, pretend we weren't, but rather an error.
475 if ($valid) {
476 $position--;
477 }
478
479 for ($j = $start; $j <= $position; $j++) {
480 $string = substr_replace($string, sprintf('%%%02X', ord($string[$j])), $j, 1);
481 $j += 2;
482 $position += 2;
483 $strlen += 2;
484 }
485 }
486 }
487
488 return $string;
489 }
490
491 /**
492 * Callback function for preg_replace_callback.
493 *
494 * Removes sequences of percent encoded bytes that represent UTF-8
495 * encoded characters in iunreserved
496 *
497 * @param array{string} $match PCRE match, a capture group #0 consisting of a sequence of valid percent-encoded bytes
498 * @return string Replacement
499 */
500 protected function remove_iunreserved_percent_encoded(array $match)
501 {
502 // As we just have valid percent encoded sequences we can just explode
503 // and ignore the first member of the returned array (an empty string).
504 $bytes = explode('%', $match[0]);
505
506 // Initialize the new string (this is what will be returned) and that
507 // there are no bytes remaining in the current sequence (unsurprising
508 // at the first byte!).
509 $string = '';
510 $remaining = 0;
511
512 // these variables will be initialized in the loop but PHPStan is not able to detect it currently
513 $start = 0;
514 $character = 0;
515 $length = 0;
516 $valid = true;
517
518 // Loop over each and every byte, and set $value to its value
519 for ($i = 1, $len = count($bytes); $i < $len; $i++) {
520 $value = hexdec($bytes[$i]);
521
522 // If we're the first byte of sequence:
523 if (!$remaining) {
524 // Start position
525 $start = $i;
526
527 // By default we are valid
528 $valid = true;
529
530 // One byte sequence:
531 if ($value <= 0x7F) {
532 $character = $value;
533 $length = 1;
534 }
535 // Two byte sequence:
536 elseif (($value & 0xE0) === 0xC0) {
537 $character = ($value & 0x1F) << 6;
538 $length = 2;
539 $remaining = 1;
540 }
541 // Three byte sequence:
542 elseif (($value & 0xF0) === 0xE0) {
543 $character = ($value & 0x0F) << 12;
544 $length = 3;
545 $remaining = 2;
546 }
547 // Four byte sequence:
548 elseif (($value & 0xF8) === 0xF0) {
549 $character = ($value & 0x07) << 18;
550 $length = 4;
551 $remaining = 3;
552 }
553 // Invalid byte:
554 else {
555 $valid = false;
556 $remaining = 0;
557 }
558 }
559 // Continuation byte:
560 else {
561 // Check that the byte is valid, then add it to the character:
562 if (($value & 0xC0) === 0x80) {
563 $remaining--;
564 $character |= ($value & 0x3F) << ($remaining * 6);
565 }
566 // If it is invalid, count the sequence as invalid and reprocess the current byte as the start of a sequence:
567 else {
568 $valid = false;
569 $remaining = 0;
570 $i--;
571 }
572 }
573
574 // If we've reached the end of the current byte sequence, append it to Unicode::$data
575 if (!$remaining) {
576 // Percent encode anything invalid or not in iunreserved
577 if (
578 // Invalid sequences
579 !$valid
580 // Non-shortest form sequences are invalid
581 || $length > 1 && $character <= 0x7F
582 || $length > 2 && $character <= 0x7FF
583 || $length > 3 && $character <= 0xFFFF
584 // Outside of range of iunreserved codepoints
585 || $character < 0x2D
586 || $character > 0xEFFFD
587 // Noncharacters
588 || ($character & 0xFFFE) === 0xFFFE
589 || $character >= 0xFDD0 && $character <= 0xFDEF
590 // Everything else not in iunreserved (this is all BMP)
591 || $character === 0x2F
592 || $character > 0x39 && $character < 0x41
593 || $character > 0x5A && $character < 0x61
594 || $character > 0x7A && $character < 0x7E
595 || $character > 0x7E && $character < 0xA0
596 || $character > 0xD7FF && $character < 0xF900
597 ) {
598 for ($j = $start; $j <= $i; $j++) {
599 $string .= '%' . strtoupper($bytes[$j]);
600 }
601 } else {
602 for ($j = $start; $j <= $i; $j++) {
603 // Cast for PHPStan, this will always be a number between 0 and 0xFF so hexdec will return int.
604 $string .= chr((int) hexdec($bytes[$j]));
605 }
606 }
607 }
608 }
609
610 // If we have any bytes left over they are invalid (i.e., we are
611 // mid-way through a multi-byte sequence)
612 if ($remaining) {
613 for ($j = $start; $j < $len; $j++) {
614 $string .= '%' . strtoupper($bytes[$j]);
615 }
616 }
617
618 return $string;
619 }
620
621 /**
622 * @return void
623 */
624 protected function scheme_normalization()
625 {
626 if ($this->scheme === null) {
627 return;
628 }
629
630 if (isset($this->normalization[$this->scheme]['iuserinfo']) && $this->iuserinfo === $this->normalization[$this->scheme]['iuserinfo']) {
631 $this->iuserinfo = null;
632 }
633 if (isset($this->normalization[$this->scheme]['ihost']) && $this->ihost === $this->normalization[$this->scheme]['ihost']) {
634 $this->ihost = null;
635 }
636 if (isset($this->normalization[$this->scheme]['port']) && $this->port === $this->normalization[$this->scheme]['port']) {
637 $this->port = null;
638 }
639 if (isset($this->normalization[$this->scheme]['ipath']) && $this->ipath === $this->normalization[$this->scheme]['ipath']) {
640 $this->ipath = '';
641 }
642 if (isset($this->normalization[$this->scheme]['iquery']) && $this->iquery === $this->normalization[$this->scheme]['iquery']) {
643 $this->iquery = null;
644 }
645 if (isset($this->normalization[$this->scheme]['ifragment']) && $this->ifragment === $this->normalization[$this->scheme]['ifragment']) {
646 $this->ifragment = null;
647 }
648 }
649
650 /**
651 * Check if the object represents a valid IRI. This needs to be done on each
652 * call as some things change depending on another part of the IRI.
653 *
654 * @return bool
655 */
656 public function is_valid()
657 {
658 if ($this->ipath === '') {
659 return true;
660 }
661
662 $isauthority = $this->iuserinfo !== null || $this->ihost !== null ||
663 $this->port !== null;
664 if ($isauthority && $this->ipath[0] === '/') {
665 return true;
666 }
667
668 if (!$isauthority && (substr($this->ipath, 0, 2) === '//')) {
669 return false;
670 }
671
672 // Relative urls cannot have a colon in the first path segment (and the
673 // slashes themselves are not included so skip the first character).
674 if (!$this->scheme && !$isauthority &&
675 strpos($this->ipath, ':') !== false &&
676 strpos($this->ipath, '/', 1) !== false &&
677 strpos($this->ipath, ':') < strpos($this->ipath, '/', 1)) {
678 return false;
679 }
680
681 return true;
682 }
683
684 /**
685 * Set the entire IRI. Returns true on success, false on failure (if there
686 * are any invalid characters).
687 *
688 * @param string|null $iri
689 * @return bool
690 */
691 public function set_iri(?string $iri, bool $clear_cache = false)
692 {
693 static $cache;
694 if ($clear_cache) {
695 $cache = null;
696 return false;
697 }
698 if (!$cache) {
699 $cache = [];
700 }
701
702 if ($iri === null) {
703 return true;
704 } elseif (isset($cache[$iri])) {
705 [
706 $this->scheme,
707 $this->iuserinfo,
708 $this->ihost,
709 $this->port,
710 $this->ipath,
711 $this->iquery,
712 $this->ifragment,
713 $return
714 ] = $cache[$iri];
715
716 return $return;
717 }
718
719 $parsed = $this->parse_iri((string) $iri);
720 if (!$parsed) {
721 return false;
722 }
723
724 $return = $this->set_scheme($parsed['scheme'])
725 && $this->set_authority($parsed['authority'])
726 && $this->set_path($parsed['path'])
727 && $this->set_query($parsed['query'])
728 && $this->set_fragment($parsed['fragment']);
729
730 $cache[$iri] = [
731 $this->scheme,
732 $this->iuserinfo,
733 $this->ihost,
734 $this->port,
735 $this->ipath,
736 $this->iquery,
737 $this->ifragment,
738 $return
739 ];
740
741 return $return;
742 }
743
744 /**
745 * Set the scheme. Returns true on success, false on failure (if there are
746 * any invalid characters).
747 *
748 * @param string|null $scheme
749 * @return bool
750 */
751 public function set_scheme(?string $scheme)
752 {
753 if ($scheme === null) {
754 $this->scheme = null;
755 } elseif (!preg_match('/^[A-Za-z][0-9A-Za-z+\-.]*$/', $scheme)) {
756 $this->scheme = null;
757 return false;
758 } else {
759 $this->scheme = strtolower($scheme);
760 }
761 return true;
762 }
763
764 /**
765 * Set the authority. Returns true on success, false on failure (if there are
766 * any invalid characters).
767 *
768 * @param string|null $authority
769 * @return bool
770 */
771 public function set_authority(?string $authority, bool $clear_cache = false)
772 {
773 static $cache;
774 if ($clear_cache) {
775 $cache = null;
776 return false;
777 }
778 if (!$cache) {
779 $cache = [];
780 }
781
782 if ($authority === null) {
783 $this->iuserinfo = null;
784 $this->ihost = null;
785 $this->port = null;
786 return true;
787 } elseif (isset($cache[$authority])) {
788 [
789 $this->iuserinfo,
790 $this->ihost,
791 $this->port,
792 $return
793 ] = $cache[$authority];
794
795 return $return;
796 }
797
798 $remaining = $authority;
799 if (($iuserinfo_end = strrpos($remaining, '@')) !== false) {
800 // Cast for PHPStan on PHP < 8.0. It does not detect that
801 // the range is not flipped so substr cannot return false.
802 $iuserinfo = (string) substr($remaining, 0, $iuserinfo_end);
803 $remaining = substr($remaining, $iuserinfo_end + 1);
804 } else {
805 $iuserinfo = null;
806 }
807 if (($port_start = strpos($remaining, ':', intval(strpos($remaining, ']')))) !== false) {
808 $port = substr($remaining, $port_start + 1);
809 if ($port === false) {
810 $port = null;
811 }
812 $remaining = substr($remaining, 0, $port_start);
813 } else {
814 $port = null;
815 }
816
817 $return = $this->set_userinfo($iuserinfo) &&
818 $this->set_host($remaining) &&
819 $this->set_port($port);
820
821 $cache[$authority] = [
822 $this->iuserinfo,
823 $this->ihost,
824 $this->port,
825 $return
826 ];
827
828 return $return;
829 }
830
831 /**
832 * Set the iuserinfo.
833 *
834 * @param string|null $iuserinfo
835 * @return bool
836 */
837 public function set_userinfo(?string $iuserinfo)
838 {
839 if ($iuserinfo === null) {
840 $this->iuserinfo = null;
841 } else {
842 $this->iuserinfo = $this->replace_invalid_with_pct_encoding($iuserinfo, '!$&\'()*+,;=:');
843 $this->scheme_normalization();
844 }
845
846 return true;
847 }
848
849 /**
850 * Set the ihost. Returns true on success, false on failure (if there are
851 * any invalid characters).
852 *
853 * @param string|null $ihost
854 * @return bool
855 */
856 public function set_host(?string $ihost)
857 {
858 if ($ihost === null) {
859 $this->ihost = null;
860 return true;
861 } elseif (substr($ihost, 0, 1) === '[' && substr($ihost, -1) === ']') {
862 if (\SimplePie\Net\IPv6::check_ipv6(substr($ihost, 1, -1))) {
863 $this->ihost = '[' . \SimplePie\Net\IPv6::compress(substr($ihost, 1, -1)) . ']';
864 } else {
865 $this->ihost = null;
866 return false;
867 }
868 } else {
869 $ihost = $this->replace_invalid_with_pct_encoding($ihost, '!$&\'()*+,;=');
870
871 // Lowercase, but ignore pct-encoded sections (as they should
872 // remain uppercase). This must be done after the previous step
873 // as that can add unescaped characters.
874 $position = 0;
875 $strlen = strlen($ihost);
876 while (($position += strcspn($ihost, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ%', $position)) < $strlen) {
877 if ($ihost[$position] === '%') {
878 $position += 3;
879 } else {
880 $ihost[$position] = strtolower($ihost[$position]);
881 $position++;
882 }
883 }
884
885 $this->ihost = $ihost;
886 }
887
888 $this->scheme_normalization();
889
890 return true;
891 }
892
893 /**
894 * Set the port. Returns true on success, false on failure (if there are
895 * any invalid characters).
896 *
897 * @param string|int|null $port
898 * @return bool
899 */
900 public function set_port($port)
901 {
902 if ($port === null) {
903 $this->port = null;
904 return true;
905 } elseif (strspn((string) $port, '0123456789') === strlen((string) $port)) {
906 $this->port = (int) $port;
907 $this->scheme_normalization();
908 return true;
909 }
910
911 $this->port = null;
912 return false;
913 }
914
915 /**
916 * Set the ipath.
917 *
918 * @param string|null $ipath
919 * @return bool
920 */
921 public function set_path(?string $ipath, bool $clear_cache = false)
922 {
923 static $cache;
924 if ($clear_cache) {
925 $cache = null;
926 return false;
927 }
928 if (!$cache) {
929 $cache = [];
930 }
931
932 $ipath = (string) $ipath;
933
934 if (isset($cache[$ipath])) {
935 $this->ipath = $cache[$ipath][(int) ($this->scheme !== null)];
936 } else {
937 $valid = $this->replace_invalid_with_pct_encoding($ipath, '!$&\'()*+,;=@:/');
938 $removed = $this->remove_dot_segments($valid);
939
940 $cache[$ipath] = [$valid, $removed];
941 $this->ipath = ($this->scheme !== null) ? $removed : $valid;
942 }
943
944 $this->scheme_normalization();
945 return true;
946 }
947
948 /**
949 * Set the iquery.
950 *
951 * @param string|null $iquery
952 * @return bool
953 */
954 public function set_query(?string $iquery)
955 {
956 if ($iquery === null) {
957 $this->iquery = null;
958 } else {
959 $this->iquery = $this->replace_invalid_with_pct_encoding($iquery, '!$&\'()*+,;=:@/?', true);
960 $this->scheme_normalization();
961 }
962 return true;
963 }
964
965 /**
966 * Set the ifragment.
967 *
968 * @param string|null $ifragment
969 * @return bool
970 */
971 public function set_fragment(?string $ifragment)
972 {
973 if ($ifragment === null) {
974 $this->ifragment = null;
975 } else {
976 $this->ifragment = $this->replace_invalid_with_pct_encoding($ifragment, '!$&\'()*+,;=:@/?');
977 $this->scheme_normalization();
978 }
979 return true;
980 }
981
982 /**
983 * Convert an IRI to a URI (or parts thereof)
984 *
985 * @param string $string
986 * @return string
987 */
988 public function to_uri(string $string)
989 {
990 static $non_ascii;
991 if (!$non_ascii) {
992 $non_ascii = implode('', range("\x80", "\xFF"));
993 }
994
995 $position = 0;
996 $strlen = strlen($string);
997 while (($position += strcspn($string, $non_ascii, $position)) < $strlen) {
998 $string = substr_replace($string, sprintf('%%%02X', ord($string[$position])), $position, 1);
999 $position += 3;
1000 $strlen += 2;
1001 }
1002
1003 return $string;
1004 }
1005
1006 /**
1007 * Get the complete IRI
1008 *
1009 * @return string|false
1010 */
1011 public function get_iri()
1012 {
1013 if (!$this->is_valid()) {
1014 return false;
1015 }
1016
1017 $iri = '';
1018 if ($this->scheme !== null) {
1019 $iri .= $this->scheme . ':';
1020 }
1021 if (($iauthority = $this->get_iauthority()) !== null) {
1022 $iri .= '//' . $iauthority;
1023 }
1024 if ($this->ipath !== '') {
1025 $iri .= $this->ipath;
1026 } elseif (!empty($this->normalization[$this->scheme]['ipath']) && $iauthority !== null && $iauthority !== '') {
1027 $iri .= $this->normalization[$this->scheme]['ipath'];
1028 }
1029 if ($this->iquery !== null) {
1030 $iri .= '?' . $this->iquery;
1031 }
1032 if ($this->ifragment !== null) {
1033 $iri .= '#' . $this->ifragment;
1034 }
1035
1036 return $iri;
1037 }
1038
1039 /**
1040 * Get the complete URI
1041 *
1042 * @return string
1043 */
1044 public function get_uri()
1045 {
1046 return $this->to_uri((string) $this->get_iri());
1047 }
1048
1049 /**
1050 * Get the complete iauthority
1051 *
1052 * @return ?string
1053 */
1054 protected function get_iauthority()
1055 {
1056 if ($this->iuserinfo !== null || $this->ihost !== null || $this->port !== null) {
1057 $iauthority = '';
1058 if ($this->iuserinfo !== null) {
1059 $iauthority .= $this->iuserinfo . '@';
1060 }
1061 if ($this->ihost !== null) {
1062 $iauthority .= $this->ihost;
1063 }
1064 if ($this->port !== null && $this->port !== 0) {
1065 $iauthority .= ':' . $this->port;
1066 }
1067 return $iauthority;
1068 }
1069
1070 return null;
1071 }
1072
1073 /**
1074 * Get the complete authority
1075 *
1076 * @return ?string
1077 */
1078 protected function get_authority()
1079 {
1080 $iauthority = $this->get_iauthority();
1081 if (is_string($iauthority)) {
1082 return $this->to_uri($iauthority);
1083 }
1084
1085 return $iauthority;
1086 }
1087}
1088
1089class_alias('SimplePie\IRI', 'SimplePie_IRI');
1090
Ui Ux Design – Teachers Night Out https://cardgames4educators.com Wed, 16 Oct 2024 22:24:18 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 https://cardgames4educators.com/wp-content/uploads/2024/06/cropped-Card-4-Educators-logo-32x32.png Ui Ux Design – Teachers Night Out https://cardgames4educators.com 32 32 Masters In English How English Speaker https://cardgames4educators.com/masters-in-english-how-english-speaker/ https://cardgames4educators.com/masters-in-english-how-english-speaker/#comments Mon, 27 May 2024 08:54:45 +0000 https://themexriver.com/wp/kadu/?p=1

Erat himenaeos neque id sagittis massa. Hac suscipit pulvinar dignissim platea magnis eu. Don tellus a pharetra inceptos efficitur dui pulvinar. Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent pulvinar odio volutpat parturient. Quisque risus finibus suspendisse mus purus magnis facilisi condimentum consectetur dui. Curae elit suspendisse cursus vehicula.

Turpis taciti class non vel pretium quis pulvinar tempor lobortis nunc. Libero phasellus parturient sapien volutpat malesuada ornare. Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae. Porta est tempor ex eget feugiat vulputate ipsum. Justo nec iaculis habitant diam arcu fermentum.

We offer comprehen sive emplo ment services such as assistance wit employer compliance.Our company is your strategic HR partner as instead of HR. john smithson

Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae.

Exploring Learning Landscapes in Academic

Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent.

]]>
https://cardgames4educators.com/masters-in-english-how-english-speaker/feed/ 1