/* File: file_mov.c Copyright (C) 1998-2007 Christophe GRENIER This software 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, write the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include #endif #ifdef HAVE_STRING_H #include #endif #include #include "types.h" #include "filegen.h" #include "common.h" #include "log.h" static void register_header_check_mov(file_stat_t *file_stat); static int header_check_mov(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new); #ifdef EXPERIMENTAL static int data_check_mov(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery); #endif const file_hint_t file_hint_mov= { .extension="mov", .description="mov/mp4/3gp/3g2/jp2", .min_header_distance=0, .max_filesize=PHOTOREC_MAX_FILE_SIZE, .recover=1, .header_check=&header_check_mov, .register_header_check=®ister_header_check_mov }; static void register_header_check_mov(file_stat_t *file_stat) { register_header_check(0, NULL,0, &header_check_mov, file_stat); } static const unsigned char * find_in_mem(const unsigned char *haystack, const unsigned int haystack_size, const unsigned char *needle, const unsigned int needle_size); static const unsigned char * find_in_mem(const unsigned char *haystack, const unsigned int haystack_size, const unsigned char *needle, const unsigned int needle_size) { unsigned int i; for(i=0;ifile_stat!=0 && file_recovery->file_stat->file_hint==&file_hint_mov) return 0; file_recovery_new->calculated_file_size=0; #endif while(i1024*1024*1024) return 0; #ifdef EXPERIMENTAL file_recovery_new->data_check=data_check_mov; file_recovery_new->file_check=&file_check_file; file_recovery_new->calculated_file_size=i+atom_size; #endif /* check for commun atom type */ if(buffer[i+4]=='p' && buffer[i+5]=='n' && buffer[i+6]=='o' && buffer[i+7]=='t') { if(atom_size < 256) { reset_file_recovery(file_recovery_new); file_recovery_new->extension=file_hint_mov.extension; return 1; } else return 0; } if(buffer[i+4]=='w' && buffer[i+5]=='i' && buffer[i+6]=='d' && buffer[i+7]=='e') { if(atom_size < 256) { reset_file_recovery(file_recovery_new); file_recovery_new->extension=file_hint_mov.extension; return 1; } else return 0; } if(buffer[i+4]=='m' && buffer[i+5]=='o' && buffer[i+6]=='o' && buffer[i+7]=='v') { if(atom_size < 256*256*256) { reset_file_recovery(file_recovery_new); file_recovery_new->extension=file_hint_mov.extension; return 1; } else return 0; } if(buffer[i+4]=='f' && buffer[i+5]=='t' && buffer[i+6]=='y' && buffer[i+7]=='p') { if(atom_size>buffer_size-i) atom_size=buffer_size-i; if(find_in_mem(&buffer[i+8], atom_size-8, "isom", 4)!=0 || find_in_mem(&buffer[i+8], atom_size-8, "mp41", 4)!=0 || find_in_mem(&buffer[i+8], atom_size-8, "mp42", 4)!=0 || find_in_mem(&buffer[i+8], atom_size-8, "mmp4", 4)!=0 || find_in_mem(&buffer[i+8], atom_size-8, "M4A", 3)!=0 || find_in_mem(&buffer[i+8], atom_size-8, "M4B", 3)!=0 || find_in_mem(&buffer[i+8], atom_size-8, "M4P", 3)!=0) { reset_file_recovery(file_recovery_new); file_recovery_new->extension="mp4"; return 1; } else if(find_in_mem(&buffer[i+8], atom_size-8, "3gp", 3)!=0) { reset_file_recovery(file_recovery_new); file_recovery_new->extension="3gp"; return 1; } else if(find_in_mem(&buffer[i+8], atom_size-8, "3g2", 3)!=0) { reset_file_recovery(file_recovery_new); file_recovery_new->extension="3g2"; return 1; } else if(find_in_mem(&buffer[i+8], atom_size-8, "jp2", 3)!=0) { reset_file_recovery(file_recovery_new); file_recovery_new->extension="jp2"; return 1; } else if(find_in_mem(&buffer[i+8], atom_size-8, "qt", 2)!=0) { reset_file_recovery(file_recovery_new); file_recovery_new->extension="mov"; return 1; } } if(prev_atom_skip==1 && buffer[i+4]=='m' && buffer[i+5]=='d' && buffer[i+6]=='a' && buffer[i+7]=='t') { reset_file_recovery(file_recovery_new); file_recovery_new->extension=file_hint_mov.extension; return 1; } if(buffer[i+4]=='s' && buffer[i+5]=='k' && buffer[i+6]=='i' && buffer[i+7]=='p') prev_atom_skip=1; else prev_atom_skip=0; i+=atom_size; } return 0; } #ifdef EXPERIMENTAL /* There are too much atom types */ static int data_check_mov(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery) { while(file_recovery->calculated_file_size + 8 < file_recovery->file_size + buffer_size/2) { unsigned int atom_size; unsigned int i; i=file_recovery->calculated_file_size - file_recovery->file_size + buffer_size/2; atom_size=(buffer[i+0]<<24)+(buffer[i+1]<<16)+(buffer[i+2]<<8)+buffer[i+3]; // log_trace("file_mov.c: atom %c%c%c%c size %u\n", buffer[i+4],buffer[i+5],buffer[i+6],buffer[i+7], atom_size); if(atom_size>=8 && atom_size<1024*1024*1024 && ((buffer[i+4]=='f' && buffer[i+5]=='r' && buffer[i+6]=='e' && buffer[i+7]=='e') || (buffer[i+4]=='s' && buffer[i+5]=='k' && buffer[i+6]=='i' && buffer[i+7]=='p') || (buffer[i+4]=='w' && buffer[i+5]=='i' && buffer[i+6]=='d' && buffer[i+7]=='e') || (buffer[i+4]=='p' && buffer[i+5]=='n' && buffer[i+6]=='o' && buffer[i+7]=='t') || (buffer[i+4]=='m' && buffer[i+5]=='o' && buffer[i+6]=='o' && buffer[i+7]=='v') || (buffer[i+4]=='m' && buffer[i+5]=='d' && buffer[i+6]=='a' && buffer[i+7]=='t') || (buffer[i+4]=='f' && buffer[i+5]=='t' && buffer[i+6]=='y' && buffer[i+7]=='p') || (buffer[i+4]=='t' && buffer[i+5]=='r' && buffer[i+6]=='a' && buffer[i+7]=='k') || (buffer[i+4]=='m' && buffer[i+5]=='d' && buffer[i+6]=='i' && buffer[i+7]=='a') || (buffer[i+4]=='s' && buffer[i+5]=='t' && buffer[i+6]=='b' && buffer[i+7]=='l') || (buffer[i+4]=='c' && buffer[i+5]=='m' && buffer[i+6]=='o' && buffer[i+7]=='v') || (buffer[i+4]=='d' && buffer[i+5]=='c' && buffer[i+6]=='o' && buffer[i+7]=='m') || (buffer[i+4]=='c' && buffer[i+5]=='m' && buffer[i+6]=='v' && buffer[i+7]=='d') || (buffer[i+4]=='j' && buffer[i+5]=='p' && buffer[i+6]=='2' && buffer[i+7]=='h') ) ) { file_recovery->calculated_file_size+=atom_size; } else { log_warning("file_mov.c: unknown atom %c%c%c%c\n", buffer[i+4],buffer[i+5],buffer[i+6],buffer[i+7]); return 2; } } file_recovery->calculated_file_size=file_recovery->file_size+(buffer_size/2); return 1; } #endif