#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; } }