net/content_disposition — total parser for the mojibake-prone header: RFC 6266 filename (quoted/token), RFC 5987 filename* ext-values (charset'lang'pct-encoded, incl. RFC 2231 continuations), legacy RFC 2047 encoded-words (=?UTF-8?B?..?= / ?Q?), and raw Latin-1 bytes; prefers filename* over filename; strips path components AFTER decoding (a base64 payload can hold '/'). 22-case test table. net/text_codec (internal) — percent-decode, UTF-8 validation, Latin-1-> UTF-8, base64, RFC 2047 — shared by the CD parser and the URL splitter. net/url — a small total URL splitter (scheme/userinfo/host/port/path/ query/fragment, http(s) validity) and url_filename() for the last path segment; used for the filename fallback. net/probe — HEAD then a ranged GET bytes=0-0 that PROVES resumability (206 + matching Content-Range + a validator), rather than trusting Accept-Ranges which servers lie about; the ranged GET is also the HEAD- refused (403/405/501) fallback. 401/407 -> success result with requires_auth, not an error. Runs on its own pool (max_concurrent, default 4) outside the segment budget per ADR 0011 §5. suggest_filename() does the resolution order (explicit -> disposition -> URL -> download.bin) with a light strip; rules/ (stage 9) owns the authoritative sanitize. tools/fuzz — libFuzzer targets for the CD parser and the URL splitter, compiling the parser sources directly so they're fully instrumented; self-guards on VELOX_BUILD_FUZZ + Clang (the top-level CMake adds every tools/* unconditionally). Seed corpora included. Fixed on the way: a p -> Transfer -> State -> cbs -> p reference cycle in Prober that leaked every probe (drop the stored Transfer; the worker keeps State alive). Tests green under ASan/UBSan and TSan. Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HPPSGhiArbvQgwC2DNiURS
41 lines
1.4 KiB
C++
41 lines
1.4 KiB
C++
// vdm/net/url.hpp — a small, total URL splitter.
|
|
//
|
|
// Not a full RFC 3986 parser (libcurl does the real fetching); just enough to pull a
|
|
// filename out of a path and to sanity-check a scheme. Total on hostile input — it has a
|
|
// fuzz target (tools/fuzz) — never throws, never asserts.
|
|
//
|
|
// This header compiles standalone.
|
|
|
|
#ifndef VDM_NET_URL_HPP
|
|
#define VDM_NET_URL_HPP
|
|
|
|
#include <cstdint>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <string_view>
|
|
|
|
namespace vdm::net {
|
|
|
|
struct SplitUrl {
|
|
std::string scheme; // lowercased, without "://"
|
|
std::string userinfo; // before '@', if any
|
|
std::string host; // lowercased; bracketed IPv6 keeps its brackets stripped
|
|
std::optional<std::uint16_t> port;
|
|
std::string path; // includes the leading '/', or empty
|
|
std::string query; // without the '?'
|
|
std::string fragment; // without the '#'
|
|
bool valid = false; // scheme + host present and scheme is http/https
|
|
|
|
[[nodiscard]] bool is_http() const noexcept { return scheme == "http" || scheme == "https"; }
|
|
};
|
|
|
|
[[nodiscard]] SplitUrl split_url(std::string_view url);
|
|
|
|
// The last non-empty path segment, percent-decoded, path components stripped. Empty when
|
|
// the path has no usable segment (ends in '/', is empty, or is only "/").
|
|
[[nodiscard]] std::string url_filename(std::string_view url);
|
|
|
|
} // namespace vdm::net
|
|
|
|
#endif // VDM_NET_URL_HPP
|