@@ -128,8 +128,14 @@ bool FontDownloadActivity::fetchAndParseManifest() {
|
|||||||
|
|
||||||
if (family.installed) {
|
if (family.installed) {
|
||||||
for (const auto& file : family.files) {
|
for (const auto& file : family.files) {
|
||||||
|
std::string localFilename = file.name;
|
||||||
|
std::string familyPrefix = family.name + "/";
|
||||||
|
if (localFilename.find(familyPrefix) == 0) {
|
||||||
|
localFilename = localFilename.substr(familyPrefix.length());
|
||||||
|
}
|
||||||
|
|
||||||
char path[128];
|
char path[128];
|
||||||
FontInstaller::buildFontPath(family.name.c_str(), file.name.c_str(), path, sizeof(path));
|
FontInstaller::buildFontPath(family.name.c_str(), localFilename.c_str(), path, sizeof(path));
|
||||||
FsFile f;
|
FsFile f;
|
||||||
if (Storage.openFileForRead("FONT", path, f)) {
|
if (Storage.openFileForRead("FONT", path, f)) {
|
||||||
size_t actual = f.fileSize();
|
size_t actual = f.fileSize();
|
||||||
@@ -219,8 +225,14 @@ void FontDownloadActivity::downloadFamily(ManifestFamily& family) {
|
|||||||
}
|
}
|
||||||
requestUpdateAndWait();
|
requestUpdateAndWait();
|
||||||
|
|
||||||
|
std::string localFilename = file.name;
|
||||||
|
std::string familyPrefix = family.name + "/";
|
||||||
|
if (localFilename.find(familyPrefix) == 0) {
|
||||||
|
localFilename = localFilename.substr(familyPrefix.length());
|
||||||
|
}
|
||||||
|
|
||||||
char stagedPath[128];
|
char stagedPath[128];
|
||||||
snprintf(stagedPath, sizeof(stagedPath), "%s/%s", stagingDir, file.name.c_str());
|
snprintf(stagedPath, sizeof(stagedPath), "%s/%s", stagingDir, localFilename.c_str());
|
||||||
|
|
||||||
// Make sure parent directories exist for the file
|
// Make sure parent directories exist for the file
|
||||||
std::string stagedPathStr(stagedPath);
|
std::string stagedPathStr(stagedPath);
|
||||||
|
|||||||
@@ -1441,7 +1441,8 @@ static constexpr size_t MAX_FONT_FILE_NAME_LEN = 60;
|
|||||||
|
|
||||||
bool isValidFontFileName(const std::string& name) {
|
bool isValidFontFileName(const std::string& name) {
|
||||||
if (name.empty() || name.size() > MAX_FONT_FILE_NAME_LEN) return false;
|
if (name.empty() || name.size() > MAX_FONT_FILE_NAME_LEN) return false;
|
||||||
if (name.find('/') != std::string::npos) return false;
|
// Allow '/' for subdirectories of font families, but prevent absolute paths
|
||||||
|
if (name[0] == '/') return false;
|
||||||
if (name.find('\\') != std::string::npos) return false;
|
if (name.find('\\') != std::string::npos) return false;
|
||||||
if (name.find("..") != std::string::npos) return false;
|
if (name.find("..") != std::string::npos) return false;
|
||||||
return true;
|
return true;
|
||||||
@@ -1515,8 +1516,14 @@ bool fetchRemoteFontManifest(FontInstaller& installer, std::vector<RemoteManifes
|
|||||||
family.hasUpdate = false;
|
family.hasUpdate = false;
|
||||||
if (family.installed) {
|
if (family.installed) {
|
||||||
for (const auto& file : family.files) {
|
for (const auto& file : family.files) {
|
||||||
|
std::string localFilename = file.name;
|
||||||
|
std::string familyPrefix = family.name + "/";
|
||||||
|
if (localFilename.find(familyPrefix) == 0) {
|
||||||
|
localFilename = localFilename.substr(familyPrefix.length());
|
||||||
|
}
|
||||||
|
|
||||||
char path[128];
|
char path[128];
|
||||||
FontInstaller::buildFontPath(family.name.c_str(), file.name.c_str(), path, sizeof(path));
|
FontInstaller::buildFontPath(family.name.c_str(), localFilename.c_str(), path, sizeof(path));
|
||||||
FsFile f;
|
FsFile f;
|
||||||
if (Storage.openFileForRead("WEB", path, f)) {
|
if (Storage.openFileForRead("WEB", path, f)) {
|
||||||
const size_t actual = static_cast<size_t>(f.size());
|
const size_t actual = static_cast<size_t>(f.size());
|
||||||
@@ -1583,13 +1590,27 @@ bool installRemoteFamily(const RemoteManifestFamily& family, const std::string&
|
|||||||
for (const auto& file : family.files) {
|
for (const auto& file : family.files) {
|
||||||
esp_task_wdt_reset();
|
esp_task_wdt_reset();
|
||||||
|
|
||||||
|
std::string localFilename = file.name;
|
||||||
|
std::string familyPrefix = family.name + "/";
|
||||||
|
if (localFilename.find(familyPrefix) == 0) {
|
||||||
|
localFilename = localFilename.substr(familyPrefix.length());
|
||||||
|
}
|
||||||
|
|
||||||
char stagedPath[128];
|
char stagedPath[128];
|
||||||
int sn = snprintf(stagedPath, sizeof(stagedPath), "%s/%s", stagingDir, file.name.c_str());
|
int sn = snprintf(stagedPath, sizeof(stagedPath), "%s/%s", stagingDir, localFilename.c_str());
|
||||||
if (sn < 0 || static_cast<size_t>(sn) >= sizeof(stagedPath)) {
|
if (sn < 0 || static_cast<size_t>(sn) >= sizeof(stagedPath)) {
|
||||||
Storage.removeDir(stagingDir);
|
Storage.removeDir(stagingDir);
|
||||||
outError = std::string("File path too long: ") + file.name;
|
outError = std::string("File path too long: ") + localFilename;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure intermediate subdirectories exist inside stagingDir
|
||||||
|
std::string stagedPathStr(stagedPath);
|
||||||
|
size_t lastSlash = stagedPathStr.find_last_of('/');
|
||||||
|
if (lastSlash != std::string::npos) {
|
||||||
|
Storage.mkdir(stagedPathStr.substr(0, lastSlash).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
const std::string url = baseUrl + file.name;
|
const std::string url = baseUrl + file.name;
|
||||||
|
|
||||||
auto result = HttpDownloader::downloadToFile(url, stagedPath, nullptr);
|
auto result = HttpDownloader::downloadToFile(url, stagedPath, nullptr);
|
||||||
|
|||||||
@@ -1820,6 +1820,7 @@
|
|||||||
<div class="nav-links">
|
<div class="nav-links">
|
||||||
<a href="/files" class="active">File Manager</a>
|
<a href="/files" class="active">File Manager</a>
|
||||||
<a href="/settings">Settings</a>
|
<a href="/settings">Settings</a>
|
||||||
|
<a href="/fonts">Font Manager</a>
|
||||||
<a href="/systeminfo">System Info</a>
|
<a href="/systeminfo">System Info</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -156,7 +156,7 @@
|
|||||||
<div class="nav-links">
|
<div class="nav-links">
|
||||||
<a href="/files">File Manager</a>
|
<a href="/files">File Manager</a>
|
||||||
<a href="/settings">Settings</a>
|
<a href="/settings">Settings</a>
|
||||||
<a href="/fonts" class="active">Fonts</a>
|
<a href="/fonts" class="active">Font Manager</a>
|
||||||
<a href="/systeminfo">System Info</a>
|
<a href="/systeminfo">System Info</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -173,6 +173,7 @@
|
|||||||
<div class="nav-links">
|
<div class="nav-links">
|
||||||
<a href="/files">File Manager</a>
|
<a href="/files">File Manager</a>
|
||||||
<a href="/settings">Settings</a>
|
<a href="/settings">Settings</a>
|
||||||
|
<a href="/fonts">Font Manager</a>
|
||||||
<a href="/systeminfo" class="active">System Info</a>
|
<a href="/systeminfo" class="active">System Info</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -300,6 +300,7 @@
|
|||||||
<div class="nav-links">
|
<div class="nav-links">
|
||||||
<a href="/files">File Manager</a>
|
<a href="/files">File Manager</a>
|
||||||
<a href="/settings" class="active">Settings</a>
|
<a href="/settings" class="active">Settings</a>
|
||||||
|
<a href="/fonts">Font Manager</a>
|
||||||
<a href="/systeminfo">System Info</a>
|
<a href="/systeminfo">System Info</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user