Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 29 additions & 4 deletions src/file_jpg.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,29 @@ const file_hint_t file_hint_jpg= {
.register_header_check=&register_header_check_jpg
};

static int jpg_marker_is_sof(const unsigned char marker)
{
switch(marker)
{
case 0xc0:
case 0xc1:
case 0xc2:
case 0xc3:
case 0xc5:
case 0xc6:
case 0xc7:
case 0xc9:
case 0xca:
case 0xcb:
case 0xcd:
case 0xce:
case 0xcf:
return 1;
default:
return 0;
}
}

/*@
@ requires PHOTOREC_MAX_BLOCKSIZE >= buffer_size;
@ requires \valid_read(buffer + (0 .. buffer_size-1));
Expand Down Expand Up @@ -120,7 +143,7 @@ static void jpg_get_size(const unsigned char *buffer, const unsigned int buffer_
/*@ assert 0 <= ((buffer[i+2]<<8) | buffer[i+3]) <= 0xffff; */
const unsigned int size=((unsigned int)buffer[i+2]<<8)|buffer[i+3];
/*@ assert size <= 0xffff; */
if(buffer[i+1]==0xc0) /* SOF0 */
if(jpg_marker_is_sof(buffer[i+1])!=0)
{
/*@ assert 0<= (buffer[i+5]<<8) <= 0xff00; */
/*@ assert 0 <= ((buffer[i+5]<<8) | buffer[i+6]) <= 0xffff; */
Expand Down Expand Up @@ -884,6 +907,8 @@ static int header_check_jpg(const unsigned char *buffer, const unsigned int buff
/*@ assert valid_header_check_param(buffer, buffer_size, safe_header_only, file_recovery, file_recovery_new); */
unsigned int i=2;
time_t jpg_time=0;
unsigned int width=0;
unsigned int height=0;
/*@
@ loop invariant \valid_read(buffer+(0..buffer_size-1));
@ loop invariant \initialized(buffer+(0..buffer_size-1));
Expand Down Expand Up @@ -925,6 +950,7 @@ static int header_check_jpg(const unsigned char *buffer, const unsigned int buff
if(i+1 < buffer_size && buffer[i+1]!=0xda)
return 0;
}
jpg_get_size(buffer, buffer_size, &height, &width);
if(file_recovery->file_stat!=NULL &&
file_recovery->file_check!=NULL)
{
Expand All @@ -940,9 +966,6 @@ static int header_check_jpg(const unsigned char *buffer, const unsigned int buff
0x00, 0x48, 0x00, 0x00, 0xff, 0xfe, 0x00
};

unsigned int width=0;
unsigned int height=0;
jpg_get_size(buffer, buffer_size, &height, &width);
#if !defined(MAIN_jpg) && !defined(SINGLE_FORMAT)
if(file_recovery->file_stat->file_hint==&file_hint_indd)
{
Expand Down Expand Up @@ -1047,6 +1070,8 @@ static int header_check_jpg(const unsigned char *buffer, const unsigned int buff
}
}
reset_file_recovery(file_recovery_new);
file_recovery_new->image_width=width;
file_recovery_new->image_height=height;
file_recovery_new->min_filesize=i;
file_recovery_new->calculated_file_size=0;
file_recovery_new->time=jpg_time;
Expand Down
12 changes: 11 additions & 1 deletion src/file_png.c
Original file line number Diff line number Diff line change
Expand Up @@ -322,14 +322,22 @@ static int header_check_mng(const unsigned char *buffer, const unsigned int buff
@*/
static int header_check_png(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)
{
const struct png_ihdr *ihdr=(const struct png_ihdr *)&buffer[16];
unsigned int width=0;
unsigned int height=0;
if( !((isupper(buffer[8+4]) || islower(buffer[8+4])) &&
(isupper(buffer[8+5]) || islower(buffer[8+5])) &&
(isupper(buffer[8+6]) || islower(buffer[8+6])) &&
(isupper(buffer[8+7]) || islower(buffer[8+7]))))
return 0;
if(memcmp(&buffer[8+4], "IHDR", 4) == 0 &&
png_check_ihdr((const struct png_ihdr *)&buffer[16])==0)
png_check_ihdr(ihdr)==0)
return 0;
if(memcmp(&buffer[8+4], "IHDR", 4) == 0)
{
width=be32(ihdr->width);
height=be32(ihdr->height);
}
#if !defined(SINGLE_FORMAT)
/* SolidWorks files contain a png */
if(file_recovery->file_stat!=NULL &&
Expand All @@ -340,6 +348,8 @@ static int header_check_png(const unsigned char *buffer, const unsigned int buff
}
#endif
reset_file_recovery(file_recovery_new);
file_recovery_new->image_width=width;
file_recovery_new->image_height=height;
file_recovery_new->extension=file_hint_png.extension;
file_recovery_new->min_filesize=16;
if(file_recovery_new->blocksize < 8)
Expand Down
2 changes: 2 additions & 0 deletions src/filegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,8 @@ void reset_file_recovery(file_recovery_t *file_recovery)
file_recovery->offset_ok=0;
file_recovery->checkpoint_status=0;
file_recovery->checkpoint_offset=0;
file_recovery->image_width=0;
file_recovery->image_height=0;
file_recovery->flags=0;
file_recovery->extra=0;
file_recovery->data_check_tmp=0;
Expand Down
4 changes: 4 additions & 0 deletions src/filegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ struct file_recovery_struct
uint64_t checkpoint_offset;
int checkpoint_status; /* 0=suspend at offset_checkpoint if offset_checkpoint>0, 1=resume at offset_checkpoint */
unsigned int blocksize;
unsigned int image_width;
unsigned int image_height;
unsigned int flags;
unsigned int data_check_tmp;
};
Expand Down Expand Up @@ -164,6 +166,8 @@ typedef struct
\initialized(&file_recovery->calculated_file_size) &&
\initialized(&file_recovery->file_check) &&
\initialized(&file_recovery->file_size) &&
\initialized(&file_recovery->image_height) &&
\initialized(&file_recovery->image_width) &&
\initialized(&file_recovery->min_filesize) &&
\initialized(&file_recovery->time)
);
Expand Down
4 changes: 4 additions & 0 deletions src/phmain.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,10 @@ int main( int argc, char **argv )
.expert=0,
.lowmem=0,
.verbose=0,
.image_min_width=0,
.image_min_height=0,
.image_min_pixels=0,
.image_min_filesize=0,
.list_file_format=array_file_enable
};
struct ph_param params;
Expand Down
4 changes: 4 additions & 0 deletions src/photorec.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ struct ph_options
unsigned int expert;
unsigned int lowmem;
int verbose;
unsigned int image_min_width;
unsigned int image_min_height;
uint64_t image_min_pixels;
uint64_t image_min_filesize;
file_enable_t *list_file_format;
};

