Skip to content

Commit

Permalink
Ignore unicode for auto-save path and special symbols for default fil…
Browse files Browse the repository at this point in the history
…ename

Also refactor and add tests.
  • Loading branch information
black-sliver committed Aug 29, 2024
1 parent 53ad682 commit 163ca54
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 15 deletions.
11 changes: 1 addition & 10 deletions src/core/statemanager.cpp
Original file line number Diff line number Diff line change
@@ -1,22 +1,13 @@
#include "statemanager.h"
#include "jsonutil.h"
#include "fileutil.h"
#include "util.h"
#include <nlohmann/json.hpp>
using nlohmann::json;

std::map<StateManager::StateID, json> StateManager::_states;
std::string StateManager::_dir;

static std::string sanitize_dir(std::string s)
{
if (s.empty()) return "_";
if ((size_t)std::count(s.begin(), s.end(), '.') == s.length()) return "_";
std::replace(s.begin(), s.end(), '/', '_');
std::replace(s.begin(), s.end(), '\\', '_');
std::replace(s.begin(), s.end(), ':', '_');
return s;
}

void StateManager::setDir(const std::string& dir)
{
_dir = dir;
Expand Down
28 changes: 23 additions & 5 deletions src/core/util.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#ifndef _CORE_UTIL_H
#define _CORE_UTIL_H

#include <stddef.h>
#include <algorithm>
#include <cstddef>
#include <cstring>


template< class Type, ptrdiff_t n >
static ptrdiff_t countOf( Type (&)[n] ) { return n; }
Expand All @@ -12,10 +15,25 @@ static std::string sanitize_print(const std::string& s) {
return res;
}

static std::string sanitize_filename(const std::string& s) {
std::string res = s;
for (auto& c: res) if (c<0x20 || c=='/' || c=='\\' || c==':') c = '_';
return res;
/// Replaces reserved/non-portable symbols by '_'.
static std::string sanitize_filename(std::string s) {
auto exclude = "<>:\"/\\|?*$'`";
auto sanitize = [&](char c) { return strchr(exclude, c) || c == 0; };
std::replace_if(s.begin(), s.end(), sanitize, '_');
return s;
}

/// Replaces non-ASCII and reserved/non-portable symbols by '_'. Returns "_" for empty and resrved folder names.
static std::string sanitize_dir(std::string s)
{
if (s.empty())
return "_";
if ((size_t)std::count(s.begin(), s.end(), '.') == s.length())
return "_";
auto exclude = "<>:\"/\\|?*$'`";
auto sanitize = [&](char c) { return c<0x20 || strchr(exclude, c); };
std::replace_if(s.begin(), s.end(), sanitize, '_');
return s;
}

template<typename T>
Expand Down
41 changes: 41 additions & 0 deletions test/core/test_util.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <gtest/gtest.h>
#include "../../src/core/util.h"


TEST(SanitizeFilenameTest, InvalidSymbol) {
EXPECT_EQ(sanitize_filename({"a\x00z", 3}), "a_z");
EXPECT_EQ(sanitize_filename("ä"), "ä");
EXPECT_EQ(sanitize_filename("a*b"), "a_b");
EXPECT_EQ(sanitize_filename("a/b"), "a_b");
EXPECT_EQ(sanitize_filename("a\\b"), "a_b");
}

TEST(SanitizeFilenameTest, Empty) {
// allow empty filename
EXPECT_EQ(sanitize_filename(""), "");
}

TEST(SanitizeDirTest, InvalidSymbol) {
EXPECT_EQ(sanitize_dir({"a\x00z", 3}), "a_z");
EXPECT_EQ(sanitize_dir("a\x01z"), "a_z");
EXPECT_EQ(sanitize_dir("a\x80z"), "a_z");
EXPECT_EQ(sanitize_dir("a*b"), "a_b");
EXPECT_EQ(sanitize_dir("a/b"), "a_b");
EXPECT_EQ(sanitize_dir("a\\b"), "a_b");
}

TEST(SanitizeDirTest, Empty) {
// can't have an empty dirname
EXPECT_EQ(sanitize_dir(""), "_");
}

TEST(SanitizeDirTest, NoCWD) {
EXPECT_EQ(sanitize_dir("."), "_");
EXPECT_EQ(sanitize_dir("./"), "._");
}

TEST(SanitizeDirTest, NoParent) {
EXPECT_EQ(sanitize_dir(".."), "_");
EXPECT_EQ(sanitize_dir("../"), ".._");
EXPECT_EQ(sanitize_dir("..\\"), ".._");
}

0 comments on commit 163ca54

Please sign in to comment.