PluginProbe ʕ •ᴥ•ʔ
Transferito: WP Migration / trunk
Transferito: WP Migration vtrunk
trunk 11.4.0 12.0.0 13.1.0 14.0.0 14.0.11 14.0.7 14.1.0 14.1.1 14.1.2 14.1.3 14.1.4
transferito / vendor / aws / aws-sdk-php / src / EndpointV2 / Ruleset / RulesetStandardLibrary.php
transferito / vendor / aws / aws-sdk-php / src / EndpointV2 / Ruleset Last commit date
Ruleset.php 11 months ago RulesetEndpoint.php 11 months ago RulesetParameter.php 11 months ago RulesetStandardLibrary.php 11 months ago
RulesetStandardLibrary.php
429 lines
1 <?php
2
3 namespace Aws\EndpointV2\Ruleset;
4
5 use Aws\Exception\UnresolvedEndpointException;
6
7 /**
8 * Provides functions and actions to be performed for endpoint evaluation.
9 * This is an internal only class and is not subject to backwards-compatibility guarantees.
10 *
11 * @internal
12 */
13 class RulesetStandardLibrary
14 {
15 const IPV4_RE = '/^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/';
16 const IPV6_RE = '/([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|
17 . ([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]
18 . {1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:)
19 . {1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|
20 . [0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:
21 . (:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|
22 . 1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]
23 . {1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]
24 . |1{0,1}[0-9]){0,1}[0-9])/';
25 const TEMPLATE_ESCAPE_RE = '/{\{\s*(.*?)\s*\}\}/';
26 const TEMPLATE_SEARCH_RE = '/\{[a-zA-Z#]+\}/';
27 const TEMPLATE_PARSE_RE = '#\{((?>[^\{\}]+)|(?R))*\}#x';
28 const HOST_LABEL_RE = '/^(?!-)[a-zA-Z\d-]{1,63}(?<!-)$/';
29
30 private $partitions;
31
32 public function __construct($partitions)
33 {
34 $this->partitions = $partitions;
35 }
36
37 /**
38 * Determines if a value is set.
39 *
40 * @return boolean
41 */
42 public function is_set($value)
43 {
44 return isset($value);
45 }
46
47 /**
48 * Function implementation of logical operator `not`
49 *
50 * @return boolean
51 */
52 public function not($value)
53 {
54 return !$value;
55 }
56
57 /**
58 * Find an attribute within a value given a path string.
59 *
60 * @return mixed
61 */
62 public function getAttr($from, $path)
63 {
64 $parts = explode('.', $path);
65 foreach ($parts as $part) {
66 $sliceIdx = strpos($part, '[');
67 if ($sliceIdx !== false) {
68 if (substr($part, -1) !== ']') {
69 return null;
70 }
71 $slice = intval(substr($part, $sliceIdx + 1, strlen($part) - 1));
72 $from = isset($from[substr($part,0, $sliceIdx)][$slice])
73 ? $from[substr($part,0, $sliceIdx)][$slice]
74 : null;
75 } else {
76 $from = $from[$part];
77 }
78 }
79 return $from;
80 }
81
82 /**
83 * Computes a substring given the start index and end index. If `reverse` is
84 * true, slice the string from the end instead.
85 *
86 * @return mixed
87 */
88 public function substring($input, $start, $stop, $reverse)
89 {
90 if (!is_string($input)) {
91 throw new UnresolvedEndpointException(
92 'Input passed to `substring` must be `string`.'
93 );
94 }
95
96 if (preg_match('/[^\x00-\x7F]/', $input)) {
97 return null;
98 }
99 if ($start >= $stop or strlen($input) < $stop) {
100 return null;
101 }
102 if (!$reverse) {
103 return substr($input, $start, $stop - $start);
104 } else {
105 $offset = strlen($input) - $stop;
106 $length = $stop - $start;
107 return substr($input, $offset, $length);
108 }
109 }
110
111 /**
112 * Evaluates two strings for equality.
113 *
114 * @return boolean
115 */
116 public function stringEquals($string1, $string2)
117 {
118 if (!is_string($string1) || !is_string($string2)) {
119 throw new UnresolvedEndpointException(
120 'Values passed to StringEquals must be `string`.'
121 );
122 }
123 return $string1 === $string2;
124 }
125
126 /**
127 * Evaluates two booleans for equality.
128 *
129 * @return boolean
130 */
131 public function booleanEquals($boolean1, $boolean2)
132 {
133 return
134 filter_var($boolean1, FILTER_VALIDATE_BOOLEAN)
135 === filter_var($boolean2, FILTER_VALIDATE_BOOLEAN);
136 }
137
138 /**
139 * Percent-encodes an input string.
140 *
141 * @return mixed
142 */
143 public function uriEncode($input)
144 {
145 if (is_null($input)) {
146 return null;
147 }
148 return str_replace('%7E', '~', rawurlencode($input));
149 }
150
151 /**
152 * Parses URL string into components.
153 *
154 * @return mixed
155 */
156 public function parseUrl($url)
157 {
158 if (is_null($url)) {
159 return null;
160 }
161
162 $parsed = parse_url($url);
163
164 if ($parsed === false || !empty($parsed['query'])) {
165 return null;
166 } elseif (!isset($parsed['scheme'])) {
167 return null;
168 }
169
170 if ($parsed['scheme'] !== 'http'
171 && $parsed['scheme'] !== 'https'
172 ) {
173 return null;
174 }
175
176 $urlInfo = [];
177 $urlInfo['scheme'] = $parsed['scheme'];
178 $urlInfo['authority'] = isset($parsed['host']) ? $parsed['host'] : '';
179 if (isset($parsed['port'])) {
180 $urlInfo['authority'] = $urlInfo['authority'] . ":" . $parsed['port'];
181 }
182 $urlInfo['path'] = isset($parsed['path']) ? $parsed['path'] : '';
183 $urlInfo['normalizedPath'] = !empty($parsed['path'])
184 ? rtrim($urlInfo['path'] ?: '', '/' . "/") . '/'
185 : '/';
186 $urlInfo['isIp'] = !isset($parsed['host']) ?
187 'false' : $this->isValidIp($parsed['host']);
188
189 return $urlInfo;
190 }
191
192 /**
193 * Evaluates whether a value is a valid host label per
194 * RFC 1123. If allow_subdomains is true, split on `.` and validate
195 * each subdomain separately.
196 *
197 * @return boolean
198 */
199 public function isValidHostLabel($hostLabel, $allowSubDomains)
200 {
201 if (!isset($hostLabel)
202 || (!$allowSubDomains && strpos($hostLabel, '.') != false)
203 ) {
204 return false;
205 }
206
207 if ($allowSubDomains) {
208 foreach (explode('.', $hostLabel) as $subdomain) {
209 if (!$this->validateHostLabel($subdomain)) {
210 return false;
211 }
212 }
213 return true;
214 } else {
215 return $this->validateHostLabel($hostLabel);
216 }
217 }
218
219 /**
220 * Parse and validate string for ARN components.
221 *
222 * @return array|null
223 */
224 public function parseArn($arnString)
225 {
226 if (is_null($arnString)
227 || substr( $arnString, 0, 3 ) !== "arn"
228 ) {
229 return null;
230 }
231
232 $arn = [];
233 $parts = explode(':', $arnString, 6);
234 if (sizeof($parts) < 6) {
235 return null;
236 }
237
238 $arn['partition'] = isset($parts[1]) ? $parts[1] : null;
239 $arn['service'] = isset($parts[2]) ? $parts[2] : null;
240 $arn['region'] = isset($parts[3]) ? $parts[3] : null;
241 $arn['accountId'] = isset($parts[4]) ? $parts[4] : null;
242 $arn['resourceId'] = isset($parts[5]) ? $parts[5] : null;
243
244 if (empty($arn['partition'])
245 || empty($arn['service'])
246 || empty($arn['resourceId'])
247 ) {
248 return null;
249 }
250 $resource = $arn['resourceId'];
251 $arn['resourceId'] = preg_split("/[:\/]/", $resource);
252
253 return $arn;
254 }
255
256 /**
257 * Matches a region string to an AWS partition.
258 *
259 * @return mixed
260 */
261 public function partition($region)
262 {
263 if (!is_string($region)) {
264 throw new UnresolvedEndpointException(
265 'Value passed to `partition` must be `string`.'
266 );
267 }
268
269 $partitions = $this->partitions;
270 foreach ($partitions['partitions'] as $partition) {
271 if (array_key_exists($region, $partition['regions'])
272 || preg_match("/{$partition['regionRegex']}/", $region)
273 ) {
274 return $partition['outputs'];
275 }
276 }
277 //return `aws` partition if no match is found.
278 return $partitions['partitions'][0]['outputs'];
279 }
280
281 /**
282 * Evaluates whether a value is a valid bucket name for virtual host
283 * style bucket URLs.
284 *
285 * @return boolean
286 */
287 public function isVirtualHostableS3Bucket($bucketName, $allowSubdomains)
288 {
289 if ((is_null($bucketName)
290 || (strlen($bucketName) < 3 || strlen($bucketName) > 63))
291 || preg_match(self::IPV4_RE, $bucketName)
292 || strtolower($bucketName) !== $bucketName
293 ) {
294 return false;
295 }
296
297 if ($allowSubdomains) {
298 $labels = explode('.', $bucketName);
299 $results = [];
300 forEach($labels as $label) {
301 $results[] = $this->isVirtualHostableS3Bucket($label, false);
302 }
303 return !in_array(false, $results);
304 }
305 return $this->isValidHostLabel($bucketName, false);
306 }
307
308 public function callFunction($funcCondition, &$inputParameters)
309 {
310 $funcArgs = [];
311
312 forEach($funcCondition['argv'] as $arg) {
313 $funcArgs[] = $this->resolveValue($arg, $inputParameters);
314 }
315
316 $funcName = str_replace('aws.', '', $funcCondition['fn']);
317 if ($funcName === 'isSet') {
318 $funcName = 'is_set';
319 }
320
321 $result = call_user_func_array(
322 [RulesetStandardLibrary::class, $funcName],
323 $funcArgs
324 );
325
326 if (isset($funcCondition['assign'])) {
327 $assign = $funcCondition['assign'];
328 if (isset($inputParameters[$assign])){
329 throw new UnresolvedEndpointException(
330 "Assignment `{$assign}` already exists in input parameters" .
331 " or has already been assigned by an endpoint rule and cannot be overwritten."
332 );
333 }
334 $inputParameters[$assign] = $result;
335 }
336 return $result;
337 }
338
339 public function resolveValue($value, $inputParameters)
340 {
341 //Given a value, check if it's a function, reference or template.
342 //returns resolved value
343 if ($this->isFunc($value)) {
344 return $this->callFunction($value, $inputParameters);
345 } elseif ($this->isRef($value)) {
346 return isset($inputParameters[$value['ref']]) ? $inputParameters[$value['ref']] : null;
347 } elseif ($this->isTemplate($value)) {
348 return $this->resolveTemplateString($value, $inputParameters);
349 }
350 return $value;
351 }
352
353 public function isFunc($arg)
354 {
355 return is_array($arg) && isset($arg['fn']);
356 }
357
358 public function isRef($arg)
359 {
360 return is_array($arg) && isset($arg['ref']);
361 }
362
363 public function isTemplate($arg)
364 {
365 return is_string($arg) && !empty(preg_match(self::TEMPLATE_SEARCH_RE, $arg));
366 }
367
368 public function resolveTemplateString($value, $inputParameters)
369 {
370 return preg_replace_callback(
371 self::TEMPLATE_PARSE_RE,
372 function ($match) use ($inputParameters) {
373 if (preg_match(self::TEMPLATE_ESCAPE_RE, $match[0])) {
374 return $match[1];
375 }
376
377 $notFoundMessage = 'Resolved value was null. Please check rules and ' .
378 'input parameters and try again.';
379
380 $parts = explode("#", $match[1]);
381 if (count($parts) > 1) {
382 $resolvedValue = $inputParameters;
383 foreach($parts as $part) {
384 if (!isset($resolvedValue[$part])) {
385 throw new UnresolvedEndpointException($notFoundMessage);
386 }
387 $resolvedValue = $resolvedValue[$part];
388 }
389 return $resolvedValue;
390 } else {
391 if (!isset($inputParameters[$parts[0]])) {
392 throw new UnresolvedEndpointException($notFoundMessage);
393 }
394 return $inputParameters[$parts[0]];
395 }
396 },
397 $value
398 );
399 }
400
401 private function validateHostLabel ($hostLabel)
402 {
403 if (empty($hostLabel) || strlen($hostLabel) > 63) {
404 return false;
405 }
406 if (preg_match(self::HOST_LABEL_RE, $hostLabel)) {
407 return true;
408 }
409 return false;
410 }
411
412 private function isValidIp($hostName)
413 {
414 $isWrapped = strpos($hostName, '[') === 0
415 && strrpos($hostName, ']') === strlen($hostName) - 1;
416
417 return preg_match(
418 self::IPV4_RE,
419 $hostName
420 )
421 //IPV6 enclosed in brackets
422 || ($isWrapped && preg_match(
423 self::IPV6_RE,
424 $hostName
425 ))
426 ? 'true' : 'false';
427 }
428 }
429