Sync.
This commit is contained in:
@@ -245,7 +245,7 @@ std::string HtmlHelper::Rfc5987EncodeFileName(const std::string &name)
|
||||
|
||||
#define MAX_FILE_NAME_LENGHT 96
|
||||
|
||||
const std::string SF_SPECIALS = " <>@;:\"\'/[]?=";
|
||||
const std::string SF_SPECIALS = " <>@;:\"\'/[]?=+";
|
||||
|
||||
std::string HtmlHelper::SafeFileName(const std::string &name)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2022 Robin Davies
|
||||
// Copyright (c) 2026 Robin Davies
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
@@ -57,6 +57,25 @@
|
||||
} \
|
||||
;
|
||||
|
||||
|
||||
#define JSON_GETTER_SETTER_REF(name) \
|
||||
const decltype(name##_) &name() const { return name##_; } \
|
||||
decltype(name##_) &name() { return name##_; } \
|
||||
void name(const decltype(name##_) &value) { name##_ = value; }
|
||||
|
||||
#define JSON_GETTER_SETTER(name) \
|
||||
decltype(name##_) name() const { return name##_; } \
|
||||
void name(decltype(name##_) value) { name##_ = value; }
|
||||
|
||||
|
||||
#define JSON_GETTER_REF(name) \
|
||||
const decltype(name##_) &name() const { return name##_; } \
|
||||
decltype(name##_) &name() { return name##_; }
|
||||
|
||||
#define JSON_GETTER(name) \
|
||||
decltype(name##_) name() const { return name##_; }
|
||||
|
||||
|
||||
namespace pipedal
|
||||
{
|
||||
class JsonException: public std::runtime_error {
|
||||
|
||||
@@ -124,5 +124,7 @@ namespace pipedal
|
||||
|
||||
std::string ToLower(const std::string&value);
|
||||
|
||||
std::string safeFilenameToString(const std::string &filename);
|
||||
std::string stringToSafeFilename(const std::string &name);
|
||||
|
||||
}
|
||||
|
||||
@@ -575,7 +575,7 @@ void json_reader::skip_object()
|
||||
}
|
||||
skip_string(); // name.
|
||||
consume(':');
|
||||
skip_object();
|
||||
skip_property();
|
||||
if (peek() == ',')
|
||||
{
|
||||
consume(',');
|
||||
|
||||
+126
-34
@@ -32,32 +32,29 @@
|
||||
|
||||
using namespace pipedal;
|
||||
|
||||
|
||||
void pipedal::SetThreadName(const std::string &name)
|
||||
{
|
||||
std::string threadName = "ppdl_" + name;
|
||||
if (threadName.length () > 15)
|
||||
if (threadName.length() > 15)
|
||||
{
|
||||
threadName = threadName.substr(0,15);
|
||||
threadName = threadName.substr(0, 15);
|
||||
}
|
||||
pthread_t pid = pthread_self();
|
||||
pthread_setname_np(pid,threadName.c_str());
|
||||
pthread_setname_np(pid, threadName.c_str());
|
||||
}
|
||||
|
||||
|
||||
static const uint8_t utf8extraBytes[256] = {
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
|
||||
};
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5};
|
||||
|
||||
constexpr char32_t ILLEGAL_CHAR32 = U'⊗';
|
||||
static const uint8_t utf8Offset[] = { 0,0b11000000, 0b11100000,0b11110000,0b11111000,0b11111100};
|
||||
static const uint8_t utf8Offset[] = {0, 0b11000000, 0b11100000, 0b11110000, 0b11111000, 0b11111100};
|
||||
|
||||
std::u32string pipedal::ToUtf32(const std::string &s)
|
||||
{
|
||||
@@ -72,16 +69,21 @@ std::u32string pipedal::ToUtf32(const std::string &s)
|
||||
if (c < 0x80)
|
||||
{
|
||||
result << (char32_t)c;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
auto extraBytes = utf8extraBytes[c];
|
||||
if (extraBytes == 0)
|
||||
{
|
||||
result << ILLEGAL_CHAR32;
|
||||
} else if (p+extraBytes > end)
|
||||
}
|
||||
else if (p + extraBytes > end)
|
||||
{
|
||||
result << ILLEGAL_CHAR32;
|
||||
break;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
char32_t cResult = c -= utf8Offset[extraBytes];
|
||||
while (extraBytes != 0)
|
||||
{
|
||||
@@ -102,11 +104,10 @@ std::u32string pipedal::ToUtf32(const std::string &s)
|
||||
return result.str();
|
||||
}
|
||||
|
||||
|
||||
std::string pipedal::GetHostName()
|
||||
{
|
||||
char buffer[1024];
|
||||
if (gethostname(buffer,1024) != 0)
|
||||
if (gethostname(buffer, 1024) != 0)
|
||||
{
|
||||
buffer[0] = '\0';
|
||||
}
|
||||
@@ -114,7 +115,6 @@ std::string pipedal::GetHostName()
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::string> pipedal::split(const std::string &value, char delimiter)
|
||||
{
|
||||
size_t start = 0;
|
||||
@@ -138,8 +138,7 @@ std::vector<std::string> pipedal::split(const std::string &value, char delimiter
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool pipedal::IsChildDirectory(const std::filesystem::path &path, const std::filesystem::path&rootPath)
|
||||
bool pipedal::IsChildDirectory(const std::filesystem::path &path, const std::filesystem::path &rootPath)
|
||||
{
|
||||
auto iter = path.begin();
|
||||
|
||||
@@ -154,8 +153,7 @@ bool pipedal::IsChildDirectory(const std::filesystem::path &path, const std::fil
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::string pipedal::ToLower(const std::string&value)
|
||||
std::string pipedal::ToLower(const std::string &value)
|
||||
{
|
||||
std::string result;
|
||||
result.resize(value.length());
|
||||
@@ -166,16 +164,17 @@ std::string pipedal::ToLower(const std::string&value)
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
std::filesystem::path pipedal::MakeRelativePath(const std::filesystem::path &path, const std::filesystem::path&parentPath)
|
||||
std::filesystem::path pipedal::MakeRelativePath(const std::filesystem::path &path, const std::filesystem::path &parentPath)
|
||||
{
|
||||
if (path.is_relative()) return path;
|
||||
if (path.is_relative())
|
||||
return path;
|
||||
|
||||
auto iter = path.begin();
|
||||
|
||||
|
||||
for (auto i = parentPath.begin(); i != parentPath.end(); ++i)
|
||||
{
|
||||
if (iter == path.end() || *iter != *i) {
|
||||
if (iter == path.end() || *iter != *i)
|
||||
{
|
||||
// not a child directory of parent directory.
|
||||
throw std::runtime_error("Not a child directory.");
|
||||
}
|
||||
@@ -187,7 +186,6 @@ std::filesystem::path pipedal::MakeRelativePath(const std::filesystem::path &pat
|
||||
remander /= *iter++;
|
||||
}
|
||||
return remander;
|
||||
|
||||
}
|
||||
|
||||
bool pipedal::HasDotDot(const std::filesystem::path &path)
|
||||
@@ -218,7 +216,7 @@ bool pipedal::IsSubdirectory(const std::filesystem::path &path, const std::files
|
||||
|
||||
if ((*i) != (*iPath))
|
||||
{
|
||||
if (*i == "" && ++i == basePath.end()) // match xyz/ (trailing /)
|
||||
if (*i == "" && ++i == basePath.end()) // match xyz/ (trailing /)
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -237,12 +235,106 @@ bool pipedal::IsSubdirectory(const std::filesystem::path &path, const std::files
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool pipedal::HasWritePermissions(const std::filesystem::path &path)
|
||||
{
|
||||
// posix, but may not work on windows.
|
||||
// posix, but may not work on windows.
|
||||
// allegedly windows provies an _access function, which is probably a superset of
|
||||
// access.
|
||||
return access(path.c_str(), W_OK) == 0;
|
||||
}
|
||||
|
||||
const std::string SF_SPECIAL_CHARS = " <>@;:\"\'/[]?=+%.";
|
||||
|
||||
static std::array<bool, 256> makeSfBits()
|
||||
{
|
||||
std::array<bool, 256> result;
|
||||
|
||||
for (char c : SF_SPECIAL_CHARS)
|
||||
{
|
||||
result[(unsigned char)c] = true;
|
||||
}
|
||||
for (size_t i = 128; i < 256; ++i)
|
||||
{
|
||||
result[i] = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::array<bool, 256> IS_SPECIAL_FILENAME_CHAR = makeSfBits();
|
||||
|
||||
static const char *HEX_CHARS = "0123456789abcdef";
|
||||
|
||||
static bool isHexChar(char c)
|
||||
{
|
||||
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
|
||||
}
|
||||
|
||||
static int fromHexChar(char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9')
|
||||
return (int)(c - '0');
|
||||
if (c >= 'a' && c <= 'f')
|
||||
return (int)(c - 'a') + 10;
|
||||
if (c >= 'A' && c <= 'F')
|
||||
return (int)(c - 'A') + 10;
|
||||
return 0;
|
||||
}
|
||||
static char fromHexChars(char c1, char c2)
|
||||
{
|
||||
int uc = fromHexChar(c1) * 16 + fromHexChar(c2);
|
||||
return (char)uc;
|
||||
}
|
||||
|
||||
std::string pipedal::safeFilenameToString(const std::string &filename)
|
||||
{
|
||||
size_t ix = 0;
|
||||
std::ostringstream os;
|
||||
|
||||
while (ix < filename.size())
|
||||
{
|
||||
char c = filename[ix++];
|
||||
if (c == '%')
|
||||
{
|
||||
// when faced with an invalid encoding, assume that user has done it.
|
||||
// So return the original.
|
||||
if (ix + 2 >= filename.size())
|
||||
{
|
||||
return filename; // just return the original.
|
||||
}
|
||||
if (!isHexChar(filename[ix]) || !isHexChar(filename[ix + 1]))
|
||||
{
|
||||
return filename;
|
||||
}
|
||||
os << fromHexChars(filename[ix], filename[ix + 1]);
|
||||
ix += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
os << c;
|
||||
}
|
||||
}
|
||||
return os.str();
|
||||
}
|
||||
std::string pipedal::stringToSafeFilename(const std::string &name)
|
||||
{
|
||||
std::ostringstream os;
|
||||
for (char c : name)
|
||||
{
|
||||
unsigned char uc = (unsigned char)c;
|
||||
if (uc < 0x20)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (IS_SPECIAL_FILENAME_CHAR[uc])
|
||||
{
|
||||
os << '%'
|
||||
<< HEX_CHARS[uc >> 4]
|
||||
<< HEX_CHARS[uc & 0x0F];
|
||||
}
|
||||
else
|
||||
{
|
||||
os << c;
|
||||
}
|
||||
}
|
||||
return os.str();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user