mirror of
https://github.com/stenzek/duckstation.git
synced 2026-02-13 01:44:33 +00:00
Path: Add IsFileNameValid()
This commit is contained in:
@@ -6,6 +6,10 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <string_view>
|
||||
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
TEST(Path, ToNativePath)
|
||||
{
|
||||
ASSERT_EQ(Path::ToNativePath(""), "");
|
||||
@@ -234,6 +238,7 @@ TEST(Path, SanitizeFileName)
|
||||
ASSERT_EQ(Path::SanitizeFileName("abcdefghijlkmnopqrstuvwxyz-0123456789+&=_[]{}"),
|
||||
"abcdefghijlkmnopqrstuvwxyz-0123456789+&=_[]{}");
|
||||
ASSERT_EQ(Path::SanitizeFileName("some*path**with*asterisks"), "some_path__with_asterisks");
|
||||
ASSERT_EQ(Path::SanitizeFileName("foo\0bar"sv), "foo_bar");
|
||||
#ifdef _WIN32
|
||||
ASSERT_EQ(Path::SanitizeFileName("foo:"), "foo_");
|
||||
ASSERT_EQ(Path::SanitizeFileName("foo:bar."), "foo_bar_");
|
||||
@@ -244,6 +249,31 @@ TEST(Path, SanitizeFileName)
|
||||
ASSERT_EQ(Path::SanitizeFileName("foo/bar", false), "foo/bar");
|
||||
}
|
||||
|
||||
TEST(Path, IsFileNameValid)
|
||||
{
|
||||
ASSERT_TRUE(Path::IsFileNameValid("foo"sv));
|
||||
ASSERT_TRUE(Path::IsFileNameValid("foo_bar-0123456789+&=_[]{}"sv));
|
||||
ASSERT_TRUE(Path::IsFileNameValid("f🙃o"sv));
|
||||
ASSERT_TRUE(Path::IsFileNameValid("ŻąłóРстуぬねのはen🍪⟑η∏☉ⴤℹ︎∩₲ ₱⟑♰⫳🐱"sv));
|
||||
ASSERT_TRUE(Path::IsFileNameValid("foo/bar"sv, true));
|
||||
ASSERT_TRUE(Path::IsFileNameValid("foo\\bar"sv, true));
|
||||
ASSERT_FALSE(Path::IsFileNameValid("foo/bar"sv));
|
||||
ASSERT_FALSE(Path::IsFileNameValid("foo\0bar"sv));
|
||||
ASSERT_FALSE(Path::IsFileNameValid("foo\nbar"sv));
|
||||
#ifdef _WIN32
|
||||
ASSERT_FALSE(Path::IsFileNameValid("foo\\bar"sv));
|
||||
ASSERT_FALSE(Path::IsFileNameValid("foo:bar"sv));
|
||||
ASSERT_FALSE(Path::IsFileNameValid("foo*bar"sv));
|
||||
ASSERT_FALSE(Path::IsFileNameValid("foo?bar"sv));
|
||||
ASSERT_FALSE(Path::IsFileNameValid("foo\"bar"sv));
|
||||
ASSERT_FALSE(Path::IsFileNameValid("foo<bar"sv));
|
||||
ASSERT_FALSE(Path::IsFileNameValid("foo>bar"sv));
|
||||
ASSERT_FALSE(Path::IsFileNameValid("foo|bar"sv));
|
||||
ASSERT_FALSE(Path::IsFileNameValid("foobar.txt."sv));
|
||||
ASSERT_FALSE(Path::IsFileNameValid("foobar."sv));
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Path, RemoveLengthLimits)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
@@ -67,6 +67,10 @@ static bool IsUNCPath(const T& path)
|
||||
|
||||
static inline bool FileSystemCharacterIsSane(char32_t c, bool strip_slashes)
|
||||
{
|
||||
// no null bytes
|
||||
if (c == 0)
|
||||
return false;
|
||||
|
||||
#ifdef _WIN32
|
||||
// https://docs.microsoft.com/en-gb/windows/win32/fileio/naming-a-file?redirectedfrom=MSDN#naming-conventions
|
||||
if ((c == U'/' || c == U'\\') && strip_slashes)
|
||||
@@ -149,6 +153,26 @@ void Path::SanitizeFileName(std::string* str, bool strip_slashes /* = true */)
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Path::IsFileNameValid(std::string_view str, bool allow_slashes)
|
||||
{
|
||||
size_t pos = 0;
|
||||
while (pos < str.length())
|
||||
{
|
||||
char32_t ch;
|
||||
pos += StringUtil::DecodeUTF8(str, pos, &ch);
|
||||
if (!FileSystemCharacterIsSane(ch, !allow_slashes))
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// Windows: Can't end filename with a period.
|
||||
if (str.length() > 0 && str.back() == '.')
|
||||
return false;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string Path::RemoveLengthLimits(std::string_view str)
|
||||
{
|
||||
std::string ret;
|
||||
|
||||
@@ -36,6 +36,9 @@ void Canonicalize(std::string* path);
|
||||
std::string SanitizeFileName(std::string_view str, bool strip_slashes = true);
|
||||
void SanitizeFileName(std::string* str, bool strip_slashes = true);
|
||||
|
||||
/// Returns true if the given filename contains any invalid characters.
|
||||
bool IsFileNameValid(std::string_view str, bool allow_slashes = false);
|
||||
|
||||
/// Mutates the path to remove any MAX_PATH limits (for Windows).
|
||||
std::string RemoveLengthLimits(std::string_view str);
|
||||
void RemoveLengthLimits(std::string* path);
|
||||
|
||||
Reference in New Issue
Block a user