This commit is contained in:
Robin E.R. Davies
2026-02-04 15:05:37 -05:00
parent f0c3995a8f
commit e5beb97466
35 changed files with 3815 additions and 317 deletions
+1 -1
View File
@@ -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)
{
+20 -1
View File
@@ -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 {
+2
View File
@@ -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);
}
+1 -1
View File
@@ -575,7 +575,7 @@ void json_reader::skip_object()
}
skip_string(); // name.
consume(':');
skip_object();
skip_property();
if (peek() == ',')
{
consume(',');
+126 -34
View File
@@ -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();
}