Expand Down
37 changes: 37 additions & 0 deletions src/photorec_check_header.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,36 @@ static pstatus_t photorec_header_found(const file_recovery_t *file_recovery_new,
return PSTATUS_OK;
}

inline static int photorec_image_filter(file_recovery_t *file_recovery_new, const struct ph_options *options)
{
const int filter_dimensions=(options->image_min_width > 0 || options->image_min_height > 0 || options->image_min_pixels > 0);
const int filter_filesize=(options->image_min_filesize > 0);
int is_filtered_image=0;
if(filter_dimensions==0 && filter_filesize==0)
return 1;
if(file_recovery_new->extension==NULL)
return 1;
if(strcmp(file_recovery_new->extension, "jpg")==0 || strcmp(file_recovery_new->extension, "png")==0)
is_filtered_image=1;
if(is_filtered_image==0 && (file_recovery_new->image_width==0 || file_recovery_new->image_height==0))
return 1;
if(filter_dimensions!=0)
{
const uint64_t pixels=(uint64_t)file_recovery_new->image_width * (uint64_t)file_recovery_new->image_height;
if(file_recovery_new->image_width==0 || file_recovery_new->image_height==0)
return 0;
if(options->image_min_width > 0 && file_recovery_new->image_width < options->image_min_width)
return 0;
if(options->image_min_height > 0 && file_recovery_new->image_height < options->image_min_height)
return 0;
if(options->image_min_pixels > 0 && pixels < options->image_min_pixels)
return 0;
}
if(filter_filesize!=0 && file_recovery_new->min_filesize < options->image_min_filesize)
file_recovery_new->min_filesize=options->image_min_filesize;
return 1;
}

