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 / UriNormalizer.php

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

176 lines 8.1 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\UriInterface;
7 /**
8 * Provides methods to normalize and compare URIs.
9 *
10 * @author Tobias Schultze
11 *
12 * @see https://datatracker.ietf.org/doc/html/rfc3986#section-6
13 */
14 final class UriNormalizer
15 {
16 /**
17 * Default normalizations which only include the ones that preserve semantics.
18 */
19 public const PRESERVING_NORMALIZATIONS = self::CAPITALIZE_PERCENT_ENCODING | self::DECODE_UNRESERVED_CHARACTERS | self::CONVERT_EMPTY_PATH | self::REMOVE_DEFAULT_HOST | self::REMOVE_DEFAULT_PORT | self::REMOVE_DOT_SEGMENTS;
20 /**
21 * All letters within a percent-encoding triplet (e.g., "%3A") are case-insensitive, and should be capitalized.
22 *
23 * Example: http://example.org/a%c2%b1b → http://example.org/a%C2%B1b
24 */
25 public const CAPITALIZE_PERCENT_ENCODING = 1;
26 /**
27 * Decodes percent-encoded octets of unreserved characters.
28 *
29 * For consistency, percent-encoded octets in the ranges of ALPHA (%41–%5A and %61–%7A), DIGIT (%30–%39),
30 * hyphen (%2D), period (%2E), underscore (%5F), or tilde (%7E) should not be created by URI producers and,
31 * when found in a URI, should be decoded to their corresponding unreserved characters by URI normalizers.
32 *
33 * Example: http://example.org/%7Eusern%61me/ → http://example.org/~username/
34 */
35 public const DECODE_UNRESERVED_CHARACTERS = 2;
36 /**
37 * Converts the empty path to "/" for http and https URIs.
38 *
39 * Example: http://example.org → http://example.org/
40 */
41 public const CONVERT_EMPTY_PATH = 4;
42 /**
43 * Removes the default host of the given URI scheme from the URI.
44 *
45 * Only the "file" scheme defines the default host "localhost".
46 * All of `file:/myfile`, `file:///myfile`, and `file://localhost/myfile`
47 * are equivalent according to RFC 3986. The first format is not accepted
48 * by PHPs stream functions and thus already normalized implicitly to the
49 * second format in the Uri class. See `GuzzleHttp\Psr7\Uri::composeComponents`.
50 *
51 * Example: file://localhost/myfile → file:///myfile
52 */
53 public const REMOVE_DEFAULT_HOST = 8;
54 /**
55 * Removes the default port of the given URI scheme from the URI.
56 *
57 * Example: http://example.org:80/ → http://example.org/
58 */
59 public const REMOVE_DEFAULT_PORT = 16;
60 /**
61 * Removes unnecessary dot-segments.
62 *
63 * Dot-segments in relative-path references are not removed as it would
64 * change the semantics of the URI reference.
65 *
66 * Example: http://example.org/../a/b/../c/./d.html → http://example.org/a/c/d.html
67 */
68 public const REMOVE_DOT_SEGMENTS = 32;
69 /**
70 * Paths which include two or more adjacent slashes are converted to one.
71 *
72 * Webservers usually ignore duplicate slashes and treat those URIs equivalent.
73 * But in theory those URIs do not need to be equivalent. So this normalization
74 * may change the semantics. Encoded slashes (%2F) are not removed.
75 *
76 * Example: http://example.org//foo///bar.html → http://example.org/foo/bar.html
77 */
78 public const REMOVE_DUPLICATE_SLASHES = 64;
79 /**
80 * Sort query parameters with their values in alphabetical order.
81 *
82 * However, the order of parameters in a URI may be significant (this is not defined by the standard).
83 * So this normalization is not safe and may change the semantics of the URI.
84 *
85 * Example: ?lang=en&article=fred → ?article=fred&lang=en
86 *
87 * Note: The sorting is neither locale nor Unicode aware (the URI query does not get decoded at all) as the
88 * purpose is to be able to compare URIs in a reproducible way, not to have the params sorted perfectly.
89 */
90 public const SORT_QUERY_PARAMETERS = 128;
91 /**
92 * Returns a normalized URI.
93 *
94 * The scheme and host component are already normalized to lowercase per PSR-7 UriInterface.
95 * This methods adds additional normalizations that can be configured with the $flags parameter.
96 *
97 * PSR-7 UriInterface cannot distinguish between an empty component and a missing component as
98 * getQuery(), getFragment() etc. always return a string. This means the URIs "/?#" and "/" are
99 * treated equivalent which is not necessarily true according to RFC 3986. But that difference
100 * is highly uncommon in reality. So this potential normalization is implied in PSR-7 as well.
101 *
102 * @param UriInterface $uri The URI to normalize
103 * @param int $flags A bitmask of normalizations to apply, see constants
104 *
105 * @see https://datatracker.ietf.org/doc/html/rfc3986#section-6.2
106 */
107 public static function normalize(UriInterface $uri, int $flags = self::PRESERVING_NORMALIZATIONS) : UriInterface
108 {
109 if ($flags & self::CAPITALIZE_PERCENT_ENCODING) {
110 $uri = self::capitalizePercentEncoding($uri);
111 }
112 if ($flags & self::DECODE_UNRESERVED_CHARACTERS) {
113 $uri = self::decodeUnreservedCharacters($uri);
114 }
115 if ($flags & self::CONVERT_EMPTY_PATH && $uri->getPath() === '' && ($uri->getScheme() === 'http' || $uri->getScheme() === 'https')) {
116 $uri = $uri->withPath('/');
117 }
118 if ($flags & self::REMOVE_DEFAULT_HOST && $uri->getScheme() === 'file' && $uri->getHost() === 'localhost') {
119 $uri = $uri->withHost('');
120 }
121 if ($flags & self::REMOVE_DEFAULT_PORT && $uri->getPort() !== null && Uri::isDefaultPort($uri)) {
122 $uri = $uri->withPort(null);
123 }
124 if ($flags & self::REMOVE_DOT_SEGMENTS && !Uri::isRelativePathReference($uri)) {
125 $uri = $uri->withPath(UriResolver::removeDotSegments($uri->getPath()));
126 }
127 if ($flags & self::REMOVE_DUPLICATE_SLASHES) {
128 $uri = $uri->withPath(\preg_replace('#//++#', '/', $uri->getPath()));
129 }
130 if ($flags & self::SORT_QUERY_PARAMETERS && $uri->getQuery() !== '') {
131 $queryKeyValues = \explode('&', $uri->getQuery());
132 \sort($queryKeyValues);
133 $uri = $uri->withQuery(\implode('&', $queryKeyValues));
134 }
135 return $uri;
136 }
137 /**
138 * Whether two URIs can be considered equivalent.
139 *
140 * Both URIs are normalized automatically before comparison with the given $normalizations bitmask. The method also
141 * accepts relative URI references and returns true when they are equivalent. This of course assumes they will be
142 * resolved against the same base URI. If this is not the case, determination of equivalence or difference of
143 * relative references does not mean anything.
144 *
145 * @param UriInterface $uri1 An URI to compare
146 * @param UriInterface $uri2 An URI to compare
147 * @param int $normalizations A bitmask of normalizations to apply, see constants
148 *
149 * @see https://datatracker.ietf.org/doc/html/rfc3986#section-6.1
150 */
151 public static function isEquivalent(UriInterface $uri1, UriInterface $uri2, int $normalizations = self::PRESERVING_NORMALIZATIONS) : bool
152 {
153 return (string) self::normalize($uri1, $normalizations) === (string) self::normalize($uri2, $normalizations);
154 }
155 private static function capitalizePercentEncoding(UriInterface $uri) : UriInterface
156 {
157 $regex = '/(?:%[A-Fa-f0-9]{2})++/';
158 $callback = function (array $match) : string {
159 return \strtoupper($match[0]);
160 };
161 return $uri->withPath(\preg_replace_callback($regex, $callback, $uri->getPath()))->withQuery(\preg_replace_callback($regex, $callback, $uri->getQuery()));
162 }
163 private static function decodeUnreservedCharacters(UriInterface $uri) : UriInterface
164 {
165 $regex = '/%(?:2D|2E|5F|7E|3[0-9]|[46][1-9A-F]|[57][0-9A])/i';
166 $callback = function (array $match) : string {
167 return \rawurldecode($match[0]);
168 };
169 return $uri->withPath(\preg_replace_callback($regex, $callback, $uri->getPath()))->withQuery(\preg_replace_callback($regex, $callback, $uri->getQuery()));
170 }
171 private function __construct()
172 {
173 // cannot be instantiated
174 }
175 }
176