-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfile_tool.cpp
More file actions
72 lines (54 loc) · 1.66 KB
/
Copy pathfile_tool.cpp
File metadata and controls
72 lines (54 loc) · 1.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include "file_tool.hpp"
#include <fstream>
#include <sstream>
#include <stdexcept>
namespace {
bool is_inside_workspace(
const std::filesystem::path& path,
const std::filesystem::path& workspace_root) {
std::error_code error;
const std::filesystem::path relative =
std::filesystem::relative(path, workspace_root, error);
if (error) {
return false;
}
for (const auto& part : relative) {
if (part == "..") {
return false;
}
}
return true;
}
} // namespace
FileTool::FileTool()
: workspace_root_(std::filesystem::weakly_canonical(
std::filesystem::current_path())) {}
std::string FileTool::read(const std::string& path) const {
const std::filesystem::path requested_path(path);
if (requested_path.is_absolute()) {
throw std::runtime_error(
"File paths must be relative to the workspace.");
}
std::error_code error;
const std::filesystem::path resolved_path =
std::filesystem::weakly_canonical(
workspace_root_ / requested_path, error);
if (error) {
throw std::runtime_error(
"Could not resolve file path: " + path);
}
if (!is_inside_workspace(resolved_path, workspace_root_)) {
throw std::runtime_error(
"File path is outside the workspace: " + path);
}
std::ifstream input(resolved_path);
if (!input) {
throw std::runtime_error("Could not open file: " + path);
}
std::ostringstream contents;
contents << input.rdbuf();
if (input.bad()) {
throw std::runtime_error("Could not read file: " + path);
}
return contents.str();
}