code wiki / _hdl_build / nx_clean_serve.nx
nx_clean_serve.nx source
↩ module page · 356 lines · 25843 B
1// nx_clean_serve.nx -- the ETHICAL clean-serve policy engine: the win-win-win transform for the Nishi search
2// engine's neutral, safe delivery of hostile sites. The problem with strip-and-block (ad_strip_junk) is that it
3// nukes EVERY script -> the user is safe but the SITE earns nothing (all ads die too). The problem with letting
4// ads through is malvertising (redirect / popunder / cryptojack / tabnab / fingerprint). The middle path is a
5// THIRD verdict -- SANITIZE: an ad is KEPT as an inert, script-free static creative (image + a click link with
6// rel="noopener noreferrer nofollow") so the SITE still earns the impression + click, while every attack vector
7// (which ALL require active content -- JS, unsandboxed frames, beacons, auto-redirect) is removed. Result:
8// USER safe (no active content survives) + gets the content native HTML5;
9// SITE monetizes (its safe static ads render + click through);
10// SEARCH neutral (a difficult site is served cleanly, not deranked).
11// Composes nx_web_filter's data-driven category verdict. Pure core: the archive daemon imports it for /visit and
12// /preserve; the gate tests it headless with an adversary corpus. Emits a machine-readable SAFETY RECEIPT.
13// license_tier: ORIGINAL
14import "nx_syscalls.nx"
15import "nx_web_filter.nx" // wf_new/wf_seed/wf_should_block + WF_AD/WF_TRACK/WF_MAL/WF_MINER/WF_POPUP/WF_CONTENT
16const CS_MAGIC_4096: i64 = 4096
17const CS_MAGIC_4095: i64 = 4095
18const CS_SKIP_LINE_CAP: i64 = 256 // one row of the media skip table (a substring), NUL-terminated
19const CS_DECL_SEP_MAX: i64 = 24 // bytes of separator tolerated between a declaration key and its quoted value (` content=`, `: `)
20const CS_TOKEN_MIN: i64 = 5 // a page id token shorter than this is too common to identify a stream (a bare numeric year, a two-letter slug)
21const CS_LISTING_MIN: i64 = 6 // this many distinct stream literals with none carrying the page token = a listing grid, not a player
22
23// --- clean-serve verdict (a superset of web_filter's BLOCK/ALLOW: the AD case graduates to SANITIZE) ---
24const CS_ALLOW: i64 = 0 // content / first-party / unknown -> pass through
25const CS_BLOCK: i64 = 1 // an attack vector (tracker/miner/malware/popunder) -> remove entirely
26const CS_SANITIZE: i64 = 2 // an ad -> keep as an inert static creative (site monetizes, user stays safe)
27
28// --- safety receipt: a flat i64 counters buffer (indices below). The honest, adversary/critic-checkable output. ---
29const CR_SCRIPTS: i64 = 0 // <script> blocks removed
30const CR_IFRAMES: i64 = 1 // active third-party frames removed
31const CR_HANDLERS: i64 = 2 // inline on*= event handlers stripped
32const CR_REDIRECTS: i64 = 3 // meta-refresh + javascript: exec/redirect vectors neutralized
33const CR_MINER: i64 = 4 // crypto-miner request URLs neutralized
34const CR_POPUP: i64 = 5 // popunder request URLs neutralized
35const CR_MAL: i64 = 6 // malware/scam request URLs neutralized
36const CR_TRACK: i64 = 7 // tracker/beacon request URLs neutralized
37const CR_ADS_KEPT: i64 = 8 // ad creatives PRESERVED as safe static (the site's monetization, intact)
38const CR_BLOCKED: i64 = 9 // total attack request URLs neutralized (sum of miner+popup+mal+track)
39const CR_ADVIDEO: i64 = 10 // autoplaying ad VIDEO elements removed (a 728x90 banner clip is a creative, not the content)
40const CR_N: i64 = 11
41
42// --- small helpers (mirror the proven ad_*/cw_* idioms; kept local so this is a self-contained core) ---
43func cs_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
44func cs_put(dst: *u8, off: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){dst[off]=s[i];off=off+1;i=i+1} return off }
45func cs_putn(dst: *u8, off: i64, v: i64) -> i64 { var m: i64=v; if m==0 { dst[off]=48 as u8; return off+1 } let t: *u8=sys_mmap(24); var k: i64=0; while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 } var j: i64=0; while j<k { dst[off]=t[k-1-j]; off=off+1; j=j+1 } return off }
46func cs_lc(c: i64) -> i64 { if c>=65 { if c<=90 { return c+32 } } return c }
47func cs_ci_at(src: *u8, slen: i64, pos: i64, lit: *u8, litlen: i64) -> i64 { if pos+litlen>slen { return 0 } var i: i64=0; while i<litlen { if cs_lc(src[pos+i]&0xff)!=cs_lc(lit[i]&0xff) { return 0 } i=i+1 } return 1 }
48func cs_skip_block(src: *u8, slen: i64, from: i64, close: *u8, closelen: i64) -> i64 {
49 var j: i64=from; var found: i64=0
50 while found==0 { if j>=slen { found=1 } else { if cs_ci_at(src, slen, j, close, closelen)==1 { j=j+closelen; found=1 } else { j=j+1 } } }
51 return j
52}
53// a real HTML tag is never this long; bounding cs_tag_end (and the cs_tag_attr/cs_within that scan up to its result)
54// to it stops an unclosed-quote tag from scanning to EOF on EVERY occurrence -- the O(n)-per-tag blowup that made a
55// tag-dense page (a live-cam roomlist) take ~40s to clean. 16 KiB comfortably covers even a big inline data: URI.
56const CS_MAX_TAG: i64 = 16384
57// index of this tag's closing '>' (quote-aware so a '>' inside an attribute value doesn't end it early)
58func cs_tag_end(src: *u8, slen: i64, from: i64) -> i64 {
59 var j: i64 = from; var q: i64 = 0
60 let lim: i64 = from + CS_MAX_TAG
61 while j < slen {
62 if j >= lim { return j }
63 let c: i64 = src[j]&0xff
64 if q==0 { if c==34 { q=1 } else { if c==39 { q=2 } else { if c==62 { return j } } } }
65 else { if q==1 { if c==34 { q=0 } } else { if c==39 { q=0 } } }
66 j = j+1
67 }
68 return slen-1
69}
70// case-insensitive "does [from,to) contain lit"
71func cs_within(src: *u8, from: i64, to: i64, lit: *u8, litlen: i64) -> i64 {
72 var i: i64 = from
73 while i <= to-litlen { if cs_ci_at(src, to, i, lit, litlen)==1 { return 1 } i=i+1 }
74 return 0
75}
76// is byte a delimiter that ends a bare <a> tag name (so <article> is NOT treated as <a>)
77func cs_a_delim(c: i64) -> i64 { if c==32 {return 1} if c==9 {return 1} if c==10 {return 1} if c==13 {return 1} if c==62 {return 1} return 0 }
78// is byte a URL terminator (for harvesting request URLs from the raw HTML)
79func cs_url_delim(c: i64) -> i64 { if c==34{return 1} if c==39{return 1} if c==32{return 1} if c==60{return 1} if c==62{return 1} if c==41{return 1} if c==125{return 1} if c==93{return 1} if c==92{return 1} if c==10{return 1} if c==9{return 1} if c==13{return 1} return 0 }
80// extract the value of attribute `name` from within a tag span [from,to) (quoted or bare, space-delimited attr)
81func cs_tag_attr(src: *u8, from: i64, to: i64, name: *u8, namelen: i64, out: *u8, cap: i64) -> i64 {
82 var i: i64 = from+1
83 while i < to {
84 var bnd: i64 = 0
85 let pc: i64 = src[i-1]&0xff
86 if pc==32 { bnd=1 } else { if pc==9 { bnd=1 } else { if pc==10 { bnd=1 } else { if pc==13 { bnd=1 } } } }
87 if bnd==1 { if cs_ci_at(src, to, i, name, namelen)==1 {
88 let after: i64 = i+namelen
89 if after<to { if (src[after]&0xff)==61 {
90 var vi: i64 = after+1; var qc: i64 = 0
91 if vi<to { let c0: i64=src[vi]&0xff; if c0==34 { qc=34; vi=vi+1 } else { if c0==39 { qc=39; vi=vi+1 } } }
92 var o: i64=0; var go: i64=1
93 while go==1 { if vi>=to { go=0 } else { let c: i64=src[vi]&0xff
94 if qc!=0 { if c==qc { go=0 } else { if o<(cap-1){out[o]=c as u8;o=o+1} vi=vi+1 } }
95 else { if c==32 { go=0 } else { if c==62 { go=0 } else { if o<(cap-1){out[o]=c as u8;o=o+1} vi=vi+1 } } } } }
96 out[o]=0 as u8; return o
97 } }
98 } }
99 i=i+1
100 }
101 out[0]=0 as u8; return 0
102}
103
104// --- allocate + zero a fresh receipt buffer ---
105func cs_rc_new() -> *i64 { let rc: *i64 = sys_mmap(8*CR_N) as *i64; var z: i64=0; while z<CR_N { rc[z]=0; z=z+1 } return rc }
106
107// --- the 3-way verdict: compose the web-filter category into BLOCK / SANITIZE / ALLOW ---
108func cs_verdict(t: *i64, url: *u8, ul: i64, out_cat: *i64) -> i64 {
109 let blk: i64 = wf_should_block(t, url, ul, out_cat)
110 if blk==0 { return CS_ALLOW }
111 if out_cat[0]==WF_AD { return CS_SANITIZE } // an ad -> sanitize+keep, not blanket-block
112 return CS_BLOCK // tracker / miner / malware / popunder -> remove
113}
114
115// The receipt's attack TALLY is evidence, not correctness. On a URL-dense page (a live-cam roomlist carries
116// thousands of thumbnail/link URLs) verdict-checking EVERY one against the O(table) filter is the dominant cost and
117// made large pages take ~40s. Bound the verdict calls: the transform still neutralizes EVERY attack regardless (the
118// script/iframe/handler stripping is verdict-independent); only the receipt COUNTS are capped past the budget.
119const CS_VERDICT_BUDGET: i64 = 400
120// --- scan the raw HTML for request URLs, tally the attacks we neutralize (evidence for the receipt) ---
121func cs_scan_urls(src: *u8, slen: i64, t: *i64, rc: *i64) -> i64 {
122 let ub: *u8 = sys_mmap(CS_MAGIC_4096)
123 let cat: *i64 = sys_mmap(8) as *i64
124 var vc: i64 = 0
125 var i: i64 = 0
126 while i < slen {
127 var hit: i64 = 0
128 if cs_ci_at(src, slen, i, "https://" as *u8, 8)==1 { hit=1 }
129 if hit==0 { if cs_ci_at(src, slen, i, "http://" as *u8, 7)==1 { hit=1 } }
130 if hit==1 {
131 var k: i64 = 0; var j: i64 = i; var go: i64 = 1
132 while go==1 { if j>=slen { go=0 } else { let c: i64=src[j]&0xff; if cs_url_delim(c)==1 { go=0 } else { if k<CS_MAGIC_4095 { ub[k]=c as u8; k=k+1 } j=j+1 } } }
133 ub[k]=0 as u8
134 if k>10 { if vc < CS_VERDICT_BUDGET {
135 vc = vc + 1
136 let v: i64 = cs_verdict(t, ub, k, cat)
137 if v==CS_BLOCK {
138 rc[CR_BLOCKED]=rc[CR_BLOCKED]+1
139 if cat[0]==WF_MINER { rc[CR_MINER]=rc[CR_MINER]+1 }
140 if cat[0]==WF_POPUP { rc[CR_POPUP]=rc[CR_POPUP]+1 }
141 if cat[0]==WF_MAL { rc[CR_MAL]=rc[CR_MAL]+1 }
142 if cat[0]==WF_TRACK { rc[CR_TRACK]=rc[CR_TRACK]+1 }
143 }
144 } }
145 i = j
146 } else { i = i + 1 }
147 }
148 return 0
149}
150
151// --- THE TRANSFORM: neutralize all active/attack content, KEEP+sanitize ad creatives, pass content. ---
152// Removes: <script>/<iframe>/<noscript>/<embed>/<object> blocks, <meta refresh>, inline on*= handlers, and
153// javascript: URIs in attribute values. Rewrites <a ...> to carry rel="noopener noreferrer nofollow" (kills
154// reverse-tabnabbing + referrer leak) while keeping the click, so the ad still monetizes. Everything else --
155// text, images, native <video>, the article DOM -- passes through byte-for-byte. Counts into the receipt `rc`.
156func cs_clean_into(out: *u8, off: i64, cap: i64, src: *u8, slen: i64, t: *i64, rc: *i64) -> i64 {
157 var o: i64 = off; var i: i64 = 0; var vc: i64 = 0
158 let av: *u8 = sys_mmap(CS_MAGIC_4096); let acat: *i64 = sys_mmap(8) as *i64 // reused per-tag scratch -- allocated ONCE, not re-mmap'd per <a>/<img> (per-tag mmap = VMA growth = the large-page O(n^2) slowdown)
159 while i < slen {
160 var handled: i64 = 0
161 if cs_ci_at(src, slen, i, "<script" as *u8, 7)==1 { i=cs_skip_block(src, slen, i+7, "</script>" as *u8, 9); rc[CR_SCRIPTS]=rc[CR_SCRIPTS]+1; handled=1 }
162 if handled==0 { if cs_ci_at(src, slen, i, "<iframe" as *u8, 7)==1 { i=cs_skip_block(src, slen, i+7, "</iframe>" as *u8, 9); rc[CR_IFRAMES]=rc[CR_IFRAMES]+1; handled=1 } }
163 if handled==0 { if cs_ci_at(src, slen, i, "<noscript" as *u8, 9)==1 { i=cs_skip_block(src, slen, i+9, "</noscript>" as *u8, 11); handled=1 } }
164 if handled==0 { if cs_ci_at(src, slen, i, "<embed" as *u8, 6)==1 { i=cs_skip_block(src, slen, i+6, ">" as *u8, 1); rc[CR_IFRAMES]=rc[CR_IFRAMES]+1; handled=1 } }
165 if handled==0 { if cs_ci_at(src, slen, i, "<object" as *u8, 7)==1 { i=cs_skip_block(src, slen, i+7, "</object>" as *u8, 9); rc[CR_IFRAMES]=rc[CR_IFRAMES]+1; handled=1 } }
166 // <video ...> whose src is an ad creative (banner-size token, ad path, preview clip) -> REMOVE the element and count it.
167 // A native player is content and stays; an autoplaying 728x90 clip is active advertising (hornyleak.tv, 2026-09-02).
168 if handled==0 { if cs_ci_at(src, slen, i, "<video" as *u8, 6)==1 {
169 let te: i64 = cs_tag_end(src, slen, i)
170 let al: i64 = cs_tag_attr(src, i, te, "src" as *u8, 3, av, CS_MAGIC_4096)
171 if al>0 { if cs_media_skip(av, al, 0 as *u8)==1 { i=cs_skip_block(src, slen, i+6, "</video>" as *u8, 8); rc[CR_ADVIDEO]=rc[CR_ADVIDEO]+1; handled=1 } }
172 } }
173 // <meta http-equiv=refresh ...> -> drop (auto-redirect / meta-refresh malvertising). Other metas kept.
174 if handled==0 { if cs_ci_at(src, slen, i, "<meta" as *u8, 5)==1 {
175 let te: i64 = cs_tag_end(src, slen, i)
176 if cs_within(src, i, te, "refresh" as *u8, 7)==1 { i=te+1; rc[CR_REDIRECTS]=rc[CR_REDIRECTS]+1; handled=1 }
177 } }
178 // <a ...> -> KEEP but harden: inject rel; the rest of the tag copies normally (so the on*= stripper + the
179 // javascript: neutralizer below still scrub it). If the href is an ad, it counts as a preserved safe ad.
180 if handled==0 { if cs_ci_at(src, slen, i, "<a" as *u8, 2)==1 {
181 let nc: i64 = src[i+2]&0xff
182 if cs_a_delim(nc)==1 {
183 let te: i64 = cs_tag_end(src, slen, i)
184 let al: i64 = cs_tag_attr(src, i, te, "href" as *u8, 4, av, CS_MAGIC_4096)
185 if al>0 { if vc < CS_VERDICT_BUDGET { vc = vc + 1; if cs_verdict(t, av, al, acat)==CS_SANITIZE { rc[CR_ADS_KEPT]=rc[CR_ADS_KEPT]+1 } } }
186 o = cs_put(out, o, "<a rel=\"noopener noreferrer nofollow\"" as *u8)
187 i = i + 2
188 handled = 1
189 }
190 } }
191 // <img ...> -> KEPT (a static image is inherently safe). Count it if its src is an ad creative. No consume.
192 if handled==0 { if cs_ci_at(src, slen, i, "<img" as *u8, 4)==1 {
193 let te: i64 = cs_tag_end(src, slen, i)
194 let al: i64 = cs_tag_attr(src, i, te, "src" as *u8, 3, av, CS_MAGIC_4096)
195 if al>0 { if vc < CS_VERDICT_BUDGET { vc = vc + 1; if cs_verdict(t, av, al, acat)==CS_SANITIZE { rc[CR_ADS_KEPT]=rc[CR_ADS_KEPT]+1 } } }
196 } }
197 // inline event handler " on...=..." -> strip (drops onclick/onload/onerror/onmouseover redirect+exec vectors)
198 if handled==0 { if cs_ci_at(src, slen, i, " on" as *u8, 3)==1 {
199 var j: i64=i+3; var ish: i64=0
200 while j<slen { if (j-i)>64 { j=slen } else { if (src[j]&0xff)==61 { ish=1; j=slen } else { if (src[j]&0xff)==32 { j=slen } else { if (src[j]&0xff)==62 { j=slen } else { j=j+1 } } } } }
201 if ish==1 {
202 var k: i64=i+3
203 var f1: i64=1; while f1==1 { if k>=slen { f1=0 } else { if (src[k]&0xff)==61 { k=k+1; f1=0 } else { k=k+1 } } }
204 if k<slen { let qc: i64=src[k]&0xff
205 if qc==34 { k=k+1; var fq: i64=1; while fq==1 { if k>=slen { fq=0 } else { if (src[k]&0xff)==34 { k=k+1; fq=0 } else { k=k+1 } } } } else { if qc==39 { k=k+1; var fs: i64=1; while fs==1 { if k>=slen { fs=0 } else { if (src[k]&0xff)==39 { k=k+1; fs=0 } else { k=k+1 } } } } else { var fb: i64=1; while fb==1 { if k>=slen { fb=0 } else { let cb: i64=src[k]&0xff; if cb==32 { fb=0 } else { if cb==62 { fb=0 } else { k=k+1 } } } } } }
206 }
207 i=k; rc[CR_HANDLERS]=rc[CR_HANDLERS]+1; handled=1
208 }
209 } }
210 // javascript: URI in an attribute value ( ="javascript:.." / ='javascript:.. / =javascript:.. ) -> neutralize
211 if handled==0 { if i>0 {
212 let pc: i64 = src[i-1]&0xff
213 var atv: i64 = 0
214 if pc==34 { atv=1 } else { if pc==39 { atv=1 } else { if pc==61 { atv=1 } } }
215 if atv==1 { if cs_ci_at(src, slen, i, "javascript:" as *u8, 11)==1 { if o<(cap-1){out[o]=35 as u8;o=o+1} i=i+11; rc[CR_REDIRECTS]=rc[CR_REDIRECTS]+1; handled=1 } }
216 } }
217 if handled==0 { if o<(cap-1) { out[o]=src[i]; o=o+1 } i=i+1 }
218 }
219 return o
220}
221
222// --- convenience: run the full policy (scan for evidence + transform) in one call. `rc` must be cs_rc_new()'d. ---
223func cs_clean_page(src: *u8, slen: i64, t: *i64, out: *u8, cap: i64, rc: *i64) -> i64 {
224 cs_scan_urls(src, slen, t, rc)
225 let o: i64 = cs_clean_into(out, 0, cap, src, slen, t, rc)
226 out[o]=0 as u8
227 return o
228}
229
230// --- entity-body contract ruler: ONE ruler for every consumer of nx_https_fetch_follow (the daemon + nx_cleanview) ---
231// nx_https_fetch_follow_best / _12 return the ENTITY BODY ONLY: ff_core copies from its parsed body_off (or dechunks)
232// into out. A consumer that then scans for the first blank CRLF line is running a SECOND header strip -- on HTML. On any
233// CRLF-formatted document (KVS/kt_player tube sites, IIS, many CMSes) the first CR LF CR LF sits INSIDE the page, and
234// everything before it -- head, the player block, flashvars, video_url -- was discarded before extraction ever ran.
235// MEASURED 2026-09-02 on camwhores.tv/videos/1855636: 81,570 B fetched, body taken from byte 41,335, the receipt said
236// 4 scripts (exactly the 4 after that point) and no video element, while the page carried a plain video_url in flashvars.
237// LF-only pages never hit it, which is why the defect was invisible on the six news sites the board was measured on.
238// The strip is legitimate ONLY when the buffer actually begins with an HTTP status line; an entity body returns 0.
239func cs_entity_body_off(buf: *u8, n: i64) -> i64 {
240 if cs_ci_at(buf, n, 0, "HTTP/" as *u8, 5) == 0 { return 0 }
241 var i: i64=0; while i+3 < n { if (buf[i]&0xff)==13 { if (buf[i+1]&0xff)==10 { if (buf[i+2]&0xff)==13 { if (buf[i+3]&0xff)==10 { return i+4 } } } } i=i+1 }
242 return 0
243}
244
245// --- CS9 media-candidate rulers (2026-09-02): the clean view must never play a preview clip, an ad or the page itself ---
246// cs_has_ci: case-insensitive substring test over a bounded buffer (the ONE matcher the rulers below share).
247func cs_has_ci(hay: *u8, hl: i64, needle: *u8) -> i64 { let nl: i64 = cs_slen(needle); if nl==0 { return 0 } if nl>hl { return 0 } var i: i64=0; let last: i64=hl-nl; while i<=last { if cs_ci_at(hay, hl, i, needle, nl)==1 { return 1 } i=i+1 } return 0 }
248// cs_media_ext: does the URL name a directly playable stream (.mp4 .m3u8 .webm)? The daemon's csd_media_ext delegates here.
249func cs_media_ext(url: *u8, ul: i64) -> i64 { if cs_has_ci(url, ul, ".m3u8" as *u8)==1 { return 1 } if cs_has_ci(url, ul, ".mp4" as *u8)==1 { return 1 } if cs_has_ci(url, ul, ".webm" as *u8)==1 { return 1 } return 0 }
250// cs_media_skip: 1 if the URL is a hover preview, thumbnail, ad or preroll clip that must NEVER become the player.
251// The table is DATA: `table` holds knowledge/cleanserve_media_skip.conf (one substring per line, case-insensitive) when the
252// daemon could read it, else the bootstrap rows below apply (rule 17: conf beats bootstrap beats code). MEASURED 2026-09-02
253// on hornyleak.tv: the first .mp4 literal in the page was one of 15 related-video hover previews on hdplayer.gives, and
254// first-mp4-wins served it as the player, which the operator read as an advertisement.
255func cs_media_skip(url: *u8, ul: i64, table: *u8) -> i64 {
256 var have_table: i64 = 0
257 if (table as i64) != 0 { if table[0] != (0 as u8) { have_table = 1 } }
258 if have_table == 1 {
259 let line: *u8 = sys_mmap(CS_SKIP_LINE_CAP); var i: i64=0; var q: i64=0
260 while table[i] != (0 as u8) {
261 let c: i64 = table[i]&0xff
262 if c==10 { line[q]=0 as u8; if q>0 { if cs_has_ci(url, ul, line)==1 { return 1 } } q=0 } else { if c!=13 { if q<(CS_SKIP_LINE_CAP-1) { line[q]=c as u8; q=q+1 } } }
263 i=i+1
264 }
265 line[q]=0 as u8; if q>0 { if cs_has_ci(url, ul, line)==1 { return 1 } }
266 return 0
267 }
268 if cs_has_ci(url, ul, "/preview/" as *u8)==1 { return 1 }
269 if cs_has_ci(url, ul, "preview." as *u8)==1 { return 1 }
270 if cs_has_ci(url, ul, "_preview" as *u8)==1 { return 1 }
271 if cs_has_ci(url, ul, "/thumb" as *u8)==1 { return 1 }
272 if cs_has_ci(url, ul, "/vast" as *u8)==1 { return 1 }
273 if cs_has_ci(url, ul, "preroll" as *u8)==1 { return 1 }
274 // IAB creative sizes and ad paths: a video named by its banner dimensions is an ad creative, never the content
275 if cs_has_ci(url, ul, "728x90" as *u8)==1 { return 1 }
276 if cs_has_ci(url, ul, "300x250" as *u8)==1 { return 1 }
277 if cs_has_ci(url, ul, "160x600" as *u8)==1 { return 1 }
278 if cs_has_ci(url, ul, "320x50" as *u8)==1 { return 1 }
279 if cs_has_ci(url, ul, "300x600" as *u8)==1 { return 1 }
280 if cs_has_ci(url, ul, "970x250" as *u8)==1 { return 1 }
281 if cs_has_ci(url, ul, "/ads/" as *u8)==1 { return 1 }
282 if cs_has_ci(url, ul, "/ad/" as *u8)==1 { return 1 }
283 if cs_has_ci(url, ul, "banner" as *u8)==1 { return 1 }
284 return 0
285}
286// cs_quoted_after: the next quoted value after `key` (at most 24 bytes of separator such as ` content=` or `: `), copied
287// into out with JSON `\/` unescaped; 0 when the key is absent or unquoted. Explicit flags, never a clobbered cursor.
288func cs_quoted_after(html: *u8, hn: i64, key: *u8, out: *u8, cap: i64) -> i64 {
289 let kl: i64 = cs_slen(key)
290 if kl==0 { out[0]=0 as u8; return 0 } if kl>hn { out[0]=0 as u8; return 0 }
291 var i: i64=0; let last: i64=hn-kl
292 while i<=last {
293 if cs_ci_at(html, hn, i, key, kl)==1 {
294 var j: i64=i+kl; var q: i64=0; var steps: i64=0; var scanning: i64=1
295 while scanning==1 { if j>=hn { scanning=0 } else { if steps>=CS_DECL_SEP_MAX { scanning=0 } else { let c: i64=html[j]&0xff; if c==34 { q=34; scanning=0 } else { if c==39 { q=39; scanning=0 } else { j=j+1; steps=steps+1 } } } } }
296 if q!=0 {
297 var o: i64=0; var k: i64=j+1; var copying: i64=1
298 while copying==1 { if k>=hn { copying=0 } else { let c: i64=html[k]&0xff
299 if c==q { copying=0 } else { if c==92 { if (k+1)<hn { if (html[k+1]&0xff)==47 { if o<(cap-1) { out[o]=47 as u8; o=o+1 } k=k+2 } else { copying=0 } } else { copying=0 } } else { if cs_url_delim(c)==1 { copying=0 } else { if o<(cap-1) { out[o]=c as u8; o=o+1 } k=k+1 } } } } }
300 out[o]=0 as u8
301 if o>0 { return o }
302 }
303 }
304 i=i+1
305 }
306 out[0]=0 as u8; return 0
307}
308// cs_find_declared: the page's DECLARED media -- schema.org VideoObject contentUrl first, then og:video:secure_url,
309// og:video, twitter:player:stream. This ruler only EXTRACTS; the caller applies cs_media_ext, because a declaration that
310// names the page itself (hdthot.com declares og:video = its own URL with og:video:type text/html, measured 2026-09-02) is
311// not media. Metas written content-first (content= before property=) are outside the 24-byte separator window.
312func cs_find_declared(html: *u8, hn: i64, out: *u8, cap: i64) -> i64 {
313 var n: i64 = cs_quoted_after(html, hn, "\"contentUrl\"" as *u8, out, cap)
314 if n>0 { return n }
315 n = cs_quoted_after(html, hn, "property=\"og:video:secure_url\"" as *u8, out, cap); if n>0 { return n }
316 n = cs_quoted_after(html, hn, "property=\"og:video\"" as *u8, out, cap); if n>0 { return n }
317 n = cs_quoted_after(html, hn, "name=\"twitter:player:stream\"" as *u8, out, cap); if n>0 { return n }
318 out[0]=0 as u8; return 0
319}
320
321// cs_page_token: the page's own identity token = its last non-empty path segment (query dropped), copied into out; 0 when
322// the URL has no path segment or the segment is shorter than CS_TOKEN_MIN. KVS pages put the numeric id in every stream
323// URL they mint (.../1855000/1855636/1855636.mp4), VK-style ids (-88674838_456240139) reappear verbatim, and a grid of
324// related videos never carries it -- which is the whole discrimination.
325func cs_page_token(url: *u8, ul: i64, out: *u8, cap: i64) -> i64 {
326 var e: i64 = ul
327 var i: i64 = 0; while i < ul { if (url[i]&0xff)==63 { e = i; i = ul } else { i = i + 1 } } // stop at the query
328 while e > 0 { if (url[e-1]&0xff)==47 { e = e - 1 } else { i = e; e = 0 } } // drop trailing slashes (i = end)
329 if i == 0 { out[0]=0 as u8; return 0 }
330 var s: i64 = i; while s > 0 { if (url[s-1]&0xff)==47 { break } s = s - 1 }
331 // the scheme's '//' must not count as a path: a URL with no path after the host yields the host, which is refused below
332 var n: i64 = i - s
333 if n < CS_TOKEN_MIN { out[0]=0 as u8; return 0 }
334 var k: i64 = 0; while k < n { if (url[s+k]&0xff)==46 { out[0]=0 as u8; return 0 } k = k + 1 } // a dotted segment is a host or a file, not an id
335 k = 0; while k < n { if k < (cap-1) { out[k] = url[s+k] } k = k + 1 }
336 if n < cap { out[n] = 0 as u8 } else { out[cap-1] = 0 as u8 }
337 return n
338}
339
340// --- machine-readable safety receipt (the win-win-win evidence, for the clean-view chrome + census/critic) ---
341func cs_receipt_json(rc: *i64, out: *u8, cap: i64) -> i64 {
342 var o: i64 = 0
343 o = cs_put(out, o, "{\"safe\":true,\"attacks_neutralized\":{\"scripts\":" as *u8); o = cs_putn(out, o, rc[CR_SCRIPTS])
344 o = cs_put(out, o, ",\"iframes\":" as *u8); o = cs_putn(out, o, rc[CR_IFRAMES])
345 o = cs_put(out, o, ",\"inline_handlers\":" as *u8); o = cs_putn(out, o, rc[CR_HANDLERS])
346 o = cs_put(out, o, ",\"redirects\":" as *u8); o = cs_putn(out, o, rc[CR_REDIRECTS])
347 o = cs_put(out, o, ",\"miners\":" as *u8); o = cs_putn(out, o, rc[CR_MINER])
348 o = cs_put(out, o, ",\"popunders\":" as *u8); o = cs_putn(out, o, rc[CR_POPUP])
349 o = cs_put(out, o, ",\"malware\":" as *u8); o = cs_putn(out, o, rc[CR_MAL])
350 o = cs_put(out, o, ",\"trackers\":" as *u8); o = cs_putn(out, o, rc[CR_TRACK])
351 o = cs_put(out, o, ",\"ad_videos\":" as *u8); o = cs_putn(out, o, rc[CR_ADVIDEO])
352 o = cs_put(out, o, "},\"ads_preserved_safe\":" as *u8); o = cs_putn(out, o, rc[CR_ADS_KEPT])
353 o = cs_put(out, o, "}" as *u8)
354 out[o]=0 as u8
355 return o
356}