17typedef enum : uint16_t {
25typedef enum : uint8_t {
49 return (
char)(((value >=
'A') && (value <=
'Z')) ? (value -
'A' +
'a') : value);
74 while ((index < length) && (prefix[index] !=
'\0')) {
80 return prefix[index] ==
'\0';
104 const size_t literal_length =
strlen(literal);
105 return (length == literal_length) && (
memcmp(data, literal, length) == 0);
130 for (
size_t index = 0U; index < length; ++index) {
131 if ((data[index] <
'0') || (data[index] >
'9')) {
157 static const char k_symbols[] =
"!#$%&'*+-.^_`|~";
161 for (
size_t index = 0U; index < length; ++index) {
162 const char value = data[index];
163 const bool alpha_numeric = ((value >=
'A') && (value <=
'Z')) ||
164 ((value >=
'a') && (value <=
'z')) ||
165 ((value >=
'0') && (value <=
'9'));
166 if (!alpha_numeric && (
strchr(k_symbols, value) ==
nullptr)) {
192 size_t field_start = 0U;
193 size_t field_index = 0U;
194 for (
size_t index = 0U; index <= length; ++index) {
195 if ((index != length) && (line[index] !=
'\t')) {
198 const size_t field_length = index - field_start;
199 if (((field_index == 0U) || (field_index == 2U) || (field_index ==
k_cookie_name_field)) &&
200 (field_length == 0U)) {
203 if (((field_index == 1U) || (field_index == 3U)) &&
216 field_start = index + 1U;
240 while ((length > 0U) && ((attribute[length - 1U] ==
' ') || (attribute[length - 1U] ==
'\t'))) {
243 const size_t prefix_length =
sizeof(
"Domain=") - 1U;
266 const size_t prefix_length =
sizeof(
"Set-Cookie:") - 1U;
267 size_t pair_end = prefix_length;
268 while ((pair_end < length) && (line[pair_end] !=
';')) {
271 size_t name_start = prefix_length;
272 while ((name_start < pair_end) && ((line[name_start] ==
' ') || (line[name_start] ==
'\t'))) {
275 size_t equals = name_start;
276 while ((equals < pair_end) && (line[equals] !=
'=')) {
282 for (
size_t start = pair_end; start < length;) {
284 while ((start < length) && ((line[start] ==
' ') || (line[start] ==
'\t'))) {
288 while ((end < length) && (line[end] !=
';')) {
320 for (
size_t index = 0U; index < length; ++index) {
321 const uint8_t value = (uint8_t)line[index];
326 while ((length > 0U) && ((line[length - 1U] ==
' ') || (line[length - 1U] ==
'\t'))) {
329 while ((length > 0U) && ((*line ==
' ') || (*line ==
'\t'))) {
339 const char*
const commands[] = {
"ALL",
"SESS",
"FLUSH",
"RELOAD"};
340 for (
size_t index = 0U; index < (
sizeof(commands) /
sizeof(commands[0])); ++index) {
376 memcpy(line, data, length);
383 (curl_easy_setopt(curl, CURLOPT_COOKIELIST, line) != CURLE_OK)) {
391 if ((curl ==
nullptr) || (cookies ==
nullptr) ||
392 ((cookies->
length == 0U) != (cookies->
data ==
nullptr))) {
395 if (curl_easy_setopt(curl, CURLOPT_COOKIELIST,
"ALL") != CURLE_OK) {
399 while (offset < cookies->length) {
401 while ((end < cookies->length) && (cookies->
data[end] != (uint8_t)
'\n') &&
402 (cookies->
data[end] != 0U)) {
405 if ((end < cookies->length) && (cookies->
data[end] == 0U)) {
408 size_t length = end - offset;
409 if ((length > 0U) && (cookies->
data[offset + length - 1U] == (uint8_t)
'\r')) {
416 offset = (end < cookies->
length) ? end + 1U : end;
424 if ((curl ==
nullptr) || (ca_pem ==
nullptr) ||
425 ((ca_pem->
length == 0U) != (ca_pem->
data ==
nullptr))) {
428 if (ca_pem->
length == 0U) {
431 for (
size_t index = 0U; index < ca_pem->
length; ++index) {
432 if (ca_pem->
data[index] == 0U) {
436#if LIBCURL_VERSION_NUM >= 0x074D00
437 if (blob ==
nullptr) {
440 *blob = (
struct curl_blob){.data = (
void*)ca_pem->
data,
442 .flags = CURL_BLOB_NOCOPY};
443 const CURLcode code = curl_easy_setopt(curl, CURLOPT_CAINFO_BLOB, blob);
444 if (code == CURLE_OK) {
Streaming HTTP(S) GET seam (a real function-pointer vtable) for the host manga downloader (v0).
ra8_err_t priv_mdl_net_curl_apply_cookies(CURL *curl, const mdl_net_bytes_t *cookies)
Enable the cookie engine and import validated caller-owned rows.
cookie_row_disposition_t
Cookie-line disposition after strict syntax validation.
@ k_cookie_row_accept
Safe cookie row to import.
@ k_cookie_row_reject
Reject the complete credential input.
@ k_cookie_row_ignore
Recognized blank/comment framing.
static bool internal_cookie_domain_valid(const char *attribute, size_t length)
Test whether a Set-Cookie attribute has a nonempty Domain value.
static bool internal_cookie_field_is(const char *data, size_t length, const char *literal)
Compare one bounded field with an exact ASCII literal.
static ra8_err_t internal_apply_cookie_line(CURL *curl, const uint8_t *data, size_t length)
Import one validated bounded cookie row.
static bool internal_cookie_name_valid(const char *data, size_t length)
Validate an RFC token-style cookie name.
static char internal_ascii_lower(char value)
Lower-case one ASCII byte without locale state.
static cookie_row_disposition_t internal_cookie_classify(const char *line, size_t length)
Classify a bounded cookie-file line for safe libcurl import.
static bool internal_netscape_cookie_valid(const char *line, size_t length)
Validate one Netscape cookie-file row without accepting commands.
static bool internal_cookie_expiry_valid(const char *data, size_t length)
Validate one decimal Netscape-cookie expiry field.
static bool internal_set_cookie_valid(const char *line, size_t length)
Validate a Set-Cookie row and require an explicit Domain attribute.
mdl_cookie_limit_t
Maximum imported cookie row including its terminating NUL.
@ k_cookie_ascii_del
First non-printable high ASCII byte.
@ k_cookie_field_count
Required Netscape cookie field count.
@ k_cookie_name_field
Netscape cookie name-field ordinal.
@ k_cookie_line_max
Honest fixed per-row importer bound.
static bool internal_ascii_has_prefix(const char *data, size_t length, const char *prefix)
Test one bounded value for an ASCII case-insensitive prefix.
ra8_err_t priv_mdl_net_curl_apply_ca_blob(CURL *curl, const mdl_net_bytes_t *ca_pem, struct curl_blob *blob)
Bind complete caller-owned CA PEM bytes with NOCOPY semantics.
Module-private libcurl-backend helpers promoted for host unit tests.
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
@ k_ra8_err_not_supported
Requested feature not compiled in, not wired, or not supported by this MCU variant.
@ k_ra8_fail
Generic unspecified failure.
@ k_ra8_err_invalid_arg
Invalid function argument.
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
@ k_ra8_err_invalid_size
Invalid size parameter (too large, too small, or misaligned).
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
int memcmp(const void *a, const void *b, size_t n)
Compare bytes in two memory areas.
size_t strlen(const char *s)
Calculate string length.
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
char * strchr(const char *s, int c)
Locate first occurrence of character in string.
Read-only caller-owned byte view retained by a network backend.
const uint8_t * data
First caller-owned byte, or NULL when empty.
size_t length
Exact readable byte count at data.