From db2c31efc63a751c3dac7926ee077d1fc1c3bdbb Mon Sep 17 00:00:00 2001 From: Christos Zoulas Date: Sun, 12 Oct 2008 21:04:49 +0000 Subject: [PATCH] re-factor so that we don't have code duplication in readcdf and cdf. --- src/cdf.c | 215 ++++++++++++++++++++++++++++++++++---------------- src/cdf.h | 36 +++++++-- src/readcdf.c | 102 +++++++++--------------- 3 files changed, 210 insertions(+), 143 deletions(-) diff --git a/src/cdf.c b/src/cdf.c index ee207e1f..ca3876b5 100644 --- a/src/cdf.c +++ b/src/cdf.c @@ -54,11 +54,8 @@ static union { #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)) /* @@ -111,12 +108,6 @@ cdf_tole8(uint64_t sv) 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) \ @@ -191,6 +182,14 @@ cdf_swap_dir(cdf_directory_t *d) 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) { @@ -211,6 +210,7 @@ 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) { @@ -468,6 +468,115 @@ cdf_read_summary_info(int fd, const 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) @@ -669,53 +778,32 @@ cdf_dump_dir(int fd, const cdf_header_t *h, const cdf_sat_t *sat, } 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); @@ -723,54 +811,41 @@ cdf_dump_section_info(const cdf_stream_t *sst, uint32_t offs) 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 diff --git a/src/cdf.h b/src/cdf.h index 7ba4980d..41799599 100644 --- a/src/cdf.h +++ b/src/cdf.h @@ -142,6 +142,28 @@ typedef struct { 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 @@ -172,21 +194,15 @@ typedef struct { #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 *); @@ -197,8 +213,12 @@ int cdf_read_dir(int, const cdf_header_t *, const cdf_sat_t *, cdf_dir_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); @@ -212,7 +232,7 @@ void cdf_dump_sat(const char *, const cdf_header_t *, const cdf_sat_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 diff --git a/src/readcdf.c b/src/readcdf.c index eff8daad..08a4ff79 100644 --- a/src/readcdf.c +++ b/src/readcdf.c @@ -26,7 +26,7 @@ #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 @@ -45,63 +45,44 @@ FILE_RCSID("@(#)$File: readcdf.c,v 1.2 2008/10/12 17:07:14 christos Exp $") #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"; @@ -111,11 +92,9 @@ cdf_file_section_info(struct magic_set *ms, const cdf_stream_t *sst, 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]; @@ -136,20 +115,10 @@ cdf_file_section_info(struct magic_set *ms, const cdf_stream_t *sst, 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; } @@ -158,39 +127,42 @@ cdf_file_section_info(struct magic_set *ms, const cdf_stream_t *sst, 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 -- 2.40.0