isValidSchemeName: Add function

(cherry picked from commit d3a85b6834)
This commit is contained in:
Robert Hensing 2023-12-06 15:14:41 +01:00
parent 772a8efff4
commit 2116ee2454
3 changed files with 44 additions and 0 deletions

View File

@ -2,6 +2,7 @@
#include "url-parts.hh"
#include "util.hh"
#include "split.hh"
#include "string.hh"
namespace nix {
@ -175,4 +176,20 @@ std::string fixGitURL(const std::string & url)
}
}
// https://www.rfc-editor.org/rfc/rfc3986#section-3.1
bool isValidSchemeName(std::string_view s)
{
if (s.empty()) return false;
if (!isASCIIAlpha(s[0])) return false;
for (auto c : s.substr(1)) {
if (isASCIIAlpha(c)) continue;
if (isASCIIDigit(c)) continue;
if (c == '+') continue;
if (c == '-') continue;
if (c == '.') continue;
return false;
}
return true;
}
}

View File

@ -50,4 +50,13 @@ ParsedUrlScheme parseUrlScheme(std::string_view scheme);
changes absolute paths into file:// URLs. */
std::string fixGitURL(const std::string & url);
/**
* Whether a string is valid as RFC 3986 scheme name.
* Colon `:` is part of the URI; not the scheme name, and therefore rejected.
* See https://www.rfc-editor.org/rfc/rfc3986#section-3.1
*
* Does not check whether the scheme is understood, as that's context-dependent.
*/
bool isValidSchemeName(std::string_view scheme);
}

View File

@ -344,4 +344,22 @@ namespace nix {
ASSERT_EQ(percentDecode(e), s);
}
TEST(nix, isValidSchemeName) {
ASSERT_TRUE(isValidSchemeName("http"));
ASSERT_TRUE(isValidSchemeName("https"));
ASSERT_TRUE(isValidSchemeName("file"));
ASSERT_TRUE(isValidSchemeName("file+https"));
ASSERT_TRUE(isValidSchemeName("fi.le"));
ASSERT_TRUE(isValidSchemeName("file-ssh"));
ASSERT_TRUE(isValidSchemeName("file+"));
ASSERT_TRUE(isValidSchemeName("file."));
ASSERT_TRUE(isValidSchemeName("file1"));
ASSERT_FALSE(isValidSchemeName("file:"));
ASSERT_FALSE(isValidSchemeName("file/"));
ASSERT_FALSE(isValidSchemeName("+file"));
ASSERT_FALSE(isValidSchemeName(".file"));
ASSERT_FALSE(isValidSchemeName("-file"));
ASSERT_FALSE(isValidSchemeName("1file"));
}
}