| 42 | } |
| 43 | |
| 44 | Str FileUrlPathConverter::pathFromUrl(const std::string_view& url) const { |
| 45 | ada::result<ada::url_aggregator> adaUrl = ada::parse(url); |
| 46 | if (!adaUrl) { |
| 47 | throwError(kErrorUrlParseFailure, url); |
| 48 | } |
| 49 | |
| 50 | const std::string_view host = adaUrl->get_host(); |
| 51 | const std::string_view encodedPath = adaUrl->get_pathname(); |
| 52 | |
| 53 | std::string_view trimmedPath = encodedPath; |
| 54 | if (host.empty() && !encodedPath.empty()) { |
| 55 | // E.g. path of `file:///C:/` is `/C:/`, so trim leading `/`. |
| 56 | trimmedPath = encodedPath.substr(1); |
| 57 | } |
| 58 | |
| 59 | Str decodedPath = ada::unicode::percent_decode(trimmedPath, trimmedPath.find(kPercent)); |
| 60 | |
| 61 | // Note: validation is ordered to match swift-url's implementation, |
| 62 | // i.e. it satisfies the error priority of the test suite from the |
| 63 | // swift-url project, which we use for our unit tests. |
| 64 | |
| 65 | if (host.empty() && !driveLetterHandler.isAbsoluteDrivePath(decodedPath)) { |
| 66 | throwError(kErrorRelativePath, url); |
| 67 | } |
| 68 | if (GenericPath::containsNullByte(decodedPath)) { |
| 69 | throwError(kErrorNullByte, url); |
| 70 | } |
| 71 | if (urlHandler.containsPercentEncodedSlash(encodedPath)) { |
| 72 | throwError(kErrorEncodedSeparator, url); |
| 73 | } |
| 74 | if (!host.empty() && uncHostHandler.isInvalidHostname(host)) { |
| 75 | throwError(kErrorUnsupportedHostname, url); |
| 76 | } |
| 77 | |
| 78 | Str windowsPath; |
| 79 | if (!host.empty()) { |
| 80 | windowsPath += kDoubleBackSlash; |
| 81 | if (const auto ip6Host = urlHandler.ip6ToValidHostname(host)) { |
| 82 | windowsPath += *ip6Host; |
| 83 | } else { |
| 84 | windowsPath += host; |
| 85 | } |
| 86 | } |
| 87 | |
| 88 | decodedPath = |
| 89 | forwardSlashSeparatedStringHandler.removeTrailingForwardSlashesInPathSegments(decodedPath); |
| 90 | windowsPath += decodedPath; |
| 91 | |
| 92 | std::replace(windowsPath.begin(), windowsPath.end(), kForwardSlash, kBackSlash); |
| 93 | |
| 94 | if (windowsPath.size() > kMaxPath) { |
| 95 | windowsPath = host.empty() |
| 96 | ? pathTypes::UncUnnormalisedDeviceDrivePath::prefixDrivePath(windowsPath) |
| 97 | : pathTypes::UncUnnormalisedDeviceSharePath::prefixUncSharePath(windowsPath); |
| 98 | } |
| 99 | |
| 100 | return windowsPath; |
| 101 | } |
nothing calls this directly
no test coverage detected