酒店预订平台
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

93 lines
2.7 KiB

  1. <?php
  2. namespace GuzzleHttp;
  3. use GuzzleHttp\Exception\InvalidArgumentException;
  4. use Psr\Http\Message\UriInterface;
  5. use Symfony\Polyfill\Intl\Idn\Idn;
  6. final class Utils
  7. {
  8. /**
  9. * Wrapper for the hrtime() or microtime() functions
  10. * (depending on the PHP version, one of the two is used)
  11. *
  12. * @return float|mixed UNIX timestamp
  13. *
  14. * @internal
  15. */
  16. public static function currentTime()
  17. {
  18. return function_exists('hrtime') ? hrtime(true) / 1e9 : microtime(true);
  19. }
  20. /**
  21. * @param int $options
  22. *
  23. * @return UriInterface
  24. * @throws InvalidArgumentException
  25. *
  26. * @internal
  27. */
  28. public static function idnUriConvert(UriInterface $uri, $options = 0)
  29. {
  30. if ($uri->getHost()) {
  31. $asciiHost = self::idnToAsci($uri->getHost(), $options, $info);
  32. if ($asciiHost === false) {
  33. $errorBitSet = isset($info['errors']) ? $info['errors'] : 0;
  34. $errorConstants = array_filter(array_keys(get_defined_constants()), function ($name) {
  35. return substr($name, 0, 11) === 'IDNA_ERROR_';
  36. });
  37. $errors = [];
  38. foreach ($errorConstants as $errorConstant) {
  39. if ($errorBitSet & constant($errorConstant)) {
  40. $errors[] = $errorConstant;
  41. }
  42. }
  43. $errorMessage = 'IDN conversion failed';
  44. if ($errors) {
  45. $errorMessage .= ' (errors: ' . implode(', ', $errors) . ')';
  46. }
  47. throw new InvalidArgumentException($errorMessage);
  48. } else {
  49. if ($uri->getHost() !== $asciiHost) {
  50. // Replace URI only if the ASCII version is different
  51. $uri = $uri->withHost($asciiHost);
  52. }
  53. }
  54. }
  55. return $uri;
  56. }
  57. /**
  58. * @param string $domain
  59. * @param int $options
  60. * @param array $info
  61. *
  62. * @return string|false
  63. */
  64. private static function idnToAsci($domain, $options, &$info = [])
  65. {
  66. if (\preg_match('%^[ -~]+$%', $domain) === 1) {
  67. return $domain;
  68. }
  69. if (\extension_loaded('intl') && defined('INTL_IDNA_VARIANT_UTS46')) {
  70. return \idn_to_ascii($domain, $options, INTL_IDNA_VARIANT_UTS46, $info);
  71. }
  72. /*
  73. * The Idn class is marked as @internal. Verify that class and method exists.
  74. */
  75. if (method_exists(Idn::class, 'idn_to_ascii')) {
  76. return Idn::idn_to_ascii($domain, $options, Idn::INTL_IDNA_VARIANT_UTS46, $info);
  77. }
  78. throw new \RuntimeException('ext-intl or symfony/polyfill-intl-idn not loaded or too old');
  79. }
  80. }