UriPartsFilter.php 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. <?php
  2. /**
  3. * @package Grav\Framework\Uri
  4. *
  5. * @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
  6. * @license MIT License; see LICENSE file for details.
  7. */
  8. namespace Grav\Framework\Uri;
  9. use InvalidArgumentException;
  10. use function is_int;
  11. use function is_string;
  12. /**
  13. * Class Uri
  14. * @package Grav\Framework\Uri
  15. */
  16. class UriPartsFilter
  17. {
  18. const HOSTNAME_REGEX = '/^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/u';
  19. /**
  20. * @param string $scheme
  21. * @return string
  22. * @throws InvalidArgumentException If the scheme is invalid.
  23. */
  24. public static function filterScheme($scheme)
  25. {
  26. if (!is_string($scheme)) {
  27. throw new InvalidArgumentException('Uri scheme must be a string');
  28. }
  29. return strtolower($scheme);
  30. }
  31. /**
  32. * Filters the user info string.
  33. *
  34. * @param string $info The raw user or password.
  35. * @return string The percent-encoded user or password string.
  36. * @throws InvalidArgumentException
  37. */
  38. public static function filterUserInfo($info)
  39. {
  40. if (!is_string($info)) {
  41. throw new InvalidArgumentException('Uri user info must be a string');
  42. }
  43. return preg_replace_callback(
  44. '/(?:[^a-zA-Z0-9_\-\.~!\$&\'\(\)\*\+,;=]+|%(?![A-Fa-f0-9]{2}))/u',
  45. function ($match) {
  46. return rawurlencode($match[0]);
  47. },
  48. $info
  49. ) ?? '';
  50. }
  51. /**
  52. * @param string $host
  53. * @return string
  54. * @throws InvalidArgumentException If the host is invalid.
  55. */
  56. public static function filterHost($host)
  57. {
  58. if (!is_string($host)) {
  59. throw new InvalidArgumentException('Uri host must be a string');
  60. }
  61. if (filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
  62. $host = '[' . $host . ']';
  63. } elseif ($host && preg_match(static::HOSTNAME_REGEX, $host) !== 1) {
  64. throw new InvalidArgumentException('Uri host name validation failed');
  65. }
  66. return strtolower($host);
  67. }
  68. /**
  69. * Filter Uri port.
  70. *
  71. * This method
  72. *
  73. * @param int|null $port
  74. * @return int|null
  75. * @throws InvalidArgumentException If the port is invalid.
  76. */
  77. public static function filterPort($port = null)
  78. {
  79. if (null === $port || (is_int($port) && ($port >= 0 && $port <= 65535))) {
  80. return $port;
  81. }
  82. throw new InvalidArgumentException('Uri port must be null or an integer between 0 and 65535');
  83. }
  84. /**
  85. * Filter Uri path.
  86. *
  87. * This method percent-encodes all reserved characters in the provided path string. This method
  88. * will NOT double-encode characters that are already percent-encoded.
  89. *
  90. * @param string $path The raw uri path.
  91. * @return string The RFC 3986 percent-encoded uri path.
  92. * @throws InvalidArgumentException If the path is invalid.
  93. * @link http://www.faqs.org/rfcs/rfc3986.html
  94. */
  95. public static function filterPath($path)
  96. {
  97. if (!is_string($path)) {
  98. throw new InvalidArgumentException('Uri path must be a string');
  99. }
  100. return preg_replace_callback(
  101. '/(?:[^a-zA-Z0-9_\-\.~:@&=\+\$,\/;%]+|%(?![A-Fa-f0-9]{2}))/u',
  102. function ($match) {
  103. return rawurlencode($match[0]);
  104. },
  105. $path
  106. ) ?? '';
  107. }
  108. /**
  109. * Filters the query string or fragment of a URI.
  110. *
  111. * @param string $query The raw uri query string.
  112. * @return string The percent-encoded query string.
  113. * @throws InvalidArgumentException If the query is invalid.
  114. */
  115. public static function filterQueryOrFragment($query)
  116. {
  117. if (!is_string($query)) {
  118. throw new InvalidArgumentException('Uri query string and fragment must be a string');
  119. }
  120. return preg_replace_callback(
  121. '/(?:[^a-zA-Z0-9_\-\.~!\$&\'\(\)\*\+,;=%:@\/\?]+|%(?![A-Fa-f0-9]{2}))/u',
  122. function ($match) {
  123. return rawurlencode($match[0]);
  124. },
  125. $query
  126. ) ?? '';
  127. }
  128. }