1 // This file is part of Deark.
2 // Copyright (C) 2016 Jason Summers
3 // See the file COPYING for terms of use.
7 // Functions in this file can be called by deark-cmd.c, but should not be called
8 // by anything in the library or modules (use deark-util.c instead).
10 #define DE_NOT_IN_MODULE
11 #include "deark-config.h"
12 #include "deark-private.h"
13 #include "deark-user.h"
15 #define DE_DEFAULT_MAX_FILE_SIZE 0x280000000LL // 10GiB
16 #define DE_DEFAULT_MAX_TOTAL_OUTPUT_SIZE 0x3c0000000LL // 15GiB
17 #define DE_DEFAULT_MAX_IMAGE_DIMENSION 10000
18 #define DE_DEFAULT_MAX_OUTPUT_FILES 1000 // Limit for direct output (not ZIP)
19 #define DE_MAX_OUTPUT_FILES_HARD_LIMIT 250000
21 // Returns the best module to use, by looking at the file contents, etc.
22 static struct deark_module_info
*detect_module_for_file(deark
*c
, int *errflag
)
27 struct deark_module_info
*best_module
= NULL
;
30 if(!c
->detection_data
) {
31 c
->detection_data
= de_malloc(c
, sizeof(struct de_detection_data_struct
));
34 // This value is made available to modules' identification functions, so
35 // that they can potentially skip expensive tests that cannot possibly return
36 // a high enough confidence.
37 c
->detection_data
->best_confidence_so_far
= 0;
39 orig_errcount
= c
->error_count
;
40 for(i
=0; i
<c
->num_modules
; i
++) {
41 if(c
->module_info
[i
].identify_fn
==NULL
) continue;
43 // If autodetect is disabled for this module, and its autodetect routine
44 // doesn't do anything that may be needed by other modules, don't bother
45 // to run this module's autodetection.
46 if((c
->module_info
[i
].flags
& DE_MODFLAG_DISABLEDETECT
) &&
47 !(c
->module_info
[i
].flags
& DE_MODFLAG_SHAREDDETECTION
))
52 result
= c
->module_info
[i
].identify_fn(c
);
54 if(c
->error_count
> orig_errcount
) {
55 // Detection routines don't normally produce errors. If one does,
56 // it's probably an internal error, or other serious problem.
61 if(c
->module_info
[i
].flags
& DE_MODFLAG_DISABLEDETECT
) {
62 // Ignore results of autodetection.
66 if(result
<= c
->detection_data
->best_confidence_so_far
) continue;
68 // This is the best result so far.
69 c
->detection_data
->best_confidence_so_far
= result
;
70 best_module
= &c
->module_info
[i
];
71 if(c
->detection_data
->best_confidence_so_far
>=100) break;
77 struct sort_data_struct
{
82 static int module_compare_fn(const void *a
, const void *b
)
84 struct sort_data_struct
*m1
, *m2
;
87 m1
= (struct sort_data_struct
*)a
;
88 m2
= (struct sort_data_struct
*)b
;
90 return de_strcasecmp(c
->module_info
[m1
->module_index
].id
,
91 c
->module_info
[m2
->module_index
].id
);
94 void de_print_module_list(deark
*c
)
97 struct sort_data_struct
*sort_data
= NULL
;
99 de_register_modules(c
);
101 // An index to the modules. Will be sorted by name.
102 sort_data
= de_mallocarray(c
, c
->num_modules
, sizeof(struct sort_data_struct
));
104 for(k
=0; k
<c
->num_modules
; k
++) {
106 sort_data
[k
].module_index
= k
;
109 qsort((void*)sort_data
, (size_t)c
->num_modules
, sizeof(struct sort_data_struct
),
112 for(k
=0; k
<c
->num_modules
; k
++) {
114 i
= sort_data
[k
].module_index
;
115 if(!c
->module_info
[i
].id
) continue;
116 if(c
->extract_level
<2) {
117 if(c
->module_info
[i
].flags
& DE_MODFLAG_HIDDEN
) continue;
118 if(c
->module_info
[i
].flags
& DE_MODFLAG_NONWORKING
) continue;
120 desc
= c
->module_info
[i
].desc
? c
->module_info
[i
].desc
: "-";
121 de_printf(c
, DE_MSGTYPE_MESSAGE
, "%-14s %s\n", c
->module_info
[i
].id
, desc
);
124 de_free(c
, sort_data
);
127 static void do_modhelp_internal(deark
*c
, struct deark_module_info
*module_to_use
)
131 if(!module_to_use
) goto done
;
132 de_msg(c
, "Module: %s", module_to_use
->id
);
134 for(k
=0; k
<DE_MAX_MODULE_ALIASES
; k
++) {
135 if(module_to_use
->id_alias
[k
]) {
136 de_msg(c
, "Alias: %s", module_to_use
->id_alias
[k
]);
143 if(module_to_use
->desc
) {
144 de_msg(c
, "Description: %s", module_to_use
->desc
);
146 if(module_to_use
->desc2
) {
147 de_msg(c
, "Other notes: %s", module_to_use
->desc2
);
150 if(!module_to_use
->help_fn
) {
151 de_msg(c
, "No help available for module \"%s\"", module_to_use
->id
);
155 de_msg(c
, "Help for module \"%s\":", module_to_use
->id
);
156 module_to_use
->help_fn(c
);
162 static void do_modhelp(deark
*c
)
164 struct deark_module_info
*module_to_use
= NULL
;
166 de_register_modules(c
);
167 module_to_use
= de_get_module_by_id(c
, c
->input_format_req
);
169 de_err(c
, "Unknown module \"%s\"", c
->input_format_req
);
173 if(de_strcmp(c
->input_format_req
, module_to_use
->id
)) {
174 de_msg(c
, "\"%s\" is an alias for module \"%s\"",
175 c
->input_format_req
, module_to_use
->id
);
178 do_modhelp_internal(c
, module_to_use
);
184 void de_register_modules(deark
*c
)
186 // The real register_modules function (de_register_modules_internal) is
187 // only called indirectly, to help simplify dependencies.
188 if(!c
->module_register_fn
) {
189 de_internal_err_fatal(c
, "module_register_fn not set");
192 c
->module_register_fn(c
);
195 static void open_extrlist(deark
*c
)
197 unsigned int flags
= 0;
199 if(c
->extrlist_dbuf
|| !c
->extrlist_filename
) return;
201 if(de_get_ext_option(c
, "extrlist:append")) {
205 c
->extrlist_dbuf
= dbuf_create_unmanaged_file(c
, c
->extrlist_filename
,
206 DE_OVERWRITEMODE_STANDARD
, flags
);
209 // Returns 0 on "serious" error; e.g. input file not found.
212 dbuf
*orig_ifile
= NULL
;
213 dbuf
*subfile
= NULL
;
215 struct deark_module_info
*module_to_use
= NULL
;
216 int module_was_autodetected
= 0;
219 int keepdirentries_opt
;
220 de_module_params
*mparams
= NULL
;
221 de_ucstring
*friendly_infn
= NULL
;
223 if(c
->modhelp_req
&& c
->input_format_req
) {
228 if(c
->extrlist_filename
) {
230 if(c
->serious_error_flag
) goto done
;
233 friendly_infn
= ucstring_create(c
);
235 if(c
->input_style
==DE_INPUTSTYLE_STDIN
) {
236 ucstring_append_sz(friendly_infn
, "[stdin]", DE_ENCODING_LATIN1
);
239 if(!c
->input_filename
) {
240 de_internal_err_nonfatal(c
, "Input file not set");
241 c
->serious_error_flag
= 1;
244 ucstring_append_sz(friendly_infn
, c
->input_filename
, DE_ENCODING_UTF8
);
247 de_register_modules(c
);
249 if(c
->input_format_req
) {
250 module_to_use
= de_get_module_by_id(c
, c
->input_format_req
);
252 de_err(c
, "Unknown module \"%s\"", c
->input_format_req
);
253 c
->serious_error_flag
= 1;
258 if(c
->slice_size_req_valid
) {
259 de_dbg(c
, "Input file: %s[%d,%d]", ucstring_getpsz_d(friendly_infn
),
260 (int)c
->slice_start_req
, (int)c
->slice_size_req
);
262 else if(c
->slice_start_req
) {
263 de_dbg(c
, "Input file: %s[%d]", ucstring_getpsz_d(friendly_infn
),
264 (int)c
->slice_start_req
);
267 de_dbg(c
, "Input file: %s", ucstring_getpsz_d(friendly_infn
));
270 if(c
->input_style
==DE_INPUTSTYLE_STDIN
) {
271 orig_ifile
= dbuf_open_input_stdin(c
);
274 orig_ifile
= dbuf_open_input_file(c
, c
->input_filename
);
276 if(orig_ifile
&& orig_ifile
->btype
==DBUF_TYPE_FIFO
) {
277 // Only now do we know that the input "file" is a named pipe.
278 // Set a flag to remember that the input filename does not
279 // reflect the file format.
280 c
->suppress_detection_by_filename
= 1;
287 c
->infile
= orig_ifile
;
289 // If we are only supposed to look at a segment of the original file,
290 // do that by creating a child dbuf, using dbuf_open_input_subfile().
291 if(c
->slice_start_req
>0 || c
->slice_size_req_valid
) {
292 if(c
->slice_size_req_valid
)
293 subfile_size
= c
->slice_size_req
;
295 subfile_size
= c
->infile
->len
- c
->slice_start_req
;
296 subfile
= dbuf_open_input_subfile(c
->infile
, c
->slice_start_req
, subfile_size
);
303 module_to_use
= detect_module_for_file(c
, &errflag
);
304 if(errflag
) goto done
;
305 module_was_autodetected
= 1;
309 if(c
->infile
->len
==0)
310 de_err(c
, "Unknown or unsupported file format (empty file)");
312 de_err(c
, "Unknown or unsupported file format");
316 if(c
->modhelp_req
&& module_was_autodetected
&&
317 module_to_use
->unique_id
!=1) // id 1 == "unsupported"
319 do_modhelp_internal(c
, module_to_use
);
323 de_info(c
, "Module: %s", module_to_use
->id
);
325 if(module_was_autodetected
&& (module_to_use
->flags
&DE_MODFLAG_SECURITYWARNING
)) {
326 de_err(c
, "The %s module has not been audited for security. There is a "
327 "greater than average chance that it is unsafe to use with untrusted "
328 "input files. Use \"-m %s\" to confirm that you want to use it.",
329 module_to_use
->id
, module_to_use
->id
);
330 c
->serious_error_flag
= 1;
334 if(module_to_use
->flags
&DE_MODFLAG_NONWORKING
) {
335 de_warn(c
, "The %s module is considered to be incomplete, and may "
336 "not work properly. Caveat emptor.",
340 if(c
->identify_only
) {
341 // Stop here, unless we're using the "unsupported" module.
342 if(module_to_use
->unique_id
!=1) {
347 de_dbg2(c
, "file size: %" I64_FMT
"", c
->infile
->len
);
349 if(c
->output_style
==DE_OUTPUTSTYLE_ARCHIVE
) {
350 subdirs_opt
= de_get_ext_option_bool(c
, "archive:subdirs", -1);
352 // By default, for archive output, enable subdirs unless -o was used.
353 if(!c
->base_output_filename
) {
354 c
->allow_subdirs
= 1;
358 c
->allow_subdirs
= subdirs_opt
?1:0;
362 keepdirentries_opt
= de_get_ext_option_bool(c
, "keepdirentries", -1);
363 if(keepdirentries_opt
<0) {
364 // By default, only keep dir entries if there is some way that
365 // files can be present in such a subdir.
366 c
->keep_dir_entries
= (u8
)(
367 (c
->output_style
==DE_OUTPUTSTYLE_ARCHIVE
) &&
369 (!c
->base_output_filename
));
372 c
->keep_dir_entries
= keepdirentries_opt
?1:0;
375 if(c
->output_style
==DE_OUTPUTSTYLE_ARCHIVE
) {
378 s_opt
= de_get_ext_option(c
, "archive:timestamp");
380 c
->reproducible_output
= 1;
381 de_unix_time_to_timestamp(de_atoi64(s_opt
), &c
->reproducible_timestamp
, 0x1);
382 if(!c
->reproducible_timestamp
.is_valid
) {
383 // Timestamp out of range? Note: Supported range is
384 // -11644473599 ( 1601-01-01 00:00:01) through
385 // 910692730085 (30828-09-14 02:48:05)
386 c
->reproducible_output
= 0;
390 if(de_get_ext_option(c
, "archive:repro")) {
391 c
->reproducible_output
= 1;
396 if(c
->output_style
==DE_OUTPUTSTYLE_DIRECT
&&
397 c
->max_output_files
> DE_DEFAULT_MAX_OUTPUT_FILES
&&
398 !c
->list_mode
&& !c
->user_set_max_output_files
)
400 c
->max_output_files
= DE_DEFAULT_MAX_OUTPUT_FILES
;
403 // If we're writing to a zip file, we normally defer creating that zip file
404 // until we find a file to extract, so that we never create a zip file with
406 // But if the zip "file" is going to stdout, we'll make sure we produce zip
407 // output, even if it has no member files.
408 if(c
->output_style
==DE_OUTPUTSTYLE_ARCHIVE
&& c
->archive_to_stdout
) {
409 if(!de_archive_initialize(c
)) {
415 if(de_get_ext_option_bool(c
, "list:fileid", 0)) {
416 c
->list_mode_include_file_id
= 1;
420 if(c
->modcodes_req
) {
422 mparams
= de_malloc(c
, sizeof(de_module_params
));
423 // This is a hack, mainly for developer use. It lets the user set the
424 // "module codes" string from the command line, so that some modules
425 // can be run in special modes. For example, you can run the psd module
426 // in its "tagged blocks" mode. (If that turns out to be useful, though,
427 // it would be better to make it available via an "-opt" option, or
428 // even a new module.)
429 mparams
->in_params
.codes
= c
->modcodes_req
;
432 if(module_was_autodetected
)
433 moddisp
= DE_MODDISP_AUTODETECT
;
435 moddisp
= DE_MODDISP_EXPLICIT
;
437 if(!de_run_module(c
, module_to_use
, mparams
, moddisp
)) {
441 // The DE_MODFLAG_NOEXTRACT flag means the module is not expected to extract
443 if(c
->num_files_extracted
==0 && c
->error_count
==0 &&
444 !(module_to_use
->flags
&DE_MODFLAG_NOEXTRACT
))
446 de_info(c
, "No files found to extract!");
450 if(c
->extrlist_dbuf
) { dbuf_close(c
->extrlist_dbuf
); c
->extrlist_dbuf
=NULL
; }
451 ucstring_destroy(friendly_infn
);
452 if(subfile
) dbuf_close(subfile
);
453 if(orig_ifile
) dbuf_close(orig_ifile
);
455 return c
->serious_error_flag
? 0 : 1;
458 deark
*de_create_internal(void)
461 c
= de_malloc(NULL
,sizeof(deark
));
462 c
->show_infomessages
= 1;
463 c
->show_warnings
= 1;
465 c
->write_density
= 1;
466 c
->filenames_from_file
= 1;
467 c
->preserve_file_times
= 1;
468 c
->preserve_file_times_archives
= 1;
469 c
->preserve_file_times_internal
= 1;
470 c
->max_output_files
= DE_MAX_OUTPUT_FILES_HARD_LIMIT
;
471 c
->max_image_dimension
= DE_DEFAULT_MAX_IMAGE_DIMENSION
;
472 c
->max_output_file_size
= DE_DEFAULT_MAX_FILE_SIZE
;
473 c
->max_total_output_size
= DE_DEFAULT_MAX_TOTAL_OUTPUT_SIZE
;
474 c
->current_time
.is_valid
= 0;
475 c
->can_decode_fltpt
= -1; // = unknown
476 c
->host_is_le
= -1; // = unknown
477 c
->input_encoding
= DE_ENCODING_UNKNOWN
;
481 void de_destroy(deark
*c
)
486 if(c
->zip_data
) { de_zip_close_file(c
); }
487 if(c
->tar_data
) { de_tar_close_file(c
); }
488 if(c
->extrlist_dbuf
) { dbuf_close(c
->extrlist_dbuf
); }
489 for(i
=0; i
<c
->num_ext_options
; i
++) {
490 de_free(c
, c
->ext_option
[i
].name
);
491 de_free(c
, c
->ext_option
[i
].val
);
493 if(c
->base_output_filename
) { de_free(c
, c
->base_output_filename
); }
494 if(c
->special_1st_filename
) { de_free(c
, c
->special_1st_filename
); }
495 if(c
->output_archive_filename
) { de_free(c
, c
->output_archive_filename
); }
496 if(c
->extrlist_filename
) { de_free(c
, c
->extrlist_filename
); }
497 if(c
->detection_data
) { de_free(c
, c
->detection_data
); }
498 de_free(c
, c
->module_info
);
502 void de_set_userdata(deark
*c
, void *x
)
507 void *de_get_userdata(deark
*c
)
512 void de_set_messages_callback(deark
*c
, de_msgfn_type fn
)
517 void de_set_special_messages_callback(deark
*c
, de_specialmsgfn_type fn
)
519 c
->specialmsgfn
= fn
;
522 void de_set_fatalerror_callback(deark
*c
, de_fatalerrorfn_type fn
)
524 c
->fatalerrorfn
= fn
;
527 static int is_pathsep(i32 ch
)
529 if(ch
=='/') return 1;
531 if(ch
=='\\') return 1;
537 #define DE_PATHSEP '\\'
539 #define DE_PATHSEP '/'
542 static const char *get_basename_ptr(const char *fn
)
545 const char *basenameptr
= fn
;
547 for(i
=0; fn
[i
]; i
++) {
548 if(is_pathsep(fn
[i
])) {
549 basenameptr
= &fn
[i
+1];
555 static i32
ucstring_char_at(de_ucstring
*s
, i64 pos
)
558 if(pos
>=0 && pos
<s
->len
) return s
->str
[pos
];
563 static void backslashes_to_slashes(de_ucstring
*s
)
567 for(i
=0; i
<s
->len
; i
++) {
568 if(s
->str
[i
]=='\\') {
575 // Construct a basename for output files, or a filename for archives.
577 // 0x1 = use base filename only
578 // 0x2 = remove path separators
579 // 0x4 = this is an "internal" filename for a zip/tar archive
580 // Returns an allocated string, which the caller must eventually free.
581 // Returns NULL if it can't make a decent filename.
582 static char *make_output_filename(deark
*c
, const char *dirname
, const char *fn
,
583 const char *suffix
, unsigned int flags
)
588 de_ucstring
*tmps
= NULL
;
591 tmps
= ucstring_create(c
);
593 if(dirname
&& dirname
[0]) {
594 ucstring_append_sz(tmps
, dirname
, DE_ENCODING_UTF8
);
595 if(!is_pathsep(ucstring_char_at(tmps
, tmps
->len
-1))) {
596 ucstring_append_char(tmps
, DE_PATHSEP
);
600 fnpartpos
= tmps
->len
;
603 // Use base filename only
604 fn_part
= get_basename_ptr(fn
);
610 ucstring_append_sz(tmps
, fn_part
, DE_ENCODING_UTF8
);
613 if(tmps
->len
<= fnpartpos
) {
614 // Disallow empty filename
615 ucstring_append_sz(tmps
, "_", DE_ENCODING_LATIN1
);
619 ucstring_append_sz(tmps
, suffix
, DE_ENCODING_UTF8
);
623 // Remove path separators; sanitize
626 for(i
=fnpartpos
; i
<tmps
->len
; i
++) {
627 if(is_pathsep(tmps
->str
[i
])) {
631 if(i
==fnpartpos
&& tmps
->str
[i
]=='.') {
639 // When a filename-like option is supplied on the command line, there are
640 // cases where we can't be agnostic about which characters are path
641 // separators. One of them is when that name is written to an archive
643 // Our rule is that, for Windows builds, both "\" and "/" are path
644 // separators. For Unix builds, only "/" is, and "\" will be treated as
645 // an ordinary filename character, if allowed by the archive format.
646 // This difference in behavior on different platforms is unfortunate, but
647 // I think it's the least bad thing to do.
648 backslashes_to_slashes(tmps
);
652 // Don't allow empty filename
653 if(tmps
->len
<1) goto done
;
655 newfn_alloc
= (size_t)ucstring_count_utf8_bytes(tmps
) + 1;
656 newfn
= de_malloc(c
, newfn_alloc
);
657 ucstring_to_sz(tmps
, newfn
, newfn_alloc
, 0, DE_ENCODING_UTF8
);
660 ucstring_destroy(tmps
);
664 // Must call de_set_output_style() before this, if at all.
666 // 0x1 = use base filename only
667 // 0x2 = remove path separators
668 void de_set_output_filename_pattern(deark
*c
, const char *dirname
, const char *fn
,
671 if(c
->base_output_filename
) de_free(c
, c
->base_output_filename
);
672 c
->base_output_filename
= NULL
;
673 if(!fn
&& !dirname
) return;
674 if(!fn
) fn
= "output";
675 if(c
->output_style
==DE_OUTPUTSTYLE_ARCHIVE
) {
678 c
->base_output_filename
= make_output_filename(c
, dirname
, fn
, NULL
, flags
);
681 // Use exactly fn for the first output file (no ".000.")
682 // Must call de_set_output_style() before this, if at all.
683 void de_set_output_special_1st_filename(deark
*c
, const char *dirname
, const char *fn
)
685 if(c
->special_1st_filename
) {
686 de_free(c
, c
->special_1st_filename
);
687 c
->special_1st_filename
= NULL
;
692 if(c
->output_style
==DE_OUTPUTSTYLE_ARCHIVE
) {
696 c
->special_1st_filename
= make_output_filename(c
, dirname
, fn
, NULL
, flags
);
700 // If flags&0x10, configure the archive file to be written to stdout.
701 // 0x20 = Append ".zip"/".tar" (must have already called de_set_output_style())
702 // 0x1 = use base filename only
703 // 0x2 = remove path separators
704 void de_set_output_archive_filename(deark
*c
, const char *dname
, const char *fn
,
707 const char *suffix
= NULL
;
708 if(c
->output_archive_filename
) de_free(c
, c
->output_archive_filename
);
711 c
->archive_to_stdout
= 1;
715 if((flags
& 0x20) && c
->output_style
==DE_OUTPUTSTYLE_ARCHIVE
) {
716 if(c
->archive_fmt
==DE_ARCHIVEFMT_ZIP
) {
719 else if(c
->archive_fmt
==DE_ARCHIVEFMT_TAR
) {
727 c
->output_archive_filename
= make_output_filename(c
, dname
, fn
, suffix
, flags
);
730 void de_set_extrlist_filename(deark
*c
, const char *fn
)
732 if(c
->extrlist_filename
) de_free(c
, c
->extrlist_filename
);
733 c
->extrlist_filename
= NULL
;
735 c
->extrlist_filename
= de_strdup(c
, fn
);
739 void de_set_std_option_int(deark
*c
, enum de_stdoptions_enum o
, int x
)
742 case DE_STDOPT_DEBUG_LEVEL
:
745 case DE_STDOPT_EXTRACT_POLICY
:
746 c
->extract_policy
= x
;
748 case DE_STDOPT_EXTRACT_LEVEL
:
749 c
->extract_level
= x
;
751 case DE_STDOPT_LISTMODE
:
752 c
->list_mode
= x
?1:0;
754 case DE_STDOPT_WANT_MODHELP
:
755 c
->modhelp_req
= x
?1:0;
757 case DE_STDOPT_ID_MODE
:
758 c
->identify_only
= x
?1:0;
760 case DE_STDOPT_WARNINGS
:
761 c
->show_warnings
= x
;
763 case DE_STDOPT_INFOMESSAGES
:
764 c
->show_infomessages
= x
;
766 case DE_STDOPT_WRITE_BOM
:
767 c
->write_bom
= (u8
)x
;
769 case DE_STDOPT_WRITE_DENSITY
:
770 c
->write_density
= (u8
)x
;
772 case DE_STDOPT_ASCII_HTML
:
773 c
->ascii_html
= (u8
)x
;
775 case DE_STDOPT_FILENAMES_FROM_FILE
:
776 c
->filenames_from_file
= (u8
)x
;
778 case DE_STDOPT_OVERWRITE_MODE
:
779 c
->overwrite_mode
= x
;
781 case DE_STDOPT_PADPIX
:
785 de_internal_err_fatal(c
, "set_std_option");
789 void de_set_input_style(deark
*c
, int x
)
794 void de_set_input_filename(deark
*c
, const char *fn
)
796 c
->input_filename
= fn
;
799 int de_set_input_encoding(deark
*c
, const char *encname
, int reserved
)
803 enc
= de_encoding_name_to_code(encname
);
804 if(enc
==DE_ENCODING_UNKNOWN
) {
807 c
->input_encoding
= enc
;
811 // A hint as to the timezone of local-time timestamps in input files.
812 // In hours east of UTC.
813 void de_set_input_timezone(deark
*c
, i64 tzoffs_seconds
)
815 c
->input_tz_offs_seconds
= tzoffs_seconds
;
818 void de_set_input_file_slice_start(deark
*c
, i64 n
)
820 c
->slice_start_req
= n
;
823 void de_set_input_file_slice_size(deark
*c
, i64 n
)
825 c
->slice_size_req
= n
;
826 c
->slice_size_req_valid
= 1;
829 void de_set_output_style(deark
*c
, int x
, int subtype
)
832 if(c
->output_style
==DE_OUTPUTSTYLE_ARCHIVE
) {
833 c
->archive_fmt
= subtype
;
840 void de_set_dprefix(deark
*c
, const char *s
)
845 void de_set_first_output_file(deark
*c
, int x
)
847 c
->first_output_file
= x
;
850 void de_set_max_output_files(deark
*c
, i64 n
)
852 if(n
>DE_MAX_OUTPUT_FILES_HARD_LIMIT
) {
853 c
->max_output_files
= DE_MAX_OUTPUT_FILES_HARD_LIMIT
;
856 c
->max_output_files
= 0;
859 c
->max_output_files
= (int)n
;
861 c
->user_set_max_output_files
= 1;
864 void de_set_max_output_file_size(deark
*c
, i64 n
)
867 c
->max_output_file_size
= n
;
868 if(c
->max_total_output_size
< n
) {
869 c
->max_total_output_size
= n
;
873 void de_set_max_total_output_size(deark
*c
, i64 n
)
876 c
->max_total_output_size
= n
;
879 void de_set_max_image_dimension(deark
*c
, i64 n
)
882 else if (n
>0x7fffffff) n
=0x7fffffff;
883 c
->max_image_dimension
= n
;
886 void de_set_preserve_file_times(deark
*c
, int setting
, int x
)
889 // For files written directly to the filesystem.
890 c
->preserve_file_times
= x
?1:0;
892 else if(setting
==1) {
893 // For member files written to .zip/.tar files.
894 // I can't think of a good reason why a user would want to disable
895 // this, but it's allowed for consistency, and it doesn't hurt
897 c
->preserve_file_times_archives
= x
?1:0;
899 else if(setting
==2) {
900 // For the tIME chunk in PNG files we generate, and other internal timestamps.
901 // (Not currently used.)
902 // TODO: I'm undecided about whether this should be a user option, or
903 // just always be on.
904 // TODO: If we allow this setting to be turned off, it would be
905 // consistent to rename it, and use it for all "converted" formats,
906 // including e.g. the "Date" header item in ANSI Art files converted
908 c
->preserve_file_times_internal
= x
?1:0;
912 void de_set_ext_option(deark
*c
, const char *name
, const char *val
)
916 n
= c
->num_ext_options
;
917 if(n
>=DE_MAX_EXT_OPTIONS
) return;
918 if(!name
|| !val
) return;
920 c
->ext_option
[n
].name
= de_strdup(c
, name
);
921 c
->ext_option
[n
].val
= de_strdup(c
, val
);
922 c
->num_ext_options
++;
925 void de_set_input_format(deark
*c
, const char *fmtname
)
927 c
->input_format_req
= fmtname
;
930 void de_set_module_init_codes(deark
*c
, const char *codes
)
932 c
->modcodes_req
= codes
;
935 // invert=0: Disable the mods in the list
936 // invert=1: Disable all mods not in the list
937 void de_set_disable_mods(deark
*c
, const char *s
, int invert
)
940 c
->disablemods_string
= s
;
943 c
->onlymods_string
= s
;
947 // invert=0: Disable autodetection of the mods in the list
948 // invert=1: Disable autodetection of all mods not in the list
949 void de_set_disable_moddetect(deark
*c
, const char *s
, int invert
)
952 c
->nodetectmods_string
= s
;
955 c
->onlydetectmods_string
= s
;