From d921a2b1443876ab701059460f34d8eb0ffe1e1d Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Fri, 11 Oct 2024 16:54:56 -0400 Subject: [PATCH] Escape LF in board file, refuse to store or print control chars --- internal/bulb/bulb.ha | 49 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/internal/bulb/bulb.ha b/internal/bulb/bulb.ha index 805016e..2ab0fe1 100644 --- a/internal/bulb/bulb.ha +++ b/internal/bulb/bulb.ha @@ -1,3 +1,4 @@ +use ascii; use bufio; use fs; use fmt; @@ -40,8 +41,37 @@ export fn read(output: io::handle, board: str, number: int) (void | error) = { // we add 1 to account for the blank line that will always be at the // bottom seek_to_nth_last_line(file, number + 1)?; - // TODO don't copy control characters! - io::copy(output, file)?; + + static let output_wbuf: [os::BUFSZ]u8 = [0...]; + let output = bufio::init(output, [], output_wbuf); + let file = bufio::newscanner(file); + defer bufio::finish(&file); + + let saw_escape = false; + for (true) { + let byte = match (bufio::scan_byte(&file)?) { + case let byte: u8 => yield byte; + case io::EOF => break; + }; + + if (byte == '\x1b') { + saw_escape = true; + } else { + if (byte == '\n') { + if (saw_escape) { + fmt::fprint(&output, "\n ")?; + } else { + fmt::fprint(&output, "\n")?; + }; + } else if (!ascii::iscntrl(byte: rune)) { + let fake_buffer: [1]u8 = [byte]; + io::write(&output, fake_buffer)?; + }; + saw_escape = false; + }; + }; + + bufio::flush(&output)?; }; export fn post(input: io::handle, board: str, user_name: (str | void)) (void | error) = { @@ -56,27 +86,26 @@ export fn post(input: io::handle, board: str, user_name: (str | void)) (void | e }; static let file_wbuf: [os::BUFSZ]u8 = [0...]; - let file = bufio::init(file, [], file_wbuf); - let scanner = bufio::newscanner(input); - defer bufio::finish(&scanner); + let file = bufio::init(file, [], file_wbuf); + let input = bufio::newscanner(input); + defer bufio::finish(&input); let saw_break = false; fmt::fprintf(&file, "{}: ", user)?; for (true) { - let byte = match (bufio::scan_byte(&scanner)?) { + let byte = match (bufio::scan_byte(&input)?) { case let byte: u8 => yield byte; case io::EOF => break; }; if (saw_break) { - fmt::fprint(&file, "\n ")?; + fmt::fprint(&file, "\x1b\n")?; saw_break = false; }; - switch (byte) { - case '\n' => + if (byte == '\n') { saw_break = true; - case => + } else if (!ascii::iscntrl(byte: rune)) { let fake_buffer: [1]u8 = [byte]; io::write(&file, fake_buffer)?; };