zachzurn / thermal

🖨️ Render Images and HTML from ESC/POS
Apache License 2.0
37 stars 4 forks source link

Sharp Cash Register receipt printing parser error #23

Closed soulflyman closed 3 weeks ago

soulflyman commented 3 weeks ago

Hi and at first, I have to thank you for this library! I was that close to write something similar 😄.

A while ago, I captured the print commands from a sharp cash register sent to an Epson thermal printer clone.

I can't upload the printer commands because the file gets detected as an unsupported binary by GitHub. So I uploaded it to a hoster where it is available for 30 days: https://upload.adminforge.de/r/u20Y6GqmwF#LWXij1ew1MNB9ToKDYs1gpMfiPSJ0ftgA588Mhx/GNE=

When I try to render these commands as an Image, it panics:

thread 'main' panicked at /home/user/.cargo/git/checkouts/thermal-61d22b10ce2786a2/e29abbf/thermal_parser/src/parser.rs:150:43:
called `Option::unwrap()` on a `None` value
stack backtrace:
   0: rust_begin_unwind
             at /rustc/aedd173a2c086e558c2b66d3743b344f977621a7/library/std/src/panicking.rs:647:5
   1: core::panicking::panic_fmt
             at /rustc/aedd173a2c086e558c2b66d3743b344f977621a7/library/core/src/panicking.rs:72:14
   2: core::panicking::panic
             at /rustc/aedd173a2c086e558c2b66d3743b344f977621a7/library/core/src/panicking.rs:144:5
   3: core::option::unwrap_failed
             at /rustc/aedd173a2c086e558c2b66d3743b344f977621a7/library/core/src/option.rs:1978:5
   4: core::option::Option<T>::unwrap
             at /rustc/aedd173a2c086e558c2b66d3743b344f977621a7/library/core/src/option.rs:931:21
   5: thermal_parser::parser::Parser::parse
             at /home/edward/.cargo/git/checkouts/thermal-61d22b10ce2786a2/e29abbf/thermal_parser/src/parser.rs:150:35
   6: thermal_parser::parser::Parser::parse_bytes
             at /home/edward/.cargo/git/checkouts/thermal-61d22b10ce2786a2/e29abbf/thermal_parser/src/parser.rs:32:13
   7: Kitchen_Commander::escpos::termparse
             at ./src/escpos.rs:56:5
   8: Kitchen_Commander::escpos::test
             at ./src/escpos.rs:12:5
   9: Kitchen_Commander::main::{{closure}}
             at ./src/main.rs:68:5
  10: tokio::runtime::park::CachedParkThread::block_on::{{closure}}
             at /home/edward/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.40.0/src/runtime/park.rs:281:63
  11: tokio::runtime::coop::with_budget
             at /home/edward/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.40.0/src/runtime/coop.rs:107:5
  12: tokio::runtime::coop::budget
             at /home/edward/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.40.0/src/runtime/coop.rs:73:5
  13: tokio::runtime::park::CachedParkThread::block_on
             at /home/edward/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.40.0/src/runtime/park.rs:281:31
  14: tokio::runtime::context::blocking::BlockingRegionGuard::block_on
             at /home/edward/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.40.0/src/runtime/context/blocking.rs:66:9
  15: tokio::runtime::scheduler::multi_thread::MultiThread::block_on::{{closure}}
             at /home/edward/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.40.0/src/runtime/scheduler/multi_thread/mod.rs:87:13
  16: tokio::runtime::context::runtime::enter_runtime
             at /home/edward/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.40.0/src/runtime/context/runtime.rs:65:16
  17: tokio::runtime::scheduler::multi_thread::MultiThread::block_on
             at /home/edward/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.40.0/src/runtime/scheduler/multi_thread/mod.rs:86:9
  18: tokio::runtime::runtime::Runtime::block_on_inner
             at /home/edward/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.40.0/src/runtime/runtime.rs:363:45
  19: tokio::runtime::runtime::Runtime::block_on
             at /home/edward/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.40.0/src/runtime/runtime.rs:335:13
  20: rocket::async_run
             at /home/edward/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rocket-0.5.1/src/lib.rs:250:18
  21: rocket::async_main
             at /home/edward/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rocket-0.5.1/src/lib.rs:282:5
  22: Kitchen_Commander::main
             at ./src/main.rs:28:46
  23: core::ops::function::FnOnce::call_once
             at /rustc/aedd173a2c086e558c2b66d3743b344f977621a7/library/core/src/ops/function.rs:

