static void do_opo_opa(deark *c, lctx *d) { de_int64 offset_2ndheader; de_int64 pos; de_int64 n; de_int64 len; de_declare_fmt(c, "Psion OPO/OPA"); // The second header marks the end of the embedded files section, I guess. offset_2ndheader = de_getui16le(18); de_dbg(c, "offset of second header: %d\n", (int)offset_2ndheader); pos = 20; // Read length of source filename n = (de_int64)de_getbyte(pos); pos++; pos+=n; while(pos<offset_2ndheader) { // Read length of this embedded file len = de_getui16le(pos); pos+=2; handle_embedded_file(c, d, pos, len); pos+=len; } }
static void de_run_gemmeta(deark *c, de_module_params *mparams) { lctx *d = NULL; de_int64 pos; de_int64 hdrlen_words; de_int64 version; de_int64 imgflag; de_int64 bytesused; d = de_malloc(c, sizeof(lctx)); de_msg(c, "Note: GEM VDI Metafiles can be parsed, but no files can be extracted from them.\n"); pos = 0; hdrlen_words = de_getui16le(pos+2); de_dbg(c, "header length: %d words\n", (int)hdrlen_words); version = de_getui16le(pos+4); de_dbg(c, "version number: %d\n", (int)version); // TODO: Read more header fields. imgflag = de_getui16le(pos+28); de_dbg(c, "image flag: %d\n", (int)imgflag); pos += hdrlen_words*2; while(1) { if(pos >= c->infile->len) break; if(!do_record(c, d, pos, &bytesused)) break; if(bytesused<=0) break; pos += bytesused; } de_free(c, d); }
static void do_extract_file(deark *c, lctx *d, de_int64 dir_pos, de_byte filetype_c64s, de_byte filetype) { de_int64 load_addr; de_int64 end_addr; de_int64 offset; dbuf *f = NULL; de_int64 payload_size; // = file_size-2 de_ucstring *fname = NULL; de_int64 fname_len; de_int64 i; de_int64 fnpos; de_finfo *fi = NULL; load_addr = de_getui16le(dir_pos+2); end_addr = de_getui16le(dir_pos+4); offset = de_getui32le(dir_pos+8); de_dbg(c, "load_addr=%d end_addr=%d offset=%d\n", (int)load_addr, (int)end_addr, (int)offset); // File name at pos+16 fnpos = dir_pos+16; // Find the length of the (space-padded) filename. fname_len = 0; for(i=15; i>=0; i--) { if(de_getbyte(fnpos+i)!=' ') { fname_len = i+1; break; } } de_dbg2(c, "filename length: %d\n", (int)fname_len); fname = ucstring_create(c); dbuf_read_to_ucstring(c->infile, fnpos, fname_len, fname, 0, DE_ENCODING_PETSCII); de_dbg(c, "filename: \"%s\"\n", ucstring_get_printable_sz(fname)); ucstring_append_sz(fname, ".prg", DE_ENCODING_ASCII); fi = de_finfo_create(c); de_finfo_set_name_from_ucstring(c, fi, fname); fi->original_filename_flag = 1; payload_size = end_addr - load_addr; if(payload_size < 0) { // TODO: Try to support files that don't have end_addr set properly. de_err(c, "This type of T64 file is not supported.\n"); goto done; } f = dbuf_create_output_file(c, NULL, fi, 0); dbuf_copy(c->infile, dir_pos+2, 2, f); dbuf_copy(c->infile, offset, payload_size, f); done: dbuf_close(f); de_finfo_destroy(c, fi); ucstring_destroy(fname); }
static void de_run_t64(deark *c, de_module_params *mparams) { lctx *d = NULL; de_int64 pos; de_int64 i; d = de_malloc(c, sizeof(lctx)); pos = 32; d->version = de_getui16le(pos); de_dbg(c, "version: 0x%04x\n", (int)d->version); if(d->version!=0x100 && d->version!=0x101) { de_warn(c, "Unexpected version number. This might not be a T64 file.\n"); } d->max_dir_entries = de_getui16le(pos+2); d->used_dir_entries = de_getui16le(pos+4); de_dbg(c, "max dir entries = %d, files = %d\n", (int)d->max_dir_entries, (int)d->used_dir_entries); pos += 32; for(i=0; i<d->max_dir_entries; i++) { do_dir_entry(c, d, i, pos+32*i); } de_free(c, d); }
// Returns 0 if we should stop reading the file. static int do_record(deark *c, lctx *d, de_int64 pos, de_int64 *bytesused) { int retval = 0; struct opcode_data op; de_int64 ptsin_size_bytes; de_int64 intin_size_bytes; de_int64 data_size_bytes; const struct opcode_info *opinfo; const char *opcode_name; *bytesused = 0; de_memset(&op, 0, sizeof(struct opcode_data)); de_dbg(c, "record at %d\n", (int)pos); de_dbg_indent(c, 1); op.opcode = de_getui16le(pos); op.ptsin_count = de_getui16le(pos+2); op.intin_count = de_getui16le(pos+4); op.func_id = de_getui16le(pos+6); ptsin_size_bytes = 4*op.ptsin_count; intin_size_bytes = 2*op.intin_count; data_size_bytes = ptsin_size_bytes + intin_size_bytes; op.ptsin_pos = pos + 8; op.intin_pos = pos + 8 + ptsin_size_bytes; opinfo = find_opcode_info(op.opcode); if(opinfo && opinfo->name) opcode_name = opinfo->name; else opcode_name = "?"; de_dbg(c, "opcode=%d (%s), func_id=%d, #pts=%d, #int=%d (dlen=%d)\n", (int)op.opcode, opcode_name, (int)op.func_id, (int)op.ptsin_count, (int)op.intin_count, (int)data_size_bytes); *bytesused = 8 + data_size_bytes; if(opinfo && opinfo->fn) { opinfo->fn(c, d, &op); } if(op.opcode==65535) { goto done; } retval = 1; done: de_dbg_indent(c, -1); return retval; }
// Sets d->version, and certain header fields. static int detect_bmp_version(deark *c, lctx *d) { de_int64 pos; pos = 0; d->fsize = de_getui32le(pos+2); pos += FILEHEADER_SIZE; d->infohdrsize = de_getui32le(pos); if(d->infohdrsize<=12) { d->bitcount = de_getui16le(pos+10); } else { d->bitcount = de_getui16le(pos+14); } if(d->infohdrsize==12) { d->version = DE_BMPVER_OS2V1; return 1; } if(d->infohdrsize<16) { return 0; } if(d->infohdrsize>=20) { d->compression_field = (de_uint32)de_getui32le(pos+16); } if(d->infohdrsize>=16 && d->infohdrsize<=64) { if(d->fsize==FILEHEADER_SIZE+d->infohdrsize) { d->version = DE_BMPVER_OS2V2; return 1; } if((d->compression_field==3 && d->bitcount==1) || (d->compression_field==4 && d->bitcount==24)) { d->version = DE_BMPVER_OS2V2; return 1; } if(d->infohdrsize!=40 && d->infohdrsize!=52 && d->infohdrsize!=56) { d->version = DE_BMPVER_OS2V2; return 1; } } d->version = DE_BMPVER_WINV345; return 1; }
static void do_img_app(deark *c, lctx *d) { de_int64 i; de_int64 offset; de_int64 len; de_declare_fmt(c, "Psion IMG/APP"); for(i=0; i<4; i++) { offset = de_getui16le(40 + 4*i); len = de_getui16le(40 + 4*i + 2); if(offset==0) break; handle_embedded_file(c, d, offset, len); } }
static void de_run_cardfile(deark *c, de_module_params *mparams) { lctx *d = NULL; de_byte b; de_int64 pos; de_int64 n; d = de_malloc(c, sizeof(lctx)); pos = 0; b = de_getbyte(pos); if(b=='R') d->fmt=DE_CRDFMT_RRG; else d->fmt=DE_CRDFMT_MGC; if(d->fmt==DE_CRDFMT_RRG) { de_err(c, "CardFile RRG format is not supported\n"); goto done; } pos+=3; d->numcards = de_getui16le(pos); de_dbg(c, "number of cards: %d\n", (int)d->numcards); pos+=2; for(n=0; n<d->numcards; n++) { do_card_index(c, d, n, pos); pos+=52; } done: de_free(c, d); }
static void do_opcode_5(deark *c, lctx *d, struct opcode_data *op) { de_int64 sub_opcode_id; const char *name; if(op->func_id!=99) return; if(op->intin_count<1) return; sub_opcode_id = de_getui16le(op->intin_pos); switch(sub_opcode_id) { case 10: name="Start Group"; break; case 11: name="End Group"; break; case 49: name="Set No Line Style"; break; case 50: name="Set Attribute Shadow On"; break; case 51: name="Set Attribute Shadow Off"; break; case 80: name="Start Draw Area Type Primitive"; break; case 81: name="End Draw Area Type Primitive"; break; default: if(sub_opcode_id>100) { name="for developer use"; } else { name="?"; } } de_dbg(c, "sub-opcode id: %d (%s)\n", (int)sub_opcode_id, name); }
static void do_psf1_unicode_table(deark *c, lctx *d, struct de_bitmap_font *font) { de_int64 cur_idx; de_int64 pos; int got_cp; int found_fffe; de_int32 n; de_dbg(c, "Unicode table at %d\n", (int)d->unicode_table_pos); de_dbg_indent(c, 1); pos = d->unicode_table_pos; cur_idx = 0; got_cp = 0; // Have we set the codepoint for glyph[cur_idx]? found_fffe = 0; while(1) { if(cur_idx >= d->num_glyphs) break; if(pos+1 >= c->infile->len) break; n = (de_int32)de_getui16le(pos); pos+=2; if(n==0xffff) { if(!got_cp) { de_warn(c, "Missing codepoint for char #%d\n", (int)cur_idx); } cur_idx++; got_cp = 0; found_fffe = 0; continue; } else if(n==0xfffe) { found_fffe = 1; } if(found_fffe) { // Anything after 0xfffe is a multi-codepoint character, which we // don't support. continue; } if(!got_cp) { de_dbg2(c, "char[%d] = U+%04x\n", (int)cur_idx, (unsigned int)n); font->char_array[cur_idx].codepoint_unicode = n; got_cp = 1; continue; } // This is an "extra" codepoint for the current glyph. do_extra_codepoint(c, d, font, cur_idx, n); } font->has_unicode_codepoints = 1; font->prefer_unicode = 1; de_dbg_indent(c, -1); }
static int de_identify_fnt(deark *c) { de_int64 ver; // TODO: Better format detection. if(de_input_file_has_ext(c, "fnt")) { ver = de_getui16le(0); if(ver==0x0100 || ver==0x0200 || ver==0x0300) return 10; } return 0; }
// Find the widest character. static void do_prescan_chars(deark *c, lctx *d) { de_int64 i; de_int64 pos; de_int64 char_width; for(i=0; i<d->num_chars_stored; i++) { pos = d->hdrsize + d->char_entry_size*i; char_width = de_getui16le(pos); if(char_width > d->detected_max_width) { d->detected_max_width = char_width; } } de_dbg(c, "detected max width: %d\n", (int)d->detected_max_width); }
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); }
// 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; }
// create bitmap_font object static void do_make_image(deark *c, lctx *d) { struct de_bitmap_font *font = NULL; de_int64 i; de_int64 pos; font = de_create_bitmap_font(c); font->has_nonunicode_codepoints = 1; if(d->encoding!=DE_ENCODING_UNKNOWN) font->has_unicode_codepoints = 1; font->prefer_unicode = 0; font->nominal_width = (int)d->nominal_char_width; font->nominal_height = (int)d->char_height; font->num_chars = d->num_chars_stored; font->char_array = de_malloc(c, font->num_chars * sizeof(struct de_bitmap_font_char)); for(i=0; i<d->num_chars_stored; i++) { de_int64 char_width; de_int64 char_offset; de_int32 char_index; de_int64 num_tiles; de_int64 tile; de_int64 row; pos = d->hdrsize + d->char_entry_size*i; char_width = de_getui16le(pos); if(d->char_entry_size==6) char_offset = de_getui32le(pos+2); else char_offset = de_getui16le(pos+2); de_dbg2(c, "char[%d] width=%d offset=%d\n", (int)(d->first_char + i), (int)char_width, (int)char_offset); num_tiles = (char_width+7)/8; if(i == d->num_chars_stored-1) { // Arbitrarily put the "absolute space" char at codepoint 256, // and U+2002 EN SPACE (best I can do). font->char_array[i].codepoint_nonunicode = 256; font->char_array[i].codepoint_unicode = 0x2002; } else { char_index = (de_int32)d->first_char + (de_int32)i; font->char_array[i].codepoint_nonunicode = char_index; if(font->has_unicode_codepoints) { if(char_index<32 && d->dfCharSet==0) { // This kind of font usually doesn't have glyphs below 32. // If it does, assume that they are VT100 line drawing characters. font->char_array[i].codepoint_unicode = de_char_to_unicode(c, 95+char_index, DE_ENCODING_DEC_SPECIAL_GRAPHICS); } else { font->char_array[i].codepoint_unicode = de_char_to_unicode(c, char_index, d->encoding); } } } font->char_array[i].width = (int)char_width; font->char_array[i].height = (int)d->char_height; font->char_array[i].rowspan = num_tiles; font->char_array[i].bitmap = de_malloc(c, d->char_height * num_tiles); for(row=0; row<d->char_height; row++) { for(tile=0; tile<num_tiles; tile++) { font->char_array[i].bitmap[row * font->char_array[i].rowspan + tile] = de_getbyte(char_offset + tile*d->char_height + row); } } } de_font_bitmap_font_to_image(c, font, d->fi, 0); if(font) { if(font->char_array) { for(i=0; i<font->num_chars; i++) { de_free(c, font->char_array[i].bitmap); } de_free(c, font->char_array); } de_destroy_bitmap_font(c, font); } }
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; }
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; }