#define NEED_SWAP (cdf_bo.u == (uint32_t)0x01020304)
-#undef CDF_TOLE8
#define CDF_TOLE8(x) (NEED_SWAP ? cdf_tole8(x) : (uint64_t)(x))
-#undef CDF_TOLE4
#define CDF_TOLE4(x) (NEED_SWAP ? cdf_tole4(x) : (uint32_t)(x))
-#undef CDF_TOLE2
#define CDF_TOLE2(x) (NEED_SWAP ? cdf_tole2(x) : (uint16_t)(x))
/*
return rv;
}
-int
-cdf_need_swap(void)
-{
- return NEED_SWAP;
-}
-
#define CDF_UNPACK(a) \
(void)memcpy(&(a), &buf[len], sizeof(a)), len += sizeof(a)
#define CDF_UNPACKA(a) \
d->d_size = CDF_TOLE4(d->d_size);
}
+void
+cdf_swap_class(cdf_classid_t *d)
+{
+ d->cl_dword = CDF_TOLE4(d->cl_dword);
+ d->cl_word[0] = CDF_TOLE2(d->cl_word[0]);
+ d->cl_word[1] = CDF_TOLE2(d->cl_word[1]);
+}
+
void
cdf_unpack_dir(cdf_directory_t *d, char *buf)
{
CDF_UNPACK(d->d_size);
CDF_UNPACK(d->d_unused0);
}
+
int
cdf_read_header(int fd, cdf_header_t *h)
{
sst);
}
+int
+cdf_read_property_info(const cdf_stream_t *sst, uint32_t offs,
+ cdf_property_info_t **info, size_t *count, size_t *maxcount)
+{
+ const cdf_section_header_t *shp;
+ cdf_section_header_t sh;
+ const uint32_t *p, *q, *e;
+ int16_t s16;
+ int32_t s32;
+ uint32_t u32;
+ cdf_timestamp_t tp;
+ size_t i, len;
+ cdf_property_info_t *inp;
+
+ shp = (const void *)((const char *)sst->sst_tab + offs);
+ sh.sh_len = CDF_TOLE4(shp->sh_len);
+ sh.sh_properties = CDF_TOLE4(shp->sh_properties);
+ if (*maxcount) {
+ *maxcount += sh.sh_properties;
+ inp = realloc(*info, *maxcount * sizeof(*inp));
+ } else {
+ *maxcount = sh.sh_properties;
+ inp = malloc(*maxcount * sizeof(*inp));
+ }
+ if (inp == NULL)
+ return -1;
+ *info = inp;
+ inp += *count;
+ *count += sh.sh_properties;
+ p = (const void *)((const char *)sst->sst_tab + offs + sizeof(sh));
+ q = p + (sh.sh_properties << 1);
+ e = (const void *)(((const char *)shp) + sh.sh_len);
+ for (i = 0; i < sh.sh_properties; i++) {
+ inp[i].pi_id = CDF_TOLE4(p[i << 1]);
+ switch (inp[i].pi_type = CDF_TOLE4(q[0])) {
+ case CDF_SIGNED16:
+ (void)memcpy(&s16, &q[1], sizeof(s16));
+ inp[i].pi_s16 = CDF_TOLE2(s16);
+ len = 2;
+ break;
+ case CDF_SIGNED32:
+ (void)memcpy(&s32, &q[1], sizeof(s32));
+ inp[i].pi_s32 = CDF_TOLE4(s32);
+ len = 4;
+ break;
+ case CDF_UNSIGNED32:
+ (void)memcpy(&u32, &q[1], sizeof(u32));
+ inp[i].pi_u32 = CDF_TOLE4(u32);
+ len = 4;
+ break;
+ case CDF_LENGTH32_STRING:
+ inp[i].pi_str.s_len = CDF_TOLE4(q[1]);
+ inp[i].pi_str.s_buf = (const char *)(&q[2]);
+ len = 4 + CDF_TOLE4(q[1]);
+ break;
+ case CDF_FILETIME:
+ (void)memcpy(&tp, &q[1], sizeof(tp));
+ inp[i].pi_tp = CDF_TOLE8(tp);
+ len = 8;
+ break;
+ case CDF_CLIPBOARD:
+ printf("\n");
+ len = 4 + CDF_TOLE4(q[1]);
+ break;
+ default:
+ len = 4;
+ DPRINTF(("Don't know how to deal with %x\n",
+ CDF_TOLE4(q[0])));
+ free(*info);
+ return -1;
+ }
+ q++;
+ q = (const void *)(((const char *)q) +
+ CDF_ROUND(len, sizeof(*q)));
+ if (q > e) {
+ DPRINTF(("Ran of the end %p > %p\n", q, e));
+ free(*info);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int
+cdf_unpack_summary_info(const cdf_stream_t *sst, cdf_summary_info_header_t *ssi,
+ cdf_property_info_t **info, size_t *count)
+{
+ size_t i, maxcount;
+ const cdf_summary_info_header_t *si = sst->sst_tab;
+ const cdf_section_declaration_t *sd = (const void *)
+ ((const char *)sst->sst_tab + CDF_SECTION_DECLARATION_OFFSET);
+
+ ssi->si_byte_order = CDF_TOLE2(si->si_byte_order);
+ ssi->si_os_version = CDF_TOLE2(si->si_os_version);
+ ssi->si_os = CDF_TOLE2(si->si_os);
+ ssi->si_class = si->si_class;
+ cdf_swap_class(&ssi->si_class);
+ ssi->si_count = CDF_TOLE2(si->si_count);
+ *count = 0;
+ maxcount = 0;
+ for (i = 0; i < CDF_TOLE4(si->si_count); i++) {
+ if (cdf_read_property_info(sst, CDF_TOLE4(sd->sd_offset),
+ info, count, &maxcount) == -1)
+ return -1;
+ }
+ return 0;
+}
+
+
int
cdf_print_classid(char *buf, size_t buflen, const cdf_classid_t *id)
}
void
-cdf_dump_section_info(const cdf_stream_t *sst, uint32_t offs)
+cdf_dump_property_info(const cdf_property_info_t *info, size_t count)
{
- const cdf_section_header_t *shp;
- cdf_section_header_t sh;
- const uint32_t *p, *q, *e;
- size_t i, len;
- uint32_t u32;
- int32_t s32;
- int16_t s16;
cdf_timestamp_t tp;
struct timespec ts;
char buf[64];
+ size_t i;
- shp = (const void *)((const char *)sst->sst_tab + offs);
- sh.sh_len = CDF_TOLE4(shp->sh_len);
- sh.sh_properties = CDF_TOLE4(shp->sh_properties);
- printf("Length %d, Properties %d\n", sh.sh_len, sh.sh_properties);
- p = (const void *)((const char *)sst->sst_tab + offs + sizeof(sh));
- q = p + (sh.sh_properties << 1);
- e = (const void *)(((const char *)shp) + sh.sh_len);
- for (i = 0; i < sh.sh_properties; i++) {
- cdf_print_property_name(buf, sizeof(buf), CDF_TOLE4(p[i << 1]));
+ for (i = 0; i < count; i++) {
+ cdf_print_property_name(buf, sizeof(buf), info[i].pi_id);
printf("%zu) %s: ", i, buf);
- switch (CDF_TOLE4(q[0])) {
+ switch (info[i].pi_type) {
case CDF_SIGNED16:
- (void)memcpy(&s16, &q[1], sizeof(s16));
- printf("signed 16 [%hd]\n", CDF_TOLE2(s16));
- len = 2;
+ printf("signed 16 [%hd]\n", info[i].pi_s16);
break;
case CDF_SIGNED32:
- (void)memcpy(&s32, &q[1], sizeof(s32));
- printf("signed 32 [%d]\n", CDF_TOLE4(s32));
- len = 4;
+ printf("signed 32 [%d]\n", info[i].pi_s32);
break;
case CDF_UNSIGNED32:
- (void)memcpy(&u32, &q[1], sizeof(u32));
- printf("unsigned 32 [%u]\n", CDF_TOLE4(u32));
- len = 4;
+ printf("unsigned 32 [%u]\n", info[i].pi_u32);
break;
case CDF_LENGTH32_STRING:
- printf("string %u [%.*s]\n", CDF_TOLE4(q[1]), CDF_TOLE4(q[1]),
- (const char *)(&q[2]));
- len = 4 + CDF_TOLE4(q[1]);
+ printf("string %u [%.*s]\n", info[i].pi_str.s_len,
+ info[i].pi_str.s_len, info[i].pi_str.s_buf);
break;
case CDF_FILETIME:
- (void)memcpy(&tp, &q[1], sizeof(tp));
- tp = CDF_TOLE8(tp);
+ tp = info[i].pi_tp;
if (tp < 1000000000000000LL) {
cdf_print_elapsed_time(buf, sizeof(buf), tp);
printf("timestamp %s\n", buf);
cdf_timestamp_to_timespec(&ts, tp);
printf("timestamp %s", ctime(&ts.tv_sec));
}
- len = 8;
break;
case CDF_CLIPBOARD:
- printf("\n");
- len = 4 + CDF_TOLE4(q[1]);
+ printf("CLIPBOARD %u\n", info[i].pi_u32);
break;
default:
- len = 4;
DPRINTF(("Don't know how to deal with %x\n",
- CDF_TOLE4(q[0])));
+ info[i].pi_type));
break;
}
- q++;
- q = (const void *)(((const char *)q) +
- CDF_ROUND(len, sizeof(*q)));
- if (q > e) {
- DPRINTF(("Ran of the end %p > %p\n", q, e));
- return;
- }
}
}
-
void
cdf_dump_summary_info(const cdf_header_t *h, const cdf_stream_t *sst)
{
char buf[128];
- size_t i;
- const cdf_summary_info_header_t *si = sst->sst_tab;
- const cdf_section_declaration_t *sd = (const void *)
- ((const char *)sst->sst_tab + CDF_SECTION_DECLARATION_OFFSET);
+ cdf_summary_info_header_t ssi;
+ cdf_property_info_t *info;
+ size_t i, count;
(void)&h;
- printf("Endian: %x\n", si->si_byte_order);
- printf("Os Version %d.%d\n", si->si_os_version & 0xff,
- si->si_os_version >> 8);
- printf("Os %d\n", si->si_os);
- cdf_print_classid(buf, sizeof(buf), &si->si_class);
+ if (cdf_unpack_summary_info(h, sst, &ssi, &info, &count) == -1)
+ return;
+ printf("Endian: %x\n", ssi.si_byte_order);
+ printf("Os Version %d.%d\n", ssi.si_os_version & 0xff,
+ ssi.si_os_version >> 8);
+ printf("Os %d\n", ssi.si_os);
+ cdf_print_classid(buf, sizeof(buf), &ssi.si_class);
printf("Class %s\n", buf);
- printf("Count %d\n", CDF_TOLE4(si->si_count));
- for (i = 0; i < CDF_TOLE4(si->si_count); i++) {
- cdf_print_classid(buf, sizeof(buf), &sd->sd_class);
- printf("Section %zu: %s %x\n", i, buf,
- CDF_TOLE4(sd->sd_offset));
- cdf_dump_section_info(sst, CDF_TOLE4(sd->sd_offset));
- }
+ printf("Count %d\n", ssi.si_count);
+ cdf_dump_property_info(info, count);
+ free(info);
}
+
#endif
#ifdef TEST
uint32_t sh_properties;
} cdf_section_header_t;
+typedef struct {
+ uint32_t pi_id;
+ uint32_t pi_type;
+ union {
+ uint16_t _pi_u16;
+ int16_t _pi_s16;
+ uint32_t _pi_u32;
+ int32_t _pi_s32;
+ cdf_timestamp_t _pi_tp;
+ struct {
+ uint32_t s_len;
+ const char *s_buf;
+ } _pi_str;
+ } pi_val;
+#define pi_u32 pi_val._pi_u32
+#define pi_s32 pi_val._pi_s32
+#define pi_u16 pi_val._pi_u16
+#define pi_s16 pi_val._pi_s16
+#define pi_tp pi_val._pi_tp
+#define pi_str pi_val._pi_str
+} cdf_property_info_t;
+
#define CDF_ROUND(val, by) (((val) + (by) - 1) & ~((by) - 1))
#define CDF_SIGNED16 0x00000002
#define CDF_PROPERTY_SECURITY 0x00000013
#define CDF_PROPERTY_LOCALE_ID 0x80000000
-#define CDF_NEED_SWAP cdf_need_swap()
-
-#define CDF_TOLE8(x) (CDF_NEED_SWAP ? cdf_tole8(x) : (uint64_t)(x))
-#define CDF_TOLE4(x) (CDF_NEED_SWAP ? cdf_tole4(x) : (uint32_t)(x))
-#define CDF_TOLE2(x) (CDF_NEED_SWAP ? cdf_tole2(x) : (uint16_t)(x))
-
struct timespec;
int cdf_timestamp_to_timespec(struct timespec *, cdf_timestamp_t);
int cdf_timespec_to_timestamp(cdf_timestamp_t *, const struct timespec *);
-int cdf_need_swap(void);
int cdf_read_header(int, cdf_header_t *);
void cdf_swap_header(cdf_header_t *);
void cdf_unpack_header(cdf_header_t *, char *);
void cdf_swap_dir(cdf_directory_t *);
void cdf_unpack_dir(cdf_directory_t *, char *);
+void cdf_swap_class(cdf_classid_t *);
ssize_t cdf_read_sector(int, void *, size_t, size_t, const cdf_header_t *,
cdf_secid_t);
int cdf_read_sat(int, cdf_header_t *, cdf_sat_t *);
int cdf_read_ssat(int, const cdf_header_t *, const cdf_sat_t *, cdf_sat_t *);
int cdf_read_short_stream(int, const cdf_header_t *, const cdf_sat_t *,
const cdf_dir_t *, cdf_stream_t *);
+int cdf_read_property_info(const cdf_stream_t *, uint32_t,
+ cdf_property_info_t **, size_t *, size_t *);
int cdf_read_summary_info(int, const cdf_header_t *, const cdf_sat_t *,
const cdf_dir_t *, cdf_stream_t *);
+int cdf_unpack_summary_info(const cdf_stream_t *, cdf_summary_info_header_t *,
+ cdf_property_info_t **, size_t *);
int cdf_print_classid(char *, size_t, const cdf_classid_t *);
int cdf_print_property_name(char *, size_t, uint32_t);
int cdf_print_elapsed_time(char *, size_t, cdf_timestamp_t);
void cdf_dump(void *, size_t);
void cdf_dump_stream(const cdf_header_t *, const cdf_stream_t *);
void cdf_dump_dir(int, const cdf_header_t *, const cdf_sat_t *, const cdf_dir_t *);
-void cdf_dump_section_info(const cdf_stream_t *, uint32_t);
+void cdf_dump_property_info(const cdf_property_info_t *, uint32_t);
void cdf_dump_summary_info(const cdf_header_t *, const cdf_stream_t *);
#endif
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: readcdf.c,v 1.2 2008/10/12 17:07:14 christos Exp $")
+FILE_RCSID("@(#)$File: readcdf.c,v 1.3 2008/10/12 19:37:04 christos Exp $")
#endif
#include <stdio.h>
#define NOTMIME(ms) (((ms)->flags & MAGIC_MIME) == 0)
private int
-cdf_file_section_info(struct magic_set *ms, const cdf_stream_t *sst,
- uint32_t offs)
+cdf_file_property_info(struct magic_set *ms, const cdf_property_info_t *info,
+ size_t count)
{
- const cdf_section_header_t *shp;
- cdf_section_header_t sh;
- const uint32_t *p, *q, *e;
- const char *s;
- size_t i, len;
- uint32_t u32;
- int32_t s32;
- int16_t s16;
+ size_t i;
cdf_timestamp_t tp;
struct timespec ts;
char buf[64];
const char *str = "vnd.ms-office";
+ const char *s;
+ int len;
- shp = (const void *)((const char *)sst->sst_tab + offs);
- sh.sh_len = CDF_TOLE4(shp->sh_len);
- sh.sh_properties = CDF_TOLE4(shp->sh_properties);
- p = (const void *)((const char *)sst->sst_tab + offs + sizeof(sh));
- q = p + (sh.sh_properties << 1);
- e = (const void *)(((const char *)shp) + sh.sh_len);
- for (i = 0; i < sh.sh_properties; i++) {
- cdf_print_property_name(buf, sizeof(buf), CDF_TOLE4(p[i << 1]));
- switch (CDF_TOLE4(q[0])) {
+ for (i = 0; i < count; i++) {
+ cdf_print_property_name(buf, sizeof(buf), info[i].pi_id);
+ switch (info[i].pi_type) {
case CDF_SIGNED16:
- (void)memcpy(&s16, &q[1], sizeof(s16));
- s16 = CDF_TOLE2(s16);
if (NOTMIME(ms) && file_printf(ms, ", %s: %hd", buf,
- s16) == -1)
+ info[i].pi_s16) == -1)
return -1;
- len = 2;
break;
case CDF_SIGNED32:
- (void)memcpy(&s32, &q[1], sizeof(s32));
- s32 = CDF_TOLE4(s32);
- if (NOTMIME(ms) && file_printf(ms, ", %s: %d", buf, s32)
- == -1)
+ if (NOTMIME(ms) && file_printf(ms, ", %s: %d", buf,
+ info[i].pi_s32) == -1)
return -1;
- len = 4;
break;
case CDF_UNSIGNED32:
- (void)memcpy(&u32, &q[1], sizeof(u32));
- u32 = CDF_TOLE4(u32);
- if (NOTMIME(ms) && file_printf(ms, ", %s: %u", buf, u32)
- == -1)
+ if (NOTMIME(ms) && file_printf(ms, ", %s: %u", buf,
+ info[i].pi_u32) == -1)
return -1;
- len = 4;
break;
case CDF_LENGTH32_STRING:
- if (q[1] > 1) {
- s = (const char *)(&q[2]);
+ len = info[i].pi_str.s_len;
+ if (len > 1) {
+ s = info[i].pi_str.s_buf;
if (NOTMIME(ms)) {
if (file_printf(ms, ", %s: %.*s", buf,
- CDF_TOLE4(q[1]), s) == -1)
+ len, s) == -1)
return -1;
- } else if (CDF_TOLE4(p[i << 1]) ==
+ } else if (info[i].pi_id ==
CDF_PROPERTY_NAME_OF_APPLICATION) {
if (strstr(s, "Word"))
str = "msword";
str = "vnd.ms-powerpoint";
}
}
- len = 4 + q[1];
break;
case CDF_FILETIME:
- (void)memcpy(&tp, &q[1], sizeof(tp));
- tp = CDF_TOLE8(tp);
+ tp = info[i].pi_tp;
if (tp != 0) {
if (tp < 1000000000000000LL) {
char tbuf[64];
return -1;
}
}
- len = 8;
break;
case CDF_CLIPBOARD:
- len = 4 + CDF_TOLE4(q[1]);
break;
default:
- len = 4;
- file_error(ms, 0, "Internal parsing error");
- return -1;
- }
- q++;
- q = (const void *)(((const char *)q) +
- CDF_ROUND(len, sizeof(*q)));
- if (q > e) {
file_error(ms, 0, "Internal parsing error");
return -1;
}
if (file_printf(ms, "application/%s", str) == -1)
return -1;
}
- return 0;
+ return 1;
}
private int
cdf_file_summary_info(struct magic_set *ms, const cdf_stream_t *sst)
{
- size_t i;
- const cdf_summary_info_header_t *si = sst->sst_tab;
- const cdf_section_declaration_t *sd = (const void *)
- ((const char *)sst->sst_tab + CDF_SECTION_DECLARATION_OFFSET);
+ cdf_summary_info_header_t si;
+ cdf_property_info_t *info;
+ size_t count;
+ int m;
+
+ if (cdf_unpack_summary_info(sst, &si, &info, &count) == -1)
+ return -1;
- if (CDF_TOLE2(si->si_byte_order) != 0xfffe)
+ if (si.si_byte_order != 0xfffe)
return 0;
if (NOTMIME(ms) && file_printf(ms, "CDF V2 Document") == -1)
return -1;
if (NOTMIME(ms) && file_printf(ms, ", %s Endian",
- CDF_TOLE4(si->si_byte_order) == 0xfffe ? "Little" : "Big") == -1)
+ si.si_byte_order == 0xfffe ? "Little" : "Big") == -1)
return -1;
if (NOTMIME(ms) && file_printf(ms, ", Os Version: %d.%d",
- si->si_os_version & 0xff, si->si_os_version >> 8) == -1)
+ si.si_os_version & 0xff, si.si_os_version >> 8) == -1)
return -1;
- if (NOTMIME(ms) && file_printf(ms, ", Os: %d", si->si_os) == -1)
+ if (NOTMIME(ms) && file_printf(ms, ", Os: %d", si.si_os) == -1)
return -1;
- for (i = 0; i < si->si_count; i++)
- if (cdf_file_section_info(ms, sst, CDF_TOLE4(sd->sd_offset))
- == -1)
- return -1;
- return 1;
+ m = cdf_file_property_info(ms, info, count);
+ free(info);
+
+ return m;
+/*###164 [cc] warning: this function may return with or without a value%%%*/
}
protected int