code wiki / (root) / nx_printers_render.nx

nx_printers_render.nx source

↩ module page · 201 lines · 9704 B

1// nx_printers_render.nx -- render the full honest printer audit as an HTML page (the standing UI law: 2// every capability gets a live UI). PURE emitter: takes a parsed IPP Get-Printer-Attributes response and 3// composes the status (nx_printer_health) + security (nx_printer_security) + waste (nx_printer_waste) 4// verdicts into a styled, self-contained HTML page. No syscalls -> never-brick. Read-only status = safe to 5// publish (controls/sensitive actions stay operator-only per the UI law). 6// genealogy_id: project-printer-management-ipp-sclass-2026-06-20 ; license_tier: ORIGINAL 7 8import "nx_ipp_codec.nx" 9import "nx_printer_health.nx" 10import "nx_printer_security.nx" 11import "nx_printer_waste.nx" 12 13func nx_pr_h(out: *u8, off: i64, s: *u8) -> i64 { 14 var o: i64 = off 15 var i: i64 = 0 16 while s[i] != (0 as u8) { out[o] = s[i]; o = o + 1; i = i + 1 } 17 return o 18} 19func nx_pr_hi(out: *u8, off: i64, v: i64) -> i64 { 20 var o: i64 = off 21 if v == 0 { out[o] = 48 as u8; return o + 1 } 22 var m: i64 = v 23 if m < 0 { out[o] = 45 as u8; o = o + 1; m = 0 - m } 24 let t: *u8 = sys_mmap(24) 25 var k: i64 = 0 26 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 27 var j: i64 = k - 1 28 while j >= 0 { out[o] = t[j]; o = o + 1; j = j - 1 } 29 return o 30} 31// copy a raw IPP string attribute value (vlen bytes) into out, or "(not reported)" 32func nx_pr_attr(out: *u8, off: i64, body: *u8, n: i64, name: *u8, sc3: *i64) -> i64 { 33 let p_tag: *i64 = sc3 34 let p_voff: *i64 = ((sc3 as i64) + 8) as *i64 35 let p_vlen: *i64 = ((sc3 as i64) + 16) as *i64 36 if nx_ipp_find(body, n, name, p_tag, p_voff, p_vlen) != NX_IPP_OK { return nx_pr_h(out, off, "(not reported)") } 37 var o: i64 = off 38 var i: i64 = 0 39 while i < p_vlen[0] { out[o] = body[p_voff[0] + i]; o = o + 1; i = i + 1 } 40 return o 41} 42 43func nx_pr_canprint(v: i64) -> *u8 { 44 if v == NX_PR_CAN_PRINT { return "READY" as *u8 } 45 if v == NX_PR_DEGRADED { return "DEGRADED" as *u8 } 46 if v == NX_PR_BLOCKED { return "BLOCKED" as *u8 } 47 return "UNKNOWN" as *u8 48} 49func nx_pr_canclass(v: i64) -> *u8 { 50 if v == NX_PR_CAN_PRINT { return "ok" as *u8 } 51 if v == NX_PR_DEGRADED { return "warn" as *u8 } 52 return "bad" as *u8 53} 54func nx_pr_secname(v: i64) -> *u8 { 55 if v == NX_PSEC_SECURE { return "SECURE" as *u8 } 56 if v == NX_PSEC_WEAK { return "WEAK" as *u8 } 57 if v == NX_PSEC_EXPOSED { return "EXPOSED" as *u8 } 58 return "UNKNOWN" as *u8 59} 60func nx_pr_sevname(s: i64) -> *u8 { 61 if s == NX_SEV_ERROR { return "ERROR" as *u8 } 62 if s == NX_SEV_WARNING { return "WARNING" as *u8 } 63 if s == NX_SEV_REPORT { return "report" as *u8 } 64 return "none" as *u8 65} 66 67// emit each printer-state-reasons value as an <li> with its severity (the bit the vendor UI hides) 68func nx_pr_reasons(out: *u8, off: i64, body: *u8, n: i64, pstate: i64) -> i64 { 69 var o: i64 = off 70 if n < 8 { return o } 71 var p: i64 = 8 72 var in_reasons: i64 = 0 73 var keep: i64 = 1 74 while keep == 1 { 75 if p >= n { keep = 0 } 76 else { 77 let tag: i64 = body[p] as i64 78 if tag == NX_IPP_TAG_END { keep = 0 } 79 else { 80 if tag <= 0x0f { p = p + 1; in_reasons = 0 } 81 else { 82 if (p + 3) > n { keep = 0 } 83 else { 84 let nlen: i64 = nx_ipp_get_u16(body, p + 1) 85 let name_off: i64 = p + 3 86 if (name_off + nlen + 2) > n { keep = 0 } 87 else { 88 let vlen_off: i64 = name_off + nlen 89 let vlen: i64 = nx_ipp_get_u16(body, vlen_off) 90 let val_off: i64 = vlen_off + 2 91 if (val_off + vlen) > n { keep = 0 } 92 else { 93 if nlen > 0 { 94 if nx_ipp_name_eq(body, name_off, "printer-state-reasons", 21) == 1 { in_reasons = 1 } 95 else { in_reasons = 0 } 96 } 97 if in_reasons == 1 { 98 let sev: i64 = nx_ph_reason_severity(body, val_off, vlen, pstate) 99 o = nx_pr_h(out, o, "<li><code>") 100 var i: i64 = 0 101 while i < vlen { out[o] = body[val_off + i]; o = o + 1; i = i + 1 } 102 o = nx_pr_h(out, o, "</code> <span class=sev>") 103 o = nx_pr_h(out, o, nx_pr_sevname(sev)) 104 o = nx_pr_h(out, o, "</span></li>") 105 } 106 p = val_off + vlen 107 } 108 } 109 } 110 } 111 } 112 } 113 } 114 return o 115} 116 117// Render the whole page. scratch = caller i64[8]. toner_bp = real toner remaining in basis points (or -1 118// if not tracked yet); toner_pages = std-pages left. Returns HTML length. 119func nx_printers_render(out: *u8, body: *u8, n: i64, scratch: *i64, toner_bp: i64, toner_pages: i64) -> i64 { 120 let o_state: *i64 = scratch 121 let o_sev: *i64 = ((scratch as i64) + 8) as *i64 122 let o_cnt: *i64 = ((scratch as i64) + 16) as *i64 123 let o_acc: *i64 = ((scratch as i64) + 24) as *i64 124 let sc3: *i64 = ((scratch as i64) + 32) as *i64 // 3 cells for find 125 let verdict: i64 = nx_printer_diagnose(body, n, sc3, o_state, o_sev, o_cnt, o_acc) 126 let secfl: *i64 = ((scratch as i64) + 56) as *i64 127 let secv: i64 = nx_printer_security(body, n, sc3, secfl) 128 let w_cnt: *i64 = ((scratch as i64) + 64) as *i64 129 let w_pct: *i64 = ((scratch as i64) + 72) as *i64 130 let w_dup: *i64 = ((scratch as i64) + 80) as *i64 131 let w_sc: *i64 = ((scratch as i64) + 88) as *i64 // 4 cells 132 let supv: i64 = nx_printer_waste(body, n, w_sc, w_cnt, w_pct, w_dup) 133 134 var o: i64 = 0 135 o = nx_pr_h(out, o, "<!DOCTYPE html><html><head><meta charset=utf-8><title>Nishi Printer Status</title><style>") 136 o = nx_pr_h(out, o, "body{font:15px/1.5 system-ui,sans-serif;max-width:760px;margin:2rem auto;padding:0 1rem;color:#1a1a1a}") 137 o = nx_pr_h(out, o, "h1{font-size:1.4rem}.card{border:1px solid #ddd;border-radius:10px;padding:1rem 1.2rem;margin:1rem 0}") 138 o = nx_pr_h(out, o, ".ok{color:#137333}.warn{color:#b06000}.bad{color:#c5221f;font-weight:600}") 139 o = nx_pr_h(out, o, ".big{font-size:1.2rem;font-weight:600}.sev{font-size:.8rem;color:#666}code{background:#f3f3f3;padding:1px 4px;border-radius:4px}") 140 o = nx_pr_h(out, o, "</style></head><body><h1>\xF0\x9F\x96\xA8\xEF\xB8\x8F Nishi Printer Status</h1>") 141 o = nx_pr_h(out, o, "<p>Sovereign IPP audit &mdash; the truth your vendor UI hides. Read-only.</p>") 142 143 // identity 144 o = nx_pr_h(out, o, "<div class=card><b>") 145 o = nx_pr_attr(out, o, body, n, "printer-make-and-model", sc3) 146 o = nx_pr_h(out, o, "</b></div>") 147 148 // can-print 149 o = nx_pr_h(out, o, "<div class=card><div class=big><span class=") 150 o = nx_pr_h(out, o, nx_pr_canclass(verdict)) 151 o = nx_pr_h(out, o, ">Can print now: ") 152 o = nx_pr_h(out, o, nx_pr_canprint(verdict)) 153 o = nx_pr_h(out, o, "</span></div><ul>") 154 o = nx_pr_reasons(out, o, body, n, o_state[0]) 155 o = nx_pr_h(out, o, "</ul></div>") 156 157 // security 158 o = nx_pr_h(out, o, "<div class=card><b>Security:</b> <span class=") 159 var seccls: *u8 = "ok" 160 if secv == NX_PSEC_EXPOSED { seccls = "bad" } 161 if secv == NX_PSEC_WEAK { seccls = "warn" } 162 o = nx_pr_h(out, o, seccls) 163 o = nx_pr_h(out, o, ">") 164 o = nx_pr_h(out, o, nx_pr_secname(secv)) 165 o = nx_pr_h(out, o, "</span>") 166 if secv == NX_PSEC_EXPOSED { 167 o = nx_pr_h(out, o, "<p class=bad>Wide open: anyone on this network can read your documents and submit jobs (same class as CUPS CVE-2024-47176).</p>") 168 } 169 o = nx_pr_h(out, o, "</div>") 170 171 // supplies & waste 172 o = nx_pr_h(out, o, "<div class=card><b>Supplies &amp; waste</b><br>Lowest supply: ") 173 if w_pct[0] < 0 { o = nx_pr_h(out, o, "unknown") } 174 else { o = nx_pr_hi(out, o, w_pct[0]); o = nx_pr_h(out, o, "%") } 175 if supv == NX_SUP_EMPTY { o = nx_pr_h(out, o, " <span class=bad>(EMPTY)</span>") } 176 if supv == NX_SUP_LOW { o = nx_pr_h(out, o, " <span class=warn>(LOW)</span>") } 177 if w_dup[0] == NX_DUP_WASTE { 178 o = nx_pr_h(out, o, "<br><span class=warn>Paper waste: duplex supported but defaults to one-sided.</span> Fix: print two-sided to halve paper.") 179 } 180 o = nx_pr_h(out, o, "</div>") 181 182 // real toner (measured by ink coverage -- the printer's gauge ignored) 183 o = nx_pr_h(out, o, "<div class=card><b>Real toner</b> <span class=sev>(measured by ink coverage, not the printer)</span><br>") 184 if toner_bp < 0 { 185 o = nx_pr_h(out, o, "not yet tracked &mdash; prints calibrate it") 186 } else { 187 o = nx_pr_h(out, o, "<span class=big class=ok>") 188 o = nx_pr_hi(out, o, toner_bp / 100) 189 o = nx_pr_h(out, o, ".") 190 let f: i64 = toner_bp % 100 191 if f < 10 { o = nx_pr_h(out, o, "0") } 192 o = nx_pr_hi(out, o, f) 193 o = nx_pr_h(out, o, "%</span> &mdash; ~") 194 o = nx_pr_hi(out, o, toner_pages) 195 o = nx_pr_h(out, o, " pages left<br><span class=warn>Printer claims 0% / Replace Toner &mdash; ignored.</span>") 196 } 197 o = nx_pr_h(out, o, "</div>") 198 o = nx_pr_h(out, o, "<p style=color:#999;font-size:.8rem>Generated by sovereign Nishi organs (nx_ipp_codec/health/security/waste/toner). No vendor driver, no cloud.</p>") 199 o = nx_pr_h(out, o, "</body></html>") 200 return o 201}