-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathcontext_items.cpp
More file actions
128 lines (107 loc) · 4.15 KB
/
Copy pathcontext_items.cpp
File metadata and controls
128 lines (107 loc) · 4.15 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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include "context_items.hpp"
#include "../session/attachment_store.hpp"
#include "../utils/utf8_path.hpp"
#include <algorithm>
#include <cctype>
#include <filesystem>
#include <fstream>
#include <iterator>
namespace acecode::desktop {
namespace {
namespace fs = std::filesystem;
std::string mime_type_for_path(const fs::path& path) {
std::string extension = path_to_utf8(path.extension());
std::transform(extension.begin(), extension.end(), extension.begin(), [](char ch) {
return static_cast<char>(std::tolower(static_cast<unsigned char>(ch)));
});
if (extension == ".png") return "image/png";
if (extension == ".jpg" || extension == ".jpeg") return "image/jpeg";
if (extension == ".gif") return "image/gif";
if (extension == ".webp") return "image/webp";
if (extension == ".bmp") return "image/bmp";
if (extension == ".svg") return "image/svg+xml";
if (extension == ".pdf") return "application/pdf";
if (extension == ".json") return "application/json";
if (extension == ".txt" || extension == ".md" || extension == ".log") {
return "text/plain";
}
return {};
}
std::string display_name(const fs::path& path) {
const fs::path filename = path.filename();
return path_to_utf8(filename.empty() ? path : filename);
}
bool requires_snapshot_bytes(const std::string& mime_type) {
return mime_type.rfind("image/", 0) == 0 && mime_type != "image/svg+xml";
}
} // namespace
ContextItemsResult materialize_context_items(
const std::vector<std::string>& paths) {
ContextItemsResult result;
result.items.reserve(paths.size());
for (const auto& raw_path : paths) {
if (raw_path.empty()) {
result.error = "filesystem path is empty";
return result;
}
const fs::path input = path_from_utf8(raw_path);
if (!input.is_absolute()) {
result.error = "filesystem path must be absolute: " + raw_path;
return result;
}
std::error_code ec;
const fs::path canonical = fs::weakly_canonical(input, ec);
if (ec || canonical.empty()) {
result.error = "filesystem path is unavailable: " + raw_path;
return result;
}
ContextItem item;
item.path = path_to_utf8_generic(canonical);
item.name = display_name(canonical);
if (fs::is_directory(canonical, ec) && !ec) {
item.kind = ContextItemKind::Folder;
result.items.push_back(std::move(item));
continue;
}
ec.clear();
if (!fs::is_regular_file(canonical, ec) || ec) {
result.error = "filesystem item is not a regular file or folder: " + raw_path;
return result;
}
item.kind = ContextItemKind::File;
item.mime_type = mime_type_for_path(canonical);
item.size_bytes = fs::file_size(canonical, ec);
if (ec) {
result.error = "failed to inspect file: " + item.name;
return result;
}
if (!requires_snapshot_bytes(item.mime_type)) {
item.reference_only = true;
result.items.push_back(std::move(item));
continue;
}
if (item.size_bytes > kMaxAttachmentBytes) {
result.error = "file exceeds the 25 MiB attachment limit: " + item.name;
return result;
}
std::ifstream input_stream(canonical, std::ios::binary);
if (!input_stream) {
result.error = "failed to read file: " + item.name;
return result;
}
item.bytes.assign(std::istreambuf_iterator<char>(input_stream),
std::istreambuf_iterator<char>());
if (!input_stream.eof() && input_stream.fail()) {
result.error = "failed to read file: " + item.name;
return result;
}
if (item.bytes.size() > kMaxAttachmentBytes) {
result.error = "file exceeds the 25 MiB attachment limit: " + item.name;
return result;
}
item.size_bytes = static_cast<std::uintmax_t>(item.bytes.size());
result.items.push_back(std::move(item));
}
return result;
}
} // namespace acecode::desktop