Skip to content

Commit 05a7321

Browse files
committed
Improve RFC3986 parsing validation
1 parent 0e79ec1 commit 05a7321

File tree

1 file changed

+44
-0
lines changed

1 file changed

+44
-0
lines changed

UriString.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,50 @@ public static function parse(Stringable|string|int $uri): array
583583
]
584584
);
585585

586+
return self::validateComponents($components);
587+
}
588+
589+
/**
590+
* Assert the URI internal state is valid.
591+
*
592+
* @link https://tools.ietf.org/html/rfc3986#section-3
593+
* @link https://tools.ietf.org/html/rfc3986#section-3.3
594+
*
595+
* @param ComponentMap $components
596+
*
597+
* @throws SyntaxError
598+
*
599+
* @return ComponentMap
600+
*/
601+
private static function validateComponents(array $components): array
602+
{
603+
$authority = UriString::buildAuthority($components);
604+
$path = $components['path'];
605+
606+
if (null !== $authority) {
607+
if (null !== $path && '' !== $path && '/' !== $path[0]) {
608+
throw new SyntaxError('If an authority is present the path must be empty or start with a `/`.');
609+
}
610+
611+
return $components;
612+
}
613+
614+
if (null === $path || '' === $path) {
615+
return $components;
616+
}
617+
618+
if (str_starts_with($path, '//')) {
619+
throw new SyntaxError('If there is no authority the path `'.$path.'` cannot start with a `//`.');
620+
}
621+
622+
if (null !== $components['scheme'] || false === ($pos = strpos($path, ':'))) {
623+
return $components;
624+
}
625+
626+
if (!str_contains(substr($path, 0, $pos), '/')) {
627+
throw new SyntaxError('In absence of a scheme and an authority the first path segment cannot contain a colon (":") character.');
628+
}
629+
586630
return $components;
587631
}
588632

0 commit comments

Comments
 (0)