PhotoRec: recover Quickbook qbb files based on OLE/Microsoft Compound Document file format

This commit is contained in:
Christophe Grenier 2010-04-27 08:14:44 +02:00
parent eaad54c249
commit 93e6e7884a

View file

@ -99,7 +99,7 @@ static void file_check_doc(file_recovery_t *file_recovery)
i>((le32(header->num_FAT_blocks)-1)<<le16(header->uSectorShift))/4 && le32(fat[i])==0xFFFFFFFF; i>((le32(header->num_FAT_blocks)-1)<<le16(header->uSectorShift))/4 && le32(fat[i])==0xFFFFFFFF;
i--) i--)
freesect_count++; freesect_count++;
doc_file_size=512+((le32(header->num_FAT_blocks)*128-freesect_count)<<le16(header->uSectorShift)); doc_file_size=512+(((le32(header->num_FAT_blocks)<<le16(header->uSectorShift))/4-freesect_count)<<le16(header->uSectorShift));
if(doc_file_size > file_recovery->file_size) if(doc_file_size > file_recovery->file_size)
{ {
free(fat); free(fat);
@ -304,9 +304,15 @@ static int header_check_doc(const unsigned char *buffer, const unsigned int buff
if(memcmp(buffer,doc_header,sizeof(doc_header))==0) if(memcmp(buffer,doc_header,sizeof(doc_header))==0)
{ {
const struct OLE_HDR *header=(const struct OLE_HDR *)buffer; const struct OLE_HDR *header=(const struct OLE_HDR *)buffer;
if(le16(header->reserved)!=0 || le32(header->reserved1)!=0 || le32(header->reserved2)!=0) if(le16(header->reserved)!=0 || le32(header->reserved1)!=0)
return 0; return 0;
if(le16(header->uMiniSectorShift)!=6 || le16(header->uSectorShift)!=9) /* qbb file have reserved2=4 */
if(le32(header->reserved2)!=0 && le32(header->reserved2)!=4)
return 0;
if(le16(header->uMiniSectorShift)!=6)
return 0;
/* qbb file have uSectorShift=12 */
if(le16(header->uSectorShift)!=9 && le16(header->uSectorShift)!=12)
return 0; return 0;
/* /*
num_FAT_blocks=109+num_extra_FAT_blocks*(512-1); num_FAT_blocks=109+num_extra_FAT_blocks*(512-1);
@ -411,30 +417,33 @@ static uint32_t *OLE_load_FAT(FILE *IN, const struct OLE_HDR *header)
memcpy(dif,(header+1),109*4); memcpy(dif,(header+1),109*4);
if(le32(header->num_extra_FAT_blocks)>0) if(le32(header->num_extra_FAT_blocks)>0)
{ /* Load DIF*/ { /* Load DIF*/
uint32_t *dif_pos=dif+109;
unsigned long int i; unsigned long int i;
unsigned long int block=le32(header->FAT_next_block); unsigned long int block;
for(i=0;i<le32(header->num_extra_FAT_blocks) && block!=0xFFFFFFFF && block!=0xFFFFFFFE;i++) unsigned char *data=(unsigned char*)&dif[109];
for(i=0, block=le32(header->FAT_next_block);
i<le32(header->num_extra_FAT_blocks) && block!=0xFFFFFFFF && block!=0xFFFFFFFE;
i++, block=le32(dif[109+i*(((1<<le16(header->uSectorShift))/4)-1)]))
{ {
// log_trace("pointeur:0x%x\n",block);
if(fseek(IN, 512+(block<<le16(header->uSectorShift)), SEEK_SET) < 0) if(fseek(IN, 512+(block<<le16(header->uSectorShift)), SEEK_SET) < 0)
{ {
free(dif); free(dif);
return NULL; return NULL;
} }
if(fread(dif_pos, (i<le32(header->num_extra_FAT_blocks)?128:(le32(header->num_FAT_blocks)-109)%127),4,IN)!=4) if(fread(data, 1<<le16(header->uSectorShift), 1, IN)!=1)
{ {
free(dif); free(dif);
return NULL; return NULL;
} }
dif_pos+=(((1<<le16(header->uSectorShift))/4)-1); data+=(1<<le16(header->uSectorShift))-4;
block=le32(dif[109+i*(((1<<le16(header->uSectorShift))/4)-1)+127]);
} }
} }
fat=(uint32_t*)MALLOC(le32(header->num_FAT_blocks)<<le16(header->uSectorShift)); fat=(uint32_t*)MALLOC(le32(header->num_FAT_blocks)<<le16(header->uSectorShift));
{ /* Load FAT */ { /* Load FAT */
unsigned long int j; unsigned long int j;
for(j=0; j<le32(header->num_FAT_blocks); j++) unsigned char *data=(unsigned char*)fat;
for(j=0, data=(unsigned char*)fat;
j<le32(header->num_FAT_blocks);
j++, data+=(1<<le16(header->uSectorShift)))
{ {
if(fseek(IN,512+(le32(dif[j])<<le16(header->uSectorShift)),SEEK_SET)<0) if(fseek(IN,512+(le32(dif[j])<<le16(header->uSectorShift)),SEEK_SET)<0)
{ {
@ -442,7 +451,7 @@ static uint32_t *OLE_load_FAT(FILE *IN, const struct OLE_HDR *header)
free(fat); free(fat);
return NULL; return NULL;
} }
if(fread(fat+((j<<le16(header->uSectorShift))/4),(1<<le16(header->uSectorShift)),1,IN)!=1) if(fread(data, (1<<le16(header->uSectorShift)), 1, IN)!=1)
{ {
free(dif); free(dif);
free(fat); free(fat);
@ -714,6 +723,12 @@ static void file_rename_doc(const char *old_filename)
fclose(file); fclose(file);
return ; return ;
} }
if(le16(header->uSectorShift)==12)
{
fclose(file);
file_rename(old_filename, NULL, 0, 0, "qbb", 1);
return ;
}
if((fat=OLE_load_FAT(file, header))==NULL) if((fat=OLE_load_FAT(file, header))==NULL)
{ {
fclose(file); fclose(file);
@ -764,8 +779,10 @@ static void file_rename_doc(const char *old_filename)
ministream_size=le32(dir_entry->size); ministream_size=le32(dir_entry->size);
} }
for(sid=0, dir_entry=dir_entries; for(sid=0, dir_entry=dir_entries;
sid<(1<<le16(header->uSectorShift))/sizeof(struct OLE_DIR) && dir_entry->type!=NO_ENTRY; sid<(1<<le16(header->uSectorShift))/sizeof(struct OLE_DIR);
sid++,dir_entry++) sid++,dir_entry++)
{
if(dir_entry->type!=NO_ENTRY)
{ {
const char SummaryInformation[38]= const char SummaryInformation[38]=
{ {
@ -863,6 +880,7 @@ static void file_rename_doc(const char *old_filename)
ext="qpw"; ext="qpw";
} }
} }
}
free(dir_entries); free(dir_entries);
} }
} }