URL.cpp 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. /*
  2. * Copyright (c) 2023, Simon Wanner <simon@skyrising.xyz>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibUnicode/IDNA.h>
  7. #include <LibUnicode/URL.h>
  8. namespace Unicode {
  9. // https://url.spec.whatwg.org/#concept-domain-to-ascii
  10. static ErrorOr<String> domain_to_ascii(StringView domain, bool be_strict)
  11. {
  12. // 1. Let result be the result of running Unicode ToASCII with domain_name set to domain, UseSTD3ASCIIRules set to beStrict, CheckHyphens set to false, CheckBidi set to true, CheckJoiners set to true, Transitional_Processing set to false, and VerifyDnsLength set to beStrict. [UTS46]
  13. // 2. If result is a failure value, domain-to-ASCII validation error, return failure.
  14. Unicode::IDNA::ToAsciiOptions const options {
  15. Unicode::IDNA::CheckHyphens::No,
  16. Unicode::IDNA::CheckBidi::Yes,
  17. Unicode::IDNA::CheckJoiners::Yes,
  18. be_strict ? Unicode::IDNA::UseStd3AsciiRules::Yes : Unicode::IDNA::UseStd3AsciiRules::No,
  19. Unicode::IDNA::TransitionalProcessing::No,
  20. be_strict ? Unicode::IDNA::VerifyDnsLength::Yes : Unicode::IDNA::VerifyDnsLength::No
  21. };
  22. auto result = TRY(Unicode::IDNA::to_ascii(Utf8View(domain), options));
  23. // 3. If result is the empty string, domain-to-ASCII validation error, return failure.
  24. if (result.is_empty())
  25. return Error::from_string_literal("Empty domain");
  26. // 4. Return result.
  27. return result;
  28. }
  29. // https://url.spec.whatwg.org/#concept-host-parser
  30. ErrorOr<URL> create_unicode_url(String const& url_string)
  31. {
  32. // NOTE: 1.-4. are implemented in URLParser::parse_host
  33. URL url = url_string;
  34. if (!url.is_valid() || !url.host().has<String>())
  35. return url;
  36. auto& domain = url.host().get<String>();
  37. if (domain.is_empty())
  38. return url;
  39. // 5. Let asciiDomain be the result of running domain to ASCII with domain and false.
  40. // 6. If asciiDomain is failure, then return failure.
  41. auto ascii_domain = TRY(domain_to_ascii(domain.bytes_as_string_view(), false));
  42. // FIXME: Reimplement 7. or call into URLParser::parse_host using ascii_domain (8. & 9. do not apply)
  43. url.set_host(ascii_domain);
  44. return url;
  45. }
  46. }