73 static const char* hex =
"0123456789ABCDEF";
75 out.reserve(s.size());
76 for (
unsigned char c : s) {
77 const bool unreserved = (c >=
'A' && c <=
'Z') || (c >=
'a' && c <=
'z') ||
78 (c >=
'0' && c <=
'9') || c ==
'-' || c ==
'_' ||
81 out.push_back(
static_cast<char>(c));
84 out.push_back(hex[c >> 4]);
85 out.push_back(hex[c & 0xF]);
94 const std::string& plugin_id,
95 const std::string& channel,
96 std::uint64_t installed_version) {
97 const char sep = (base_url.find(
'?') == std::string::npos) ?
'?' :
'&';
100 "&installed=" + std::to_string(installed_version);
142 auto offline = [&](std::string why) {
146 r.detail +=
" — using offline fallback pack";
153 if (cfg.
base_url.rfind(
"https://", 0) != 0)
154 return offline(
"remote update requires an https:// endpoint");
155 if (!cfg.
fetcher)
return offline(
"no fetcher configured");
157 const std::string url =
167 {},
"malformed manifest: " + err};
169 const auto decision =
172 if (!decision.ok()) {
177 decision, {}, decision.detail};
194 std::string files_base_url, std::filesystem::path download_dir,
int timeout_seconds = 20) {
195 return [files_base_url = std::move(files_base_url),
196 download_dir = std::move(download_dir), timeout_seconds](
const std::string& url) {
199 if (!manifest_resp.ok()) {
200 out.
detail = manifest_resp.error.empty()
201 ? (
"HTTP " + std::to_string(manifest_resp.status_code))
202 : manifest_resp.error;
215 std::filesystem::create_directories(download_dir, ec);
216 for (
const auto& f : manifest->files) {
223 out.
detail =
"unsafe manifest path rejected: " + f.path;
226 const std::filesystem::path dest = download_dir / f.path;
228 out.
detail =
"unsafe manifest path rejected: " + f.path;
231 std::filesystem::create_directories(dest.parent_path(), ec);
234 out.
detail =
"download failed: " + f.path;
A granted-capability set.
Definition reload_capabilities.hpp:74
bool is_safe_relative_path(const std::filesystem::path &path)
True only if path is safe to join beneath a destination directory: a non-empty relative path with no ...
Definition safe_relative_path.hpp:25
bool http_download(std::string_view url, std::string_view output_path, int timeout_seconds=60)
Download a file from a URL to a local path. Returns true on success.
bool is_within_directory(const std::filesystem::path &directory, const std::filesystem::path &candidate)
True if candidate, compared lexically after normalization, is directory itself or lies beneath it.
Definition safe_relative_path.hpp:43
HttpResponse http_get(std::string_view url, int timeout_seconds=30)
Perform an HTTP GET request.
Signed Revocation List (SRL) + namespaced monotonic epoch floor.
Screening for untrusted relative paths that will be joined beneath a destination directory: archive e...
Sealed swap-pack manifest + per-file integrity.