Files
video-shader-toys/src/shader/ShaderUiPath.cpp
Aiden b7ce079a26
All checks were successful
CI / React UI Build (push) Successful in 39s
CI / Native Windows Build And Tests (push) Successful in 2m23s
CI / Windows Release Package (push) Successful in 3m6s
Fixed duplication
2026-06-01 06:52:56 -04:00

97 lines
2.5 KiB
C++

#include "stdafx.h"
#include "ShaderUiPath.h"
namespace ShaderUiPath
{
namespace
{
bool IsPathUnderRoot(const std::filesystem::path& root, const std::filesystem::path& path)
{
std::error_code errorCode;
const std::filesystem::path canonicalRoot = std::filesystem::weakly_canonical(root, errorCode);
if (errorCode)
return false;
const std::filesystem::path canonicalPath = std::filesystem::weakly_canonical(path, errorCode);
if (errorCode)
return false;
const std::filesystem::path relative = canonicalPath.lexically_relative(canonicalRoot);
if (relative.empty() || relative.is_absolute())
return false;
for (const std::filesystem::path& part : relative)
{
if (part == "..")
return false;
}
return true;
}
}
bool NormalizeAssetPath(const std::string& assetPath, std::filesystem::path& normalizedPath)
{
normalizedPath.clear();
if (assetPath.empty() || assetPath.find('\\') != std::string::npos ||
assetPath.find(':') != std::string::npos || assetPath.find('?') != std::string::npos ||
assetPath.find('#') != std::string::npos)
{
return false;
}
const std::filesystem::path path(assetPath);
if (path.empty() || path.is_absolute())
return false;
bool firstPart = true;
bool startsInUiDirectory = false;
for (const std::filesystem::path& part : path)
{
if (part.empty() || part == "." || part == "..")
return false;
if (firstPart)
{
startsInUiDirectory = part == "ui";
firstPart = false;
}
}
if (!startsInUiDirectory)
return false;
normalizedPath = path.lexically_normal();
if (normalizedPath.empty() || normalizedPath.is_absolute())
return false;
for (const std::filesystem::path& part : normalizedPath)
{
if (part.empty() || part == "." || part == "..")
return false;
}
return true;
}
bool IsModulePath(const std::filesystem::path& normalizedPath)
{
const std::string extension = normalizedPath.extension().string();
return extension == ".js" || extension == ".mjs";
}
bool ResolveAssetPath(
const std::filesystem::path& packageRoot,
const std::string& assetPath,
std::filesystem::path& resolvedPath)
{
resolvedPath.clear();
std::filesystem::path normalizedPath;
if (!NormalizeAssetPath(assetPath, normalizedPath))
return false;
const std::filesystem::path candidatePath = packageRoot / normalizedPath;
if (!IsPathUnderRoot(packageRoot, candidatePath))
return false;
if (!std::filesystem::exists(candidatePath) || !std::filesystem::is_regular_file(candidatePath))
return false;
resolvedPath = candidatePath;
return true;
}
}