/*@
@ requires \valid(file_recovery);
@ requires valid_file_recovery(file_recovery);
Expand Down Expand Up @@ -208,6 +238,13 @@ inline static pstatus_t photorec_check_header(file_recovery_t *file_recovery, st
file_check->header_check(buffer, read_size, 0, file_recovery, &file_recovery_new)!=0)
{
file_recovery_new.file_stat=file_check->file_stat;
if(photorec_image_filter(&file_recovery_new, options)==0)
{
file_recovery_new.file_stat=NULL;
file_recovery_new.blocksize=blocksize;
file_recovery_new.location.start=offset;
continue;
}
/*@ assert valid_file_recovery(&file_recovery_new); */
return photorec_header_found(&file_recovery_new, file_recovery, params, options, list_search_space, buffer, file_recovered, offset);
}
Expand Down
26 changes: 24 additions & 2 deletions src/phrecn.c
Original file line number Diff line number Diff line change
Expand Up @@ -504,14 +504,16 @@ int photorec(struct ph_param *params, const struct ph_options *options, alloc_da
#ifdef HAVE_NCURSES
void interface_options_photorec_ncurses(struct ph_options *options)
{
unsigned int menu = 5;
unsigned int menu = 6;
char image_options[128];
struct MenuItem menuOptions[]=
{
{ 'P', NULL, "Check JPG files" },
{ 'K',NULL,"Keep corrupted files"},
{ 'S',NULL,"Try to skip indirect block"},
{ 'E',NULL,"Provide additional controls"},
{ 'L',NULL,"Low memory"},
{ 'I',NULL,"Set minimum dimensions or size for recovered images"},
{ 'Q',"Quit","Return to main menu"},
{ 0, NULL, NULL }
};
Expand All @@ -535,8 +537,19 @@ void interface_options_photorec_ncurses(struct ph_options *options)
menuOptions[2].name=options->mode_ext2?"ext2/ext3 mode: Yes":"ext2/ext3 mode : No";
menuOptions[3].name=options->expert?"Expert mode : Yes":"Expert mode : No";
menuOptions[4].name=options->lowmem?"Low memory: Yes":"Low memory: No";
if(options->image_min_width==0 && options->image_min_height==0 &&
options->image_min_pixels==0 && options->image_min_filesize==0)
menuOptions[5].name="Image minimums : Off";
else
{
snprintf(image_options, sizeof(image_options), "Image minimums : %ux%u %llu px %llu bytes",
options->image_min_width, options->image_min_height,
(long long unsigned)options->image_min_pixels,
(long long unsigned)options->image_min_filesize);
menuOptions[5].name=image_options;
}
aff_copy(stdscr);
car=wmenuSelect_ext(stdscr, 23, INTER_OPTION_Y, INTER_OPTION_X, menuOptions, 0, "PKELQ", MENU_VERT|MENU_VERT_ARROW2VALID, &menu,&real_key);
car=wmenuSelect_ext(stdscr, 23, INTER_OPTION_Y, INTER_OPTION_X, menuOptions, 0, "PKSELIQ", MENU_VERT|MENU_VERT_ARROW2VALID, &menu,&real_key);
switch(car)
{
case 'p':
Expand All @@ -562,6 +575,15 @@ void interface_options_photorec_ncurses(struct ph_options *options)
case 'L':
options->lowmem=!options->lowmem;
break;
case 'i':
case 'I':
aff_copy(stdscr);
wmove(stdscr, INTER_OPTION_Y, INTER_OPTION_X);
options->image_min_width=(unsigned int)ask_number(options->image_min_width, 0, 4294967295ULL, "Minimum image width in pixels ");
options->image_min_height=(unsigned int)ask_number(options->image_min_height, 0, 4294967295ULL, "Minimum image height in pixels ");
options->image_min_pixels=ask_number(options->image_min_pixels, 0, 0, "Minimum image width*height in pixels ");
options->image_min_filesize=ask_number(options->image_min_filesize, 0, 0, "Minimum image file size in bytes ");
break;
case key_ESC:
case 'q':
case 'Q':
Expand Down
33 changes: 33 additions & 0 deletions src/poptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@
#include "log.h"
#include "poptions.h"

static unsigned int get_image_dimension_from_command(char **current_cmd)
{
const uint64_t value=get_int_from_command(current_cmd);
return (value > 4294967295ULL ? 4294967295U : (unsigned int)value);
}

void interface_options_photorec_cli(struct ph_options *options, char **current_cmd)
{
if(*current_cmd==NULL)
Expand All @@ -46,6 +52,8 @@ void interface_options_photorec_cli(struct ph_options *options, char **current_c
@ loop assigns *current_cmd;
@ loop assigns options->paranoid, options->keep_corrupted_file, options->mode_ext2;
@ loop assigns options->expert, options->lowmem;
@ loop assigns options->image_min_width, options->image_min_height;
@ loop assigns options->image_min_pixels, options->image_min_filesize;
@*/
while(1)
{
Expand Down Expand Up @@ -87,6 +95,26 @@ void interface_options_photorec_cli(struct ph_options *options, char **current_c
{
options->lowmem=1;
}
else if(check_command(current_cmd,"image_min_width",15)==0)
{
skip_comma_in_command(current_cmd);
options->image_min_width=get_image_dimension_from_command(current_cmd);
}
else if(check_command(current_cmd,"image_min_height",16)==0)
{
skip_comma_in_command(current_cmd);
options->image_min_height=get_image_dimension_from_command(current_cmd);
}
else if(check_command(current_cmd,"image_min_pixels",16)==0)
{
skip_comma_in_command(current_cmd);
options->image_min_pixels=get_int_from_command(current_cmd);
}
else if(check_command(current_cmd,"image_min_filesize",18)==0)
{
skip_comma_in_command(current_cmd);
options->image_min_filesize=get_int_from_command(current_cmd);
}
else
{
#ifndef DISABLED_FOR_FRAMAC
Expand All @@ -108,4 +136,9 @@ void interface_options_photorec_log(const struct ph_options *options)
options->mode_ext2?"Yes":"No",
options->expert?"Yes":"No",
options->lowmem?"Yes":"No");
log_info(" Image minimum width : %u\n Image minimum height : %u\n Image minimum pixels : %llu\n Image minimum filesize : %llu\n",
options->image_min_width,
options->image_min_height,
(long long unsigned)options->image_min_pixels,
(long long unsigned)options->image_min_filesize);
}
4 changes: 4 additions & 0 deletions src/qphotorec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ QPhotorec::QPhotorec(QWidget *my_parent) : QWidget(my_parent)
options->expert=0;
options->lowmem=0;
options->verbose=0;
options->image_min_width=0;
options->image_min_height=0;
options->image_min_pixels=0;
options->image_min_filesize=0;
options->list_file_format=array_file_enable;
reset_array_file_enable(options->list_file_format);

Expand Down
8 changes: 8 additions & 0 deletions src/sessionp.c
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,14 @@ int session_save(const alloc_data_t *list_free_space, const struct ph_param *par
fprintf(f_session, "expert,");
if(options->lowmem>0)
fprintf(f_session, "lowmem,");
if(options->image_min_width>0)
fprintf(f_session, "image_min_width,%u,", options->image_min_width);
if(options->image_min_height>0)
fprintf(f_session, "image_min_height,%u,", options->image_min_height);
if(options->image_min_pixels>0)
fprintf(f_session, "image_min_pixels,%llu,", (long long unsigned)options->image_min_pixels);
if(options->image_min_filesize>0)
fprintf(f_session, "image_min_filesize,%llu,", (long long unsigned)options->image_min_filesize);
/* Save options - End */
if(params->carve_free_space_only>0)
fprintf(f_session,"freespace,");
Expand Down