|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Implementation of the robots.txt parser, matcher, and per-host cache. More...
#include "mdl_robots.h"#include <math.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include "ra8_attributes.h"Go to the source code of this file.
Enumerations | |
| enum | mdl_robots_local_size_t : uint16_t { k_robots_line_max = 512 , k_robots_url_max = 256 } |
| Local parse/format sizes. More... | |
| enum | mdl_robots_ms_t : uint32_t { k_ms_per_s = 1000U , k_crawl_cap_ms = 60000U } |
| Millisecond conversions and the crawl-delay ceiling. More... | |
| enum | mdl_robots_spec_t : int8_t { k_spec_none = -1 } |
| "No user-agent match" sentinel for the specificity score. More... | |
Functions | |
| static char | internal_lower_ascii (char c) |
| ASCII lower-case of one character (locale-independent). | |
| static bool | internal_ieq (const char *a, const char *b) |
| Case-insensitive equality of two NUL-terminated strings. | |
| static bool | internal_ci_prefix (const char *prefix, const char *s) |
| True if prefix (case-insensitive) is a prefix of s. | |
| static char * | internal_trim_ws (char *s) |
| Trim leading/trailing ASCII whitespace in place; return start. | |
| static bool | internal_next_line (const char **pp, const char *end, char *buf, size_t cap, bool *truncated) |
| Read one line into buf; strip its # comment and trim whitespace. | |
| static bool | internal_split_field (char *line, char **field, char **value) |
| Split a trimmed line into field/value on the first :. | |
| static int | internal_agent_spec (const char *agent, const char *ua_token) |
| Specificity of a robots user-agent token vs ours (-1 = no match). | |
| static bool | internal_scan_spec (const char *text, size_t len, const char *ua_token, int *best, bool *wild) |
| Pass 1: find the best specific match length and wildcard presence. | |
| static bool | internal_group_selected (int target, bool wildcard_target, int grp_spec, bool grp_wild) |
| True if a group of this specificity is the selected group. | |
| static void | internal_add_rule (mdl_robots_t *out, mdl_robots_rule_kind_t kind, const char *value) |
| Append an Allow/Disallow rule (non-empty patterns only). | |
| static void | internal_set_crawl (mdl_robots_t *out, const char *value) |
| Record the strictest Crawl-delay seen (clamped to the ceiling). | |
| static void | internal_apply_directive (mdl_robots_t *out, const char *field, const char *value) |
| Apply one non-user-agent directive line to the selected group. | |
| static void | internal_harvest (const char *text, size_t len, const char *ua_token, int target, bool wildcard_target, mdl_robots_t *out) |
| Pass 2: collect rules/crawl-delay from the selected group(s). | |
| void | mdl_robots_parse (const char *text, size_t len, const char *ua_token, mdl_robots_t *out) |
| Parse robots.txt text for the group matching ua_token. | |
| static bool | internal_glob_prefix (const char *pat, size_t patlen, const char *path, bool anchored) |
| Match pat (len patlen, * glob) against a prefix of path. | |
| static bool | internal_robots_match (const char *pat, size_t len, const char *path) |
| Match a rule pattern (honouring a trailing $) against path. | |
| static const mdl_robots_rule_t * | internal_best_matching_rule (const mdl_robots_t *robots, const char *path) |
| Longest matching rule for path (Allow wins ties), or NULL. | |
| bool | mdl_robots_allows (const mdl_robots_t *robots, const char *path) |
| Decide whether path is allowed by a parsed robots group. | |
| const char * | mdl_robots_disallow_reason (const mdl_robots_t *robots, const char *path) |
| Return the Disallow pattern that forbids path, or NULL if allowed. | |
| static mdl_robots_cache_entry_t * | internal_cache_find (mdl_robots_cache_t *cache, const char *scheme, const char *host) |
| Locate an existing cache entry for one origin, or NULL if absent. | |
| static mdl_robots_cache_entry_t * | internal_cache_slot (mdl_robots_cache_t *cache) |
| Pick a free cache slot, or the dedicated uncached overflow slot. | |
| const mdl_robots_t * | mdl_robots_cache_consult (mdl_robots_cache_t *cache, const char *scheme, const char *host, const char *ua_token, mdl_robots_fetch_fn fetch, void *ctx, char *scratch, size_t scratch_cap) |
| Return the cached robots rules for host, fetching on first contact. | |
Implementation of the robots.txt parser, matcher, and per-host cache.
Parses a bounded robots document in two passes, selects the most specific applicable user-agent group, and retains its rules in fixed caller storage. Matching and cache lookup remain allocation-free and network access is supplied through the public fetch callback seam.
Definition in file mdl_robots.c.
| enum mdl_robots_local_size_t : uint16_t |
Local parse/format sizes.
| Enumerator | |
|---|---|
| k_robots_line_max | Max robots.txt line length. |
| k_robots_url_max | Max /robots.txt URL length. |
Definition at line 22 of file mdl_robots.c.
| enum mdl_robots_ms_t : uint32_t |
Millisecond conversions and the crawl-delay ceiling.
| Enumerator | |
|---|---|
| k_ms_per_s | Milliseconds per second. |
| k_crawl_cap_ms | Clamp a Crawl-delay to at most 60s. |
Definition at line 28 of file mdl_robots.c.
| enum mdl_robots_spec_t : int8_t |
"No user-agent match" sentinel for the specificity score.
| Enumerator | |
|---|---|
| k_spec_none | No group matched our user-agent. |
Definition at line 34 of file mdl_robots.c.
|
static |
Append an Allow/Disallow rule (non-empty patterns only).
Empty patterns are no-ops; capacity or length overflow invalidates the parse.
| [in,out] | out | Parsed rule set. |
| [in] | kind | Allow or disallow classification. |
| [in] | value | NUL-terminated rule pattern. |
out and value are non-NULL. out owns writable fixed rule storage. out. Definition at line 313 of file mdl_robots.c.
References mdl_robots_t::count, k_mdl_robots_max_rules, k_mdl_robots_path_max, mdl_robots_rule_t::kind, mdl_robots_rule_t::len, mdl_robots_rule_t::path, mdl_robots_t::rules, strlen(), strnlen(), and mdl_robots_t::valid.
Referenced by internal_apply_directive().
|
static |
Specificity of a robots user-agent token vs ours (-1 = no match).
Wildcard scores zero; a specific ASCII-folded prefix scores its length.
| [in] | agent | Robots user-agent value. |
| [in] | ua_token | This tool's product token. |
| -1 | No match. |
| other | Zero for wildcard or a positive prefix length. |
Definition at line 215 of file mdl_robots.c.
References internal_ci_prefix(), k_spec_none, RA8_INTERNAL, strcmp(), and strlen().
Referenced by internal_harvest(), and internal_scan_spec().
|
static |
Apply one non-user-agent directive line to the selected group.
Dispatches Allow, Disallow, and Crawl-delay; unknown fields are ignored.
| [in,out] | out | Parsed robots result. |
| [in] | field | Normalised directive name. |
| [in] | value | Trimmed directive value. |
out owns writable fixed storage. out unchanged. out. Definition at line 376 of file mdl_robots.c.
References internal_add_rule(), internal_ieq(), internal_set_crawl(), k_mdl_rule_allow, and k_mdl_rule_disallow.
Referenced by internal_harvest().
|
static |
Longest matching rule for path (Allow wins ties), or NULL.
Definition at line 559 of file mdl_robots.c.
References mdl_robots_t::count, internal_robots_match(), k_mdl_rule_allow, k_spec_none, mdl_robots_rule_t::kind, mdl_robots_rule_t::len, mdl_robots_rule_t::path, RA8_INTERNAL, and mdl_robots_t::rules.
Referenced by mdl_robots_allows(), and mdl_robots_disallow_reason().
|
static |
Locate an existing cache entry for one origin, or NULL if absent.
Definition at line 598 of file mdl_robots.c.
References mdl_robots_cache_entry_t::host, mdl_robots_cache_t::hosts, k_mdl_robots_max_hosts, mdl_robots_cache_entry_t::scheme, strcmp(), and mdl_robots_cache_entry_t::used.
Referenced by mdl_robots_cache_consult().
|
static |
Pick a free cache slot, or the dedicated uncached overflow slot.
Definition at line 610 of file mdl_robots.c.
References mdl_robots_cache_t::hosts, k_mdl_robots_max_hosts, mdl_robots_cache_t::overflow, RA8_INTERNAL, and mdl_robots_cache_entry_t::used.
Referenced by mdl_robots_cache_consult().
|
static |
True if prefix (case-insensitive) is a prefix of s.
Compares the candidate prefix using ASCII folding.
| [in] | prefix | Candidate prefix. |
| [in] | s | String to inspect. |
| true | Every prefix byte matches. |
| false | A byte differs. |
s is readable through the candidate prefix length. Definition at line 95 of file mdl_robots.c.
References internal_lower_ascii(), and RA8_INTERNAL.
Referenced by internal_agent_spec().
|
static |
Match pat (len patlen, * glob) against a prefix of path.
Uses bounded wildcard backtracking and optionally requires complete path consumption.
| [in] | pat | Pattern bytes. |
| [in] | patlen | Pattern length without a terminal anchor. |
| [in] | path | NUL-terminated URL path. |
| [in] | anchored | Whether the match must consume the complete path. |
| true | The required prefix or full path matched. |
| false | No wildcard expansion matched. |
pat and path are non-NULL and readable for their lengths. patlen excludes a terminal $ marker. Definition at line 499 of file mdl_robots.c.
Referenced by internal_robots_match().
|
static |
True if a group of this specificity is the selected group.
Selects wildcard membership only for wildcard fallback, else exact specificity.
| [in] | target | Selected specific score. |
| [in] | wildcard_target | Whether wildcard fallback was selected. |
| [in] | grp_spec | Current group's score. |
| [in] | grp_wild | Whether the current group contains wildcard. |
| true | The group matches the selected target. |
| false | The group is not selected. |
Definition at line 293 of file mdl_robots.c.
Referenced by internal_harvest().
|
static |
Pass 2: collect rules/crawl-delay from the selected group(s).
Rescans the document and applies directives only while a selected group is active.
| [in] | text | Robots document bytes. |
| [in] | len | Readable document length. |
| [in] | ua_token | Product token used for specificity. |
| [in] | target | Selected specific score. |
| [in] | wildcard_target | Whether wildcard fallback was selected. |
| [in,out] | out | Result receiving directives. |
text is readable for len bytes. out. out. out. Definition at line 404 of file mdl_robots.c.
References internal_agent_spec(), internal_apply_directive(), internal_group_selected(), internal_ieq(), internal_next_line(), internal_split_field(), k_robots_line_max, k_spec_none, RA8_INTERNAL, and mdl_robots_t::valid.
Referenced by mdl_robots_parse().
|
static |
Case-insensitive equality of two NUL-terminated strings.
Compares ASCII-folded bytes through both terminators.
| [in] | a | First string. |
| [in] | b | Second string. |
| true | All folded bytes match. |
| false | A byte or length differs. |
a and b are non-NULL and NUL-terminated. Definition at line 71 of file mdl_robots.c.
References internal_lower_ascii(), and RA8_INTERNAL.
Referenced by internal_apply_directive(), internal_harvest(), and internal_scan_spec().
|
static |
ASCII lower-case of one character (locale-independent).
Maps A through Z; all other values pass through.
| [in] | c | Character to map. |
| other | Mapped or unchanged character. |
c is representable as char. Definition at line 51 of file mdl_robots.c.
References RA8_INTERNAL.
Referenced by internal_ci_prefix(), and internal_ieq().
|
static |
Read one line into buf; strip its # comment and trim whitespace.
Consumes through the next newline or end. Bytes that exceed the buffer are still consumed and set the caller's sticky truncation flag, while the retained prefix is always NUL-terminated before comment processing.
| [in,out] | pp | Cursor updated to the start of the following line. |
| [in] | end | One-past-last byte of the robots document. |
| [out] | buf | Storage receiving the bounded line prefix. |
| [in] | cap | Capacity of buf in bytes. |
| [in,out] | truncated | Sticky flag set when a line does not fit. |
| true | One line was consumed and buf was populated. |
| false | The cursor was already at or beyond end. |
pp, buf, and truncated are non-NULL and cap is non-zero. end delimit one readable contiguous byte range. buf is NUL-terminated and contains no inline comment. truncated value. Definition at line 144 of file mdl_robots.c.
References strchr().
Referenced by internal_harvest(), and internal_scan_spec().
|
static |
Match a rule pattern (honouring a trailing $) against path.
Removes a terminal anchor from the glob length and delegates matching.
| [in] | pat | Rule pattern bytes. |
| [in] | len | Stored pattern length. |
| [in] | path | NUL-terminated URL path. |
path. | true | The rule matches. |
| false | The rule does not match. |
pat and path are non-NULL. pat is readable for len bytes. Definition at line 548 of file mdl_robots.c.
References internal_glob_prefix(), and RA8_INTERNAL.
Referenced by internal_best_matching_rule().
|
static |
Pass 1: find the best specific match length and wildcard presence.
Scans every User-agent field without retaining rules. The longest case-insensitive prefix match becomes best; a * group is reported independently through wild for use only when no specific group wins.
| [in] | text | Robots document bytes. |
| [in] | len | Number of readable bytes at text. |
| [in] | ua_token | Product token to match against user-agent fields. |
| [out] | best | Longest specific match, or the no-match sentinel. |
| [out] | wild | Whether a wildcard user-agent group was present. |
| true | The complete document was scanned without truncation. |
| false | At least one line exceeded the parser buffer. |
text and ua_token are non-NULL; text is readable for len bytes. best and wild point to writable result storage. best and wild describe all complete and truncated line prefixes scanned. Definition at line 249 of file mdl_robots.c.
References internal_agent_spec(), internal_ieq(), internal_next_line(), internal_split_field(), k_robots_line_max, and k_spec_none.
Referenced by mdl_robots_parse().
|
static |
Record the strictest Crawl-delay seen (clamped to the ceiling).
Parses a finite non-negative decimal and retains the largest bounded delay.
| [in,out] | out | Parsed robots result. |
| [in] | value | NUL-terminated crawl-delay value. |
out and value are non-NULL. out contains writable result storage. out. Definition at line 345 of file mdl_robots.c.
References mdl_robots_t::crawl_delay_ms, mdl_robots_t::have_crawl_delay, k_crawl_cap_ms, k_ms_per_s, and RA8_INTERNAL.
Referenced by internal_apply_directive().
|
static |
Split a trimmed line into field/value on the first :.
Replaces the delimiter with NUL and returns trimmed pointers into line.
| [in,out] | line | Writable directive line. |
| [out] | field | Receives the field pointer. |
| [out] | value | Receives the value pointer. |
| true | Both outputs identify substrings in line. |
| false | No delimiter exists or the field is empty. |
line is writable and NUL-terminated. line is split in place. line storage. Definition at line 188 of file mdl_robots.c.
References internal_trim_ws(), RA8_INTERNAL, and strchr().
Referenced by internal_harvest(), and internal_scan_spec().
|
static |
Trim leading/trailing ASCII whitespace in place; return start.
Definition at line 108 of file mdl_robots.c.
References RA8_INTERNAL, and strlen().
Referenced by internal_split_field().
| bool mdl_robots_allows | ( | const mdl_robots_t * | robots, |
| const char * | path ) |
Decide whether path is allowed by a parsed robots group.
Applies the longest-match rule; when an Allow and a Disallow match at the same pattern length, the Allow wins (RFC 9309). A group with no rules permits everything. Patterns honour * and a trailing $.
| [in] | robots | Parsed rules from mdl_robots_parse. |
| [in] | path | URL path to test (with leading /). |
| true | No rule matches, or the winning rule is an Allow. |
| false | The winning (longest) matching rule is a Disallow. |
Definition at line 578 of file mdl_robots.c.
References internal_best_matching_rule(), k_mdl_rule_allow, mdl_robots_rule_t::kind, and mdl_robots_t::valid.
| const mdl_robots_t * mdl_robots_cache_consult | ( | mdl_robots_cache_t * | cache, |
| const char * | scheme, | ||
| const char * | host, | ||
| const char * | ua_token, | ||
| mdl_robots_fetch_fn | fetch, | ||
| void * | ctx, | ||
| char * | scratch, | ||
| size_t | scratch_cap ) |
Return the cached robots rules for host, fetching on first contact.
On a cache miss, builds <scheme>://<host>/robots.txt, calls fetch, applies the RFC 9309 convention (absent/transport error = allow all; 5xx = disallow all), parses a retrieved body for ua_token, and stores the outcome. Subsequent calls for the same host return the stored entry without a network round-trip. When the cache is full, the fetched result is returned uncached rather than evicting a live entry.
| [in] | cache | Per-run cache (zero-initialised before first use). |
| [in] | scheme | URL scheme ("http" or "https"). |
| [in] | host | Host to consult. |
| [in] | ua_token | Our user-agent product token. |
| [in] | fetch | Fetch callback (dependency injection seam). |
| [in] | ctx | Opaque context passed to fetch. |
| [out] | scratch | Working buffer the callback fills. |
| [in] | scratch_cap | Capacity of scratch. |
| non-NULL | Rules to test paths against. |
| NULL | The host said "disallow all" (5xx); refuse every path. |
Definition at line 620 of file mdl_robots.c.
References mdl_robots_cache_entry_t::disallow_all, mdl_robots_cache_entry_t::host, internal_cache_find(), internal_cache_slot(), k_mdl_robots_fetch_denied, k_mdl_robots_fetch_ok, k_mdl_robots_host_max, k_robots_url_max, mdl_robots_parse(), nullptr, mdl_robots_cache_entry_t::rules, mdl_robots_cache_entry_t::scheme, strcmp(), strnlen(), mdl_robots_cache_entry_t::used, and mdl_robots_t::valid.
Referenced by mdl_session_url_allowed().
| const char * mdl_robots_disallow_reason | ( | const mdl_robots_t * | robots, |
| const char * | path ) |
Return the Disallow pattern that forbids path, or NULL if allowed.
Names the exact rule responsible for a refusal so the caller can log a clear, actionable message rather than a bare "disallowed". Uses the same longest-match, Allow-wins-ties resolution as mdl_robots_allows.
| [in] | robots | Parsed rules from mdl_robots_parse. |
| [in] | path | URL path to test (with leading /). |
| non-NULL | Borrowed pointer to the blocking rule's pattern. |
| NULL | No rule blocks path (the winning rule allows, or none). |
Definition at line 587 of file mdl_robots.c.
References internal_best_matching_rule(), k_mdl_rule_disallow, mdl_robots_rule_t::kind, and mdl_robots_rule_t::path.
Referenced by mdl_session_url_allowed().
| void mdl_robots_parse | ( | const char * | text, |
| size_t | len, | ||
| const char * | ua_token, | ||
| mdl_robots_t * | out ) |
Parse robots.txt text for the group matching ua_token.
Selects the most specific matching User-agent group (a case-insensitive User-agent value that is a prefix of ua_token; * is the fallback), merging groups that match at the same specificity, and collects that group's Allow/Disallow rules and the strictest Crawl-delay. Empty Disallow values (which impose no restriction) are skipped. Malformed lines are ignored. An input with no matching group leaves out empty (allow all).
| [in] | text | robots.txt bytes (need not be NUL-terminated). |
| [in] | len | Length of text in bytes. |
| [in] | ua_token | Our user-agent product token (e.g. "mdl"). |
| [out] | out | Result; fully overwritten (zeroed first). |
Definition at line 450 of file mdl_robots.c.
References internal_harvest(), internal_scan_spec(), k_spec_none, and mdl_robots_t::valid.
Referenced by mdl_robots_cache_consult().