Making the following changes does prevent the error and parses the printer code:

diff --git a/thermal_parser/src/parser.rs b/thermal_parser/src/parser.rs
index 0e461f8..615fc56 100644
--- a/thermal_parser/src/parser.rs
+++ b/thermal_parser/src/parser.rs
@@ -145,7 +145,7 @@ impl Parser {
             self.current_command_is_default = true;
             self.match_depth = 0;

-            if new_cmd.is_some() {
+            if new_cmd.is_some() && self.current_command.is_some() {
                 mem::swap(&mut self.current_command, &mut new_cmd);
                 self.emit_command(new_cmd.unwrap()); //new_command has become the previous command after the swap
                 return;

I'm not familiar enough with your library to decide if this is a valid fix or if something else is wrong.

zachzurn commented 3 weeks ago

Do you have an image of how this receipt should look?

zachzurn commented 3 weeks ago

This is definitely a bug. I'll take a look at it. The library should never panic.

zachzurn commented 3 weeks ago

Bug has been fixed.

Some additional information to think about regarding the binary file.

  1. It seems to have some starting bytes that do not begin with a known command byte (Like ESC).
  2. There is an unknown GS command in the file (We should possibly add support for it, see below)
  3. The file has some text that we cannot parse with unicode (This library only supports unicode at the moment, but happy to accept a code page to unicode pull request)

Test Output

Begin Print Unknown Command ;0;1 Initialize Set Code Table [13] Set International Character Set [00] Line Feed Line Feed Set Character Size [00]

Line Feed Line Feed Set Character Size [00] UTF8 TEXT ERROR invalid utf-8 sequence of 1 bytes from index 15 [20, 20, 20, 20, 20, 20, 20, 20, 44, 61, 6E, 6B, 65, 20, 66, 81, 72, 20, 49, 68, 72, 65, 20, 42, 65, 73, 74, 65, 6C, 6C, 75, 6E, 67, 20, 20, 20, 20, 20, 20, 20, 20, 20] Line Feed Line Feed Set Character Size [00]

Line Feed Line Feed Line Feed Line Feed Set Character Size [00] 15:23:00
Set Character Size [10] BON NR# Set Character Size [00] 12/01/20 Line Feed Line Feed Set Character Size [10]

Unknown Command [1D, 11, 11, 20, 31, 31, 30, 35] Line Feed Line Feed Line Feed Line Feed Line Feed Line Feed Line Feed Line Feed Set Character Size [00] 3x Supp + Speck Set Hri Print POS [03] Print and Feed Lines [04] Set Text Justification [01] CODE 39 Barcode with 4 bytes: 1105 Print and Feed Lines [04] Line Feed Line Feed Feed and Cut [00] Line Feed Line Feed  Initialize End Print


Binary File Details

The provided binary file is pasted here as hex. You can see that the file starts with 3B (Which is semicolon is not a known command byte).

3B 30 00 3B 31 00 00 00 00 00 00 18 1B 3D 01 1B 40 1B 74 13 1B 52 00 0D 0A 1D 21 00 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 0D 0A 1D 21 00 20 20 20 20 20 20 20 20 44 61 6E 6B 65 20 66 81 72 20 49 68 72 65 20 42 65 73 74 65 6C 6C 75 6E 67 20 20 20 20 20 20 20 20 20 0D 0A 1D 21 00 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 0D 0A 0D 0A 1D 21 00 31 35 3A 32 33 3A 30 30 20 20 20 20 20 1D 21 10 42 4F 4E 20 4E 52 23 1D 21 00 20 20 20 20 20 20 20 31 32 2F 30 31 2F 32 30 0D 0A 1D 21 10 20 20 20 20 1D 11 20 31 31 30 35 0D 0A 0D 0A 0D 0A 0D 0A 1D 21 00 33 78 20 53 75 70 70 20 2B 20 53 70 65 63 6B 1D 48 03 1B 64 04 1B 61 01 1D 6B 04 31 31 30 35 00 1B 64 04 0D 0A 1D 56 00 0D 0A 00 00 00 00 00 18 1B 3D 01 1B