@@ -21,8 +21,13 @@ local function crc32_hex(data)
2121 return bit .tohex (bit .bxor (crc , 0xFFFFFFFF ))
2222end
2323
24- -- Strip transport whitespace (space/tab/CR/LF) from an encoded payload.
25- local function canonical_payload (s )
24+ -- Strip transport whitespace from an encoded payload. Normally all of space/tab/
25+ -- CR/LF are transport noise. When keep_spaces is set (container --spaces), literal
26+ -- spaces are DATA, so only tab/CR/LF are stripped as noise.
27+ local function canonical_payload (s , keep_spaces )
28+ if keep_spaces then
29+ return (s :gsub (" [\t\r\n ]" , " " ))
30+ end
2631 return (s :gsub (" [ \t\r\n ]" , " " ))
2732end
2833
3237local function json_get_string (json , key )
3338 return json :match (' "' .. key .. ' "%s*:%s*"(.-)"' )
3439end
35-
36-
3740-- PrintableBinary: A utility to encode/decode binary data into human-readable UTF-8
3841-- Module definition
3942local PrintableBinary = {}
@@ -1028,19 +1031,45 @@ if arg then
10281031 -- Container (.pbf.json) mode (issue #1): assemble/parse the flat-JSON envelope
10291032 -- over the shared encode/decode + crc32 (A2). Transport-resistant.
10301033 if container_mode then
1034+ -- Only --spaces is honored in container mode. --tabs/--crlf/-w/--preserve would
1035+ -- put raw tab/CR/LF (or arbitrary chars) into the JSON value, breaking both
1036+ -- single-line-JSON validity and the tab/CR/LF-stripping transport-resistance.
1037+ if tabs_mode or crlf_mode or preserve_chars ~= " " then
1038+ io.stderr :write (" Error: --tabs/--crlf/-w/--preserve are not supported with "
1039+ .. " --container (only --spaces is honored; other whitespace stays encoded)\n " )
1040+ os.exit (1 )
1041+ end
10311042 if decode_mode then
10321043 local data_raw = json_get_string (input_data , " data" )
10331044 if not data_raw then
10341045 io.stderr :write (" Error: not a printable-binary-file container (missing 'data')\n " )
10351046 os.exit (1 )
10361047 end
1037- local clean = canonical_payload (data_raw )
1048+ -- Flagless crc-probe: no schema flag records whether --spaces was used; the
1049+ -- crc32_encoded oracle disambiguates. Try keeping literal spaces (they're DATA
1050+ -- in a --spaces container); if the crc mismatches, strip them as transport noise.
1051+ local clean = canonical_payload (data_raw , true )
1052+ local spaces = true
10381053 local ce = json_get_string (input_data , " crc32_encoded" )
10391054 if ce and crc32_hex (clean ) ~= ce then
1040- io.stderr :write (" Error: container crc32_encoded mismatch (data corrupted)\n " )
1041- os.exit (1 )
1055+ local stripped = canonical_payload (data_raw , false )
1056+ if crc32_hex (stripped ) == ce then
1057+ -- Literal spaces were noise. If the space glyph is ALSO present, the payload
1058+ -- mixed real (glyph) spaces with formatting spaces -> warn we dropped them.
1059+ local space_glyph = encode_map [32 ]
1060+ if space_glyph and clean :find (space_glyph , 1 , true ) then
1061+ io.stderr :write (" Warning: literal spaces in container data were assumed to be "
1062+ .. " ignorable formatting because the space glyph " .. space_glyph
1063+ .. " was also present; stripping them\n " )
1064+ end
1065+ clean = stripped
1066+ spaces = false
1067+ else
1068+ io.stderr :write (" Error: container crc32_encoded mismatch (data corrupted)\n " )
1069+ os.exit (1 )
1070+ end
10421071 end
1043- local decoded = PrintableBinary .decode (clean , {})
1072+ local decoded = PrintableBinary .decode (clean , { spaces = spaces })
10441073 local co = json_get_string (input_data , " crc32" )
10451074 if co and crc32_hex (decoded ) ~= co then
10461075 io.stderr :write (" Error: container crc32 mismatch (decoded data corrupted)\n " )
@@ -1049,8 +1078,8 @@ if arg then
10491078 io.write (decoded )
10501079 os.exit (0 )
10511080 else
1052- local data = PrintableBinary .encode (input_data , {})
1053- local clean = canonical_payload (data )
1081+ local data = PrintableBinary .encode (input_data , { spaces = spaces_mode })
1082+ local clean = canonical_payload (data , spaces_mode )
10541083 local crc_orig = crc32_hex (input_data )
10551084 local crc_enc = crc32_hex (clean )
10561085 local fname = " "
0 commit comments