From cdb342b10bc97d97af4d8fcaa548451feb554552 Mon Sep 17 00:00:00 2001 From: Christophe Grenier Date: Fri, 12 Jun 2009 09:48:42 +0200 Subject: [PATCH] PhotoRec: extract time from JPEG (fix), better detect end of file --- src/file_jpg.c | 91 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 27 deletions(-) diff --git a/src/file_jpg.c b/src/file_jpg.c index 8dd653e8..71a3e24f 100644 --- a/src/file_jpg.c +++ b/src/file_jpg.c @@ -2,7 +2,7 @@ File: file_jpg.c - Copyright (C) 1998-2008 Christophe GRENIER + Copyright (C) 1998-2009 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 @@ -53,6 +53,7 @@ static int header_check_jpg(const unsigned char *buffer, const unsigned int buff static void file_check_jpg(file_recovery_t *file_recovery); static void jpg_check_structure(file_recovery_t *file_recovery, const unsigned int extract_thumb); static int data_check_jpg(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery); +static int data_check_jpg2(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery); const file_hint_t file_hint_jpg= { .extension="jpg", @@ -95,6 +96,7 @@ static int header_check_jpg(const unsigned char *buffer, const unsigned int buff memcmp(buffer, jpg_header_com, sizeof(jpg_header_com))==0) { unsigned int i=2; + time_t jpg_time=0; while(i<6*512 && i+4time=get_date_from_tiff_header((const TIFFHeader*)&buffer[i+0x0A], tiff_size); + jpg_time=get_date_from_tiff_header((const TIFFHeader*)&buffer[i+0x0A], tiff_size); } } else if((buffer[i+1]>=0xe0 && buffer[i+1]<=0xef) || @@ -126,6 +128,7 @@ static int header_check_jpg(const unsigned char *buffer, const unsigned int buff file_recovery_new->min_filesize=(i>288?i:288); file_recovery_new->data_check=&data_check_jpg; file_recovery_new->calculated_file_size=2; + file_recovery_new->time=jpg_time; return 1; } i+=2+(buffer[i+2]<<8)+buffer[i+3]; @@ -136,6 +139,7 @@ static int header_check_jpg(const unsigned char *buffer, const unsigned int buff file_recovery_new->min_filesize=i; file_recovery_new->data_check=&data_check_jpg; file_recovery_new->calculated_file_size=2; + file_recovery_new->time=jpg_time; return 1; } return 0; @@ -154,16 +158,13 @@ static void my_emit_message (j_common_ptr cinfo, int msg_level); static void my_output_message (j_common_ptr cinfo) { +#ifdef DEBUG_JPEG struct my_error_mgr *myerr = (struct my_error_mgr *) cinfo->err; -#ifdef DEBUG - { - char buffermsg[JMSG_LENGTH_MAX]; - /* Create the message */ - (*cinfo->err->format_message) (cinfo, buffermsg); - log_error("test_jpeg error %s\n",buffermsg); - } + char buffermsg[JMSG_LENGTH_MAX]; + /* Create the message */ + (*cinfo->err->format_message) (cinfo, buffermsg); + log_info("jpeg: %s\n", buffermsg); #endif - longjmp(myerr->setjmp_buffer, 1); } static void my_error_exit (j_common_ptr cinfo) @@ -390,33 +391,36 @@ static void file_check_jpg(file_recovery_t *file_recovery) static struct jpeg_decompress_struct cinfo; #endif file_recovery->file_size=0; - file_recovery->offset_error=0; -#if defined(HAVE_LIBJPEG) && defined(HAVE_JPEGLIB_H) -#else - /* Not accurate */ - jpeg_size=ftell(infile); + if(file_recovery->calculated_file_size==0) + file_recovery->offset_error=0; +#ifdef DEBUG_JPEG + log_info("%s %llu error at %llu\n", file_recovery->filename, + (long long unsigned)file_recovery->calculated_file_size, + (long long unsigned)file_recovery->offset_error); #endif + if(file_recovery->offset_error!=0) + return ; jpg_check_structure(file_recovery, 0); if(file_recovery->offset_error!=0) return ; #if defined(HAVE_LIBJPEG) && defined(HAVE_JPEGLIB_H) { JSAMPARRAY buffer; /* Output row buffer */ - int row_stride; /* physical row width in output buffer */ + unsigned int row_stride; /* physical row width in output buffer */ fseek(infile,0,SEEK_SET); cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.output_message = my_output_message; jerr.pub.error_exit = my_error_exit; jerr.pub.emit_message= my_emit_message; - // jerr.pub.emit_message = my_emit_message; +#ifdef DEBUG_JPEG + jerr.pub.trace_level= 3; +#endif /* Establish the setjmp return context for my_error_exit to use. */ if (setjmp(jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. * We need to clean up the JPEG object and return. */ - /* Not accurate */ - // jpeg_size=ftell(infile); my_source_mgr * src; src = (my_source_mgr *) cinfo.src; jpeg_size=src->file_size - src->pub.bytes_in_buffer; @@ -443,8 +447,9 @@ static void file_check_jpg(file_recovery_t *file_recovery) row_stride = cinfo.output_width * cinfo.output_components; buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); - while (cinfo.output_scanline < cinfo.output_height) { - (void) jpeg_read_scanlines(&cinfo, buffer, 1); + while (cinfo.output_scanline < cinfo.output_height) + { + (void)jpeg_read_scanlines(&cinfo, buffer, 1); } (void) jpeg_finish_decompress(&cinfo); { @@ -469,8 +474,13 @@ static void file_check_jpg(file_recovery_t *file_recovery) return; } #endif - file_recovery->file_size=jpeg_size; - file_search_footer(file_recovery, jpg_footer, sizeof(jpg_footer), 0); + if(file_recovery->calculated_file_size>0) + file_recovery->file_size=file_recovery->calculated_file_size; + else + { + file_recovery->file_size=jpeg_size; + file_search_footer(file_recovery, jpg_footer, sizeof(jpg_footer), 0); + } } static void jpg_check_structure(file_recovery_t *file_recovery, const unsigned int extract_thumb) @@ -511,11 +521,11 @@ static void jpg_check_structure(file_recovery_t *file_recovery, const unsigned i { const unsigned int thumb_offset=thumb_data-(const char*)buffer; const unsigned int thumb_size=ifbytecount-(const char*)tiff; - unsigned int j_old; if(thumb_offset < sizeof(buffer) && thumb_offset+thumb_size < sizeof(buffer)) { unsigned int j=thumb_offset+2; unsigned int thumb_sos_found=0; + unsigned int j_old; j_old=j; while(j+4calculated_file_size+=2+size; if(buffer[i+1]==0xda) /* SOS: Start Of Scan */ { - file_recovery->data_check=NULL; - file_recovery->calculated_file_size=0; - return 1; + file_recovery->data_check=&data_check_jpg2; + return data_check_jpg2(buffer, buffer_size, file_recovery); } } else @@ -588,3 +597,31 @@ static int data_check_jpg(const unsigned char *buffer, const unsigned int buffer return 1; } +static int data_check_jpg2(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery) +{ + while(file_recovery->calculated_file_size + buffer_size/2 >= file_recovery->file_size && + file_recovery->calculated_file_size < file_recovery->file_size + buffer_size/2) + { + const unsigned int i=file_recovery->calculated_file_size - file_recovery->file_size + buffer_size/2; + if(buffer[i-1]==0xFF) + { + if(buffer[i]==0xd9) + { + /* JPEG_EOI */ + file_recovery->calculated_file_size++; + return 2; + } + else if(buffer[i] >= 0xd0 && buffer[i] <= 0xd7) + { + /* JPEG_RST0 .. JPEG_RST7 markers */ + } + else if(buffer[i]!=0x00) + { + file_recovery->offset_error=file_recovery->calculated_file_size; + return 2; + } + } + file_recovery->calculated_file_size++; + } + return 1; +}