コード例 #1
0
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);
}
コード例 #2
0
ファイル: ogg.c プロジェクト: jsummers/deark
static void do_vorbis_comment_block(deark *c, lctx *d, dbuf *f, i64 pos1)
{
	i64 pos = pos1;
	i64 n;
	i64 ncomments;
	i64 k;
	de_ucstring *s = NULL;

	n = dbuf_getu32le_p(f, &pos);
	if(pos+n > f->len) goto done;
	s = ucstring_create(c);
	dbuf_read_to_ucstring_n(f, pos, n, DE_DBG_MAX_STRLEN, s, 0, DE_ENCODING_UTF8);
	de_dbg(c, "vendor: \"%s\"", ucstring_getpsz_d(s));
	pos += n;

	ncomments = dbuf_getu32le_p(f, &pos);
	de_dbg(c, "number of comments: %d", (int)ncomments);

	for(k=0; k<ncomments; k++) {
		if(pos+4 > f->len) goto done;
		n = dbuf_getu32le_p(f, &pos);
		if(pos+n > f->len) goto done;
		ucstring_empty(s);
		dbuf_read_to_ucstring_n(f, pos, n, DE_DBG_MAX_STRLEN, s, 0, DE_ENCODING_UTF8);
		de_dbg(c, "comment[%d]: \"%s\"", (int)k, ucstring_getpsz_d(s));
		pos += n;
	}

done:
	ucstring_destroy(s);
}
コード例 #3
0
ファイル: apple2-dsk.c プロジェクト: jsummers/deark
static void do_woz_META(deark *c, struct de_iffctx *ictx,
	const struct de_iffchunkctx *chunkctx)
{
	i64 k;
	int reading_val;
	de_ucstring *s = NULL;
	de_ucstring *name = NULL;
	de_ucstring *val = NULL;

	// Read the entire metadata string.
	s = ucstring_create(c);
	dbuf_read_to_ucstring_n(ictx->f, chunkctx->dpos, chunkctx->dlen,
		65536, s, 0, DE_ENCODING_UTF8);

	// Parse out the individual metadata items
	name = ucstring_create(c);
	val = ucstring_create(c);
	reading_val = 0;

	for(k=0; k<s->len; k++) {
		i32 ch = s->str[k];

		if(ch==0x0a) { // End of item
			do_woz_print_metadata_item(c, name, val);
			ucstring_empty(name);
			ucstring_empty(val);
			reading_val = 0;
		}
		else if(ch==0x09 && !reading_val) { // Name/value separator
			reading_val = 1;
		}
		else { // A non-special character
			if(reading_val) {
				ucstring_append_char(val, ch);
			}
			else {
				ucstring_append_char(name, ch);
			}
		}
	}
	do_woz_print_metadata_item(c, name, val);

	ucstring_destroy(s);
	ucstring_destroy(name);
	ucstring_destroy(val);
}
コード例 #4
0
de_ucstring *ucstring_clone(de_ucstring *src)
{
	de_ucstring *dst;

	if(!src) return NULL;
	dst = ucstring_create(src->c);
	ucstring_append_ucstring(dst, src);
	return dst;
}
コード例 #5
0
ファイル: ebml.c プロジェクト: jsummers/deark
static void handler_filename(deark *c, lctx *d, struct handler_params *hp)
{
	if(!d->attachmentctx) return;
	if(d->attachmentctx->filename) return;
	if(hp->dlen<1) return;

	d->attachmentctx->filename = ucstring_create(c);
	dbuf_read_to_ucstring_n(c->infile, hp->dpos, hp->dlen, 300,
		d->attachmentctx->filename,
		DE_CONVFLAG_STOP_AT_NUL, DE_ENCODING_UTF8);
}
コード例 #6
0
ファイル: ebml.c プロジェクト: jsummers/deark
static void decode_string(deark *c, lctx *d, const struct ele_id_info *ele_id,
	  i64 pos, i64 len, int encoding)
{
	de_ucstring *s = NULL;

	s = ucstring_create(c);
	dbuf_read_to_ucstring_n(c->infile, pos, len, DE_DBG_MAX_STRLEN, s,
		DE_CONVFLAG_STOP_AT_NUL, encoding);
	de_dbg(c, "value: \"%s\"", ucstring_getpsz_d(s));

	ucstring_destroy(s);
}
コード例 #7
0
static void handle_text(deark *c, lctx *d, const struct ds_info *dsi,
	de_int64 pos, de_int64 len)
{
	int encoding;
	de_ucstring *s = NULL;

	s = ucstring_create(c);
	encoding = get_ds_encoding(c, d, dsi->recnum);
	if(encoding==DE_ENCODING_UNKNOWN)
		encoding = DE_ENCODING_ASCII;
	dbuf_read_to_ucstring(c->infile, pos, len, s, 0, encoding);
	de_dbg(c, "%s: \"%s\"\n", dsi->dsname, ucstring_get_printable_sz_n(s, 300));
	ucstring_destroy(s);
}
コード例 #8
0
static void do_read_linked_profile(deark *c, lctx *d)
{
	de_ucstring *fname = NULL;

	de_dbg(c, "linked profile filename at %d\n", (int)d->profile_offset);
	fname = ucstring_create(c);
	dbuf_read_to_ucstring_n(c->infile, d->profile_offset,
		d->profile_size, 300, fname,
		DE_CONVFLAG_STOP_AT_NUL, DE_ENCODING_WINDOWS1252);
	de_dbg_indent(c, 1);
	de_dbg(c, "profile filename: \"%s\"\n", ucstring_get_printable_sz(fname));
	de_dbg_indent(c, -1);
	ucstring_destroy(fname);
}
コード例 #9
0
ファイル: ebml.c プロジェクト: jsummers/deark
// Print an element ID number, in the format used by the Matroska spec.
static void print_encoded_id(deark *c, lctx *d, i64 pos, i64 len)
{
	de_ucstring *s = NULL;
	i64 i;

	if(len>8) return;
	s = ucstring_create(c);
	for(i=0; i<len; i++) {
		ucstring_printf(s, DE_ENCODING_UTF8, "[%02x]",
			(unsigned int)de_getbyte(pos+i));
	}
	de_dbg(c, "encoded id: %s", ucstring_getpsz_d(s));
	ucstring_destroy(s);
}
コード例 #10
0
ファイル: ogg.c プロジェクト: jsummers/deark
static char *get_hdrtype_descr(deark *c, char *buf, size_t buflen, u8 hdr_type)
{
	if(hdr_type==0) {
		de_strlcpy(buf, "", buflen);
	}
	else {
		de_ucstring *s = NULL;
		s = ucstring_create(c);
		if(hdr_type&0x01) ucstring_append_flags_item(s, "continuation page");
		if(hdr_type&0x02) ucstring_append_flags_item(s, "first page");
		if(hdr_type&0x04) ucstring_append_flags_item(s, "last page");
		de_snprintf(buf, buflen, " (%s)", ucstring_getpsz(s));
		ucstring_destroy(s);
	}
	return buf;
}
コード例 #11
0
ファイル: apple2-dsk.c プロジェクト: jsummers/deark
static void do_woz_INFO(deark *c, struct de_iffctx *ictx,
	const struct de_iffchunkctx *chunkctx)
{
	u8 b;
	i64 n;
	i64 pos = chunkctx->dpos;
	lctx *d = ictx->userdata;
	de_ucstring *s = NULL;

	if(chunkctx->dlen<37) return;
	b = dbuf_getbyte_p(ictx->f, &pos);
	de_dbg(c, "INFO chunk version: %d", (int)b);
	b = dbuf_getbyte_p(ictx->f, &pos);
	de_dbg(c, "disk type: %d (%s)", (int)b, get_woz_disk_type_name(b));
	b = dbuf_getbyte_p(ictx->f, &pos);
	de_dbg(c, "write protected: %d", (int)b);
	b = dbuf_getbyte_p(ictx->f, &pos);
	de_dbg(c, "synchronized: %d", (int)b);
	b = dbuf_getbyte_p(ictx->f, &pos);
	de_dbg(c, "cleaned: %d", (int)b);

	s = ucstring_create(c);
	dbuf_read_to_ucstring(ictx->f, pos, 32, s, 0, DE_ENCODING_UTF8);
	ucstring_strip_trailing_spaces(s);
	de_dbg(c, "creator: \"%s\"", ucstring_getpsz(s));
	pos += 32;

	if(d->wozver<'2') goto done;

	b = dbuf_getbyte_p(ictx->f, &pos);
	de_dbg(c, "disk sides: %d", (int)b);
	b = dbuf_getbyte_p(ictx->f, &pos);
	de_dbg(c, "boot sector format: %d", (int)b);
	b = dbuf_getbyte_p(ictx->f, &pos);
	de_dbg(c, "optimal bit timing: %d", (int)b);
	n = dbuf_getu16le_p(ictx->f, &pos);
	de_dbg(c, "compatible hardware: %d", (int)n);
	n = dbuf_getu16le_p(ictx->f, &pos);
	de_dbg(c, "required RAM: %dK", (int)n);
	n = dbuf_getu16le_p(ictx->f, &pos);
	de_dbg(c, "largest track: %d blocks", (int)n);

done:
	ucstring_destroy(s);
}
コード例 #12
0
ファイル: wri.c プロジェクト: jsummers/deark
static void extract_unknown_ole_obj(deark *c, lctx *d, i64 pos, i64 len,
	struct de_stringreaderdata *srd_typename)
{
	de_finfo *fi = NULL;
	de_ucstring *s = NULL;

