code wiki / _hdl_build / nx_email_retrieve_gate.nx

nx_email_retrieve_gate.nx source

↩ module page · 138 lines · 6900 B

1// nx_email_retrieve_gate.nx -- GATE for EMAIL R4 (POP3/IMAP, nx_email_retrieve). 2// 3// COMPLETENESS : POP3 +OK/-ERR status, STAT count/octets, command 4// build, multi-line de-dot-stuffing + terminator; IMAP 5// tagged command build, tagged completion status, 6// literal "{n}" size. 7// NEG-CONTROL : a non-status POP3 line -> -1; an IMAP response with 8// only untagged data -> incomplete (0). 9// TAMPER : IMAP status scan SKIPS untagged "* OK [...]" lines and 10// returns the real tagged "A001 OK" (untagged-confusion 11// defense); POP3 de-dot turns "..x" into ".x" and stops 12// exactly at the lone "." terminator. 13// 14// Evidence -> knowledge/status/email_retrieve.log 15// (RETRIEVEGATE authored=organ ... verdict=GREEN) 16// license_tier: ORIGINAL 17import "nx_email_retrieve.nx" 18import "nx_syscalls.nx" 19import "nx_gate_verdict.nx" 20 21const RET_LOG: *u8 = "knowledge/status/email_retrieve.log" 22 23func ew(fd: i64, s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(fd, s, n); return 0 } 24func ewn(fd: i64, v: i64) -> i64 { 25 let b: *u8 = sys_mmap(28); var m: i64 = v 26 if m < 0 { m = 0 - m; sys_write(fd, "-" as *u8, 1) } 27 let t: *u8 = sys_mmap(28); var k: i64 = 0 28 if m == 0 { t[0] = 48; k = 1 } 29 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 30 var i: i64 = 0; while i < k { b[i] = t[k - 1 - i]; i = i + 1 } 31 sys_write(fd, b, k); return 0 32} 33func epf(fd: i64, label: *u8, pass: i64) -> i64 { ew(fd, label); if pass == 1 { ew(fd, "PASS" as *u8) } else { ew(fd, "FAIL" as *u8) } return 0 } 34func slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 35func memeq(a: *u8, b: *u8, len: i64) -> i64 { var i: i64 = 0; while i < len { if a[i] != b[i] { return 0 } i = i + 1 } return 1 } 36 37func main() -> i64 { 38 var ok: i64 = 1 39 let out: *u8 = sys_mmap(1024) 40 let oc: *i64 = sys_mmap(8) as *i64 41 let oo: *i64 = sys_mmap(8) as *i64 42 let st: *i64 = sys_mmap(8) as *i64 43 let lit: *i64 = sys_mmap(8) as *i64 44 45 // ---- POP3 status ---- 46 var pop_ok: i64 = 0 47 if nx_pop3_reply_ok("+OK 5 messages\r\n" as *u8, slen("+OK 5 messages\r\n" as *u8)) == 1 { pop_ok = 1 } else { ok = 0 } 48 var pop_err: i64 = 0 49 if nx_pop3_reply_ok("-ERR no such\r\n" as *u8, slen("-ERR no such\r\n" as *u8)) == 0 { pop_err = 1 } else { ok = 0 } 50 var pop_garbage: i64 = 0 51 if nx_pop3_reply_ok("garbage line\r\n" as *u8, slen("garbage line\r\n" as *u8)) == (0 - 1) { pop_garbage = 1 } else { ok = 0 } 52 53 // ---- POP3 STAT ---- 54 var pop_stat: i64 = 0 55 if nx_pop3_parse_stat("+OK 2 320\r\n" as *u8, slen("+OK 2 320\r\n" as *u8), oc, oo) == 1 { 56 if *oc == 2 && *oo == 320 { pop_stat = 1 } 57 } 58 if pop_stat != 1 { ok = 0 } 59 60 // ---- POP3 build ---- 61 let bl: i64 = nx_pop3_build(out, 1024, "RETR" as *u8, "1" as *u8, 1) 62 var pop_build: i64 = 0 63 if bl == slen("RETR 1\r\n" as *u8) && memeq(out, "RETR 1\r\n" as *u8, bl) == 1 { pop_build = 1 } else { ok = 0 } 64 let bl2: i64 = nx_pop3_build(out, 1024, "STAT" as *u8, "" as *u8, 0) 65 if memeq(out, "STAT\r\n" as *u8, bl2) != 1 { ok = 0 } 66 67 // ---- POP3 de-dot-stuff ---- 68 let dd: i64 = nx_pop3_dedot("Hello\r\n..stuffed\r\n.\r\n" as *u8, slen("Hello\r\n..stuffed\r\n.\r\n" as *u8), out, 1024) 69 var pop_dedot: i64 = 0 70 if dd == slen("Hello\r\n.stuffed\r\n" as *u8) && memeq(out, "Hello\r\n.stuffed\r\n" as *u8, dd) == 1 { pop_dedot = 1 } else { ok = 0 } 71 72 // ---- POP3 multi-line completeness ---- 73 var pop_complete: i64 = 0 74 if nx_pop3_multiline_complete("line1\r\nline2\r\n.\r\n" as *u8, slen("line1\r\nline2\r\n.\r\n" as *u8)) == 1 75 && nx_pop3_multiline_complete("partial\r\n" as *u8, slen("partial\r\n" as *u8)) == 0 { pop_complete = 1 } else { ok = 0 } 76 77 // ---- IMAP build ---- 78 let il: i64 = nx_imap_build_tagged(out, 1024, "A001" as *u8, 4, "LOGIN user pass" as *u8, 15) 79 var imap_build: i64 = 0 80 if memeq(out, "A001 LOGIN user pass\r\n" as *u8, il) == 1 && il == slen("A001 LOGIN user pass\r\n" as *u8) { imap_build = 1 } else { ok = 0 } 81 82 // ---- IMAP tagged status, skipping untagged "* OK" ---- 83 let resp: *u8 = "* 2 EXISTS\r\n* OK [UIDVALIDITY 1]\r\nA001 OK LOGIN completed\r\n" as *u8 84 var imap_ok: i64 = 0 85 if nx_imap_reply_status(resp, slen(resp), "A001" as *u8, 4, st) == 1 { 86 if *st == 0 { imap_ok = 1 } 87 } 88 if imap_ok != 1 { ok = 0 } 89 // untagged-only -> incomplete 90 var imap_incomplete: i64 = 0 91 if nx_imap_reply_status("* 2 EXISTS\r\n" as *u8, slen("* 2 EXISTS\r\n" as *u8), "A001" as *u8, 4, st) == 0 { imap_incomplete = 1 } else { ok = 0 } 92 // NO status 93 var imap_no: i64 = 0 94 if nx_imap_reply_status("A002 NO [AUTHENTICATIONFAILED] bad\r\n" as *u8, slen("A002 NO [AUTHENTICATIONFAILED] bad\r\n" as *u8), "A002" as *u8, 4, st) == 1 { 95 if *st == 1 { imap_no = 1 } 96 } 97 if imap_no != 1 { ok = 0 } 98 99 // ---- IMAP literal size ---- 100 var imap_lit: i64 = 0 101 if nx_imap_literal_size("* 1 FETCH (BODY[] {42}\r\n" as *u8, slen("* 1 FETCH (BODY[] {42}\r\n" as *u8), lit) == 1 { 102 if *lit == 42 { imap_lit = 1 } 103 } 104 if imap_lit != 1 { ok = 0 } 105 106 var fd: i64 = 1 107 while fd >= 1 { 108 ew(fd, "RETRIEVEGATE authored=organ rfc=1939+3501 " as *u8) 109 epf(fd, "pop3_ok=" as *u8, pop_ok) 110 epf(fd, " pop3_err=" as *u8, pop_err) 111 epf(fd, " pop3_garbage_negctrl=" as *u8, pop_garbage) 112 epf(fd, " pop3_stat=" as *u8, pop_stat) 113 epf(fd, " pop3_build=" as *u8, pop_build) 114 epf(fd, " pop3_dedot=" as *u8, pop_dedot) 115 epf(fd, " pop3_complete=" as *u8, pop_complete) 116 epf(fd, " imap_build=" as *u8, imap_build) 117 epf(fd, " imap_status_ok=" as *u8, imap_ok) 118 epf(fd, " imap_untagged_skip_incomplete=" as *u8, imap_incomplete) 119 epf(fd, " imap_status_no=" as *u8, imap_no) 120 ew(fd, " imap_literal=" as *u8); ewn(fd, *lit) 121 epf(fd, " imap_literal_ok=" as *u8, imap_lit) 122 if ok == 1 { ew(fd, " verdict=GREEN\n" as *u8) } else { ew(fd, " verdict=RED\n" as *u8) } 123 if fd == 1 { 124 let lf: i64 = sys_openat_append(RET_LOG, 420) 125 if lf >= 1 { fd = lf } else { fd = 0 } 126 } else { sys_close(fd); fd = 0 } 127 } 128 129 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 130 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 131 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 132 let ctr__dry: *i64 = gv_ctr() 133 ctr__dry[0] = ok 134 ctr__dry[1] = 1 135 let rc__dry: i64 = gv_verdict("EMAIL-RETRIEVE-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8) 136 sys_exit(rc__dry) 137 return rc__dry 138}