diff options
author | Christophe Grenier <[email protected]> | 2019-01-02 16:39:28 +0100 |
---|---|---|
committer | Christophe Grenier <[email protected]> | 2019-01-02 16:39:28 +0100 |
commit | 3ceea092e0b89a53c72cab40d222fed5d9ef1545 (patch) | |
tree | 7d3488fe99b2a5d685f26f33f53bfa9e8e81139c | |
parent | ef8c70e2efd522693d2e369af569f80aba9211b7 (diff) |
PhotoRec: recover Snagit .snag files
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/file_doc.c | 55 | ||||
-rw-r--r-- | src/file_doc.h | 30 | ||||
-rw-r--r-- | src/file_list.c | 2 | ||||
-rw-r--r-- | src/file_snag.c | 65 |
5 files changed, 131 insertions, 24 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index ad8554a4..52ea9602 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -291,6 +291,7 @@ file_C = filegen.c \ file_sit.c \ file_skd.c \ file_skp.c \ + file_snag.c \ file_sp3.c \ file_spe.c \ file_spf.c \ @@ -357,7 +358,7 @@ file_C = filegen.c \ file_zip.c \ file_zpr.c -file_H = ext2.h ext2_common.h filegen.h file_jpg.h file_gz.h file_sp3.h file_tar.h file_tiff.h file_txt.h ole.h pe.h suspend.h +file_H = ext2.h ext2_common.h filegen.h file_doc.h file_jpg.h file_gz.h file_sp3.h file_tar.h file_tiff.h file_txt.h ole.h pe.h suspend.h photorec_C = photorec.c phcfg.c addpart.c chgarch.c dir.c exfatp.c ext2grp.c ext2_dir.c ext2p.c fat_dir.c fatp.c file_found.c geometry.c ntfs_dir.c ntfsp.c pdisksel.c phcli.c poptions.c sessionp.c setdate.c dfxml.c diff --git a/src/file_doc.c b/src/file_doc.c index e73dc524..44517961 100644 --- a/src/file_doc.c +++ b/src/file_doc.c @@ -38,13 +38,14 @@ #include "log.h" #include "memmem.h" #include "setdate.h" +#include "file_doc.h" static void register_header_check_doc(file_stat_t *file_stat); static void file_check_doc(file_recovery_t *file_recovery); static int header_check_doc(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); static void file_rename_doc(file_recovery_t *file_recovery); -static uint32_t *OLE_load_FAT(FILE *IN, const struct OLE_HDR *header); -static uint32_t *OLE_load_MiniFAT(FILE *IN, const struct OLE_HDR *header, const uint32_t *fat, const unsigned int fat_entries); +static uint32_t *OLE_load_FAT(FILE *IN, const struct OLE_HDR *header, const uint64_t offset); +static uint32_t *OLE_load_MiniFAT(FILE *IN, const struct OLE_HDR *header, const uint32_t *fat, const unsigned int fat_entries, const uint64_t offset); const file_hint_t file_hint_doc= { .extension="doc", @@ -67,7 +68,7 @@ const char WilcomDesignInformationDDD[56]= 'D', '\0', 'D', '\0', 'D', '\0', '\0', '\0' }; -static void file_check_doc(file_recovery_t *file_recovery) +void file_check_doc_aux(file_recovery_t *file_recovery, const uint64_t offset) { unsigned char buffer_header[512]; uint64_t doc_file_size; @@ -76,9 +77,9 @@ static void file_check_doc(file_recovery_t *file_recovery) unsigned int freesect_count=0; const struct OLE_HDR *header=(const struct OLE_HDR*)&buffer_header; const uint64_t doc_file_size_org=file_recovery->file_size; - file_recovery->file_size=0; + file_recovery->file_size=offset; /*reads first sector including OLE header */ - if(my_fseek(file_recovery->handle, 0, SEEK_SET) < 0 || + if(my_fseek(file_recovery->handle, offset, SEEK_SET) < 0 || fread(&buffer_header, sizeof(buffer_header), 1, file_recovery->handle) != 1) return ; #ifdef DEBUG_OLE @@ -92,7 +93,7 @@ static void file_check_doc(file_recovery_t *file_recovery) le32(header->num_extra_FAT_blocks)>50 || le32(header->num_FAT_blocks)>109+le32(header->num_extra_FAT_blocks)*((1<<le16(header->uSectorShift))-1)) return ; - if((fat=OLE_load_FAT(file_recovery->handle, header))==NULL) + if((fat=OLE_load_FAT(file_recovery->handle, header, offset))==NULL) { #ifdef DEBUG_OLE log_info("OLE_load_FAT failed\n"); @@ -104,11 +105,12 @@ static void file_check_doc(file_recovery_t *file_recovery) i>0 && le32(fat[i])==0xFFFFFFFF; i--) freesect_count++; - doc_file_size=((1+(le32(header->num_FAT_blocks)<<le16(header->uSectorShift))/4-freesect_count)<<le16(header->uSectorShift)); + doc_file_size=offset + ((1+(le32(header->num_FAT_blocks)<<le16(header->uSectorShift))/4-freesect_count)<<le16(header->uSectorShift)); if(doc_file_size > doc_file_size_org) { #ifdef DEBUG_OLE - log_info("doc_file_size=(1+(%u<<%u)/4-%u)<<%u\n", + log_info("doc_file_size=%llu + (1+(%u<<%u)/4-%u)<<%u\n", + (unsigned long long)offset, le32(header->num_FAT_blocks), le16(header->uSectorShift), freesect_count, le16(header->uSectorShift)); log_info("doc_file_size %llu > doc_file_size_org %llu\n", @@ -143,7 +145,7 @@ static void file_check_doc(file_recovery_t *file_recovery) free(fat); return ; } - if(my_fseek(file_recovery->handle, (1+block)<<le16(header->uSectorShift), SEEK_SET)<0) + if(my_fseek(file_recovery->handle, offset + ((1+block)<<le16(header->uSectorShift)), SEEK_SET)<0) { #ifdef DEBUG_OLE log_info("fseek failed\n"); @@ -168,7 +170,8 @@ static void file_check_doc(file_recovery_t *file_recovery) sid<(1<<le16(header->uSectorShift))/sizeof(struct OLE_DIR) && dir_entry->type!=NO_ENTRY; sid++,dir_entry++) { - if(le32(dir_entry->start_block) > 0 && le32(dir_entry->size) > 0 && + if(offset + + le32(dir_entry->start_block) > 0 && le32(dir_entry->size) > 0 && ((le32(dir_entry->size) >= le32(header->miniSectorCutoff) && le32(dir_entry->start_block) > fat_entries) || le32(dir_entry->size) > doc_file_size)) @@ -189,6 +192,11 @@ static void file_check_doc(file_recovery_t *file_recovery) file_recovery->file_size=doc_file_size; } +static void file_check_doc(file_recovery_t *file_recovery) +{ + file_check_doc_aux(file_recovery, 0); +} + static const char *ole_get_file_extension(const unsigned char *buffer, const unsigned int buffer_size) { const struct OLE_HDR *header=(const struct OLE_HDR *)buffer; @@ -489,7 +497,7 @@ static int header_check_doc(const unsigned char *buffer, const unsigned int buff return 1; } -static uint32_t *OLE_load_FAT(FILE *IN, const struct OLE_HDR *header) +static uint32_t *OLE_load_FAT(FILE *IN, const struct OLE_HDR *header, const uint64_t offset) { uint32_t *fat; uint32_t *dif; @@ -504,7 +512,7 @@ static uint32_t *OLE_load_FAT(FILE *IN, const struct OLE_HDR *header) i<le32(header->num_extra_FAT_blocks) && block!=0xFFFFFFFF && block!=0xFFFFFFFE; i++, block=le32(dif[109+i*(((1<<le16(header->uSectorShift))/4)-1)])) { - if(my_fseek(IN, (1+block)<<le16(header->uSectorShift), SEEK_SET) < 0) + if(my_fseek(IN, offset + ((1+block)<<le16(header->uSectorShift)), SEEK_SET) < 0) { free(dif); return NULL; @@ -525,7 +533,7 @@ static uint32_t *OLE_load_FAT(FILE *IN, const struct OLE_HDR *header) j<le32(header->num_FAT_blocks); j++, data+=(1<<le16(header->uSectorShift))) { - if(my_fseek(IN, (1+le32(dif[j]))<<le16(header->uSectorShift), SEEK_SET)<0) + if(my_fseek(IN, offset + ((1+le32(dif[j]))<<le16(header->uSectorShift)), SEEK_SET)<0) { free(dif); free(fat); @@ -545,7 +553,7 @@ static uint32_t *OLE_load_FAT(FILE *IN, const struct OLE_HDR *header) static void *OLE_read_stream(FILE *IN, const uint32_t *fat, const unsigned int fat_entries, const unsigned int uSectorShift, - const unsigned int block_start, const unsigned int len) + const unsigned int block_start, const unsigned int len, const uint64_t offset) { unsigned char *dataPt; unsigned int block; @@ -560,7 +568,7 @@ static void *OLE_read_stream(FILE *IN, free(dataPt); return NULL; } - if(my_fseek(IN, (1+block)<<uSectorShift, SEEK_SET)<0) + if(my_fseek(IN, offset + ((1+block)<<uSectorShift), SEEK_SET)<0) { free(dataPt); return NULL; @@ -574,7 +582,7 @@ static void *OLE_read_stream(FILE *IN, return dataPt; } -static uint32_t *OLE_load_MiniFAT(FILE *IN, const struct OLE_HDR *header, const uint32_t *fat, const unsigned int fat_entries) +static uint32_t *OLE_load_MiniFAT(FILE *IN, const struct OLE_HDR *header, const uint32_t *fat, const unsigned int fat_entries, const uint64_t offset) { unsigned char*minifat_pos; uint32_t *minifat; @@ -587,7 +595,7 @@ static uint32_t *OLE_load_MiniFAT(FILE *IN, const struct OLE_HDR *header, const block=le32(header->MiniFat_block); for(i=0; i < le32(header->csectMiniFat) && block < fat_entries; i++) { - if(my_fseek(IN, ((uint64_t)1+block) << le16(header->uSectorShift), SEEK_SET) < 0) + if(my_fseek(IN, offset + (((uint64_t)1+block) << le16(header->uSectorShift)), SEEK_SET) < 0) { free(minifat); return NULL; @@ -794,7 +802,8 @@ static void *OLE_read_ministream(unsigned char *ministream, static void OLE_parse_summary(FILE *file, const uint32_t *fat, const unsigned int fat_entries, const struct OLE_HDR *header, const unsigned int ministream_block, const unsigned int ministream_size, - const unsigned int block, const unsigned int len, const char **ext, char **title, time_t *file_time) + const unsigned int block, const unsigned int len, const char **ext, char **title, time_t *file_time, + const uint64_t offset) { unsigned char *summary=NULL; if(len < 48 || len>1024*1024) @@ -806,11 +815,11 @@ static void OLE_parse_summary(FILE *file, const uint32_t *fat, const unsigned in const unsigned int mini_fat_entries=(le32(header->csectMiniFat) << le16(header->uSectorShift)) / 4; uint32_t *minifat; unsigned char *ministream; - if((minifat=OLE_load_MiniFAT(file, header, fat, fat_entries))==NULL) + if((minifat=OLE_load_MiniFAT(file, header, fat, fat_entries, offset))==NULL) return ; ministream=(unsigned char *)OLE_read_stream(file, fat, fat_entries, le16(header->uSectorShift), - ministream_block, ministream_size); + ministream_block, ministream_size, offset); if(ministream != NULL) { summary=(unsigned char*)OLE_read_ministream(ministream, @@ -824,7 +833,7 @@ static void OLE_parse_summary(FILE *file, const uint32_t *fat, const unsigned in else summary=(unsigned char *)OLE_read_stream(file, fat, fat_entries, le16(header->uSectorShift), - block, len); + block, len, offset); if(summary!=NULL) { OLE_parse_summary_aux(summary, len, ext, title, file_time); @@ -864,7 +873,7 @@ static void file_rename_doc(file_recovery_t *file_recovery) fclose(file); return ; } - if((fat=OLE_load_FAT(file, header))==NULL) + if((fat=OLE_load_FAT(file, header, 0))==NULL) { fclose(file); return ; @@ -1039,7 +1048,7 @@ static void file_rename_doc(file_recovery_t *file_recovery) OLE_parse_summary(file, fat, fat_entries, header, ministream_block, ministream_size, le32(dir_entry->start_block), le32(dir_entry->size), - &ext, &title, &file_time); + &ext, &title, &file_time, 0); } else if(memcmp(dir_entry->name,"P\0o\0w\0e\0r\0P\0o\0i\0n\0t\0 \0D\0o\0c\0u\0m\0e\0n\0t\0\0\0", 40)==0) ext="ppt"; diff --git a/src/file_doc.h b/src/file_doc.h new file mode 100644 index 00000000..05f0c07b --- /dev/null +++ b/src/file_doc.h @@ -0,0 +1,30 @@ +/* + + File: file_doc.h + + Copyright (C) 2018 Christophe GRENIER <[email protected]> + + 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 __cplusplus +extern "C" { +#endif + +void file_check_doc_aux(file_recovery_t *file_recovery, const uint64_t offset); + +#ifdef __cplusplus +} /* closing brace for extern "C" */ +#endif diff --git a/src/file_list.c b/src/file_list.c index d8b9a56b..61a1dd5a 100644 --- a/src/file_list.c +++ b/src/file_list.c @@ -294,6 +294,7 @@ extern const file_hint_t file_hint_sig; extern const file_hint_t file_hint_sit; extern const file_hint_t file_hint_skd; extern const file_hint_t file_hint_skp; +extern const file_hint_t file_hint_snag; extern const file_hint_t file_hint_snz; extern const file_hint_t file_hint_sp3; extern const file_hint_t file_hint_spe; @@ -628,6 +629,7 @@ file_enable_t list_file_enable[]= { .enable=0, .file_hint=&file_hint_sit }, { .enable=0, .file_hint=&file_hint_skd }, { .enable=0, .file_hint=&file_hint_skp }, + { .enable=0, .file_hint=&file_hint_snag }, { .enable=0, .file_hint=&file_hint_snz }, { .enable=0, .file_hint=&file_hint_sp3 }, { .enable=0, .file_hint=&file_hint_spe }, diff --git a/src/file_snag.c b/src/file_snag.c new file mode 100644 index 00000000..a8670778 --- /dev/null +++ b/src/file_snag.c @@ -0,0 +1,65 @@ +/* + + File: file_snag.c + + Copyright (C) 2018 Christophe GRENIER <[email protected]> + + 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 <config.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif +#include <stdio.h> +#include "types.h" +#include "filegen.h" +#include "file_doc.h" + +static void register_header_check_snag(file_stat_t *file_stat); + +const file_hint_t file_hint_snag= { + .extension="snag", + .description="Snagit", + .max_filesize=PHOTOREC_MAX_FILE_SIZE, + .recover=1, + .enable_by_default=1, + .register_header_check=®ister_header_check_snag +}; + +static void file_check_snag(file_recovery_t *file_recovery) +{ + file_check_doc_aux(file_recovery, 24); +} + +static int header_check_snag(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) +{ + reset_file_recovery(file_recovery_new); + file_recovery_new->extension=file_hint_snag.extension; + file_recovery_new->file_check=&file_check_snag; + file_recovery_new->min_filesize=24+512; + return 1; +} + +static void register_header_check_snag(file_stat_t *file_stat) +{ + static const unsigned char snag_header[8]= { + 0xcb, 'T' , 'S' , 'C' , 'S' , 'N' , 'A' , 'G' + }; + register_header_check(0, snag_header, sizeof(snag_header), &header_check_snag, file_stat); +} |