code wiki / _hdl_build / nx_cms_booking.nx

nx_cms_booking.nx source

↩ module page · 82 lines · 5090 B

1// nx_cms_booking.nx -- the consultation-booking BACKEND that finishes the "scheduler that works with the email 2// systems" (the crash-interrupted rung). Composes existing organs, no reinvention: 3// nx_cms_store -- persists the booking as a sovereign record (@name/@phone/@email/@matter/@date/@time/@status) 4// nx_cms_email -- email_addr_valid() gates the client address 5// nx_email_mime -- (format reference) RFC 5322 confirmation message 6// nx_cron -- registers a same-day reminder job (fires once) 7// Defensive at the boundary (Cardinal 12): every web-supplied value is SANITIZED (control chars incl CR/LF 8// stripped) before it enters a record field OR an email header -> header-injection / record-format-break safe. 9// Pure logic (mmap only) -> fully gateable offline; the LIVE rung (daemon POST /schedule -> bk_book + real MTA 10// send via nx_email_send) wires this to andelinwest.com next. license_tier: ORIGINAL 11import "nx_syscalls.nx" 12import "nx_cms_store.nx" 13import "nx_cms_email.nx" 14import "nx_cron.nx" 15const K_MAGIC_8192: i64 = 8192 16const K_MAGIC_2000000000: i64 = 2000000000 17 18func bk_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 19func bk_cat(dst: *u8, off: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){ dst[off+i]=s[i]; i=i+1 } return off+i } 20// copy s into dst dropping ALL control chars (<32): strips CR(13)/LF(10)/tab(9) -> no header injection, no 21// record-format break. returns new offset. 22func bk_san(dst: *u8, off: i64, s: *u8) -> i64 { 23 var o: i64=off; var i: i64=0 24 while s[i]!=(0 as u8) { let c: i64=s[i] as i64; if c>=32 { dst[o]=s[i]; o=o+1 } i=i+1 } 25 return o 26} 27func bk_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 28 29// build the booking record (nx_cms_store format) into out; status="requested"; return length 30func bk_store(name: *u8, phone: *u8, email: *u8, matter: *u8, date: *u8, time: *u8, out: *u8) -> i64 { 31 var o: i64=0 32 o=bk_cat(out,o,"@name\n" as *u8); o=bk_san(out,o,name); out[o]=10 as u8; o=o+1 33 o=bk_cat(out,o,"@phone\n" as *u8); o=bk_san(out,o,phone); out[o]=10 as u8; o=o+1 34 o=bk_cat(out,o,"@email\n" as *u8); o=bk_san(out,o,email); out[o]=10 as u8; o=o+1 35 o=bk_cat(out,o,"@matter\n" as *u8); o=bk_san(out,o,matter); out[o]=10 as u8; o=o+1 36 o=bk_cat(out,o,"@date\n" as *u8); o=bk_san(out,o,date); out[o]=10 as u8; o=o+1 37 o=bk_cat(out,o,"@time\n" as *u8); o=bk_san(out,o,time); out[o]=10 as u8; o=o+1 38 o=bk_cat(out,o,"@status\nrequested\n" as *u8) 39 return o 40} 41 42// assemble the RFC 5322 confirmation email to the client; return length. Header values sanitized. 43func bk_confirm(name: *u8, email: *u8, matter: *u8, date: *u8, time: *u8, out: *u8) -> i64 { 44 var o: i64=0 45 o=bk_cat(out,o,"From: intake@andelinwest.com\r\nTo: " as *u8); o=bk_san(out,o,email) 46 o=bk_cat(out,o,"\r\nSubject: Your consultation request - " as *u8); o=bk_san(out,o,matter) 47 o=bk_cat(out,o,"\r\n\r\nDear " as *u8); o=bk_san(out,o,name) 48 o=bk_cat(out,o,",\r\n\r\nWe received your consultation request (" as *u8); o=bk_san(out,o,matter) 49 o=bk_cat(out,o,", preferred " as *u8); o=bk_san(out,o,date); out[o]=32 as u8; o=o+1; o=bk_san(out,o,time) 50 o=bk_cat(out,o,"). Our intake team will confirm your appointment shortly. If your matter is urgent, please call (801) 555-0100.\r\n\r\n-- Andelin West, PLLC\r\nintake@andelinwest.com\r\n" as *u8) 51 return o 52} 53 54// register a same-day reminder for this booking via the cron core; return the cron verdict 55func bk_reminder(name: *u8, namelen: i64, fire_at: i64) -> i64 { 56 let jp: *NxCronJob = sys_mmap(256) as *NxCronJob 57 jp.job_name_ptr = name 58 jp.job_name_len = namelen 59 jp.schedule_kind = NX_CRON_KIND_AT_UNIX_ONCE 60 jp.interval_seconds = 0 61 jp.fire_at_unix = fire_at 62 jp.missed_policy = NX_CRON_MISSED_CATCH_UP_ONCE 63 jp.action_kind = NX_CRON_ACTION_PUBLISH 64 jp.action_arg = 1 65 jp.enabled = 1 66 return nx_cron_register_job(jp) 67} 68 69func main() -> i64 { 70 // demo: book a sample consultation -> record + confirmation + reminder 71 let rec: *u8 = sys_mmap(K_MAGIC_8192) 72 let rl: i64 = bk_store("Jane Roe" as *u8, "801-555-1212" as *u8, "jane@example.com" as *u8, "Estate Planning" as *u8, "2026-07-01" as *u8, "Morning (9-12)" as *u8, rec) 73 bk_puts("=== BOOKING RECORD ===\n" as *u8); sys_write(1, rec, rl); bk_puts("\n" as *u8) 74 let msg: *u8 = sys_mmap(K_MAGIC_8192) 75 let ml: i64 = bk_confirm("Jane Roe" as *u8, "jane@example.com" as *u8, "Estate Planning" as *u8, "2026-07-01" as *u8, "Morning (9-12)" as *u8, msg) 76 bk_puts("=== CONFIRMATION EMAIL ===\n" as *u8); sys_write(1, msg, ml); bk_puts("\n" as *u8) 77 let v: i64 = bk_reminder("reminder-jane" as *u8, 13, K_MAGIC_2000000000) 78 bk_puts("reminder cron verdict=" as *u8) 79 let bb: *u8=sys_mmap(28); var m: i64=v; var k: i64=0; if m==0{bb[0]=48 as u8;k=1}; let t: *u8=sys_mmap(28); while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1}; var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1}; sys_write(1,bb,k) 80 bk_puts("\n" as *u8) 81 sys_exit(0); return 0 82}