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}