	fi = de_finfo_create(c);
	s = ucstring_create(c);

	ucstring_append_sz(s, "oleobj", DE_ENCODING_LATIN1);
	if(ucstring_isnonempty(srd_typename->str)) {
		ucstring_append_sz(s, ".", DE_ENCODING_LATIN1);
		ucstring_append_ucstring(s, srd_typename->str);
	}

	de_finfo_set_name_from_ucstring(c, fi, s, 0);

	dbuf_create_file_from_slice(c->infile, pos, len, "bin", fi, 0);

	ucstring_destroy(s);
	de_finfo_destroy(c, fi);
}
コード例 #13
0
// 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);
}
コード例 #14
0
ファイル: wri.c プロジェクト: jsummers/deark
static void do_para_fprop(deark *c, lctx *d, struct para_info *pinfo,
	i64 bfprop, u8 is_dup)
{
	i64 fprop_dlen = 0;

	// bfprop is a pointer into the 123 bytes of data starting
	// at pos+4. The maximum sensible value is at most 122.
	if(bfprop<=122) {
		// It appears that the length prefix does not include itself,
		// contrary to what one source says.
		fprop_dlen = (i64)de_getbyte(pinfo->bfprop_offset);
		if(!is_dup) de_dbg(c, "fprop dlen: %d", (int)fprop_dlen);
	}

	if(fprop_dlen>=2) {
		pinfo->justification = de_getbyte(pinfo->bfprop_offset + 1 + 1) & 0x03;
		if(!is_dup && pinfo->justification!=0) {
			de_dbg(c, "justification: %d", (int)pinfo->justification);
		}
	}

	if(fprop_dlen>=17) {
		pinfo->papflags = de_getbyte(pinfo->bfprop_offset + 1 + 16);
		if(!is_dup) {
			de_ucstring *flagstr = ucstring_create(c);
			if(pinfo->papflags&0x06) {
				ucstring_append_flags_item(flagstr, (pinfo->papflags&0x01)?"footer":"header");
				ucstring_append_flags_item(flagstr, (pinfo->papflags&0x08)?"print on first page":
					"do not print on first page");
			}
			if(pinfo->papflags&0x10) ucstring_append_flags_item(flagstr, "picture");
			de_dbg(c, "paragraph flags: 0x%02x (%s)", (unsigned int)pinfo->papflags,
				ucstring_getpsz(flagstr));
			ucstring_destroy(flagstr);
		}
	}
}
コード例 #15
0
ファイル: gzip.c プロジェクト: jsummers/deark
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;
}
コード例 #16
0
ファイル: tga.c プロジェクト: jsummers/deark
static void do_read_extension_area(deark *c, lctx *d, i64 pos)
{
	i64 ext_area_size;
	i64 k;
	int has_date;
	de_ucstring *s = NULL;
	i64 val[6];

	de_dbg(c, "extension area at %d", (int)pos);
	if(pos > c->infile->len - 2) {
		de_warn(c, "Bad extension area offset: %u", (unsigned int)pos);
		return;
	}

	de_dbg_indent(c, 1);

	s = ucstring_create(c);

	ext_area_size = de_getu16le(pos);
	de_dbg(c, "extension area size: %d", (int)ext_area_size);
	if(ext_area_size<495) goto done;

	d->has_extension_area = 1;

	ucstring_empty(s);
	dbuf_read_to_ucstring(c->infile, pos+2, 41, s, DE_CONVFLAG_STOP_AT_NUL, DE_ENCODING_ASCII);
	ucstring_strip_trailing_spaces(s);
	de_dbg(c, "author: \"%s\"", ucstring_getpsz_d(s));

	for(k=0; k<4; k++) {
		ucstring_empty(s);
		dbuf_read_to_ucstring(c->infile, pos+43+81*k, 81, s, DE_CONVFLAG_STOP_AT_NUL, DE_ENCODING_ASCII);
		ucstring_strip_trailing_spaces(s);
		de_dbg(c, "comment line %d: \"%s\"", (int)k, ucstring_getpsz_d(s));
	}

	// date/time: pos=367, size=12
	has_date = 0;
	for(k=0; k<6; k++) {
		val[k] = de_getu16le(pos+367+2*k);
		if(val[k]!=0) has_date = 1;
	}
	if(has_date) {
		char timestamp_buf[64];

		de_make_timestamp(&d->mod_time, val[2], val[0], val[1], val[3], val[4], val[5]);
		d->mod_time.tzcode = DE_TZCODE_LOCAL;
		de_timestamp_to_string(&d->mod_time, timestamp_buf, sizeof(timestamp_buf), 0);
		de_dbg(c, "timestamp: %s", timestamp_buf);
	}

	// Job name: pos=379, size=41 (not implemented)
	// Job time: pos=420, size=6 (not implemented)

	ucstring_empty(s);
	dbuf_read_to_ucstring(c->infile, pos+426, 41, s, DE_CONVFLAG_STOP_AT_NUL, DE_ENCODING_ASCII);
	ucstring_strip_trailing_spaces(s);
	de_dbg(c, "software id: \"%s\"", ucstring_getpsz_d(s));

	val[0] = de_getu16le(pos+467);
	val[1] = (i64)de_getbyte(pos+469);
	if(val[0]!=0 || val[1]!=32) {
		de_dbg(c, "software version: %u,%u,%u",
			(unsigned int)(val[0]/100), (unsigned int)(val[0]%100),
			(unsigned int)val[1]);
	}

	val[0] = de_getu32le(pos+470);
	if(val[0]!=0) {
		de_dbg(c, "background color: 0x%08x", (unsigned int)val[0]);
	}

	// TODO: Retain the aspect ratio. (Need sample files. Nobody seems to use this field.)
	d->aspect_ratio_num = de_getu16le(pos+474);
	d->aspect_ratio_den = de_getu16le(pos+476);
	if(d->aspect_ratio_den!=0) {
		de_dbg(c, "aspect ratio: %d/%d", (int)d->aspect_ratio_num, (int)d->aspect_ratio_den);
	}

	// Gamma: pos=478, size=4 (not implemented)
	// Color correction table offset: pos=482, size=4 (not implemented)

	d->thumbnail_offset = de_getu32le(pos+486);
	de_dbg(c, "thumbnail image offset: %d", (int)d->thumbnail_offset);

	val[0] = de_getu32le(pos+490);
	de_dbg(c, "scan line table offset: %"I64_FMT, val[0]);

	d->attributes_type = de_getbyte(pos+494);
	de_dbg(c, "attributes type: %d", (int)d->attributes_type);
	if(d->attributes_type==0 && d->num_attribute_bits!=0) {
		de_warn(c, "Incompatible \"number of attribute bits\" (%d) and \"attributes type\" "
			"(%d) fields. Transparency may not be handled correctly.",
			(int)d->num_attribute_bits, (int)d->attributes_type);
	}

done:
	de_dbg_indent(c, -1);
	ucstring_destroy(s);
}
コード例 #17
0
ファイル: deark-dbuf.c プロジェクト: jsummers/deark
// An advanced function for reading a string from a file.
// The issue is that some strings are both human-readable and machine-readable.
// In such a case, we'd like to read some data from a file into a nice printable
// ucstring, while also making some or all of the raw bytes available, say for
// byte-for-byte string comparisons.
// Plus (for NUL-terminated/padded strings), we may need to know the actual length
// of the string in the file, so that it can be skipped over, even if we don't
// care about the whole string.
// Caller is responsible for calling destroy_stringreader() on the returned value.
//  max_bytes_to_scan: The maximum number of bytes to read from the file.
//  max_bytes_to_keep: The maximum (or in some cases the exact) number of bytes,
//   not counting any NUL terminator, to return in ->sz.
//   The ->str field is a Unicode version of ->sz, so this also affects ->str.
// If DE_CONVFLAG_STOP_AT_NUL is not set, it is assumed we are reading a string
// of known length, that may have internal NUL bytes. The caller must set
// max_bytes_to_scan and max_bytes_to_keep to the same value. The ->sz field will
// always be allocated with this many bytes, plus one more for an artificial NUL
// terminator.
// If DE_CONVFLAG_WANT_UTF8 is set, then the ->sz_utf8 field will be set to a
// UTF-8 version of ->str. This is mainly useful if the original string was
// UTF-16. sz_utf8 is not "printable" -- use ucstring_get_printable_sz_n(str) for
// that.
// Recognized flags:
//   - DE_CONVFLAG_STOP_AT_NUL
//   - DE_CONVFLAG_WANT_UTF8
struct de_stringreaderdata *dbuf_read_string(dbuf *f, i64 pos,
	i64 max_bytes_to_scan,
	i64 max_bytes_to_keep,
	unsigned int flags, int encoding)
{
	deark *c = f->c;
	struct de_stringreaderdata *srd;
	i64 foundpos = 0;
	int ret;
	i64 bytes_avail_to_read;
	i64 bytes_to_malloc;
	i64 x_strlen;

	srd = de_malloc(c, sizeof(struct de_stringreaderdata));
	srd->str = ucstring_create(c);

	bytes_avail_to_read = max_bytes_to_scan;
	if(bytes_avail_to_read > f->len-pos) {
		bytes_avail_to_read = f->len-pos;
	}

	srd->bytes_consumed = bytes_avail_to_read; // default

	// From here on, we can safely bail out ("goto done"). The
	// de_stringreaderdata struct is sufficiently valid.

	if(!(flags&DE_CONVFLAG_STOP_AT_NUL) &&
		(max_bytes_to_scan != max_bytes_to_keep))
	{
		// To reduce possible confusion, we require that
		// max_bytes_to_scan==max_bytes_to_keep in this case.
		srd->sz = de_malloc(c, max_bytes_to_keep+1);
		goto done;
	}

	if(flags&DE_CONVFLAG_STOP_AT_NUL) {
		ret = dbuf_search_byte(f, 0x00, pos, bytes_avail_to_read, &foundpos);
		if(ret) {
			srd->found_nul = 1;
		}
		else {
			// No NUL byte found. Could be an error in some formats, but in
			// others NUL is used as separator or as padding, not a terminator.
			foundpos = pos+bytes_avail_to_read;
		}

		x_strlen = foundpos-pos;
		srd->bytes_consumed = x_strlen+1;
	}
	else {
		x_strlen = max_bytes_to_keep;
		srd->bytes_consumed = x_strlen;
	}

	bytes_to_malloc = x_strlen+1;
	if(bytes_to_malloc>(max_bytes_to_keep+1)) {
		bytes_to_malloc = max_bytes_to_keep+1;
		srd->was_truncated = 1;
	}

	srd->sz = de_malloc(c, bytes_to_malloc);
	dbuf_read(f, (u8*)srd->sz, pos, bytes_to_malloc-1); // The last byte remains NUL

	ucstring_append_bytes(srd->str, (const u8*)srd->sz, bytes_to_malloc-1, 0, encoding);

	if(flags&DE_CONVFLAG_WANT_UTF8) {
		srd->sz_utf8_strlen = (size_t)ucstring_count_utf8_bytes(srd->str);
		srd->sz_utf8 = de_malloc(c, srd->sz_utf8_strlen + 1);
		ucstring_to_sz(srd->str, srd->sz_utf8, srd->sz_utf8_strlen + 1, 0, DE_ENCODING_UTF8);
	}

done:
	if(!srd->sz) {
		// Always return a valid sz, even on failure.
		srd->sz = de_malloc(c, 1);
	}
	if((flags&DE_CONVFLAG_WANT_UTF8) && !srd->sz_utf8) {
		// Always return a valid sz_utf8 if it was requested, even on failure.
		srd->sz_utf8 = de_malloc(c, 1);
		srd->sz_utf8_strlen = 0;
	}
	return srd;
}
コード例 #18
0
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;
}
コード例 #19
0
static void do_card_index(deark *c, lctx *d, de_int64 cardnum, de_int64 pos)
{
	de_int64 datapos;
	de_int64 bitmap_len;
	de_int64 w, h;
	de_int64 src_rowspan;
	de_int64 text_len;
	de_int64 text_pos;
	struct deark_bitmap *img = NULL;
	de_finfo *fi_bitmap = NULL;
	de_finfo *fi_text = NULL;
	const char *cardtype;
	de_ucstring *name = NULL;
	int saved_indent_level;

	de_dbg_indent_save(c, &saved_indent_level);

	datapos = de_getui32le(pos+6);
	de_dbg(c, "card #%d at %d, dpos=%d\n", (int)cardnum, (int)pos, (int)datapos);
	de_dbg_indent(c, 1);

	if(datapos>=c->infile->len) goto done;
	bitmap_len = de_getui16le(datapos);
	de_dbg(c, "bitmap length: %d\n", (int)bitmap_len);

	if(bitmap_len==0) {
		text_len = de_getui16le(datapos+2);
		text_pos = datapos+4;
	}
	else {
		text_len = de_getui16le(datapos + bitmap_len + 10);
		text_pos = datapos + bitmap_len + 10;
	}
	de_dbg(c, "text length: %d\n", (int)text_len);

	if(bitmap_len==0 && text_len==0) {
		cardtype = "empty";
	}
	else if(bitmap_len==0) {
		cardtype = "text-only";
	}
	else if(text_len==0) {
		cardtype = "graphics-only";
	}
	else {
		cardtype = "graphics+text";
	}
	de_dbg(c, "card type: %s\n", cardtype);

	if(bitmap_len==0 && text_len==0) {
		goto done;
	}

	name = ucstring_create(c);
	dbuf_read_to_ucstring(c->infile, pos+11, 40, name, DE_CONVFLAG_STOP_AT_NUL, DE_ENCODING_ASCII);
	de_dbg(c, "name: \"%s\"\n", ucstring_get_printable_sz(name));

	// Text

	if(text_len!=0 && c->extract_level>=2) {
		fi_text = de_finfo_create(c);
		if(c->filenames_from_file)
			de_finfo_set_name_from_ucstring(c, fi_text, name);

		do_text_data(c, d, fi_text, text_pos, text_len);
	}

	// Bitmap

	if(bitmap_len==0) goto done;

	fi_bitmap = de_finfo_create(c);
	if(c->filenames_from_file)
		de_finfo_set_name_from_ucstring(c, fi_bitmap, name);

	w = de_getui16le(datapos+2);
	h = de_getui16le(datapos+4);
	de_dbg(c, "bitmap dimensions: %dx%d\n", (int)w, (int)h);

	img = de_bitmap_create(c, w, h, 1);
	src_rowspan = ((w+15)/16)*2;

	de_convert_and_write_image_bilevel(c->infile, datapos+10,
		w, h, src_rowspan, 0, fi_bitmap, 0);

done:
	ucstring_destroy(name);
	de_bitmap_destroy(img);
	de_finfo_destroy(c, fi_bitmap);
	de_finfo_destroy(c, fi_text);
	de_dbg_indent_restore(c, saved_indent_level);
}