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