/*************************************************************************** * Copyright (C) 2010 by Roberto Maar * * robi6@users.sf.net * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, see . * * * * C Implementation: file_type * ***************************************************************************/ #include #include #include #include #include #include "util.h" #include "inode.h" #ifdef WORDS_BIGENDIAN #define ext4magic_be64_to_cpu(x) ((__u64)(x)) #else #define ext4magic_be64_to_cpu(x) ext2fs_swab64((x)) #endif //#define DEBUG_QUICK_TIME //#define DEBUG_MAGIC_MP3_STREAM //#define DEBUG_OGG_STREAM //#define DEBUG_MAGIC_MP3_STREAM extern ext2_filsys current_fs ; // index of the files corresponding magic result strings int ident_file(struct found_data_t *new, __u32 *scan, char *magic_buf, void *buf){ //Please do not modify the following lines. //they are used for indices to the filestypes char typestr[] ="application/ audio/ image/ message/ model/ text/ video/ "; char imagestr[] ="gif jp2 jpeg png svg+xml tiff vnd.adobe.photoshop vnd.djvu x-coreldraw x-cpi x-ico x-ms-bmp x-niff x-portable-bitmap x-portable-greymap x-portable-pixmap x-psion-sketch x-quicktime x-unknown x-xcursor x-xpmi x-tga x-xcf "; char videostr[] ="3gpp h264 mp2p mp2t mp4 mp4v-es mpeg mpv quicktime x-flc x-fli x-flv x-jng x-mng x-msvideo x-sgi-movie x-unknown x-ms-asf x-matroska webm "; char audiostr[] ="basic midi mp4 mpeg x-adpcm x-aiff x-dec-basic x-flac x-hx-aac-adif x-hx-aac-adts x-mod x-mp4a-latm x-pn-realaudio x-unknown x-wav "; char messagestr[] ="news rfc822 "; char modelstr[] ="vrml x3d "; char applistr[] ="dicom mac-binhex40 msword octet-stream ogg pdf pgp pgp-encrypted pgp-keys pgp-signature postscript unknown+zip vnd.google-earth.kml+xml vnd.google-earth.kmz vnd.lotus-wordpro vnd.ms-cab-compressed vnd.ms-excel vnd.ms-tnef vnd.oasis.opendocument. vnd.rn-realmedia vnd.symbian.install x-123 x-adrift x-archive x-arc x-arj x-bittorrent x-bzip2 x-compress x-coredump x-cpio x-dbf x-dbm x-debian-package x-dosexec x-dvi x-eet x-elc x-executable x-gdbm x-gnucash x-gnumeric x-gnupg-keyring x-gzip x-hdf x-hwp x-ichitaro4 x-ichitaro5 x-ichitaro6 x-iso9660-image x-java-applet x-java-jce-keystore x-java-keystore x-java-pack200 x-kdelnk x-lha x-lharc x-lzip x-mif xml xml-sitemap x-msaccess x-ms-reader x-object x-pgp-keyring x-quark-xpress-3 x-quicktime-player x-rar x-rpm x-sc x-setupscript x-sharedlib x-shockwave-flash x-stuffit x-svr4-package x-tar x-tex-tfm x-tokyocabinet-btree x-tokyocabinet-fixed x-tokyocabinet-hash x-tokyocabinet-table x-xz x-zoo zip x-font-ttf x-7z-compressed "; char textstr[] = "html PGP rtf texmacs troff vnd.graphviz x-awk x-diff x-fortran x-gawk x-info x-lisp x-lua x-msdos-batch x-nawk x-perl x-php x-shellscript x-texinfo x-tex x-vcard x-xmcd plain x-pascal x-c++ x-c x-mail x-makefile x-asm x-python x-java PEM SGML libtool M3U tcl POD PPD configure ruby sed expect ssh text "; //Files not found as mime-type char undefstr[] ="MPEG Targa 7-zip cpio CD-ROM DVD 9660 Kernel boot ext2 ext3 ext4 Image Composite SQLite OpenOffice.org Microsoft VMWare3 VMware4 JPEG ART PCX RIFF DIF IFF ATSC ScreamTracker EBML LZMA Audio=Visual Sample=Vision ISO=Media Linux filesystem x86 LUKS python ESRI=Shape CDF ecryptfs Matlab=v5 "; //----------------------------------------------------------------------------------- char* p_search; char token[30]; int len, flag; int major = 0; int minor = 0; flag = 0; p_search = typestr; while (*p_search){ len=0; while((*p_search) != 0x20){ token[len] = *p_search; p_search++; len++; } token[len] = 0; major++; if (!strncmp(magic_buf,token,strlen(token))){ flag = 1; switch (major){ case 1: p_search = applistr; break; case 2: p_search = audiostr; break; case 3: p_search = imagestr; break; case 4: p_search = messagestr; break; case 5: p_search = modelstr; break; case 6: p_search = textstr; break; case 7: p_search = videostr; break; default: p_search = undefstr; major = 8; } break; } p_search++; } if (!flag){ p_search = undefstr; major = 8; } flag = 0; minor = 0; while (*p_search){ len=0; while((*p_search) != 0x20){ token[len] = ((*p_search)==0x3d)? 0x20 : (*p_search); p_search++; len++; } token[len] = 0; minor++; if (strstr(magic_buf,token)){ flag = 1; break; } p_search++; } if(!flag) minor=255; #ifdef DEBUG_MAGIC_SCAN printf("major : %d minor : %d\n", major,minor); #endif *scan = (major <<8)| minor; return 1; } static int analysis_ret1(char* typename, struct found_data_t* f_data, int ret , int b_count, __u32 offset, __u32 last_match){ if (last_match) f_data->last_match_blk = (last_match/current_fs->blocksize) +1 ; if (ret){ f_data->scantype = DATA_CARVING; f_data->size = offset; if (offset > (b_count * current_fs->blocksize)) f_data->buf_length = b_count; else f_data->buf_length = offset / current_fs->blocksize; f_data->next_offset = offset - (f_data->buf_length * current_fs->blocksize); } switch (ret){ case 0 : // fprintf(stderr,"%s-CHECK: Block %lu : Break \n",typename,f_data->first); f_data->scantype |= DATA_BREAK; f_data->first = 0; return 0; break; case 1: break; case 2 : f_data->scantype |= DATA_READY; if(offset % current_fs->blocksize)(f_data->buf_length)++; break; case 3 : f_data->scantype = 0; // printf("%s %lu can not recover over data carving\n",typename,f_data->first); break; } return ret; } static int analysis_ret2(char* typename, struct found_data_t* f_data, int ret, __u32 offset, __u32 last_match){ if (last_match) f_data->last_match_blk = ((f_data->size - f_data->next_offset + last_match)/current_fs->blocksize) +1 ; if (ret){ f_data->size += offset - f_data->next_offset; f_data->buf_length = offset / current_fs->blocksize; f_data->next_offset = offset - (f_data->buf_length * current_fs->blocksize); } switch (ret){ case 0 : // fprintf(stderr,"%s-CHECK: data error block %lu , recover not\n",typename, f_data->last+(offset / current_fs->blocksize)); f_data->scantype |= DATA_BREAK; break; case 1 : // fprintf(stderr,"%s-CHECK: data next found\n", typename); break; case 2 : // fprintf(stderr,"%s-CHECK: data end found, recover\n", typename); f_data->scantype |= DATA_READY; if(offset % current_fs->blocksize) (f_data->buf_length)++; break; case 3 : // printf("%s-CHECK: %lu : break data following -> block scan now\n",typename,f_data->first); break; } return ret; } //FLAC__crc16_table /* CRC-16, poly = x^16 + x^15 + x^2 + x^0, init = 0 */ __u16 FLAC__crc16_table[256] = { 0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011, 0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022, 0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072, 0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041, 0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2, 0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1, 0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1, 0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082, 0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192, 0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1, 0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1, 0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2, 0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151, 0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162, 0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132, 0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101, 0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312, 0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321, 0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371, 0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342, 0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1, 0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2, 0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2, 0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381, 0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291, 0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2, 0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2, 0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1, 0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252, 0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261, 0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231, 0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202}; __u16 FLAC__crc16(const unsigned char *data, unsigned len, __u16 crc_last){ __u32 crc = (crc_last) ? crc_last : 0 ; while(len--) crc = ((crc<<8) ^ FLAC__crc16_table[(crc>>8) ^ *data++]) & 0xffff; return crc; } static __u32 test_id3_tag(unsigned char *buf){ __u32 offset = 0; if(buf[0]=='I' && buf[1]=='D' && buf[2]=='3' && (buf[3]==2 || buf[3]==3 || buf[3]==4) && buf[4]==0){ if(buf[3]==4 && (buf[5]&0x10)==0x10) offset = 10 ; offset += ((buf[6]&0x7f)<<21) + ((buf[7]&0x7f)<<14) + ((buf[8]&0x7f)<<7) + (buf[9]&0x7f)+ 10; // fprintf (stderr,"ID3-TAG found : size %lu \n", offset); } return offset; } static int read_ebml(__u64* p_con , void* ebml){ int i,j; unsigned char c, *p; p = (unsigned char*) ebml; c = 0x80; for (i=8;i>0;i--){ if ( *p & c) break; c = c >>1 ; } if (!i) return 0; *p_con = (__u64) (*p & ~c); p++; for (j=8 ; j > i; j--){ *p_con = (*p_con <<8); *p_con += (__u64)*p; p++; } return 9 - i; } /* // skeleton function (Version: 0.3.0) // The following functions control the recover of the individual file types. All this functions have the same // call parameters and run on a common function-pointer. // This is a statement of values and variables for your own extensions. // For each file type, such a specific function can be defined. If no function is assigned, is used automatically "file_default()". // In accordance with the scan result one of these functions is selected by "get_file_property()" // and invoked during the program run, with different parameters for different tasks. // The variables have also different meanings. int file_dummy(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ switch (flag){ // the function is controlled by the variable "flag" case 0 : // Called to test whether the file is encountered. // unsigned char *buf == pointer to the data of the current last known block // (allowed access buf[0] to buf[blocksize-1] ) // int *size == pointer to the "size" of this block. (means: The last character which is not NULL.) // this can be changed here to set the correct file length // __u32 scan == undefined // struct found_data_t* f_data == pointer to the data structure of its own file, including the generated inode. allowed full access to all fields. return // 0 == this is not a file end (do not recover now) // 1 == file end is here ; File length is adjusted according to the value in "size". (The length of the last block) // recover this file. // 2 == The file could end here if the next block is a new file. (Or the next data block can not be attached) // File length is adjusted accordingly "size". recover if possible // 4 == As at "return 2" ; but not if the length of the file currently has 12 blocks. //FIXME case 1 : // Test if a single block can be added to the file or has a wrong content for this file.(ext3 only small files <= 12*blocksize) // unsigned char *buf == undefined // int *size == undefined // __u32 scan == the scan result of the next data block, Use the Macro in src/util.h // struct found_data_t* f_data == undefined return // 0 == not attach this block // 1 == attach this block case 2: // Called during initialization, can test the beginning of the file and the initial course of the file // unsigned char *buf == pointer to data blocks for a possible new file of this type // (allowed access buf[-blocksize] to buf[(blocksize * 12]) -1 ) // The data of the file can be checked up to 12 data block. // For many file types can be determined in the final file length. // int *size == undefined // __u32 scan == undefined // struct found_data_t* f_data == pointer to the new data structure for the new file. // allowed full access to all fields, except inode, (these data are not produced at this time). // possible change of the name for the file, or change the file_function() for this filetype, // often a sign created for the file length in the variable "f_data->size", which will // be used later for file length determination. (see "case 0:" ) // f_data->func = NULL or f_data->first = 0 prevent the recover of the file return // the return value is currently not evaluated . case 3: // Called if set "f_data->scantype = DATA_CARVING" to check all the blocks of a file. // All properties from "case 3" are also available below "case 2" but there only maximum of the first 12 blocks // unsigned char *buf == pointer to data blocks for a possible append to file (max 16 blocks) // int *size == undefined // __u32 scan == undefined // struct found_data_t* f_data == pointer to the new data structure for the new file. // There a any flags and variable to control this function, these have to be evaluated and/or re-set in this function. // f_data->scantype (control method flag ; break or ready see also util.h) // f_data->buf_length (how many blocks, input blocks availabe (max 16); output how many blocks add to file corresponding with f_data->next_offset) // f_data->last_match_blk (output the last matching logical block) // f_data->next_offset (input and output the offset relative to the first block in buf) // f_data->size ( output the current total size of the file to f_data->next_offset) // the pointer f_data->priv can hold private data, (allocated) return // 0 == break; // 1 == countinue // 2 == ready // control f_data->scantype // must set f_data->next_offset; f_data->buf_length ; optional f_data->last_match_blk and f_data->size // break; case 4 : // If private memory has been alloc to f_data->priv must free here. // In this case not use f_data->func = NULL at "case 2", that would lead to a memory error here. // return value is currently not evaluated . break; } } */ //default int file_default(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 0; switch (flag){ case 0 : if(f_data->scantype & DATA_METABLOCK){ ret = 1; break; } else{ if (*size < (current_fs->blocksize -4)) ret = 4; if (*size < (current_fs->blocksize -64)) ret = 2; if (*size < (current_fs->blocksize -256)) ret = 1; } break; case 1 : return (scan & (M_IS_META | M_CLASS_1)) ? 0 :1 ; break; } return ret; } //none #do not recover this int file_none(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ return 0; } //Textfiles int file_txt(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ switch (flag){ case 0 : if (*size < current_fs->blocksize){ if (buf[(*size)-1] == (unsigned char)0x0a) return 1; } else { if (buf[(*size)-1] == (unsigned char)0x0a) return (f_data->scantype & DATA_METABLOCK) ? 2 : 4 ; } break; case 1 : return (scan & M_TXT); break; } return 0; } //html int file_html(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ switch (flag){ case 0 : if (*size < current_fs->blocksize){ if ((buf[(*size)-1] == (unsigned char)0x0a) || (buf[(*size)-1] == (unsigned char)0x3e)) return 1; } else { if (buf[(*size)-1] == (unsigned char)0x0a) return (f_data->scantype & DATA_METABLOCK) ? 2 : 4 ; } break; case 1 : return (scan & M_TXT); break; } return 0; } //troff just check > forward to file_txt int chk_troff(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ char c[8][2] = {{0x2e,0x22},{0x0a,0x2e},{0x0a,0x5c},{0x2e,0x53},{0x2e,0x54},{0x2e,0x50},{0x5c,0x2d},{0x2e,0x42}}; int ret=0; int i,j; if (flag ==2){ i=0; while ((!ret)&&( i++ < 24)){ if (buf[i] == 0x20) ret++; } i=0; while ((ret == 1)&&( i++ < 80)){ if (buf[i] == 0x0a) ret++; if (!buf[i]) ret = 0; } i=0; while ((ret == 2)&&( i++ < 256)){ for (j=0; j<8;j++){ if ((buf[i] == c[j][0]) && (buf[i+1] == c[j][1])){ ret++; break; } } } if (ret == 3) f_data->func =file_txt; else f_data->func = NULL; } return 1; } //Textfiles binary int file_bin_txt(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ switch (flag){ case 0 : if (*size < current_fs->blocksize){ return 1; } else { if (buf[(*size)-1] == (unsigned char)0x0a) return (f_data->scantype & DATA_METABLOCK) ? 2 : 4 ; } break; case 1 : return (scan & M_TXT); break; } return 0; } struct zip_priv_t{ int flag; __u32 count;}; static int follow_zip(unsigned char *buf, __u16 blockcount, __u32 *offset, __u32 *last_match, struct zip_priv_t * priv){ #define ZIP_CENTRAL_DIR 0x02014B50 #define ZIP_FILE_ENTRY 0x04034B50 #define ZIP_SIGNATURE 0x05054B50 #define ZIP_END_CENTRAL_DIR 0x06054B50 #define ZIP_CENTRAL_DIR64 0x06064B50 #define ZIP_END_CENTRAL_DIR64 0x07064B50 #define ZIP_EXTRA_DATA 0x08064B50 #define ZIP_DATA_DESCRIPTOR 0x08074B50 __u32 i=*offset; int ret = 1; __u32 header; __u32 end = (blockcount * current_fs->blocksize)-30; __u16 *p_16; __u32 *p_32; if (i == end) end++; while ((ret == 1 )&& ( i < end )){ if (priv->flag){ while ((i < end) && (!((buf[i] == 0x50) && (buf[i+1] ==0x4B) && (buf[i+2] ==0x07)&& (buf[i+3] ==0x08)))){ (priv->count)++; i++; if (priv->count > 4194304){ // only 4MB then we give up ret = 3; break; } } if ((i == end)||(ret == 3)) break; p_32 = (__u32*)(buf+i+8); if (ext2fs_le32_to_cpu(*p_32) == priv->count){ priv->flag = 0; *last_match = i+1; } else{ ret = 0; break; } } else{ header = ext2fs_le32_to_cpu(*(__u32*)(buf+i)); switch (header){ case ZIP_CENTRAL_DIR : *last_match = i +1; p_16 = (__u16*)(buf+i+28); i += ext2fs_le16_to_cpu(*p_16); p_16++; i += ext2fs_le16_to_cpu(*p_16) + 46; p_16++; i += ext2fs_le16_to_cpu(*p_16); break; case ZIP_FILE_ENTRY : *last_match = i+1; p_32 = (__u32*)(buf+i+18); if (! ext2fs_le32_to_cpu(*p_32)){ if ( (buf[i+6] & 0x08) ){ priv->flag = 1; priv->count = 0; } } p_16 = (__u16*)(buf+i+26); i += ext2fs_le32_to_cpu(*p_32) + ext2fs_le16_to_cpu(*p_16); p_16++; i += ext2fs_le16_to_cpu(*p_16) + 30; break; case ZIP_SIGNATURE : *last_match = i +1; p_16 = (__u16*)(buf+i+4); i += ext2fs_le16_to_cpu(*p_16) + 6; break; case ZIP_END_CENTRAL_DIR : *last_match = i +1; p_16 = (__u16*)(buf+i+20); i += ext2fs_le16_to_cpu(*p_16) + 22; ret = 2; break; //I think the follow is never needed case ZIP_EXTRA_DATA : // p_32 = (__u32*)(buf+i+4); // i += ext2fs_le32_to_cpu(*p_16) + 8; //break; case ZIP_CENTRAL_DIR64 : // i + 12 ; // ret = 2 ; //break; case ZIP_END_CENTRAL_DIR64 : case ZIP_DATA_DESCRIPTOR : *last_match = i +1; i+=16; if (buf[i] != 0x50) ret = 3; break; default : ret = 0 ; break; } } } *offset = i; return ret; } //------------------------------- #include #include #define OUTLEN 8000 struct priv_zlib_t { __u32 flag; __u32 crc; z_stream z_strm; unsigned char out_buf[OUTLEN]; }; struct priv_bzlib_t { __u32 flag; bz_stream b_strm; unsigned char out_buf[OUTLEN]; }; static int init_priv_zlib(struct found_data_t* f_data){ struct priv_zlib_t *private = NULL; private = malloc(sizeof(struct priv_zlib_t)); if (!private){ fprintf(stderr,"ERROR: can't allocate memory\n"); return 1; } private->flag = 0; private->crc = 0; memset(&(private->z_strm),0,sizeof(z_stream)); f_data->priv = private; return 0; } static int init_priv_bzlib(struct found_data_t* f_data){ struct priv_bzlib_t *private = NULL; private = malloc(sizeof(struct priv_bzlib_t)); if (!private){ fprintf(stderr,"ERROR: can't allocate memory\n"); return 1; } private->flag = 0; memset(&(private->b_strm),0,sizeof(bz_stream)); f_data->priv = private; return 0; } static int follow_zlib(unsigned char *buf, __u16 blockcount, __u32 *offset, __u32 *last_match, struct priv_zlib_t *priv){ int ret = 1; //priv->flag: Bit0=initialize2 ; Bit1=initialize ; Bit2=check maxout; Bit3=crc32 ; Bit15=Init int z_ret = 0; //0x0b = initialize for gzip , or use 0x06 for z int end = blockcount * current_fs->blocksize; __u32 p_offset ; __u32 total ; unsigned char *out = &(priv->out_buf[0]); //----------------- Initialize if ((priv->flag) & 0x2){ if ((priv->flag) & 0x8) priv->crc = 0; if ((priv->flag) & 0x4) priv->crc = *offset; //compr. size priv->z_strm.zalloc = Z_NULL; priv->z_strm.zfree = Z_NULL; priv->z_strm.opaque = Z_NULL; priv->z_strm.avail_in = 0; priv->z_strm.next_in = Z_NULL; if ((priv->flag) & 0x1) z_ret = inflateInit2(&(priv->z_strm), -MAX_WBITS); else z_ret = inflateInit(&(priv->z_strm)); if ((z_ret != Z_OK) || (!out)){ printf("Error: init zlib\n"); } priv->flag &= ~0x3; priv->flag |= 0x80; //flag = if necessary use inflateEnd return z_ret; } //---------------------- Decompress p_offset = *offset; total = priv->z_strm.total_in; priv->z_strm.next_in = buf + p_offset ; priv->z_strm.avail_in = end - p_offset; priv->z_strm.next_out = out; priv->z_strm.avail_out = OUTLEN; while ((ret == 1) && (!z_ret) && (priv->z_strm.avail_in)){ z_ret = inflate(&(priv->z_strm), Z_NO_FLUSH); p_offset = priv->z_strm.total_in - total + *offset ; if (!(priv->z_strm.avail_out)){ if ((priv->flag) & 0x8) priv->crc = crc32(priv->crc, out, OUTLEN - priv->z_strm.avail_out); priv->z_strm.next_out = out; priv->z_strm.avail_out = OUTLEN; *last_match = p_offset ; } if (((priv->flag) & 0x4) && (priv->crc < priv->z_strm.total_out)) ret = 0; } if (((priv->flag) & 0x8)&&(OUTLEN - priv->z_strm.avail_out)) priv->crc = crc32(priv->crc, out, OUTLEN - priv->z_strm.avail_out); if (z_ret == Z_STREAM_END){ if ((priv->flag) & 0x8){ if ((priv->z_strm.avail_in > 3) && ((ext2fs_le32_to_cpu (*(__u32*)(buf + p_offset))) == priv->crc )){ p_offset += 8; ret = 2; } else ret = 0; } else ret =2; inflateEnd(&(priv->z_strm)); priv->flag = 0; } else if ((!ret) || (z_ret && (z_ret != Z_STREAM_END))){ inflateEnd(&(priv->z_strm)); priv->flag = 0; ret = 0; } *offset = p_offset; return ret; } static int follow_bz2lib(unsigned char *buf, __u16 blockcount, __u32 *offset, __u32 *last_match, struct priv_bzlib_t *priv){ int ret = 1; //flag: Bit1=initialize int z_ret = 0; int end = blockcount * current_fs->blocksize; __u32 p_offset ; __u32 total ; unsigned char *out = &(priv->out_buf[0]); if ((priv->flag) & 0x2){ //DecompressInit priv->b_strm.bzalloc = Z_NULL; priv->b_strm.bzfree = Z_NULL; priv->b_strm.opaque = Z_NULL; priv->b_strm.avail_in = 0; priv->b_strm.avail_out = 0; priv->b_strm.next_in = Z_NULL; z_ret = BZ2_bzDecompressInit ( &(priv->b_strm), 0, 1 ); if (z_ret != BZ_OK){ BZ2_bzDecompressEnd( &(priv->b_strm) ); } priv->flag = 0x80; return z_ret; } //---------------------- Decompress p_offset = *offset; total = priv->b_strm.total_in_lo32; priv->b_strm.next_in = (char*)buf + p_offset ; priv->b_strm.avail_in = end - p_offset; priv->b_strm.next_out = (char*)out; priv->b_strm.avail_out = OUTLEN; while ((z_ret >=0) && (z_ret != BZ_STREAM_END) && (priv->b_strm.avail_in)){ z_ret = BZ2_bzDecompress ( &(priv->b_strm) ); p_offset = priv->b_strm.total_in_lo32 - total + *offset ; if ((z_ret == BZ_OUTBUFF_FULL) || (!priv->b_strm.avail_out)){ priv->b_strm.next_out = (char*)out; priv->b_strm.avail_out = OUTLEN; *last_match = p_offset ; z_ret = 0; } } if (z_ret){ ret = (z_ret == BZ_STREAM_END) ? 2 : 0 ; BZ2_bzDecompressEnd( &(priv->b_strm) ); priv->flag = 0; } *offset = p_offset; return ret; } //gzip int file_gzip(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ #define GZ_FTEXT 1 #define GZ_FHCRC 2 #define GZ_FEXTRA 4 #define GZ_FNAME 8 #define GZ_FCOMMENT 0x10 int z_flags, b_count, ret = 0; __u32 offset; __u32 last_match = 0; switch (flag){ case 0 : if(f_data->scantype & DATA_READY){ *size = (f_data->next_offset)?f_data->next_offset : *size; ret = 1; } else{ if(*size < (current_fs->blocksize -8)) ret = 1 ; else { if(*size < (current_fs->blocksize -4)) ret = 2 ; } *size += 4; } break; case 1 : return ((scan & (M_IS_META | M_CLASS_1 | M_BLANK | M_TXT))||(f_data->scantype & DATA_READY)) ? 0 :1 ; break; case 2 : if(init_priv_zlib(f_data)) return 0; ((struct priv_zlib_t*)(f_data->priv))->flag = 0xb; if ((buf[0]==0x1F)&&(buf[1]==0x8B)&&(buf[2]==0x08)&&((buf[3]&0xe0)==0)&& (!follow_zlib(NULL,0,NULL,NULL,(struct priv_zlib_t *)f_data->priv))){ offset = 10; z_flags=buf[3]; if((z_flags&GZ_FEXTRA)!=0){ offset += 2; offset += (buf[10]|(buf[11]<<8)); } if((z_flags&GZ_FNAME)!=0){ while( (offset < 256) && (buf[offset++]!='\0')){ } } if((z_flags&GZ_FCOMMENT)!=0){ while((offset<1024) && (buf[offset++]!='\0')){ } } if((z_flags&GZ_FHCRC)!=0){ offset+=2; } b_count = (f_data->buf_length > 12) ? 12 : f_data->buf_length ; ret = follow_zlib(buf, b_count, &offset, &last_match,(struct priv_zlib_t *)f_data->priv); ret = analysis_ret1("GZIP", f_data, ret , b_count, offset, last_match); } else f_data->first = 0; break; case 3 : offset = f_data->next_offset ; ret = follow_zlib(buf, f_data->buf_length, &offset, &last_match,(struct priv_zlib_t *)f_data->priv); ret = analysis_ret2("GZIP", f_data, ret, offset, last_match); break; case 4: if (f_data->priv){ if (((struct priv_zlib_t*)(f_data->priv))->flag) inflateEnd( &((struct priv_zlib_t*)(f_data->priv))->z_strm); free(f_data->priv); } break; } return ret; } //bzip2 int file_bzip2(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int b_count, ret = 0; __u32 offset; __u32 last_match = 0; switch (flag){ case 0 : if(f_data->scantype & DATA_READY){ *size = (f_data->next_offset)?f_data->next_offset : *size; ret = 1; } else{ if(*size < (current_fs->blocksize -8)) ret = 1 ; else { if(*size < (current_fs->blocksize -4)) ret = 2 ; } *size += 4; } break; case 1 : return ((scan & (M_IS_META | M_CLASS_1 | M_BLANK | M_TXT))||(f_data->scantype & DATA_READY)) ? 0 :1 ; break; case 2 : offset = 0; if(init_priv_bzlib(f_data)) return 0; ((struct priv_bzlib_t*)(f_data->priv))->flag = 0x2; b_count = (f_data->buf_length > 12) ? 12 : f_data->buf_length ; ret = follow_bz2lib(NULL, 0, NULL, NULL, (struct priv_bzlib_t *)f_data->priv); if (! ret) ret = follow_bz2lib(buf, b_count, &offset, &last_match,(struct priv_bzlib_t *)f_data->priv); else return 0; ret = analysis_ret1("BZIP2", f_data, ret , b_count, offset, last_match); break; case 3 : offset = f_data->next_offset ; ret = follow_bz2lib(buf, f_data->buf_length, &offset, &last_match, (struct priv_bzlib_t *)f_data->priv); ret = analysis_ret2("BZIP2", f_data, ret, offset, last_match); break; case 4: if (f_data->priv){ if (((struct priv_bzlib_t*)(f_data->priv))->flag) BZ2_bzDecompressEnd( &((struct priv_bzlib_t*)(f_data->priv))->b_strm); free(f_data->priv); } break; } return ret; } //zip int file_zip(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 0; int j,i, b_count; char token[5]; __u32 last_match = 0; struct zip_priv_t *z_priv = NULL; __u32 offset; sprintf(token,"%c%c%c%c",0x50,0x4b,0x05,0x06); switch (flag){ case 0 :if(f_data->scantype & DATA_READY){ *size = (f_data->next_offset)?f_data->next_offset : current_fs->blocksize ; ret = 1; } else{ if((*size) > 22){ j = strlen(token) -1; i = (*size -12); while((i > ((*size)-22)) && (buf[i] != token[j])){ i--; } while ((i> ((*size)-22)) && (j >= 0) && (buf[i] == token[j])){ j--; i--; } if ( j<0){ *size = i+22+1; ret =1; } } else{ *size += 4; ret = 2; } } break; case 1 : return ((scan & (M_IS_META | M_CLASS_1 | M_BLANK))||(f_data->scantype & DATA_READY)) ? 0 :1 ; break; case 2 : offset = 0; z_priv = malloc(sizeof(struct zip_priv_t)); if (!z_priv){ f_data->first = 0; return 0; } z_priv->flag = 0; z_priv->count = 0; f_data->priv = z_priv; b_count = (f_data->buf_length > 12) ? 12 : f_data->buf_length ; ret = follow_zip(buf, b_count, &offset, &last_match,f_data->priv); ret = analysis_ret1("ZIP", f_data, ret , b_count, offset, last_match); break; case 3 : offset = f_data->next_offset ; ret = follow_zip(buf, f_data->buf_length, &offset, &last_match,f_data->priv); ret = analysis_ret2("ZIP", f_data, ret, offset, last_match); break; case 4 : if (f_data->priv) free(f_data->priv); break; } return ret; } //x-compress int file_lzw(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 0; switch (flag){ case 0 : if(f_data->scantype & DATA_METABLOCK){ ret = 1; break; } else{ if (*size < (current_fs->blocksize -3)){ *size += 2; ret = 2; } if (*size < (current_fs->blocksize -6)){ *size += 2; ret = 1; } } break; case 1 : return (scan & (M_IS_META | M_CLASS_1)) ? 0 :1 ; break; case 2 : if ((buf[2] & 0x60) || ((buf[2] & 0x1F)<12) || ((buf[2] & 0x1F)>16)) f_data->first = 0; break; } return ret; } //rpm int file_rpm(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ #define GZ_FTEXT 1 #define GZ_FHCRC 2 #define GZ_FEXTRA 4 #define GZ_FNAME 8 #define GZ_FCOMMENT 0x10 int i, z_flags, b_count, ret = 0; __u32 offset; __u32 last_match = 0; __u32 h_count,h_size; __u32 p_size = 0; switch (flag){ case 0 : if(f_data->scantype & DATA_READY){ *size = (f_data->next_offset)?f_data->next_offset : *size; ret = 1; } else{ if (f_data->scantype & DATA_LENGTH) { if (f_data->inode->i_size < f_data->size) ret = 0; else{ p_size = ((f_data->size-1) % current_fs->blocksize)+1; if (*size < p_size) *size = p_size; ret = 1; } } else{ if(*size < (current_fs->blocksize -8)) ret = 1 ; else { if(*size < (current_fs->blocksize -4)) ret = 2 ; } *size += 2; } } break; case 1 : return ((scan & (M_IS_META | M_CLASS_1 | M_BLANK | M_TXT))||(f_data->scantype & DATA_READY)) ? 0 :1 ; break; case 2 : if (!((buf[0]==0xed)&&(buf[1]==0xab)&&(buf[2]==0xee)&&(buf[3]==0xdb)&&(buf[4]==0x03))){ f_data->func = file_default ; return 0; } if (buf[7] == 1){ f_data->name[strlen(f_data->name)-3] = 0 ; strncat(f_data->name,"srpm",6); } offset=96; if ((buf[offset]== 0x8e)&&(buf[offset+1]== 0xad)&&(buf[offset+2]== 0xe8)) { h_count=((buf[offset+8]<<24)|(buf[offset+9]<<16)|(buf[offset+10]<<8)|(buf[offset+11])); h_size=((buf[offset+12]<<24)|(buf[offset+13]<<16)|(buf[offset+14]<<8)|(buf[offset+15])); for (i=0;ibuf_length > 12) ? 12 : f_data->buf_length ; if (((offset+12) > (b_count *current_fs->blocksize)) || (buf[offset]!=0x1F)||(buf[offset+1]!=0x8B)|| (buf[offset+2]!=0x08)||((buf[offset+3]&0xe0)!=0) || (init_priv_zlib(f_data))){ f_data->size = p_size ; f_data->scantype = DATA_LENGTH ; ret = 1; break; } else { ((struct priv_zlib_t*)(f_data->priv))->flag = 0xb; if (!follow_zlib(NULL,0,NULL,NULL,(struct priv_zlib_t *)f_data->priv)){ z_flags=buf[offset+3]; offset += 10; if((z_flags&GZ_FEXTRA)!=0){ offset += (buf[offset]|(buf[offset+1]<<8)); offset += 2; } if((z_flags&GZ_FNAME)!=0){ while( (offset < 256) && (buf[offset++]!='\0')){ } } if((z_flags&GZ_FCOMMENT)!=0){ while((offset<1024) && (buf[offset++]!='\0')){ } } if((z_flags&GZ_FHCRC)!=0){ offset+=2; } ret = follow_zlib(buf, b_count, &offset, &last_match,(struct priv_zlib_t *)f_data->priv); ret = analysis_ret1("RPM", f_data, ret , b_count, offset, last_match); } else f_data->first = 0; } break; case 3 : offset = f_data->next_offset ; ret = follow_zlib(buf, f_data->buf_length, &offset, &last_match,(struct priv_zlib_t *)f_data->priv); ret = analysis_ret2("RPM", f_data, ret, offset, last_match); break; case 4: if (f_data->priv){ if (((struct priv_zlib_t*)(f_data->priv))->flag) inflateEnd( &((struct priv_zlib_t*)(f_data->priv))->z_strm); free(f_data->priv); } break; } return ret; } //ttf int file_ttf(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ __u32 table_id[9] = {0x70616d63,0x66796c67,0x64616568,0x61656868,0x78746d68,0x61636f6c,0x7078616d,0x656d616e,0x74736f70}; int i,j,id_count,ret = 0; __u16 tables ; //s_range, shift; __u32 *p, id, tmp; unsigned char *c; switch (flag){ case 0 : if(((*size) < (current_fs->blocksize - 16))|| (f_data->inode->i_size > f_data->size)){ *size = ((*size ) + 3) & ~3 ; ret =1; } else { *size = ((*size ) + 3) & ~3 ; ret = 2; } break; case 1 :return (scan & (M_IS_META | M_CLASS_1 | M_BLANK)) ? 0 :1 ; break; case 2 : id_count = 0; tables = (buf[4]<<8) + buf[5]; c = (unsigned char*) buf + 12; for (i = 0; i< tables; i++){ p = (__u32*)c; id = ext2fs_le32_to_cpu(*p); for (j=0;j<9;j++){ if (id == table_id[j]){ id_count++; break; } } for (j=0;j<4;j++){ if (( *c < 32) || ((*c > 126) && (*c != 0xa9))){ f_data->func = NULL; return 0; } c++; } p = (__u32*)(c + 4); tmp = ext2fs_be32_to_cpu(*p); p++; tmp += ext2fs_be32_to_cpu(*p); if (f_data->size < tmp) f_data->size = tmp; c+=12; } if(id_count < 5){ f_data->func = NULL; ret = 0; } else { f_data->size = (f_data->size +3) & ~3 ; f_data->scantype = DATA_LENGTH ; ret = 1; } break; } return ret; } //iso9660 CD-ROM int file_iso9660(unsigned char *buf, int *size, __u32 scan , int flag , struct found_data_t* f_data){ __u64 lsize = 0; __u32 *p_32; __u16 *p_16; int ssize; int ret = 0; char cd_str[] = "CD001"; switch (flag){ case 0 : if (f_data->size || f_data->h_size) { if (f_data->h_size != f_data->inode->i_size_high) ret = 0; else{ if (f_data->inode->i_size < f_data->size) ret = 0; else{ ssize = ((f_data->size-1) % current_fs->blocksize)+1; *size = (ssize)? ssize : current_fs->blocksize; ret = 1; } } } else { ret =0; } break; case 1 : return 1; break; case 2 : if (current_fs->blocksize > 2048){ p_32 = (__u32*)(buf + 0x8050); p_16 = (__u16*)(buf + 0x8080); if ((!strncmp(((char*)buf+0x8001),cd_str,5)) && (ext2fs_le32_to_cpu(*(p_32 +1)) == ext2fs_be32_to_cpu(*p_32))){ lsize = (__u64)(ext2fs_le32_to_cpu(*p_32)) * ext2fs_le16_to_cpu(*p_16); f_data->size = lsize & 0xFFFFFFFF; f_data->h_size = lsize >> 32; ret =1; } } if (!lsize) f_data->first = 0; break; } return ret; } //gnumeric only switch to gzip or xml int file_gnumeric(unsigned char *buf, int *size, __u32 scan , int flag , struct found_data_t* f_data){ if ((buf[0]==0x1F)&&(buf[1]==0x8B)&&(buf[2]==0x08)&&((buf[3]&0xe0)==0)) f_data->func = file_gzip; else f_data->func = file_txt; return f_data->func(buf, size,scan,flag,f_data); } //dvi int file_dvi(unsigned char *buf, int *size, __u32 scan , int flag , struct found_data_t* f_data){ int ret = 0; int i,j; switch (flag){ case 0 : j = 3; i = (*size) -1; while ((i >= 0) && (j >= 0) && (buf[i] == 0xdf)){ i--; j--; } if ((i == -1) || (j == -1)){ ret = 1; } break; case 1 : return (scan & (M_IS_META | M_CLASS_1| M_BLANK | M_TXT)) ? 0 :1 ; break; case 2 : if(buf[14]){ //test for preamble comment for (i=0; ifunc = NULL; return 0; } } } else f_data->func = NULL; break; } return ret; } //lzma int file_lzma(unsigned char *buf, int *size, __u32 scan , int flag , struct found_data_t* f_data){ int ret = 0; switch (flag){ case 0 : if ((*size< (current_fs->blocksize - 3))) ret = 1; break; case 1 : return (scan & (M_IS_META | M_CLASS_1| M_BLANK | M_TXT)) ? 0 :1 ; break; } return ret; } // 7-zip int file_7z(unsigned char *buf, int *size, __u32 scan , int flag , struct found_data_t* f_data){ __u64 lsize,*p; __u32 ssize; int ret = 0; switch (flag){ case 0 : if (f_data->size || f_data->h_size) { if (f_data->h_size != f_data->inode->i_size_high) ret = 0; else{ if (f_data->inode->i_size < f_data->size) ret = 0; else{ ssize = ((f_data->size-1) % current_fs->blocksize)+1; if (*size < ssize) *size = ssize; ret = 1; } } } else { ret =0x10; //not recover for now *size += 7; } break; case 1 : return ( scan & (M_IS_META | M_CLASS_1 | M_BLANK)) ? 0 :1 ; break; case 2 : p = (__u64*)(buf+12); lsize = ext2fs_le64_to_cpu(*p) + (__u64)32; p++; lsize = lsize + (ext2fs_le64_to_cpu(*p)); f_data->size = lsize & 0xFFFFFFFF ; f_data->h_size = lsize >> 32; f_data->scantype = DATA_LENGTH ; ret = 1; break; } return ret; } static int follow_rar(unsigned char *buf, __u16 blockcount, __u32 *offset, __u32 *last_match, int flag){ int ret = 1 ; __u32 tmp ; __u32 f_offset = *offset; while ((ret ==1) && (f_offset < ((blockcount * current_fs->blocksize)-10))){ switch (buf[f_offset +2]){ case 0x7b: if(zero_space(buf,f_offset+7)) ret = 2; case 0x72: *last_match = f_offset; f_offset += ((buf[f_offset +6]<<8) + (buf[f_offset +5])); break; case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: case 0x78: *last_match = f_offset; tmp = ((buf[f_offset +6]<<8) + (buf[f_offset +5])); tmp += ((buf[f_offset +10]<<24) + (buf[f_offset +9]<<16) + (buf[f_offset +8]<<8) + (buf[f_offset +7])); f_offset += tmp; break; default: ret = 0; } } *offset = f_offset; return ret; } //rar int file_rar(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int i,j, b_count; int ret = 0; __u32 offset; __u32 last_match = 0; unsigned char token[7]={0xc4, 0x3d, 0x7b, 0x00, 0x40, 0x07, 0x00 }; switch (flag){ case 0 : if (f_data->scantype & DATA_READY){ *size = f_data->size % current_fs->blocksize; ret = 1; break; } j = 5; i = (*size) -1; while ((i >= 0) && (j >= 0) && (buf[i] == token[j])){ i--; j--; } if ((i == -1) || (j == -1)){ *size = (*size) + 1; ret = 1; } break; case 1 : return ((scan & (M_IS_META | M_CLASS_1 | M_BLANK))||(f_data->scantype & DATA_READY)) ? 0 :1 ; break; case 2 : offset = 0; b_count = (f_data->buf_length > 12) ? 12 : f_data->buf_length ; ret = follow_rar(buf, b_count, &offset, &last_match,0); ret = analysis_ret1("RAR", f_data, ret , b_count, offset, last_match); break; case 3 : offset = f_data->next_offset ; ret = follow_rar(buf, f_data->buf_length, &offset, &last_match,0); ret = analysis_ret2("RAR", f_data, ret, offset, last_match); break; } return ret; } static int follow_cpio(unsigned char *buf, __u16 blockcount, __u32 *offset, __u32 *last_match, int flag){ struct header_old_cpio { unsigned short c_magic; unsigned short c_dev; unsigned short c_ino; unsigned short c_mode; unsigned short c_uid; unsigned short c_gid; unsigned short c_nlink; unsigned short c_rdev; unsigned short c_mtime[2]; unsigned short c_namesize; unsigned short c_filesize[2]; }; struct cpio_odc_header { char c_magic[6]; char c_dev[6]; char c_ino[6]; char c_mode[6]; char c_uid[6]; char c_gid[6]; char c_nlink[6]; char c_rdev[6]; char c_mtime[11]; char c_namesize[6]; char c_filesize[11]; }; struct cpio_newc_header { char c_magic[6]; char c_ino[8]; char c_mode[8]; char c_uid[8]; char c_gid[8]; char c_nlink[8]; char c_mtime[8]; char c_filesize[8]; char c_devmajor[8]; char c_devminor[8]; char c_rdevmajor[8]; char c_rdevminor[8]; char c_namesize[8]; char c_check[8]; }; char footer[]="TRAILER!!!"; int i, ret = 1; //j; __u64 f_offset = (__u64) *offset; __u32 n_len ; __u64 f_len ; __u8 *o_str; struct header_old_cpio *old_cpio; struct cpio_odc_header *odc_header; struct cpio_newc_header *newc_header; char help[9]; while ((ret ==1) && (f_offset < ((blockcount * current_fs->blocksize)-122))){ n_len = 0; f_len = 0; old_cpio = (struct header_old_cpio*) (buf+f_offset) ; if ((old_cpio->c_magic == 0xc771)||(old_cpio->c_magic == 0x71c7)){ if (strstr((char*)buf+f_offset+sizeof(struct header_old_cpio),footer)) ret=2; if (old_cpio->c_magic == 0xc771) f_offset +=((ext2fs_be16_to_cpu(old_cpio->c_filesize[0])<<16) + ((ext2fs_be16_to_cpu(old_cpio->c_filesize[1])+1) & ~1) + ((ext2fs_be16_to_cpu(old_cpio->c_namesize) +1) & ~1)); else f_offset +=((ext2fs_le16_to_cpu(old_cpio->c_filesize[0])<<16) + ((ext2fs_le16_to_cpu(old_cpio->c_filesize[1])+1) & ~1) + ((ext2fs_le16_to_cpu(old_cpio->c_namesize) +1) & ~1)); *last_match = f_offset+1; f_offset += sizeof(struct header_old_cpio); continue; } else{ if( (buf[f_offset] == 0x30)&&(buf[f_offset+1] == 0x37)&&(buf[f_offset+2] == 0x30)&&(buf[f_offset+3] == 0x37)&&(buf[f_offset+4] == 0x30)){ if (buf[f_offset+5] == 0x37){ if (strstr((char*)buf+f_offset+sizeof(struct cpio_odc_header),footer)) ret=2; odc_header = (struct cpio_odc_header*) old_cpio; o_str = (__u8*) &(odc_header->c_namesize); for (i=0;i<6;i++){ n_len <<= 3; n_len += (*o_str & 0x7) ; o_str++; } o_str = (__u8*) &(odc_header->c_filesize); for (i=0;i<11;i++){ f_len <<= 3; f_len += (*o_str & 0x7) ; o_str++; } if(n_len || f_len){ *last_match = f_offset+1; f_offset += n_len + f_len + sizeof(struct cpio_odc_header); continue; } } else { if (strstr((char*)buf+f_offset+sizeof(struct cpio_newc_header),footer)) ret=2; newc_header = (struct cpio_newc_header*) old_cpio; memcpy(help,newc_header->c_namesize,8); help[8] = 0; n_len = strtoul(help,NULL,16); memcpy(help,newc_header->c_filesize,8); f_len = strtoul(help,NULL,16); if(n_len || n_len){ n_len = (n_len + sizeof(struct cpio_newc_header)+ 3) & ~3; *last_match = f_offset+1; f_offset += n_len + f_len ; f_offset = ((f_offset +3) & ~3); continue; } } } } ret = 0; } *offset = f_offset; return ret; } //cpio int file_cpio(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int i,j,b_count; int ret = 0; __u32 offset; __u32 last_match = 0; char token[]="TRAILER!!!"; switch (flag){ case 0 : if ((((__u64)f_data->inode->i_size |((__u64)f_data->inode->i_size_high<<32)) >= (__u64)f_data->size) && ((*size) < (current_fs->blocksize - 0xff))){ if (!(*size)) *size = current_fs->blocksize; else *size = ((*size) + 0x01ff) & 0xfe00 ; ret = 1; }else{ if (*size){ j = strlen(token) -1; i = (*size) -1; while ((i >= 0) && (j >= 0) && (buf[i] == token[j])){ i--; j--; } if ((i == -1) || (j == -1)){ *size = ((*size) + 0x01FF) & 0xfe00 ; ret=1; } } } break; case 1 : return ((scan & (M_IS_META))||(f_data->scantype & DATA_READY)) ? 0 :1 ; //FIXME break; case 2 : offset = 0; b_count = (f_data->buf_length > 12) ? 12 : f_data->buf_length ; ret = follow_cpio(buf, b_count, &offset, &last_match,0); ret = analysis_ret1("CPIO", f_data, ret , b_count, offset, last_match); break; case 3 : offset = f_data->next_offset ; ret = follow_cpio(buf, f_data->buf_length, &offset, &last_match,0); ret = analysis_ret2("CPIO", f_data, ret, offset, last_match); break; } return ret; } //function currently not used /*static int a2u(unsigned char *buf, __u32 *value){ int count=0; __u32 tmp=0; while ((buf[0+count]==0x20) ||(buf[0+count]==0x0a) ||(buf[0+count]==0x0d)){ count++; } if ((buf[0+count] & 0xc0) != 0x30) return 0; while ((buf[0+count] > 0x2f) && (buf[0+count] < 0x3a)){ tmp *= 10; tmp += (buf[0+count] & 0x0f); count++; } while (buf[0+count]==0x20){ count++; } if (count > 1){ *value = tmp; return count; } return 0; }*/ static int follow_archive(unsigned char *buf, __u16 blockcount, __u32 *offset, __u32 *last_match, int flag){ int ret = 1; __u32 tmp ; __u32 end = blockcount * current_fs->blocksize ; __u32 f_offset = *offset; __u8 *o_str; if ((blockcount ==1) && (f_offset>=(end-59)) && (zero_space(buf,f_offset))) ret = 2; while ((ret ==1) && (f_offset < (end-59))){ if (buf[f_offset] == 0x0a){ f_offset++; continue; } if ((!buf[f_offset]) && (zero_space(buf,f_offset))) ret = 2; else{ if ((buf[58+f_offset]==0x60)&&(buf[59+f_offset]==0x0a)){ tmp = 0; o_str = (buf + 48 + f_offset); while ((*o_str > 0x2f) && (*o_str < 0x3a) && (o_str < (buf + 58 + f_offset))){ tmp *= 10; tmp += (*o_str & 0x0f); o_str++; } if (!tmp) ret = 0; *last_match = f_offset; f_offset += (tmp + 60); } else ret = 0; } } *offset = f_offset; return ret; } //x-archive int file_archive(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 0; __u32 offset,b_count,last_match = 0; switch (flag){ case 0 : if(f_data->scantype & DATA_READY){ *size = (f_data->next_offset)?f_data->next_offset : *size; ret = 1; }else{ if((*size) < (current_fs->blocksize - 16)){ *size = ((*size ) + 3) & ~3 ; ret =1; } else { *size = ((*size ) + 3) & ~3 ; ret = 4; } } break; case 1 :return ((scan & (M_IS_META | M_CLASS_1 | M_BLANK))||(f_data->scantype & DATA_READY)) ? 0 :1 ; break; case 2 : if((buf[0]==0x21)&&(buf[1]==0x3c)&&(buf[2]==0x61)&&(buf[3]==0x72)&&(buf[4]==0x63)&&(buf[5]==0x68)&&(buf[6]==0x3e)) offset = 8; else{ f_data->func = NULL; return 0; } b_count = (f_data->buf_length > 12) ? 12 : f_data->buf_length ; ret = follow_archive(buf, b_count, &offset, &last_match,0); ret = analysis_ret1("AR", f_data, ret , b_count, offset, last_match); break; case 3 : offset = f_data->next_offset ; ret = follow_archive(buf, f_data->buf_length, &offset, &last_match,0); ret = analysis_ret2("AR", f_data, ret, offset, last_match); break; } return ret; } struct priv_pdf_t { __u32 flag; __u32 o_nr; __u32 xref_0; __u32 xref_1; __u32 len; }; int pdf_is_obj(unsigned char *buf,__u32 offset){ int i,j; if(isdigit(buf[offset])){ i=1; while (isdigit(buf[offset + i]) && (i<12)) i++; if (buf[offset + i] == 0x20){ i++; j=0; while (isdigit(buf[offset + i + j]) && (j<4)) j++; i += j; if ((buf[offset + i] == 0x20) && (buf[offset + i + 1] == 0x6f) && (buf[offset + i + 2] == 0x62) && (buf[offset + i + 3] == 0x6a)){ return (i+4); } } } return 0; } static int follow_pdf(unsigned char *buf, __u16 blockcount, __u32 *offset, __u32 *last_match, struct priv_pdf_t *priv){ int nr,tmp,i,ret = 1; __u32 f_offset = *offset; __u32 end = (blockcount * current_fs->blocksize)-20; __u32 o_nr; while ((ret ==1) && (f_offset < end)){ switch (priv->flag & 0x07){ case 0: while ((f_offset < end) && (!((buf[f_offset] == 0x0d) || (buf[f_offset] == 0x0a)))) f_offset++; if (f_offset == end) break; else (priv->flag)++; case 1: while ((f_offset < end) && ((buf[f_offset] == 0x0d) || (buf[f_offset] == 0x0a) || (buf[f_offset] == 0x20))) f_offset++; if (f_offset == end){ break; } else (priv->flag)++; case 2: // if (f_offset > end) // break; switch (priv->flag & 0x70){ case 0: //obj tmp = pdf_is_obj(buf,f_offset); if (tmp){ *last_match = f_offset; o_nr=0; i=0; while (isdigit(buf[f_offset +i])){ o_nr *= 10; o_nr += (buf[f_offset +i] - 0x30); i++; } if (buf[f_offset+i] != 0x20) ret = 0; if (o_nr > priv->o_nr) priv->o_nr = o_nr; f_offset += tmp; priv->flag = 0x10; // printf("obj %08x\n",priv->len - *offset +f_offset); break; } //xref if((buf[f_offset] ==0x78)&& (buf[f_offset+1] ==0x72) && (buf[f_offset+2] ==0x65) && (buf[f_offset+3] ==0x66)){ *last_match = f_offset; priv->xref_1 = priv->xref_0; priv->xref_0 = priv->len - *offset + f_offset; f_offset += 4; priv->flag = 0x40; // printf("xref %08x\n",priv->len - *offset +f_offset); break; } //startxref whithout xref if((buf[f_offset] ==0x73)&& (buf[f_offset+1] ==0x74) && (buf[f_offset+2] ==0x61) && (buf[f_offset+3] ==0x72) && (buf[f_offset+4] ==0x74) && (buf[f_offset+5] ==0x78)&& (buf[f_offset+6] ==0x72)&&(buf[f_offset+7] ==0x65) && (buf[f_offset+8] ==0x66)){ priv->flag = 0x30; *last_match = f_offset; f_offset += 9; // printf("startxref %08x\n",priv->len - *offset +f_offset); break; } break; break; case 0x10 ://endobj if((buf[f_offset] ==0x65)&& (buf[f_offset+1] ==0x6e) && (buf[f_offset+2] ==0x64) && (buf[f_offset+3] ==0x6f) && (buf[f_offset+4] ==0x62) && (buf[f_offset+5] ==0x6a)){ *last_match = f_offset; f_offset += 6; priv->flag = 0x00; // printf("endobj %08x\n",priv->len - *offset +f_offset); break; } //xref (if no linebreak before the last endobj if((buf[f_offset] ==0x78)&& (buf[f_offset+1] ==0x72) && (buf[f_offset+2] ==0x65) && (buf[f_offset+3] ==0x66)){ *last_match = f_offset; priv->xref_1 = priv->xref_0; priv->xref_0 = priv->len - *offset + f_offset; f_offset += 4; priv->flag = 0x40; // printf("xref %08x\n",priv->len - *offset +f_offset); break; } break; case 0x30 : //check offset of the xref table if (!isdigit(buf[f_offset])) ret = 0; else { i=0; nr = 0; while (isdigit(buf[f_offset +i])){ nr *= 10; nr += (buf[f_offset +i] - 0x30); i++; } if(nr && priv->xref_0 && (nr != priv->xref_0)&&(nr != priv->xref_1)){ // printf("PDF : xref table check failed\n"); ret = 0; } else { priv->flag = 0x60; f_offset += i; } } break; case 0x40 : //trailer if((buf[f_offset] ==0x74)&& (buf[f_offset+1] ==0x72) && (buf[f_offset+2] ==0x61) && (buf[f_offset+3] ==0x69) && (buf[f_offset+4] ==0x6c) && (buf[f_offset+5] ==0x65)&& (buf[f_offset+6] ==0x72)){ priv->flag = 0x50; *last_match = f_offset; f_offset += 7; // printf("trailer %08x\n",priv->len - *offset +f_offset); } else{ while (isdigit(buf[f_offset])) f_offset++; while (buf[f_offset] == 0x20) f_offset++; if(! isdigit(buf[f_offset])){ ret= 0; break; } i=0; nr = 0; while (isdigit(buf[f_offset +i])){ nr *= 10; nr += (buf[f_offset +i] - 0x30); i++; } f_offset += ((nr * 20)+i); } break; case 0x50 : //startxref if((buf[f_offset] ==0x73)&& (buf[f_offset+1] ==0x74) && (buf[f_offset+2] ==0x61) && (buf[f_offset+3] ==0x72) && (buf[f_offset+4] ==0x74) && (buf[f_offset+5] ==0x78)&& (buf[f_offset+6] ==0x72)&&(buf[f_offset+7] ==0x65) && (buf[f_offset+8] ==0x66)){ priv->flag = 0x30; *last_match = f_offset; f_offset += 9; // printf("startxref %08x\n",priv->len - *offset +f_offset); } //else // break; break; case 0x60 ://EOF if((buf[f_offset] ==0x25)&& (buf[f_offset+1] ==0x25) && (buf[f_offset+2] ==0x45) && (buf[f_offset+3] ==0x4f) && (buf[f_offset+4] ==0x46)){ *last_match = f_offset; f_offset += 5; // printf("EOF %08x\n",priv->len - *offset +f_offset); while ((buf[f_offset] == 0x0d) || (buf[f_offset] == 0x0a)) f_offset++; if (zero_space(buf,f_offset)){ ret = 2; } else { f_offset--; priv->o_nr = 0; priv->flag = 0; } } else ret = 0; break; }//while 0x70 priv->flag &= (~0x07); }//while 0x07 } *offset = f_offset; return ret; } //pdf int file_pdf(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int i,j; int ret = 0; __u32 offset; __u32 last_match = 0; int b_count; struct priv_pdf_t *priv = NULL; char token[6]; sprintf(token,"%c%c%c%c%c",0x25,0x45,0x4f,0x46,0x0a); switch (flag){ case 0 : if(f_data->scantype & DATA_READY){ *size = (f_data->next_offset)?f_data->next_offset : *size; ret = 1; }else{ if ((*size) < 3) ret =2; else{ j = strlen(token) -2; i = (*size) -2; if(buf[i] != 0x46) i--; while ((i >= 0) && (j >= 0) && (buf[i] == token[j])){ i--; j--; } if ((i == -1) || (j == -1)){ ret=1; } } } break; case 1 : return ((scan & (M_IS_META | M_CLASS_1))||(f_data->scantype & DATA_READY)) ? 0 :1 ; break; case 2 : offset = 0; priv = malloc(sizeof(struct priv_pdf_t)); priv->o_nr = 0; priv->flag = 0; priv->xref_0 = 0; priv->xref_1 = 0; priv->len = 0; f_data->priv = priv; b_count = (f_data->buf_length > 12) ? 12 : f_data->buf_length ; ret = follow_pdf(buf, b_count, &offset, &last_match,f_data->priv); ret = analysis_ret1("PDF", f_data, ret , b_count, offset, last_match); break; case 3 : offset = f_data->next_offset ; ((struct priv_pdf_t*)(f_data->priv))->len = f_data->size; ret = follow_pdf(buf, f_data->buf_length, &offset, &last_match,f_data->priv); ret = analysis_ret2("PDF", f_data, ret, offset, last_match); break; case 4 : if(f_data->priv) free (f_data->priv); break; } return ret; } #define MAX_SMTP_CONTENT 16 struct priv_smtp_t { __u16 flag; __u16 len; struct { __u16 c_flag; __u16 crc; __u16 crc_len; __u16 c_code; } slot[MAX_SMTP_CONTENT]; }; static __u16 cull; static int read_smtp_len(unsigned char *buf,__u32 f_offset, __u32 end, __u16 flag){ __u32 i = f_offset; int len = 0; int exception = 0; __u16 save_flag = flag; if ((buf[i]==0x0a) ||((buf[i]==0x0d)&&(buf[i+1]==0x0a))) return 1; if (!(buf[i])) return -2; for (;(i46)) | ((buf[i]<91) && (buf[i]>64)) | ((buf[i]<123) && (buf[i]>96)))){ if ((buf[i]==0x20) && ((buf[i+1]==0x0a)||(buf[i+1]==0x0a))){ //Warning, there is a blanc } else return 0; } case 0x200: if ((buf[i]<0x07) || ((buf[i]<0x20) && (buf[i]>0x0d))) return 0; break; case 0x800: if (((i-f_offset)==8) && (!(strncmp("Subject:", (char*)buf+f_offset, 8)))){ flag = 0x200; exception = 2; } if ((buf[i] == '=') && (buf[i+1] == '?')){ flag = 0x200; exception =1; } case 0x000: if (buf[i] & 0x80) cull++; if ((buf[i]<0x09) || ((buf[i]<0x20) && (buf[i]>0x0d))) return 0; if ((buf[i] == 0x3c) && (buf[i+3] == 0x3e) && ((buf[i+1] & 0x20) == 0x42) && ((buf[i+1] & 0x20) == 0x52)){ cull++; len = 0; } break; case 0x100: if ((buf[i]<0x09) || (buf[i] & 0x80) || ((buf[i]<0x20) && (buf[i]>0x0d))) return 0; break; } if (buf[i]==0x0a){ if (len > 1000) return 0; if (((flag & 0x800) | exception) && ((buf[i+1]==0x20)||(buf[i+1]==0x09))){ i++; len = -1; flag = save_flag; if (exception == 1) exception = 0; } else { return ( i - f_offset + 1); } } } return (len < 1000)? -1 : 0; } static int read_smtp_codestr(unsigned char *buf,__u32 f_offset, int len){ char codestr[] ="7bit 7Bit quoted-printable Quoted-printable 8bit 8Bit binary Binary base64 Base64 "; char* p_search; char token[20]; int i; int flag = 0; int type = -1; if (len < 32) return 0; p_search = codestr; while (*p_search){ i=0; while((*p_search) != 0x20){ token[i] = *p_search; p_search++; i++; } token[i] = 0; type++; if (!strncmp((char*)buf + 27 + f_offset,token,strlen(token))){ flag = 1; break; } p_search++; } if(!flag) type=0; return (type >>1); } static int smtp_decode_content_type(unsigned char * buf, __u32 offset, int len, struct priv_smtp_t *priv){ int i,j,slot; if (!strncmp("Content-Type:",(char*)buf+offset,12)) { i = 13; while ((i<(len-6)) && (buf[offset +i] != ';')) i++; while ((i<(len-6)) && (!((buf[offset +i] == 'd') && // dary= (buf[offset +i+1] == 'a') && (buf[offset +i+2] == 'r') && (buf[offset +i+3] == 'y') && (buf[offset +i+4] == '=')))) i++; if (i < (len-6)){ i += 5; //while ((i<(len-6)) && (buf[offset +i] != '"')) i++; if (buf[offset +i] == '"') i++; j = i +1; while ((buf[offset +j] != '"') && (buf[offset +j] != 0x0a) && (buf[offset +j] != 0x0d)) j++; if (--j < len){ for(slot=0;slotslot[slot].c_flag) break; if (slot==MAX_SMTP_CONTENT){ printf("SMTP no free slot found\n"); return 0; } else{ priv->slot[slot].crc = FLAC__crc16(buf+offset+i,j-i+1,0); priv->slot[slot].crc_len = j-i+1; priv->slot[slot].c_flag = 1; } } else{ return 0; } } } return 1; } static int follow_smtp(unsigned char *buf, __u16 blockcount, __u32 *offset, __u32 *last_match, struct priv_smtp_t *priv){ int i = 0; int ret = 1; __u32 f_offset = *offset; __u32 end = (blockcount * current_fs->blocksize)-20; int len = 0; int tmp_slot,slot = 0; __u16 tmp_flag = 0; //crc,crc_d ; if (end == f_offset) end++; while ((ret ==1) && (f_offset < end)){ switch (priv->flag & 0x07){ case 0 : //header len = read_smtp_len(buf,f_offset,end,0x800); switch (len){ case 0 : ret = 0; break; case -1 : *offset = f_offset; return 1; break; case -2 : for(i=0;islot[i].c_flag) return 0; *offset = f_offset; return 2; break; case 1 : if (buf[f_offset]== 0x0d) f_offset++; f_offset++; *last_match = f_offset; cull = 0; priv->flag = (priv->flag & ~0x0f) | 1; break; default : if (!strncmp("From: ", (char*)buf+f_offset, 6) || !strncmp("From ", (char*)buf+f_offset, 5) || !strncmp("To: ", (char*)buf+f_offset, 4) || !strncmp("Reply-", (char*)buf+f_offset, 6) || !strncmp("Cc: ", (char*)buf+f_offset, 4) || !strncmp("Bcc: ", (char*)buf+f_offset, 5) || !strncmp("Content-", (char*)buf+f_offset, 8) || !strncmp("MIME-Version: ", (char*)buf+f_offset, 14)){ if(buf[f_offset + 8] == 'T') { if (!strncmp("Content-Transfer-Encoding:",(char*)buf+f_offset,26)){ priv->flag = ((priv->flag & 0xff)|(read_smtp_codestr(buf,f_offset,len)<<8)); //FIXME if (priv->flag & 0xff00 } else ret = smtp_decode_content_type(buf, f_offset, len, priv); } if (ret) { *last_match = f_offset; f_offset += len; } } else{ for(i=0;((islot[i].c_flag) break; if (i==MAX_SMTP_CONTENT){ *offset = f_offset; return 2; } else return 0; } if (!strncmp("--", (char*)buf+f_offset, 2)){ tmp_flag = (priv->flag & ~0x0f) | 3; priv->flag = (priv->flag & ~0x0f) | 2; break; } if (!strncmp("From ", (char*)buf+f_offset, 5)){ for(i=0;islot[i].c_flag) break; if (i==MAX_SMTP_CONTENT){ priv->flag = 0; cull = 0; break; } else { // printf("SMTP Warning not all slots empty\n"); //FIXME } } priv->flag = (priv->flag & ~0x0f) | 3; case 3 : //MIME format len = read_smtp_len(buf,f_offset,end,priv->flag); switch (len){ case 0 : ret = 0; break; case -1 : *offset = f_offset; return 1; break; case -2 : for(i=0;islot[i].c_flag) return 0; *offset = f_offset; return 2; break; case 1 : if (buf[f_offset]== 0x0d) f_offset++; f_offset++; break; default: if ((len > 30) && (!strncmp("This ", (char*)buf+f_offset, 5))){ for(i=6;((iflag = (priv->flag & ~0x0f) | 1; } }else priv->flag = (priv->flag & ~0x0f) | 4; f_offset += len; break; } break; case 4 : //text len = read_smtp_len(buf,f_offset,end,priv->flag); switch (len){ case -2 : if (zero_space(buf,f_offset)){ *offset = f_offset; return 2; } case 0 : ret = 0; break; case -1 : *offset = f_offset; return 1; break; case 1 : if (buf[f_offset]== 0x0d) f_offset++; f_offset++; priv->flag = (priv->flag & ~0x0f) | 1; *last_match = f_offset; break; default : f_offset += len; break; } break; case 2 : if ((end - 80)slot[slot].crc, FLAC__crc16(buf+f_offset+2,priv->slot[slot].crc_len,0)); if((priv->slot[slot].c_flag) && (priv->slot[slot].crc_len < i) && (priv->slot[slot].crc == FLAC__crc16(buf+f_offset+2,priv->slot[slot].crc_len,0))) break; } if (slot == MAX_SMTP_CONTENT){ // printf("SMTP can not find crc\n"); priv->flag = tmp_flag; slot = tmp_slot; while (buf[f_offset] == '-') f_offset++; while ((buf[f_offset]== 0x0a) || (buf[f_offset]== 0x0d)) f_offset++; break; } if ((buf[f_offset+priv->slot[slot].crc_len+2]=='-')&&(buf[f_offset+priv->slot[slot].crc_len+3]=='-')){ priv->slot[slot].crc = 0; priv->slot[slot].c_flag = 0; priv->slot[slot].crc_len = 0; priv->slot[slot].c_code = 0; priv->flag = (priv->flag & ~0x0f) | 1; } else { priv->flag = (priv->flag & ~0x0f) | 5; } *last_match = f_offset; f_offset += i; while ((buf[f_offset]== 0x0a) || (buf[f_offset]== 0x0d)) f_offset++; break; case 5: len = read_smtp_len(buf,f_offset,end,0x800); switch (len){ case 0 : ret = 0; break; case -1 : *offset = f_offset; return 1; break; case -2 : for(i=0;islot[i].c_flag) return 0; *offset = f_offset; return 2; break; case 1 : while ((buf[f_offset]== 0x0d) || (buf[f_offset]== 0x0a)) f_offset++; priv->len = 0; if (priv->slot[slot].c_flag & 0x02) priv->flag = (priv->flag & ~0x0f) | 6; else priv->flag = (priv->flag & ~0x0f) | 1; break; default: if(buf[f_offset + 8] == 'T'){ if(!strncmp("Content-Transfer-Encoding:",(char*)buf+f_offset,26)){ priv->slot[slot].c_flag = 3; priv->slot[slot].c_code = (read_smtp_codestr(buf,f_offset,len)<<8); } else ret = smtp_decode_content_type(buf, f_offset, len, priv); } if (ret) { *last_match = f_offset; f_offset += len; } break; } break; case 6 : if((priv->slot[slot].c_code == 0x400) && ((buf[f_offset] == '-') &&(buf[f_offset +1] == '-'))) priv->slot[slot].c_flag |= 4; len = read_smtp_len(buf,f_offset,end, (((priv->slot[slot].c_code != 0x200) && ((priv->slot[slot].c_flag & 4) &&(buf[f_offset] == '-') &&(buf[f_offset +1] == '-'))) ? 0 : priv->slot[slot].c_code )); switch (len){ case 0 : case -2 : ret = 0; break; case -1 : *offset = f_offset; return 1; break; case 1 : if (buf[f_offset]== 0x0d) f_offset++; f_offset++; priv->slot[slot].c_flag |= 4; if (priv->slot[slot].c_code & 0x400){ tmp_flag = priv->flag; priv->flag = (priv->flag & ~0x0f) | 2; } break; default : if (!priv->len) priv->len = len; if ((len > 7)&&(!strncmp("--", (char*)buf+f_offset, 2))){ tmp_flag = priv->flag; priv->flag = (priv->flag & ~0x0f) | 2; break; } if(priv->slot[slot].c_flag & 4) priv->slot[slot].c_flag &= ~4; if ((priv->slot[slot].c_code & 0x400) && (priv->len != len) ){ if(!((len < priv->len) && ((buf[f_offset +len] ==0x0d) || (buf[f_offset +len] ==0x0a) || (buf[f_offset +len] == '-')))) return 0; } f_offset += len; break; } break; }//switch flag }//while *offset = f_offset; return ret; } //rfc822 int file_smtp(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 0; __u32 offset; __u32 last_match = 0; int b_count; struct priv_smtp_t *priv = NULL; switch (flag){ case 0 : if (*size < current_fs->blocksize){ if (buf[(*size)-1] == (unsigned char)0x0a) ret = 1; } else { if (buf[(*size)-1] == (unsigned char)0x0a) ret = (f_data->scantype & DATA_METABLOCK) ? 2 : 4 ; } break; case 1 : return (scan & M_TXT); break; case 2 : offset = 0; priv = malloc(sizeof(struct priv_smtp_t)); memset(priv,0,sizeof(struct priv_smtp_t)); f_data->priv = priv; b_count = (f_data->buf_length > 12) ? 12 : f_data->buf_length ; ret = follow_smtp(buf, b_count, &offset, &last_match,f_data->priv); ret = analysis_ret1("SMTP", f_data, ret , b_count, offset, last_match); break; case 3 : offset = f_data->next_offset ; ret = follow_smtp(buf, f_data->buf_length, &offset, &last_match,f_data->priv); ret = analysis_ret2("SMTP", f_data, ret, offset, last_match); break; case 4 : if(f_data->priv) free (f_data->priv); break; } return ret; } //ps switch only to pdf or txt int file_ps(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 1; // unsigned char *c; // unsigned char token[9] = "PS-Adobe"; switch (flag){ case 0 : break; case 1 : break; case 2 : //c = buf+2 ; //if (! strncmp(c,token,7)) // f_data->func = file_pdf ; //else f_data->func = file_txt ; break; } return ret; } //arj int file_arj(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 0; switch (flag){ case 0 : if ((*size>1) && (*size < current_fs->blocksize) && (buf[(*size)-1] == (unsigned char)0xea) && (buf[(*size)-2] == (unsigned char)0x60)){ *size +=2; ret = 1; } break; case 1 : return (scan & ((M_IS_META | M_CLASS_1)| M_BLANK | M_TXT)) ? 0 :1 ; break; } return ret; } //xz int file_xz(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 0; switch (flag){ case 0 : if ((*size>3) && (buf[(*size)-1] == (unsigned char)0x5a) && (buf[(*size)-2] == (unsigned char)0x59)) ret = 1; break; case 1 : return ((scan & (M_IS_META | M_CLASS_1 | M_TXT | M_BLANK )&&(!(scan & M_DATA)))) ? 0 :1 ; break; } return ret; } static int follow_tar(unsigned char *buf, __u16 blockcount, __u32 *offset, __u32 *last_match, int flag){ int i, j,ret = 1; __u64 f_offset = (__u64) *offset; __u64 f_len = 0; __u8 *o_str; while ((ret ==1) && (f_offset < ((blockcount * current_fs->blocksize)-27))){ if (((buf[f_offset + 0x101] == 0x75) && (buf[f_offset + 0x102] == 0x73) && (buf[f_offset + 0x103] == 0x74)&& (buf[f_offset + 0x104] == 0x61) && (buf[f_offset + 0x105] == 0x72))||( (!buf[f_offset + 0x101])&&(!buf[f_offset + 0x102])&&(!buf[f_offset + 0x103])&&(!buf[f_offset + 0x104])&&(!buf[f_offset + 0x105])&& buf[f_offset])){ f_len = 0; *last_match = (__u32) f_offset +1; o_str = (__u8*)(buf + f_offset + 0x7c); for (i=0;i<10;i++){ f_len += (*o_str & 0x7) ; f_len <<= 3; o_str++; } f_len += (*o_str & 0x7); f_len = ((f_len + 0x1ff) & ~0x1ff); f_offset += f_len + 0x200 ; // printf("TAR follow : offset %8lu \n", f_offset); continue; } else{ for (j=0, i=f_offset; ((ret==1)&&(j<30)&&(i<(blockcount * current_fs->blocksize))); i++,j++){ if (buf[i]){ // printf("TAR break %lu \n",i); ret=0; } } if (ret) { // printf("TAR complete %lu \n",f_offset); ret = 2; } break; } } *offset = f_offset & 0xFFFFFFFF; return ret; } //tar int file_tar(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 0; int b_count; __u32 offset; __u32 last_match = 0; switch (flag){ case 0 : if ((((__u64)f_data->inode->i_size |((__u64)f_data->inode->i_size_high<<32)) >= (__u64)f_data->size) && ((*size) < (current_fs->blocksize - 0xff))){ if (!(*size)) *size = current_fs->blocksize; else *size = ((*size) + 1023) & ~1023 ; if (((!(f_data->inode->i_flags & EXT4_EXTENTS_FL)) &&(f_data->inode->i_block[12])) || (f_data->size < f_data->inode->i_size) || (f_data->scantype & DATA_READY)) //FIXME ret = 1; } break; case 1 : if (scan & M_TAR) ret = 1; else ret = ((scan & (M_IS_META | M_CLASS_1))||(f_data->scantype & DATA_READY)) ? 0 :1 ; break; case 2 : offset = 0; b_count = (f_data->buf_length > 12) ? 12 : f_data->buf_length ; ret = follow_tar(buf,b_count, &offset, &last_match,0); ret = analysis_ret1("TAR", f_data, ret , b_count, offset, last_match); break; case 3 : offset = f_data->next_offset ; ret = follow_tar(buf, f_data->buf_length, &offset, &last_match,0); ret = analysis_ret2("TAR", f_data, ret, offset, last_match); break; } return ret; } static int follow_elf(unsigned char *buf, __u16 blockcount, __u32 *offset, __u32 *table, int flag){ int i; __u16 count = (flag >>3); int ret = 1; __u32 f_offset = *offset; int size; __u32 end = blockcount * current_fs->blocksize; __u32 max; __u32 entry; if((!f_offset) && (flag & 0x1) && (!(*table))){ // HEAD if (flag & 0x4){ //64 bit if (flag & 0x2){ // BIG Endian f_offset = (buf[44]<<24)+(buf[45]<<16)+(buf[46]<<8)+(buf[47]); count = (buf[60]<<8)+(buf[61]); } else{ //Little Endian f_offset = (buf[40])+(buf[41]<<8)+(buf[42]<<16)+(buf[43]<<24); count = (buf[60])+(buf[61]<<8); } } else{ //x32 bit if (flag & 0x2){ // BIG Endian f_offset = (buf[32]<<24)+(buf[33]<<16)+(buf[34]<<8)+(buf[35]); count = (buf[48]<<8)+(buf[49]); } else{ //Little Endian f_offset = (buf[32])+(buf[33]<<8)+(buf[34]<<16)+(buf[35]<<24); count = (buf[48])+(buf[49]<<8); } } *offset = f_offset; *table = f_offset; return count; } //---------------------- if((flag & 0x1) && (*table)){ // Section Header size = (flag & 0x4) ? 64 :40 ; if ((f_offset + (count *size))<= end){ for (i=0;i<(size+4);i++) if (buf[f_offset +i]) break; if((i max) max = entry; } *offset += (max - *table); ret = 3; } if (*offset < end){ f_offset = *offset; flag &= (~1); } else return ret; } //---------------------- if(!(flag & 0x1)){ if ((f_offset < end) && (zero_space(buf,f_offset))) ret = 2; else ret = 0; } else { ret = 0; } return ret; } //binary int file_binary(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 0; __u32 offset = 0; __u32 tmp; __u32 table = 0; int b_count = 0; switch (flag){ case 0 : if (f_data->scantype & DATA_READY){ *size = f_data->next_offset; ret =1; } else { if (*size && ((*size) < current_fs->blocksize - 7)&&(buf[(*size)-1] == 0x01)){ *size +=7; ret = 1; } else { if ((*size < current_fs->blocksize) && ((*size) > current_fs->blocksize - 7) && (buf[(*size)-1] == 0x01)){ *size = current_fs->blocksize; ret = 2; } else{ if (!(*size)){ *size = 7; ret = 1; } else{ if ((buf[(*size)-1] != 0x01)&&(*size < current_fs->blocksize - 128)){ *size +=1; ret = 2; } } } } } break; case 1 : return ((scan & (M_IS_META | M_CLASS_1))||(f_data->scantype & DATA_READY)) ? 0 :1 ; break; case 2 : offset = 0; if (!((buf[0] == 0x7f) && (buf[1] == 0x45) && (buf[2] == 0x4c) && (buf[3] == 0x46))){ f_data->func = NULL; return 0; } f_data->scantype |= (buf[4] == 0x2) ? DATA_X64 :0 ; f_data->scantype |= (buf[5] == 0x2) ? DATA_BIG_END :0 ; f_data->scantype |= DATA_FLAG ; offset = 0; b_count = (f_data->buf_length > 12) ? 12 : f_data->buf_length ; ret = follow_elf(buf,b_count, &offset, &table,f_data->scantype >>13); if (!ret){ f_data->func = NULL; return 0; } f_data->last_match_blk=1; f_data->h_size = ret; f_data->scantype |= DATA_CARVING; f_data->size = table; if (( offset + (((f_data->scantype & DATA_X64)?64:40) * ret)) >= (b_count * current_fs->blocksize)){ if (offset > (b_count * current_fs->blocksize)) f_data->buf_length = b_count; else f_data->buf_length = offset / current_fs->blocksize; f_data->next_offset = offset - (f_data->buf_length * current_fs->blocksize); return 1; } case 3 : if (!offset) offset = f_data->next_offset ; if (!table) table = f_data->size ; if (!b_count) b_count = f_data->buf_length; tmp = offset; ret = follow_elf(buf,b_count, &offset, &table,((f_data->h_size)<<3) + (f_data->scantype >>13)); if (ret){ f_data->buf_length = offset / current_fs->blocksize; f_data->next_offset = offset - (f_data->buf_length * current_fs->blocksize); } switch (ret){ case 0 : // fprintf(stderr,"ELF-CHECK: error, recover not \n"); f_data->scantype |= DATA_BREAK; break; case 1 : // fprintf(stderr,"ELF-CHECK: data next found\n"); break; case 2 : // fprintf(stderr,"ELF-CHECK: data end found, recover \n"); f_data->scantype |= DATA_READY; if(offset % current_fs->blocksize) (f_data->buf_length)++; break; case 3 :f_data->last_match_blk = f_data->last -f_data->first +1; // fprintf(stderr,"ELF-CHECK: file size found\n"); f_data->scantype &= (~DATA_FLAG); f_data->size += (offset - tmp); f_data->h_size = 0; ret = 1; break; } } return ret; } //bin-raw int file_bin_raw(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 0; switch (flag){ case 0 : if(f_data->scantype & DATA_METABLOCK){ ret = 1; break; } else{ if (*size < (current_fs->blocksize -8)) ret = 2; if (*size < (current_fs->blocksize -16)) ret = 1; } break; case 1 : return (scan & (M_IS_META | M_CLASS_1)) ? 0 :1 ; break; } return ret; } int file_tfm(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int i,ret = 0; __u16 *p_header; __u16 header[12]; switch (flag){ case 0 : if ((f_data->size) && (f_data->inode->i_size == f_data->size)) return 1; if ((f_data->size) && (f_data->inode->i_size < f_data->size)) return 0; else{ if (*size <= f_data->size % current_fs->blocksize ){ *size = f_data->size % current_fs->blocksize; ret = 1; } } break; case 1 : return (scan & (M_IS_META | M_CLASS_1 | M_BLANK | M_TXT)) ? 0 :1 ; break; case 2 : p_header = (__u16*) buf; for (i=0; i< 12; i++){ header[i] = ext2fs_be16_to_cpu( *p_header); p_header++; } if (header[0] != (6+header[1]+(header[3]-header[2]+1)+header[4]+header[5]+header[6]+header[7]+header[8]+header[9]+header[10]+header[11])) f_data->func = NULL; else{ f_data->size = header[0] << 2; f_data->scantype = DATA_LENGTH ; ret =1; } } return ret; } int file_qt(unsigned char*, int*, __u32, int, struct found_data_t*); static int follow_jp2000(unsigned char *buf, __u16 blockcount, __u32 *offset, __u32 *last_match, int flag){ int ret = 1; int end = blockcount * current_fs->blocksize; __u32 f_offset = *offset; __u32 size; while ((ret == 1)&&( f_offset < (end - 3))){ if (buf[f_offset] == 0xff){ switch (buf[f_offset+1]){ case 0x4f : //SOC f_offset += 2; break; case 0xd9 : //EOC *last_match = f_offset; f_offset += 2; if (zero_space(buf,f_offset)) ret = 2; else ret = 0; break; case 0x90 : //SOT *last_match = f_offset; size = ((buf[f_offset+6])<<24)+((buf[f_offset+7])<<16)+((buf[f_offset+8])<<8) + buf[f_offset+9]; f_offset += size; break; case 0x51 : //SIZ case 0x52 : //COD case 0x53 : //COC case 0x5e : //RGN case 0x5c : //QCD case 0x5d : //QCC case 0x5f : //POC case 0x55 : //TLM case 0x57 : //PLM case 0x58 : //PLT case 0x60 : //PPM case 0x61 : //PPT case 0x91 : //SOP case 0x63 : //CRG case 0x64 : //COM case 0x68 : //EPC case 0x66 : //EPB case 0x67 : //ESD case 0x69 : //RED case 0x65 : //SEC case 0x94 : //INSEC *last_match = f_offset; f_offset += 2; size = ((buf[f_offset])<<8) + buf[f_offset+1]; if (size < 2){ ret = 0; break; } f_offset += size; break; case 0x93 : //SOD f_offset += 2; ret = 0; // printf("ERROR JP2000 SOD-Marker\n"); break; default : // printf("Error JP2000 Unknown marker %02x \n",buf[f_offset+1]); ret = 0; break; } } else{ ret = 0; } } *offset = f_offset; return ret; } //jp2 int file_jp2(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int b_count,ret = 0; __u32 offset; __u32 last_match = 0; switch (flag){ case 0 : if ((*size>1) && (buf[(*size)-1] == (unsigned char)0xd9) && (buf[(*size)-2] == (unsigned char)0xff)) ret = 1; else if ((*size == 1) && (buf[(*size)-1] == (unsigned char)0xd9)) ret = 1; break; case 1 : return ((scan & (M_IS_META | M_CLASS_1))||(f_data->scantype & DATA_READY)) ? 0 :1 ; break; case 2 : offset = f_data->next_offset; //take the offset from QuickTime b_count = (f_data->buf_length > 12) ? 12 : f_data->buf_length ; ret = follow_jp2000(buf, b_count, &offset, &last_match,0); ret = analysis_ret1("JP2000", f_data, ret , b_count, offset, last_match); break; case 3 : offset = f_data->next_offset ; ret = follow_jp2000(buf, f_data->buf_length, &offset, &last_match,0); ret = analysis_ret2("JP2000", f_data, ret , offset, last_match); break; } return ret; } //switch only to QT or jp2 int file_jp2000(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ if ((buf[0]==0xff) && (buf[1]==0x4f)) f_data->func=file_jp2; else f_data->func=file_qt; return f_data->func(buf,size,scan,flag,f_data); } static int follow_jpeg(unsigned char *buf, __u16 blockcount, __u32 *offset, __u32 *last_match, int* flag){ int ret = 1; int end = blockcount * current_fs->blocksize; __u32 f_offset = *offset; __u16 size; while ((ret == 1)&&( f_offset < (end - 3))){ if ((!(*flag))&&(buf[f_offset] == 0xff)){ switch (buf[f_offset+1]){ case 0xd8 : //Start Of Image (beginning of datastream) f_offset += 2; break; case 0xd9 : //End Of Image (end of datastream) *last_match = f_offset; f_offset += 2; if (zero_space(buf,f_offset)) ret = 2; else ret = 0; break; case 0xc0 : //Baseline case 0xc1 : //Extended sequential case 0xc2 : //Progressive case 0xc3 : //Lossless case 0xc5 : //Differential sequential case 0xc6 : //Differential progressive case 0xc7 : //Differential lossless case 0xc9 : //Extended sequential, arithmetic coding case 0xca : //Progressive, arithmetic coding case 0xcb : //Lossless, arithmetic coding case 0xcd : //Differential sequential, arithmetic coding case 0xce : //Differential progressive, arithmetic coding case 0xcf : //Differential lossless, arithmetic coding case 0xc4 : //Huffman-table case 0xc8 : //reserv JPEG extension case 0xcc : //arithmetic Code case 0xdb : //DQT case 0xdd : //Application-specific marker; all 16 APPn's case 0xe0 : //JFIF case 0xe1 : //EXIF case 0xe2 : case 0xe3 : case 0xe4 : case 0xe5 : case 0xe6 : case 0xe7 : case 0xe8 : case 0xe9 : case 0xea : case 0xeb : case 0xec : case 0xed : case 0xee : //often Copyright case 0xef : case 0xfe : //COMment *last_match = f_offset; f_offset += 2; size = ((buf[f_offset])<<8) + buf[f_offset+1]; if (size < 2){ ret = 0; break; } f_offset += size; break; case 0xda : //Start Of Scan (begins compressed data) *last_match = f_offset; f_offset += 2; *flag = 1; break; default : // printf("Error JPEG %02x \n",buf[f_offset+1]); ret = 0; break; } } else{ if (*flag){ loop: while ((f_offset < (end-2)) && ((buf[f_offset]) != 0xff)) f_offset++; if (((buf[f_offset])==0xff) && ((!buf[f_offset+1]) || ((buf[f_offset+1] >= 0xd0)&&(buf[f_offset+1] <= 0xd7)))){ f_offset++; goto loop; } else { if ((buf[f_offset]) == 0xff){ if (buf[f_offset+1] == 0xd8){ ret = 0; // this is begin of a new jpeg f_offset--; } else *flag = 0; } } } else{ ret = 0; } } } *offset = f_offset; return ret; } //jpeg int file_jpeg(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int b_count,ret = 0; __u32 offset; __u32 last_match = 0; int *priv_flag = NULL; switch (flag){ case 0 : if ((*size>1) && (buf[(*size)-1] == (unsigned char)0xd9) && (buf[(*size)-2] == (unsigned char)0xff)) ret = 1; else if ((*size == 1) && (buf[(*size)-1] == (unsigned char)0xd9)) ret = 1; break; case 1 : return ((scan & (M_IS_META | M_CLASS_1))||(f_data->scantype & DATA_READY)) ? 0 :1 ; break; case 2 : offset = 0; priv_flag = malloc(4); *priv_flag = 0; f_data->priv = priv_flag; b_count = (f_data->buf_length > 12) ? 12 : f_data->buf_length ; ret = follow_jpeg(buf, b_count, &offset, &last_match,(int*)f_data->priv); ret = analysis_ret1("JPEG", f_data, ret , b_count, offset, last_match); break; case 3 : offset = f_data->next_offset ; ret = follow_jpeg(buf, f_data->buf_length, &offset, &last_match,(int*)f_data->priv); ret = analysis_ret2("JPEG", f_data, ret, offset, last_match); break; case 4 : if (f_data->priv) free(f_data->priv); break; } return ret; } //art int file_art(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 0; static const unsigned char header[8] = {0x4a,0x47,0x04,0x0e,0x00,0x00,0x00,0x00}; switch (flag){ case 0 : if ((*size >1) && (*size < current_fs->blocksize) && (buf[(*size)-1] == 0xcb) && (buf[(*size)-2] == 0xcf)) ret = 1; break; case 1 : return ((scan & (M_IS_META | M_CLASS_1 | M_TXT | M_BLANK )&&(!(scan & M_DATA)))) ? 0 :1 ; break; case 2 : if(memcmp(buf,header,8)) f_data->func = NULL; else ret = 1 ; break; } return ret; } #define GIF_SUB_BLOCK 0x40000000 #define GIF_IMAGE_DATA 0x80000000 #define GIF_DATA 0xC0000000 static int follow_gif(unsigned char *buf, __u16 blockcount, __u32 *offset, __u32 *last_match, int flag, __u32 *gif_data){ int ret = 1; __u32 i = *offset ; __u32 data_flag = *gif_data; //File begin if ((!flag) && (!i)){ //Header if ((buf[i] == 0x47) && (buf[i+1] == 0x49) && (buf[i+2] ==0x46 ) && (buf[i+3] & 0x38) && (buf[i+4] & 0x30) && (buf[i+5] > 0x60) && (buf[i+5] < 0x7b)){ i+=6; //Logical Screen Descriptor if(buf[i+4] & 0x80) //Global Color Table i += ((0x02 << (buf[i+4] & 0x07))*3) + 7 ; else i += 7 ; } else ret = 0; } while ((ret == 1)&&( i < ((blockcount * current_fs->blocksize)-12))){ switch (buf[i]){ case 0x00 : //Block Terminator if (data_flag & GIF_DATA){ i++; data_flag = 0; }else ret = 0; break; case 0x21 : //Extension Introducer switch (buf[i+1]){ case 0x01 : //Plain Text Label *last_match = i; i += (16 + buf[i+15]); data_flag = GIF_SUB_BLOCK ; break; case 0xf9 : //Graphic Control Extension *last_match = i; i += 7; data_flag = GIF_SUB_BLOCK ; break; case 0xfe : //Comment Label *last_match = i; i += (3 + buf[i+2]); data_flag = GIF_SUB_BLOCK ; break; case 0xff : //Application Extension Label *last_match = i; i += (15 + buf[i+14]); data_flag = GIF_SUB_BLOCK ; break; default: ret = 0; break; } break; case 0x3B : //Trailer i++; ret = 2; break; case 0x2C : //Image Separator if(buf[i+9] & 0x80) //Local Color Table i += ((0x02 << (buf[i+9] & 0x07))*3) + 10 ; else i += 10 ; //--------------------------------------- //Table Based Image Data. i++; //LZW Minimum Code Size data_flag = GIF_IMAGE_DATA; forward: while ((i < ((blockcount * current_fs->blocksize)-12))&& (buf[i])){ i += (buf[i]+1); } break; default : if (data_flag & GIF_IMAGE_DATA){ goto forward; }else ret = 0; break; }//switch }//while *offset = i ; *gif_data = data_flag ; return ret; } //gif int file_gif(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int b_count,ret = 0; __u32 last_match = 0; __u32 offset; __u32 gif_data = 0; switch (flag){ case 0 : if ((f_data->size) && (f_data->size <= f_data->inode->i_size)){ if(f_data->scantype & DATA_READY){ *size = (f_data->next_offset)?f_data->next_offset : *size; ret = 1 ; break; } } if ((*size) && (*size < current_fs->blocksize) && (buf[(*size)-1] == 0x3b)) ret = 1; break; case 1 : return ((scan & (M_IS_META | M_CLASS_1))||(f_data->scantype & DATA_READY)) ? 0 :1 ; break; case 2 : offset = 0; b_count = (f_data->buf_length > 12) ? 12 : f_data->buf_length ; ret = follow_gif(buf, b_count, &offset, &last_match,0,&gif_data); if (last_match) f_data->last_match_blk = (last_match/current_fs->blocksize) +1 ; if (ret){ f_data->scantype = DATA_CARVING; if(gif_data) f_data->scantype |= gif_data; f_data->size = offset; if (offset > (b_count * current_fs->blocksize)) f_data->buf_length = b_count; else f_data->buf_length = offset / current_fs->blocksize; f_data->next_offset = offset - (f_data->buf_length * current_fs->blocksize); } switch (ret){ case 0 : // fprintf(stderr,"GIF-CHECK: Block %lu : Break \n",f_data->first); f_data->scantype |= DATA_BREAK; f_data->func = NULL; return 0; break; case 1: break; case 2 : f_data->scantype |= DATA_READY; if(offset % current_fs->blocksize)(f_data->buf_length)++; break; } break; case 3 : offset = f_data->next_offset ; gif_data = f_data->scantype & GIF_DATA ; ret = follow_gif(buf, f_data->buf_length, &offset, &last_match,1,&gif_data); if (last_match) f_data->last_match_blk = ((f_data->size - f_data->next_offset + last_match)/current_fs->blocksize) +1 ; if (ret){ if(gif_data) f_data->scantype |= gif_data; else f_data->scantype &= 0x3FFFFFFF ; f_data->size += offset - f_data->next_offset; f_data->buf_length = offset / current_fs->blocksize; f_data->next_offset = offset - (f_data->buf_length * current_fs->blocksize); } switch (ret){ case 0 : // fprintf(stderr,"GIF-CHECK: data error, recover not \n"); f_data->scantype |= DATA_BREAK; break; case 1 : // fprintf(stderr,"GIF-CHECK: data next found\n"); break; case 2 : // fprintf(stderr,"GIF-CHECK: data end found, recover \n"); f_data->scantype |= DATA_READY; if(offset % current_fs->blocksize) (f_data->buf_length)++; break; } break; } return ret; } //bmp int file_bmp(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ __u32 wi,hi,offset,ssize; int ret = 0; __u16 colors; /* struct bmp_header { __u16 bfType; __u32 bfSize; __u16 bfReserved1; __u16 bfReserved2; __u32 bfOffBits; } *p_bmp_header; struct bmp_info { __u32 biSize; __u32 biWidth; __u32 biHeight; __u16 biPlanes; __u16 biBitCount; __u32 biCompression; __u32 biSizeImage; __u32 biXPelsPerMeter; __u32 biYPelsPerMeter; __u32 biClrUsed; __u32 biClrImportant; } *p_bmp_info; struct bmp_info_s { __u32 biSize; __u16 biWidth; __u16 biHeight; __u16 biPlanes; __u16 biBitCount; } *p_bmp_info_s; */ switch (flag){ case 0 : if (f_data->size && (f_data->size <= f_data->inode->i_size)) { ssize = ((f_data->size-1) % current_fs->blocksize) + 1; if (f_data->inode->i_size > (f_data->size - ssize)){ *size = ssize; ret =1; } } break; case 1 : return (scan & (M_IS_META | M_CLASS_1 )) ? 0 :1 ; break; case 2 : offset = ((__u32)*(buf+10)) | ((__u32)*(buf+11))<<8 | ((__u32)*(buf+12))<<16 | ((__u32)*(buf+13))<<24 ; if ( *(buf+14) == 0x0c){ wi = ((__u32)*(buf+18)) | ((__u32)*(buf+19))<<8 ; colors = ((__u16)*(buf+24)) | ((__u16)*(buf+25))<<8 ; switch (colors){ case 1: wi = (((((wi+0x7) & ~0x7) / 8) + 1) & ~1); break; case 4: wi = (((wi+0x7) & ~0x07) / 2); break; case 8: wi = ((wi +0x03) & ~0x03); break; case 16: wi *=2; break; case 24: wi *=3; break; case 32: wi *=4; break; } hi = ((__u32)*(buf+20)) | ((__u32)(*(buf+21) & 0x7f))<<8 ; ssize = (wi * hi) + offset ; } else{ ssize = ((__u32)*(buf+34)) | ((__u32)*(buf+35))<<8 | ((__u32)*(buf+36))<<16 | ((__u32)*(buf+37))<<24 ; if(ssize){ ssize += offset; } else{ wi = ((__u32)*(buf+18)) | ((__u32)*(buf+19))<<8 | ((__u32)*(buf+20))<<16 | ((__u32)*(buf+21))<<24 ; colors = ((__u16)*(buf+28)) | ((__u16)*(buf+29))<<8 ; switch (colors){ case 1: wi = (((((wi+0x7) & ~0x7) / 8) + 1) & ~1); break; case 4: wi = (((wi+0x7) & ~0x07) / 2); break; case 8: wi = ((wi +0x03) & ~0x03); break; case 16: wi *=2; break; case 24: wi *=3; break; case 32: wi *=4; break; } hi = ((__u32)*(buf+22)) | ((__u32)*(buf+23))<<8 | ((__u32)*(buf+24))<<16 | ((__u32)(*(buf+25) & 0x7f))<<24 ; ssize = (wi * hi) + offset ; } } f_data->size = ssize; f_data->scantype = DATA_LENGTH ; ret =1; break; } return ret; } static int follow_png(unsigned char *buf, __u16 blockcount, __u32 *offset, __u32 *last_match, int flag){ char searchstr[] = "IDAT IEND MHDR MEND LOOP IHDR JHDR JDAT JDAA JSEP TERM BACK SAVE SEEK sBIT gAMA cHRM PLTE hIST bKGD tRNS pHYS oFFs pCAL sCAL tIME tEXt zTXt gIFg gIFx eXPI pHYg iTXt iCCP sRGB pHYs DEFI ENDL FILT MAGN BASI sPLT fRAc vpAg dSIG gIFt sTER tXMP "; char chunk[5]; char endchunk[]="IEND"; int ret = 1; __u32 i = *offset; int j; if (flag) endchunk[0]=0x4d; while ( i < (blockcount * current_fs->blocksize)-12){ for (j=i+4;j<(i+8);j++){ if (((buf[j] & 0xdf) < 65) || ((buf[j] & 0xdf) > 90)){ ret = 0 ; break; } } if (buf[i] & 0x8){ ret = 0 ; break; } memcpy(chunk, buf+i+4, 4); chunk[4] = 0; if(!strstr(searchstr,chunk)){ ret = 0; break; } if (strstr(chunk,endchunk)){ i+=12; ret = 2; break; } *last_match = i; i += (buf[i]<<24)+(buf[i+1]<<16)+(buf[i+2]<<8)+buf[i+3] + 12; } *offset = i; return ret; } //png int file_png(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int b_count,ret = 0; __u32 last_match = 0; __u32 offset; switch (flag){ case 0 : if ((f_data->size) && (f_data->size <= f_data->inode->i_size)){ if(f_data->scantype & DATA_READY){ *size = (f_data->next_offset)?f_data->next_offset : *size; ret = 1; break; } /* if((!(f_data->inode->i_flags & EXT4_EXTENTS_FL))&&(f_data->size < (12 * current_fs->blocksize))){ f_data->inode->i_size = (f_data->size + current_fs->blocksize -1) & ~(current_fs->blocksize-1); *size = f_data->size % current_fs->blocksize; }*/ else{ // if((!(f_data->inode->i_flags & EXT4_EXTENTS_FL))){ if (*size > 8){ if (strstr((char*)buf + (*size) -8,"END")) ret=1; } else{ if (*size >= 5){ if (strtok((char*)buf,"D" )) ret=1; } else if (*size < 5) ret = 2; } } } break; case 1 : return ((scan & (M_IS_META | M_CLASS_1))||(f_data->scantype & DATA_READY)) ? 0 :1 ; break; case 2 : offset = 8; b_count = (f_data->buf_length > 12) ? 12 : f_data->buf_length ; ret = follow_png(buf, b_count, &offset, &last_match,(f_data->type == 0x070e)?1:0); ret = analysis_ret1("PNG", f_data, ret , b_count, offset, last_match); break; case 3 : offset = f_data->next_offset ; ret = follow_png(buf, f_data->buf_length, &offset, &last_match,(f_data->type == 0x070e)?1:0); ret = analysis_ret2("PNG", f_data, ret, offset, last_match); break; } return ret; } //mng /*int file_mng(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 0; switch (flag){ case 0 : if ((*size>1) && (buf[(*size)-1] == (unsigned char)0xd5) && (buf[(*size)-2] == (unsigned char)0xf7)) ret = 1; else if ((*size == 1) && (buf[(*size)-1] == (unsigned char)0xd5)) ret = 1; break; case 1 : return (scan & (M_IS_META | M_CLASS_1)) ? 0 :1 ; break; } return ret; }*/ //iff int file_iff(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int i,ret = 0; __u32 ssize; char token[5]; char type[] = "AIFF AIFC 8SVX 16SV SAMP MAUD SMUS CMUS ILBM RGBN RGB8 DEEP DR2D TDDD LWOB LWO2 LWLO REAL MC4D ANIM YAFA SSA ACBM FAXX FTXT CTLG PREF DTYP PTCH AMFF WZRD DOC "; switch (flag){ case 0 : if ((f_data->size) && (f_data->inode->i_size >= f_data->size)) { ssize = ((f_data->size-1) % current_fs->blocksize) +1; if (f_data->inode->i_size > (f_data->size - ssize)){ *size = ssize; ret =1; } } break; case 1 : return (scan & (M_IS_META | M_CLASS_1 )) ? 0 :1 ; break; case 2 : if ((buf[0]==0x46) && (buf[1]==0x4f) && (buf[2] ==0x52) && (buf[3]==0x4d)){ for (i=0;i<4;i++) token[i]=buf[i+8]; token[i] = 0; if(strstr(type,token)){ f_data->size = (buf[4]<<24) + (buf[5]<<16) + (buf[6]<<8) + buf[7] + 8; f_data->scantype = DATA_LENGTH ; ret =1; } } break; } return ret; } //DjVu int file_djvu(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int i,ret = 0; __u32 ssize; char token[5]; char type[] = "DJVU DJVM DJVI THUM "; switch (flag){ case 0 : if ((f_data->size) && (f_data->inode->i_size >= f_data->size)) { ssize = ((f_data->size-1) % current_fs->blocksize) +1; if (f_data->inode->i_size > (f_data->size - ssize)){ *size = ssize; ret =1; } } break; case 1 : return (scan & (M_IS_META | M_CLASS_1 )) ? 0 :1 ; break; case 2 : if ((buf[0]==0x41) && (buf[1]==0x54) && (buf[2] ==0x26) && (buf[3]==0x54) && (buf[4]==0x46) && (buf[5]==0x4f) && (buf[6] ==0x52) && (buf[7]==0x4d)){ for (i=0;i<4;i++) token[i]=buf[i+12]; token[i] = 0; if(strstr(type,token)){ f_data->size = (buf[8]<<24) + (buf[9]<<16) + (buf[10]<<8) + buf[11] + 12; f_data->scantype = DATA_LENGTH ; ret =1; } } break; } return ret; } struct pcx_priv_t { __u16 width; __u16 height; __u16 planes; __u16 w; __u16 h; __u16 p; __u16 RLC; }; static int follow_pcx(unsigned char *buf, __u16 blockcount, __u32 *offset, __u32 *last_match, void *priv){ int flag = 1; int ret = 1; __u32 f_offset = *offset; __u32 end = blockcount * current_fs->blocksize; __u16 w,h,p; struct pcx_priv_t *p_data = (struct pcx_priv_t*) priv; w = h = p = 0; while ( (ret == 1) && (f_offset < (end-1))){ for (p = ((flag) ? p_data->p:0) ; p < p_data->planes ; p++){ for (h = ((flag) ? p_data->h :0) ; h < p_data->height; h++){ for (w = ((flag) ? p_data->w :0) ; w < p_data->width; w++){ if ((p_data->RLC) && ((buf[f_offset] & 0xc0) == 0xc0)){ w += ((buf[f_offset] & 0x3f)-1); f_offset+=2; } else f_offset++; if (f_offset >=(end-1)){ goto out; } } if (flag) flag = 0; if (w > p_data->width){ ret = 0; goto out; } // printf("-----< %d %d %d %d %02x \n",p,h,w,f_offset,buf[f_offset]); } } if (!zero_space(buf,f_offset)){ if (buf[f_offset] == 0x0c){ f_offset += 769; ret =2; } else ret = 0; } else ret =2; } out: // printf("----> %d %d %d %d %02x \n",p,h,w,f_offset,buf[f_offset]); p_data->w = w+1; p_data->h = h; p_data->p = p; *offset = f_offset; return ret; } //pcx int file_pcx(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int i,ret = 0; struct pcx_priv_t *priv; __u32 offset; __u32 last_match = 0; __u32 b_count; struct pcx_header { __u8 Manufacturer; /* should always be 0Ah */ __u8 Version; __u8 Encoding; /* 0: unsed, 1: RLE compressed */ __u8 BitsPerPixel; __u16 XMin; /* image width = XMax-XMin+1 */ __u16 YMin; /* image height = YMax-YMin+1 */ __u16 XMax; __u16 YMax; __u16 H_DPI; __u16 V_DPI; __u8 Palette[48]; __u8 Reserved; __u8 ColorPlanes; /* 4 -- 16 colors ; * 3 -- 24 bit color (16.7 million colors) */ __u16 BytesPerLine; __u16 PaletteType; __u16 HScrSize; /* only supported by */ __u16 VScrSize; /* PC Paintbrush IV or higher */ __u8 Filler[54]; }; struct pcx_header *pcx; switch (flag){ case 0 : if(f_data->scantype & DATA_READY){ *size = (f_data->next_offset)?f_data->next_offset : *size; ret = 1 ; } else { if (*size < (current_fs->blocksize -3)) ret = 4; if (*size < (current_fs->blocksize - 32)) ret = 2; if (*size < (current_fs->blocksize - 64)) ret = 1; } break; case 1 :return ((scan & (M_IS_META | M_CLASS_1 | M_BLANK ))||(f_data->scantype & DATA_READY)) ? 0 :1 ; break; case 2 : pcx = (struct pcx_header*) buf; for (i=0;i<54;i++) if (pcx->Filler[i]) break; if ((pcx->Version<=5 && pcx->Version!=1) && pcx->Encoding <= 1 && (pcx->BitsPerPixel==1 || pcx->BitsPerPixel==4 || pcx->BitsPerPixel==8 || pcx->BitsPerPixel==24) && (pcx->Reserved==0) && (i == 54) && (f_data->priv = malloc(sizeof(struct pcx_priv_t)))){ f_data->priv_len = sizeof(struct pcx_priv_t); memset(f_data->priv,0,sizeof(struct pcx_priv_t)); priv = f_data->priv ; f_data->last_match_blk =1; } else { f_data->first = 0; return 0; } if (!((pcx->Encoding)&& (pcx->ColorPlanes < 4))){// && (pcx->BitsPerPixel > 4))){ return 1; } priv->RLC = pcx->Encoding; priv->width = pcx->BytesPerLine; priv->height = pcx->YMax -pcx->YMin + 1; priv->planes = pcx->ColorPlanes; offset = 128; b_count = (f_data->buf_length > 12) ? 12 : f_data->buf_length ; ret = follow_pcx(buf,b_count, &offset, &last_match,f_data->priv); ret = analysis_ret1("PCX", f_data, ret , b_count, offset, last_match); break; case 3 : offset = f_data->next_offset ; ret = follow_pcx(buf, f_data->buf_length, &offset, &last_match,f_data->priv); ret = analysis_ret2("PCX", f_data, ret, offset, last_match); break; case 4: if (f_data->priv) free(f_data->priv); break; } return ret; } struct xcf_priv_t { int flag ; __u32 width ; __u32 height ; int byte_p_pix ; int s_count ; int compress; __u32 b_stream ; __u32 l_offset ; }; static int follow_xcf(unsigned char *buf, __u16 blockcount, __u32 *offset, __u32 *last_match, void *priv){ int i; int ret = 1; __u32 f_offset = *offset; __u32 *p1, *p2; __u32 type, pl, pointer; __u32 end = (blockcount * current_fs->blocksize)-30; struct xcf_priv_t *p_data = (struct xcf_priv_t*) priv; while ( (ret == 1) && (f_offset < (end-1))){ switch (p_data->flag){ case 0://Master image structure if ((!f_offset) &&(! p_data->b_stream)){ f_offset += 26; p1 = (__u32*) (buf+14); p_data->width = ext2fs_be32_to_cpu(*p1); p1++; p_data->height = ext2fs_be32_to_cpu(*p1); } do{ //Image properties p1 = (__u32*) (buf+f_offset); p2 = p1 +1; type = ext2fs_be32_to_cpu(*p1); pl = ext2fs_be32_to_cpu(*p2); if ((type == 17) && (pl == 1)) p_data->compress = buf[f_offset+8]; if (type) f_offset += (pl + 8); }while(type && (type <28) && (f_offset < end)); if((!pl) && (!type)) { f_offset += 8; p_data->flag = 1; } if (type > 27) ret = 0; break; case 1 : //Pointer to the layer structure do{ p1 = (__u32*) (buf+f_offset); pointer = ext2fs_be32_to_cpu(*p1); if (p_data->l_offset < pointer) p_data->l_offset = pointer; if((p_data->s_count)++ > 256) ret = 0; f_offset += 4; }while (ret && pointer && (f_offset < end)); if(ret && (f_offset < end)){ p_data->flag = 2; p_data->s_count = 0; } break; case 2 : //Pointer to the channel structure do{ p1 = (__u32*) (buf+f_offset); pointer = ext2fs_be32_to_cpu(*p1); if (p_data->l_offset < pointer){ p_data->l_offset = pointer; p_data->flag = 5; //FIXME } if((p_data->s_count)++ > 64) ret = 0; f_offset += 4; }while (ret && pointer && (f_offset < end)); if(ret && (f_offset < end)){ (p_data->flag)++; //FIXME f_offset = (p_data->l_offset - (p_data->b_stream - *offset)); } break; case 3 : //Layer structure p1 = (__u32*) (buf+f_offset); p_data->width = ext2fs_be32_to_cpu(*p1); p1++; p_data->height = ext2fs_be32_to_cpu(*p1); p1++; switch (ext2fs_be32_to_cpu(*p1)){ case 0 : p_data->byte_p_pix = 3 ; break; case 1 : p_data->byte_p_pix = 4 ; break; case 2 : case 4 : p_data->byte_p_pix = 1 ; break; case 3 : case 5 : p_data->byte_p_pix = 2 ; break; default : p_data->byte_p_pix = 0; } if (p_data->width && p_data->height && p_data->byte_p_pix){ p1++; //Layer name pl = ext2fs_be32_to_cpu(*p1); if ((f_offset + 20 + pl) < end){ f_offset += 16; if (pl){ for (i=0; i < (pl-1); i++){ if (! isprint(buf[f_offset+i])){ if (! is_unicode(buf+f_offset+i)) ret = 0; break; } } } if (ret && (!buf[f_offset + pl -1])){ *last_match = f_offset; f_offset += pl; p_data->flag = 4; } } else { end = f_offset; break; } } if (p_data->flag != 4) ret = 0; break; case 7 : //Channel or Mask properties case 4 : //Layer properties do{ p1 = (__u32*) (buf+f_offset); p2 = p1 +1; type = ext2fs_be32_to_cpu(*p1); pl = ext2fs_be32_to_cpu(*p2); if (type) f_offset += (pl + 8); }while(type && (type <28) && (f_offset < end)); if((!pl) && (!type)) { f_offset += 8; (p_data->flag)++; } if (type > 27) ret = 0; break; case 5 : //Pointer to the hierarchy structure p1 = (__u32*) (buf+f_offset); pointer = ext2fs_be32_to_cpu(*p1); if (p_data->l_offset < pointer){ p_data->l_offset = pointer; p_data->flag = 9; } p1++; //Pointer to the layer mask (a channel structure) pointer = ext2fs_be32_to_cpu(*p1); if (pointer &&(p_data->l_offset < pointer)){ p_data->l_offset = pointer; p_data->flag = 6; } f_offset += 8; if (p_data->flag == 5) ret = 0; else { *last_match = f_offset; if (p_data->l_offset < ((p_data->b_stream - *offset) + f_offset)){ ret = 3; break; } else f_offset = (p_data->l_offset - (p_data->b_stream - *offset)); } break; case 6 : //Channel structure (layer masks or from the master image structure) p1 = (__u32*) (buf+f_offset); p2 = p1 +1; if ((p_data->width == ext2fs_be32_to_cpu(*p1)) && (p_data->height == ext2fs_be32_to_cpu(*p2))){ p2++; //Channel or Mask name pl = ext2fs_be32_to_cpu(*p2); if ((f_offset + 20 + pl) < end){ f_offset += 12; if (pl){ for (i=0; i < (pl-1); i++){ if (! isprint(buf[f_offset +i])){ if (! is_unicode(buf+f_offset+i)) ret = 0; break; } } } if (ret && (!buf[f_offset + pl -1])){ *last_match = f_offset; f_offset += pl; p_data->flag = 7; } } else { end = f_offset; break; } } if (p_data->flag == 6) ret = 0; else { *last_match = f_offset; } break; case 8 : //Pointer to the hierarchy structure p1 = (__u32*) (buf+f_offset); pointer = ext2fs_be32_to_cpu(*p1); if (p_data->l_offset < pointer){ p_data->l_offset = pointer; p_data->flag = 9; } f_offset += 4; if (p_data->flag == 8) ret = 0; else { *last_match = f_offset; if (p_data->l_offset < ((p_data->b_stream - *offset) + f_offset)){ ret = 3; break; } else f_offset = (p_data->l_offset - (p_data->b_stream - *offset)); } break; case 9 : //hierarchy structure p1 = (__u32*) (buf+f_offset); p2 = p1 +1; if ((p_data->width == ext2fs_be32_to_cpu(*p1)) && (p_data->height == ext2fs_be32_to_cpu(*p2))){ p2 += 3; p_data->l_offset = ext2fs_be32_to_cpu(*p2); if ((p_data->l_offset)&& (p_data->l_offset > ((p_data->b_stream - *offset) + f_offset))){ *last_match = f_offset; f_offset = (p_data->l_offset - (p_data->b_stream - *offset)); p_data->flag = 10; } else{ ret = 3; break; } } if (p_data->flag == 9) ret = 0; break; case 10 ://Pointer to unused level structure if (f_offset < (end -120)){ do { p1 = (__u32*) (buf+f_offset); p2 = p1 +1; p_data->width >>= 1; p_data->height >>= 1; if (!((p_data->width == ext2fs_be32_to_cpu(*p1)) && (p_data->height == ext2fs_be32_to_cpu(*p2)))){ ret = 0; } else { f_offset += 12; } }while ((p_data->width > 64) || (p_data->height > 64)); if (ret) ret = 2; } else end = f_offset; break; } } p_data->b_stream += (f_offset - *offset); *offset = f_offset; return ret; } //xcf int file_xcf(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int i,ret = 0; __u32 offset; __u32 last_match = 0; __u32 b_count; switch (flag){ case 0 : if(f_data->scantype & DATA_READY){ *size = (f_data->next_offset)?f_data->next_offset : *size; ret = 1 ; } else { __u32 *p1; __u32 e[4]; if (*size > 16){ p1 = (__u32*) (buf + *size -4); for (i = 0; i<4; i++){ e[i] = ext2fs_be32_to_cpu(*p1); p1--; } if((e[0]<65) && ((!e[1])||(!e[2])) && ((e[3] & ~1) == (e[0]<<1))){ ret = 1; *size += 4; break; } } if (*size < (current_fs->blocksize - 8)) ret = 2; if (*size < (current_fs->blocksize - 12)) ret = 1; *size += 4; } break; case 1 :return ((scan & (M_IS_META | M_CLASS_1 | M_BLANK ))||(f_data->scantype & DATA_READY)) ? 0 :1 ; break; case 2 : if ((buf[8]==0x20) && (!buf[13]) && (!buf[22]) && (!buf[23]) && (!buf[24]) && (buf[25]<4) && (f_data->priv = malloc(sizeof(struct xcf_priv_t)))){ f_data->priv_len = sizeof(struct xcf_priv_t); memset(f_data->priv,0,sizeof(struct xcf_priv_t)); f_data->last_match_blk =1; } else{ f_data->first = 0; return 0; } offset = 0; b_count = (f_data->buf_length > 12) ? 12 : f_data->buf_length ; ret = follow_xcf(buf,b_count, &offset, &last_match,f_data->priv); ret = analysis_ret1("XCF", f_data, ret , b_count, offset, last_match); break; case 3 : offset = f_data->next_offset ; ret = follow_xcf(buf, f_data->buf_length, &offset, &last_match,f_data->priv); ret = analysis_ret2("XCF", f_data, ret, offset, last_match); break; case 4: if (f_data->priv) free(f_data->priv); break; } return ret; } //ico int file_ico(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ struct ico_directory { __u8 width; __u8 heigth; __u8 color_count; __u8 reserved; __u16 color_planes; __u16 bits_per_pixel; __u32 bitmap_size; __u32 bitmap_offset; } *ico_dir; __u16 *p_count; int counter; int ret = 0; __u32 offset = 22 ; switch (flag){ case 0 : if ((f_data->size) && (f_data->inode->i_size >= f_data->size)) { counter = ((f_data->size-1) % current_fs->blocksize)+1; if (f_data->inode->i_size > (f_data->size - counter)){ *size = counter; ret =1; } } else{ if ((*size) < (current_fs->blocksize - 128)){ ret=1; } else if ((*size) < (current_fs->blocksize - 16)){ ret=2; } } break; case 1 : return (scan & (M_IS_META | M_CLASS_1)) ? 0 :1 ; break; case 2 : p_count = (__u16*) (buf + 4) ; counter = (int) (ext2fs_le16_to_cpu(*p_count)); if (counter && (counter <= 256)){ ico_dir = (struct ico_directory*)(buf + 6) ; while (counter && offset){ if ((!ico_dir->reserved) && ico_dir->width && ico_dir->heigth){ if (ext2fs_le32_to_cpu(ico_dir->bitmap_offset) >= offset){ offset = ext2fs_le32_to_cpu(ico_dir->bitmap_offset) + ext2fs_le32_to_cpu(ico_dir->bitmap_size); }//else // offset = 0; } else{ offset = 0; break; } counter-- ; ico_dir++ ; } } if ((offset > 22) && (! counter)){ f_data->size = offset; f_data->scantype = DATA_LENGTH; ret = 1; } else f_data->func = NULL; break; } return ret; } //tga int file_tga(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int i,j,x,y; __u16 *p ; __u32 ssize = 0; __u32 psize = 0; int ret = 0; char token[]="-XFILE."; switch (flag){ case 0 : if ((f_data->size) && (f_data->inode->i_size < f_data->size)) return 0; j = strlen(token) -1; i = (*size) -1; while ((i >= 0) && (j >= 0) && (buf[i] == token[j])){ i--; j--; } if ((i == -1) || (j == -1)){ *size = (*size) + 1 ; ret=1; } else{ if (f_data->size){ ssize = ((f_data->size-1) % current_fs->blocksize)+1; if (f_data->inode->i_size > (f_data->size - ssize)){ // *size = ssize; ret = 2; } } else{ if ((*size) < (current_fs->blocksize - 256)){ ret=1; } else if ((*size) < (current_fs->blocksize - 32)){ ret=2; } } } break; case 1 : return (scan & (M_IS_META | M_CLASS_1)) ? 0 :1 ; break; case 2 : if ((buf[16]==1) || (buf[16]==8) || (buf[16]==15) || (buf[16]==16) || (buf[16]==24) || (buf[16]==32)){ if (buf[2] < 4){ p = (__u16*) (buf + 8); i = ext2fs_le16_to_cpu(*p); p++; j = ext2fs_le16_to_cpu(*p); p++; x = ext2fs_le16_to_cpu(*p); p++; y = ext2fs_le16_to_cpu(*p); if ((x<32)||(y<32)|| (i>(x/8))||(j>(y/8))){ f_data->first = 0; return 0; } ssize = x * y; switch (buf[16]){ case 1 : ssize = 0; break; case 15 : ssize *= 2; break; default : ssize *= (buf[16] / 8); break; } if (ssize && (buf[1] == 1)) { p = (__u16*) (buf + 5); psize = ext2fs_le16_to_cpu(*p) ; psize *= ((buf[7]+1) / 8); p--; psize += ext2fs_le16_to_cpu(*p); } if (ssize){ ssize += (psize + 18); f_data->size = ssize; f_data->scantype = DATA_MIN_LENGTH; ret = 1; } } else //runlength encoding f_data->scantype = H_F_Carving; } else{ f_data->func = NULL; ret = 0; } break; } return ret; } //matroska int file_mkv(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int i, ret = 0; unsigned char header[] ={0x1a,0x45,0xDF,0xA3}; unsigned char segment[] ={0x18,0x53,0x80,0x67}; unsigned char *p; __u64 offset = 0; __u64 result; switch (flag){ case 0 : if (f_data->size || f_data->h_size) { if (f_data->h_size != f_data->inode->i_size_high) ret = 0; else{ if (f_data->inode->i_size < f_data->size) ret = 0; else{ if (f_data->scantype & DATA_LENGTH){ *size = ((f_data->size-1) % current_fs->blocksize)+1 ; ret = 1; } else{ if (*size < (current_fs->blocksize -16)) ret = 4; if (*size < (current_fs->blocksize -64)) ret = 2; if (*size < (current_fs->blocksize -256)) ret = 1; } } } } break; case 1 : return (scan & (M_IS_META | M_CLASS_1)) ? 0 :1 ; break; case 2 : p = buf; if (strncmp((char*)p,(char*)header,4)) break; p +=4; i = read_ebml(&result,(void*)p); if (!i) break; offset = result + 4 + i; p += (__u32) result + i; if (strncmp((char*)p,(char*)segment,4)) break; p +=4; i = read_ebml(&result,(void*)p); if (!i) break; offset += result + 4 + i; f_data->size = offset & 0xFFFFFFFF; f_data->h_size = offset >> 32; f_data->scantype = DATA_LENGTH; ret = 1; break; } return ret; } //midi int file_midi(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 0; switch (flag){ case 0 : if ((*size>1) && (buf[(*size)-1] == (unsigned char)0x2f) && (buf[(*size)-2] == (unsigned char)0xff)){ *size +=1; ret = 1; } else if ((*size == 1) && (buf[(*size)-1] == (unsigned char)0x2f)){ *size +=1 ; ret = 1; } break; case 1 :return (scan & (M_IS_META | M_CLASS_1 | M_BLANK)) ? 0 :1 ; break; } return ret; } //swf int file_swf(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 0; __u32 *p_32; __u32 ssize; __u32 b_count; __u32 offset = 0; __u32 last_match = 0; switch (flag){ case 0 : if (f_data->size){ ssize = ((f_data->size-1) % current_fs->blocksize)+1; if ((f_data->inode->i_size >= f_data->size) && (f_data->inode->i_size > (f_data->size - ssize))){ *size = ssize; ret =1; } } else{ if ((*size) < (current_fs->blocksize - 3)){ ret=1; } } break; case 1: return ((scan & (M_IS_META | M_CLASS_1 | M_BLANK ))||(f_data->scantype & DATA_READY)) ? 0 :1 ; break; case 2: p_32 = (__u32*)(buf+4); ssize = ext2fs_le32_to_cpu(*p_32); if (buf[0] == 'F'){ f_data->size = ssize; f_data->scantype = DATA_LENGTH; ret = 1; } else { ssize -= 8; if(init_priv_zlib(f_data)) return 0; ((struct priv_zlib_t*)(f_data->priv))->flag = 0x6; if ((buf[0] == 'C') && (!follow_zlib(NULL,0,&ssize,NULL,(struct priv_zlib_t *)f_data->priv))){ offset = 8; b_count = (f_data->buf_length > 12) ? 12 : f_data->buf_length ; ret = follow_zlib(buf, b_count, &offset, &last_match,(struct priv_zlib_t *)f_data->priv); ret = analysis_ret1("CWF", f_data, ret , b_count, offset, last_match); } } break; case 3 : offset = f_data->next_offset ; ret = follow_zlib(buf, f_data->buf_length, &offset, &last_match,(struct priv_zlib_t *)f_data->priv); ret = analysis_ret2("CWF", f_data, ret, offset, last_match); break; case 4: if (f_data->priv){ if (((struct priv_zlib_t*)(f_data->priv))->flag) inflateEnd( &((struct priv_zlib_t*)(f_data->priv))->z_strm); free(f_data->priv); } break; } return ret; } /* //aiff int file_aiff(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 0; __u32 *p_32; __u32 ssize; switch (flag){ case 0 : if ((f_data->size) && (f_data->inode->i_size >= f_data->size)) { ssize = ((f_data->size-1) % current_fs->blocksize)+1; if (f_data->inode->i_size > (f_data->size - ssize)){ *size = ssize; ret =1; } } break; case 1: return (scan & (M_IS_META | M_CLASS_1 | M_BLANK )) ? 0 :1 ; break; case 2: if (buf[8] == 'A'){ p_32 = (__u32*)(buf+4); ssize = ext2fs_be32_to_cpu(*p_32) +8; f_data->size = ssize; f_data->scantype = DATA_LENGTH; ret = 1; } break; } return ret; } */ static int follow_asf(unsigned char *buf, __u16 blockcount, __u32 *offset, __u32 *last_match, int flag){ static const unsigned char top_header[16] = { 0x30,0x26,0xb2,0x75,0x8e,0x66,0xcf,0x11,0xa6,0xd9,0x00,0xaa,0x00,0x62,0xce,0x6c }; static const unsigned char index[6][8] = { {0x36,0x26,0xb2,0x75,0x8e,0x66,0xcf,0x11}, {0x90,0x08,0x00,0x33,0xb1,0xe5,0xcf,0x11}, {0xd3,0x29,0xe2,0xd6,0xda,0x35,0xd1,0x11}, {0xf8,0x03,0xb1,0xfe,0xad,0x12,0x64,0x4c}, {0xd0,0x3f,0xb7,0x3c,0x4a,0x0c,0x03,0x48}, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}; int ret = 1; unsigned char *p_offset; __u64 f_offset; __u64 obj_size; int j,i=0; f_offset = (__u64) *offset; while ( (ret == 1) && (f_offset < (blockcount * current_fs->blocksize)-57)){ obj_size = 0; p_offset = buf + (f_offset & 0xffffffff); if (flag && (!f_offset)){ if( memcmp(buf,top_header,16)) { i = 7; } } else { for (i=0 ; i<6 ; i++){ for (j=0;j<8;j++){ if (! (p_offset[j] == index[i][j])) break; } if(j < 8) continue; break; } } if (i<6){ obj_size = (__u64) p_offset[16] | (p_offset[17]<<8) | (p_offset[18]<<16) | (p_offset[19]<<24) | ((__u64)p_offset[20]<<32) | ((__u64)p_offset[21]<<40) | ((__u64)p_offset[22]<<48) | ((__u64)p_offset[23]<<56) ; } else ret = 0; if (ret && (obj_size < 30)){ if ((!obj_size) && (i==5) && (zero_space(buf, f_offset & 0xffffffff))) ret =2; //FIXME if this is zero block else ret = 0; } if (ret){ *last_match = (__u32)(f_offset & 0xffffffff); f_offset += obj_size; } } *offset = (__u32) f_offset & 0xFFFFFFFF ; return ret; } //asf int file_asf(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 0; __u32 last_match = 0; __u32 offset; int b_count; switch (flag){ case 0 : if (f_data->size || f_data->h_size) { if (f_data->h_size != f_data->inode->i_size_high) ret = 0; else{ if (f_data->inode->i_size < f_data->size) ret = 0; else{ if (f_data->scantype & DATA_READY){ *size = ((f_data->size-1) % current_fs->blocksize)+1 ; ret = 1; } else{ *size += 4; ret = 2; } } } } break; case 1: return ((scan & (M_IS_META | M_CLASS_1 | M_BLANK ))||(f_data->scantype & DATA_READY)) ? 0 :1 ; break; case 2 : offset = 0; b_count = (f_data->buf_length > 12) ? 12 : f_data->buf_length ; ret = follow_asf(buf, b_count, &offset, &last_match,1); ret = analysis_ret1("ASF", f_data, ret , b_count, offset, last_match); break; case 3 : offset = f_data->next_offset ; ret = follow_asf(buf, f_data->buf_length, &offset, &last_match,0); ret = analysis_ret2("ASF", f_data, ret, offset, last_match); break; } return ret; } struct flac_priv_t { __u8 b_head[4]; __u32 begin; __u32 max_blocks; __u16 crc; __u16 flag;} ; static int follow_flac(unsigned char *buf, __u16 blockcount, __u32 *offset, __u32 *last_match, void *priv){ int size,ret = 1; struct flac_priv_t *p_data = (struct flac_priv_t*) priv; __u32 end = blockcount * current_fs->blocksize; __u32 blocksize; __u32 bits_per_sample; __u32 channel; // __u64 total_samples; __u32 f_offset = *offset; p_data->begin = f_offset; while ( (ret == 1) && (f_offset < (end-21))){ switch (p_data->flag){ case 0: //search metadata if ((buf[f_offset] == 0xff) && ((buf[f_offset+1] & 0xfd) == 0xf8)){ // first Blockheader (p_data->flag)++; memcpy(p_data->b_head,buf+f_offset,4); *last_match = f_offset; p_data->flag = 1; // p_data->begin = f_offset; break; } if ((buf[f_offset] & 0x7f) > 126 ) // invalid break ret = 0; else{ //meta data size = (buf[f_offset+1]<<16) + (buf[f_offset+2]<<8) + buf[f_offset+3] +4; if(!(buf[f_offset] & 0x7f)){ //stream info blocksize = (buf[f_offset+4]<<8) + buf[f_offset+5]; bits_per_sample = ((buf[f_offset+16] & 0x01) << 4) + ((buf[f_offset+17] & 0xf0) >> 4) +1 ; channel = ((buf[f_offset+16] & 0x0e) >>1) +1; // total_samples = (((__u64)(buf[f_offset+17] & 0x0f0))<<32)+(buf[f_offset+18] <<24)+(buf[f_offset+19] <<16)+ // (buf[f_offset+20] <<8)+(buf[f_offset+21]); p_data->max_blocks = blocksize * 2 * channel; } f_offset += size; } break; case 1: // first FRAME_HEADER if ((p_data->b_head[0] == buf[f_offset]) && (p_data->b_head[1] == buf[f_offset+1]) && (p_data->b_head[2] == buf[f_offset+2]) && ((p_data->b_head[3]&0x0f) == (buf[f_offset+3]&0x0f))){ p_data->begin = f_offset; p_data->flag = 3; p_data->crc = 0; f_offset += 4; } case 2: f_offset += 4; p_data->flag = 3; case 3: if (p_data->begin == f_offset) f_offset += 2; while (( f_offset < (end -4)) && ((f_offset - p_data->begin)< p_data->max_blocks) && (!((buf[f_offset] == 0xff) && ((buf[f_offset+1] & 0xfd) == 0xf8) && (p_data->b_head[2] == buf[f_offset+2]) && ((p_data->b_head[3]&0x0f) == (buf[f_offset+3]&0x0f))))){ f_offset ++; if ((!(buf[f_offset])) && (!(buf[f_offset+1]))&& (!(buf[f_offset+2]))&&(zero_space(buf,f_offset))){ p_data->crc = FLAC__crc16(buf+p_data->begin,f_offset - p_data->begin-2,p_data->crc); p_data->begin = f_offset - 2; if ((((p_data->crc) & 0x00ff) == buf[f_offset-1]) && ((((p_data->crc) & 0xff00)>>8) == buf[f_offset-2])){ *offset = f_offset; return 2; // file complete } } } if (f_offset == (end -4)){ f_offset--; p_data->crc = FLAC__crc16(buf+p_data->begin,f_offset - p_data->begin,p_data->crc); } else { if ((f_offset - p_data->begin)== p_data->max_blocks) ret = 0; else { p_data->crc = FLAC__crc16(buf+p_data->begin,f_offset - p_data->begin-2,p_data->crc); if (!((((p_data->crc) & 0x00ff) == buf[f_offset-1]) && ((((p_data->crc) & 0xff00)>>8) == buf[f_offset-2]))) ret = 0; else { p_data->begin = f_offset; *last_match = f_offset; p_data->crc = 0; p_data->flag = 2; } } } break; } } *offset = f_offset; return ret; } static int follow_creative_voice(unsigned char *buf, __u16 blockcount, __u32 *offset, __u32 *last_match, int flag){ int size,ret = 1; __u32 end = blockcount * current_fs->blocksize; __u32 f_offset = *offset; while ( (ret == 1) && (f_offset < (end-4))){ size = buf[f_offset+1] + ((buf[f_offset+2])<<8) + ((buf[f_offset+3])<<16); switch (buf[f_offset]){ case 0 : if (zero_space(buf, f_offset)){ f_offset++; ret= 2; } else ret = 0; break; case 1 : case 2 : case 3 : case 4 : case 5 : case 6 : case 7 : case 8 : *last_match = f_offset; f_offset += (size +4) ; break; case 9 : *last_match = f_offset; f_offset += (size + 12) ; break; default: ret = 0; break; } } *offset = f_offset; return ret; } //Creative Voice int file_creative_voice(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ unsigned char cv_header[20] = "Creative Voice File" ; cv_header[19] = 0x1a; __u32 offset; __u32 last_match = 0; __u32 b_count; __s16 tmp; int ret = 0; switch (flag){ case 0 : if(f_data->scantype & DATA_READY){ *size = (f_data->next_offset)?f_data->next_offset : *size; ret = 1; } else{ if (*size < (current_fs->blocksize -8)) ret = 4; if (*size < (current_fs->blocksize -64)) ret = 2; if (*size < (current_fs->blocksize -128)) ret = 1; (*size)++; } break; case 1 : return ((scan & (M_IS_META | M_CLASS_1 | M_BLANK))||(f_data->scantype & DATA_READY)) ? 0 :1 ; break; case 2 : tmp = ~((buf[23]<<8)+buf[22]); if ((memcmp(buf,cv_header,20)) || ((__s16)(((buf[25])<<8) + buf[24] -0x1234) != tmp)){ f_data->func = NULL; return 0; } offset = ((buf[21])<<8) + buf[20]; b_count = (f_data->buf_length > 12) ? 12 : f_data->buf_length ; ret = follow_creative_voice(buf, b_count, &offset, &last_match,0); ret = analysis_ret1("CREATIVE-VOICE", f_data, ret , b_count, offset, last_match); break; case 3 : offset = f_data->next_offset ; ret = follow_creative_voice(buf, f_data->buf_length, &offset, &last_match,0); ret = analysis_ret2("CREATIVE-VOICE", f_data, ret, offset, last_match); break; } return ret; } //flac int file_flac(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ __u32 offset; __u32 last_match = 0; __u32 b_count; int ret = 0; //static const unsigned char token[4]= {0x66,0x4c,0x61,0x43}; switch (flag){ case 0 : if(f_data->scantype & DATA_READY){ *size = (f_data->next_offset)?f_data->next_offset : *size; ret = 1; } else{ if ((f_data->size) && (f_data->size < f_data->inode->i_size)){ if (*size < current_fs->blocksize-7) ret = 1; } else { if (!f_data->size){ if (*size < current_fs->blocksize-64) ret = 2; if (*size < current_fs->blocksize-128) ret = 1; } } } break; case 1 : if (f_data->size > f_data->inode->i_size) ret = (scan & (M_IS_META | M_CLASS_1 )) ? 0 :1 ; else ret = ((scan & (M_IS_META | M_CLASS_1 | M_BLANK | M_TXT ))||(f_data->scantype & DATA_READY)) ? 0 :1 ; break; case 2: f_data->priv = malloc(sizeof(struct flac_priv_t)); if(f_data->priv){ f_data->priv_len = sizeof(struct flac_priv_t); memset(f_data->priv,0,sizeof(struct flac_priv_t)); } else { f_data->first = 0; return 0; } offset = test_id3_tag(buf) +4 ; b_count = (f_data->buf_length > 12) ? 12 : f_data->buf_length ; ret = follow_flac(buf, b_count, &offset, &last_match,f_data->priv); ret = analysis_ret1("FLAC", f_data, ret , b_count, offset, last_match); break; case 3 : offset = f_data->next_offset ; ret = follow_flac(buf, f_data->buf_length, &offset, &last_match,f_data->priv); ret = analysis_ret2("FLAC", f_data, ret, offset, last_match); break; case 4 : if (f_data->priv) free(f_data->priv); ret = 1; break; } return ret; } static int follow_mpeg(unsigned char *buf, __u16 blockcount, __u32 *offset, __u32 *last_match, int flag){ int ret =1; __u32 end; __u32 frame_offset = *offset; __u32 tmp = 0; __u32 i ; int tolerance = 64; //for incorrect zero-byte padding end = blockcount * current_fs->blocksize ; while ((ret == 1) && ((frame_offset+14) <= end)){ if (buf[frame_offset] || buf[frame_offset+1] || (buf[frame_offset+2] != 0x01)) { if (tolerance){ if ((!buf[frame_offset]) && (!buf[frame_offset+1]) && (!buf[frame_offset+2])){ frame_offset++; tolerance --; continue; } } if (zero_space(buf,frame_offset)) ret = 3; else ret = 0; break; } if (!flag){ switch (buf[frame_offset+3]) {//Multiplexed Stream case 0xb9: /* program end code */ ret = 2; frame_offset += 4; break; case 0xba: /* pack header */ if ((buf[frame_offset+4] & 0xc0) == 0x40) /* mpeg2 */ tmp = 14 + (buf[frame_offset+13] & 7); else if ((buf[frame_offset+4] & 0xf0) == 0x20) /* mpeg1 */ tmp = 12; *last_match = frame_offset; frame_offset += tmp; break; //audio case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: //video case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: //privat stream / Padding stream /System Header/Program Stream Map case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf: tmp = 6 + (buf[frame_offset+4] << 8) + buf[frame_offset+5]; *last_match = frame_offset; frame_offset += tmp; break; default: if (buf[frame_offset+3] < 0xb9) { // fprintf(stderr, "broken stream - skipping data\n"); tmp = 6 + (buf[frame_offset+4] << 8) + buf[frame_offset+5]; // *last_match = frame_offset; frame_offset += tmp; break; } else ret = 3; //0xf0->0xff } } else{ //Elementar Stream switch (buf[frame_offset+3]) { case 0x00: //Picture tmp = 8; if (buf[frame_offset+5] & 0x10) //backward_vector tmp += 1; //FIXME (extra_bit_picture) *last_match = frame_offset; frame_offset += tmp ; break; case 0xb3: //Sequence Header *last_match = frame_offset; if (frame_offset < (end -75)){ tmp = (buf[frame_offset+11] & 0x2)? 76 : 12 ; //Intra Matrix tmp += (buf[frame_offset + tmp -1] & 0x01) ? 64 : 0; //Non Intra Matrix frame_offset += tmp ; } else ret = 8; break; case 0xb5: //extension header *last_match = frame_offset; if (frame_offset < (end -196)){ switch (buf[frame_offset+4] & 0xf0){ case 0x10: //Sequence Extension tmp = 10; break; case 0x20: //Sequence Display Extension tmp = (buf[frame_offset+4] & 0x01) ? 12 : 9; break; case 0x30: //Quant Matrix Extension tmp = (buf[frame_offset+4] & 0x8) ? 69 : 5 ; //Intra Quantiser Matrix tmp += (buf[frame_offset+tmp-1] & 0x4) ? 64 : 0 ; //Non Intra Quantiser Matrix tmp += (buf[frame_offset+tmp-1] & 0x2) ? 64 : 0 ; //Chroma Intra Quantiser Matrix tmp += (buf[frame_offset+tmp-1] & 0x1) ? 64 : 0 ; //Chroma Non Intra Quantiser Matrix break; case 0x40: //Copyright Extension tmp = 15; break; case 0x50: //Sequence Scalable Extension // tmp = (buf[frame_offset+4] & 0x0c) ??? 6 ??? 7 ??? 12 ; //FIXME tmp = 6; while ((tmp <= 12) && (buf[frame_offset + tmp] || buf[frame_offset + tmp +1] || (buf[frame_offset+ tmp +2] != 0x01))) tmp++; if (tmp > 12) ret = 0; break; case 0x70: //Picture Display Extension tmp = 9; break; case 0x80: //Picture Coding Extension tmp = (buf[frame_offset+8] & 0x40) ? 11 : 9; break; } frame_offset += tmp; } else ret = 8; break; case 0xb7: //Sequence End tmp = 4 ; frame_offset += tmp ; if ((!buf[frame_offset]) && (!buf[frame_offset+1]) && (buf[frame_offset+2] == 1)) break; else ret = 2; break; case 0xb8: //Group of Picture tmp = 8; *last_match = frame_offset; frame_offset += tmp; break; default: if ((buf[frame_offset+3] < 0xb0) || (buf[frame_offset+3] == 0xb2)){ // slice or user_data *last_match = frame_offset; tmp = 6; while (((frame_offset + tmp + 4) < end) && (buf[frame_offset + tmp] || buf[frame_offset + tmp +1] || (buf[frame_offset+ tmp +2] != 0x01))) tmp++; if ((frame_offset + tmp + 4) >= end) // ret=8; ret =((10*current_fs->blocksize)<=tmp)?0:8; else{ if (((buf[frame_offset + tmp +3]) < 0xb9) && (tmp < 9500)) //max slice size ??????? frame_offset += tmp; else { i=6; while ((i<(tmp-1))&&((buf[frame_offset+i])||(buf[frame_offset+i+1]))) i++; if ((i < tmp) && zero_space(buf,frame_offset+i)){ frame_offset += i; ret = 2; } else ret = 0; } } break; } else{ // fprintf(stderr, "broken mpeg elementar stream - skipping data\n"); ret = 0; } } } //if }//while *offset = frame_offset; return ret; } //mpeg int file_mpeg(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int i,j; int ret = 0; __u32 offset; __u32 b_count; __u32 last_match = 0; static const unsigned char token0[4]= {0x00,0x00,0x01,0xb9}; static const unsigned char token1[4]= {0x00,0x00,0x01,0xb7}; switch (flag){ case 0 : j = 3 ; i = (*size) -1; while ((i >= 0) && (j >= 0) && (buf[i] == token0[j])){ i--; j--; } if ((i != -1 ) && (j != -1)){ j = 3 ; i = (*size) -1; while ((i >= 0) && (j >= 0) && (buf[i] == token1[j])){ i--; j--; } } if ((i == -1) || (j == -1)){ ret=1; } else{ if ((f_data->scantype & (DATA_READY))||((f_data->last_match_blk) && (f_data->last_match_blk <= (f_data->inode->i_size/current_fs->blocksize)) && (*size < (current_fs->blocksize - 2)))){ ret=1; break; } if(*size < (current_fs->blocksize - 48)) ret=4; else{ //FIXME if (!(current_fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) && (*size > (current_fs->blocksize - 2)) && (f_data->inode->i_size > (12 * current_fs->blocksize)) && ((f_data->inode->i_blocks - (13 * (current_fs->blocksize / 512))) % 256) ){ *size = current_fs->blocksize; ret = 4; } } } break; case 1 : return ((scan & (M_IS_META | M_CLASS_1 ))||(f_data->scantype & DATA_READY)) ? 0 :1 ; break; case 2 : offset = 0; if (buf[3] < 0xb9) f_data->scantype = DATA_ELEMENT | DATA_NO_FOOT ; b_count = (f_data->buf_length > 12) ? 12 : f_data->buf_length ; ret = follow_mpeg(buf, b_count, &offset, &last_match,(f_data->scantype & DATA_ELEMENT)); if (last_match) f_data->last_match_blk = (last_match/current_fs->blocksize) +1 ; if (ret){ f_data->scantype |= DATA_CARVING; f_data->size = offset; if (offset > (b_count * current_fs->blocksize)) f_data->buf_length = b_count; else f_data->buf_length = offset / current_fs->blocksize; f_data->next_offset = offset - (f_data->buf_length * current_fs->blocksize); } switch (ret){ case 0 : // fprintf(stderr,"MPEG-CHECK: Block %lu : Break\n",f_data->first); f_data->scantype |= DATA_BREAK; f_data->func = NULL; return 0; break; case 1: break; case 2 : f_data->scantype |= DATA_READY; if(offset % current_fs->blocksize)(f_data->buf_length)++; break; case 3: // fprintf(stderr,"MPEG-CHECK: mpeg-sequence found, H_F-Carving on\n"); f_data->scantype = H_F_Carving; break; case 8 : ret = 1; break; } break; case 3 : offset = f_data->next_offset ; ret = follow_mpeg(buf, f_data->buf_length, &offset, &last_match,(f_data->scantype & DATA_ELEMENT)); if (last_match) f_data->last_match_blk = ((f_data->size - f_data->next_offset + last_match)/current_fs->blocksize) +1 ; if (ret){ f_data->size += offset - f_data->next_offset; f_data->buf_length = offset / current_fs->blocksize; f_data->next_offset = offset - (f_data->buf_length * current_fs->blocksize); } switch (ret){ case 0 : // fprintf(stderr,"MPEG-CHECK: mpeg-data error, recover not\n"); f_data->scantype |= DATA_BREAK; break; case 8 : ret = 1; // NO break; case 1 : // fprintf(stderr,"MPEG-CHECK: mpeg-data next found\n"); break; case 2 : // fprintf(stderr,"MPEG-CHECK: mpeg-data end found, recover\n"); f_data->scantype |= DATA_READY; if(offset % current_fs->blocksize) (f_data->buf_length)++; break; case 3: // fprintf(stderr,"MPEG-CHECK: mpeg-sequence or end of stream found, H_F-Carving on\n"); if (!f_data->next_offset){ f_data->scantype |= DATA_READY; ret = 2; } else f_data->scantype = H_F_Carving; break; } break; } return ret; } //riff int file_riff(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ __u32 *p_32 ; __u32 ssize , offset ; int ret = 0; switch (flag){ case 0 : if ((f_data->size) && (f_data->size <= f_data->inode->i_size)){ ssize = ((f_data->size-1) % current_fs->blocksize)+1; *size = (ssize >= *size)? ssize : (*size) + 2; ret = 1; } else { if ( (!f_data->size) && (*size>4) && (buf[(*size)-2] == 'D') && (buf[(*size)-3] == 'N') &&(buf[(*size)-4] == 'E')) ret = 1; else ret =0; } break; case 1 : return (scan & (M_IS_META | M_CLASS_1 )) ? 0 :1 ; break; case 2 : offset = test_id3_tag(buf); p_32 = (__u32*)(buf + offset); p_32++; switch (buf[offset + 3]){ case 'F' : ssize = ext2fs_le32_to_cpu(*p_32) + 8 ; break; case 'X' : ssize = ext2fs_be32_to_cpu(*p_32) + 8 ; break; default : ssize = 0; } f_data->size = offset ? (offset + ssize) : ssize ; if (f_data->size > current_fs->blocksize) f_data->scantype = DATA_LENGTH; else f_data->scantype = H_F_Carving; ret=1; break; } return ret; } //psd int file_psd(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 0; switch (flag){ case 0 : if (*size < (current_fs->blocksize - 16)){ if ((!buf[(*size)-2]) && (!buf[(*size)-4])) (*size)++; ret = 1; } else { if (*size < (current_fs->blocksize - 2)) ret = 2; } break; case 1 : return (scan & (M_IS_META | M_CLASS_1)) ? 0 :1 ; break; } return ret; } //pnm int file_pnm(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int x,y,d,s ; char *c, *txt; __u32 ssize = 0; int ret = 0; switch (flag){ case 0 : if (f_data->size ) { ssize = ((f_data->size-1) % current_fs->blocksize)+1; if (f_data->inode->i_size > (f_data->size - ssize)){ *size = ssize; ret =1; } } else{ if ((*size) < (current_fs->blocksize - 16)){ ret = 2; } } break; case 1: return (scan & (M_IS_META | M_CLASS_1 )) ? 0 :1 ; break; case 2: c = (char*)buf; if (*c =='P'){ c++; txt = c + 1; while (isspace(*txt)) txt++; while (*txt == '#'){ s = 0; while ((*txt != 0x0a) && (*txt != 0x0d) && (s < 70)){ txt++; s++; } if (s == 70) { f_data->func = file_none; return 0; } while (isspace(*txt)) txt++; } x=atoi(txt); while (isdigit(*txt)) txt++; txt++; y=atoi(txt); while (isdigit(*txt)) txt++; txt++; if (x && y){ switch (*c){ case 49 : case 50 : case 51 : f_data->func = file_bin_txt; break; case 52 : ssize = ((x*y)+7) / 8 ; ssize += (__u32)(txt - (char*)buf); break; case 53 : d = atoi(txt); while (isdigit(*txt)) txt++; txt++; if (d && d< 256) ssize = 1; else if(d) ssize = 2; if (ssize){ ssize *= (x*y); ssize += (__u32)(txt - (char*)buf); } break; case 54 : d = atoi(txt); while (isdigit(*txt)) txt++; txt++; if (d && d< 256) ssize = 3; else if(d) ssize = 6; if (ssize){ ssize *= (x*y); ssize += (__u32)(txt - (char*)buf); } break; } if (ssize){ f_data->size = ssize; if (f_data->size > current_fs->blocksize) f_data->scantype = DATA_LENGTH; else f_data->scantype = H_F_Carving; ret = 1; } } } break; } return ret; } struct private_tiff_t { int flag ; // Bit0 search IFD; Bit1 process IFD; Bit2 test EOF; Bit7 BIGENDIAN __u32 count; __u32 last_id; __u32 ifd; //offset of last IFD __u32 max ; // currently found maximum offset }; static int follow_tiff(unsigned char *buf, __u16 blockcount, __u32 *offset, __u32 *last_match, struct private_tiff_t* priv){ char b_count[13]= {0,1,1,2,4,8,1,1,2,4,8,4,8}; //size in Byte int i,j; int ret = 1; __u32 f_offset = *offset; __u16 count, id; __u16 type = 0; __u16 needful = 4 ; __u32 end = blockcount * current_fs->blocksize; __u32 max = priv->max; __u32 entry_offset = 0; __u32 entry_count = 0; __u32 entry; __u32 last_strip_offset = 0; __u32 last_strip_byte_count = 0; if ((priv->count) && (priv->flag & 0x2)) needful = (priv->count * 12)+4 ; while ((ret == 1) && (f_offset < (end - needful))){ switch ((priv->flag) & 0x7){ case 1 : if ((priv->flag)&0x8) count = ((buf[f_offset])<<8) + buf[f_offset+1]; else count = ((buf[f_offset+1])<<8) + buf[f_offset]; f_offset += 2; if ((count) && (count < 256)){ priv->count = count; priv->last_id = 0; priv->flag += 1; needful = (count*12)+4; } else ret = 0; break; case 2 : if (priv->count){ for (i = 0; i < priv->count; i++){ entry = 0; if ((priv->flag)&0x8) id = ((buf[f_offset])<<8) + buf[f_offset+1]; else id = ((buf[f_offset+1])<<8) + buf[f_offset]; if (priv->last_id > id){ ret = 0; break; } priv->last_id = id; if ((priv->flag)&0x8) type = ((buf[f_offset+2])<<8) + buf[f_offset+3]; else type = ((buf[f_offset+3])<<8) + buf[f_offset+2]; if(!type || (type > 12)){ ret = 0; break; } type = b_count[type]; if ((priv->flag)&0x8){ entry_count = ((buf[f_offset+4])<<24)+((buf[f_offset+5])<<16)+((buf[f_offset+6])<<8)+buf[f_offset+7]; entry_offset = (((buf[f_offset+8])<<24)+((buf[f_offset+9])<<16)+((buf[f_offset+10])<<8)+buf[f_offset+11]); if ((entry_count * type)>4) entry =(entry_count * type ) + entry_offset; } else{ entry_count = ((buf[f_offset+7])<<24)+((buf[f_offset+6])<<16)+((buf[f_offset+5])<<8)+buf[f_offset+4]; entry_offset = (((buf[f_offset+11])<<24)+((buf[f_offset+10])<<16)+((buf[f_offset+9])<<8)+buf[f_offset+8]); if ((entry_count *type)>4) entry =(entry_count * type) + entry_offset; } if (!entry_count){ ret=0; break; } if ((id == 273) && (entry) && (entry < (priv->ifd - *offset + end))&& ((priv->ifd - *offset) < entry)){//StripOffsets j = (priv->ifd)? (entry - priv->ifd + *offset) : entry; switch (type){ case 2: if ((priv->flag)&0x8) last_strip_offset = ((buf[j-2])<<8) + buf[j-1] ; else last_strip_offset = ((buf[j-1])<<8) + buf[j-2] ; break; case 4: if ((priv->flag)&0x8) last_strip_offset = ((buf[j-4])<<24) + ((buf[j-3])<<16)+ ((buf[j-2])<<8) + buf[j-1] ; else last_strip_offset = ((buf[j-1])<<24) + ((buf[j-2])<<16)+ ((buf[j-3])<<8) + buf[j-4] ; break; default: ret = 0; } } if ((id == 279) && (entry) && (entry < (priv->ifd - *offset + end)) && ((priv->ifd - *offset) < entry)){//StripByteCounts j = (priv->ifd)? (entry - priv->ifd + *offset) : entry; switch (type){ case 2: if ((priv->flag)&0x8) last_strip_byte_count = ((buf[j-2])<<8) + buf[j-1] ; else last_strip_byte_count = ((buf[j-1])<<8) + buf[j-2] ; break; case 4: if ((priv->flag)&0x8) last_strip_byte_count = ((buf[j-4])<<24)+((buf[j-3])<<16)+ ((buf[j-2])<<8) + buf[j-1] ; else last_strip_byte_count = ((buf[j-1])<<24)+((buf[j-2])<<16)+ ((buf[j-3])<<8) + buf[j-4] ; break; default: ret = 0; } } if (!ret) break; if (max < entry) max = entry; f_offset += 12; } if (last_strip_offset && last_strip_byte_count){ entry = last_strip_offset + last_strip_byte_count; if (max < entry) max = entry; } priv->max = max; if ((!buf[f_offset])&&(!buf[f_offset+1])&&(!buf[f_offset+2])&&(!buf[f_offset+3])){ *last_match = f_offset; f_offset += 4; if ((max > (priv->ifd+12*priv->count))&&((max - priv->ifd + *offset) > f_offset)) f_offset = max - priv->ifd + *offset; priv->flag += 2; needful = 1; } else{ if ((priv->flag)&0x8) entry = (((buf[f_offset])<<24)+((buf[f_offset+1])<<16)+((buf[f_offset+2])<<8)+ buf[f_offset+3]); else entry = (((buf[f_offset+3])<<24)+((buf[f_offset+2])<<16)+((buf[f_offset+1])<<8)+ buf[f_offset]); f_offset = entry - priv->ifd + *offset; priv->ifd = entry; priv->flag -= 1; needful = 4; } } else ret = 0; break; case 4 : if ((!buf[f_offset])&& (zero_space(buf,f_offset))) ret = 2; else ret = 3; break; default : ret = 0; } } *offset = f_offset; return ret; } // tiff int file_tiff(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ __u32 *p_32 ; __u32 offset = 0; __u32 last_match = 0; int b_count,ret = 0; struct private_tiff_t* priv = NULL; switch (flag){ case 0 : if (f_data->scantype & DATA_READY){ *size = f_data->next_offset; ret =1; } else { if (f_data->size ){ if ((f_data->inode->i_size > f_data->size) && (*size < (current_fs->blocksize -8))){ ret = 4; if (*size < (current_fs->blocksize - 256)) ret = 1; *size += 8; } } else{ if (f_data->scantype & DATA_METABLOCK){ //FIXME *size += 8; ret = 2; } } } break; case 1 : return ((scan & (M_IS_META | M_CLASS_1))||(f_data->scantype & DATA_READY)) ? 0 :1 ; break; case 2 : priv = malloc(sizeof(struct private_tiff_t)); if (!priv){ return 0; } f_data->priv = priv; priv->max = 0; priv->count = 0; priv->flag = 0; priv->last_id = 0; p_32 = (__u32*)buf; p_32++; if ((*buf == 0x49) && (*(buf+1) == 0x49)){ priv->flag = 0x01; offset = ext2fs_le32_to_cpu(*p_32); } if ((*buf == 0x4d) && (*(buf+1) == 0x4d)){ priv->flag = 0x09; offset = ext2fs_be32_to_cpu(*p_32); } if ((!offset) || (!priv->flag)){ f_data->first = 0; return 0; } f_data->last_match_blk = 1; priv->ifd = offset; b_count = (f_data->buf_length > 12) ? 12 : f_data->buf_length ; ret = follow_tiff(buf,b_count, &offset, &last_match,f_data->priv); ret = analysis_ret1("TIFF", f_data, ret , b_count, offset, last_match); break; case 3 : offset = f_data->next_offset ; ret = follow_tiff(buf, f_data->buf_length, &offset, &last_match,f_data->priv); ret = analysis_ret2("TIFF", f_data, ret, offset, last_match); break; case 4 : if (f_data->priv) free(f_data->priv); ret = 1; break; } return ret; } //mod int file_mod(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 0; switch (flag){ case 0 : if (*size < (current_fs->blocksize -4)){ *size = ((*size) +3) & 0xfffc ; ret = 1; } break; case 1 : return (scan & (M_IS_META | M_CLASS_1)) ? 0 :1 ; break; } return ret; } //---CDF------------------------------------------------------- struct OLE_HDR{ char magic[8]; // 0 char clsid[16]; // 8 __u16 uMinorVersion; // 24 __u16 uDllVersion; // 26 __u16 uByteOrder; // 28 __u16 uSectorShift; // 30 __u16 uMiniSectorShift; // 32 __u16 reserved; // 34 __u32 reserved1; // 36 __u32 reserved2; // 40 __u32 num_FAT_blocks; // 44 __u32 root_start_block; // 48 __u32 dfsignature; // 52 __u32 miniSectorCutoff; // 56 __u32 dir_flag; // 60 first sec in the mini fat chain __u32 csectMiniFat; // 64 number of sectors in the minifat __u32 FAT_next_block; // 68 __u32 num_extra_FAT_blocks; // 72 // FAT block list starts here !! first 109 entries }; struct OLE_DIR { char name[64]; // 0 __u16 namsize; // 64 char type; // 66 char bflags; // 67: 0 or 1 __u32 prev_dirent; // 68 __u32 next_dirent; // 72 __u32 sidChild; // 76 char clsid[16]; // 80 __u32 userFlags; // 96 int secs1; // 100 int days1; // 104 int secs2; // 108 int days2; // 112 __u32 start_block; // 116 starting SECT of stream __u32 size; // 120 __u16 reserved; // 124 must be 0 __u16 padding; // 126 must be 0 }; struct priv_cdf_t{ __u32 flag; __u32 shift; __u32 FAT_blocks; __u32 s_offset; __u32 extra_FAT_blocks; __u32 FAT_next_block; __u32 root_start_block; __u32 max; __u32 d0; __u32 d1; __u32 type; __u32 p[5]; }; static int read_dirname(char *buf, int len){ int ret = 0; if (len > 63) return ret; if(!(memcmp(buf, "R\0o\0o\0t\0 \0E\0n\0t\0r\0y\0",20))) return 0; if(!(memcmp(buf, "W\0o\0r\0d\0D\0o\0c\0u\0m\0e\0n\0t\0",24))) return 1; // doc if(!(memcmp(buf, "W\0o\0r\0k\0b\0o\0o\0k\0",16))) return 2; // xls if(!(memcmp(buf,"S\0f\0x\0D\0o\0c\0u\0m\0e\0n\0t\0",22))) return 3; // sdw if(!(memcmp(buf,"S\0t\0a\0r\0D\0r\0a\0w\0",16))) return 4; // sda if(!(memcmp(buf,"S\0t\0a\0r\0C\0a\0l\0c\0",16))) return 5; // sdc if(!(memcmp(buf,"W\0k\0s\0S\0S\0W\0o\0r\0k\0B\0o\0o\0k\0",26))) return 6; // xlr if(!(memcmp(buf,"I\0m\0a\0g\0e\0s\0S\0t\0o\0r\0e\0",22))) return 7; // albm if(!(memcmp(buf,"J\0N\0B\0V\0e\0r\0s\0i\0o\0n\0", 20))) return 8; // jnb if(!(memcmp(buf,"P\0o\0w\0e\0r\0P\0o\0i\0n\0t\0",20))) return 9; // ppt if(!(memcmp(buf,"C\0O\0N\0T\0E\0N\0T\0S\0",16))) return 10; //wps if(!(memcmp(buf,"_\0_\0n\0a\0m\0e\0i\0d\0_\0v\0e\0r\0s\0i\0o\0n\0001\0.\0000\0",38))) return 11; // msg if(!(memcmp(buf,"L\0i\0c\0o\0m\0",10))) return 12; //amb if(!(memcmp(buf,"V\0i\0s\0i\0o\0D\0o\0c\0u\0m\0e\0n\0t\0",26))) return 13; // vsd if(!(memcmp(buf,"s\0w\0X\0m\0l\0C\0o\0n\0t\0e\0n\0t\0s\0",26))) return 14; // sld if(!(memcmp(buf,"N\0a\0t\0i\0v\0e\0C\0o\0n\0t\0e\0n\0t\0_\0M\0A\0I\0N\0", 36))) return 15; // qpw if(!(memcmp(buf,"D\0g\0n", 6))) return 16; // dgn if(!(memcmp(buf,"P\0i\0c\0t\0u\0r\0e\0s\0",16))) return 17; // pps if(!(memcmp(buf,"p\0e\0r\0s\0i\0s\0t\0 \0e\0l\0e\0m\0e\0n\0t\0s\0",32))) return 50; // ??? sdw if(!(memcmp(buf,"1\0\0\0", 4))) return 100; // db if(!(memcmp(buf,"1\0\0\0", 4))) return 100; // db return ret; } static int follow_cdf(unsigned char *buf, __u16 blockcount, __u32 *offset, __u32 *last_match, struct priv_cdf_t* priv){ int i,j,flag; int ret = 1; __u32 f_offset = *offset; __u32 len = (1<shift); __u32 count = len / 4; __u32 end = (blockcount * current_fs->blocksize) - ((priv->flag & 0x80)? 0 : len); __u32 *p_32; struct OLE_DIR *o_dir; while ((ret == 1) && (f_offset <= ((priv->flag & 0x10)?(blockcount * current_fs->blocksize): end))){ switch (priv->flag & 0x1f){ case 0 : if (priv->root_start_block < priv->max){ priv->p[0] = priv->root_start_block; priv->flag |= 0x100; } else{ ret = 0; break; } *last_match = f_offset; if ((f_offset == 76) && (priv->FAT_blocks < 110)){ f_offset += (priv->FAT_blocks -1)*4; p_32 = (__u32*) (buf+f_offset); priv->p[3] = ext2fs_le32_to_cpu(*p_32); priv->flag |= 0x800; if (priv->FAT_blocks >1){ p_32--; if (ext2fs_le32_to_cpu(*p_32) < priv->max){ priv->p[2] = ext2fs_le32_to_cpu(*p_32); priv->flag |= 0x400; } } } else { if (f_offset == 76){ priv->p[1] = priv->FAT_next_block; priv->flag |= 0x200; }else ret = 0; } break; case 0x1 : o_dir = (struct OLE_DIR*) (buf+f_offset); for (i=0;((i< 4) && (o_dir->type));i++){ if (/*(o_dir->reserved) || o_dir->padding ||*/ (o_dir->bflags >1) || (o_dir->type > 5) || (!o_dir->namsize) || (o_dir->namsize > 63) || (o_dir->name[1] && o_dir->name[2])){ ret = 0; break; } #ifdef DEBUG_MAGIC_SCAN for (j=0;jnamsize;j++){ if(o_dir->name[j]) printf("%c",o_dir->name[j]); } printf("\t\t\t type : %u \t sector %u (%u bytes)\n", o_dir->type, o_dir->start_block, o_dir->size); #endif if ((!priv->type) || (priv->type <50)){ flag = read_dirname(o_dir->name,o_dir->namsize); if (flag) priv->type = flag; } o_dir++; } *last_match = f_offset; priv->flag &= (~0x100); break; case 0x2 : *last_match = f_offset+1; if (priv->extra_FAT_blocks >1){ p_32 = (__u32*) (buf+f_offset + len -4); if ((ext2fs_le32_to_cpu(*p_32) > priv->p[1]) && (ext2fs_le32_to_cpu(*p_32) < priv->max)){ priv->p[1] = ext2fs_le32_to_cpu(*p_32); (priv->extra_FAT_blocks)--; } else{ // printf("ERROR CDF Extra FAT: %lu \n",priv-> s_offset); ret = 0; } break; } i = (priv->FAT_blocks -109) % (count-1); p_32 = (__u32*) (buf+f_offset); p_32 += (i-1); priv->flag &= (~0x200); if ((ext2fs_le32_to_cpu(*p_32) > priv->p[1]) && (ext2fs_le32_to_cpu(*p_32) < priv->max)){ priv->p[3] = ext2fs_le32_to_cpu(*p_32); priv->flag |= 0x800; if (i > 1){ p_32--; if ((ext2fs_le32_to_cpu(*p_32) > priv->p[1]) && (ext2fs_le32_to_cpu(*p_32) < priv->max)){ priv->p[2] = ext2fs_le32_to_cpu(*p_32); priv->flag |= 0x400; } } } else { // printf("ERROR CDF Extra FAT: %lu \n",priv-> s_offset); ret = 0; } break; case 0x4 : case 0x8 : j=0; flag = 0; p_32 = (__u32*) (buf+f_offset + (len-4)); for (i=0;i < count; i++, p_32--){ if((!flag) && (*p_32 == 0xffffffff)){ j++; continue; } if ((ext2fs_le32_to_cpu(*p_32) > priv->max) && (ext2fs_le32_to_cpu(*p_32) < 0xfffffffd)){ ret = 0; break; } else flag++; } *last_match = f_offset+1; if ((priv->flag & 0x1f) == 0x4){ priv->d0 = j; priv->flag &= (~0x400); } else{ priv->d1 = j; priv->flag &= (~0x800); if (j < count) priv->flag &= (~0x400); } if(!(priv->flag & 0xc00)){ priv->p[4] = priv->max - ((priv->d1 < count) ? priv->d1 : (priv->d1 + priv->d0)); priv->flag |= 0x1000; } break; case 0x10 : if (zero_space(buf, f_offset)){ ret = 2; } else{ if (!(f_offset % current_fs->blocksize)){ ret = 2; } else{ // printf("ERROR CDF EOF: %lu \n",priv-> s_offset); ret = 0; } } break; } if (ret == 1){ priv->flag &= 0x1f00; flag = 0; for (i=0;i<5;i++){ if( priv->flag & (1<<(i+8))){ flag = i+1; for(j=i+1;j<5;j++){ if(( priv->flag & (1<<(j+8))) && (priv->p[i] > priv->p[j])){ flag = j+1; break; } } if(j==5) break; } } if (flag){ flag--; f_offset = ((priv->p[flag] << priv->shift) + 512) - (priv->s_offset - *offset) ; priv->flag |= (1<<(flag)); } else { ret = 0; } } } priv->s_offset = (priv->s_offset - *offset) + f_offset; *offset = f_offset; return ret; } //CDF int file_CDF(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ char cdf_ext[19][4]={{'d','o','c','\0'}, {'d','o','c','\0'},{'x','l','s','\0'},{'s','d','w','\0'},{'s','d','a','\0'},{'s','d','c','\0'},{'x','l','r','\0'}, {'a','l','b','\0'},{'j','n','b','\0'},{'p','p','t','\0'},{'w','p','s','\0'},{'m','s','g','\0'},{'a','m','b','\0'}, {'v','s','d','\0'},{'s','l','d','\0'},{'q','p','w','\0'},{'d','g','n','\0'},{'p','p','s','\0'},{'d','b','\0','\0'}}; int b_count, ret = 0; struct OLE_HDR *head; struct priv_cdf_t *priv = NULL; __u32 FAT_blocks,extra_FAT_blocks; __u32 last_match = 0; __u16 shift; __u32 offset; //,last_match_blk = 0; switch (flag){ case 0 : if (f_data->scantype & DATA_READY){ if (f_data->priv){ priv = f_data->priv; if (priv->type == 50) priv->type = 3; if (priv->type == 100) priv->type = 18; if (priv->type > 18) priv->type = 0; f_data->name[strlen(f_data->name)-3] = 0 ; strncat(f_data->name,cdf_ext[priv->type],4); } *size = (f_data->next_offset)?f_data->next_offset : current_fs->blocksize; ret =1; } else { if ((f_data->scantype & DATA_METABLOCK) || (*size < (current_fs->blocksize - 64))){ *size = (((*size) +127) & ~127); ret = 1; } } break; case 1 : return (scan & (M_IS_META | M_CLASS_1)) ? 0 :1 ; break; case 2 : head =(struct OLE_HDR*)buf; FAT_blocks = ext2fs_le32_to_cpu(head->num_FAT_blocks); extra_FAT_blocks = ext2fs_le32_to_cpu(head->num_extra_FAT_blocks); shift = ext2fs_le16_to_cpu(head->uSectorShift); priv = malloc(sizeof(struct priv_cdf_t)); if ((!((buf[0]==0xd0)&&(buf[1]==0xcf)&&(buf[2]==0x11)&&(buf[3]==0xe0)&&(buf[4]==0xa1) &&(buf[5]==0xb1)&&(buf[6]==0x1a)&&(buf[7]==0xe1) && (buf[28]==0xfe))) || (!FAT_blocks) || (extra_FAT_blocks > 50) || (FAT_blocks > ((extra_FAT_blocks * (((1< 11) || (! priv)) { f_data->first = 0; if( priv) free(priv); break; } offset = 76; memset(priv,0,sizeof(struct priv_cdf_t)); priv->s_offset = offset; priv->FAT_blocks = FAT_blocks; priv->extra_FAT_blocks = extra_FAT_blocks; priv->shift = shift; priv->root_start_block = ext2fs_le32_to_cpu(head->root_start_block); priv->FAT_next_block = ext2fs_le32_to_cpu(head->FAT_next_block); f_data->priv = priv; f_data->last_match_blk = 1; priv->max = FAT_blocks * ((1<buf_length > 12) ? 12 : f_data->buf_length ; ret = follow_cdf(buf,b_count, &offset, &last_match,f_data->priv); ret = analysis_ret1("CDF", f_data, ret , b_count, offset, last_match); f_data->scantype |= DATA_NO_FOOT; break; case 3 : offset = f_data->next_offset ; ret = follow_cdf(buf, f_data->buf_length, &offset, &last_match,f_data->priv); ret = analysis_ret2("CDF", f_data, ret, offset, last_match); break; case 4 : if (f_data->priv) free(f_data->priv); ret = 1; break; } return ret; } //----END CDF-------------------------------------------------------------------- //vmware FIXME ???????????????? int file_vmware(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 0; switch (flag){ case 0 : if (f_data->scantype & DATA_METABLOCK){ //FIXME *size = current_fs->blocksize; ret = 1; } break; case 1: return (f_data->scantype & DATA_METABLOCK) ? 0 : 1 ; break; } return ret; } //ext2fs int file_ext2fs(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 0; __u32 tmp,i; __u64 lsize,ssize; int blksize = 1024; int blkcount; switch (flag){ case 0: if (f_data->size || f_data->h_size) { if (f_data->scantype & DATA_METABLOCK){ f_data->inode->i_size_high = f_data->h_size; f_data->inode->i_size = f_data->size; *size = current_fs->blocksize; ret = 1; } else { lsize = (__u64)f_data->h_size << 32; lsize += f_data->size; ssize = (__u64)f_data->inode->i_size_high << 32; ssize += f_data->inode->i_size; if (lsize > ssize) ret = 0; else{ f_data->inode->i_size = f_data->size; *size = current_fs->blocksize; ret = 1; } } } break; case 1: return (f_data->scantype & DATA_METABLOCK) ? 0 : 1 ; break; case 2: tmp = (buf[1051]<<24)+(buf[1050]<<16)+(buf[1049]<<8)+buf[1048]; if (((f_data->buf_length * current_fs->blocksize) < 2048) || (buf[1080] != 0x53) || (buf[1081] != 0xEF) || (tmp > 2)){ f_data->func = NULL; } else{ for ( i=0 ;i < tmp; i++) blksize *= 2; blkcount = (buf[1031]<<24)+(buf[1030]<<16)+(buf[1029]<<8)+buf[1028]; lsize =(__u64) blkcount * blksize; f_data->size = lsize & 0xFFFFFFFF; f_data->h_size = lsize >> 32; f_data->scantype = DATA_LENGTH; ret =1; } break; } return ret; } //LUKS FIXME ??????????????? int file_luks(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ #define LUKSMAGIC 6 #define LUKSCIPHERNAME 32 #define LUKSCIPHERMODEL 32 #define LUKSDIGESTSIZE 20 #define LUKSSALTSIZE 32 #define LUKSHASHSPEC 32 #define UUIDSTRING 40 #define LUKSNUMKEYS 8 struct luks_phdr { char magic [LUKSMAGIC] ; __u16 version ; char cipherName[LUKSCIPHERNAME] ; char cipherMode [LUKSCIPHERMODEL] ; char hashSpec [LUKSHASHSPEC] ; __u32 payloadOffset ; __u32 keyBytes ; char mkDigest [LUKSDIGESTSIZE] ; char mkDigestSalt [LUKSSALTSIZE] ; __u32 mkDigestIterations ; char uuid [UUIDSTRING] ; struct { __u32 active ; __u32 passwordIterations ; char passwordSalt [LUKSSALTSIZE] ; __u32 keyMaterialOffset ; __u32 stripes ; } keyblock [LUKSNUMKEYS] ; }; unsigned char luksmagic[] = {'L','U','K','S',0xBA,0xBE}; struct luks_phdr *phdr = (struct luks_phdr*)buf; int ret = 0; switch (flag){ case 0 : if(f_data->scantype & DATA_METABLOCK){ ret = 1; } else{ if ((f_data->inode->i_size_high) || (f_data->inode->i_size > f_data->size)) ret = 8; // ext4 recover nothing // There is no size and no footer for find the end of file } *size = current_fs->blocksize; break; case 1 :return (scan & (M_IS_META | M_CLASS_1 )) ? 0 :1 ; break; case 2 : if (!(strncmp((char*)buf,(char*)luksmagic,6))){ f_data->size = ext2fs_be32_to_cpu(phdr->payloadOffset) * 512; f_data->scantype = DATA_MIN_LENGTH ; ret = 1; } else{ f_data->func = NULL; } } return ret; } static int follow_matlab(unsigned char *buf, __u16 blockcount, __u32 *offset, __u32 *last_match, int flag){ int ret = 1 ; __u32 m_type ; __u32 *m_pt; __u32 *m_ps; __u32 m_size ; __u32 f_offset = *offset; while ((ret ==1) && (f_offset < ((blockcount * current_fs->blocksize)-8))){ m_pt=(__u32*) (buf+f_offset); if ((!(*m_pt))&& (zero_space(buf,f_offset))){ ret = 2; continue; } m_ps=m_pt+1; if (flag & DATA_BIG_END){ // BIG Endian m_type = ext2fs_be32_to_cpu(*m_pt); m_size = ext2fs_be32_to_cpu(*m_ps); } else { //Little Endian m_type = ext2fs_le32_to_cpu(*m_pt); m_size = ext2fs_le32_to_cpu(*m_ps); } if (m_type && (m_type < 19)){ *last_match = f_offset; f_offset+=((m_type == 14)||(m_type == 15)) ? m_size : ((m_size +7) & ~7); f_offset+=8; } else{ // Check "Compressed Data Element Format" __u16 ms_type ; __u16 *ms_pt; __u16 *ms_ps; __u16 ms_size ; if ((m_type > 15) && (m_type < 19)){ ms_ps=(__u16*) (buf+f_offset); ms_pt=ms_ps+1; if (flag & DATA_BIG_END){ // BIG Endian ms_type = ext2fs_be16_to_cpu(*ms_pt); ms_size = ext2fs_be16_to_cpu(*ms_ps); } else { //Little Endian ms_type = ext2fs_le16_to_cpu(*ms_pt); ms_size = ext2fs_le16_to_cpu(*ms_ps); } if (ms_size && ms_type && (ms_size < 5)&&( ms_type <12)){ f_offset+=8; *last_match = f_offset; } else{ ret = 0; } } else ret = 0; } } *offset = f_offset; return ret; } //matlab (only Level 5) int file_matlab(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int b_count; int ret = 0; __u32 offset; __u32 last_match = 0; char header[16]={0x4d,0x41,0x54,0x4c,0x41,0x42,0x20,0x35,0x2e,0x30,0x20,0x4d,0x41,0x54,0x2d,0x66}; switch (flag){ case 0 : if ((f_data->size) && (f_data->size <= f_data->inode->i_size)){ if(f_data->scantype & DATA_READY){ *size = (f_data->next_offset)?f_data->next_offset : *size; ret = 1; break; }//FIXME if((!(f_data->inode->i_flags & EXT4_EXTENTS_FL))&&(f_data->size < (12 * current_fs->blocksize))){ f_data->inode->i_size = (f_data->size + current_fs->blocksize -1) & ~(current_fs->blocksize-1); *size = f_data->size % current_fs->blocksize; ret = 1; } } else { ret =0; } break; case 1 : return ((scan & (M_IS_META | M_CLASS_1 | M_BLANK))||(f_data->scantype & DATA_READY)) ? 0 :1 ; break; case 2 : if (strncmp((char*)buf,header,16)){ f_data->first = 0; break; } if ((buf[126] == 0x4d) && (buf[127] == 0x49) && ( buf[124] == 0x01) && (! buf[125])){ f_data->scantype |= DATA_BIG_END ; } else if (!((buf[126] == 0x49) && (buf[127] == 0x4d)&&( buf[125] == 0x01)&&(! buf[124]))){ f_data->first = 0; break; } offset = 128; b_count = (f_data->buf_length > 12) ? 12 : f_data->buf_length ; ret = follow_matlab(buf, b_count, &offset, &last_match,f_data->scantype); ret = analysis_ret1("MAT", f_data, ret , b_count, offset, last_match); break; case 3 : offset = f_data->next_offset ; ret = follow_matlab(buf, f_data->buf_length, &offset, &last_match,f_data->scantype); ret = analysis_ret2("MAT", f_data, ret, offset, last_match); break; } return ret; } //dbf int file_dbf(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 0; __u32 ssize; __u32 b_size; __u16 head,count; __u32 *p32; __u16 *p16; switch (flag){ case 0 : if ((f_data->size ) && (f_data->inode->i_size >= f_data->size)){ ssize = ((f_data->size-1) % current_fs->blocksize)+1; if (f_data->inode->i_size > (f_data->size - ssize)){ *size = ssize; ret =1; } } else{ if (*size < (current_fs->blocksize -128)){ *size += 4; ret = 4; } } break; case 1: return (scan & (M_IS_META | M_CLASS_1 | M_TXT)) ? 0 :1 ; break; case 2: p32 = (__u32*) (buf +4); p16 = (__u16*) (buf +8); b_size = ext2fs_le32_to_cpu(*p32); head = ext2fs_le16_to_cpu(*p16); p16++; count = ext2fs_le16_to_cpu(*p16); //FIXME for DB7 http://www.dbase.com/KnowledgeBase/int/db7_file_fmt.htm if( (buf[1]<100)|| (buf[1]>130)|| (!buf[2]) || (!buf[3]) || (buf[2]>12) || (buf[3] >31) || (!b_size) || (head < 65) || (head & 0x1e) || (!count) || (b_size > 0x8000) || buf[12] || buf[13] || buf[30] || buf[31]){ f_data->first = 0; break; } else{ f_data->size = (count * b_size) + head + 1; f_data->scantype = DATA_LENGTH; ret = 1; } break; } return ret; } //ESRI int file_esri(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 0; __u32 ssize; __u32 head; int i; __u32 *p32; switch (flag){ case 0 : if ((f_data->size ) && (f_data->inode->i_size >= f_data->size)){ ssize = ((f_data->size-1) % current_fs->blocksize)+1; if (f_data->inode->i_size > (f_data->size - ssize)){ *size = ssize; ret =1; } } else{ if (*size < (current_fs->blocksize -128)){ *size += 4; ret = 4; } } break; case 1: return (scan & (M_IS_META | M_CLASS_1 | M_TXT)) ? 0 :1 ; break; case 2: p32 = (__u32*) buf; head = ext2fs_be32_to_cpu(*p32); for (i=4;i<24;i++) if (buf[i]) break; if( (i<24) || (head != 9994)){ f_data->first = 0; break; } else{ p32 = (__u32*) (buf +24); f_data->size = 2 * ext2fs_be32_to_cpu(*p32); f_data->scantype = DATA_LENGTH; ret = 1; } break; } return ret; } //SQLite int file_SQLite(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 0; __u16 *p_16; __u16 b_size; __u32 count; __u64 ssize; switch (flag){ case 0 : if ((f_data->size ) || (f_data->h_size)) { if (f_data->h_size != f_data->inode->i_size_high) ret = 0; else{ if (f_data->inode->i_size < f_data->size) ret = 0; else{ count = ((f_data->size-1) % current_fs->blocksize)+1; *size = (count)? count : current_fs->blocksize; ret = 1; } } } break; case 1: return (scan & (M_IS_META | M_CLASS_1)) ? 0 :1 ; break; case 2: p_16 = (__u16*)(buf+16); b_size = (__u32)ext2fs_be16_to_cpu(*p_16); if (b_size ==1) b_size = 1; else { if((b_size <512)||(b_size > 32768) || (b_size &1)) b_size = 0; } count=(buf[28]<<24)+(buf[29]<<16)+(buf[30]<<8)+(buf[31]); if ((count) && (b_size) && (buf[23] == 32)){ ssize = ((__u64)count) * ((b_size == 1)?65536:b_size); f_data->size = ssize & 0xffffffff; f_data->h_size = ssize >>32; f_data->scantype = DATA_LENGTH ; ret = 1; } else f_data->first = 0; break; } return ret; } //smp (Sample Vision Format) int file_smp(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ static const unsigned char smp_header[18]= "SOUND SAMPLE DATA "; int ret = 0; __u32 ssize; switch (flag){ case 0 : if (f_data->size ) { ssize = ((f_data->size-1) % current_fs->blocksize)+1; if (f_data->inode->i_size > (f_data->size - ssize)){ *size = ssize; ret =1; } } else{ if (*size < (current_fs->blocksize -4)){ *size += 4; ret = 4; } } break; case 1: return (scan & (M_IS_META | M_CLASS_1 | M_TXT)) ? 0 :1 ; break; case 2: if(memcmp(buf,smp_header,18)==0){ ssize = buf[112]+(buf[113]<<8)+(buf[114]<<16)+(buf[115]<<24); ssize *= 2; ssize += 331; // 116+2+(8*11)+(8*14)+1+12 f_data->size = ssize; f_data->scantype = DATA_LENGTH; ret =1; } else f_data->first = 0; break; } return ret; } //avr (Audio Visual Research) int file_avr(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ static const unsigned char avr_header[4]= {'2','B','I','T'}; int ret = 0; __u32 ssize; __u64 wsize; __u16 rez = (buf[14]<<8) + buf[15]; switch (flag){ case 0 : if (f_data->size || f_data->h_size) { if (f_data->h_size != f_data->inode->i_size_high) ret = 0; else{ if (f_data->inode->i_size < f_data->size) ret = 0; else{ ssize = ((f_data->size-1) % current_fs->blocksize)+1; if (*size < ssize) *size = ssize; ret = 1; } } } break; case 1: return (scan & (M_IS_META | M_CLASS_1 | M_TXT)) ? 0 :1 ; break; case 2: if((memcmp(buf,avr_header,4)==0) && ((rez == 8)||(rez ==16))){ wsize = (((__u64)buf[30])<<56)+(((__u64)buf[31])<<48)+(((__u64)buf[32])<<40)+ (((__u64)buf[33])<<32)+(((__u64)buf[34])<<24)+(((__u64)buf[35])<<16)+ (((__u64)buf[36])<<8)+buf[37]; wsize = wsize * (rez/8); f_data->size = wsize & 0xFFFFFFFF; f_data->h_size = wsize >> 32; f_data->scantype = DATA_LENGTH; ret =1; } else f_data->first = 0; break; } return ret; } //au (NeXT) int file_au(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ //static const unsigned char au_header[4]= {'.','s','n','d'}; struct au_header_t { __u32 magic; __u32 offset; __u32 size; __u32 encoding; __u32 sample_rate; __u32 channels; }; int ret = 0; __u32 ssize; struct au_header_t *p_header; switch (flag){ case 0 : if (f_data->size ) { ssize = ((f_data->size-1) % current_fs->blocksize)+1; if (f_data->inode->i_size > (f_data->size - ssize)){ *size = ssize; ret =1; } } else{ if (*size < (current_fs->blocksize -4)){ *size += 4; ret = 4; } } break; case 1: return (scan & (M_IS_META | M_CLASS_1 | M_TXT)) ? 0 :1 ; break; case 2: p_header = (struct au_header_t*) buf; if(memcmp(buf,p_header,sizeof(struct au_header_t)) == 0 && ext2fs_be32_to_cpu(p_header->encoding)<=27 && ext2fs_be32_to_cpu(p_header->channels)<=256){ if(ext2fs_be32_to_cpu(p_header->size)!=0xffffffff){ f_data->size = ext2fs_be32_to_cpu(p_header->offset) + ext2fs_be32_to_cpu(p_header->size); f_data->scantype = DATA_LENGTH; } ret = 1; } else f_data->first = 0; break; } return ret; } //ra int file_ra(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ static const unsigned char ra_header[4]= { '.', 'r', 'a', 0xfd}; static const unsigned char rm_header[9] = { '.', 'R', 'M', 'F', 0x00, 0x00, 0x00, 0x12, 0x00}; int ret = 0; __u32 ssize; switch (flag){ case 0 : if (f_data->size ) { ssize = ((f_data->size-1) % current_fs->blocksize)+1; if (f_data->inode->i_size > (f_data->size - ssize)){ *size = ssize; ret =1; } } else{ if (*size < (current_fs->blocksize -4)){ *size += 4; ret = 4; } } break; case 1: return (scan & (M_IS_META | M_CLASS_1 | M_TXT)) ? 0 :1 ; break; case 2: if(! memcmp(buf,ra_header,4)) { if(buf[4]==0x00 && buf[5]==0x03) return 1; //V3 if(buf[4]==0x00 && buf[5]==0x04 && buf[9]=='r' && buf[10]=='a' && buf[11]=='4'){ //V4 f_data->size = (buf[12]<<24) + (buf[13]<<16) + (buf[14]<<8) + buf[15] + 40; f_data->scantype = DATA_LENGTH; return 1; } } else{ if(! memcmp(buf,rm_header,9)) return 1 ; } break; } return ret; } static int follow_qt(unsigned char *buf, __u16 blockcount, __u32 *offset, __u32 *last_match, struct found_data_t* f_data){ static unsigned char atom[][4]={ {'c','m','o','v'}, {'c','m','v','d'}, {'d','c','o','m'}, {'f','r','e','e'}, {'f','t','y','p'}, {'j','p','2','h'}, {'j','p','2','c'}, {'m','d','a','t'}, {'m','d','i','a'}, {'m','o','o','v'}, {'P','I','C','T'}, {'p','n','o','t'}, {'s','k','i','p'}, {'s','t','b','l'}, {'r','m','r','a'}, {'m','e','t','a'}, {'i','d','s','c'}, {'i','d','a','t'}, {'t','r','a','k'}, {'u','u','i','d'}, {'w','i','d','e'}, //MP4 atom {'I','D','3','2'}, {'a','l','b','m'}, {'a','u','t','h'}, {'b','p','c','c'}, {'b','u','f','f'}, {'b','x','m','l'}, {'c','c','i','d'}, {'c','d','e','f'}, {'c','l','s','f'}, {'c','m','a','p'}, {'c','o','6','4'}, {'c','o','l','r'}, {'c','p','r','t'}, {'c','r','h','d'}, {'c','s','l','g'}, {'c','t','t','s'}, {'c','v','r','u'}, {'d','c','f','D'}, {'d','i','n','f'}, {'d','r','e','f'}, {'d','s','c','p'}, {'d','s','g','d'}, {'d','s','t','g'}, {'e','d','t','s'}, {'e','l','s','t'}, {'f','e','c','i'}, {'f','e','c','r'}, {'f','i','i','n'}, {'f','i','r','e'}, {'f','p','a','r'}, {'f','r','m','a'}, {'g','i','t','n'}, {'g','n','r','e'}, {'g','r','p','i'}, {'h','d','l','r'}, {'h','m','h','d'}, {'h','p','i','x'}, {'i','c','n','u'}, {'i','h','d','r'}, {'i','i','n','f'}, {'i','l','o','c'}, {'i','m','i','f'}, {'i','n','f','u'}, {'i','o','d','s'}, {'i','p','h','d'}, {'i','p','m','c'}, {'i','p','r','o'}, {'i','r','e','f'}, {'j','P',' ',' '}, {'j','p','2','i'}, {'k','y','w','d'}, {'l','o','c','i'}, {'l','r','c','u'}, {'m','7','h','d'}, {'m','d','h','d'}, {'m','d','r','i'}, {'m','e','c','o'}, {'m','e','h','d'}, {'m','e','r','e'}, {'m','f','h','d'}, {'m','f','r','a'}, {'m','f','r','o'}, {'m','i','n','f'}, {'m','j','h','d'}, {'m','o','o','f'}, {'m','v','c','g'}, {'m','v','c','i'}, {'m','v','e','x'}, {'m','v','h','d'}, {'m','v','r','a'}, {'n','m','h','d'}, {'o','c','h','d'}, {'o','d','a','f'}, {'o','d','d','a'}, {'o','d','h','d'}, {'o','d','h','e'}, {'o','d','r','b'}, {'o','d','r','m'}, {'o','d','t','t'}, {'o','h','d','r'}, {'p','a','d','b'}, {'p','a','e','n'}, {'p','c','l','r'}, {'p','d','i','n'}, {'p','e','r','f'}, {'p','i','t','m'}, {'r','e','s',' '}, {'r','e','s','c'}, {'r','e','s','d'}, {'r','t','n','g'}, {'s','b','g','p'}, {'s','c','h','i'}, {'s','c','h','m'}, {'s','d','e','p'}, {'s','d','h','d'}, {'s','d','t','p'}, {'s','d','v','p'}, {'s','e','g','r'}, {'s','g','p','d'}, {'s','i','d','x'}, {'s','i','n','f'}, {'s','m','h','d'}, {'s','r','m','b'}, {'s','r','m','c'}, {'s','r','p','p'}, {'s','t','c','o'}, {'s','t','d','p'}, {'s','t','s','c'}, {'s','t','s','d'}, {'s','t','s','h'}, {'s','t','s','s'}, {'s','t','s','z'}, {'s','t','t','s'}, {'s','t','y','p'}, {'s','t','z','2'}, {'s','u','b','s'}, {'s','w','t','c'}, {'t','f','a','d'}, {'t','f','h','d'}, {'t','f','m','a'}, {'t','f','r','a'}, {'t','i','b','r'}, {'t','i','r','i'}, {'t','i','t','l'}, {'t','k','h','d'}, {'t','r','a','f'}, {'t','r','e','f'}, {'t','r','e','x'}, {'t','r','g','r'}, {'t','r','u','n'}, {'t','s','e','l'}, {'u','d','t','a'}, {'u','i','n','f'}, {'U','I','T','S'}, {'u','l','s','t'}, {'u','r','l',' '}, {'v','m','h','d'}, {'v','w','d','i'}, {'x','m','l',' '}, {'y','r','r','c'}}; int atom_db_len = sizeof(atom) / 4; int i,ret = 1 ; __u32 qt_offset = *offset; __u32 atom_size; while ((ret ==1) && (qt_offset < ((blockcount * current_fs->blocksize)-8))){ atom_size=(buf[qt_offset+0]<<24)+(buf[qt_offset+1]<<16)+(buf[qt_offset+2]<<8)+buf[qt_offset+3]; for (i=0;ifunc = file_jp2; #ifdef DEBUG_QUICK_TIME fprintf(stderr,"QuickTime : found JP-2000, block %lu ; offset size :%llu\n",f_data->first, ((__u64)f_data->h_size<<32) + f_data->size + qt_offset + 8); #endif *offset = qt_offset +8; return 1; } if (atom_size == 1){ f_data->size = (buf[qt_offset+12]<<24)+(buf[qt_offset+13]<<16)+(buf[qt_offset+14]<<8)+buf[qt_offset+15] + qt_offset; f_data->h_size = (buf[qt_offset+8]<<24)+(buf[qt_offset+9]<<16)+(buf[qt_offset+10]<<8)+buf[qt_offset+11]; #ifdef DEBUG_QUICK_TIME fprintf(stderr,"QuickTime : found a large atom, block %lu ; offset size :%llu\n",f_data->first, ((__u64)f_data->h_size<<32) + f_data->size + qt_offset); #endif f_data->scantype = DATA_MIN_LENGTH ; return 1; } *last_match = qt_offset; qt_offset += atom_size; #ifdef DEBUG_QUICK_TIME fprintf(stderr,"QuickTime : atom \"%c%c%c%c\" ; size %lu\n", atom[i][0],atom[i][1],atom[i][2],atom[i][3],qt_offset); #endif break; } if (i == atom_db_len){ if (((!atom_size) && (!buf[qt_offset+4])) || (zero_space(buf, qt_offset))) ret = 2; else{ #ifdef DEBUG_QUICK_TIME fprintf(stderr,"QuickTime : atom \"%c%c%c%c\" unknown ; block %lu ; offset %lu , size %lu\n", buf[qt_offset+4],buf[qt_offset+5],buf[qt_offset+6],buf[qt_offset+7], f_data->first, qt_offset, atom_size); #endif ret = 0; } } } #ifdef DEBUG_QUICK_TIME fprintf(stderr,"QuickTime : found ; block %lu ; offset %lu\n", f_data->first, qt_offset); #endif *offset = qt_offset; return ret; } //-------------------------------- //QuickTime int file_qt(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int i, j, ret = 0; __u32 atom_size; __u32 offset; __u32 last_match = 0; __u16 b_count; static unsigned char basic[18][4]={ {'f','t','y','p'}, {'m','d','a','t'}, {'m','o','o','v'}, {'c','m','o','v'}, {'c','m','v','d'}, {'p','n','o','t'}, {'d','c','o','m'}, {'w','i','d','e'}, {'f','r','e','e'}, {'s','k','i','p'}, {'j','p','2','h'}, {'i','d','s','c'}, {'i','d','a','t'}, {'m','d','i','a'}, {'p','c','k','g'}, {'s','t','b','l'}, {'t','r','a','k'}, {'j','P',' ',' '}}; static unsigned char ftype[12][3]={ {'i','s','o'}, {'m','p','4'}, {'m','m','p'}, {'M','4','A'}, {'M','4','B'}, {'M','4','C'}, {'3','g','p'}, {'3','g','2'}, {'j','p','2'}, {'m','j','p'}, {'q','t',' '}, {'a','v','s'}}; switch (flag){ case 0 : if (f_data->size || f_data->h_size) { if ((f_data->h_size == 0xffff )&& (!f_data->size)){ if (*size < (current_fs->blocksize - 4)){ ret = 4; break; } } if (f_data->h_size != f_data->inode->i_size_high) ret = 0; else{ if (f_data->inode->i_size < f_data->size) ret = 0; else{ ret = 1; } } } else { ret =0; } break; case 1 : return ((scan & (M_IS_META | M_CLASS_1 | M_BLANK | M_TXT))||(f_data->scantype & DATA_READY)) ? 0 :1 ; break; case 2 : offset = 0; atom_size=(buf[offset+0]<<24)+(buf[offset+1]<<16)+(buf[offset+2]<<8)+buf[offset+3]; for (i=0;i<18;i++){ if(memcmp((void*)(buf + offset +4), basic[i], 4)) continue; f_data->last_match_blk = 1; if((!atom_size) && (i == 1)){ //FIXME f_data->h_size = 0xffff; #ifdef DEBUG_QUICK_TIME fprintf(stderr,"QuickTime : found a \"mdat\" atom at begin , block %lu\n",f_data->first); #endif return 1; } if(atom_size == 1){ f_data->size = (buf[offset+12]<<24)+(buf[offset+13]<<16)+(buf[offset+14]<<8)+buf[offset+15]; f_data->h_size = (buf[offset+8]<<24)+(buf[offset+9]<<16)+(buf[offset+10]<<8)+buf[offset+11]; #ifdef DEBUG_QUICK_TIME fprintf(stderr,"QuickTime : found a large atom, block %lu ; offset size :%llu\n",f_data->first, ((__u64)f_data->h_size<<32) + f_data->size + offset); #endif f_data->scantype = DATA_MIN_LENGTH ; return 1; } if(!i){ for (j=0;j<12;j++){ if(memcmp((void*)(buf + offset +8), ftype[j], 3)) continue; #ifdef DEBUG_QUICK_TIME fprintf(stderr,"QuickTime : Type \"%c%c%c\"\n",ftype[j][0],ftype[j][1],ftype[j][2]); #endif break; //FIXME } if (j == 12){ #ifdef DEBUG_QUICK_TIME fprintf(stderr,"QuickTime : Type : \"%c%c%c%c\" is unknown\n",buf[offset +4],buf[offset +5],buf[offset+6],buf[offset+7]); #endif f_data->func = file_none; return 0; } } offset += atom_size; break; } for (j=0;(j<12)&&(isprint(buf[j]));j++){}; if ((i == 18)||(j==12)||((i==7)&&(atom_size != 8)) || ((i==7)&&(atom_size != 8)) || ((!i)&&(atom_size % 4))) { #ifdef DEBUG_QUICK_TIME fprintf(stderr,"QuickTime : first Container atom unknown ; block %lu ; size %lu\n",f_data->first, atom_size); #endif f_data->func = NULL; return 0; } b_count = (f_data->buf_length > 12) ? 12 : f_data->buf_length ; ret = follow_qt(buf, b_count, &offset, &last_match,f_data); ret = analysis_ret1("QT", f_data, ret , b_count, offset, last_match); break; case 3 : offset = f_data->next_offset ; ret = follow_qt(buf, f_data->buf_length, &offset, &last_match,f_data); ret = analysis_ret2("QT", f_data, ret, offset, last_match); break; } return ret; } //fli int file_fli(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 0; __u32 ssize; switch (flag){ case 0 : if (f_data->size ) { ssize = ((f_data->size-1) % current_fs->blocksize)+1; if (f_data->inode->i_size > (f_data->size - ssize)){ *size = ssize; ret =1; } } break; case 1: return (scan & (M_IS_META | M_CLASS_1 | M_TXT)) ? 0 :1 ; break; case 2: if ((!(buf[4] & 0xec)) &&(buf[5]== 0xaf)){ f_data->size = (buf[3]<<24) + (buf[2]<<16) + (buf[1]<<8) + buf[0] ; f_data->scantype = DATA_LENGTH ; ret = 1; } else f_data->func = file_none; break; } return ret; } //file_ecryptfs int file_ecryptfs(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 0; __u32 blz,count; __u64 lsize,ssize; switch (flag){ case 0: if (f_data->size || f_data->h_size) { if (f_data->scantype & DATA_METABLOCK){ f_data->inode->i_size_high = f_data->h_size; f_data->inode->i_size = f_data->size; *size = current_fs->blocksize; ret = 1; } else { lsize = (__u64)f_data->h_size << 32; lsize += f_data->size; ssize = (__u64)f_data->inode->i_size_high << 32; ssize += f_data->inode->i_size; if (lsize > ssize) ret = 0; else{ f_data->inode->i_size = f_data->size; *size = current_fs->blocksize; ret = 1; } } } break; case 1: return (scan & (M_IS_META | M_CLASS_1 | M_BLANK | M_TXT)) ? 0 : 1 ; break; case 2: lsize = ((__u64)buf[0]<<56)+((__u64)buf[1]<<48)+((__u64)buf[2]<<40)+((__u64)buf[3]<<32)+ (buf[4]<<24)+(buf[5]<<16)+(buf[6]<<8)+buf[7]; blz = (buf[20]<<24)+(buf[21]<<16)+(buf[22]<<8)+buf[23]; count = (buf[24]<<8)+buf[25]; if (!(blz & 0x3ff)){ // if (!lsize) lsize++; lsize += (blz *count); f_data->size = lsize & 0xFFFFFFFF; f_data->size = (f_data->size + (blz-1)) & (~(blz-1)); f_data->h_size = lsize >> 32; f_data->scantype = DATA_LENGTH; ret =1; } break; } return ret; } static int follow_ac3(unsigned char *buf, __u16 blockcount, __u32 *offset, __u32 *last_match, int flag){ static const __u16 tab[38][3] = { { 64 , 69 , 96 }, { 64 , 70 , 96 }, { 80 , 87 , 120 }, { 80 , 88 , 120 }, { 96 , 104 , 144 }, { 96 , 105 , 144 }, { 112 , 121 , 168 }, { 112 , 122 , 168 }, { 128 , 139 , 192 }, { 128 , 140 , 192 }, { 160 , 174 , 240 }, { 160 , 175 , 240 }, { 192 , 208 , 288 }, { 192 , 209 , 288 }, { 224 , 243 , 336 }, { 224 , 244 , 336 }, { 256 , 278 , 384 }, { 256 , 279 , 384 }, { 320 , 348 , 480 }, { 320 , 349 , 480 }, { 384 , 417 , 576 }, { 384 , 418 , 576 }, { 448 , 487 , 672 }, { 448 , 488 , 672 }, { 512 , 557 , 768 }, { 512 , 558 , 768 }, { 640 , 696 , 960 }, { 640 , 697 , 960 }, { 768 , 835 , 1152 }, { 768 , 836 , 1152 }, { 896 , 975 , 1344 }, { 896 , 976 , 1344 }, { 1024 , 1114 , 1536 },{ 1024 , 1115 , 1536 },{ 1152 , 1253 , 1728 },{ 1152 , 1254 , 1728 }, { 1280 , 1393 , 1920 },{ 1280 , 1394 , 1920 }}; int ret = 1; unsigned char *ac3_h; __u16 fscod, frmsizecod ; __u32 frame_offset = *offset ; __u32 frame_size ; while ((ret == 1) && (frame_offset < (blockcount * current_fs->blocksize)-5)){ ac3_h = (buf + frame_offset); if (((!ac3_h[0]) && (!ac3_h[1]) && (!ac3_h[2]) && (!ac3_h[3]) && (!ac3_h[4]) && ac3_h[-1]) && (zero_space(buf, frame_offset))){ ret = 2; continue; } if ((ac3_h[0] == 0x0b) && (ac3_h[1] == 0x77)){ fscod = (ac3_h[4] & 0xc0 ) >> 6 ; frmsizecod = ac3_h[4] & 0x3f ; if (((fscod > 2) || (frmsizecod > 0x25)) || ((flag) && (flag != ac3_h[4]))) { ret = 0; break; } frame_size = tab[frmsizecod][fscod] * 2; *last_match = frame_offset; frame_offset += frame_size; } else { if (frame_offset % (current_fs->blocksize)) ret = 0; else ret = 2; } } *offset = frame_offset; return ret; } //ac3 int file_ac3(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 0; __u32 b_count; __u32 offset = 0; __u32 last_match = 0; switch (flag){ case 0 : if ((f_data->size) && (f_data->size <= f_data->inode->i_size)){ if(f_data->scantype & DATA_READY){ *size = (f_data->next_offset)?f_data->next_offset : *size; ret = 1; break; } //FIXME if((!(f_data->inode->i_flags & EXT4_EXTENTS_FL))&&(f_data->size < (12 * current_fs->blocksize))){ f_data->inode->i_size = (f_data->size + current_fs->blocksize -1) & ~(current_fs->blocksize-1); *size = f_data->size % current_fs->blocksize; ret = 1; } } else { ret =0; } break; case 1 : return ((scan & (M_IS_META | M_CLASS_1 | M_BLANK | M_TXT))||(f_data->scantype & DATA_READY)) ? 0 :1 ; break; case 2 : offset = test_id3_tag(buf); b_count = (f_data->buf_length > 12) ? 12 : f_data->buf_length ; ret = follow_ac3(buf, b_count, &offset, &last_match,0); ret = analysis_ret1("AC3", f_data, ret , b_count, offset, last_match); if (ret == 1){ f_data->scantype |= DATA_NO_FOOT ; f_data->type = buf[4]; } break; case 3 : offset = f_data->next_offset ; ret = follow_ac3(buf, f_data->buf_length, &offset, &last_match, f_data->type); ret = analysis_ret2("AC3", f_data, ret, offset, last_match); break; } return ret; } static int follow_ogg(unsigned char *buf, __u16 blockcount, __u32 *offset, __u32 *last_match, int flag){ int i, ret = 1; int last = 0; unsigned char *ogg_h; __u8 *t_pointer; __u32 frame_offset = *offset; __u32 seq_len; while ((ret == 1) && (frame_offset < (blockcount * current_fs->blocksize)-27)){ ogg_h = (buf + frame_offset); seq_len = 27; i = 0; t_pointer = (__u8*) (buf + frame_offset + seq_len); if ((ogg_h[0] == 0x4f)&&(ogg_h[1] == 0x67)&&(ogg_h[2] == 0x67) &&(ogg_h[3] == 0x53)){ if ( ogg_h[5] & 0x4) last = 1; for (i = 0; i < ogg_h[26] ;i++, t_pointer++){ if ((frame_offset + 27 + i) >= (blockcount * current_fs->blocksize)) break; seq_len += *t_pointer; } } else { if (last) ret = 2; else { if (ret && (ogg_h[0] || ogg_h[1] ||ogg_h[2] ||ogg_h[3])) ret = 0; else { if (zero_space(buf, frame_offset)) ret = 2; } } break; } *last_match = frame_offset; frame_offset += seq_len + ogg_h[26]; if (last && (!frame_offset % current_fs->blocksize)) ret = 2 ; #ifdef DEBUG_OGG_STREAM fprintf(stderr,"OGG-STREAM: serial number %12lu : size %6lu : offset %6lu \n", (ogg_h[14] | (ogg_h[15]<<8) | (ogg_h[16]<<16) | (ogg_h[17]<<24)), seq_len , frame_offset); #endif } *offset = frame_offset; return ret; } //ogg int file_ogg(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 0; unsigned char token[2][7]= {{0x80, 't', 'h', 'e', 'o', 'r', 'a'}, {0x01, 'v', 'i', 'd' ,'e', 'o', 0x00}}; unsigned char *ogg_h; __u32 b_count; __u32 offset = 0; __u32 last_match = 0; switch (flag){ case 0 : if ((f_data->size) && (f_data->size <= f_data->inode->i_size)){ if(f_data->scantype & DATA_READY){ *size = (f_data->next_offset)?f_data->next_offset : *size; ret = 1; break; }//FIXME if((!(f_data->inode->i_flags & EXT4_EXTENTS_FL))&&(f_data->size < (12 * current_fs->blocksize))){ f_data->inode->i_size = (f_data->size + current_fs->blocksize -1) & ~(current_fs->blocksize-1); *size = f_data->size % current_fs->blocksize; ret = 1; } else { *size +=2; ret = 2; } } else { ret =0; } break; case 1 : return ((scan & (M_IS_META | M_CLASS_1 | M_BLANK | M_TXT))||(f_data->scantype & DATA_READY)) ? 0 :1 ; break; case 2 : offset = test_id3_tag(buf); ogg_h = (buf + offset) ; if (!(ogg_h[5] & 0x02)){ #ifdef DEBUG fprintf(stderr,"OGG : Block %8lu is sequence %lu and not begin of a file\n",f_data->first, (ogg_h[18] | (ogg_h[19]<<8) | (ogg_h[20]<<16) | (ogg_h[21]<<24))); #endif f_data->func = file_none; return 0; } if((!(memcmp((void*)(buf + offset +28), token[0], 7))) || (!(memcmp((void*)(buf + offset +28), token[1], 7)))) f_data->name[strlen(f_data->name)-1] = 'm' ; b_count = (f_data->buf_length > 12) ? 12 : f_data->buf_length ; ret = follow_ogg(buf, b_count, &offset, &last_match,0); ret = analysis_ret1("OGG", f_data, ret , b_count, offset, last_match); break; case 3 : offset = f_data->next_offset ; ret = follow_ogg(buf, f_data->buf_length, &offset, &last_match,0); ret = analysis_ret2("OGG", f_data, ret, offset, last_match); break; } return ret; } static int follow_mp3(unsigned char *buf, __u16 blockcount, __u32 *offset, int *flag, __u32 *last_match, unsigned char* head){ #define MPEG_V25 0 #define MPEG_V2 2 #define MPEG_V1 3 #define MPEG_L3 0x01 #define MPEG_L2 0x02 #define MPEG_L1 0x03 int ret = 1; __u32 frame_offset = *offset ; int frame_flag = *flag; int mpeg_version; int mpeg_layer; int bit_rate_key; int sampling_rate_key; int padding; int bit_rate; int sample_rate; __u32 frameLength = 0; static const unsigned int sample_rate_table[4][4]={ {11025, 12000, 8000, 0}, /* MPEG_V25 */ { 0, 0, 0, 0}, {22050, 24000, 16000, 0}, /* MPEG_V2 */ {44100, 48000, 32000, 0} /* MPEG_V1 */ }; static const unsigned int bit_rate_table[4][4][16]= { /* MPEG_V25 */ { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}, { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}, { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0} }, /* MPEG_INVALID */ { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, /* MPEG_V2 */ { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}, { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}, { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0} }, /* MPEG_V1 */ { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0}, { 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0}, { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 294, 416, 448, 0} } }; while (frame_offset < (blockcount * current_fs->blocksize)-2){ if((buf[frame_offset + 0]==0xFF && ((buf[frame_offset + 1]&0xFE)==0xFA || (buf[frame_offset + 1]&0xFE)==0xF2 || (buf[frame_offset + 1]&0xFE)==0xE2))){ mpeg_version = (buf[frame_offset + 1]>>3) & 0x03; mpeg_layer = (buf[frame_offset + 1]>>1) & 0x03; bit_rate_key = (buf[frame_offset + 2]>>4) & 0x0F; sampling_rate_key = (buf[frame_offset + 2]>>2) & 0x03; padding = (buf[frame_offset + 2]>>1) & 0x01; bit_rate = bit_rate_table[mpeg_version][mpeg_layer][bit_rate_key]; sample_rate = sample_rate_table[mpeg_version][sampling_rate_key]; frameLength = 0; if(sample_rate==0 || bit_rate==0 || mpeg_layer==MPEG_L1){ return 0; } if(mpeg_layer==MPEG_L3) { if(mpeg_version==MPEG_V1) frameLength = 144000 * bit_rate / sample_rate + padding; else frameLength = 72000 * bit_rate / sample_rate + padding; } else{ if(mpeg_layer==MPEG_L2) frameLength = 144000 * bit_rate / sample_rate + padding; else frameLength = (12000 * bit_rate / sample_rate + padding) * 4; } #ifdef DEBUG_MAGIC_MP3_STREAM fprintf(stderr,"MP3-STREAM %8u-> framesize: %u, layer: %u, bitrate: %u, padding: %u\n", frame_flag, frameLength, 4-mpeg_layer, bit_rate, padding); #endif if( ! frameLength ){ return 0; } if (head && (! frame_flag) && (!frame_offset)) { head[0] = buf[frame_offset]; head[1] = buf[frame_offset +1]; head[2] = buf[frame_offset +2]; head[3] = (unsigned char)((frameLength-padding) >>8); head[4] = (unsigned char)((frameLength-padding) & 0xff); } *last_match = frame_offset; frame_offset += frameLength; frame_flag++; } else{ if((buf[frame_offset + 0] =='T') && (buf[frame_offset + 1] == 'A') && (buf[frame_offset + 2] == 'G')){ frame_offset += 128 ; #ifdef DEBUG_MAGIC_MP3_STREAM fprintf (stderr,"\nMP3-TAG-END : offset %lu : last_frame %lu\n", frame_offset, frameLength); #endif *last_match = frame_offset; ret= 2; break; } if((!(frame_offset % current_fs->blocksize)) || ( ! ( buf[frame_offset + 0]) && ( ! ( buf[frame_offset + 1]) )&& (zero_space(buf, frame_offset)))){ #ifdef DEBUG_MAGIC_MP3_STREAM fprintf (stderr,"\nMP3-END : offset %lu : last_frame %lu\n", frame_offset, frameLength); #endif ret = 2; break; } else { #ifdef DEBUG_MAGIC_MP3_STREAM fprintf (stderr,"MP3-STREAM_END : offset %lu : last_frame %lu\n", frame_offset, frameLength); blockhex(stderr,(void*)(buf+frame_offset),0,64); #endif ret = 0; break; } } } if (frame_offset >= (blockcount * current_fs->blocksize)-2) ret = 1; else{ if ((ret != 2) && (frame_flag) && (frame_offset % current_fs->blocksize)) ret = 3; } *offset = frame_offset; *flag = frame_flag; return ret; } //mp3 int file_mp3(unsigned char *buf, int *size, __u32 scan , int flag, struct found_data_t* f_data){ int ret = 0; __u32 offset = 0 ; __u32 last_match = 0; int frame_flag = 0; int b_count, tag_flag = 0; unsigned char head[5]={0,0,0,0,0}; switch (flag){ case 0 : if ((f_data->size) && (f_data->size <= f_data->inode->i_size)){ if(f_data->scantype & DATA_READY){ *size = (f_data->next_offset)?f_data->next_offset : *size; ret = 1; break; }//FIXME if((!(f_data->inode->i_flags & EXT4_EXTENTS_FL))&&(f_data->size < (12 * current_fs->blocksize))){ f_data->inode->i_size = (f_data->size + current_fs->blocksize -1) & ~(current_fs->blocksize-1); *size = f_data->size % current_fs->blocksize; ret = 1; } } else { ret =0; } break; case 1 : return ((scan & (M_IS_META | M_CLASS_1 | M_BLANK ))||(f_data->scantype & DATA_READY)) ? 0 :1 ; break; case 2 : offset = test_id3_tag(buf); if (offset) { tag_flag++; } b_count = (f_data->buf_length > 12) ? 12 : f_data->buf_length ; ret = follow_mp3(buf, b_count, &offset, &frame_flag, &last_match, head); if (last_match) f_data->last_match_blk = (last_match/current_fs->blocksize) +1 ; if (ret){ f_data->scantype = DATA_CARVING + DATA_NO_FOOT; f_data->size = offset; if (offset > (b_count * current_fs->blocksize)) f_data->buf_length = b_count; else f_data->buf_length = offset / current_fs->blocksize; f_data->next_offset = offset - (f_data->buf_length * current_fs->blocksize); switch (ret){ case 3 : #ifdef DEBUG_MAGIC_MP3_STREAM fprintf(stderr,"MP3-CHECK: Block %lu : mp3-data block found, to short for recover\n",f_data->first); #endif f_data->scantype |= DATA_BREAK; f_data->func = NULL; return 0; break; case 1 : break; case 2 : if (offset){ f_data->scantype |= DATA_READY; if(offset % current_fs->blocksize)(f_data->buf_length)++; } else { f_data->func = NULL; return 0; } break; } if ((frame_flag > 2) &&( ! tag_flag)){ if (head[0]){ __u16 reverse = (__u16)(head[3]<<8) + head[4]; __u32 b_size = current_fs->blocksize; unsigned char *v_buf = buf - b_size; if (reverse < (b_size -1)){ if (((v_buf[b_size-reverse] == head[0]) && (v_buf[b_size-reverse +1 ] == head[1]) && (v_buf[b_size-reverse+2] == (head[2] & ~0x2))) || ((v_buf[b_size-reverse-1] == head[0]) && (v_buf[b_size-reverse] == (head[1])) && (v_buf[b_size-reverse+1] == (head[2] | 0x2)))){ #ifdef DEBUG_MAGIC_MP3_STREAM fprintf(stderr,"MP3-CHECK: Block %lu : is mp3-data but not begin of file\n", f_data->first); blockhex(stderr,(void*)(v_buf+b_size-reverse-16),0,64); #endif f_data->func = NULL; } } } ret = 1; } } else{ f_data->func = NULL; } break; case 3: offset = f_data->next_offset ; ret = follow_mp3(buf, f_data->buf_length , &offset, &frame_flag, &last_match, NULL); if (last_match) f_data->last_match_blk = ((f_data->size - f_data->next_offset + last_match)/current_fs->blocksize) +1 ; if (ret){ f_data->size += offset - f_data->next_offset; f_data->buf_length = offset / current_fs->blocksize; f_data->next_offset = offset - (f_data->buf_length * current_fs->blocksize); switch (ret){ case 3 : #ifdef DEBUG_MAGIC_MP3_STREAM fprintf(stderr,"MP3-CHECK: mp3-data found, recover not all\n"); #endif f_data->scantype |= DATA_BREAK; break; case 1 : #ifdef DEBUG_MAGIC_MP3_STREAM // fprintf(stderr,"MP3-CHECK: mp3-data next found\n"); #endif break; case 2 : #ifdef DEBUG_MAGIC_MP3_STREAM fprintf(stderr,"MP3-CHECK: mp3-data end found, recover \n"); #endif f_data->scantype |= DATA_READY; if(offset % current_fs->blocksize) (f_data->buf_length)++; break; } } break; } //switch return ret; }//end mp3 //change this only carefully //Although the scanner is controlled here, but you can not directly configure whether a file is found or not. //This function has a strong influence on the accuracy of the result. void get_file_property(struct found_data_t* this){ switch (this->type){ //Application case 0x0101 : //dicom // this->func = file_dicom ; // strncat(this->name,".dicom",7); break; case 0x0102 : //mac-binhex40 // this->func = file_mac-binhex40 ; strncat(this->name,".hqx",7); break; case 0x0103 : //msword this->func = file_CDF ; strncat(this->name,".doc",7); break; case 0x0104 : //octet-stream // this->func = file_octet-stream; strncat(this->name,".unknown",8); break; case 0x0105 : //ogg this->func = file_ogg ; strncat(this->name,".ogg",7); break; case 0x0106 : //pdf this->func = file_pdf ; strncat(this->name,".pdf",7); break; case 0x0107 : //pgp // this->func = file_pgp ; strncat(this->name,".pgp",7); break; case 0x0108 : //pgp-encrypted // this->func = file_pgp-encrypted ; strncat(this->name,".pgp",7); break; case 0x0109 : //pgp-keys // this->func = file_pgp-keys ; strncat(this->name,".key",7); break; case 0x010a : //pgp-signature // this->func = file_pgp-signature ; strncat(this->name,".pgp",7); break; case 0x010b : //postscript this->func = file_ps ; strncat(this->name,".ps",7); break; case 0x010c : //unknown+zip this->func = file_zip ; strncat(this->name,".zip",7); break; case 0x010d : //vnd.google-earth.kml+xml // this->func = file_vnd.google-earth.kml+xml ; // strncat(this->name,".vnd.google-earth.kml+xml",7); break; case 0x010e : //vnd.google-earth.kmz // this->func = file_vnd.google-earth.kmz ; // strncat(this->name,".vnd.google-earth.kmz",7); break; case 0x010f : //vnd.lotus-wordpro // this->func = file_vnd.lotus-wordpro ; // strncat(this->name,".vnd.lotus-wordpro",7); break; case 0x0110 : //vnd.ms-cab-compressed // this->func = file_vnd.ms-cab-compressed ; strncat(this->name,".cab",7); break; case 0x0111 : //vnd.ms-excel // this->func = file_vnd.ms-excel ; strncat(this->name,".xls",7); break; case 0x0112 : //vnd.ms-tnef this->func = file_none ; strncat(this->name,".dat",7); break; case 0x0113 : //vnd.oasis.opendocument. this->func = file_zip ; if (strstr(this->scan_result,"text")){ strncat(this->name,".odt",7); break; } if (strstr(this->scan_result,"presentation")){ strncat(this->name,".odp",7); break; } if (strstr(this->scan_result,"spreadsheet")){ strncat(this->name,".ods",7); break; } if (strstr(this->scan_result,"graphics")){ strncat(this->name,".odg",7); break; } break; case 0x0114 : //vnd.rn-realmedia this->func = file_ra ; strncat(this->name,".ra",7); break; case 0x0115 : //vnd.symbian.install // this->func = file_vnd.symbian.install ; strncat(this->name,".sis",7); break; case 0x0116 : //x-123 // this->func = file_x-123 ; strncat(this->name,".123",7); break; case 0x0117 : //x-adrift // this->func = file_x-adrift ; // strncat(this->name,".x-adrift",7); break; case 0x0118 : //x-archive this->func = file_archive ; strncat(this->name,".a",7); break; case 0x0119 : //x-arc deaktiv // this->func = file_x-arc ; strncat(this->name,".arc",7); break; case 0x011a : //x-arj this->func = file_arj ; strncat(this->name,".arj",7); break; case 0x011b : //x-bittorrent // this->func = file_x-bittorrent ; // strncat(this->name,".x-bittorrent",7); break; case 0x011c : //x-bzip2 this->func = file_bzip2 ; strncat(this->name,".bzip2",7); break; case 0x011d : //x-compress this->func = file_lzw ; strncat(this->name,".Z",7); break; case 0x011e : //x-coredump // this->func = file_x-coredump ; strncat(this->name,".core",7); break; case 0x011f : //x-cpio this->func = file_cpio ; strncat(this->name,".cpio",7); break; case 0x0120 : //x-dbf this->func = file_dbf ; strncat(this->name,".dbf",7); break; case 0x0121 : //x-dbm // this->func = file_x-dbm ; strncat(this->name,".dbm",7); break; case 0x0122 : //x-debian-package this->func = file_archive; strncat(this->name,".deb",7); break; case 0x0123 : //x-dosexec // this->func = file_x-dosexec ; strncat(this->name,".exe",7); break; case 0x0124 : //x-dvi this->func = file_dvi ; strncat(this->name,".dvi",7); break; case 0x0125 : //x-eet // this->func = file_x-eet ; strncat(this->name,".eet",7); break; case 0x0126 : //x-elc // this->func = file_x-elc ; strncat(this->name,".elc",7); break; case 0x0127 : //x-executable this->func = file_binary ; strncat(this->name,".bin",7); break; case 0x0128 : //x-gdbm // this->func = file_x-gdbm ; strncat(this->name,".dbm",7); break; case 0x0129 : //x-gnucash this->func = file_txt ; strncat(this->name,".xml",7); break; case 0x012a : //x-gnumeric this->func = file_gnumeric ; strncat(this->name,".gnm",7); break; case 0x012b : //x-gnupg-keyring deaktiv // this->func = file_x-gnupg-keyring ; strncat(this->name,".key",7); break; case 0x012c : //x-gzip this->func = file_gzip ; strncat(this->name,".gz",7); break; case 0x012d : //x-hdf // this->func = file_x-hdf ; strncat(this->name,".hdf",7); break; case 0x012e : //x-hwp // this->func = file_x-hwp ; strncat(this->name,".hwp",7); break; case 0x012f : //x-ichitaro4 // this->func = file_x-ichitaro4 ; strncat(this->name,".JDT",7); break; case 0x0130 : //x-ichitaro5 // this->func = file_x-ichitaro5 ; strncat(this->name,".JDT",7); break; case 0x0131 : //x-ichitaro6 // this->func = file_x-ichitaro6 ; strncat(this->name,".JDT",7); break; case 0x0132 : //x-iso9660-image this->func = file_iso9660 ; strncat(this->name,".iso",7); break; case 0x0133 : //x-java-applet // this->func = file_x-java-applet ; strncat(this->name,".jar",7); break; case 0x0134 : //x-java-jce-keystore // this->func = file_x-java-jce-keystore ; // strncat(this->name,".x-java-jce-keystore",7); break; case 0x0135 : //x-java-keystore // this->func = file_x-java-keystore ; // strncat(this->name,".x-java-keystore",7); break; case 0x0136 : //x-java-pack200 // this->func = file_x-java-pack200 ; // strncat(this->name,".x-java-pack200",7); break; case 0x0137 : //x-kdelnk // this->func = file_x-kdelnk ; // strncat(this->name,".x-kdelnk",7); break; case 0x0138 : //x-lha // this->func = file_x-lha ; strncat(this->name,".lzh",7); break; case 0x0139 : //x-lharc // this->func = file_x-lharc ; strncat(this->name,".lzs",7); break; case 0x013a : //x-lzip // this->func = file_x-lzip ; strncat(this->name,".lz",7); break; case 0x013b : //x-mif // this->func = file_x-mif ; strncat(this->name,".mif",7); break; case 0x013c : //xml this->func = file_txt; strncat(this->name,".xml",7); break; case 0x013d : //xml-sitemap this->func = file_txt ; strncat(this->name,".xml",7); break; case 0x013e : //x-msaccess // this->func = file_x-msaccess ; strncat(this->name,".mdb",7); break; case 0x013f : //x-ms-reader // this->func = file_x-ms-reader ; // strncat(this->name,".x-ms-reader",7); break; case 0x0140 : //x-object this->func = file_binary ; strncat(this->name,".o",7); break; case 0x0141 : //x-pgp-keyring deaktiv // this->func = file_x-pgp-keyring ; // strncat(this->name,".x-pgp-keyring",7); break; case 0x0142 : //x-quark-xpress-3 // this->func = file_x-quark-xpress-3 ; strncat(this->name,".qxp",7); break; case 0x0143 : //x-quicktime-player this->func = file_qt; strncat(this->name,".qt",7); break; case 0x0144 : //x-rar this->func = file_rar ; strncat(this->name,".rar",7); break; case 0x0145 : //x-rpm this->func = file_rpm ; strncat(this->name,".rpm",7); break; case 0x0146 : //x-sc // this->func = file_x-sc ; strncat(this->name,".sc",7); break; case 0x0147 : //x-setupscript // this->func = file_x-setupscript ; // strncat(this->name,".x-setupscript",7); break; case 0x0148 : //x-sharedlib this->func = file_binary ; strncat(this->name,".so",7); break; case 0x0149 : //x-shockwave-flash this->func = file_swf ; strncat(this->name,".swf",7); break; case 0x014a : //x-stuffit // this->func = file_x-stuffit ; strncat(this->name,".sit",7); break; case 0x014b : //x-svr4-package // this->func = file_x-svr4-package ; // strncat(this->name,".x-svr4-package",7); break; case 0x014c : //x-tar this->func = file_tar ; strncat(this->name,".tar",7); break; case 0x014d : //x-tex-tfm this->func = file_tfm ; strncat(this->name,".tfm",7); break; case 0x014e : //x-tokyocabinet-btree // this->func = file_x-tokyocabinet-btree ; // strncat(this->name,".x-tokyocabinet-btree",7); break; case 0x014f : //x-tokyocabinet-fixed // this->func = file_x-tokyocabinet-fixed ; // strncat(this->name,".x-tokyocabinet-fixed",7); break; case 0x0150 : //x-tokyocabinet-hash // this->func = file_x-tokyocabinet-hash ; // strncat(this->name,".x-tokyocabinet-hash",7); break; case 0x0151 : //x-tokyocabinet-table // this->func = file_x-tokyocabinet-table ; // strncat(this->name,".x-tokyocabinet-table",7); break; case 0x0152 : //x-xz this->func = file_xz ; strncat(this->name,".xz",7); break; case 0x0153 : //x-zoo // this->func = file_x-zoo ; strncat(this->name,".zoo",7); break; case 0x0154 : //zip this->func = file_zip ; strncat(this->name,".zip",7); break; case 0x0155 : //x-font-ttf this->func = file_ttf ; strncat(this->name,".ttf",7); break; case 0x0156 : //x-7z-compressed this->func = file_7z ; strncat(this->name,".7z",7); break; //---------------------------------------------------------------- //Audio case 0x0201 : //basic this->func = file_au ; strncat(this->name,".au",7); break; case 0x0202 : //midi this->func = file_midi ; strncat(this->name,".mid",7); break; case 0x0203 : //mp4 this->func = file_qt ; strncat(this->name,".mp4",7); break; case 0x0204 : //mpeg this->func = file_mp3 ; strncat(this->name,".mp3",7); break; case 0x0205 : //x-adpcm this->func = file_au ; strncat(this->name,".au",7); break; case 0x0206 : //x-aiff this->func = file_iff ; strncat(this->name,".aiff",7); break; case 0x0207 : //x-dec-basic // this->func = file_x-dec-basic ; // strncat(this->name,".x-dec-basic",7); break; case 0x0208 : //x-flac this->func = file_flac ; strncat(this->name,".flac",7); break; case 0x0209 : //x-hx-aac-adif // this->func = file_x-hx-aac-adif ; strncat(this->name,".aac",7); break; case 0x020a : //x-hx-aac-adts deaktiv // this->func = file_x-hx-aac-adts ; strncat(this->name,".aac",7); break; case 0x020b : //x-mod this->func = file_mod ; strncat(this->name,".mod",7); break; case 0x020c : //x-mp4a-latm deaktiv // this->func = file_x-mp4a-latm ; // strncat(this->name,".x-mp4a-latm",7); break; case 0x020d : //x-pn-realaudio this->func = file_ra; strncat(this->name,".ra",7); break; case 0x020e : //x-unknown this->func = file_creative_voice; strncat(this->name,".voc",7); break; case 0x020f : //x-wav this->func = file_riff ; strncat(this->name,".wav",7); break; //---------------------------------------------------------------- //Images case 0x0301 : //gif this->func = file_gif ; strncat(this->name,".gif",7); break; case 0x0302 : //jp2 this->func = file_jp2000; strncat(this->name,".jp2",7); break; case 0x0303 : //jpeg this->func = file_jpeg ; strncat(this->name,".jpg",7); break; case 0x0304 : //png this->func = file_png ; strncat(this->name,".png",7); break; case 0x0305 : //svg+xml this->func = file_txt ; strncat(this->name,".svg",7); break; case 0x0306 : //tiff this->func = file_tiff ; strncat(this->name,".tif",7); break; case 0x0307 : //vnd.adobe.photoshop this->func = file_psd; strncat(this->name,".psd",7); break; case 0x0308 : //vnd.djvu this->func = file_djvu ; strncat(this->name,".djvu",7); break; case 0x0309 : //x-coreldraw this->func = file_riff ; strncat(this->name,".cdr",7); break; case 0x030a : //x-cpi // this->func = file_x-cpi ; strncat(this->name,".cpi",7); break; case 0x030b : //x-ico this->func = file_ico ; strncat(this->name,".ico",7); break; case 0x030c : //x-ms-bmp this->func = file_bmp ; strncat(this->name,".bmp",7); break; case 0x030d : //x-niff this->func = file_riff ; strncat(this->name,".niff",7); break; case 0x030e : //x-portable-bitmap this->func = file_pnm ; strncat(this->name,".pbm",7); break; case 0x030f : //x-portable-greymap this->func = file_pnm ; strncat(this->name,".pgm",7); break; case 0x0310 : //x-portable-pixmap this->func = file_pnm ; strncat(this->name,".ppm",7); break; case 0x0311 : //x-psion-sketch // this->func = file_x-psion-sketch ; // strncat(this->name,".x-psion-sketch",7); break; case 0x0312 : //x-quicktime this->func = file_qt ; strncat(this->name,".qtif",7); break; case 0x0313 : //x-unknown // this->func = file_x-unknown ; strncat(this->name,".unknown",8); break; case 0x0314 : //x-xcursor // this->func = file_x-xcursor ; strncat(this->name,".cur",7); break; case 0x0315 : //x-xpmi // this->func = file_x-xpmi ; strncat(this->name,".xpm",7); break; case 0x0316 : //x-tga this->func = file_tga ; strncat(this->name,".tga",7); break; case 0x0317 : //x-xcf this->func = file_xcf; strncat(this->name,".xcf",7); break; //---------------------------------------------------------------- //Messages case 0x0401 : //news this->func = file_txt ; // strncat(this->name,".news",7); break; case 0x0402 : //rfc822 this->func = file_smtp ; // strncat(this->name,".rfc822",7); break; //---------------------------------------------------------------- //Model case 0x0501 : //vrml // this->func = file_vrml ; // strncat(this->name,".vrml",7); break; case 0x0502 : //x3d // this->func = file_x3d ; // strncat(this->name,".x3d",7); break; //---------------------------------------------------------------- //Text case 0x0601 : //html this->func = file_html ; strncat(this->name,".html",7); break; case 0x0602 : //PGP this->func = file_txt ; strncat(this->name,".pgp",7); break; case 0x0603 : //rtf this->func = file_txt ; strncat(this->name,".rtf",7); break; case 0x0604 : //texmacs // this->func = file_texmacs ; strncat(this->name,".tm",7); break; case 0x0605 : //troff this->func = chk_troff; strncat(this->name,".man",7); break; case 0x0606 : //vnd.graphviz // this->func = file_vnd.graphviz ; strncat(this->name,".gv",7); break; case 0x0607 : //x-awk this->func = file_txt ; strncat(this->name,".awk",7); break; case 0x0608 : //x-diff this->func = file_txt ; strncat(this->name,".diff",7); break; case 0x0609 : //x-fortran this->func = file_txt ; strncat(this->name,".f",7); break; case 0x060a : //x-gawk this->func = file_txt ; strncat(this->name,".awk",7); break; case 0x060b : //x-info this->func = file_txt ; strncat(this->name,".info",7); break; case 0x060c : //x-lisp this->func = file_txt ; strncat(this->name,".l",7); break; case 0x060d : //x-lua // this->func = file_x-lua ; strncat(this->name,".lua",7); break; case 0x060e : //x-msdos-batch this->func = file_txt ; strncat(this->name,".bat",7); break; case 0x060f : //x-nawk this->func = file_txt ; strncat(this->name,".awk",7); break; case 0x0610 : //x-perl this->func = file_txt ; strncat(this->name,".pl",7); break; case 0x0611 : //x-php this->func = file_txt ; strncat(this->name,".php",7); break; case 0x0612 : //x-shellscript this->func = file_txt ; strncat(this->name,".sh",7); break; case 0x0613 : //x-texinfo this->func = file_txt ; strncat(this->name,".texi",7); break; case 0x0614 : //x-tex this->func = file_bin_txt; strncat(this->name,".tex",7); break; case 0x0615 : //x-vcard this->func = file_txt; strncat(this->name,".vcf",7); break; case 0x0616 : //x-xmcd // this->func = file_x-xmcd ; // strncat(this->name,".x-xmcd",7); break; case 0x0617 : //plain this->func = file_bin_txt ; strncat(this->name,".txt",7); break; case 0x0618 : //x-pascal (often c files) this->func = file_txt ; strncat(this->name,".pas",7); break; case 0x0619 : //c++ this->func = file_txt ; strncat(this->name,".c++",7); break; case 0x061a : //c this->func = file_txt ; strncat(this->name,".c",7); break; case 0x061b : //x-mail this->func = file_txt ; // strncat(this->name,".x-mail",7); break; case 0x061c : //x-makefile this->func = file_txt ; // strncat(this->name,".x-makefile",7); break; case 0x061d : //x-asm this->func = file_txt ; strncat(this->name,".S",7); break; case 0x061e : //x-python this->func = file_txt ; strncat(this->name,".py",7); break; case 0x061f : //x-java this->func = file_txt ; strncat(this->name,".jar",7); break; case 0x0620 : //PEM this->func = file_txt ; strncat(this->name,".pem",7); break; case 0x0621 : //SGML this->func = file_txt ; strncat(this->name,".rc",7); break; case 0x0622 : //libtool this->func = file_txt ; strncat(this->name,".la",7); break; case 0x0623 : //M3U this->func = file_txt ; strncat(this->name,".m3u",7); break; case 0x0624 : //tcl this->func = file_txt ; strncat(this->name,".tcl",7); break; case 0x0625 : //POD this->func = file_txt ; strncat(this->name,".pod",7); break; case 0x0626 : //PPD this->func = file_txt ; strncat(this->name,".ppd",7); break; case 0x0627 : //configure this->func = file_txt ; strncat(this->name,".conf",7); break; case 0x0628 : //ruby this->func = file_txt ; strncat(this->name,".rb",7); break; case 0x0629 : //sed this->func = file_txt ; strncat(this->name,".sed",7); break; case 0x062a : //expect this->func = file_txt ; // strncat(this->name,".expect",8); break; case 0x062b : //ssh this->func = file_txt ; strncat(this->name,".key",7); break; case 0x062c : //text (for all unknown) this->func = file_txt ; strncat(this->name,".txt",7); break; //---------------------------------------------------------------- //Video case 0x0701 : //3gpp this->func = file_qt ; strncat(this->name,".3gp",7); break; case 0x0702 : //h264 // this->func = file_h264 ; strncat(this->name,".mp4",7); break; case 0x0703 : //mp2p // this->func = file_mp2p ; strncat(this->name,".ps",7); break; case 0x0704 : //mp2t // this->func = file_mp2t ; strncat(this->name,".ts",7); break; case 0x0705 : //mp4 this->func = file_qt ; strncat(this->name,".mp4",7); break; case 0x0706 : //mp4v-es // this->func = file_mp4v-es ; strncat(this->name,".mp4",7); break; case 0x0707 : //mpeg this->func = file_mpeg ; strncat(this->name,".mpeg",7); break; case 0x0708 : //mpv // this->func = file_mpv ; strncat(this->name,".mpv",7); break; case 0x0709 : //quicktime this->func = file_qt ; strncat(this->name,".qt",7); break; case 0x070a : //x-flc this->func = file_fli ; strncat(this->name,".flc",7); break; case 0x070b : //x-fli this->func = file_fli ; strncat(this->name,".fli",7); break; case 0x070c : //x-flv // this->func = file_x-flv ; strncat(this->name,".flv",7); break; case 0x070d : //x-jng this->func = file_png ; strncat(this->name,".jng",7); break; case 0x070e : //x-mng this->func = file_png ; strncat(this->name,".mng",7); break; case 0x070f : //x-msvideo this->func = file_riff ; strncat(this->name,".avi",7); break; case 0x0710 : //x-sgi-movie // this->func = file_x-sgi-movie ; strncat(this->name,".movie",7); break; case 0x0711 : //x-unknown // this->func = file_x-unknown ; strncat(this->name,".unknown",8); break; case 0x0712 : //x-ms-asf this->func = file_asf ; strncat(this->name,".asf",7); break; case 0x0713 : //x-matroska this->func = file_mkv ; strncat(this->name,".mkv",7); break; case 0x0714 : //webm this->func = file_mkv ; strncat(this->name,".mkv",7); break; //---------------------------------------------------------------- //Reservoir found in application/octet-stream case 0x0801 : //MPEG this->func = file_mpeg ; strncat(this->name,".mpeg",7); break; case 0x0802 : //Targa this->func = file_tga ; strncat(this->name,".tga",7); break; case 0x0803 : //7-zip this->func = file_7z ; strncat(this->name,".7z",7); break; case 0x0804 : //cpio this->func = file_cpio ; strncat(this->name,".cpio",7); break; case 0x0805 : //CD-ROM this->func = file_iso9660 ; strncat(this->name,".iso",7); break; case 0x0806 : //DVD // this->func = file_DVD ; strncat(this->name,".iso",7); break; case 0x0807 : //9660 this->func = file_iso9660 ; strncat(this->name,".iso",7); break; case 0x0808 : //Kernel // this->func = file_Kernel ; // strncat(this->name,".Kernel",7); break; case 0x0809 : //boot // this->func = file_boot ; strncat(this->name,".iso",7); break; case 0x080a : //ext2 this->func = file_ext2fs ; strncat(this->name,".ext2",7); break; case 0x080b : //ext3 this->func = file_ext2fs ; strncat(this->name,".ext3",7); break; case 0x080c : //ext4 this->func = file_ext2fs ; strncat(this->name,".ext4",7); break; case 0x080d : //Image // this->func = file_Image ; // strncat(this->name,".Image",7); break; case 0x080e : //Composite this->func = file_CDF ; strncat(this->name,".doc",7); break; case 0x080f : //SQLite this->func = file_SQLite ; strncat(this->name,".sql",7); break; case 0x0810 : //OpenOffice.org this->func = file_zip ; strncat(this->name,".sxw",7); break; case 0x0811 : //Microsoft this->func = file_CDF ; strncat(this->name,".doc",7); break; case 0x0812 : //VMWare3 this->func = file_vmware ; strncat(this->name,".vmdk",7); break; case 0x0813 : //VMware4 this->func = file_vmware ; strncat(this->name,".vmdk",7); break; case 0x0814 : //JPEG this->func = file_jp2000; strncat(this->name,".jp2",7); break; case 0x0815 : //ART this->func = file_art ; strncat(this->name,".art",7); break; case 0x0816 : //PCX this->func = file_pcx ; strncat(this->name,".pcx",7); break; case 0x0817 : //RIFF this->func = file_riff ; strncat(this->name,".amv",7); break; case 0x0818 : //DIF // this->func = file_dv ; strncat(this->name,".dv",7); break; case 0x0819 : //IFF this->func = file_iff ; strncat(this->name,".iff",7); break; case 0x081a : //ATSC this->func = file_ac3 ; strncat(this->name,".ac3",7); break; case 0x081b : // ScreamTracker III this->func = file_mod ; strncat(this->name,".s3m",7); break; case 0x081c : // EBML matroska this->func = file_mkv ; strncat(this->name,".mkv",7); break; case 0x081d : // LZMA this->func = file_lzma ; strncat(this->name,".lzma",7); break; case 0x081e : //Audio Visual Research this->func = file_avr ; strncat(this->name,".avr",7); break; case 0x081f : //Sample Vision Format this->func = file_smp ; strncat(this->name,".smp",7); break; case 0x0820 : //ISO Media (mp4) this->func = file_qt ; strncat(this->name,".mp4",7); break; case 0x0821 : //Linux // this->func = file_Linux ; // strncat(this->name,".Linux",7); break; case 0x0822 : //filesystem // this->func = file_filesystem ; strncat(this->name,".iso",7); break; case 0x0823 : //x86 // this->func = file_x86 ; this->func = file_none ; //do not recover this // strncat(this->name,".iso",7); break; case 0x0824 : //LUKS this->func = file_luks ; strncat(this->name,".luks",7); break; case 0x0825 : //python (binary) this->func = file_bin_raw ; strncat(this->name,".pyc",7); break; case 0x0826 : //ESRI Shapefile this->func = file_esri ; strncat(this->name,".shp",7); break; case 0x0827 : //CDF this->func = file_CDF ; strncat(this->name,".doc",7); break; case 0x0828 : //ecryptfs this->func = file_ecryptfs ; strncat(this->name,".ecrypt",8); break; case 0x0829 : //Matlab v5 this->func = file_matlab ; strncat(this->name,".mat",8); break; //---------------------------------------------------------------- default: this->func = file_default ; } if (!this->func) this->func = file_default ; }