Exemplo n.º 1
0
// 16-color 160x100 (maybe up to 160x102) mode.
// This is really a text mode, and can be processed by do_char() as well.
static int do_cga16(deark *c, lctx *d)
{
	de_bitmap *img = NULL;
	i64 max_possible_height;
	i64 i, j;
	int retval = 0;
	u8 charcode, colorcode;
	i64 src_rowspan;
	u8 color0, color1;
	int charwarning = 0;

	de_declare_fmt(c, "BSAVE-PC 16-color CGA pseudo-graphics");

	img = de_bitmap_create_noinit(c);
	img->width = get_width(c, d, 160);
	img->height = get_height(c, d, 100);

	img->bytes_per_pixel = 3;

	// Every pair of bytes codes for two pixels; i.e. one byte per pixel.
	src_rowspan = img->width;
	max_possible_height = (d->data_size+src_rowspan-1)/src_rowspan;
	if(img->height > max_possible_height)
		img->height = max_possible_height;

	if(img->height < 1) {
		de_err(c, "Not enough data for this format");
		goto done;
	}

	for(j=0; j<img->height; j++) {
		for(i=0; i<img->width; i+=2) {
			charcode = de_getbyte(BSAVE_HDRSIZE + j*src_rowspan + i);
			colorcode = de_getbyte(BSAVE_HDRSIZE + j*src_rowspan + i+1);

			if(charwarning==0 && charcode!=0xdd && charcode!=0xde) {
				// TODO: We could also handle space characters and full-block characters,
				// at least. But maybe not worth the trouble.
				de_warn(c, "Unexpected code found (0x%02x). Format may not be correct.", (int)charcode);
				charwarning=1;
			}

			if(charcode==0xde) {
				color0 = colorcode>>4;
				color1 = colorcode&0x0f;
			}
			else {
				color1 = colorcode>>4;
				color0 = colorcode&0x0f;
			}

			de_bitmap_setpixel_rgb(img, i+0, j, de_palette_pc16(color0));
			de_bitmap_setpixel_rgb(img, i+1, j, de_palette_pc16(color1));
		}
Exemplo n.º 2
0
Arquivo: wri.c Projeto: jsummers/deark
// TODO: Consolidate this withe do_static_bitmap()?
static void do_picture_bitmap(deark *c, lctx *d, struct para_info *pinfo)
{
	i64 pos1 = pinfo->thisparapos;
	i64 pos;
	i64 cbHeader, cbSize;
	i64 bmWidth, bmHeight;
	i64 bmPlanes;
	i64 bmBitsPixel;
	i64 rowspan;

	pos = pos1;
	pos += 16;
	pos += 2;
	bmWidth = de_getu16le_p(&pos); // pos1+16+2
	bmHeight = de_getu16le_p(&pos); // pos1+16+4
	de_dbg_dimensions(c, bmWidth, bmHeight);

	rowspan = de_getu16le_p(&pos); // pos1+16+6
	de_dbg(c, "bytes/row: %d", (int)rowspan);

	bmPlanes = (i64)de_getbyte_p(&pos);
	de_dbg(c, "planes: %d", (int)bmPlanes);

	bmBitsPixel = (i64)de_getbyte_p(&pos); // pos1+16+9
	de_dbg(c, "bmBitsPixel: %d", (int)bmBitsPixel);

	pos += 4;

	cbHeader = de_getu16le_p(&pos); // pos1+30
	de_dbg(c, "cbHeader: %d", (int)cbHeader);

	cbSize = de_getu32le_p(&pos); // pos1+32
	de_dbg(c, "cbSize: %d", (int)cbSize);

	if(bmBitsPixel!=1 || bmPlanes!=1) {
		de_err(c, "This type of bitmap is not supported (bmBitsPixel=%d, planes=%d)",
			(int)bmBitsPixel, (int)bmPlanes);
		goto done;
	}

	pos = pos1 + cbHeader;

	de_convert_and_write_image_bilevel(c->infile, pos, bmWidth, bmHeight, rowspan, 0, NULL, 0);

done:
	;
}
Exemplo n.º 3
0
Arquivo: ogg.c Projeto: jsummers/deark
static int de_identify_ogg(deark *c)
{
	i64 pos = 0;

	if(!c->detection_data.id3.detection_attempted) {
		de_err(c, "ogg detection requires id3 module");
		return 0;
	}

	if(c->detection_data.id3.has_id3v2) {
		pos = (i64)c->detection_data.id3.bytes_at_start;
	}

	if(!dbuf_memcmp(c->infile, pos, "OggS", 4))
		return 100;

	return 0;
}
Exemplo n.º 4
0
Arquivo: wri.c Projeto: jsummers/deark
// pos1 points to the ole_id field (should be 0x00000501).
// Returns nonzero if there may be additional renditions.
static int do_picture_ole_rendition(deark *c, lctx *d, struct para_info *pinfo,
	unsigned int objectType,
	int rendition_idx, i64 pos1, i64 *bytes_consumed)
{
	unsigned int ole_id;
	unsigned int objectType2;
	int retval = 0;

	de_dbg(c, "OLE rendition[%d] at %d", rendition_idx, (int)pos1);
	de_dbg_indent(c, 1);

	ole_id = (unsigned int)de_getu32le(pos1);
	de_dbg(c, "ole id: 0x%08x", ole_id);
	if(ole_id!=0x00000501U) {
		de_err(c, "Unexpected ole_id: 0x%08x", ole_id);
		goto done;
	}

	objectType2 = (unsigned int)de_getu32le(pos1+4);
	de_dbg(c, "type: %u", objectType2);

	if(objectType==1) {
		if(objectType2==3) {
			do_picture_ole_static_rendition(c, d, pinfo, rendition_idx, pos1, bytes_consumed);
		}
	}
	else if(objectType==2) {
		if(objectType2==0) {
			goto done;
		}
		else if(objectType2==2) {
			do_picture_ole_embedded_rendition(c, d, pinfo, rendition_idx, pos1, bytes_consumed);
			retval = 1;
		}
		else if(objectType2==5) { // replacement
			do_picture_ole_static_rendition(c, d, pinfo, rendition_idx, pos1, bytes_consumed);
		}
	}

done:
	de_dbg_indent(c, -1);
	return retval;
}
Exemplo n.º 5
0
// Decode the base-64 data, and write to d->decoded.
// Returns 0 if there was an error.
static int do_decode_main(deark *c, lctx *d, de_int64 pos)
{
    de_byte b;
    de_byte x;
    de_byte pending_byte = 0;
    unsigned int pending_bits_used = 0;

    while(1) {
        if(pos >= c->infile->len) return 0; // unexpected end of file
        b = de_getbyte(pos);
        pos++;
        if(b==':') {
            break;
        }
        else if(b=='\x0a' || b=='\x0d' || b==' ' || b=='\t') {
            // Ignore whitespace
            continue;
        }

        x = get_char_value(b);
        if(x>=64) {
            de_err(c, "Invalid BinHex data at %d\n", (int)(pos-1));
            return 0;
        }

        // TODO: Simplify this code
        if(pending_bits_used==0) {
            pending_byte = x;
            pending_bits_used = 6;
        }
        else if(pending_bits_used==2) {
            pending_byte = (pending_byte<<(8-pending_bits_used))|x;
            dbuf_writebyte(d->decoded, pending_byte);
            pending_bits_used -= 2;
        }
        else if(pending_bits_used==4) {
            pending_byte = (pending_byte<<(8-pending_bits_used))|(x>>(pending_bits_used-2));
            dbuf_writebyte(d->decoded, pending_byte);
            pending_byte = x&0x03;
            pending_bits_used -= 2;
        }
        else if(pending_bits_used==6) {
Exemplo n.º 6
0
Arquivo: rpm.c Projeto: jsummers/deark
static int do_lead_section(deark *c, lctx *d)
{
	int retval = 0;

	de_dbg(c, "lead section at %d", 0);
	de_dbg_indent(c, 1);

	d->ver_major = de_getbyte(4);
	d->ver_minor = de_getbyte(5);
	de_dbg(c, "RPM format version: %d.%d", (int)d->ver_major, (int)d->ver_minor);
	if(d->ver_major < 3) {
		de_err(c, "Unsupported RPM version (%d.%d)", (int)d->ver_major, (int)d->ver_minor);
		goto done;
	}

	retval = 1;
done:
	de_dbg_indent(c, -1);
	return retval;
}
Exemplo n.º 7
0
static void de_run_woz(deark *c, de_module_params *mparams)
{
	lctx *d = NULL;
	struct de_iffctx *ictx = NULL;
	u32 crc;
	i64 pos = 0;

	// WOZ has a 12-byte header, then sequence of chunks that are basically the
	// same format as RIFF.
	d = de_malloc(c, sizeof(lctx));
	ictx = de_malloc(c, sizeof(struct de_iffctx));

	ictx->userdata = (void*)d;
	ictx->preprocess_chunk_fn = my_preprocess_woz_chunk_fn;
	ictx->handle_chunk_fn = my_woz_chunk_handler;
	ictx->f = c->infile;
	ictx->is_le = 1;
	ictx->reversed_4cc = 0;

	if(ictx->f->len<12) goto done;
	de_dbg(c, "header at %d", (int)pos);
	de_dbg_indent(c, 1);
	pos += 3; // "WOZ" part of signature
	d->wozver = dbuf_getbyte_p(ictx->f, &pos);
	de_dbg(c, "format version: '%c'", de_byte_to_printable_char(d->wozver));
	if(d->wozver<'1' || d->wozver>'2') {
		de_err(c, "Unsupported WOZ format version");
		goto done;
	}
	pos += 4; // rest of signature
	crc = (u32)dbuf_getu32le_p(ictx->f, &pos);
	de_dbg(c, "crc: 0x%08x", (unsigned int)crc);
	de_dbg_indent(c, -1);

	de_fmtutil_read_iff_format(c, ictx, pos, ictx->f->len-pos);

done:
	de_free(c, ictx);
	de_free(c, d);
}
Exemplo n.º 8
0
static void do_modhelp(deark *c)
{
	struct deark_module_info *module_to_use = NULL;

	de_register_modules(c);
	module_to_use = de_get_module_by_id(c, c->input_format_req);
	if(!module_to_use) {
		de_err(c, "Unknown module \"%s\"\n", c->input_format_req);
		goto done;
	}

	if(!module_to_use->help_fn) {
		de_msg(c, "No help available for module \"%s\"\n", c->input_format_req);
		goto done;
	}

	de_msg(c, "Help for module \"%s\":\n", c->input_format_req);
	module_to_use->help_fn(c);

done:
	;
}
Exemplo n.º 9
0
void dbuf_write(dbuf *f, const u8 *m, i64 len)
{
	if(f->len + len > f->max_len_hard) {
		do_on_dbuf_size_exceeded(f);
	}

	if(f->writecallback_fn) {
		f->writecallback_fn(f, m, len);
	}

	if(f->btype==DBUF_TYPE_NULL) {
		f->len += len;
		return;
	}
	else if(f->btype==DBUF_TYPE_OFILE || f->btype==DBUF_TYPE_STDOUT) {
		if(!f->fp) return;
		if(f->c->debug_level>=3) {
			de_dbg3(f->c, "writing %d bytes to %s", (int)len, f->name);
		}
		fwrite(m, 1, (size_t)len, f->fp);
		f->len += len;
		return;
	}
	else if(f->btype==DBUF_TYPE_MEMBUF) {
		if(f->c->debug_level>=3 && f->name) {
			de_dbg3(f->c, "appending %d bytes to membuf %s", (int)len, f->name);
		}
		membuf_append(f, m, len);
		return;
	}
	else if(f->btype==DBUF_TYPE_ODBUF) {
		dbuf_write(f->parent_dbuf, m, len);
		f->len += len;
		return;
	}

	de_err(f->c, "Internal: Invalid output file type (%d)", f->btype);
	de_fatalerror(f->c);
}
Exemplo n.º 10
0
// Create or open a file for writing, that is *not* one of the usual
// "output.000.ext" files we extract from the input file.
//
// overwrite_mode, flags: Same as for de_fopen_for_write().
//
// On failure, prints an error message, and sets f->btype to DBUF_TYPE_NULL.
dbuf *dbuf_create_unmanaged_file(deark *c, const char *fname, int overwrite_mode,
	unsigned int flags)
{
	dbuf *f;
	char msgbuf[200];

	f = de_malloc(c, sizeof(dbuf));
	f->c = c;
	f->is_managed = 0;
	f->name = de_strdup(c, fname);

	f->btype = DBUF_TYPE_OFILE;
	f->max_len_hard = c->max_output_file_size;
	f->fp = de_fopen_for_write(c, f->name, msgbuf, sizeof(msgbuf),
		c->overwrite_mode, flags);

	if(!f->fp) {
		de_err(c, "Failed to write %s: %s", f->name, msgbuf);
		f->btype = DBUF_TYPE_NULL;
	}

	return f;
}
Exemplo n.º 11
0
static int do_page(deark *c, lctx *d, int pagenum, de_int64 pos1)
{
	struct page_ctx *pg = NULL;
	int retval = 0;

	pg = de_malloc(c, sizeof(struct page_ctx));

	pg->fmt = identify_fmt(c, pos1);
	d->last_fmt = pg->fmt;
	pg->fmt_name = get_fmt_name(pg->fmt);
	if(pg->fmt==0) {
		de_err(c, "Not PNM/PAM format\n");
		goto done;
	}

	if(pagenum==0) {
		de_declare_fmt(c, pg->fmt_name);
	}

	if(pg->fmt==FMT_PAM) {
		if(!read_pam_header(c, d, pg, pos1)) goto done;
	}
	else {
		if(!read_pnm_header(c, d, pg, pos1)) goto done;
	}

	if(!do_image(c, d, pg, pg->hdr_parse_pos)) {
		goto done;
	}

	d->last_bytesused = (pg->hdr_parse_pos + pg->image_data_len) - pos1;

	retval = 1;
done:
	de_free(c, pg);
	return retval;
}
Exemplo n.º 12
0
Arquivo: ogg.c Projeto: jsummers/deark
static void run_ogg_internal(deark *c, lctx *d)
{
	i64 pos;
	i64 ogg_end;
	struct de_id3info id3i;

	d->always_hexdump = de_get_ext_option(c, "ogg:hexdump")?1:0;
	d->streamtable = de_inthashtable_create(c);

	de_fmtutil_handle_id3(c, c->infile, &id3i, 0);
	pos = id3i.main_start;
	ogg_end = id3i.main_end;

	while(1) {
		u32 sig;
		int ret;
		i64 bytes_consumed = 0;

		if(pos >= ogg_end) break;
		sig = (u32)de_getu32be(pos);
		if(sig!=0x04f676753U) {
			de_err(c, "Ogg page signature not found at %"I64_FMT, pos);
			break;
		}
		de_dbg(c, "page at %"I64_FMT, pos);
		de_dbg_indent(c, 1);
		ret = do_ogg_page(c, d, pos, &bytes_consumed);
		de_dbg_indent(c, -1);
		if(!ret || bytes_consumed<=4) break;
		pos += bytes_consumed;
		d->total_page_count++;
	}

	if(!d->format_declared) declare_ogg_format(c, d);

	de_dbg(c, "number of bitstreams: %d", (int)d->bitstream_count);
}
Exemplo n.º 13
0
static int do_box(deark *c, struct de_boxesctx *bctx, i64 pos, i64 len,
	int level, i64 *pbytes_consumed)
{
	i64 size32, size64;
	i64 header_len; // Not including UUIDs
	i64 payload_len; // Including UUIDs
	i64 total_len;
	struct de_fourcc box4cc;
	char uuid_string[50];
	int ret;
	int retval = 0;
	struct de_boxdata *parentbox;
	struct de_boxdata *curbox;

	parentbox = bctx->curbox;
	bctx->curbox = de_malloc(c, sizeof(struct de_boxdata));
	curbox = bctx->curbox;
	curbox->parent = parentbox;

	if(len<8) {
		de_dbg(c, "(ignoring %d extra bytes at %"I64_FMT")", (int)len, pos);
		goto done;
	}

	size32 = dbuf_getu32be(bctx->f, pos);
	dbuf_read_fourcc(bctx->f, pos+4, &box4cc, 4, 0x0);
	curbox->boxtype = box4cc.id;

	if(size32>=8) {
		header_len = 8;
		payload_len = size32-8;
	}
	else if(size32==0) {
		header_len = 8;
		payload_len = len-8;
	}
	else if(size32==1) {
		if(len<16) {
			de_dbg(c, "(ignoring %d extra bytes at %"I64_FMT")", (int)len, pos);
			goto done;
		}
		header_len = 16;
		size64 = dbuf_geti64be(bctx->f, pos+8);
		if(size64<16) goto done;
		payload_len = size64-16;
	}
	else {
		de_err(c, "Invalid or unsupported box format");
		goto done;
	}

	total_len = header_len + payload_len;

	if(curbox->boxtype==DE_BOX_uuid && payload_len>=16) {
		curbox->is_uuid = 1;
		dbuf_read(bctx->f, curbox->uuid, pos+header_len, 16);
	}

	curbox->level = level;
	curbox->box_pos = pos;
	curbox->box_len = total_len;
	curbox->payload_pos = pos+header_len;
	curbox->payload_len = payload_len;
	if(curbox->is_uuid) {
		curbox->payload_pos += 16;
		curbox->payload_len -= 16;
	}

	if(bctx->identify_box_fn) {
		bctx->identify_box_fn(c, bctx);
	}

	if(c->debug_level>0) {
		char name_str[80];

		if(curbox->box_name) {
			de_snprintf(name_str, sizeof(name_str), " (%s)", curbox->box_name);
		}
		else {
			name_str[0] = '\0';
		}

		if(curbox->is_uuid) {
			de_fmtutil_render_uuid(c, curbox->uuid, uuid_string, sizeof(uuid_string));
			de_dbg(c, "box '%s'{%s}%s at %"I64_FMT", len=%"I64_FMT,
				box4cc.id_dbgstr, uuid_string, name_str,
				pos, total_len);
		}
		else {
			de_dbg(c, "box '%s'%s at %"I64_FMT", len=%"I64_FMT", dlen=%"I64_FMT,
				box4cc.id_dbgstr, name_str, pos,
				total_len, payload_len);
		}
	}

	if(total_len > len) {
		de_err(c, "Invalid oversized box, or unexpected end of file "
			"(box at %"I64_FMT" ends at %"I64_FMT", "
			"parent ends at %"I64_FMT")",
			pos, pos+total_len, pos+len);
		goto done;
	}

	de_dbg_indent(c, 1);
	ret = bctx->handle_box_fn(c, bctx);
	de_dbg_indent(c, -1);
	if(!ret) goto done;

	if(curbox->is_superbox) {
		i64 children_pos, children_len;
		i64 max_nchildren;

		de_dbg_indent(c, 1);
		children_pos = pos+header_len + curbox->extra_bytes_before_children;
		children_len = payload_len - curbox->extra_bytes_before_children;
		max_nchildren = (curbox->num_children_is_known) ? curbox->num_children : -1;
		do_box_sequence(c, bctx, children_pos, children_len, max_nchildren, level+1);
		de_dbg_indent(c, -1);
	}

	*pbytes_consumed = total_len;
	retval = 1;

done:
	de_free(c, bctx->curbox);
	bctx->curbox = parentbox; // Restore the curbox pointer
	return retval;
}
Exemplo n.º 14
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;
}
Exemplo n.º 15
0
static void de_run_alphabmp(deark *c, de_module_params *mparams)
{
	unsigned int flags;
	lctx *d = NULL;
	i64 pos;
	i64 palsize;
	dbuf *unc_pixels = NULL;
	int saved_indent_level;

	de_dbg_indent_save(c, &saved_indent_level);

	d = de_malloc(c, sizeof(lctx));
	de_declare_fmt(c, "Alpha Microsystems BMP");

	pos = 10;

	de_dbg(c, "bitmap image definition block at %d", (int)pos);
	de_dbg_indent(c, 1);

	d->w = de_getu16le(pos);
	d->h = de_getu16le(pos+2);
	de_dbg_dimensions(c, d->w, d->h);
	if(!de_good_image_dimensions(c, d->w, d->h)) goto done;

	d->bpp = de_getu16le(pos+4);
	de_dbg(c, "bits/pixel: %d", (int)d->bpp);

	flags = (unsigned int)de_getu16le(pos+6);
	d->has_palette = flags & 0x01;
	d->palette_is_hls = (flags>>1) & 0x01;
	de_dbg(c, "has-palette: %d", (int)d->has_palette);
	if(d->has_palette)
		de_dbg(c, "palette-is-HLS: %d", (int)d->palette_is_hls);

	d->compression = de_getu16le(pos+8);
	de_dbg(c, "compression: %d", (int)d->compression);
	de_dbg_indent(c, -1);

	pos += 70;

	if(d->has_palette) {
		if(d->palette_is_hls && d->bpp<=8) {
			de_err(c, "HLS palettes are not supported");
			goto done;
		}
		if(!do_read_palette(c, d, pos, &palsize)) goto done;
		pos += palsize;
	}
	else if(d->bpp<=8) {
		de_err(c, "Paletted images without an embedded palette are not supported");
		goto done;
	}

	de_dbg(c, "bitmap at %d", (int)pos);
	de_dbg_indent(c, 1);

	if(d->compression) {
		unc_pixels = dbuf_create_membuf(c, 32768, 0);
		if(!do_uncompress_image(c, d, pos, unc_pixels)) goto done;
	}
	else {
		unc_pixels = dbuf_open_input_subfile(c->infile, pos, c->infile->len - pos);
	}

	if(d->bpp!=1 && d->bpp!=4 && d->bpp!=8 && d->bpp!=24) {
		de_err(c, "%d bits/pixel is not supported", (int)d->bpp);
		goto done;
	}

	do_bitmap(c, d, unc_pixels);
	de_dbg_indent(c, -1);

done:
	de_dbg_indent_restore(c, saved_indent_level);
	dbuf_close(unc_pixels);
	de_free(c, d);
}
Exemplo n.º 16
0
static void de_run_unifont_hex(deark *c, de_module_params *mparams)
{
	struct de_bitmap_font *font = NULL;
	i64 char_array_numalloc = 0;
	char linebuf[256];
	struct de_linereader *lr = NULL;
	int ok = 0;

	font = de_create_bitmap_font(c);
	font->has_unicode_codepoints = 1;
	font->prefer_unicode = 1;
	font->nominal_height = 16;
	char_array_numalloc = 1024;
	font->char_array = de_mallocarray(c, char_array_numalloc, sizeof(struct de_bitmap_font_char));

	lr = de_linereader_create(c, c->infile);

	while(de_linereader_readnextline(c, lr, linebuf, sizeof(linebuf), 0)) {
		i64 idx;
		struct de_bitmap_font_char *ch;
		i64 fdata_len;
		char *dptr; // Pointer into linebuf, to the char after the ":"

		if(font->num_chars>=17*65536) goto done;

		idx = font->num_chars;
		if(idx >= char_array_numalloc) {
			i64 new_numalloc = char_array_numalloc*2;
			font->char_array = de_reallocarray(c, font->char_array,
				char_array_numalloc, sizeof(struct de_bitmap_font_char),
				new_numalloc);
			char_array_numalloc = new_numalloc;
		}
		ch = &font->char_array[idx];

		dptr = de_strchr(linebuf, ':');
		if(!dptr) goto done;
		*dptr = '\0';
		dptr++;

		fdata_len = (i64)de_strlen(dptr);
		ch->codepoint_unicode = (i32)de_strtoll(linebuf, NULL, 16);
		if(ch->codepoint_unicode<0 || ch->codepoint_unicode>=17*65536) goto done;

		ch->width = (int)((fdata_len/32)*8);
		ch->height = 16;
		de_dbg2(c, "char[%d] U+%04X %d"DE_CHAR_TIMES"%d",
			(int)font->num_chars, (unsigned int)ch->codepoint_unicode,
			ch->width, ch->height);
		if(ch->width<8 || ch->width>32) goto done;
		ch->rowspan = (ch->width+7)/8;
		ch->bitmap = de_malloc(c, ch->rowspan * ch->height);
		decode_fontdata(c, dptr, ch);

		font->num_chars++;
		if(ch->width > font->nominal_width) {
			font->nominal_width = ch->width;
		}
	}

	de_dbg(c, "number of characters: %d", (int)font->num_chars);
	if(font->num_chars<1) goto done;
	if(font->nominal_width<1) goto done;

	de_font_bitmap_font_to_image(c, font, NULL, 0);
	ok = 1;

done:
	if(!ok) {
		de_err(c, "Error parsing HEX font file (offset %"I64_FMT")", lr->f_pos);
	}
	de_linereader_destroy(c, lr);
	if(font) {
		if(font->char_array) {
			i64 k;
			for(k=0; k<font->num_chars; k++) {
				de_free(c, font->char_array[k].bitmap);
			}
			de_free(c, font->char_array);
		}
		font->char_array = NULL;
		de_destroy_bitmap_font(c, font);
	}
}
Exemplo n.º 17
0
// Read any version of BITMAPINFOHEADER.
//
// Note: Some of this BMP parsing code is duplicated in the
// de_fmtutil_get_bmpinfo() library function. The BMP module's needs are
// not quite aligned with what that function is intended for, and it
// would be too messy to try to add the necessary features to it.
static int read_infoheader(deark *c, lctx *d, de_int64 pos)
{
	de_int64 height_raw;
	de_int64 clr_used_raw;
	int cmpr_ok;
	int retval = 0;

	de_dbg(c, "info header at %d\n", (int)pos);
	de_dbg_indent(c, 1);
	de_dbg(c, "info header size: %d\n", (int)d->infohdrsize);

	if(d->version==DE_BMPVER_OS2V1) {
		d->width = de_getui16le(pos+4);
		d->height = de_getui16le(pos+6);
	}
	else {
		d->width = dbuf_geti32le(c->infile, pos+4);
		height_raw = dbuf_geti32le(c->infile, pos+8);
		if(height_raw<0) {
			d->top_down = 1;
			d->height = -height_raw;
		}
		else {
			d->height = height_raw;
		}
	}
	de_dbg(c, "dimensions: %dx%d\n", (int)d->width, (int)d->height);
	if(!de_good_image_dimensions(c, d->width, d->height)) {
		goto done;
	}
	if(d->top_down) {
		de_dbg(c, "orientation: top-down\n");
	}

	// Already read, in detect_bmp_version()
	de_dbg(c, "bits/pixel: %d\n", (int)d->bitcount);

	if(d->bitcount!=0 && d->bitcount!=1 && d->bitcount!=2 && d->bitcount!=4 &&
		d->bitcount!=8 && d->bitcount!=16 && d->bitcount!=24 && d->bitcount!=32)
	{
		de_err(c, "Bad bits/pixel: %d\n", (int)d->bitcount);
		goto done;
	}

	if(d->version==DE_BMPVER_OS2V1) {
		d->bytes_per_pal_entry = 3;
	}
	else {
		// Already read, in detect_bmp_version()
		de_dbg(c, "compression (etc.): %d\n", (int)d->compression_field);
		d->bytes_per_pal_entry = 4;
	}

	d->compression_type = CMPR_NONE; // Temporary default

	cmpr_ok = 0;
	switch(d->compression_field) {
	case 0: // BI_RGB
		if(d->bitcount==16 || d->bitcount==32) {
			d->bitfields_type = BF_DEFAULT;
		}
		d->compression_type = CMPR_NONE;
		cmpr_ok = 1;
		break;
	case 1: // BI_RLE8
		d->compression_type=CMPR_RLE8;
		cmpr_ok = 1;
		break;
	case 2: // BI_RLE4
		d->compression_type=CMPR_RLE4;
		cmpr_ok = 1;
		break;
	case 3: // BI_BITFIELDS or Huffman_1D
		if(d->version==DE_BMPVER_OS2V2) {
			if(d->bitcount==1) {
				d->compression_type=CMPR_HUFFMAN1D;
				cmpr_ok = 1;
			}
		}
		else if(d->bitcount==16 || d->bitcount==32) {
			d->compression_type = CMPR_NONE;
			cmpr_ok = 1;
			if(d->infohdrsize>=52) {
				d->bitfields_type = BF_IN_HEADER;
			}
			else {
				d->bitfields_type = BF_SEGMENT;
				d->bitfields_segment_len = 12;
			}
		}
		break;
	case 4: // BI_JPEG or RLE24
		if(d->version==DE_BMPVER_OS2V2) {
			if(d->bitcount==24) {
				d->compression_type=CMPR_RLE24;
				cmpr_ok = 1;
			}
		}
		else {
			d->compression_type=CMPR_JPEG;
			cmpr_ok = 1;
		}
		break;
	case 5: // BI_PNG
		d->compression_type=CMPR_PNG;
		cmpr_ok = 1;
		break;
	case 6: // BI_ALPHABITFIELDS
		if(d->bitcount==16 || d->bitcount==32) {
			d->compression_type = CMPR_NONE;
			cmpr_ok = 1;
			if(d->infohdrsize>=56) {
				d->bitfields_type = BF_IN_HEADER;
			}
			else {
				d->bitfields_type = BF_SEGMENT;
				d->bitfields_segment_len = 16;
			}
		}
		break;
	}

	if(!cmpr_ok) {
		de_err(c, "Unsupported compression type: %d\n", (int)d->compression_field);
		goto done;
	}

	if(d->infohdrsize>=24) {
		d->size_image = de_getui32le(pos+20);
		de_dbg(c, "biSizeImage: %d\n", (int)d->size_image);
	}

	if(d->infohdrsize>=32) {
		d->xpelspermeter = dbuf_geti32le(c->infile, pos+24);
		d->ypelspermeter = dbuf_geti32le(c->infile, pos+28);
		de_dbg(c, "density: %dx%d pixels/meter\n", (int)d->xpelspermeter, (int)d->ypelspermeter);
	}

	if(d->infohdrsize>=36)
		clr_used_raw = de_getui32le(pos+32);
	else
		clr_used_raw = 0;

	if(d->bitcount>=1 && d->bitcount<=8 && clr_used_raw==0) {
		d->pal_entries = ((de_int64)1)<<d->bitcount;
	}
	else {
		d->pal_entries = clr_used_raw;
	}
	de_dbg(c, "number of palette colors: %d\n", (int)d->pal_entries);

	// Note that after 40 bytes, WINV345 and OS2V2 header fields are different,
	// so we have to pay more attention to the version.

	if(d->bitfields_type==BF_IN_HEADER) {
		do_read_bitfields(c, d, pos+40, d->infohdrsize>=56 ? 16 : 12);
	}

	if(d->bitfields_type==BF_DEFAULT) {
		set_default_bitfields(c, d);
	}

	if(d->version==DE_BMPVER_WINV345 && d->infohdrsize>=108) {
		dbuf_read_fourcc(c->infile, pos+56, &d->cstype4cc, 1);
		de_dbg(c, "CSType: 0x%08x ('%s')\n", (unsigned int)d->cstype4cc.id,
			d->cstype4cc.id_printable);
	}

	if(d->version==DE_BMPVER_WINV345 && d->infohdrsize>=124 &&
		(d->cstype4cc.id==CODE_MBED || d->cstype4cc.id==CODE_LINK))
	{
		d->profile_offset_raw = de_getui32le(pos+112);
		de_dbg(c, "profile offset: %d+%d\n", FILEHEADER_SIZE,
			(int)d->profile_offset_raw);
		d->profile_size = de_getui32le(pos+116);
		de_dbg(c, "profile size: %d\n", (int)d->profile_size);
	}

	retval = 1;
done:
	de_dbg_indent(c, -1);
	return retval;
}
Exemplo n.º 18
0
void de_run(deark *c)
{
	dbuf *orig_ifile = NULL;
	dbuf *subfile = NULL;
	de_int64 subfile_size;
	struct deark_module_info *module_to_use = NULL;
	const char *friendly_infn;

	if(c->modhelp_req && c->input_format_req) {
		do_modhelp(c);
		goto done;
	}

	if(c->input_style==DE_INPUTSTYLE_STDIN) {
		friendly_infn = "[stdin]";
	}
	else {
		friendly_infn = c->input_filename;
	}

	if(!friendly_infn) {
		de_err(c, "Input file not set\n");
		de_fatalerror(c);
		return;
	}

	de_register_modules(c);

	if(c->input_format_req) {
		module_to_use = de_get_module_by_id(c, c->input_format_req);
		if(!module_to_use) {
			de_err(c, "Unknown module \"%s\"\n", c->input_format_req);
			goto done;
		}
	}

	if(c->slice_size_req_valid) {
		de_dbg(c, "Input file: %s[%d,%d]\n", friendly_infn,
			(int)c->slice_start_req, (int)c->slice_size_req);
	}
	else if(c->slice_start_req) {
		de_dbg(c, "Input file: %s[%d]\n", friendly_infn,
			(int)c->slice_start_req);
	}
	else {
		de_dbg(c, "Input file: %s\n", friendly_infn);
	}

	if(c->input_style==DE_INPUTSTYLE_STDIN) {
		orig_ifile = dbuf_open_input_stdin(c, c->input_filename);
	}
	else {
		orig_ifile = dbuf_open_input_file(c, c->input_filename);
	}
	if(!orig_ifile) {
		goto done;
	}

	c->infile = orig_ifile;

	// If we are only supposed to look at a segment of the original file,
	// do that by creating a child dbuf, using dbuf_open_input_subfile().
	if(c->slice_start_req>0 || c->slice_size_req_valid) {
		if(c->slice_size_req_valid)
			subfile_size = c->slice_size_req;
		else
			subfile_size = dbuf_get_length(c->infile) - c->slice_start_req;
		subfile = dbuf_open_input_subfile(c->infile, c->slice_start_req, subfile_size);
		c->infile = subfile;
	}

	if(!module_to_use) {
		module_to_use = detect_module_for_file(c);
	}

	if(!module_to_use) {
		if(c->infile->len==0)
			de_err(c, "Unknown or unsupported file format (empty file)\n");
		else
			de_err(c, "Unknown or unsupported file format\n");
		goto done;
	}

	de_msg(c, "Module: %s\n", module_to_use->id);
	if(module_to_use->flags&DE_MODFLAG_NONWORKING) {
		de_warn(c, "The %s module is considered to be incomplete, and may "
			"not work properly. Caveat emptor.\n",
			module_to_use->id);
	}
	de_dbg2(c, "file size: %" INT64_FMT "\n", c->infile->len);

	if(!de_run_module(c, module_to_use, NULL)) {
		goto done;
	}

	// The DE_MODFLAG_NOEXTRACT flag means the module is not expected to extract
	// any files.
	if(c->num_files_extracted==0 && c->error_count==0 &&
		!(module_to_use->flags&DE_MODFLAG_NOEXTRACT))
	{
		de_msg(c, "No files found to extract!\n");
	}

done:
	if(subfile) dbuf_close(subfile);
	if(orig_ifile) dbuf_close(orig_ifile);
}
Exemplo n.º 19
0
static void do_icon(deark *c, lctx *d, struct page_ctx *pg)
{
	de_int64 expected_image_size;
	int is_compressed;

	if(!pg->type_info) return; // Shouldn't happen.

	de_strlcpy(pg->filename_token, "", sizeof(pg->filename_token));

	if(pg->type_info->image_type==IMGTYPE_MASK) {
		de_dbg(c, "transparency mask\n");
		return;
	}

	if(pg->type_info->image_type==IMGTYPE_EMBEDDED_FILE) {
		de_snprintf(pg->filename_token, sizeof(pg->filename_token), "%dx%d",
			(int)pg->type_info->width, (int)pg->type_info->height);
		do_extract_png_or_jp2(c, d, pg);
		return;
	}

	if(pg->type_info->image_type!=IMGTYPE_IMAGE &&
		pg->type_info->image_type!=IMGTYPE_IMAGE_AND_MASK)
	{
		return;
	}

	// At this point we know it's a regular image (or an image+mask)

	// Note - This pg->rowspan is arguably incorrect for 24-bit images, since
	// rows aren't stored contiguously.
	pg->rowspan = ((pg->type_info->bpp * pg->type_info->width)+7)/8;

	expected_image_size = pg->rowspan * pg->type_info->height;
	if(pg->type_info->image_type==IMGTYPE_IMAGE_AND_MASK) {
		expected_image_size *= 2;
	}

	is_compressed = (pg->type_info->bpp==24) ? 1 : 0;

	if(!is_compressed) {
		if(pg->image_len < expected_image_size) {
			de_err(c, "(Image #%d) Premature end of image (expected %d bytes, found %d)\n",
				pg->image_num, (int)expected_image_size, (int)pg->image_len);
			return;
		}
		if(pg->image_len > expected_image_size) {
			de_warn(c, "(Image #%d) Extra image data found (expected %d bytes, found %d)\n",
				pg->image_num, (int)expected_image_size, (int)pg->image_len);
		}
	}

	find_mask(c, d, pg);

	de_snprintf(pg->filename_token, sizeof(pg->filename_token), "%dx%dx%d",
		(int)pg->type_info->width, (int)pg->type_info->height, (int)pg->type_info->bpp);

	de_dbg(c, "image dimensions: %dx%d, bpp: %d\n",
		pg->type_info->width, pg->type_info->height, pg->type_info->bpp);

	if(pg->type_info->bpp==1 || pg->type_info->bpp==4 || pg->type_info->bpp==8) {
		do_decode_1_4_8bit(c, d, pg);
		return;
	}
	else if(pg->type_info->bpp==24) {
		do_decode_24bit(c, d, pg);
		return;
	}

	de_warn(c, "(Image #%d) Image type '%s' is not supported\n", pg->image_num, pg->code4cc.id_printable);
}
Exemplo n.º 20
0
static void de_run_gemraster(deark *c, de_module_params *mparams)
{
	i64 ver;
	i64 ext_word0 = 0;
	lctx *d = NULL;
	int need_format_warning = 0;
	int saved_indent_level;

	de_dbg_indent_save(c, &saved_indent_level);
	d = de_malloc(c, sizeof(lctx));

	de_dbg(c, "header (base part) at %d", 0);
	de_dbg_indent(c, 1);
	ver = de_getu16be(0);
	de_dbg(c, "version: %d", (int)ver);
	d->header_size_in_words = de_getu16be(2);
	d->header_size_in_bytes = d->header_size_in_words*2;
	de_dbg(c, "header size: %d words (%d bytes)", (int)d->header_size_in_words,
		(int)d->header_size_in_bytes);
	d->nplanes = de_getu16be(4);
	de_dbg(c, "planes: %d", (int)d->nplanes);

	if(d->header_size_in_words>=11) {
		d->is_ximg = !dbuf_memcmp(c->infile, 16, "XIMG", 4);
	}

	d->patlen = de_getu16be(6);
	de_dbg(c, "pattern def len: %d", (int)d->patlen);
	d->pixwidth = de_getu16be(8);
	d->pixheight = de_getu16be(10);
	de_dbg(c, "pixel size: %d"DE_CHAR_TIMES"%d microns", (int)d->pixwidth, (int)d->pixheight);
	d->w = de_getu16be(12);
	d->h = de_getu16be(14);
	de_dbg_dimensions(c, d->w, d->h);
	de_dbg_indent(c, -1);

	if(d->header_size_in_words>=9) {
		// This may help to detect the image format.
		ext_word0 = de_getu16be(16);
	}

	if(ver>2) {
		de_err(c, "This version of GEM Raster (%d) is not supported.", (int)ver);
		goto done;
	}

	if(d->is_ximg) {
		de_declare_fmt(c, "GEM VDI Bit Image, XIMG extension");
	}
	else if(d->header_size_in_words==25 && d->patlen==2 && ext_word0==0x0080) {
		de_declare_fmt(c, "GEM VDI Bit Image, Hyperpaint extension");
	}
	else if(d->header_size_in_words==8 && d->nplanes==1) {
		;
	}
	else if(d->header_size_in_words==8 && (d->nplanes>=2 && d->nplanes<=8)) {
		need_format_warning = 1;
	}
	else if(d->header_size_in_words==9 && (d->nplanes>=1 && d->nplanes<=8)) {
		need_format_warning = 1;
	}
	else {
		if(d->header_size_in_words==27 && ext_word0==0x5354) {
			de_declare_fmt(c, "GEM VDI Bit Image, STTT extension");
		}
		de_err(c, "This version of GEM Raster is not supported.");
		goto done;
	}

	if(need_format_warning) {
		de_warn(c, "This type of GEM Raster image is not very portable, and might "
			"not be handled correctly.");
	}

	if(!de_good_image_dimensions(c, d->w, d->h)) goto done;

	d->rowspan_per_plane = (d->w+7)/8;
	d->rowspan_total = d->rowspan_per_plane * d->nplanes;

	// If we haven't declared the format yet, do so.
	de_declare_fmt(c, "GEM VDI Bit Image");

	if(d->is_ximg) {
		do_gem_ximg(c, d);
	}
	else if(d->header_size_in_words==25) {
		do_gem_ximg(c, d);
	}
	else {
		do_gem_img(c, d);
	}

done:
	de_dbg_indent_restore(c, saved_indent_level);
	de_free(c, d);
}
Exemplo n.º 21
0
Arquivo: rpm.c Projeto: jsummers/deark
// Note that a header *structure* is distinct from the header *section*.
// Both the signature section and the header section use a header structure.
static int do_header_structure(deark *c, lctx *d, int is_sig, i64 pos1,
	i64 *section_size)
{
	i64 pos;
	i64 indexcount;
	i64 storesize;
	u8 buf[4];
	u8 header_ver;
	i64 i;
	i64 tag_id, tag_type, tag_offset, tag_count;
	i64 data_store_pos;
	const char *hdrname;
	int retval = 0;

	hdrname = is_sig?"sig":"hdr";
	pos = pos1;
	de_dbg(c, "%s section at %d", hdrname, (int)pos1);
	de_dbg_indent(c, 1);

	de_read(buf, pos, 4);
	if(buf[0]!=0x8e || buf[1]!=0xad || buf[2]!=0xe8) {
		de_err(c, "Bad header signature at %d", (int)pos);
		goto done;
	}
	header_ver = buf[3];
	if(header_ver != 1) {
		de_err(c, "Unsupported header version");
		goto done;
	}
	pos += 8;

	indexcount = de_getu32be(pos);
	storesize = de_getu32be(pos+4);
	de_dbg(c, "%s: pos=%d indexcount=%d storesize=%d", hdrname,
		(int)pos, (int)indexcount, (int)storesize);
	pos += 8;

	if(indexcount>1000) goto done;

	data_store_pos = pos + 16*indexcount;

	de_dbg(c, "%s: tag table at %d", hdrname, (int)pos);
	de_dbg_indent(c, 1);

	for(i=0; i<indexcount; i++) {
		tag_id = de_getu32be(pos);
		tag_type = de_getu32be(pos+4);
		tag_offset = de_getu32be(pos+8);
		tag_count = de_getu32be(pos+12);

		de_dbg2(c, "tag #%d type=%d offset=%d count=%d", (int)tag_id,
			(int)tag_type, (int)tag_offset, (int)tag_count);


		if(is_sig==0 && tag_id==DE_RPMTAG_PAYLOADCOMPRESSOR && tag_type==DE_RPM_STRING_TYPE) {
			read_compression_type(c, d, data_store_pos+tag_offset);
		}
		else if(is_sig==0 && tag_id==DE_RPMTAG_NAME && tag_type==DE_RPM_STRING_TYPE) {
			if(!d->name_srd) {
				d->name_srd = dbuf_read_string(c->infile, data_store_pos+tag_offset,
					DE_DBG_MAX_STRLEN, DE_DBG_MAX_STRLEN,
					DE_CONVFLAG_STOP_AT_NUL, DE_ENCODING_ASCII);
				de_dbg(c, "name: \"%s\"", ucstring_getpsz(d->name_srd->str));
			}
		}
		else if(is_sig==0 && tag_id==DE_RPMTAG_VERSION && tag_type==DE_RPM_STRING_TYPE) {
			if(!d->version_srd) {
				d->version_srd = dbuf_read_string(c->infile, data_store_pos+tag_offset,
					DE_DBG_MAX_STRLEN, DE_DBG_MAX_STRLEN,
					DE_CONVFLAG_STOP_AT_NUL, DE_ENCODING_ASCII);
				de_dbg(c, "version: \"%s\"", ucstring_getpsz(d->version_srd->str));
			}
		}
		else if(is_sig==0 && tag_id==DE_RPMTAG_RELEASE && tag_type==DE_RPM_STRING_TYPE) {
			if(!d->release_srd) {
				d->release_srd = dbuf_read_string(c->infile, data_store_pos+tag_offset,
					DE_DBG_MAX_STRLEN, DE_DBG_MAX_STRLEN,
					DE_CONVFLAG_STOP_AT_NUL, DE_ENCODING_ASCII);
				de_dbg(c, "release: \"%s\"", ucstring_getpsz(d->release_srd->str));
			}
		}

		pos += 16;
	}

	de_dbg_indent(c, -1);

	pos = data_store_pos;
	de_dbg(c, "%s: data store at %d", hdrname, (int)pos);
	pos += storesize;

	*section_size = pos - pos1;
	retval = 1;
done:
	de_dbg_indent(c, -1);
	return retval;
}
Exemplo n.º 22
0
dbuf *dbuf_create_output_file(deark *c, const char *ext, de_finfo *fi,
	unsigned int createflags)
{
	char nbuf[500];
	char msgbuf[200];
	dbuf *f;
	const char *basefn;
	int file_index;
	u8 is_directory = 0;
	char *name_from_finfo = NULL;
	i64 name_from_finfo_len = 0;

	if(ext && fi && fi->original_filename_flag) {
		de_dbg(c, "[internal warning: Incorrect use of create_output_file]");
	}

	f = de_malloc(c, sizeof(dbuf));
	f->c = c;
	f->max_len_hard = c->max_output_file_size;
	f->is_managed = 1;

	if(fi && fi->is_directory) {
		is_directory = 1;
	}

	if(is_directory && !c->keep_dir_entries) {
		de_dbg(c, "skipping 'directory' file");
		f->btype = DBUF_TYPE_NULL;
		goto done;
	}

	if(c->extract_policy==DE_EXTRACTPOLICY_MAINONLY) {
		if(createflags&DE_CREATEFLAG_IS_AUX) {
			de_dbg(c, "skipping 'auxiliary' file");
			f->btype = DBUF_TYPE_NULL;
			goto done;
		}
	}
	else if(c->extract_policy==DE_EXTRACTPOLICY_AUXONLY) {
		if(!(createflags&DE_CREATEFLAG_IS_AUX)) {
			de_dbg(c, "skipping 'main' file");
			f->btype = DBUF_TYPE_NULL;
			goto done;
		}
	}

	file_index = c->file_count;
	c->file_count++;

	basefn = c->base_output_filename ? c->base_output_filename : "output";

	if(fi && ucstring_isnonempty(fi->file_name_internal)) {
		name_from_finfo_len = 1 + ucstring_count_utf8_bytes(fi->file_name_internal);
		name_from_finfo = de_malloc(c, name_from_finfo_len);
		ucstring_to_sz(fi->file_name_internal, name_from_finfo, (size_t)name_from_finfo_len, 0,
			DE_ENCODING_UTF8);
	}

	if(c->output_style==DE_OUTPUTSTYLE_ARCHIVE && !c->base_output_filename &&
		fi && fi->is_directory &&
		(fi->is_root_dir || (fi->detect_root_dot_dir && fi->orig_name_was_dot)))
	{
		de_strlcpy(nbuf, ".", sizeof(nbuf));
	}
	else if(c->output_style==DE_OUTPUTSTYLE_ARCHIVE && !c->base_output_filename &&
		fi && fi->original_filename_flag && name_from_finfo)
	{
		// TODO: This is a "temporary" hack to allow us to, when both reading from
		// and writing to an archive format, use some semblance of the correct
		// filename (instead of "output.xxx.yyy").
		// There are some things that we don't handle optimally, such as
		// subdirectories.
		// A major redesign of the file naming logic would be good.
		de_strlcpy(nbuf, name_from_finfo, sizeof(nbuf));
	}
	else {
		char fn_suffix[256];

		if(ext && name_from_finfo) {
			de_snprintf(fn_suffix, sizeof(fn_suffix), "%s.%s", name_from_finfo, ext);
		}
		else if(ext) {
			de_strlcpy(fn_suffix, ext, sizeof(fn_suffix));
		}
		else if(is_directory && name_from_finfo) {
			de_snprintf(fn_suffix, sizeof(fn_suffix), "%s.dir", name_from_finfo);
		}
		else if(name_from_finfo) {
			de_strlcpy(fn_suffix, name_from_finfo, sizeof(fn_suffix));
		}
		else if(is_directory) {
			de_strlcpy(fn_suffix, "dir", sizeof(fn_suffix));
		}
		else {
			de_strlcpy(fn_suffix, "bin", sizeof(fn_suffix));
		}

		de_snprintf(nbuf, sizeof(nbuf), "%s.%03d.%s", basefn, file_index, fn_suffix);
	}

	f->name = de_strdup(c, nbuf);

	if(fi) {
		// The finfo object passed to us at file creation is not required to
		// remain valid, so make a copy of anything in it that we might need
		// later.
		f->fi_copy = de_finfo_create(c);
		finfo_shallow_copy(c, fi, f->fi_copy);

		// Here's where we respect the -intz option, by using it to convert to
		// UTC in some cases.
		if(f->fi_copy->mod_time.is_valid && f->fi_copy->mod_time.tzcode==DE_TZCODE_LOCAL &&
			c->input_tz_offs_seconds!=0)
		{
			de_timestamp_cvt_to_utc(&f->fi_copy->mod_time, -c->input_tz_offs_seconds);
		}

		if(f->fi_copy->image_mod_time.is_valid && f->fi_copy->image_mod_time.tzcode==DE_TZCODE_LOCAL &&
			c->input_tz_offs_seconds!=0)
		{
			de_timestamp_cvt_to_utc(&f->fi_copy->image_mod_time, -c->input_tz_offs_seconds);
		}
	}

	if(file_index < c->first_output_file) {
		f->btype = DBUF_TYPE_NULL;
		goto done;
	}

	if(c->max_output_files>=0 &&
		file_index >= c->first_output_file + c->max_output_files)
	{
		f->btype = DBUF_TYPE_NULL;
		goto done;
	}

	c->num_files_extracted++;

	if(c->extrlist_dbuf) {
		dbuf_printf(c->extrlist_dbuf, "%s\n", f->name);
		dbuf_flush(c->extrlist_dbuf);
	}

	if(c->list_mode) {
		f->btype = DBUF_TYPE_NULL;
		if(c->list_mode_include_file_id) {
			de_msg(c, "%d:%s", file_index, f->name);
		}
		else {
			de_msg(c, "%s", f->name);
		}
		goto done;
	}

	if(c->output_style==DE_OUTPUTSTYLE_ARCHIVE && c->archive_fmt==DE_ARCHIVEFMT_TAR) {
		de_info(c, "Adding %s to TAR file", f->name);
		f->btype = DBUF_TYPE_ODBUF;
		// A dummy max_len_hard value. The parent will do the checking.
		f->max_len_hard = DE_DUMMY_MAX_FILE_SIZE;
		f->writing_to_tar_archive = 1;
		de_tar_start_member_file(c, f);
	}
	else if(c->output_style==DE_OUTPUTSTYLE_ARCHIVE) { // ZIP
		i64 initial_alloc;
		de_info(c, "Adding %s to ZIP file", f->name);
		f->btype = DBUF_TYPE_MEMBUF;
		f->max_len_hard = DE_MAX_MEMBUF_SIZE;
		if(is_directory) {
			// A directory entry is not expected to have any data associated
			// with it (besides the files it contains).
			initial_alloc = 16;
		}
		else {
			initial_alloc = 65536;
		}
		f->membuf_buf = de_malloc(c, initial_alloc);
		f->membuf_alloc = initial_alloc;
		f->write_memfile_to_zip_archive = 1;
	}
	else if(c->output_style==DE_OUTPUTSTYLE_STDOUT) {
		de_info(c, "Writing %s to [stdout]", f->name);
		f->btype = DBUF_TYPE_STDOUT;
		// TODO: Should we increase f->max_len_hard?
		f->fp = stdout;
	}
	else {
		de_info(c, "Writing %s", f->name);
		f->btype = DBUF_TYPE_OFILE;
		f->fp = de_fopen_for_write(c, f->name, msgbuf, sizeof(msgbuf),
			c->overwrite_mode, 0);

		if(!f->fp) {
			de_err(c, "Failed to write %s: %s", f->name, msgbuf);
			f->btype = DBUF_TYPE_NULL;
		}
	}

done:
	de_free(c, name_from_finfo);
	return f;
}
Exemplo n.º 23
0
// Read len bytes, starting at file position pos, into buf.
// Unread bytes will be set to 0.
void dbuf_read(dbuf *f, u8 *buf, i64 pos, i64 len)
{
	i64 bytes_read = 0;
	i64 bytes_to_read;
	deark *c;

	c = f->c;

	bytes_to_read = len;
	if(pos >= f->len) {
		bytes_to_read = 0;
	}
	else if(pos + bytes_to_read > f->len) {
		bytes_to_read = f->len - pos;
	}

	if(bytes_to_read<1) {
		goto done_read;
	}

	if(!f->cache && f->cache_policy==DE_CACHE_POLICY_ENABLED) {
		populate_cache(f);
	}

	// If the data we need is all cached, get it from cache.
	if(f->cache &&
		pos >= f->cache_start_pos &&
		pos + bytes_to_read <= f->cache_start_pos + f->cache_bytes_used)
	{
		de_memcpy(buf, &f->cache[pos - f->cache_start_pos], (size_t)bytes_to_read);
		bytes_read = bytes_to_read;
		goto done_read;
	}

	switch(f->btype) {
	case DBUF_TYPE_IFILE:
		if(!f->fp) {
			de_err(c, "Internal: File not open");
			de_fatalerror(c);
			return;
		}

		// For performance reasons, don't call fseek if we're already at the
		// right position.
		if(!f->file_pos_known || f->file_pos!=pos) {
			de_fseek(f->fp, pos, SEEK_SET);
		}

		bytes_read = fread(buf, 1, (size_t)bytes_to_read, f->fp);

		f->file_pos = pos + bytes_read;
		f->file_pos_known = 1;
		break;

	case DBUF_TYPE_IDBUF:
		// Recursive call to the parent dbuf.
		dbuf_read(f->parent_dbuf, buf, f->offset_into_parent_dbuf+pos, bytes_to_read);

		// The parent dbuf always writes 'bytes_to_read' bytes.
		bytes_read = bytes_to_read;
		break;

	case DBUF_TYPE_MEMBUF:
		de_memcpy(buf, &f->membuf_buf[pos], (size_t)bytes_to_read);
		bytes_read = bytes_to_read;
		break;

	default:
		de_err(c, "Internal: getbytes from this I/O type not implemented");
		de_fatalerror(c);
		return;
	}

done_read:
	// Zero out any requested bytes that were not read.
	if(bytes_read < len) {
		de_zeromem(buf+bytes_read, (size_t)(len - bytes_read));
	}
}
Exemplo n.º 24
0
Arquivo: tga.c Projeto: jsummers/deark
static void de_run_tga(deark *c, de_module_params *mparams)
{
	lctx *d = NULL;
	i64 pos;
	dbuf *unc_pixels = NULL;
	int saved_indent_level;
	i64 rowspan_tmp;

	de_dbg_indent_save(c, &saved_indent_level);
	d = de_malloc(c, sizeof(lctx));

	detect_file_format(c, d);

	if(d->file_format==FMT_VST) {
		de_declare_fmt(c, "TrueVista");
	}
	else {
		de_declare_fmt(c, "TGA");
	}

	pos = 0;

	if(d->file_format==FMT_VST) {
		if(!do_read_vst_headers(c, d)) goto done;
	}
	else {
		if(!do_read_tga_headers(c, d)) goto done;
	}
	pos += 18;

	if(d->id_field_len>0) {
		de_dbg(c, "image ID at %d (len=%d)", (int)pos, (int)d->id_field_len);
		pos += d->id_field_len;
	}

	if(d->color_map_type!=0) {
		d->bytes_per_pal_entry = (d->cmap_depth+7)/8;
		d->pal_size_in_bytes = d->cmap_length * d->bytes_per_pal_entry;
		de_dbg(c, "color map at %d (%d colors, %d bytes)", (int)pos,
			(int)d->cmap_length, (int)d->pal_size_in_bytes);

		de_dbg_indent(c, 1);
		if(!do_read_palette(c, d, pos)) goto done;
		de_dbg_indent(c, -1);

		pos += d->pal_size_in_bytes;
	}

	de_dbg(c, "bitmap at %d", (int)pos);
	de_dbg_indent(c, 1);

	d->bytes_per_pixel = ((d->pixel_depth+7)/8);
	if(d->pixel_depth==1) {
		rowspan_tmp = (d->main_image.width+7)/8;
	}
	else {
		rowspan_tmp = d->main_image.width * d->bytes_per_pixel;
	}
	d->main_image.img_size_in_bytes = d->main_image.height * rowspan_tmp;

	if(d->color_type!=TGA_CLRTYPE_PALETTE && d->color_type!=TGA_CLRTYPE_TRUECOLOR &&
		d->color_type!=TGA_CLRTYPE_GRAYSCALE)
	{
		de_err(c, "Unsupported color type (%d: %s)", (int)d->color_type, d->clrtype_name);
		goto done;
	}

	if( (d->color_type==TGA_CLRTYPE_PALETTE && d->pixel_depth==8) ||
		(d->color_type==TGA_CLRTYPE_TRUECOLOR && d->pixel_depth==15) ||
		(d->color_type==TGA_CLRTYPE_TRUECOLOR && d->pixel_depth==16) ||
		(d->color_type==TGA_CLRTYPE_TRUECOLOR && d->pixel_depth==24) ||
		(d->color_type==TGA_CLRTYPE_TRUECOLOR && d->pixel_depth==32) ||
		(d->color_type==TGA_CLRTYPE_GRAYSCALE && d->pixel_depth==1) ||
		(d->color_type==TGA_CLRTYPE_GRAYSCALE && d->pixel_depth==8) )
	{
		;
	}
	else {
		de_err(c, "Unsupported TGA image type (%s, depth=%d)", d->clrtype_name,
			(int)d->pixel_depth);
		goto done;
	}

	if(d->cmpr_type==TGA_CMPR_RLE) {
		if(d->pixel_depth<8) {
			de_err(c, "RLE compression not supported when depth (%d) is less than 8",
				(int)d->pixel_depth);
			goto done;
		}
		unc_pixels = dbuf_create_membuf(c, d->main_image.img_size_in_bytes, 1);
		if(!do_decode_rle(c, d, pos, unc_pixels)) goto done;
	}
	else if(d->cmpr_type==TGA_CMPR_NONE) {
		unc_pixels = dbuf_open_input_subfile(c->infile, pos, d->main_image.img_size_in_bytes);
	}
	else {
		de_err(c, "Unsupported compression type (%d, %s)", (int)d->cmpr_type, d->cmpr_name);
		goto done;
	}

	// Maybe scan the image, to help detect transparency.
	do_prescan_image(c, d, unc_pixels);

	if(d->pixel_depth==32) {
		de_dbg(c, "using alpha channel: %s", d->has_alpha_channel?"yes":"no");
	}

	// TODO: 16-bit images could theoretically have a transparency bit, but I don't
	// know how to detect that.

	do_decode_image(c, d, &d->main_image, unc_pixels, NULL, 0);

	de_dbg_indent(c, -1);

	if(d->thumbnail_offset!=0) {
		do_decode_thumbnail(c, d);
	}

done:
	dbuf_close(unc_pixels);
	de_dbg_indent_restore(c, saved_indent_level);
	de_free(c, d);
}
Exemplo n.º 25
0
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;
}
Exemplo n.º 26
0
void de_font_bitmap_font_to_image(deark *c, struct de_bitmap_font *font1, de_finfo *fi,
	unsigned int createflags)
{
	struct font_render_ctx *fctx = NULL;
	i64 i, j, k;
	de_bitmap *img = NULL;
	i64 xpos, ypos;
	i64 img_leftmargin, img_topmargin;
	i64 img_rightmargin, img_bottommargin;
	i64 img_vpixelsperchar;
	i64 img_width, img_height;
	i64 num_table_rows_to_display;
	i64 num_table_rows_total;
	i64 last_valid_row;
	struct de_bitmap_font *dfont = NULL;
	i64 chars_per_row = 32;
	const char *s;
	struct row_info_struct *row_info = NULL;
	struct col_info_struct *col_info = NULL;
	int unicode_req = 0;
	i64 label_stride;
	i64 rownum, colnum;
	i64 curpos;
	unsigned int dnflags;

	fctx = de_malloc(c, sizeof(struct font_render_ctx));
	fctx->font = font1;

	if(fctx->font->num_chars<1) goto done;
	if(fctx->font->num_chars>17*65536) goto done;
	if(fctx->font->nominal_width>512 || fctx->font->nominal_height>512) {
		de_err(c, "Font size too big (%d"DE_CHAR_TIMES"%d). Not supported.",
			(int)fctx->font->nominal_width, (int)fctx->font->nominal_height);
		goto done;
	}

	// -1 = "no preference"
	unicode_req = de_get_ext_option_bool(c, "font:tounicode", -1);

	if(unicode_req==0 &&
		(fctx->font->has_nonunicode_codepoints || !fctx->font->has_unicode_codepoints))
	{
		; // Render as nonunicode.
	}
	else if(fctx->font->has_unicode_codepoints &&
		(unicode_req>0 || fctx->font->prefer_unicode || !fctx->font->has_nonunicode_codepoints))
	{
		fctx->render_as_unicode = 1;
	}

	s = de_get_ext_option(c, "font:charsperrow");
	if(s) {
		chars_per_row = de_atoi64(s);
		if(chars_per_row<1) chars_per_row=1;
	}

	dfont = make_digit_font(c);

	fctx->codepoint_tmp = de_mallocarray(c, fctx->font->num_chars, sizeof(i32));
	fixup_codepoints(c, fctx);

	get_min_max_codepoint(fctx);
	if(fctx->num_valid_chars<1) goto done;
	num_table_rows_total = fctx->max_codepoint/chars_per_row+1;

	// TODO: Clean up these margin calculations, and make it more general.
	if(fctx->render_as_unicode) {
		img_leftmargin = dfont->nominal_width * 5 + 6;
	}
	else {
		if(fctx->max_codepoint >= 1000)
			img_leftmargin = dfont->nominal_width * 5 + 6;
		else
			img_leftmargin = dfont->nominal_width * 3 + 6;
	}
	img_topmargin = dfont->nominal_height + 6;
	img_rightmargin = 1;
	img_bottommargin = 1;

	// Scan the characters, and record relevant information.
	row_info = de_mallocarray(c, num_table_rows_total, sizeof(struct row_info_struct));
	col_info = de_mallocarray(c, chars_per_row, sizeof(struct col_info_struct));
	for(i=0; i<chars_per_row; i++) {
#define MIN_CHAR_CELL_WIDTH 5
		col_info[i].display_width = MIN_CHAR_CELL_WIDTH;
	}

	for(k=0; k<fctx->font->num_chars; k++) {
		i64 char_display_width;

		if(fctx->codepoint_tmp[k] == DE_CODEPOINT_INVALID) continue;
		if(!is_valid_char(&fctx->font->char_array[k])) continue;
		rownum = fctx->codepoint_tmp[k] / chars_per_row;
		colnum = fctx->codepoint_tmp[k] % chars_per_row;
		if(rownum<0 || rownum>=num_table_rows_total) {
			de_err(c, "internal: bad rownum");
			de_fatalerror(c);
		}

		// Remember that there is at least one valid character in this character's row.
		row_info[rownum].is_visible = 1;

		// Track the maximum width of any character in this character's column.
		char_display_width = (i64)(fctx->font->char_array[k].width +
				(int)fctx->font->char_array[k].extraspace_l +
				(int)fctx->font->char_array[k].extraspace_r);
		if(char_display_width > col_info[colnum].display_width) {
			col_info[colnum].display_width = char_display_width;
		}
	}

	img_vpixelsperchar = fctx->font->nominal_height + 1;

	// Figure out how many rows are used, and where to draw them.
	num_table_rows_to_display = 0;
	last_valid_row = -1;
	curpos = img_topmargin;
	for(j=0; j<num_table_rows_total; j++) {
		if(!row_info[j].is_visible) continue;

		// If we skipped one or more rows, leave some extra vertical space.
		if(num_table_rows_to_display>0 && !row_info[j-1].is_visible) curpos+=3;

		last_valid_row = j;
		row_info[j].display_pos = curpos;
		curpos += img_vpixelsperchar;
		num_table_rows_to_display++;
	}
	if(num_table_rows_to_display<1) goto done;

	// Figure out the positions of the columns.
	curpos = img_leftmargin;
	for(i=0; i<chars_per_row; i++) {
		col_info[i].display_pos = curpos;
		curpos += col_info[i].display_width + 1;
	}

	img_width = col_info[chars_per_row-1].display_pos +
		col_info[chars_per_row-1].display_width + img_rightmargin;
	img_height = row_info[last_valid_row].display_pos +
		img_vpixelsperchar -1 + img_bottommargin;

	img = de_bitmap_create(c, img_width, img_height, 1);

	// Clear the image
	for(j=0; j<img->height; j++) {
		for(i=0; i<img->width; i++) {
			de_bitmap_setpixel_gray(img, i, j, 128);
		}
	}

	// Draw/clear the cell backgrounds
	for(j=0; j<num_table_rows_total; j++) {
		if(!row_info[j].is_visible) continue;
		ypos = row_info[j].display_pos;

		for(i=0; i<chars_per_row; i++) {
			i64 ii, jj;

			xpos = col_info[i].display_pos;
			for(jj=0; jj<img_vpixelsperchar-1; jj++) {
				for(ii=0; ii<col_info[i].display_width; ii++) {
					de_bitmap_setpixel_gray(img, xpos+ii, ypos+jj, (ii/2+jj/2)%2 ? 176 : 192);
				}
			}
		}
	}

	// Draw the labels in the top margin.

	// TODO: Better label spacing logic.
	if(fctx->font->nominal_width <= 12)
		label_stride = 2;
	else
		label_stride = 1;

	for(i=0; i<chars_per_row; i++) {
		if(i%label_stride != 0) continue;
		xpos = col_info[i].display_pos + col_info[i].display_width/2;
		ypos = img_topmargin - 3;

		dnflags = DNFLAG_HCENTER;
		if(fctx->render_as_unicode) dnflags |= DNFLAG_HEX;

		draw_number(c, img, dfont, i, xpos, ypos, dnflags);
	}

	// Draw the labels in the left margin.
	for(j=0; j<num_table_rows_total; j++) {
		if(!row_info[j].is_visible) continue;
		xpos = img_leftmargin - 3;
		ypos = row_info[j].display_pos + (img_vpixelsperchar + dfont->nominal_height + 1)/2;

		dnflags = 0;
		if(fctx->render_as_unicode) dnflags |= DNFLAG_HEX | DNFLAG_LEADING_ZEROES;

		draw_number(c, img, dfont, j*chars_per_row, xpos, ypos, dnflags);
	}

	// Render the glyphs.
	for(k=0; k<fctx->font->num_chars; k++) {
		if(fctx->codepoint_tmp[k] == DE_CODEPOINT_INVALID) continue;
		if(!is_valid_char(&fctx->font->char_array[k])) continue;

		rownum = fctx->codepoint_tmp[k] / chars_per_row;
		colnum = fctx->codepoint_tmp[k] % chars_per_row;
		if(rownum<0 || rownum>=num_table_rows_total) {
			de_err(c, "internal: bad rownum");
			de_fatalerror(c);
		}

		xpos = col_info[colnum].display_pos;
		ypos = row_info[rownum].display_pos;

		de_font_paint_character_idx(c, img, fctx->font, k, xpos, ypos,
			DE_STOCKCOLOR_BLACK, DE_STOCKCOLOR_WHITE, 0);
	}

	de_bitmap_write_to_file_finfo(img, fi, createflags);

done:
	if(dfont) {
		de_free(c, dfont->char_array);
		de_destroy_bitmap_font(c, dfont);
	}
	de_bitmap_destroy(img);
	de_free(c, row_info);
	de_free(c, col_info);
	if(fctx) {
		de_free(c, fctx->codepoint_tmp);
		de_free(c, fctx);
	}
}
Exemplo n.º 27
0
static void de_run_icns_pass(deark *c, lctx *d, int pass)
{
	de_int64 i;
	de_int64 segment_pos;
	struct page_ctx *pg = NULL;
	int image_count;

	segment_pos = 8;
	image_count = 0;

	while(1) {
		de_int64 segment_len;

		if(pg) { de_free(c, pg); pg=NULL; }

		if(segment_pos+8 > d->file_size) break;

		pg = de_malloc(c, sizeof(struct page_ctx));
		pg->image_num = image_count;

		dbuf_read_fourcc(c->infile, segment_pos, &pg->code4cc, 0);

		segment_len = de_getui32be(segment_pos+4);

		pg->image_pos = segment_pos + 8;
		pg->image_len = segment_len - 8;

		if(pass==2) {
			de_dbg(c, "image #%d, type '%s', at %d, size=%d\n", pg->image_num, pg->code4cc.id_printable,
				(int)pg->image_pos, (int)pg->image_len);
		}
		if(segment_len<8 || segment_pos+segment_len > d->file_size) {
			if(pass==2) {
				de_err(c, "Invalid length for segment '%s' (%u)\n", pg->code4cc.id_printable,
					(unsigned int)segment_len);
			}
			break;
		}

		if(pass==2) {
			// Find this type code in the image_type_info array
			pg->type_info = NULL;
			for(i=0; image_type_info_arr[i].code!=0; i++) {
				if(image_type_info_arr[i].code==pg->code4cc.id) {
					pg->type_info = &image_type_info_arr[i];
					break;
				}
			}
			if(!pg->type_info) {
				de_warn(c, "(Image #%d) Unknown image type '%s'\n", pg->image_num, pg->code4cc.id_printable);
			}
		}

		if(pass==1) {
			switch(pg->code4cc.id) {
			case 0x69636d23: // icm# 16x12x1
				d->mkpos_16_16_1 = pg->image_pos + (16*12)/8;
				break;
			case 0x69637323: // ics# 16x16x1
				d->mkpos_16_16_1 = pg->image_pos + 16*16/8;
				break;
			case 0x49434e23: // ICN# 32x32x1
				d->mkpos_32_32_1 = pg->image_pos + 32*32/8;
				break;
			case 0x69636823: // ich# 48x48x1
				d->mkpos_48_48_1 = pg->image_pos + 48*48/8;
				break;
			case 0x73386d6b: // s8mk 16x16x8
				d->mkpos_16_16_8 = pg->image_pos;
				break;
			case 0x6c386d6b: // l8mk 32x32x8
				d->mkpos_32_32_8 = pg->image_pos;
				break;
			case 0x68386d6b: // h8mk 48x48x8
				d->mkpos_48_48_8 = pg->image_pos;
				break;
			case 0x74386d6b: // t8mk 128x128x8
				d->mkpos_128_128_8 = pg->image_pos;
				break;
			}
		}
		else if(pass==2) {
			de_dbg_indent(c, 1);
			do_icon(c, d, pg);
			de_dbg_indent(c, -1);
		}

		image_count++;
		segment_pos += segment_len;
	}

	if(pg) de_free(c, pg);
}
Exemplo n.º 28
0
static int do_dataset(deark *c, lctx *d, de_int64 ds_idx, de_int64 pos1,
	de_int64 *bytes_consumed)
{
	de_byte b;
	de_byte recnum, dsnum;
	int retval = 0;
	de_int64 pos = pos1;
	de_int64 dflen;
	de_int64 dflen_bytes_consumed;
	struct ds_info dsi;
	int ds_known;

	*bytes_consumed = 0;

	b = de_getbyte(pos);
	if(b!=0x1c) {
		if(b==0x00 && ds_idx>0) {
			// Extraneous padding at the end of data?
			de_warn(c, "Expected %d bytes of IPTC data, only found %d\n",
				(int)c->infile->len, (int)pos);
		}
		else {
			de_err(c, "Bad IPTC tag marker (0x%02x) at %d\n", (int)b, (int)pos);
		}
		goto done;
	}
	pos++;

	recnum = de_getbyte(pos++);
	dsnum = de_getbyte(pos++);

	ds_known = lookup_ds_info(recnum, dsnum, &dsi);

	if(!read_dflen(c, c->infile, pos, &dflen, &dflen_bytes_consumed)) goto done;
	pos += dflen_bytes_consumed;

	de_dbg(c, "IPTC dataset %d:%02d (%s) dpos=%" INT64_FMT " dlen=%" INT64_FMT "\n",
		(int)recnum, (int)dsnum, dsi.dsname, pos, dflen);

	// Decode the value
	de_dbg_indent(c, 1);

	if(dsi.hfn) {
		dsi.hfn(c, d, &dsi, pos, dflen);
	}
	else if(dsi.flags&0x1) {
		handle_text(c, d, &dsi, pos, dflen);
	}
	else if(dsi.recnum==2 && !ds_known) {
		// Unknown record-2 datasets often contain readable text.
		handle_text(c, d, &dsi, pos, dflen);
	}
	pos += dflen;

	de_dbg_indent(c, -1);
	//

	*bytes_consumed = pos - pos1;
	retval = 1;
done:
	return retval;
}
Exemplo n.º 29
0
// XIMG and similar formats.
// TODO: Should this function be merged with do_gem_img()?
static int do_gem_ximg(deark *c, lctx *d)
{
	dbuf *unc_pixels = NULL;
	de_bitmap *img = NULL;
	de_finfo *fi = NULL;
	int retval = 0;
	int saved_indent_level;

	de_dbg_indent_save(c, &saved_indent_level);

	de_dbg(c, "header (continued) at %d", 8*2);
	de_dbg_indent(c, 1);

	if((d->nplanes>=1 && d->nplanes<=8) /* || d->nplanes==24 */) {
		;
	}
	else {
		if(d->is_ximg)
			de_err(c, "%d-plane XIMG images are not supported", (int)d->nplanes);
		else
			de_err(c, "This type of %d-plane image is not supported", (int)d->nplanes);
		goto done;
	}

	if(d->header_size_in_words==25 && !d->is_ximg) {
		i64 pal_pos = d->header_size_in_bytes-32;
		de_dbg(c, "palette at %d", (int)pal_pos);
		de_dbg_indent(c, 1);
		de_fmtutil_read_atari_palette(c, c->infile, pal_pos,
			d->pal, 16, ((i64)1)<<d->nplanes, 0);
		de_dbg_indent(c, -1);
	}
	else {
		read_palette_ximg(c, d);
	}

	if(d->nplanes==1 && d->pal[0]==d->pal[1]) {
		de_dbg(c, "Palette doesn't seem to be present. Using a default palette.");
		d->pal[0] = DE_STOCKCOLOR_WHITE;
		d->pal[1] = DE_STOCKCOLOR_BLACK;
	}

	de_dbg_indent(c, -1);

	de_dbg(c, "image at %d", (int)d->header_size_in_bytes);

	unc_pixels = dbuf_create_membuf(c, d->rowspan_total*d->h, 0);
	uncompress_pixels(c, d, unc_pixels, d->header_size_in_bytes, c->infile->len-d->header_size_in_bytes);

	img = de_bitmap_create(c, d->w, d->h, 3);

	fi = de_finfo_create(c);
	set_density(c, d, fi);

	if(d->nplanes>8) {
		read_rgb_image(c, d, unc_pixels, img);
	}
	else {
		read_paletted_image(c, d, unc_pixels, img);
	}

	de_bitmap_write_to_file_finfo(img, fi, 0);

	retval = 1;

done:
	de_bitmap_destroy(img);
	de_finfo_destroy(c, fi);
	dbuf_close(unc_pixels);
	de_dbg_indent_restore(c, saved_indent_level);
	return retval;
}
Exemplo n.º 30
0
static int do_read_header(deark *c, lctx *d)
{
	de_int64 dfType;
	de_int64 dfPixWidth;
	de_int64 dfPixHeight;
	de_int64 dfMaxWidth;
	int is_vector = 0;
	int retval = 0;

	d->fnt_version = de_getui16le(0);
	de_dbg(c, "dfVersion: 0x%04x\n", (int)d->fnt_version);

	if(d->fnt_version==0x0300)
		d->hdrsize = 148;
	else
		d->hdrsize = 118;

	dfType = de_getui16le(66);
	de_dbg(c, "dfType: 0x%04x\n", (int)dfType);
	is_vector = (dfType&0x1)?1:0;
	de_dbg(c, "Font type: %s\n", is_vector?"vector":"bitmap");

	d->dfPoints = de_getui16le(68);
	de_dbg(c, "dfPoints: %d\n", (int)d->dfPoints);

	dfPixWidth = de_getui16le(86);
	de_dbg(c, "dfPixWidth: %d\n", (int)dfPixWidth);
	dfPixHeight = de_getui16le(88);
	de_dbg(c, "dfPixHeight: %d\n", (int)dfPixHeight);

	d->dfCharSet = de_getbyte(85);
	de_dbg(c, "charset: 0x%02x\n", (int)d->dfCharSet);
	if(d->dfCharSet==0x00) { // "ANSI"
		d->encoding = DE_ENCODING_WINDOWS1252; // Guess
	}
	else if(d->dfCharSet==0xff) { // "OEM"
		d->encoding = DE_ENCODING_CP437_G; // Guess
	}
	else {
		d->encoding = DE_ENCODING_UNKNOWN;
	}

	dfMaxWidth = de_getui16le(93);
	de_dbg(c, "dfMaxWidth: %d\n", (int)dfMaxWidth);

	if(dfPixWidth!=dfMaxWidth && dfPixWidth!=0) {
		de_warn(c, "dfMaxWidth (%d) does not equal dfPixWidth (%d)\n",
			(int)dfMaxWidth, (int)dfPixWidth);
	}

	d->first_char = de_getbyte(95);
	d->last_char = de_getbyte(96);
	de_dbg(c, "first char: %d, last char: %d\n", (int)d->first_char, (int)d->last_char);

	if(is_vector) {
		de_err(c, "This is a vector font. Not supported.\n");
		goto done;
	}

	// Apparently, the first 117 bytes (through the dfBitsOffset field) are
	// common to all versions
	if(d->fnt_version<0x0200) {
		de_err(c, "This version of FNT is not supported\n");
		goto done;
	}

	if(d->fnt_version >= 0x0200) {
		d->dfFace = de_getui32le(105);
	}

	// There is an extra character at the end of the table that is an
	// "absolute-space" character, and is guaranteed to be blank.
	d->num_chars_stored = (de_int64)d->last_char - d->first_char + 1 + 1;

	if(d->fnt_version==0x0300) {
		d->char_entry_size = 6;
	}
	else {
		d->char_entry_size = 4;
	}

	d->char_table_size = d->char_entry_size * d->num_chars_stored;
	de_dbg(c, "character index at %d, size %d, %d bytes/entry\n", (int)d->hdrsize,
		(int)d->char_table_size, (int)d->char_entry_size);

	do_prescan_chars(c, d);
	if(d->detected_max_width<1) goto done;
	d->nominal_char_width = d->detected_max_width;

	d->char_height = dfPixHeight;

	retval = 1;
done:
	return retval;
}