Fixed duplication
This commit is contained in:
96
src/shader/ShaderUiPath.cpp
Normal file
96
src/shader/ShaderUiPath.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user