readcdf.c revision 191739
1191739Sobrien/*- 2191739Sobrien * Copyright (c) 2008 Christos Zoulas 3191739Sobrien * All rights reserved. 4191739Sobrien * 5191739Sobrien * Redistribution and use in source and binary forms, with or without 6191739Sobrien * modification, are permitted provided that the following conditions 7191739Sobrien * are met: 8191739Sobrien * 1. Redistributions of source code must retain the above copyright 9191739Sobrien * notice, this list of conditions and the following disclaimer. 10191739Sobrien * 2. Redistributions in binary form must reproduce the above copyright 11191739Sobrien * notice, this list of conditions and the following disclaimer in the 12191739Sobrien * documentation and/or other materials provided with the distribution. 13191739Sobrien * 14191739Sobrien * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 15191739Sobrien * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 16191739Sobrien * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17191739Sobrien * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 18191739Sobrien * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19191739Sobrien * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20191739Sobrien * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21191739Sobrien * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22191739Sobrien * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23191739Sobrien * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24191739Sobrien * POSSIBILITY OF SUCH DAMAGE. 25191739Sobrien */ 26191739Sobrien#include "file.h" 27191739Sobrien 28191739Sobrien#ifndef lint 29191739SobrienFILE_RCSID("@(#)$File: readcdf.c,v 1.11 2009/02/03 20:27:51 christos Exp $") 30191739Sobrien#endif 31191739Sobrien 32191739Sobrien#include <stdlib.h> 33191739Sobrien#include <unistd.h> 34191739Sobrien#include <string.h> 35191739Sobrien#include <time.h> 36191739Sobrien#include <ctype.h> 37191739Sobrien 38191739Sobrien#include "cdf.h" 39191739Sobrien#include "magic.h" 40191739Sobrien 41191739Sobrien#define NOTMIME(ms) (((ms)->flags & MAGIC_MIME) == 0) 42191739Sobrien 43191739Sobrienprivate int 44191739Sobriencdf_file_property_info(struct magic_set *ms, const cdf_property_info_t *info, 45191739Sobrien size_t count) 46191739Sobrien{ 47191739Sobrien size_t i; 48191739Sobrien cdf_timestamp_t tp; 49191739Sobrien struct timespec ts; 50191739Sobrien char buf[64]; 51191739Sobrien const char *str = "vnd.ms-office"; 52191739Sobrien const char *s; 53191739Sobrien int len; 54191739Sobrien 55191739Sobrien for (i = 0; i < count; i++) { 56191739Sobrien cdf_print_property_name(buf, sizeof(buf), info[i].pi_id); 57191739Sobrien switch (info[i].pi_type) { 58191739Sobrien case CDF_SIGNED16: 59191739Sobrien if (NOTMIME(ms) && file_printf(ms, ", %s: %hd", buf, 60191739Sobrien info[i].pi_s16) == -1) 61191739Sobrien return -1; 62191739Sobrien break; 63191739Sobrien case CDF_SIGNED32: 64191739Sobrien if (NOTMIME(ms) && file_printf(ms, ", %s: %d", buf, 65191739Sobrien info[i].pi_s32) == -1) 66191739Sobrien return -1; 67191739Sobrien break; 68191739Sobrien case CDF_UNSIGNED32: 69191739Sobrien if (NOTMIME(ms) && file_printf(ms, ", %s: %u", buf, 70191739Sobrien info[i].pi_u32) == -1) 71191739Sobrien return -1; 72191739Sobrien break; 73191739Sobrien case CDF_LENGTH32_STRING: 74191739Sobrien len = info[i].pi_str.s_len; 75191739Sobrien if (len > 1) { 76191739Sobrien s = info[i].pi_str.s_buf; 77191739Sobrien if (NOTMIME(ms)) { 78191739Sobrien if (file_printf(ms, ", %s: %.*s", buf, 79191739Sobrien len, s) == -1) 80191739Sobrien return -1; 81191739Sobrien } else if (info[i].pi_id == 82191739Sobrien CDF_PROPERTY_NAME_OF_APPLICATION) { 83191739Sobrien if (strstr(s, "Word")) 84191739Sobrien str = "msword"; 85191739Sobrien else if (strstr(s, "Excel")) 86191739Sobrien str = "vnd.ms-excel"; 87191739Sobrien else if (strstr(s, "Powerpoint")) 88191739Sobrien str = "vnd.ms-powerpoint"; 89191739Sobrien } 90191739Sobrien } 91191739Sobrien break; 92191739Sobrien case CDF_FILETIME: 93191739Sobrien tp = info[i].pi_tp; 94191739Sobrien if (tp != 0) { 95191739Sobrien if (tp < 1000000000000000LL) { 96191739Sobrien char tbuf[64]; 97191739Sobrien cdf_print_elapsed_time(tbuf, 98191739Sobrien sizeof(tbuf), tp); 99191739Sobrien if (NOTMIME(ms) && file_printf(ms, 100191739Sobrien ", %s: %s", buf, tbuf) == -1) 101191739Sobrien return -1; 102191739Sobrien } else { 103191739Sobrien char *c, *ec; 104191739Sobrien cdf_timestamp_to_timespec(&ts, tp); 105191739Sobrien c = ctime(&ts.tv_sec); 106191739Sobrien if ((ec = strchr(c, '\n')) != NULL) 107191739Sobrien *ec = '\0'; 108191739Sobrien 109191739Sobrien if (NOTMIME(ms) && file_printf(ms, 110191739Sobrien ", %s: %s", buf, c) == -1) 111191739Sobrien return -1; 112191739Sobrien } 113191739Sobrien } 114191739Sobrien break; 115191739Sobrien case CDF_CLIPBOARD: 116191739Sobrien break; 117191739Sobrien default: 118191739Sobrien file_error(ms, 0, "Internal parsing error"); 119191739Sobrien return -1; 120191739Sobrien } 121191739Sobrien } 122191739Sobrien if (!NOTMIME(ms)) { 123191739Sobrien if (file_printf(ms, "application/%s", str) == -1) 124191739Sobrien return -1; 125191739Sobrien } 126191739Sobrien return 1; 127191739Sobrien} 128191739Sobrien 129191739Sobrienprivate int 130191739Sobriencdf_file_summary_info(struct magic_set *ms, const cdf_stream_t *sst) 131191739Sobrien{ 132191739Sobrien cdf_summary_info_header_t si; 133191739Sobrien cdf_property_info_t *info; 134191739Sobrien size_t count; 135191739Sobrien int m; 136191739Sobrien 137191739Sobrien if (cdf_unpack_summary_info(sst, &si, &info, &count) == -1) { 138191739Sobrien if (si.si_byte_order != 0xfffe) 139191739Sobrien return 0; 140191739Sobrien else 141191739Sobrien return -1; 142191739Sobrien } 143191739Sobrien 144191739Sobrien if (si.si_byte_order != 0xfffe) 145191739Sobrien return 0; 146191739Sobrien 147191739Sobrien if (NOTMIME(ms)) { 148191739Sobrien if (file_printf(ms, "CDF V2 Document") == -1) 149191739Sobrien return -1; 150191739Sobrien 151191739Sobrien if (file_printf(ms, ", %s Endian", 152191739Sobrien si.si_byte_order == 0xfffe ? "Little" : "Big") == -1) 153191739Sobrien return -1; 154191739Sobrien switch (si.si_os) { 155191739Sobrien case 2: 156191739Sobrien if (file_printf(ms, ", Os: Windows, Version %d.%d", 157191739Sobrien si.si_os_version & 0xff, si.si_os_version >> 8) 158191739Sobrien == -1) 159191739Sobrien return -1; 160191739Sobrien break; 161191739Sobrien case 1: 162191739Sobrien if (file_printf(ms, ", Os: MacOS, Version %d.%d", 163191739Sobrien si.si_os_version >> 8, si.si_os_version & 0xff) 164191739Sobrien == -1) 165191739Sobrien return -1; 166191739Sobrien break; 167191739Sobrien default: 168191739Sobrien if (file_printf(ms, ", Os %d, Version: %d.%d", si.si_os, 169191739Sobrien si.si_os_version & 0xff, si.si_os_version >> 8) 170191739Sobrien == -1) 171191739Sobrien return -1; 172191739Sobrien break; 173191739Sobrien } 174191739Sobrien } 175191739Sobrien 176191739Sobrien m = cdf_file_property_info(ms, info, count); 177191739Sobrien free(info); 178191739Sobrien 179191739Sobrien return m; 180191739Sobrien} 181191739Sobrien 182191739Sobrienprotected int 183191739Sobrienfile_trycdf(struct magic_set *ms, int fd, const unsigned char *buf, 184191739Sobrien size_t nbytes) 185191739Sobrien{ 186191739Sobrien cdf_header_t h; 187191739Sobrien cdf_sat_t sat, ssat; 188191739Sobrien cdf_stream_t sst, scn; 189191739Sobrien cdf_dir_t dir; 190191739Sobrien int i; 191191739Sobrien (void)&nbytes; 192191739Sobrien (void)&buf; 193191739Sobrien 194191739Sobrien if (ms->flags & MAGIC_APPLE) 195191739Sobrien return 0; 196191739Sobrien if (cdf_read_header(fd, &h) == -1) 197191739Sobrien return 0; 198191739Sobrien#ifdef CDF_DEBUG 199191739Sobrien cdf_dump_header(&h); 200191739Sobrien#endif 201191739Sobrien 202191739Sobrien if (cdf_read_sat(fd, &h, &sat) == -1) { 203191739Sobrien file_error(ms, errno, "Can't read SAT"); 204191739Sobrien return -1; 205191739Sobrien } 206191739Sobrien#ifdef CDF_DEBUG 207191739Sobrien cdf_dump_sat("SAT", &h, &sat); 208191739Sobrien#endif 209191739Sobrien 210191739Sobrien if ((i = cdf_read_ssat(fd, &h, &sat, &ssat)) == -1) { 211191739Sobrien file_error(ms, errno, "Can't read SAT"); 212191739Sobrien goto out1; 213191739Sobrien } 214191739Sobrien#ifdef CDF_DEBUG 215191739Sobrien cdf_dump_sat("SSAT", &h, &ssat); 216191739Sobrien#endif 217191739Sobrien 218191739Sobrien if ((i = cdf_read_dir(fd, &h, &sat, &dir)) == -1) { 219191739Sobrien file_error(ms, errno, "Can't read directory"); 220191739Sobrien goto out2; 221191739Sobrien } 222191739Sobrien 223191739Sobrien if ((i = cdf_read_short_stream(fd, &h, &sat, &dir, &sst)) == -1) { 224191739Sobrien file_error(ms, errno, "Cannot read short stream"); 225191739Sobrien goto out3; 226191739Sobrien } 227191739Sobrien 228191739Sobrien#ifdef CDF_DEBUG 229191739Sobrien cdf_dump_dir(fd, &h, &sat, &ssat, &sst, &dir); 230191739Sobrien#endif 231191739Sobrien if ((i = cdf_read_summary_info(fd, &h, &sat, &ssat, &sst, &dir, &scn)) 232191739Sobrien == -1) { 233191739Sobrien /* Some files don't have summary info! */ 234191739Sobrien#ifdef notyet 235191739Sobrien file_error(ms, errno, "Can't read summary_info"); 236191739Sobrien#else 237191739Sobrien i = 0; 238191739Sobrien#endif 239191739Sobrien goto out4; 240191739Sobrien } 241191739Sobrien#ifdef CDF_DEBUG 242191739Sobrien cdf_dump_summary_info(&h, &scn); 243191739Sobrien#endif 244191739Sobrien if ((i = cdf_file_summary_info(ms, &scn)) == -1) 245191739Sobrien file_error(ms, errno, "Can't expand summary_info"); 246191739Sobrien free(scn.sst_tab); 247191739Sobrienout4: 248191739Sobrien free(sst.sst_tab); 249191739Sobrienout3: 250191739Sobrien free(dir.dir_tab); 251191739Sobrienout2: 252191739Sobrien free(ssat.sat_tab); 253191739Sobrienout1: 254191739Sobrien free(sat.sat_tab); 255191739Sobrien return i; 256191739Sobrien} 257