static void do_extract_file(deark *c, lctx *d, de_int64 dir_pos, de_byte filetype_c64s, de_byte filetype) { de_int64 load_addr; de_int64 end_addr; de_int64 offset; dbuf *f = NULL; de_int64 payload_size; // = file_size-2 de_ucstring *fname = NULL; de_int64 fname_len; de_int64 i; de_int64 fnpos; de_finfo *fi = NULL; load_addr = de_getui16le(dir_pos+2); end_addr = de_getui16le(dir_pos+4); offset = de_getui32le(dir_pos+8); de_dbg(c, "load_addr=%d end_addr=%d offset=%d\n", (int)load_addr, (int)end_addr, (int)offset); // File name at pos+16 fnpos = dir_pos+16; // Find the length of the (space-padded) filename. fname_len = 0; for(i=15; i>=0; i--) { if(de_getbyte(fnpos+i)!=' ') { fname_len = i+1; break; } } de_dbg2(c, "filename length: %d\n", (int)fname_len); fname = ucstring_create(c); dbuf_read_to_ucstring(c->infile, fnpos, fname_len, fname, 0, DE_ENCODING_PETSCII); de_dbg(c, "filename: \"%s\"\n", ucstring_get_printable_sz(fname)); ucstring_append_sz(fname, ".prg", DE_ENCODING_ASCII); fi = de_finfo_create(c); de_finfo_set_name_from_ucstring(c, fi, fname); fi->original_filename_flag = 1; payload_size = end_addr - load_addr; if(payload_size < 0) { // TODO: Try to support files that don't have end_addr set properly. de_err(c, "This type of T64 file is not supported.\n"); goto done; } f = dbuf_create_output_file(c, NULL, fi, 0); dbuf_copy(c->infile, dir_pos+2, 2, f); dbuf_copy(c->infile, offset, payload_size, f); done: dbuf_close(f); de_finfo_destroy(c, fi); ucstring_destroy(fname); }
static void do_html_begin(deark *c, lctx *d) { dbuf *f; if(d->html_outf) return; d->html_outf = dbuf_create_output_file(c, "html", NULL, 0); f = d->html_outf; if(c->write_bom && !c->ascii_html) dbuf_write_uchar_as_utf8(f, 0xfeff); dbuf_puts(f, "<!DOCTYPE html>\n"); dbuf_puts(f, "<html>\n"); dbuf_puts(f, "<head>\n"); dbuf_printf(f, "<meta charset=\"%s\">\n", c->ascii_html?"US-ASCII":"UTF-8"); dbuf_puts(f, "<title></title>\n"); dbuf_puts(f, "<style type=\"text/css\">\n"); dbuf_puts(f, " body { color: #000; background-color: #fff }\n"); dbuf_puts(f, " p { margin-top: 0; margin-bottom: 0 }\n"); dbuf_puts(f, " .c { color: #ccc }\n"); // Visible control characters // Replacement object dbuf_puts(f, " .r { padding: 0.5ex; color: #800; background-color: #eee;\n"); dbuf_puts(f, " font-style: italic; border: 0.34ex dotted #800 }\n"); dbuf_puts(f, " .tc { text-align: center }\n"); dbuf_puts(f, " .tr { text-align: right }\n"); dbuf_puts(f, " .tj { text-align: justify }\n"); dbuf_puts(f, "</style>\n"); dbuf_puts(f, "</head>\n"); dbuf_puts(f, "<body>\n"); }
int dbuf_create_file_from_slice(dbuf *inf, i64 pos, i64 data_size, const char *ext, de_finfo *fi, unsigned int createflags) { dbuf *f; f = dbuf_create_output_file(inf->c, ext, fi, createflags); if(!f) return 0; dbuf_copy(inf, pos, data_size, f); dbuf_close(f); return 1; }
static void handler_iccp(deark *c, lctx *d, struct handler_params *hp) { u8 cmpr_type; dbuf *f = NULL; struct de_stringreaderdata *prof_name_srd = NULL; de_finfo *fi = NULL; char prof_name2[100]; size_t prof_name2_strlen; i64 pos = hp->dpos; prof_name_srd = dbuf_read_string(c->infile, pos, 80, 80, DE_CONVFLAG_STOP_AT_NUL, DE_ENCODING_LATIN1); if(!prof_name_srd->found_nul) goto done; de_dbg(c, "profile name: \"%s\"", ucstring_getpsz_d(prof_name_srd->str)); pos += prof_name_srd->bytes_consumed; // Our working copy, to use as part of the filename. de_strlcpy(prof_name2, prof_name_srd->sz, sizeof(prof_name2)); if(!de_strcasecmp(prof_name2, "icc") || !de_strcasecmp(prof_name2, "icc profile")) { prof_name2[0] = '\0'; // Ignore generic name. } prof_name2_strlen = de_strlen(prof_name2); if(prof_name2_strlen>=5) { if(de_sz_has_ext(prof_name2, "icc")) { // If the name already ends in ".icc", chop it off so that we don't end // up with a double ".icc.icc" file extension. prof_name2[prof_name2_strlen-4] = '\0'; } } cmpr_type = de_getbyte_p(&pos); if(cmpr_type!=0) return; fi = de_finfo_create(c); if(c->filenames_from_file && prof_name2[0]) de_finfo_set_name_from_sz(c, fi, prof_name2, 0, DE_ENCODING_LATIN1); f = dbuf_create_output_file(c, "icc", fi, DE_CREATEFLAG_IS_AUX); de_decompress_deflate(c->infile, pos, hp->dlen - pos, f, 0, NULL, d->is_CgBI ? 0 : DE_DEFLATEFLAG_ISZLIB); done: dbuf_close(f); de_finfo_destroy(c, fi); de_destroy_stringreaderdata(c, prof_name_srd); }
// Caption/abstract static void handle_2_120(deark *c, lctx *d, const struct ds_info *dsi, de_int64 pos, de_int64 len) { de_ucstring *s = NULL; dbuf *outf = NULL; int encoding; const char *fntoken; if(c->extract_level<2) { handle_text(c, d, dsi, pos, len); goto done; } // FIXME: There is currently no way to extract IPTC captions to files, // except when reading a raw IPTC file. If IPTC is embedded in some other // file (as it usually is), then the -a option will extract the entire // IPTC data, and we will never get here. fntoken = "caption.txt"; encoding = get_ds_encoding(c, d, dsi->recnum); if(encoding==DE_ENCODING_UNKNOWN) { // If the encoding is unknown, copy the raw bytes. dbuf_create_file_from_slice(c->infile, pos, len, fntoken, NULL, DE_CREATEFLAG_IS_AUX); goto done; } // If the encoding is known, convert to UTF-8. s = ucstring_create(c); dbuf_read_to_ucstring(c->infile, pos, len, s, 0, encoding); outf = dbuf_create_output_file(c, fntoken, NULL, DE_CREATEFLAG_IS_AUX); ucstring_write_as_utf8(c, s, outf, 1); done: if(outf) dbuf_close(outf); if(s) ucstring_destroy(s); }
static int do_gzip_read_member(deark *c, lctx *d, i64 pos1, i64 *member_size) { u8 b0, b1; i64 pos; i64 n; i64 foundpos; i64 string_len; i64 cmpr_data_len; i64 mod_time_unix; u32 crc_calculated; de_ucstring *member_name = NULL; int saved_indent_level; int ret; struct member_data *md = NULL; int retval = 0; md = de_malloc(c, sizeof(struct member_data)); de_dbg_indent_save(c, &saved_indent_level); de_dbg(c, "gzip member at %d", (int)pos1); de_dbg_indent(c, 1); pos = pos1; b0 = de_getbyte(pos+0); b1 = de_getbyte(pos+1); if(b0!=0x1f || b1!=0x8b) { de_err(c, "Invalid gzip signature at %d. This is not a valid gzip file.", (int)pos1); goto done; } md->cmpr_code = de_getbyte(pos+2); if(md->cmpr_code!=0x08) { de_err(c, "Unsupported compression type (%d)", (int)md->cmpr_code); goto done; } md->flags = de_getbyte(pos+3); de_dbg(c, "flags: 0x%02x", (unsigned int)md->flags); pos += 4; mod_time_unix = de_getu32le(pos); de_unix_time_to_timestamp(mod_time_unix, &md->mod_time_ts, 0x1); if(md->mod_time_ts.is_valid) { char timestamp_buf[64]; de_timestamp_to_string(&md->mod_time_ts, timestamp_buf, sizeof(timestamp_buf), 0); de_dbg(c, "mod time: %" I64_FMT " (%s)", mod_time_unix, timestamp_buf); } pos += 4; b0 = de_getbyte(pos++); de_dbg(c, "extra flags: 0x%02x", (unsigned int)b0); b0 = de_getbyte(pos++); de_dbg(c, "OS or filesystem: %d (%s)", (int)b0, get_os_name(b0)); if(md->flags & GZIPFLAG_FEXTRA) { n = de_getu16le(pos); // XLEN // TODO: It might be interesting to dissect these extra fields, but it's // hard to find even a single file that uses them. de_dbg(c, "[extra fields at %d, dpos=%d, dlen=%d]", (int)pos, (int)(pos+2), (int)n); pos += 2; pos += n; } if(md->flags & GZIPFLAG_FNAME) { ret = dbuf_search_byte(c->infile, 0x00, pos, c->infile->len - pos, &foundpos); if(!ret) { de_err(c, "Invalid NAME field"); goto done; } string_len = foundpos - pos; member_name = ucstring_create(c); #define DE_GZIP_MAX_FNLEN 300 dbuf_read_to_ucstring_n(c->infile, pos, string_len, DE_GZIP_MAX_FNLEN, member_name, 0, DE_ENCODING_LATIN1); de_dbg(c, "file name at %d, len=%d: \"%s\"", (int)pos, (int)string_len, ucstring_getpsz_d(member_name)); pos = foundpos + 1; } if(md->flags & GZIPFLAG_FCOMMENT) { ret = dbuf_search_byte(c->infile, 0x00, pos, c->infile->len - pos, &foundpos); if(!ret) { de_err(c, "Invalid COMMENT field"); goto done; } pos = foundpos + 1; } if(md->flags & GZIPFLAG_FHCRC) { md->crc16_reported = (u32)de_getu16le(pos); de_dbg(c, "crc16 (reported): 0x%04x", (unsigned int)md->crc16_reported); pos += 2; } de_dbg(c, "compressed blocks at %d", (int)pos); if(!d->output_file) { // Although any member can have a name and mod time, this metadata // is ignored for members after the first one. de_finfo *fi = NULL; fi = de_finfo_create(c); if(member_name && c->filenames_from_file) { de_finfo_set_name_from_ucstring(c, fi, member_name, 0); fi->original_filename_flag = 1; } if(md->mod_time_ts.is_valid) { fi->mod_time = md->mod_time_ts; } d->output_file = dbuf_create_output_file(c, member_name?NULL:"bin", fi, 0); de_finfo_destroy(c, fi); } d->output_file->writecallback_fn = our_writecallback; d->output_file->userdata = (void*)md; md->crco = d->crco; de_crcobj_reset(md->crco); ret = de_decompress_deflate(c->infile, pos, c->infile->len - pos, d->output_file, 0, &cmpr_data_len, 0); crc_calculated = de_crcobj_getval(md->crco); d->output_file->writecallback_fn = NULL; d->output_file->userdata = NULL; if(!ret) goto done; pos += cmpr_data_len; de_dbg(c, "crc32 (calculated): 0x%08x", (unsigned int)crc_calculated); md->crc32_reported = (u32)de_getu32le(pos); de_dbg(c, "crc32 (reported) : 0x%08x", (unsigned int)md->crc32_reported); pos += 4; if(crc_calculated != md->crc32_reported) { de_warn(c, "CRC check failed: Expected 0x%08x, got 0x%08x", (unsigned int)md->crc32_reported, (unsigned int)crc_calculated); } md->isize = de_getu32le(pos); de_dbg(c, "uncompressed size (mod 2^32): %u", (unsigned int)md->isize); pos += 4; retval = 1; done: if(retval) *member_size = pos - pos1; else *member_size = 0; ucstring_destroy(member_name); de_free(c, md); de_dbg_indent_restore(c, saved_indent_level); return retval; }
static int do_gzip_read_member(deark *c, lctx *d, de_int64 pos1, de_int64 *member_size) { de_byte b0, b1; de_int64 cmpr_code; de_int64 pos; de_int64 n; de_int64 foundpos; de_int64 string_len; de_int64 cmpr_data_len; de_int64 isize; de_int64 mod_time_unix; struct de_timestamp mod_time_ts; de_uint32 crc32_field; de_ucstring *member_name = NULL; de_finfo *fi = NULL; int saved_indent_level; int ret; int retval = 0; mod_time_ts.is_valid = 0; de_dbg_indent_save(c, &saved_indent_level); de_dbg(c, "gzip member at %d\n", (int)pos1); de_dbg_indent(c, 1); pos = pos1; b0 = de_getbyte(pos+0); b1 = de_getbyte(pos+1); if(b0!=0x1f || b1!=0x8b) { de_err(c, "Invalid gzip signature at %d. This is not a valid gzip file.\n", (int)pos1); goto done; } cmpr_code=de_getbyte(pos+2); if(cmpr_code!=0x08) { de_err(c, "Unsupported compression type (%d)\n", (int)cmpr_code); goto done; } d->flags = de_getbyte(pos+3); de_dbg(c, "flags: 0x%02x\n", (unsigned int)d->flags); pos += 4; mod_time_unix = de_getui32le(pos); de_unix_time_to_timestamp(mod_time_unix, &mod_time_ts); if(mod_time_ts.is_valid) { char timestamp_buf[64]; de_timestamp_to_string(&mod_time_ts, timestamp_buf, sizeof(timestamp_buf), 1); de_dbg(c, "mod time: %" INT64_FMT " (%s)\n", mod_time_unix, timestamp_buf); } pos += 4; b0 = de_getbyte(pos++); de_dbg(c, "extra flags: 0x%02x\n", (unsigned int)b0); b0 = de_getbyte(pos++); de_dbg(c, "OS or filesystem: %d (%s)\n", (int)b0, get_os_name(b0)); if(d->flags & GZIPFLAG_FEXTRA) { n = de_getui16le(pos); // XLEN // TODO: It might be interesting to dissect these extra fields, but it's // hard to find even a single file that uses them. de_dbg(c, "[extra fields at %d, dpos=%d, dlen=%d]\n", (int)pos, (int)(pos+2), (int)n); pos += 2; pos += n; } if(d->flags & GZIPFLAG_FNAME) { ret = dbuf_search_byte(c->infile, 0x00, pos, c->infile->len - pos, &foundpos); if(!ret) { de_err(c, "Invalid NAME field\n"); goto done; } string_len = foundpos - pos; member_name = ucstring_create(c); dbuf_read_to_ucstring_n(c->infile, pos, string_len, 300, member_name, 0, DE_ENCODING_LATIN1); de_dbg(c, "file name at %d, len=%d: \"%s\"\n", (int)pos, (int)string_len, ucstring_get_printable_sz(member_name)); pos = foundpos + 1; } if(d->flags & GZIPFLAG_FCOMMENT) { ret = dbuf_search_byte(c->infile, 0x00, pos, c->infile->len - pos, &foundpos); if(!ret) { de_err(c, "Invalid COMMENT field\n"); goto done; } pos = foundpos + 1; } if(d->flags & GZIPFLAG_FHCRC) { pos += 2; } de_dbg(c, "compressed blocks at %d\n", (int)pos); if(!d->output_file) { fi = de_finfo_create(c); if(member_name && c->filenames_from_file) { de_finfo_set_name_from_ucstring(c, fi, member_name); fi->original_filename_flag = 1; } if(mod_time_ts.is_valid) { fi->mod_time = mod_time_ts; } d->output_file = dbuf_create_output_file(c, member_name?NULL:"bin", fi, 0); } ret = de_uncompress_deflate(c->infile, pos, c->infile->len - pos, d->output_file, &cmpr_data_len); if(!ret) goto done; pos += cmpr_data_len; crc32_field = (de_uint32)de_getui32le(pos); de_dbg(c, "crc32: 0x%08x\n", (unsigned int)crc32_field); pos += 4; // TODO: Validate CRCs isize = de_getui32le(pos); de_dbg(c, "uncompressed size (mod 2^32): %u\n", (unsigned int)isize); pos += 4; retval = 1; done: if(retval) *member_size = pos - pos1; else *member_size = 0; ucstring_destroy(member_name); de_finfo_destroy(c, fi); de_dbg_indent_restore(c, saved_indent_level); return retval; }
// Generic (ImageMagick?) profile. Hex-encoded, with three header lines. static void on_im_generic_profile_main(deark *c, lctx *d, struct text_chunk_ctx *tcc, dbuf *inf, i64 pos1, i64 len) { int k; i64 pos = pos1; i64 dlen; int dump_to_file = 0; int decode_to_membuf = 0; const char *ext = NULL; // Skip the first three lines for(k=0; k<3; k++) { int ret; i64 foundpos = 0; ret = dbuf_search_byte(inf, 0x0a, pos, pos1+len-pos, &foundpos); if(!ret) goto done; pos = foundpos+1; } dlen = pos1+len-pos; if(tcc->im_generic_profile_type==PROFILETYPE_XMP) { dump_to_file = 1; ext = "xmp"; } else if(tcc->im_generic_profile_type==PROFILETYPE_8BIM) { decode_to_membuf = 1; } else if(tcc->im_generic_profile_type==PROFILETYPE_IPTC) { if(c->extract_level>=2) { dump_to_file = 1; ext = "iptc"; } else { decode_to_membuf = 1; } } else if(tcc->im_generic_profile_type==PROFILETYPE_ICC) { dump_to_file = 1; ext = "icc"; } else { if(c->extract_level>=2) { dump_to_file = 1; ext = "profile.bin"; } } if(dump_to_file) { dbuf *outf; outf = dbuf_create_output_file(c, ext?ext:"bin", NULL, DE_CREATEFLAG_IS_AUX); de_decode_base16(c, inf, pos, dlen, outf, 0); dbuf_close(outf); } if(decode_to_membuf) { dbuf *tmpf; tmpf = dbuf_create_membuf(c, 0, 0); de_decode_base16(c, inf, pos, dlen, tmpf, 0); if(tcc->im_generic_profile_type==PROFILETYPE_8BIM) { de_fmtutil_handle_photoshop_rsrc(c, tmpf, 0, tmpf->len, 0x0); } else if(tcc->im_generic_profile_type==PROFILETYPE_IPTC) { de_fmtutil_handle_iptc(c, tmpf, 0, tmpf->len, 0x0); } dbuf_close(tmpf); } done: ; }