static int de_identify_cardfile(deark *c) { de_byte buf[4]; de_read(buf, 0, 4); if(!de_memcmp(buf, "MGC", 3)) return 80; if(!de_memcmp(buf, "RRG", 3)) return 80; return 0; }
static int do_identify_png_internal(deark *c) { u8 buf[8]; de_read(buf, 0, sizeof(buf)); if(!de_memcmp(buf, "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", 8)) return DE_PNGFMT_PNG; if(!de_memcmp(buf, "\x8b\x4a\x4e\x47\x0d\x0a\x1a\x0a", 8)) return DE_PNGFMT_JNG; if(!de_memcmp(buf, "\x8a\x4d\x4e\x47\x0d\x0a\x1a\x0a", 8)) return DE_PNGFMT_MNG; return 0; }
static int de_identify_psionapp(deark *c) { de_byte b[16]; de_read(b, 0, 16); if(!de_memcmp(b, "ImageFileType**\0", 16)) return 100; if(!de_memcmp(b, "OPLObjectFile**\0", 16)) return 100; return 0; }
static int de_identify_macpaint(deark *c) { de_byte buf[8]; de_read(buf, 65, 8); // Not all MacPaint files can be easily identified, but this will work // for some of them. if(!de_memcmp(buf, "PNTGMPNT", 8)) return 80; if(!de_memcmp(buf, "PNTG", 4)) return 70; if(de_input_file_has_ext(c, "mac")) return 10; if(de_input_file_has_ext(c, "macp")) return 15; if(de_input_file_has_ext(c, "pntg")) return 15; return 0; }
static int dbufmemcmp_cbfn(struct de_bufferedreadctx *brctx, const u8 *buf, i64 buf_len) { // Return 0 if there is a mismatch. return !de_memcmp(buf, &(((const u8*)brctx->userdata)[brctx->offset]), (size_t)buf_len); }
int dbuf_memcmp(dbuf *f, i64 pos, const void *s, size_t n) { u8 buf1[128]; if(f->cache && pos >= f->cache_start_pos && pos + (i64)n <= f->cache_start_pos + f->cache_bytes_used) { // Fastest path: Compare directly to cache. return de_memcmp(s, &f->cache[pos - f->cache_start_pos], n); } if(n<=sizeof(buf1)) { // Use a stack buffer if small enough. dbuf_read(f, buf1, pos, n); return de_memcmp(buf1, s, n); } // Fallback method. return !dbuf_buffered_read(f, pos, n, dbufmemcmp_cbfn, (void*)s); }
static void read_compression_type(deark *c, lctx *d, i64 pos) { u8 buf[16]; de_dbg(c, "compression type at %d", (int)pos); de_read(buf, pos, sizeof(buf)); if(!de_memcmp(buf, "lzma\0", 5)) { d->cmpr_type = DE_RPM_CMPR_LZMA; } // Other valid compression types are "gzip", "bzip2", and "xz". // We'll autodetect most of them, but lzma is hard to detect. }
// Handle some box types that might be common to multiple formats. // This function should be called as needed by the client's box handler function. // TODO: A way to identify (name) the boxes that we handle here. int de_fmtutil_default_box_handler(deark *c, struct de_boxesctx *bctx) { struct de_boxdata *curbox = bctx->curbox; if(curbox->is_uuid) { if(!de_memcmp(curbox->uuid, "\xb1\x4b\xf8\xbd\x08\x3d\x4b\x43\xa5\xae\x8c\xd7\xd5\xa6\xce\x03", 16)) { de_dbg(c, "GeoTIFF data at %d, len=%d", (int)curbox->payload_pos, (int)curbox->payload_len); dbuf_create_file_from_slice(bctx->f, curbox->payload_pos, curbox->payload_len, "geo.tif", NULL, DE_CREATEFLAG_IS_AUX); } else if(!de_memcmp(curbox->uuid, "\xbe\x7a\xcf\xcb\x97\xa9\x42\xe8\x9c\x71\x99\x94\x91\xe3\xaf\xac", 16)) { de_dbg(c, "XMP data at %d, len=%d", (int)curbox->payload_pos, (int)curbox->payload_len); dbuf_create_file_from_slice(bctx->f, curbox->payload_pos, curbox->payload_len, "xmp", NULL, DE_CREATEFLAG_IS_AUX); } else if(!de_memcmp(curbox->uuid, "\x2c\x4c\x01\x00\x85\x04\x40\xb9\xa0\x3e\x56\x21\x48\xd6\xdf\xeb", 16)) { de_dbg(c, "Photoshop resources at %d, len=%d", (int)curbox->payload_pos, (int)curbox->payload_len); de_fmtutil_handle_photoshop_rsrc(c, bctx->f, curbox->payload_pos, curbox->payload_len, 0x0); } else if(!de_memcmp(curbox->uuid, "\x05\x37\xcd\xab\x9d\x0c\x44\x31\xa7\x2a\xfa\x56\x1f\x2a\x11\x3e", 16)) { de_dbg(c, "Exif data at %d, len=%d", (int)curbox->payload_pos, (int)curbox->payload_len); de_fmtutil_handle_exif(c, curbox->payload_pos, curbox->payload_len); } } return 1; }
static int de_identify_wri(deark *c) { u8 buf[6]; de_read(buf, 0, 6); if((buf[0]==0x31 || buf[0]==0x32) && !de_memcmp(&buf[1], "\xbe\x00\x00\x00\xab", 5)) { i64 pnMac; pnMac = de_getu16le(48*2); if(pnMac==0) return 0; // Apparently MSWord, not Write return 100; } return 0; }
static void handle_embedded_file(deark *c, lctx *d, de_int64 offset, de_int64 len) { de_byte buf[16]; const char *ext; int extract_this_file; int is_pic; de_dbg(c, "embedded file at %d, len=%d\n", (int)offset, (int)len); is_pic = 0; ext = "bin"; extract_this_file = 0; if(len>0 && c->extract_level>=2) extract_this_file = 1; // As far as I can tell, there's no way to tell the type of an // embedded file, except by sniffing it. de_read(buf, offset, 16); if(len>=8) { if(!de_memcmp(buf, "PIC\xdc\x30\x30", 6)) { // Looks like a PIC file is_pic = 1; ext = "pic"; extract_this_file = 1; } } if(extract_this_file) { if(is_pic && d->convert_images) { // Convert PIC to PNG. // For consistency, this option shouldn't exist. But I'm not sure that // PIC files embedded in APP files are really the same as PIC files on // their own. They might need special handling. Until I'm sure they don't, // I'll leave this option here. de_run_module_by_id_on_slice(c, "psionpic", NULL, c->infile, offset, len); } else { // Just extract the file dbuf_create_file_from_slice(c->infile, offset, len, ext, NULL, is_pic?0:DE_CREATEFLAG_IS_AUX); } } else { de_dbg(c, "(not extracting this file)\n"); } }
static void do_identify_bitstream(deark *c, lctx *d, struct stream_info *si, i64 pos, i64 len) { u8 idbuf[16]; size_t bytes_to_scan; size_t k; bytes_to_scan = (size_t)len; if(bytes_to_scan > sizeof(idbuf)) { bytes_to_scan = sizeof(idbuf); } de_read(idbuf, pos, bytes_to_scan); for(k=0; k<DE_ITEMS_IN_ARRAY(stream_type_info_arr); k++) { if(!de_memcmp(idbuf, stream_type_info_arr[k].magic, stream_type_info_arr[k].magic_len)) { si->sti = &stream_type_info_arr[k]; si->stream_type = si->sti->stream_type; break; } } if(si->stream_type==STREAMTYPE_VORBIS) { d->found_vorbis = 1; } else if(si->stream_type==STREAMTYPE_THEORA) { d->found_theora = 1; } else if(si->stream_type==STREAMTYPE_SKELETON) { d->found_skeleton = 1; } else if(si->sti && (si->sti->flags&0x1)) { d->found_ogm = 1; } if(si->stream_type!=STREAMTYPE_VORBIS && si->stream_type!=STREAMTYPE_THEORA) { d->has_non_vorbis_non_theora_stream = 1; } de_dbg(c, "bitstream type: %s", si->sti?si->sti->name:"unknown"); }
// pos1 points to the ole_id field (should be 0x00000501). // Caller must have looked ahead to check the type. static int do_picture_ole_embedded_rendition(deark *c, lctx *d, struct para_info *pinfo, int rendition_idx, i64 pos1, i64 *bytes_consumed) { i64 pos = pos1; i64 stringlen; i64 data_len; u8 buf[16]; struct de_stringreaderdata *srd_typename = NULL; struct de_stringreaderdata *srd_filename = NULL; struct de_stringreaderdata *srd_params = NULL; pos += 4; // 0x00000501 pos += 4; // "type" (probably already read by caller) stringlen = de_getu32le_p(&pos); srd_typename = dbuf_read_string(c->infile, pos, stringlen, 260, DE_CONVFLAG_STOP_AT_NUL, DE_ENCODING_ASCII); de_dbg(c, "typename: \"%s\"", ucstring_getpsz(srd_typename->str)); pos += stringlen; stringlen = de_getu32le_p(&pos); srd_filename = dbuf_read_string(c->infile, pos, stringlen, 260, DE_CONVFLAG_STOP_AT_NUL, DE_ENCODING_ASCII); de_dbg(c, "filename: \"%s\"", ucstring_getpsz(srd_filename->str)); pos += stringlen; stringlen = de_getu32le_p(&pos); srd_params = dbuf_read_string(c->infile, pos, stringlen, 260, DE_CONVFLAG_STOP_AT_NUL, DE_ENCODING_ASCII); de_dbg(c, "params: \"%s\"", ucstring_getpsz(srd_params->str)); pos += stringlen; data_len = de_getu32le_p(&pos); de_dbg(c, "embedded ole rendition data: pos=%d, len=%d", (int)pos, (int)data_len); // TODO: I don't know the extent to which it's better to sniff the data, or // rely on the typename. de_read(buf, pos, sizeof(buf)); if(!de_strcmp(srd_typename->sz, "CDraw") && !de_memcmp(&buf[0], (const void*)"RIFF", 4) && !de_memcmp(&buf[8], (const void*)"CDR", 3) ) { // Looks like CorelDRAW dbuf_create_file_from_slice(c->infile, pos, data_len, "cdr", NULL, 0); } else if(buf[0]=='B' && buf[1]=='M') { // TODO: Detect true length of data dbuf_create_file_from_slice(c->infile, pos, data_len, "bmp", NULL, 0); } else { if(d->extract_ole) { extract_unknown_ole_obj(c, d, pos, data_len, srd_typename); } else { de_warn(c, "Unknown/unsupported type of OLE object (\"%s\") at %d", ucstring_getpsz(srd_typename->str), (int)pos1); } } pos += data_len; *bytes_consumed = pos - pos1; de_destroy_stringreaderdata(c, srd_typename); de_destroy_stringreaderdata(c, srd_filename); de_destroy_stringreaderdata(c, srd_params); return 1; }