summaryrefslogtreecommitdiffstats
path: root/src/file_ra.c
diff options
context:
space:
mode:
authorChristophe Grenier <grenier@cgsecurity.org>2013-11-01 12:17:22 +0100
committerChristophe Grenier <grenier@cgsecurity.org>2013-11-01 12:17:22 +0100
commite75bc7d6f3ef8b9851262bdcae9cbe6470f1b1fa (patch)
tree1bdf3f4aa2fc9a652666148a737db07f17865c0e /src/file_ra.c
parent626e44b4b24698627942a4911f030555087094bf (diff)
PhotoRec: detect filesize for RealAudio3
Diffstat (limited to 'src/file_ra.c')
-rw-r--r--src/file_ra.c87
1 files changed, 63 insertions, 24 deletions
diff --git a/src/file_ra.c b/src/file_ra.c
index 76bc82c..d0182e2 100644
--- a/src/file_ra.c
+++ b/src/file_ra.c
@@ -28,11 +28,10 @@
#endif
#include <stdio.h>
#include "types.h"
+#include "common.h"
#include "filegen.h"
-
static void register_header_check_ra(file_stat_t *file_stat);
-static int header_check_ra(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 file_hint_t file_hint_ra= {
.extension="ra",
@@ -44,33 +43,73 @@ const file_hint_t file_hint_ra= {
.register_header_check=&register_header_check_ra
};
-static const unsigned char ra_header[4] = { '.', 'r', 'a', 0xfd};
+struct ra3_header {
+ char magic[4];
+ uint16_t version; /* 3 */
+ uint16_t header_size; /* not including first 8 bytes */
+ char unk1[10];
+ uint32_t data_size;
+ uint8_t title_length;
+ char title[0];
+} __attribute__ ((__packed__));
+
+struct ra4_header {
+ char magic[4];
+ uint16_t version; /* 4 */
+ uint16_t unused; /* always 0 */
+ char sign[4]; /* .ra4 */
+ uint32_t data_size;
+ uint16_t version2;
+ uint16_t header_size; /* not including the first 20 bytes ? */
+ uint16_t codec_flavor;
+ uint32_t codec_frame_size;
+ char unk1[12];
+ uint16_t sub_packet_h;
+ uint16_t frame_size;
+ uint16_t subpacket_size;
+ uint16_t unk2;
+ uint16_t samplerate;
+ uint16_t unk3;
+ uint16_t sample_size;
+ uint16_t channels;
+ char interleaver_ID_length; /* always 4 */
+ char interleaver_ID[4];
+ char FourCC_length; /* always 4 */
+ char FourCC_string[4];
+ char unk4[3];
+ uint8_t title_length;
+ char title[0];
+} __attribute__ ((__packed__));
-static void register_header_check_ra(file_stat_t *file_stat)
-{
- register_header_check(0, ra_header,sizeof(ra_header), &header_check_ra, file_stat);
-}
static int header_check_ra(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)
{
- if(memcmp(buffer,ra_header,sizeof(ra_header))==0)
- {
- if(buffer[4]==0x00 && buffer[5]==0x03)
- { /* V3 */
- reset_file_recovery(file_recovery_new);
- file_recovery_new->extension=file_hint_ra.extension;
- return 1;
- }
- else if(buffer[4]==0x00 && buffer[5]==0x04 && buffer[8]=='r' && buffer[9]=='a' && buffer[10]=='4')
- { /* V4 */
- reset_file_recovery(file_recovery_new);
- file_recovery_new->calculated_file_size=(buffer[11]<<24)+(buffer[12]<<16)+(buffer[13]<<8)+buffer[14]+40;
- file_recovery_new->extension=file_hint_ra.extension;
- file_recovery_new->data_check=&data_check_size;
- file_recovery_new->file_check=&file_check_size;
- return 1;
- }
+ if(buffer[4]==0x00 && buffer[5]==0x03)
+ { /* V3 */
+ const struct ra3_header *ra3=(const struct ra3_header *)buffer;
+ reset_file_recovery(file_recovery_new);
+ file_recovery_new->extension=file_hint_ra.extension;
+ file_recovery_new->calculated_file_size=8 + be16(ra3->header_size) + be32(ra3->data_size);
+ file_recovery_new->data_check=&data_check_size;
+ file_recovery_new->file_check=&file_check_size;
+ return 1;
+ }
+ else if(buffer[4]==0x00 && buffer[5]==0x04 &&
+ buffer[8]=='.' && buffer[9]=='r' && buffer[10]=='a' && buffer[11]=='4')
+ { /* V4 */
+ const struct ra4_header *ra4=(const struct ra4_header *)buffer;
+ reset_file_recovery(file_recovery_new);
+ file_recovery_new->extension=file_hint_ra.extension;
+ file_recovery_new->calculated_file_size=40 + be16(ra4->header_size) + be32(ra4->data_size);
+ file_recovery_new->data_check=&data_check_size;
+ file_recovery_new->file_check=&file_check_size;
+ return 1;
}
return 0;
}
+static void register_header_check_ra(file_stat_t *file_stat)
+{
+ static const unsigned char ra_header[4] = { '.', 'r', 'a', 0xfd};
+ register_header_check(0, ra_header,sizeof(ra_header), &header_check_ra, file_stat);
+}