1 // This file is part of Deark.
2 // Copyright (C) 2016-2021 Jason Summers
3 // See the file COPYING for terms of use.
5 // This file is for miscellaneous formats that are easy to support.
7 #include <deark-private.h>
8 #include <deark-fmtutil.h>
9 DE_DECLARE_MODULE(de_module_copy
);
10 DE_DECLARE_MODULE(de_module_null
);
11 DE_DECLARE_MODULE(de_module_split
);
12 DE_DECLARE_MODULE(de_module_xor
);
13 DE_DECLARE_MODULE(de_module_plaintext
);
14 DE_DECLARE_MODULE(de_module_cp437
);
15 DE_DECLARE_MODULE(de_module_crc
);
16 DE_DECLARE_MODULE(de_module_datetime
);
17 DE_DECLARE_MODULE(de_module_hexdump
);
18 DE_DECLARE_MODULE(de_module_bytefreq
);
19 DE_DECLARE_MODULE(de_module_deflate
);
20 DE_DECLARE_MODULE(de_module_zlib
);
21 DE_DECLARE_MODULE(de_module_winzle
);
22 DE_DECLARE_MODULE(de_module_mrw
);
23 DE_DECLARE_MODULE(de_module_vgafont
);
24 DE_DECLARE_MODULE(de_module_pcrfont
);
25 DE_DECLARE_MODULE(de_module_zbr
);
26 DE_DECLARE_MODULE(de_module_compress
);
27 DE_DECLARE_MODULE(de_module_hpi
);
28 DE_DECLARE_MODULE(de_module_dclimplode
);
29 DE_DECLARE_MODULE(de_module_lzss_oku
);
30 DE_DECLARE_MODULE(de_module_lzhuf
);
31 DE_DECLARE_MODULE(de_module_compress_lzh
);
32 DE_DECLARE_MODULE(de_module_lzstac
);
33 DE_DECLARE_MODULE(de_module_npack
);
34 DE_DECLARE_MODULE(de_module_lzs221
);
35 DE_DECLARE_MODULE(de_module_xpk
);
37 // **************************************************************************
40 // This is a trivial module that makes a copy of the input file.
41 // **************************************************************************
43 static void de_run_copy(deark
*c
, de_module_params
*mparams
)
45 dbuf_create_file_from_slice(c
->infile
, 0, c
->infile
->len
, "bin", NULL
, 0);
48 void de_module_copy(deark
*c
, struct deark_module_info
*mi
)
51 mi
->desc
= "Copy the file unchanged";
52 mi
->run_fn
= de_run_copy
;
55 // **************************************************************************
58 // This is a trivial module that does nothing.
59 // **************************************************************************
61 static void de_run_null(deark
*c
, de_module_params
*mparams
)
66 void de_module_null(deark
*c
, struct deark_module_info
*mi
)
69 mi
->desc
= "Do nothing";
70 mi
->run_fn
= de_run_null
;
71 mi
->flags
|= DE_MODFLAG_NOEXTRACT
;
74 // **************************************************************************
76 // Split the input file into equal-sized chunks.
77 // **************************************************************************
79 static void do_split_onechunk(deark
*c
, i64 chunknum
, i64 offset
, i64 size
)
84 de_snprintf(ext
, sizeof(ext
), "part%"I64_FMT
, chunknum
);
85 outf
= dbuf_create_output_file(c
, ext
, NULL
, 0);
86 dbuf_copy(c
->infile
, offset
, size
, outf
);
90 static void de_run_split(deark
*c
, de_module_params
*mparams
)
95 i64 chunksize
, chunkstride
;
98 s
= de_get_ext_option(c
, "split:size");
100 de_err(c
, "\"-opt split:size=<n>\" is required.");
103 chunksize
= de_atoi64(s
);
105 de_err(c
, "Invalid chunk size");
109 s
= de_get_ext_option(c
, "split:stride");
111 chunkstride
= de_atoi64(s
);
112 if(chunkstride
<chunksize
) {
113 de_err(c
, "Stride must be "DE_CHAR_GEQ
" size");
118 chunkstride
= chunksize
;
121 chunkcount
= (c
->infile
->len
+ (chunkstride
-1)) / chunkstride
;
123 if((chunkcount
>256) && (!c
->user_set_max_output_files
)) {
124 de_err(c
, "Large number of chunks; use \"-maxfiles %"I64_FMT
"\" if you "
125 "really want to do this.", chunkcount
);
130 for(chunknum
= 0; chunknum
<chunkcount
; chunknum
++) {
133 this_chunk_size
= de_min_int(chunksize
, c
->infile
->len
-pos
);
134 do_split_onechunk(c
, chunknum
, pos
, this_chunk_size
);
143 static void de_help_split(deark
*c
)
145 de_msg(c
, "-opt split:size=<n> : The size of each chunk, in bytes");
146 de_msg(c
, "-opt split:stride=<n> : Source distance between chunks");
149 void de_module_split(deark
*c
, struct deark_module_info
*mi
)
152 mi
->desc
= "Split the file into equal-sized chunks";
153 mi
->run_fn
= de_run_split
;
154 mi
->help_fn
= de_help_split
;
157 // **************************************************************************
159 // Apply an XOR key to the file. Can be used to de-obfuscate some files.
160 // **************************************************************************
162 struct xorctx_struct
{
169 static int xor_cbfn(struct de_bufferedreadctx
*brctx
, const u8
*buf
,
173 struct xorctx_struct
*xorctx
= (struct xorctx_struct
*)brctx
->userdata
;
175 for(i
=0; i
<buf_len
; i
++) {
176 dbuf_writebyte(xorctx
->outf
, buf
[i
] ^ xorctx
->key
[xorctx
->key_pos
]);
177 if(xorctx
->key_len
>1) {
178 xorctx
->key_pos
= (xorctx
->key_pos
+1) % xorctx
->key_len
;
184 static void de_run_xor(deark
*c
, de_module_params
*mparams
)
186 struct xorctx_struct
*xorctx
= NULL
;
190 xorctx
= de_malloc(c
, sizeof(struct xorctx_struct
));
191 xorctx
->key
[0] = 0xff;
194 opt_key
= de_get_ext_option(c
, "xor:key");
199 key_strlen
= (UI
)de_strlen(opt_key
);
200 if(key_strlen
%2) { badkey_flag
= 1; goto done
; }
201 xorctx
->key_len
= key_strlen
/2;
202 if(xorctx
->key_len
<1 || (size_t)xorctx
->key_len
>sizeof(xorctx
->key
)) {
206 for(k
=0; k
<xorctx
->key_len
; k
++) {
211 d1
= de_decode_hex_digit(opt_key
[k
*2], &errflag1
);
212 d2
= de_decode_hex_digit(opt_key
[k
*2+1], &errflag2
);
213 if(errflag1
|| errflag2
) { badkey_flag
= 1; goto done
; }
214 xorctx
->key
[k
] = (d1
<<4) | d2
;
218 xorctx
->outf
= dbuf_create_output_file(c
, "bin", NULL
, 0);
219 dbuf_enable_wbuffer(xorctx
->outf
);
220 dbuf_buffered_read(c
->infile
, 0, c
->infile
->len
, xor_cbfn
, (void*)xorctx
);
224 de_err(c
, "Bad XOR key");
227 dbuf_close(xorctx
->outf
);
232 static void de_help_xor(deark
*c
)
234 de_msg(c
, "-opt xor:key=<aabbcc...> : Hex bytes to use as XOR key");
237 void de_module_xor(deark
*c
, struct deark_module_info
*mi
)
240 mi
->desc
= "Invert bits, or XOR with a key";
241 mi
->run_fn
= de_run_xor
;
242 mi
->help_fn
= de_help_xor
;
245 // **************************************************************************
247 // Convert text files to UTF-8.
248 // **************************************************************************
250 static de_encoding
get_bom_enc(deark
*c
, UI
*blen
)
255 if(buf
[0]==0xef && buf
[1]==0xbb && buf
[2]==0xbf) {
257 return DE_ENCODING_UTF8
;
259 else if(buf
[0]==0xfe && buf
[1]==0xff) {
261 return DE_ENCODING_UTF16BE
;
263 else if(buf
[0]==0xff && buf
[1]==0xfe) {
265 return DE_ENCODING_UTF16LE
;
268 return DE_ENCODING_UNKNOWN
;
271 static void de_run_plaintext(deark
*c
, de_module_params
*mparams
)
273 de_encoding input_encoding
;
274 de_encoding enc_from_bom
;
275 UI existing_bom_len
= 0;
279 enc_from_bom
= get_bom_enc(c
, &existing_bom_len
);
280 input_encoding
= de_get_input_encoding(c
, NULL
, DE_ENCODING_UNKNOWN
);
281 if(input_encoding
==DE_ENCODING_UNKNOWN
) {
282 if(enc_from_bom
!=DE_ENCODING_UNKNOWN
) {
283 input_encoding
= enc_from_bom
;
286 input_encoding
= DE_ENCODING_UTF8
;
289 if(input_encoding
!=enc_from_bom
) {
290 // Even if there was something that looked like a BOM, ignore it.
291 existing_bom_len
= 0;
294 dpos
= (i64
)existing_bom_len
;
295 dlen
= c
->infile
->len
- dpos
;
297 outf
= dbuf_create_output_file(c
, "txt", NULL
, 0);
298 dbuf_enable_wbuffer(outf
);
301 dbuf_write_uchar_as_utf8(outf
, 0xfeff);
304 dbuf_copy_slice_convert_to_utf8(c
->infile
, dpos
, dlen
,
305 DE_EXTENC_MAKE(input_encoding
, DE_ENCSUBTYPE_HYBRID
),
311 void de_module_plaintext(deark
*c
, struct deark_module_info
*mi
)
313 mi
->id
= "plaintext";
314 mi
->desc
= "Plain text";
315 mi
->desc2
= "Convert to UTF-8";
316 mi
->run_fn
= de_run_plaintext
;
319 // **************************************************************************
321 // Convert CP437 text files to UTF-8.
322 // **************************************************************************
324 struct cp437ctx_struct
{
326 struct de_encconv_state es
;
329 static int cp437_cbfn(struct de_bufferedreadctx
*brctx
, const u8
*buf
,
335 struct cp437ctx_struct
*cp437ctx
= (struct cp437ctx_struct
*)brctx
->userdata
;
337 for(i
=0; i
<buf_len
; i
++) {
339 if(ch
==0x09 || ch
==0x0a || ch
==0x0c || ch
==0x0d) {
340 // Leave HT, NL, FF, CR as-is.
344 // Lots of CP437 files end with a Ctrl+Z character, but modern files
345 // don't use any in-band character to signify end-of-file.
346 // I don't just want to delete the character, though, so I guess I'll
347 // change it to U+2404 SYMBOL FOR END OF TRANSMISSION.
351 u
= de_char_to_unicode_ex((i32
)ch
, &cp437ctx
->es
);
353 dbuf_write_uchar_as_utf8(cp437ctx
->outf
, u
);
359 static void de_run_cp437(deark
*c
, de_module_params
*mparams
)
361 struct cp437ctx_struct cp437ctx
;
363 cp437ctx
.outf
= dbuf_create_output_file(c
, "txt", NULL
, 0);
364 dbuf_enable_wbuffer(cp437ctx
.outf
);
365 de_encconv_init(&cp437ctx
.es
, DE_ENCODING_CP437_G
);
367 dbuf_write_uchar_as_utf8(cp437ctx
.outf
, 0xfeff);
369 dbuf_buffered_read(c
->infile
, 0, c
->infile
->len
, cp437_cbfn
, (void*)&cp437ctx
);
370 dbuf_close(cp437ctx
.outf
);
373 void de_module_cp437(deark
*c
, struct deark_module_info
*mi
)
376 mi
->desc
= "Code Page 437 text";
377 mi
->run_fn
= de_run_cp437
;
380 // **************************************************************************
382 // Prints various CRCs and checksums. Does not create any files.
383 // **************************************************************************
385 struct crcm_alg_info
{
387 u8 flags
; // 1 = computed by default
388 u8 nbits
; // 0 = special
392 #define CRCM_NUMCRCS 11
393 static const struct crcm_alg_info crcm_map
[CRCM_NUMCRCS
] = {
394 { DE_CRCOBJ_CRC32_IEEE
, 1, 32, "CRC-32-IEEE" },
395 { DE_CRCOBJ_CRC16_ARC
, 1, 16, "CRC-16/ARC"},
396 { DE_CRCOBJ_CRC16_XMODEM
, 1, 16, "CRC-16/XMODEM" },
397 { DE_CRCOBJ_CRC32_JAMCRC
, 0, 32, "CRC-32/JAMCRC" },
398 { DE_CRCOBJ_CRC32_PL
, 0, 32, "CRC-32/PL" },
399 { DE_CRCOBJ_ADLER32
, 0, 32, "Adler-32" },
400 { DE_CRCOBJ_CRC16_IBMSDLC
, 0, 16, "CRC-16/IBM-SDLC" },
401 { DE_CRCOBJ_CRC16_IBM3740
, 0, 16, "CRC-16/IBM-3740" },
402 { DE_CRCOBJ_SUM_BYTES
, 1, 0, "Sum of bytes" },
403 { DE_CRCOBJ_SUM_U16LE
, 0, 0, "Sum of uint16-LE" },
404 { DE_CRCOBJ_SUM_U16BE
, 0, 0, "Sum of uint16-BE" }
407 struct crcctx_struct
{
409 struct de_crcobj
*crcos
[CRCM_NUMCRCS
];
412 static int crc_cbfn(struct de_bufferedreadctx
*brctx
, const u8
*buf
,
415 struct crcctx_struct
*crcctx
= (struct crcctx_struct
*)brctx
->userdata
;
418 for(n
=0; n
<CRCM_NUMCRCS
; n
++) {
419 if(!crcctx
->crcos
[n
]) continue;
420 de_crcobj_addbuf(crcctx
->crcos
[n
], buf
, buf_len
);
426 static void de_run_crc(deark
*c
, de_module_params
*mparams
)
428 struct crcctx_struct crcctx
;
431 de_zeromem(&crcctx
, sizeof(struct crcctx_struct
));
432 crcctx
.opt_all
= (u8
)de_get_ext_option_bool(c
, "crc:all", 0xff);
433 if(crcctx
.opt_all
==0xff) {
434 if(c
->extract_level
>=2) {
442 for(n
=0; n
<CRCM_NUMCRCS
; n
++) {
443 if((crcm_map
[n
].flags
& 0x1)==0 && !crcctx
.opt_all
) continue;
444 crcctx
.crcos
[n
] = de_crcobj_create(c
, crcm_map
[n
].crctype
);
447 dbuf_buffered_read(c
->infile
, 0, c
->infile
->len
, crc_cbfn
, (void*)&crcctx
);
449 for(n
=0; n
<CRCM_NUMCRCS
; n
++) {
453 if(!crcctx
.crcos
[n
]) continue;
455 if(crcm_map
[n
].nbits
==0) {
456 val64
= de_crcobj_getval64(crcctx
.crcos
[n
]);
459 val
= de_crcobj_getval(crcctx
.crcos
[n
]);
462 if(crcm_map
[n
].nbits
==0) {
463 de_msg(c
, "%-18s: 0x%"U64_FMTx
, crcm_map
[n
].name
, val64
);
465 else if(crcm_map
[n
].nbits
==16) {
466 de_msg(c
, "%-18s: 0x%04x", crcm_map
[n
].name
, (UI
)val
);
469 de_msg(c
, "%-18s: 0x%08x", crcm_map
[n
].name
, (UI
)val
);
473 for(n
=0; n
<CRCM_NUMCRCS
; n
++) {
474 de_crcobj_destroy(crcctx
.crcos
[n
]);
478 static void de_help_crc(deark
*c
)
480 de_msg(c
, "-a : Also compute uncommon checksum types");
483 void de_module_crc(deark
*c
, struct deark_module_info
*mi
)
486 mi
->id_alias
[0] = "crc32";
487 mi
->desc
= "Calculate various CRCs";
488 mi
->run_fn
= de_run_crc
;
489 mi
->help_fn
= de_help_crc
;
490 mi
->flags
|= DE_MODFLAG_NOEXTRACT
;
493 // **************************************************************************
495 // Interpret the start of the file as a date/time field, in various formats.
496 // **************************************************************************
498 static void datetime_msg(deark
*c
, struct de_timestamp
*ts
, const char *name
)
500 char timestamp_buf
[64];
502 de_timestamp_to_string(ts
, timestamp_buf
, sizeof(timestamp_buf
), 0);
503 de_msg(c
, "%s: %s", name
, timestamp_buf
);
506 static void de_run_datetime(deark
*c
, de_module_params
*mparams
)
508 struct de_timestamp timestamp
;
512 dtime
= de_getu16le(0);
513 ddate
= de_getu16le(2);
514 de_dos_datetime_to_timestamp(×tamp
, ddate
, dtime
);
515 datetime_msg(c
, ×tamp
, "DOS time,date");
517 ddate
= de_getu16le(0);
518 dtime
= de_getu16le(2);
519 de_dos_datetime_to_timestamp(×tamp
, ddate
, dtime
);
520 datetime_msg(c
, ×tamp
, "DOS date,time");
523 de_unix_time_to_timestamp(t
, ×tamp
, 0x1);
524 datetime_msg(c
, ×tamp
, "Unix-LE");
527 de_unix_time_to_timestamp(t
, ×tamp
, 0x1);
528 datetime_msg(c
, ×tamp
, "Unix-BE");
531 de_mac_time_to_timestamp(t
, ×tamp
);
532 datetime_msg(c
, ×tamp
, "Mac/HFS-BE");
535 de_FILETIME_to_timestamp(t
, ×tamp
, 0x1);
536 datetime_msg(c
, ×tamp
, "Windows FILETIME");
539 void de_module_datetime(deark
*c
, struct deark_module_info
*mi
)
542 mi
->desc
= "Interpret a date/time field";
543 mi
->run_fn
= de_run_datetime
;
544 mi
->flags
|= DE_MODFLAG_HIDDEN
| DE_MODFLAG_NOEXTRACT
;
547 // **************************************************************************
549 // Prints a hex dump. Does not create any files.
550 // **************************************************************************
552 static void de_run_hexdump(deark
*c
, de_module_params
*mparams
)
554 de_hexdump2(c
, c
->infile
, 0, c
->infile
->len
,
555 c
->infile
->len
, 0x3);
558 void de_module_hexdump(deark
*c
, struct deark_module_info
*mi
)
561 mi
->desc
= "Print a hex dump";
562 mi
->run_fn
= de_run_hexdump
;
563 mi
->flags
|= DE_MODFLAG_NOEXTRACT
;
566 // **************************************************************************
568 // Prints a summary of how many times each byte value occurs.
569 // **************************************************************************
571 struct bytefreqentry
{
573 #define DE_BYTEFREQ_NUMLOC 3
574 i64 locations
[DE_BYTEFREQ_NUMLOC
];
577 struct bytefreqctx_struct
{
578 struct bytefreqentry e
[256];
581 static int bytefreq_cbfn(struct de_bufferedreadctx
*brctx
, const u8
*buf
,
585 struct bytefreqctx_struct
*bfctx
= (struct bytefreqctx_struct
*)brctx
->userdata
;
587 for(k
=0; k
<buf_len
; k
++) {
588 struct bytefreqentry
*bf
= &bfctx
->e
[(unsigned int)buf
[k
]];
590 // Save the location of the first few occurrences of this byte value.
591 if(bf
->count
<DE_BYTEFREQ_NUMLOC
) {
592 bf
->locations
[bf
->count
] = brctx
->offset
+ k
;
599 static void de_run_bytefreq(deark
*c
, de_module_params
*mparams
)
601 struct bytefreqctx_struct
*bfctx
= NULL
;
602 de_ucstring
*s
= NULL
;
604 de_encoding input_encoding
;
605 struct de_encconv_state es
;
607 bfctx
= de_malloc(c
, sizeof(struct bytefreqctx_struct
));
608 input_encoding
= de_get_input_encoding(c
, NULL
, DE_ENCODING_WINDOWS1252
);
609 if(input_encoding
==DE_ENCODING_UTF8
) {
610 input_encoding
=DE_ENCODING_ASCII
;
612 de_encconv_init(&es
, input_encoding
);
614 dbuf_buffered_read(c
->infile
, 0, c
->infile
->len
, bytefreq_cbfn
, (void*)bfctx
);
616 de_msg(c
, "====Byte==== ===Count=== ==Locations==");
617 s
= ucstring_create(c
);
618 for(k
=0; k
<256; k
++) {
622 struct bytefreqentry
*bf
= &bfctx
->e
[k
];
624 if(bf
->count
==0) continue;
627 ucstring_printf(s
, DE_ENCODING_LATIN1
, "%3u 0x%02x ", k
, k
);
629 ch
= de_char_to_unicode_ex((i32
)k
, &es
);
630 if(ch
==DE_CODEPOINT_INVALID
) {
634 cflag
= de_is_printable_uchar(ch
);
638 ucstring_append_sz(s
, "'", DE_ENCODING_LATIN1
);
639 ucstring_append_char(s
, ch
);
640 ucstring_append_sz(s
, "'", DE_ENCODING_LATIN1
);
643 ucstring_append_sz(s
, " ", DE_ENCODING_LATIN1
);
646 ucstring_printf(s
, DE_ENCODING_LATIN1
, " %11"I64_FMT
" ", bf
->count
);
648 for(z
=0; z
<DE_BYTEFREQ_NUMLOC
&& z
<bf
->count
; z
++) {
649 ucstring_printf(s
, DE_ENCODING_LATIN1
, "%"I64_FMT
, bf
->locations
[z
]);
651 ucstring_append_sz(s
, ",", DE_ENCODING_LATIN1
);
654 if(bf
->count
>DE_BYTEFREQ_NUMLOC
) {
655 ucstring_append_sz(s
, "...", DE_ENCODING_LATIN1
);
658 de_msg(c
, "%s", ucstring_getpsz(s
));
660 de_msg(c
, " Total: %11"I64_FMT
, c
->infile
->len
);
665 void de_module_bytefreq(deark
*c
, struct deark_module_info
*mi
)
668 mi
->desc
= "Print a byte frequence analysis";
669 mi
->run_fn
= de_run_bytefreq
;
670 mi
->flags
|= DE_MODFLAG_NOEXTRACT
;
673 // **************************************************************************
674 // Raw "Deflate"-compressed data
675 // **************************************************************************
677 static void run_deflate_internal(deark
*c
, UI flags
)
680 struct de_dfilter_in_params dcmpri
;
681 struct de_dfilter_out_params dcmpro
;
682 struct de_dfilter_results dres
;
683 struct de_deflate_params deflparams
;
685 de_dfilter_init_objects(c
, &dcmpri
, &dcmpro
, &dres
);
686 de_zeromem(&deflparams
, sizeof(struct de_deflate_params
));
687 deflparams
.flags
= flags
;
689 outf
= dbuf_create_output_file(c
, "unc", NULL
, 0);
690 dbuf_enable_wbuffer(outf
);
691 dcmpri
.f
= c
->infile
;
693 dcmpri
.len
= c
->infile
->len
;
695 fmtutil_decompress_deflate_ex(c
, &dcmpri
, &dcmpro
, &dres
, &deflparams
);
698 de_err(c
, "Decompression failed: %s", de_dfilter_get_errmsg(c
, &dres
));
701 if(dres
.bytes_consumed_valid
) {
702 de_dbg(c
, "decompressed %"I64_FMT
" bytes to %"I64_FMT
, dres
.bytes_consumed
,
710 static void de_run_deflate(deark
*c
, de_module_params
*mparams
)
714 if(de_get_ext_option_bool(c
, "deflate:deflate64", 0)) {
715 flags
|= DE_DEFLATEFLAG_DEFLATE64
;
718 run_deflate_internal(c
, flags
);
721 void de_module_deflate(deark
*c
, struct deark_module_info
*mi
)
724 mi
->desc
= "Raw Deflate compressed data";
725 mi
->run_fn
= de_run_deflate
;
728 // **************************************************************************
731 // This module is for decompressing zlib-compressed files.
732 // **************************************************************************
734 static void de_run_zlib(deark
*c
, de_module_params
*mparams
)
736 run_deflate_internal(c
, DE_DEFLATEFLAG_ISZLIB
);
739 static int de_identify_zlib(deark
*c
)
747 if(b
[0]<0x08 || b
[0]>0x78)
750 if(((((unsigned int)b
[0])<<8)|b
[1])%31 != 0)
756 void de_module_zlib(deark
*c
, struct deark_module_info
*mi
)
759 mi
->desc
= "Raw zlib compressed data";
760 mi
->run_fn
= de_run_zlib
;
761 mi
->identify_fn
= de_identify_zlib
;
764 // **************************************************************************
765 // Winzle! puzzle image
766 // **************************************************************************
768 static void de_run_winzle(deark
*c
, de_module_params
*mparams
)
775 xorsize
= c
->infile
->len
>= 256 ? 256 : c
->infile
->len
;
776 de_read(buf
, 0, xorsize
);
777 for(i
=0; i
<xorsize
; i
++) {
781 f
= dbuf_create_output_file(c
, "bmp", NULL
, 0);
782 dbuf_write(f
, buf
, xorsize
);
783 if(c
->infile
->len
> 256) {
784 dbuf_copy(c
->infile
, 256, c
->infile
->len
- 256, f
);
789 static int de_identify_winzle(deark
*c
)
792 de_read(b
, 0, sizeof(b
));
794 if(b
[0]==0x4f && b
[1]==0x40) {
795 if(b
[14]==0x25 && b
[15]==0x0d && b
[16]==0x0d && b
[17]==0x0d) {
803 void de_module_winzle(deark
*c
, struct deark_module_info
*mi
)
806 mi
->desc
= "Winzle! puzzle image";
807 mi
->run_fn
= de_run_winzle
;
808 mi
->identify_fn
= de_identify_winzle
;
811 // **************************************************************************
813 // **************************************************************************
815 static void do_mrw_seg_list(deark
*c
, i64 pos1
, i64 len
)
822 while(pos
< pos1
+len
) {
823 de_read(seg_id
, pos
, 4);
824 data_len
= de_getu32be(pos
+4);
826 if(pos
+data_len
> pos1
+len
) break;
827 if(!de_memcmp(seg_id
, "\0TTW", 4)) { // Exif
828 fmtutil_handle_exif(c
, pos
, data_len
);
834 static void de_run_mrw(deark
*c
, de_module_params
*mparams
)
838 mrw_seg_size
= de_getu32be(4);
839 do_mrw_seg_list(c
, 8, mrw_seg_size
);
842 static int de_identify_mrw(deark
*c
)
844 if(!dbuf_memcmp(c
->infile
, 0, "\x00\x4d\x52\x4d", 4))
849 void de_module_mrw(deark
*c
, struct deark_module_info
*mi
)
852 mi
->desc
= "Minolta RAW";
853 mi
->desc2
= "resources only";
854 mi
->run_fn
= de_run_mrw
;
855 mi
->identify_fn
= de_identify_mrw
;
858 // **************************************************************************
859 // 8xN "VGA" font (intended for development/debugging use)
860 // **************************************************************************
862 static void do_vgafont_internal(deark
*c
, dbuf
*inf
)
865 struct de_bitmap_font
*font
= NULL
;
868 de_encoding encoding_req
;
869 de_encoding encoding_to_use
;
870 struct de_encconv_state es
;
872 #define VGAFONT_MINH 3
873 #define VGAFONT_MAXH 20
874 height
= inf
->len
/ 256;
875 if((inf
->len
% 256) || height
<VGAFONT_MINH
|| height
>VGAFONT_MAXH
) {
876 de_err(c
, "Bad file size");
880 fontdata
= de_malloc(c
, height
*256);
881 dbuf_read(inf
, fontdata
, 0, height
*256);
883 if(de_get_ext_option(c
, "vgafont:c")) {
885 ff
= dbuf_create_output_file(c
, "h", NULL
, 0);
886 for(i
=0; i
<(height
*256); i
++) {
887 if(i
%height
==0) dbuf_puts(ff
, "\t");
888 dbuf_printf(ff
, "%d", (int)fontdata
[i
]);
889 if(i
!=(height
*256-1)) dbuf_puts(ff
, ",");
890 if(i
%height
==(height
-1)) dbuf_puts(ff
, "\n");
896 encoding_req
= de_get_input_encoding(c
, NULL
, DE_ENCODING_UNKNOWN
);
897 if(encoding_req
!=DE_ENCODING_UNKNOWN
)
898 encoding_to_use
= encoding_req
;
900 encoding_to_use
= DE_ENCODING_CP437
;
902 font
= de_create_bitmap_font(c
);
903 font
->num_chars
= 256;
904 font
->has_nonunicode_codepoints
= 1;
905 font
->has_unicode_codepoints
= 1;
906 font
->prefer_unicode
= (encoding_req
!=DE_ENCODING_UNKNOWN
);
907 font
->nominal_width
= 8;
908 font
->nominal_height
= (int)height
;
909 font
->char_array
= de_mallocarray(c
, font
->num_chars
, sizeof(struct de_bitmap_font_char
));
911 de_encconv_init(&es
, encoding_to_use
);
913 for(i
=0; i
<font
->num_chars
; i
++) {
914 font
->char_array
[i
].codepoint_nonunicode
= (i32
)i
;
915 if(font
->has_unicode_codepoints
) {
916 font
->char_array
[i
].codepoint_unicode
= de_char_to_unicode_ex((i32
)i
, &es
);
918 font
->char_array
[i
].width
= font
->nominal_width
;
919 font
->char_array
[i
].height
= font
->nominal_height
;
920 font
->char_array
[i
].rowspan
= 1;
921 font
->char_array
[i
].bitmap
= &fontdata
[i
*font
->nominal_height
];
924 de_font_bitmap_font_to_image(c
, font
, NULL
, 0);
928 de_free(c
, font
->char_array
);
929 de_destroy_bitmap_font(c
, font
);
931 de_free(c
, fontdata
);
934 static void de_run_vgafont(deark
*c
, de_module_params
*mparams
)
936 do_vgafont_internal(c
, c
->infile
);
939 static void de_help_vgafont(deark
*c
)
941 de_msg(c
, "-opt vgafont:c : Emit C code");
944 void de_module_vgafont(deark
*c
, struct deark_module_info
*mi
)
947 mi
->desc
= "Raw 8xN bitmap font";
948 mi
->run_fn
= de_run_vgafont
;
949 mi
->help_fn
= de_help_vgafont
;
952 // **************************************************************************
953 // PCR font (OPTICKS)
954 // **************************************************************************
956 static void de_run_pcrfont(deark
*c
, de_module_params
*mparams
)
964 // I assume either hdr[7] or hdr[10] is the high byte of the font data size,
965 // but I don't know which.
966 if(hdr
[6]!=0x1 || hdr
[7]!=hdr
[10] || hdr
[8]!=0 || hdr
[9]!=0) {
971 de_dbg(c
, "height: %d", (int)h
);
972 if(h
<VGAFONT_MINH
|| h
>VGAFONT_MAXH
|| c
->infile
->len
< 11+h
*256) {
977 inf
= dbuf_open_input_subfile(c
->infile
, 11, h
*256);
978 do_vgafont_internal(c
, inf
);
983 de_err(c
, "Unsupported type of PCR font");
987 static int de_identify_pcrfont(deark
*c
)
991 if(dbuf_memcmp(c
->infile
, 0, "KPG", 3)) return 0;
992 if(de_getbyte(5)!=0x20) return 0;
994 if(h
<6 || h
>16) return 0;
995 if(de_getbyte(10)!=h
) return 0;
999 void de_module_pcrfont(deark
*c
, struct deark_module_info
*mi
)
1002 mi
->desc
= "PCR font";
1003 mi
->run_fn
= de_run_pcrfont
;
1004 mi
->identify_fn
= de_identify_pcrfont
;
1007 // **************************************************************************
1008 // ZBR (Zoner Zebra Metafile)
1009 // **************************************************************************
1011 static void de_run_zbr(deark
*c
, de_module_params
*mparams
)
1015 static const u8 hdrs
[54] = {
1016 0x42,0x4d,0xc6,0x14,0,0,0,0,0,0,0x76,0,0,0, // FILEHEADER
1017 0x28,0,0,0,0x64,0,0,0,0x64,0,0,0,0x01,0,0x04,0, // INFOHEADER...
1018 0,0,0,0,0x50,0x14,0,0,0,0,0,0,0,0,0,0,
1019 0x10,0,0,0,0,0,0,0 };
1021 pos
+= 4; // signature, version
1022 pos
+= 100; // comment
1024 de_dbg(c
, "preview image at %d", (int)pos
);
1025 // By design, this image is formatted as a headerless BMP/DIB. We'll just
1026 // add the 54 bytes of headers needed to make it a BMP, and call it done.
1027 outf
= dbuf_create_output_file(c
, "preview.bmp", NULL
, DE_CREATEFLAG_IS_AUX
);
1028 dbuf_write(outf
, hdrs
, 54);
1029 dbuf_copy(c
->infile
, pos
, 16*4 + 100*52, outf
);
1033 static int de_identify_zbr(deark
*c
)
1035 if(!dbuf_memcmp(c
->infile
, 0, "\x9a\x02", 2)) {
1036 if(de_input_file_has_ext(c
, "zbr")) return 100;
1042 void de_module_zbr(deark
*c
, struct deark_module_info
*mi
)
1045 mi
->desc
= "ZBR (Zebra Metafile)";
1046 mi
->desc2
= "extract preview image";
1047 mi
->run_fn
= de_run_zbr
;
1048 mi
->identify_fn
= de_identify_zbr
;
1051 // **************************************************************************
1053 // **************************************************************************
1055 static void de_run_compress(deark
*c
, de_module_params
*mparams
)
1057 struct de_dfilter_results dres
;
1058 struct de_dfilter_in_params dcmpri
;
1059 struct de_dfilter_out_params dcmpro
;
1060 struct de_lzw_params delzwp
;
1063 f
= dbuf_create_output_file(c
, "bin", NULL
, 0);
1064 dbuf_enable_wbuffer(f
);
1066 de_dfilter_init_objects(c
, &dcmpri
, &dcmpro
, &dres
);
1067 dcmpri
.f
= c
->infile
;
1069 dcmpri
.len
= c
->infile
->len
;
1071 dcmpro
.len_known
= 0;
1073 de_zeromem(&delzwp
, sizeof(struct de_lzw_params
));
1074 delzwp
.fmt
= DE_LZWFMT_UNIXCOMPRESS
;
1075 delzwp
.flags
|= DE_LZWFLAG_HAS3BYTEHEADER
;
1077 fmtutil_decompress_lzw(c
, &dcmpri
, &dcmpro
, &dres
, &delzwp
);
1079 if(dres
.errcode
!=0) {
1080 de_err(c
, "%s", de_dfilter_get_errmsg(c
, &dres
));
1085 static int de_identify_compress(deark
*c
)
1087 if(!dbuf_memcmp(c
->infile
, 0, "\x1f\x9d", 2))
1092 void de_module_compress(deark
*c
, struct deark_module_info
*mi
)
1094 mi
->id
= "compress";
1095 mi
->desc
= "Compress (.Z)";
1096 mi
->run_fn
= de_run_compress
;
1097 mi
->identify_fn
= de_identify_compress
;
1100 // **************************************************************************
1101 // Hemera Photo-Object image (.hpi)
1102 // **************************************************************************
1104 static void de_run_hpi(deark
*c
, de_module_params
*mparams
)
1111 jpgpos
= de_getu32le_p(&pos
);
1112 jpglen
= de_getu32le_p(&pos
);
1113 de_dbg(c
, "jpeg: pos=%"I64_FMT
", len=%"I64_FMT
, jpgpos
, jpglen
);
1114 pngpos
= de_getu32le_p(&pos
);
1115 pnglen
= de_getu32le_p(&pos
);
1116 de_dbg(c
, "png: pos=%"I64_FMT
", len=%"I64_FMT
, pngpos
, pnglen
);
1118 if(jpglen
>0 && jpgpos
+jpglen
<=c
->infile
->len
&& de_getbyte(jpgpos
)==0xff) {
1121 if(pnglen
==0) ext
="jpg";
1122 else ext
="foreground.jpg";
1123 dbuf_create_file_from_slice(c
->infile
, jpgpos
, jpglen
, ext
, NULL
, 0);
1125 if(pnglen
>0 && pngpos
+pnglen
<=c
->infile
->len
&& de_getbyte(pngpos
)==0x89) {
1126 dbuf_create_file_from_slice(c
->infile
, pngpos
, pnglen
, "mask.png", NULL
, 0);
1130 static int de_identify_hpi(deark
*c
)
1132 if(!dbuf_memcmp(c
->infile
, 0, "\x89\x48\x50\x49\x0d\x0a\x1a\x0a", 8)) return 100;
1136 void de_module_hpi(deark
*c
, struct deark_module_info
*mi
)
1139 mi
->desc
= "Hemera Photo-Object image";
1140 mi
->run_fn
= de_run_hpi
;
1141 mi
->identify_fn
= de_identify_hpi
;
1144 // **************************************************************************
1145 // PKWARE DCL Implode compressed file
1146 // **************************************************************************
1148 static void de_run_dclimplode(deark
*c
, de_module_params
*mparams
)
1151 struct de_dfilter_in_params dcmpri
;
1152 struct de_dfilter_out_params dcmpro
;
1153 struct de_dfilter_results dres
;
1155 outf
= dbuf_create_output_file(c
, "unc", NULL
, 0);
1156 dbuf_enable_wbuffer(outf
);
1157 de_dfilter_init_objects(c
, &dcmpri
, &dcmpro
, &dres
);
1158 dcmpri
.f
= c
->infile
;
1160 dcmpri
.len
= c
->infile
->len
;
1163 fmtutil_dclimplode_codectype1(c
, &dcmpri
, &dcmpro
, &dres
, NULL
);
1166 de_err(c
, "Decompression failed: %s", de_dfilter_get_errmsg(c
, &dres
));
1172 static int de_identify_dclimplode(deark
*c
)
1178 if(c
->infile
->len
<4) return 0;
1182 if(b1
<4 || b1
>6) return 0;
1184 // Look for the end-of-data code in the last 2 or 3 bytes.
1185 // Assumes the last byte is padded with '0' bits, and there are
1186 // no extraneous bytes after that.
1187 x
= (u32
)de_getu32le(c
->infile
->len
-4);
1188 for(i
=0; i
<8; i
++) {
1189 if((x
& 0xfffffe00U
)==0x01fe0200U
) {
1190 if(b0
==0 && b1
==6) return 40;
1198 void de_module_dclimplode(deark
*c
, struct deark_module_info
*mi
)
1200 mi
->id
= "dclimplode";
1201 mi
->id_alias
[0] = "ttcomp";
1202 mi
->desc
= "PKWARE DCL Implode compressed file";
1203 mi
->run_fn
= de_run_dclimplode
;
1204 mi
->identify_fn
= de_identify_dclimplode
;
1207 // **************************************************************************
1208 // LZSS (Haruhiko Okumura) compressed file
1209 // **************************************************************************
1211 static void de_run_lzss_oku(deark
*c
, de_module_params
*mparams
)
1214 struct de_dfilter_in_params dcmpri
;
1215 struct de_dfilter_out_params dcmpro
;
1216 struct de_dfilter_results dres
;
1218 outf
= dbuf_create_output_file(c
, "unc", NULL
, 0);
1219 dbuf_enable_wbuffer(outf
);
1220 de_dfilter_init_objects(c
, &dcmpri
, &dcmpro
, &dres
);
1221 dcmpri
.f
= c
->infile
;
1223 dcmpri
.len
= c
->infile
->len
;
1226 fmtutil_decompress_lzss1(c
, &dcmpri
, &dcmpro
, &dres
, 0x0);
1229 de_err(c
, "Decompression failed: %s", de_dfilter_get_errmsg(c
, &dres
));
1235 void de_module_lzss_oku(deark
*c
, struct deark_module_info
*mi
)
1237 mi
->id
= "lzss_oku";
1238 mi
->desc
= "LZSS.C by Haruhiko Okumura";
1239 mi
->run_fn
= de_run_lzss_oku
;
1242 // **************************************************************************
1243 // LZHUF (Haruyasu Yoshizaki) compressed file
1244 // **************************************************************************
1246 static void de_run_lzhuf(deark
*c
, de_module_params
*mparams
)
1250 struct de_dfilter_in_params dcmpri
;
1251 struct de_dfilter_out_params dcmpro
;
1252 struct de_dfilter_results dres
;
1254 // We're assuming the size field is 4 bytes, little-endian. (But it could
1255 // be platform-specific.)
1256 #define LZHUF_HDRSIZE 4
1257 #define LZHUF_IS_LE 1
1259 if(c
->infile
->len
<LZHUF_HDRSIZE
) goto done
;
1260 unc_filesize
= dbuf_getint_ext(c
->infile
, 0, LZHUF_HDRSIZE
, LZHUF_IS_LE
, 0);
1261 de_dbg(c
, "orig filesize: %"I64_FMT
, unc_filesize
);
1263 outf
= dbuf_create_output_file(c
, "unc", NULL
, 0);
1264 dbuf_enable_wbuffer(outf
);
1265 de_dfilter_init_objects(c
, &dcmpri
, &dcmpro
, &dres
);
1266 dcmpri
.f
= c
->infile
;
1267 dcmpri
.pos
= LZHUF_HDRSIZE
;
1268 dcmpri
.len
= c
->infile
->len
-LZHUF_HDRSIZE
;
1270 dcmpro
.len_known
= 1;
1271 dcmpro
.expected_len
= unc_filesize
;
1273 fmtutil_lh1_codectype1(c
, &dcmpri
, &dcmpro
, &dres
, NULL
);
1276 de_err(c
, "Decompression failed: %s", de_dfilter_get_errmsg(c
, &dres
));
1282 void de_module_lzhuf(deark
*c
, struct deark_module_info
*mi
)
1285 mi
->desc
= "LZHUF compressed file";
1286 mi
->run_fn
= de_run_lzhuf
;
1289 // **************************************************************************
1291 // **************************************************************************
1293 static void de_run_compress_lzh(deark
*c
, de_module_params
*mparams
)
1296 struct de_dfilter_in_params dcmpri
;
1297 struct de_dfilter_out_params dcmpro
;
1298 struct de_dfilter_results dres
;
1299 struct de_lh5x_params lzhparams
;
1301 #define SCOLZH_HDRSIZE 2
1302 if(c
->infile
->len
<SCOLZH_HDRSIZE
) goto done
;
1303 outf
= dbuf_create_output_file(c
, "unc", NULL
, 0);
1304 dbuf_enable_wbuffer(outf
);
1305 de_dfilter_init_objects(c
, &dcmpri
, &dcmpro
, &dres
);
1306 dcmpri
.f
= c
->infile
;
1307 dcmpri
.pos
= SCOLZH_HDRSIZE
;
1308 dcmpri
.len
= c
->infile
->len
-SCOLZH_HDRSIZE
;
1311 de_zeromem(&lzhparams
, sizeof(struct de_lh5x_params
));
1312 lzhparams
.fmt
= DE_LH5X_FMT_LH5
;
1313 lzhparams
.zero_codes_block_behavior
= DE_LH5X_ZCB_STOP
;
1315 fmtutil_decompress_lh5x(c
, &dcmpri
, &dcmpro
, &dres
, &lzhparams
);
1318 de_err(c
, "Decompression failed: %s", de_dfilter_get_errmsg(c
, &dres
));
1324 static int de_identify_compress_lzh(deark
*c
)
1326 if((UI
)de_getu16be(0) != 0x1fa0) return 0;
1327 if(de_input_file_has_ext(c
, "z")) return 90;
1331 void de_module_compress_lzh(deark
*c
, struct deark_module_info
*mi
)
1333 mi
->id
= "compress_lzh";
1334 mi
->desc
= "SCO compress LZH";
1335 mi
->run_fn
= de_run_compress_lzh
;
1336 mi
->identify_fn
= de_identify_compress_lzh
;
1339 // **************************************************************************
1340 // Raw LZS (Stac) compressed data
1341 // **************************************************************************
1343 static void do_lzstac_internal(deark
*c
, i64 cmpr_pos
, i64 cmpr_len
, UI flags
)
1346 struct de_dfilter_in_params dcmpri
;
1347 struct de_dfilter_out_params dcmpro
;
1348 struct de_dfilter_results dres
;
1349 struct de_lzstac_params lzstacparams
;
1351 outf
= dbuf_create_output_file(c
, "unc", NULL
, 0);
1352 dbuf_enable_wbuffer(outf
);
1353 de_dfilter_init_objects(c
, &dcmpri
, &dcmpro
, &dres
);
1354 dcmpri
.f
= c
->infile
;
1355 dcmpri
.pos
= cmpr_pos
;
1356 dcmpri
.len
= cmpr_len
;
1359 de_zeromem(&lzstacparams
, sizeof(struct de_lzstac_params
));
1360 lzstacparams
.flags
= flags
;
1361 fmtutil_lzstac_codectype1(c
, &dcmpri
, &dcmpro
, &dres
, (void*)&lzstacparams
);
1365 de_err(c
, "Decompression failed: %s", de_dfilter_get_errmsg(c
, &dres
));
1368 if(dres
.bytes_consumed_valid
) {
1369 de_dbg(c
, "decompressed %"I64_FMT
" bytes to %"I64_FMT
, dres
.bytes_consumed
,
1371 if(dres
.bytes_consumed
<cmpr_len
) {
1372 de_warn(c
, "%"I64_FMT
" extra bytes at end of file. File might not "
1373 "have decompressed correctly.", cmpr_len
- dres
.bytes_consumed
);
1381 static void de_run_lzstac(deark
*c
, de_module_params
*mparams
)
1383 do_lzstac_internal(c
, 0, c
->infile
->len
, 0);
1386 void de_module_lzstac(deark
*c
, struct deark_module_info
*mi
)
1389 mi
->desc
= "Raw LZS (Stac) compressed data";
1390 mi
->run_fn
= de_run_lzstac
;
1393 // **************************************************************************
1395 // An installer format by Symantec & Stac
1396 // **************************************************************************
1398 static void de_run_npack(deark
*c
, de_module_params
*mparams
)
1400 // NPack decompresses at most 1 LZS block, hence the 0x2 flag.
1401 do_lzstac_internal(c
, 5, c
->infile
->len
-5, 0x2);
1404 static int de_identify_npack(deark
*c
)
1406 if(dbuf_memcmp(c
->infile
, 0, (const void*)"MSTSM", 5)) {
1412 void de_module_npack(deark
*c
, struct deark_module_info
*mi
)
1415 mi
->desc
= "NPack compressed file";
1416 mi
->run_fn
= de_run_npack
;
1417 mi
->identify_fn
= de_identify_npack
;
1420 // **************************************************************************
1422 // e.g. LZSDEMO v3.1 by Stac
1423 // **************************************************************************
1425 static void de_run_lzs221(deark
*c
, de_module_params
*mparams
)
1427 do_lzstac_internal(c
, 4, c
->infile
->len
-4, 0);
1430 static int de_identify_lzs221(deark
*c
)
1432 if(dbuf_memcmp(c
->infile
, 0, (const void*)"sTaC", 4)) {
1438 void de_module_lzs221(deark
*c
, struct deark_module_info
*mi
)
1441 mi
->desc
= "LZS221 compressed file";
1442 mi
->run_fn
= de_run_lzs221
;
1443 mi
->identify_fn
= de_identify_lzs221
;
1446 // **************************************************************************
1447 // XPK compressed file format (XPKF)
1448 // **************************************************************************
1450 #define CODE_XPKF 0x58504b46U
1452 static void xpkf_internal(deark
*c
)
1454 dbuf
*tmpoutf
= NULL
;
1456 struct de_dfilter_in_params dcmpri
;
1457 struct de_dfilter_out_params dcmpro
;
1458 struct de_dfilter_results dres
;
1460 tmpoutf
= dbuf_create_membuf(c
, 0, 0);
1462 de_dfilter_init_objects(c
, &dcmpri
, &dcmpro
, &dres
);
1463 dcmpri
.f
= c
->infile
;
1465 dcmpri
.len
= c
->infile
->len
;
1468 fmtutil_xpk_codectype1(c
, &dcmpri
, &dcmpro
, &dres
, NULL
);
1469 dbuf_flush(tmpoutf
);
1471 if(dres
.errcode
==0 || tmpoutf
->len
>0) {
1472 outf
= dbuf_create_output_file(c
, "unc", NULL
, 0);
1473 dbuf_copy(tmpoutf
, 0, tmpoutf
->len
, outf
);
1477 de_err(c
, "Decompression failed: %s", dres
.errmsg
);
1483 dbuf_close(tmpoutf
);
1486 static void de_run_xpk(deark
*c
, de_module_params
*mparams
)
1491 static int de_identify_xpk(deark
*c
)
1493 if((u32
)de_getu32be(0)!=CODE_XPKF
) return 0;
1497 void de_module_xpk(deark
*c
, struct deark_module_info
*mi
)
1500 mi
->desc
= "XPK compressed file";
1501 mi
->run_fn
= de_run_xpk
;
1502 mi
->identify_fn
= de_identify_xpk
;
1503 mi
->flags
|= DE_MODFLAG_HIDDEN
;