1 // This file is part of Deark.
2 // Copyright (C) 2019 Jason Summers
3 // See the file COPYING for terms of use.
7 #include <deark-config.h>
8 #include <deark-private.h>
9 DE_DECLARE_MODULE(de_module_rm
);
11 #define CODE_CONT 0x434f4e54U
12 #define CODE_MDPR 0x4d445052U
13 #define CODE_PROP 0x50524f50U
16 struct de_fourcc chunk4cc
;
23 typedef struct localctx_struct
{
27 static void read_chunk_version_p(deark
*c
, lctx
*d
, struct chunkinfo
*ci
, i64
*ppos
)
29 ci
->version
= (unsigned int)de_getu16be_p(ppos
);
30 de_dbg(c
, "object version: %u", ci
->version
);
33 static void do_chunk_PROP(deark
*c
, lctx
*d
, struct chunkinfo
*ci
)
38 read_chunk_version_p(c
, d
, ci
, &pos
);
39 if(ci
->version
!=0 || ci
->dlen
<42) goto done
;
41 pos
+= 7*4; // TODO: other fields
43 n
= de_getu32be_p(&pos
);
44 de_dbg(c
, "index offset: %"I64_FMT
, n
);
45 n
= de_getu32be_p(&pos
);
46 de_dbg(c
, "data offset: %"I64_FMT
, n
);
47 n
= de_getu16be_p(&pos
);
48 de_dbg(c
, "num streams: %d", (int)n
);
49 n
= de_getu16be_p(&pos
);
50 de_dbg(c
, "flags: 0x%04x", (unsigned int)n
);
55 static void do_chunk_CONT(deark
*c
, lctx
*d
, struct chunkinfo
*ci
)
58 de_ucstring
*s
= NULL
;
61 read_chunk_version_p(c
, d
, ci
, &pos
);
62 if(ci
->version
!= 0) goto done
;
64 s
= ucstring_create(c
);
65 slen
= de_getu16be_p(&pos
);
66 dbuf_read_to_ucstring(c
->infile
, pos
, slen
, s
, 0, d
->input_encoding
);
67 de_dbg(c
, "title: \"%s\"", ucstring_getpsz_d(s
));
71 slen
= de_getu16be_p(&pos
);
72 dbuf_read_to_ucstring(c
->infile
, pos
, slen
, s
, 0, d
->input_encoding
);
73 de_dbg(c
, "author: \"%s\"", ucstring_getpsz_d(s
));
77 slen
= de_getu16be_p(&pos
);
78 dbuf_read_to_ucstring(c
->infile
, pos
, slen
, s
, 0, d
->input_encoding
);
79 de_dbg(c
, "copyright: \"%s\"", ucstring_getpsz_d(s
));
86 static void do_chunk_MDPR(deark
*c
, lctx
*d
, struct chunkinfo
*ci
)
89 de_ucstring
*s
= NULL
;
93 read_chunk_version_p(c
, d
, ci
, &pos
);
94 if(ci
->version
!= 0) goto done
;
96 n
= de_getu16be_p(&pos
);
97 de_dbg(c
, "stream number: %d", (int)n
);
99 pos
+= 7*4; // TODO: other fields
101 slen
= (i64
)de_getbyte_p(&pos
);
102 s
= ucstring_create(c
);
103 dbuf_read_to_ucstring(c
->infile
, pos
, slen
, s
, 0, DE_ENCODING_ASCII
);
104 de_dbg(c
, "stream name: \"%s\"", ucstring_getpsz_d(s
));
107 slen
= (i64
)de_getbyte_p(&pos
);
109 dbuf_read_to_ucstring(c
->infile
, pos
, slen
, s
, 0, DE_ENCODING_ASCII
);
110 de_dbg(c
, "mime type: \"%s\"", ucstring_getpsz_d(s
));
113 if(pos
+4 > ci
->dpos
+ ci
->dlen
) goto done
;
114 n
= de_getu32be_p(&pos
);
115 if(n
== 0) goto done
;
116 de_dbg(c
, "type specific data at %"I64_FMT
", len=%"I64_FMT
, pos
, n
);
117 if(pos
+n
> ci
->dpos
+ ci
->dlen
) goto done
;
119 de_dbg_hexdump(c
, c
->infile
, pos
, n
, 256, NULL
, 0x1);
120 de_dbg_indent(c
, -1);
126 static int do_rm_chunk(deark
*c
, lctx
*d
, i64 pos1
, i64 maxlen
,
132 int hexdump_flag
= 0;
133 struct chunkinfo
*ci
= NULL
;
135 ci
= de_malloc(c
, sizeof(struct chunkinfo
));
137 dbuf_read_fourcc(c
->infile
, pos
, &ci
->chunk4cc
, 4, 0x0);
138 de_dbg(c
, "chunk type: '%s'", ci
->chunk4cc
.id_dbgstr
);
140 chunklen
= de_getu32be_p(&pos
);
141 de_dbg(c
, "chunk len: %"I64_FMT
, chunklen
);
142 if(chunklen
< 8) goto done
;
143 if(chunklen
> maxlen
) {
144 de_warn(c
, "Chunk at %"I64_FMT
" exceeds its parent's bounds", pos1
);
148 *bytes_consumed
= chunklen
;
152 ci
->dlen
= chunklen
- 8;
153 de_dbg(c
, "dpos: %"I64_FMT
", dlen: %"I64_FMT
, ci
->dpos
, ci
->dlen
);
155 switch(ci
->chunk4cc
.id
) {
157 do_chunk_CONT(c
, d
, ci
);
160 do_chunk_MDPR(c
, d
, ci
);
163 do_chunk_PROP(c
, d
, ci
);
169 if(hexdump_flag
&& c
->debug_level
>=2) {
170 de_dbg_hexdump(c
, c
->infile
, ci
->dpos
, ci
->dlen
, 256, NULL
, 0x1);
178 static int do_rm_chunk_sequence(deark
*c
, lctx
*d
, i64 pos1
, i64 len
)
184 i64 bytes_consumed
= 0;
186 if(pos
>= pos1
+len
) break;
187 de_dbg(c
, "chunk at %"I64_FMT
, pos
);
189 ret
= do_rm_chunk(c
, d
, pos
, pos1
+len
-pos
, &bytes_consumed
);
190 de_dbg_indent(c
, -1);
191 if((!ret
) || (bytes_consumed
<1)) goto done
;
192 pos
+= bytes_consumed
;
199 static void de_run_rm(deark
*c
, de_module_params
*mparams
)
203 d
= de_malloc(c
, sizeof(lctx
));
204 d
->input_encoding
= de_get_input_encoding(c
, NULL
, DE_ENCODING_WINDOWS1252
);
205 do_rm_chunk_sequence(c
, d
, 0, c
->infile
->len
);
209 static int de_identify_rm(deark
*c
)
211 if(!dbuf_memcmp(c
->infile
, 0, ".RMF\0", 5))
216 void de_module_rm(deark
*c
, struct deark_module_info
*mi
)
219 mi
->desc
= "RealMedia";
220 mi
->run_fn
= de_run_rm
;
221 mi
->identify_fn
= de_identify_rm
;