1191739Sobrien/*- 2309848Sdelphij * Copyright (c) 2008, 2016 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 29328875SeadlerFILE_RCSID("@(#)$File: readcdf.c,v 1.65 2017/04/08 20:58:03 christos Exp $") 30191739Sobrien#endif 31191739Sobrien 32267843Sdelphij#include <assert.h> 33191739Sobrien#include <stdlib.h> 34191739Sobrien#include <unistd.h> 35191739Sobrien#include <string.h> 36191739Sobrien#include <time.h> 37191739Sobrien#include <ctype.h> 38191739Sobrien 39191739Sobrien#include "cdf.h" 40191739Sobrien#include "magic.h" 41191739Sobrien 42284778Sdelphij#ifndef __arraycount 43284778Sdelphij#define __arraycount(a) (sizeof(a) / sizeof(a[0])) 44284778Sdelphij#endif 45284778Sdelphij 46191739Sobrien#define NOTMIME(ms) (((ms)->flags & MAGIC_MIME) == 0) 47191739Sobrien 48267843Sdelphijstatic const struct nv { 49267843Sdelphij const char *pattern; 50267843Sdelphij const char *mime; 51267843Sdelphij} app2mime[] = { 52267843Sdelphij { "Word", "msword", }, 53267843Sdelphij { "Excel", "vnd.ms-excel", }, 54267843Sdelphij { "Powerpoint", "vnd.ms-powerpoint", }, 55267843Sdelphij { "Crystal Reports", "x-rpt", }, 56267843Sdelphij { "Advanced Installer", "vnd.ms-msi", }, 57267843Sdelphij { "InstallShield", "vnd.ms-msi", }, 58267843Sdelphij { "Microsoft Patch Compiler", "vnd.ms-msi", }, 59267843Sdelphij { "NAnt", "vnd.ms-msi", }, 60267843Sdelphij { "Windows Installer", "vnd.ms-msi", }, 61267843Sdelphij { NULL, NULL, }, 62267843Sdelphij}, name2mime[] = { 63300899Sdelphij { "Book", "vnd.ms-excel", }, 64300899Sdelphij { "Workbook", "vnd.ms-excel", }, 65267843Sdelphij { "WordDocument", "msword", }, 66267843Sdelphij { "PowerPoint", "vnd.ms-powerpoint", }, 67267843Sdelphij { "DigitalSignature", "vnd.ms-msi", }, 68267843Sdelphij { NULL, NULL, }, 69267843Sdelphij}, name2desc[] = { 70300899Sdelphij { "Book", "Microsoft Excel", }, 71300899Sdelphij { "Workbook", "Microsoft Excel", }, 72300899Sdelphij { "WordDocument", "Microsoft Word", }, 73267843Sdelphij { "PowerPoint", "Microsoft PowerPoint", }, 74267843Sdelphij { "DigitalSignature", "Microsoft Installer", }, 75267843Sdelphij { NULL, NULL, }, 76267843Sdelphij}; 77267843Sdelphij 78267843Sdelphijstatic const struct cv { 79267843Sdelphij uint64_t clsid[2]; 80267843Sdelphij const char *mime; 81267843Sdelphij} clsid2mime[] = { 82267843Sdelphij { 83276415Sdelphij { 0x00000000000c1084ULL, 0x46000000000000c0ULL }, 84267843Sdelphij "x-msi", 85267843Sdelphij }, 86267843Sdelphij { { 0, 0 }, 87267843Sdelphij NULL, 88267843Sdelphij }, 89267843Sdelphij}, clsid2desc[] = { 90267843Sdelphij { 91276415Sdelphij { 0x00000000000c1084ULL, 0x46000000000000c0ULL }, 92267843Sdelphij "MSI Installer", 93267843Sdelphij }, 94267843Sdelphij { { 0, 0 }, 95267843Sdelphij NULL, 96267843Sdelphij }, 97267843Sdelphij}; 98267843Sdelphij 99267843Sdelphijprivate const char * 100267843Sdelphijcdf_clsid_to_mime(const uint64_t clsid[2], const struct cv *cv) 101267843Sdelphij{ 102267843Sdelphij size_t i; 103267843Sdelphij for (i = 0; cv[i].mime != NULL; i++) { 104267843Sdelphij if (clsid[0] == cv[i].clsid[0] && clsid[1] == cv[i].clsid[1]) 105267843Sdelphij return cv[i].mime; 106267843Sdelphij } 107284778Sdelphij#ifdef CDF_DEBUG 108284778Sdelphij fprintf(stderr, "unknown mime %" PRIx64 ", %" PRIx64 "\n", clsid[0], 109284778Sdelphij clsid[1]); 110284778Sdelphij#endif 111267843Sdelphij return NULL; 112267843Sdelphij} 113267843Sdelphij 114267843Sdelphijprivate const char * 115267843Sdelphijcdf_app_to_mime(const char *vbuf, const struct nv *nv) 116267843Sdelphij{ 117267843Sdelphij size_t i; 118267843Sdelphij const char *rv = NULL; 119276415Sdelphij#ifdef USE_C_LOCALE 120276415Sdelphij locale_t old_lc_ctype, c_lc_ctype; 121267843Sdelphij 122276415Sdelphij c_lc_ctype = newlocale(LC_CTYPE_MASK, "C", 0); 123276415Sdelphij assert(c_lc_ctype != NULL); 124276415Sdelphij old_lc_ctype = uselocale(c_lc_ctype); 125267843Sdelphij assert(old_lc_ctype != NULL); 126300899Sdelphij#else 127300899Sdelphij char *old_lc_ctype = setlocale(LC_CTYPE, "C"); 128276415Sdelphij#endif 129267843Sdelphij for (i = 0; nv[i].pattern != NULL; i++) 130267843Sdelphij if (strcasestr(vbuf, nv[i].pattern) != NULL) { 131267843Sdelphij rv = nv[i].mime; 132267843Sdelphij break; 133267843Sdelphij } 134284778Sdelphij#ifdef CDF_DEBUG 135284778Sdelphij fprintf(stderr, "unknown app %s\n", vbuf); 136284778Sdelphij#endif 137276415Sdelphij#ifdef USE_C_LOCALE 138276415Sdelphij (void)uselocale(old_lc_ctype); 139276415Sdelphij freelocale(c_lc_ctype); 140300899Sdelphij#else 141300899Sdelphij setlocale(LC_CTYPE, old_lc_ctype); 142276415Sdelphij#endif 143267843Sdelphij return rv; 144267843Sdelphij} 145267843Sdelphij 146191739Sobrienprivate int 147191739Sobriencdf_file_property_info(struct magic_set *ms, const cdf_property_info_t *info, 148267843Sdelphij size_t count, const cdf_directory_t *root_storage) 149191739Sobrien{ 150226048Sobrien size_t i; 151226048Sobrien cdf_timestamp_t tp; 152226048Sobrien struct timespec ts; 153226048Sobrien char buf[64]; 154226048Sobrien const char *str = NULL; 155328875Seadler const char *s, *e; 156226048Sobrien int len; 157191739Sobrien 158267843Sdelphij if (!NOTMIME(ms) && root_storage) 159267843Sdelphij str = cdf_clsid_to_mime(root_storage->d_storage_uuid, 160267843Sdelphij clsid2mime); 161267843Sdelphij 162226048Sobrien for (i = 0; i < count; i++) { 163226048Sobrien cdf_print_property_name(buf, sizeof(buf), info[i].pi_id); 164226048Sobrien switch (info[i].pi_type) { 165226048Sobrien case CDF_NULL: 166226048Sobrien break; 167226048Sobrien case CDF_SIGNED16: 168226048Sobrien if (NOTMIME(ms) && file_printf(ms, ", %s: %hd", buf, 169226048Sobrien info[i].pi_s16) == -1) 170226048Sobrien return -1; 171226048Sobrien break; 172226048Sobrien case CDF_SIGNED32: 173226048Sobrien if (NOTMIME(ms) && file_printf(ms, ", %s: %d", buf, 174226048Sobrien info[i].pi_s32) == -1) 175226048Sobrien return -1; 176226048Sobrien break; 177226048Sobrien case CDF_UNSIGNED32: 178226048Sobrien if (NOTMIME(ms) && file_printf(ms, ", %s: %u", buf, 179226048Sobrien info[i].pi_u32) == -1) 180226048Sobrien return -1; 181226048Sobrien break; 182234250Sobrien case CDF_FLOAT: 183234250Sobrien if (NOTMIME(ms) && file_printf(ms, ", %s: %g", buf, 184234250Sobrien info[i].pi_f) == -1) 185234250Sobrien return -1; 186234250Sobrien break; 187234250Sobrien case CDF_DOUBLE: 188234250Sobrien if (NOTMIME(ms) && file_printf(ms, ", %s: %g", buf, 189234250Sobrien info[i].pi_d) == -1) 190234250Sobrien return -1; 191234250Sobrien break; 192226048Sobrien case CDF_LENGTH32_STRING: 193226048Sobrien case CDF_LENGTH32_WSTRING: 194226048Sobrien len = info[i].pi_str.s_len; 195226048Sobrien if (len > 1) { 196226048Sobrien char vbuf[1024]; 197226048Sobrien size_t j, k = 1; 198191739Sobrien 199226048Sobrien if (info[i].pi_type == CDF_LENGTH32_WSTRING) 200226048Sobrien k++; 201226048Sobrien s = info[i].pi_str.s_buf; 202328875Seadler e = info[i].pi_str.s_buf + len; 203328875Seadler for (j = 0; s < e && j < sizeof(vbuf) 204328875Seadler && len--; s += k) { 205226048Sobrien if (*s == '\0') 206226048Sobrien break; 207226048Sobrien if (isprint((unsigned char)*s)) 208267843Sdelphij vbuf[j++] = *s; 209226048Sobrien } 210226048Sobrien if (j == sizeof(vbuf)) 211226048Sobrien --j; 212226048Sobrien vbuf[j] = '\0'; 213226048Sobrien if (NOTMIME(ms)) { 214226048Sobrien if (vbuf[0]) { 215226048Sobrien if (file_printf(ms, ", %s: %s", 216226048Sobrien buf, vbuf) == -1) 217226048Sobrien return -1; 218226048Sobrien } 219267843Sdelphij } else if (str == NULL && info[i].pi_id == 220267843Sdelphij CDF_PROPERTY_NAME_OF_APPLICATION) { 221267843Sdelphij str = cdf_app_to_mime(vbuf, app2mime); 222267843Sdelphij } 223267843Sdelphij } 224226048Sobrien break; 225226048Sobrien case CDF_FILETIME: 226226048Sobrien tp = info[i].pi_tp; 227226048Sobrien if (tp != 0) { 228267843Sdelphij char tbuf[64]; 229226048Sobrien if (tp < 1000000000000000LL) { 230226048Sobrien cdf_print_elapsed_time(tbuf, 231226048Sobrien sizeof(tbuf), tp); 232226048Sobrien if (NOTMIME(ms) && file_printf(ms, 233226048Sobrien ", %s: %s", buf, tbuf) == -1) 234226048Sobrien return -1; 235226048Sobrien } else { 236226048Sobrien char *c, *ec; 237226048Sobrien cdf_timestamp_to_timespec(&ts, tp); 238267843Sdelphij c = cdf_ctime(&ts.tv_sec, tbuf); 239267843Sdelphij if (c != NULL && 240267843Sdelphij (ec = strchr(c, '\n')) != NULL) 241267843Sdelphij *ec = '\0'; 242226048Sobrien 243226048Sobrien if (NOTMIME(ms) && file_printf(ms, 244226048Sobrien ", %s: %s", buf, c) == -1) 245226048Sobrien return -1; 246226048Sobrien } 247226048Sobrien } 248226048Sobrien break; 249226048Sobrien case CDF_CLIPBOARD: 250226048Sobrien break; 251226048Sobrien default: 252226048Sobrien return -1; 253226048Sobrien } 254226048Sobrien } 255226048Sobrien if (!NOTMIME(ms)) { 256226048Sobrien if (str == NULL) 257226048Sobrien return 0; 258234250Sobrien if (file_printf(ms, "application/%s", str) == -1) 259234250Sobrien return -1; 260226048Sobrien } 261226048Sobrien return 1; 262191739Sobrien} 263191739Sobrien 264191739Sobrienprivate int 265276415Sdelphijcdf_file_catalog(struct magic_set *ms, const cdf_header_t *h, 266276415Sdelphij const cdf_stream_t *sst) 267276415Sdelphij{ 268276415Sdelphij cdf_catalog_t *cat; 269276415Sdelphij size_t i; 270276415Sdelphij char buf[256]; 271276415Sdelphij cdf_catalog_entry_t *ce; 272276415Sdelphij 273276415Sdelphij if (NOTMIME(ms)) { 274276415Sdelphij if (file_printf(ms, "Microsoft Thumbs.db [") == -1) 275276415Sdelphij return -1; 276276415Sdelphij if (cdf_unpack_catalog(h, sst, &cat) == -1) 277276415Sdelphij return -1; 278276415Sdelphij ce = cat->cat_e; 279276415Sdelphij /* skip first entry since it has a , or paren */ 280276415Sdelphij for (i = 1; i < cat->cat_num; i++) 281276415Sdelphij if (file_printf(ms, "%s%s", 282276415Sdelphij cdf_u16tos8(buf, ce[i].ce_namlen, ce[i].ce_name), 283276415Sdelphij i == cat->cat_num - 1 ? "]" : ", ") == -1) { 284276415Sdelphij free(cat); 285276415Sdelphij return -1; 286276415Sdelphij } 287276415Sdelphij free(cat); 288276415Sdelphij } else { 289276415Sdelphij if (file_printf(ms, "application/CDFV2") == -1) 290276415Sdelphij return -1; 291276415Sdelphij } 292276415Sdelphij return 1; 293276415Sdelphij} 294276415Sdelphij 295276415Sdelphijprivate int 296226048Sobriencdf_file_summary_info(struct magic_set *ms, const cdf_header_t *h, 297267843Sdelphij const cdf_stream_t *sst, const cdf_directory_t *root_storage) 298191739Sobrien{ 299226048Sobrien cdf_summary_info_header_t si; 300226048Sobrien cdf_property_info_t *info; 301226048Sobrien size_t count; 302226048Sobrien int m; 303191739Sobrien 304226048Sobrien if (cdf_unpack_summary_info(sst, h, &si, &info, &count) == -1) 305226048Sobrien return -1; 306191739Sobrien 307226048Sobrien if (NOTMIME(ms)) { 308267843Sdelphij const char *str; 309267843Sdelphij 310234250Sobrien if (file_printf(ms, "Composite Document File V2 Document") 311234250Sobrien == -1) 312226048Sobrien return -1; 313191739Sobrien 314226048Sobrien if (file_printf(ms, ", %s Endian", 315226048Sobrien si.si_byte_order == 0xfffe ? "Little" : "Big") == -1) 316234250Sobrien return -2; 317226048Sobrien switch (si.si_os) { 318226048Sobrien case 2: 319226048Sobrien if (file_printf(ms, ", Os: Windows, Version %d.%d", 320226048Sobrien si.si_os_version & 0xff, 321226048Sobrien (uint32_t)si.si_os_version >> 8) == -1) 322234250Sobrien return -2; 323226048Sobrien break; 324226048Sobrien case 1: 325226048Sobrien if (file_printf(ms, ", Os: MacOS, Version %d.%d", 326226048Sobrien (uint32_t)si.si_os_version >> 8, 327226048Sobrien si.si_os_version & 0xff) == -1) 328234250Sobrien return -2; 329226048Sobrien break; 330226048Sobrien default: 331226048Sobrien if (file_printf(ms, ", Os %d, Version: %d.%d", si.si_os, 332226048Sobrien si.si_os_version & 0xff, 333226048Sobrien (uint32_t)si.si_os_version >> 8) == -1) 334234250Sobrien return -2; 335226048Sobrien break; 336226048Sobrien } 337267843Sdelphij if (root_storage) { 338267843Sdelphij str = cdf_clsid_to_mime(root_storage->d_storage_uuid, 339267843Sdelphij clsid2desc); 340276415Sdelphij if (str) { 341267843Sdelphij if (file_printf(ms, ", %s", str) == -1) 342267843Sdelphij return -2; 343267843Sdelphij } 344267843Sdelphij } 345276415Sdelphij } 346191739Sobrien 347267843Sdelphij m = cdf_file_property_info(ms, info, count, root_storage); 348226048Sobrien free(info); 349191739Sobrien 350234250Sobrien return m == -1 ? -2 : m; 351191739Sobrien} 352191739Sobrien 353267843Sdelphij#ifdef notdef 354267843Sdelphijprivate char * 355267843Sdelphijformat_clsid(char *buf, size_t len, const uint64_t uuid[2]) { 356267843Sdelphij snprintf(buf, len, "%.8" PRIx64 "-%.4" PRIx64 "-%.4" PRIx64 "-%.4" 357267843Sdelphij PRIx64 "-%.12" PRIx64, 358276415Sdelphij (uuid[0] >> 32) & (uint64_t)0x000000000ffffffffULL, 359276415Sdelphij (uuid[0] >> 16) & (uint64_t)0x0000000000000ffffULL, 360276415Sdelphij (uuid[0] >> 0) & (uint64_t)0x0000000000000ffffULL, 361276415Sdelphij (uuid[1] >> 48) & (uint64_t)0x0000000000000ffffULL, 362276415Sdelphij (uuid[1] >> 0) & (uint64_t)0x0000fffffffffffffULL); 363267843Sdelphij return buf; 364267843Sdelphij} 365267843Sdelphij#endif 366267843Sdelphij 367284778Sdelphijprivate int 368284778Sdelphijcdf_file_catalog_info(struct magic_set *ms, const cdf_info_t *info, 369284778Sdelphij const cdf_header_t *h, const cdf_sat_t *sat, const cdf_sat_t *ssat, 370284778Sdelphij const cdf_stream_t *sst, const cdf_dir_t *dir, cdf_stream_t *scn) 371284778Sdelphij{ 372284778Sdelphij int i; 373284778Sdelphij 374284778Sdelphij if ((i = cdf_read_user_stream(info, h, sat, ssat, sst, 375284778Sdelphij dir, "Catalog", scn)) == -1) 376284778Sdelphij return i; 377284778Sdelphij#ifdef CDF_DEBUG 378309848Sdelphij cdf_dump_catalog(h, scn); 379284778Sdelphij#endif 380284778Sdelphij if ((i = cdf_file_catalog(ms, h, scn)) == -1) 381284778Sdelphij return -1; 382284778Sdelphij return i; 383284778Sdelphij} 384284778Sdelphij 385309848Sdelphijprivate int 386309848Sdelphijcdf_check_summary_info(struct magic_set *ms, const cdf_info_t *info, 387309848Sdelphij const cdf_header_t *h, const cdf_sat_t *sat, const cdf_sat_t *ssat, 388309848Sdelphij const cdf_stream_t *sst, const cdf_dir_t *dir, cdf_stream_t *scn, 389309848Sdelphij const cdf_directory_t *root_storage, const char **expn) 390309848Sdelphij{ 391309848Sdelphij int i; 392309848Sdelphij const char *str = NULL; 393309848Sdelphij cdf_directory_t *d; 394309848Sdelphij char name[__arraycount(d->d_name)]; 395309848Sdelphij size_t j, k; 396309848Sdelphij 397309848Sdelphij#ifdef CDF_DEBUG 398309848Sdelphij cdf_dump_summary_info(h, scn); 399309848Sdelphij#endif 400309848Sdelphij if ((i = cdf_file_summary_info(ms, h, scn, root_storage)) < 0) { 401309848Sdelphij *expn = "Can't expand summary_info"; 402309848Sdelphij return i; 403309848Sdelphij } 404309848Sdelphij if (i == 1) 405309848Sdelphij return i; 406309848Sdelphij for (j = 0; str == NULL && j < dir->dir_len; j++) { 407309848Sdelphij d = &dir->dir_tab[j]; 408309848Sdelphij for (k = 0; k < sizeof(name); k++) 409309848Sdelphij name[k] = (char)cdf_tole2(d->d_name[k]); 410309848Sdelphij str = cdf_app_to_mime(name, 411309848Sdelphij NOTMIME(ms) ? name2desc : name2mime); 412309848Sdelphij } 413309848Sdelphij if (NOTMIME(ms)) { 414309848Sdelphij if (str != NULL) { 415309848Sdelphij if (file_printf(ms, "%s", str) == -1) 416309848Sdelphij return -1; 417309848Sdelphij i = 1; 418309848Sdelphij } 419309848Sdelphij } else { 420309848Sdelphij if (str == NULL) 421309848Sdelphij str = "vnd.ms-office"; 422309848Sdelphij if (file_printf(ms, "application/%s", str) == -1) 423309848Sdelphij return -1; 424309848Sdelphij i = 1; 425309848Sdelphij } 426309848Sdelphij if (i <= 0) { 427309848Sdelphij i = cdf_file_catalog_info(ms, info, h, sat, ssat, sst, 428309848Sdelphij dir, scn); 429309848Sdelphij } 430309848Sdelphij return i; 431309848Sdelphij} 432309848Sdelphij 433284778Sdelphijprivate struct sinfo { 434284778Sdelphij const char *name; 435284778Sdelphij const char *mime; 436284778Sdelphij const char *sections[5]; 437284778Sdelphij const int types[5]; 438284778Sdelphij} sectioninfo[] = { 439284778Sdelphij { "Encrypted", "encrypted", 440284778Sdelphij { 441309848Sdelphij "EncryptedPackage", "EncryptedSummary", 442309848Sdelphij NULL, NULL, NULL, 443284778Sdelphij }, 444284778Sdelphij { 445309848Sdelphij CDF_DIR_TYPE_USER_STREAM, 446309848Sdelphij CDF_DIR_TYPE_USER_STREAM, 447309848Sdelphij 0, 0, 0, 448284778Sdelphij 449284778Sdelphij }, 450284778Sdelphij }, 451284778Sdelphij { "QuickBooks", "quickbooks", 452284778Sdelphij { 453284778Sdelphij#if 0 454284778Sdelphij "TaxForms", "PDFTaxForms", "modulesInBackup", 455284778Sdelphij#endif 456284778Sdelphij "mfbu_header", NULL, NULL, NULL, NULL, 457284778Sdelphij }, 458284778Sdelphij { 459284778Sdelphij#if 0 460284778Sdelphij CDF_DIR_TYPE_USER_STORAGE, 461284778Sdelphij CDF_DIR_TYPE_USER_STORAGE, 462284778Sdelphij CDF_DIR_TYPE_USER_STREAM, 463284778Sdelphij#endif 464284778Sdelphij CDF_DIR_TYPE_USER_STREAM, 465284778Sdelphij 0, 0, 0, 0 466284778Sdelphij }, 467284778Sdelphij }, 468309848Sdelphij { "Microsoft Excel", "vnd.ms-excel", 469309848Sdelphij { 470309848Sdelphij "Book", "Workbook", NULL, NULL, NULL, 471309848Sdelphij }, 472309848Sdelphij { 473309848Sdelphij CDF_DIR_TYPE_USER_STREAM, 474309848Sdelphij CDF_DIR_TYPE_USER_STREAM, 475309848Sdelphij 0, 0, 0, 476309848Sdelphij }, 477309848Sdelphij }, 478309848Sdelphij { "Microsoft Word", "msword", 479309848Sdelphij { 480309848Sdelphij "WordDocument", NULL, NULL, NULL, NULL, 481309848Sdelphij }, 482309848Sdelphij { 483309848Sdelphij CDF_DIR_TYPE_USER_STREAM, 484309848Sdelphij 0, 0, 0, 0, 485309848Sdelphij }, 486309848Sdelphij }, 487309848Sdelphij { "Microsoft PowerPoint", "vnd.ms-powerpoint", 488309848Sdelphij { 489309848Sdelphij "PowerPoint", NULL, NULL, NULL, NULL, 490309848Sdelphij }, 491309848Sdelphij { 492309848Sdelphij CDF_DIR_TYPE_USER_STREAM, 493309848Sdelphij 0, 0, 0, 0, 494309848Sdelphij }, 495309848Sdelphij }, 496309848Sdelphij { "Microsoft Outlook Message", "vnd.ms-outlook", 497309848Sdelphij { 498309848Sdelphij "__properties_version1.0", 499309848Sdelphij "__recip_version1.0_#00000000", 500309848Sdelphij NULL, NULL, NULL, 501309848Sdelphij }, 502309848Sdelphij { 503309848Sdelphij CDF_DIR_TYPE_USER_STREAM, 504309848Sdelphij CDF_DIR_TYPE_USER_STORAGE, 505309848Sdelphij 0, 0, 0, 506309848Sdelphij }, 507309848Sdelphij }, 508284778Sdelphij}; 509284778Sdelphij 510284778Sdelphijprivate int 511284778Sdelphijcdf_file_dir_info(struct magic_set *ms, const cdf_dir_t *dir) 512284778Sdelphij{ 513284778Sdelphij size_t sd, j; 514284778Sdelphij 515284778Sdelphij for (sd = 0; sd < __arraycount(sectioninfo); sd++) { 516284778Sdelphij const struct sinfo *si = §ioninfo[sd]; 517284778Sdelphij for (j = 0; si->sections[j]; j++) { 518284778Sdelphij if (cdf_find_stream(dir, si->sections[j], si->types[j]) 519309848Sdelphij > 0) 520309848Sdelphij break; 521284778Sdelphij#ifdef CDF_DEBUG 522309848Sdelphij fprintf(stderr, "Can't read %s\n", si->sections[j]); 523284778Sdelphij#endif 524284778Sdelphij } 525309848Sdelphij if (si->sections[j] == NULL) 526284778Sdelphij continue; 527284778Sdelphij if (NOTMIME(ms)) { 528284778Sdelphij if (file_printf(ms, "CDFV2 %s", si->name) == -1) 529284778Sdelphij return -1; 530284778Sdelphij } else { 531309848Sdelphij if (file_printf(ms, "application/%s", si->mime) == -1) 532284778Sdelphij return -1; 533284778Sdelphij } 534284778Sdelphij return 1; 535284778Sdelphij } 536284778Sdelphij return -1; 537284778Sdelphij} 538284778Sdelphij 539191739Sobrienprotected int 540191739Sobrienfile_trycdf(struct magic_set *ms, int fd, const unsigned char *buf, 541191739Sobrien size_t nbytes) 542191739Sobrien{ 543226048Sobrien cdf_info_t info; 544226048Sobrien cdf_header_t h; 545226048Sobrien cdf_sat_t sat, ssat; 546226048Sobrien cdf_stream_t sst, scn; 547226048Sobrien cdf_dir_t dir; 548226048Sobrien int i; 549226048Sobrien const char *expn = ""; 550276415Sdelphij const cdf_directory_t *root_storage; 551191739Sobrien 552309848Sdelphij scn.sst_tab = NULL; 553226048Sobrien info.i_fd = fd; 554226048Sobrien info.i_buf = buf; 555226048Sobrien info.i_len = nbytes; 556284778Sdelphij if (ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION)) 557226048Sobrien return 0; 558226048Sobrien if (cdf_read_header(&info, &h) == -1) 559226048Sobrien return 0; 560191739Sobrien#ifdef CDF_DEBUG 561226048Sobrien cdf_dump_header(&h); 562191739Sobrien#endif 563191739Sobrien 564226048Sobrien if ((i = cdf_read_sat(&info, &h, &sat)) == -1) { 565226048Sobrien expn = "Can't read SAT"; 566226048Sobrien goto out0; 567226048Sobrien } 568191739Sobrien#ifdef CDF_DEBUG 569226048Sobrien cdf_dump_sat("SAT", &sat, CDF_SEC_SIZE(&h)); 570191739Sobrien#endif 571191739Sobrien 572226048Sobrien if ((i = cdf_read_ssat(&info, &h, &sat, &ssat)) == -1) { 573226048Sobrien expn = "Can't read SSAT"; 574226048Sobrien goto out1; 575226048Sobrien } 576191739Sobrien#ifdef CDF_DEBUG 577226048Sobrien cdf_dump_sat("SSAT", &ssat, CDF_SHORT_SEC_SIZE(&h)); 578191739Sobrien#endif 579191739Sobrien 580226048Sobrien if ((i = cdf_read_dir(&info, &h, &sat, &dir)) == -1) { 581226048Sobrien expn = "Can't read directory"; 582226048Sobrien goto out2; 583226048Sobrien } 584191739Sobrien 585267843Sdelphij if ((i = cdf_read_short_stream(&info, &h, &sat, &dir, &sst, 586267843Sdelphij &root_storage)) == -1) { 587226048Sobrien expn = "Cannot read short stream"; 588226048Sobrien goto out3; 589226048Sobrien } 590191739Sobrien#ifdef CDF_DEBUG 591226048Sobrien cdf_dump_dir(&info, &h, &sat, &ssat, &sst, &dir); 592191739Sobrien#endif 593267843Sdelphij#ifdef notdef 594267843Sdelphij if (root_storage) { 595267843Sdelphij if (NOTMIME(ms)) { 596267843Sdelphij char clsbuf[128]; 597267843Sdelphij if (file_printf(ms, "CLSID %s, ", 598267843Sdelphij format_clsid(clsbuf, sizeof(clsbuf), 599267843Sdelphij root_storage->d_storage_uuid)) == -1) 600267843Sdelphij return -1; 601267843Sdelphij } 602267843Sdelphij } 603267843Sdelphij#endif 604192348Sdelphij 605267843Sdelphij if ((i = cdf_read_user_stream(&info, &h, &sat, &ssat, &sst, &dir, 606267843Sdelphij "FileHeader", &scn)) != -1) { 607267843Sdelphij#define HWP5_SIGNATURE "HWP Document File" 608328875Seadler if (scn.sst_len * scn.sst_ss >= sizeof(HWP5_SIGNATURE) - 1 609267843Sdelphij && memcmp(scn.sst_tab, HWP5_SIGNATURE, 610267843Sdelphij sizeof(HWP5_SIGNATURE) - 1) == 0) { 611267843Sdelphij if (NOTMIME(ms)) { 612267843Sdelphij if (file_printf(ms, 613267843Sdelphij "Hangul (Korean) Word Processor File 5.x") == -1) 614267843Sdelphij return -1; 615267843Sdelphij } else { 616267843Sdelphij if (file_printf(ms, "application/x-hwp") == -1) 617267843Sdelphij return -1; 618267843Sdelphij } 619267843Sdelphij i = 1; 620267843Sdelphij goto out5; 621267843Sdelphij } else { 622309848Sdelphij cdf_zero_stream(&scn); 623267843Sdelphij } 624267843Sdelphij } 625267843Sdelphij 626226048Sobrien if ((i = cdf_read_summary_info(&info, &h, &sat, &ssat, &sst, &dir, 627226048Sobrien &scn)) == -1) { 628284778Sdelphij if (errno != ESRCH) { 629226048Sobrien expn = "Cannot read summary info"; 630284778Sdelphij } 631309848Sdelphij } else { 632309848Sdelphij i = cdf_check_summary_info(ms, &info, &h, 633309848Sdelphij &sat, &ssat, &sst, &dir, &scn, root_storage, &expn); 634309848Sdelphij cdf_zero_stream(&scn); 635284778Sdelphij } 636309848Sdelphij if (i <= 0) { 637309848Sdelphij if ((i = cdf_read_doc_summary_info(&info, &h, &sat, &ssat, 638309848Sdelphij &sst, &dir, &scn)) == -1) { 639309848Sdelphij if (errno != ESRCH) { 640309848Sdelphij expn = "Cannot read summary info"; 641267843Sdelphij } 642267843Sdelphij } else { 643309848Sdelphij i = cdf_check_summary_info(ms, &info, &h, &sat, &ssat, 644309848Sdelphij &sst, &dir, &scn, root_storage, &expn); 645267843Sdelphij } 646226048Sobrien } 647309848Sdelphij if (i <= 0) { 648309848Sdelphij i = cdf_file_dir_info(ms, &dir); 649309848Sdelphij if (i < 0) 650309848Sdelphij expn = "Cannot read section info"; 651309848Sdelphij } 652267843Sdelphijout5: 653309848Sdelphij cdf_zero_stream(&scn); 654309848Sdelphij cdf_zero_stream(&sst); 655191739Sobrienout3: 656226048Sobrien free(dir.dir_tab); 657191739Sobrienout2: 658226048Sobrien free(ssat.sat_tab); 659191739Sobrienout1: 660226048Sobrien free(sat.sat_tab); 661192348Sdelphijout0: 662267843Sdelphij if (i == -1) { 663267843Sdelphij if (NOTMIME(ms)) { 664267843Sdelphij if (file_printf(ms, 665267843Sdelphij "Composite Document File V2 Document") == -1) 666267843Sdelphij return -1; 667267843Sdelphij if (*expn) 668284778Sdelphij if (file_printf(ms, ", %s", expn) == -1) 669267843Sdelphij return -1; 670267843Sdelphij } else { 671309848Sdelphij if (file_printf(ms, "application/CDFV2") == -1) 672267843Sdelphij return -1; 673267843Sdelphij } 674267843Sdelphij i = 1; 675267843Sdelphij } 676226048Sobrien return i; 677191739Sobrien} 678