* @brief Validate a file path against access restrictions. * * @param filePath The file path to validate. * @param mode The file access mode. * @param allowedDirs The list of allowed directories. * @return Empty string on success, or error message on failure. */
| 261 | * @return Empty string on success, or error message on failure. |
| 262 | */ |
| 263 | std::string ValidateFilePath(const std::string& filePath, |
| 264 | FileAccessMode mode, |
| 265 | const std::vector<std::string>& allowedDirs) |
| 266 | { |
| 267 | if (mode == FileAccessMode::Unrestricted) |
| 268 | { |
| 269 | return ""; |
| 270 | } |
| 271 | |
| 272 | // Canonicalize the requested path |
| 273 | std::error_code ec; |
| 274 | const fs::path canonicalPath = fs::canonical(filePath, ec); |
| 275 | if (ec) |
| 276 | { |
| 277 | return "Cannot resolve file path: " + filePath; |
| 278 | } |
| 279 | |
| 280 | const std::string canonicalStr = canonicalPath.string(); |
| 281 | |
| 282 | // Check allowed directories |
| 283 | for (const auto& allowedDir : allowedDirs) |
| 284 | { |
| 285 | const fs::path canonicalAllowed = fs::canonical(allowedDir, ec); |
| 286 | if (ec) |
| 287 | { |
| 288 | continue; |
| 289 | } |
| 290 | const std::string allowedStr = canonicalAllowed.string(); |
| 291 | if (canonicalStr.rfind(allowedStr, 0) == 0 && |
| 292 | (canonicalStr.length() == allowedStr.length() || |
| 293 | canonicalStr[allowedStr.length()] == '/' || |
| 294 | canonicalStr[allowedStr.length()] == '\\')) |
| 295 | { |
| 296 | return ""; |
| 297 | } |
| 298 | } |
| 299 | |
| 300 | return "File path is not within any allowed directory: " + filePath; |
| 301 | } |
| 302 | } // anonymous namespace |
| 303 | |
| 304 | DataStorageController::DataStorageController(DataStorageBridge& bridge) |