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 29284778SdelphijFILE_RCSID("@(#)$File: readcdf.c,v 1.53 2015/04/09 20:01:41 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[] = { 63267843Sdelphij { "WordDocument", "msword", }, 64267843Sdelphij { "PowerPoint", "vnd.ms-powerpoint", }, 65267843Sdelphij { "DigitalSignature", "vnd.ms-msi", }, 66267843Sdelphij { NULL, NULL, }, 67267843Sdelphij}, name2desc[] = { 68267843Sdelphij { "WordDocument", "Microsoft Office Word",}, 69267843Sdelphij { "PowerPoint", "Microsoft PowerPoint", }, 70267843Sdelphij { "DigitalSignature", "Microsoft Installer", }, 71267843Sdelphij { NULL, NULL, }, 72267843Sdelphij}; 73267843Sdelphij 74267843Sdelphijstatic const struct cv { 75267843Sdelphij uint64_t clsid[2]; 76267843Sdelphij const char *mime; 77267843Sdelphij} clsid2mime[] = { 78267843Sdelphij { 79276415Sdelphij { 0x00000000000c1084ULL, 0x46000000000000c0ULL }, 80267843Sdelphij "x-msi", 81267843Sdelphij }, 82267843Sdelphij { { 0, 0 }, 83267843Sdelphij NULL, 84267843Sdelphij }, 85267843Sdelphij}, clsid2desc[] = { 86267843Sdelphij { 87276415Sdelphij { 0x00000000000c1084ULL, 0x46000000000000c0ULL }, 88267843Sdelphij "MSI Installer", 89267843Sdelphij }, 90267843Sdelphij { { 0, 0 }, 91267843Sdelphij NULL, 92267843Sdelphij }, 93267843Sdelphij}; 94267843Sdelphij 95267843Sdelphijprivate const char * 96267843Sdelphijcdf_clsid_to_mime(const uint64_t clsid[2], const struct cv *cv) 97267843Sdelphij{ 98267843Sdelphij size_t i; 99267843Sdelphij for (i = 0; cv[i].mime != NULL; i++) { 100267843Sdelphij if (clsid[0] == cv[i].clsid[0] && clsid[1] == cv[i].clsid[1]) 101267843Sdelphij return cv[i].mime; 102267843Sdelphij } 103284778Sdelphij#ifdef CDF_DEBUG 104284778Sdelphij fprintf(stderr, "unknown mime %" PRIx64 ", %" PRIx64 "\n", clsid[0], 105284778Sdelphij clsid[1]); 106284778Sdelphij#endif 107267843Sdelphij return NULL; 108267843Sdelphij} 109267843Sdelphij 110267843Sdelphijprivate const char * 111267843Sdelphijcdf_app_to_mime(const char *vbuf, const struct nv *nv) 112267843Sdelphij{ 113267843Sdelphij size_t i; 114267843Sdelphij const char *rv = NULL; 115276415Sdelphij#ifdef USE_C_LOCALE 116276415Sdelphij locale_t old_lc_ctype, c_lc_ctype; 117267843Sdelphij 118276415Sdelphij c_lc_ctype = newlocale(LC_CTYPE_MASK, "C", 0); 119276415Sdelphij assert(c_lc_ctype != NULL); 120276415Sdelphij old_lc_ctype = uselocale(c_lc_ctype); 121267843Sdelphij assert(old_lc_ctype != NULL); 122276415Sdelphij#endif 123267843Sdelphij for (i = 0; nv[i].pattern != NULL; i++) 124267843Sdelphij if (strcasestr(vbuf, nv[i].pattern) != NULL) { 125267843Sdelphij rv = nv[i].mime; 126267843Sdelphij break; 127267843Sdelphij } 128284778Sdelphij#ifdef CDF_DEBUG 129284778Sdelphij fprintf(stderr, "unknown app %s\n", vbuf); 130284778Sdelphij#endif 131276415Sdelphij#ifdef USE_C_LOCALE 132276415Sdelphij (void)uselocale(old_lc_ctype); 133276415Sdelphij freelocale(c_lc_ctype); 134276415Sdelphij#endif 135267843Sdelphij return rv; 136267843Sdelphij} 137267843Sdelphij 138191739Sobrienprivate int 139191739Sobriencdf_file_property_info(struct magic_set *ms, const cdf_property_info_t *info, 140267843Sdelphij size_t count, const cdf_directory_t *root_storage) 141191739Sobrien{ 142226048Sobrien size_t i; 143226048Sobrien cdf_timestamp_t tp; 144226048Sobrien struct timespec ts; 145226048Sobrien char buf[64]; 146226048Sobrien const char *str = NULL; 147226048Sobrien const char *s; 148226048Sobrien int len; 149191739Sobrien 150267843Sdelphij if (!NOTMIME(ms) && root_storage) 151267843Sdelphij str = cdf_clsid_to_mime(root_storage->d_storage_uuid, 152267843Sdelphij clsid2mime); 153267843Sdelphij 154226048Sobrien for (i = 0; i < count; i++) { 155226048Sobrien cdf_print_property_name(buf, sizeof(buf), info[i].pi_id); 156226048Sobrien switch (info[i].pi_type) { 157226048Sobrien case CDF_NULL: 158226048Sobrien break; 159226048Sobrien case CDF_SIGNED16: 160226048Sobrien if (NOTMIME(ms) && file_printf(ms, ", %s: %hd", buf, 161226048Sobrien info[i].pi_s16) == -1) 162226048Sobrien return -1; 163226048Sobrien break; 164226048Sobrien case CDF_SIGNED32: 165226048Sobrien if (NOTMIME(ms) && file_printf(ms, ", %s: %d", buf, 166226048Sobrien info[i].pi_s32) == -1) 167226048Sobrien return -1; 168226048Sobrien break; 169226048Sobrien case CDF_UNSIGNED32: 170226048Sobrien if (NOTMIME(ms) && file_printf(ms, ", %s: %u", buf, 171226048Sobrien info[i].pi_u32) == -1) 172226048Sobrien return -1; 173226048Sobrien break; 174234250Sobrien case CDF_FLOAT: 175234250Sobrien if (NOTMIME(ms) && file_printf(ms, ", %s: %g", buf, 176234250Sobrien info[i].pi_f) == -1) 177234250Sobrien return -1; 178234250Sobrien break; 179234250Sobrien case CDF_DOUBLE: 180234250Sobrien if (NOTMIME(ms) && file_printf(ms, ", %s: %g", buf, 181234250Sobrien info[i].pi_d) == -1) 182234250Sobrien return -1; 183234250Sobrien break; 184226048Sobrien case CDF_LENGTH32_STRING: 185226048Sobrien case CDF_LENGTH32_WSTRING: 186226048Sobrien len = info[i].pi_str.s_len; 187226048Sobrien if (len > 1) { 188226048Sobrien char vbuf[1024]; 189226048Sobrien size_t j, k = 1; 190191739Sobrien 191226048Sobrien if (info[i].pi_type == CDF_LENGTH32_WSTRING) 192226048Sobrien k++; 193226048Sobrien s = info[i].pi_str.s_buf; 194267843Sdelphij for (j = 0; j < sizeof(vbuf) && len--; s += k) { 195226048Sobrien if (*s == '\0') 196226048Sobrien break; 197226048Sobrien if (isprint((unsigned char)*s)) 198267843Sdelphij vbuf[j++] = *s; 199226048Sobrien } 200226048Sobrien if (j == sizeof(vbuf)) 201226048Sobrien --j; 202226048Sobrien vbuf[j] = '\0'; 203226048Sobrien if (NOTMIME(ms)) { 204226048Sobrien if (vbuf[0]) { 205226048Sobrien if (file_printf(ms, ", %s: %s", 206226048Sobrien buf, vbuf) == -1) 207226048Sobrien return -1; 208226048Sobrien } 209267843Sdelphij } else if (str == NULL && info[i].pi_id == 210267843Sdelphij CDF_PROPERTY_NAME_OF_APPLICATION) { 211267843Sdelphij str = cdf_app_to_mime(vbuf, app2mime); 212267843Sdelphij } 213267843Sdelphij } 214226048Sobrien break; 215226048Sobrien case CDF_FILETIME: 216226048Sobrien tp = info[i].pi_tp; 217226048Sobrien if (tp != 0) { 218267843Sdelphij char tbuf[64]; 219226048Sobrien if (tp < 1000000000000000LL) { 220226048Sobrien cdf_print_elapsed_time(tbuf, 221226048Sobrien sizeof(tbuf), tp); 222226048Sobrien if (NOTMIME(ms) && file_printf(ms, 223226048Sobrien ", %s: %s", buf, tbuf) == -1) 224226048Sobrien return -1; 225226048Sobrien } else { 226226048Sobrien char *c, *ec; 227226048Sobrien cdf_timestamp_to_timespec(&ts, tp); 228267843Sdelphij c = cdf_ctime(&ts.tv_sec, tbuf); 229267843Sdelphij if (c != NULL && 230267843Sdelphij (ec = strchr(c, '\n')) != NULL) 231267843Sdelphij *ec = '\0'; 232226048Sobrien 233226048Sobrien if (NOTMIME(ms) && file_printf(ms, 234226048Sobrien ", %s: %s", buf, c) == -1) 235226048Sobrien return -1; 236226048Sobrien } 237226048Sobrien } 238226048Sobrien break; 239226048Sobrien case CDF_CLIPBOARD: 240226048Sobrien break; 241226048Sobrien default: 242226048Sobrien return -1; 243226048Sobrien } 244226048Sobrien } 245226048Sobrien if (!NOTMIME(ms)) { 246226048Sobrien if (str == NULL) 247226048Sobrien return 0; 248234250Sobrien if (file_printf(ms, "application/%s", str) == -1) 249234250Sobrien return -1; 250226048Sobrien } 251226048Sobrien return 1; 252191739Sobrien} 253191739Sobrien 254191739Sobrienprivate int 255276415Sdelphijcdf_file_catalog(struct magic_set *ms, const cdf_header_t *h, 256276415Sdelphij const cdf_stream_t *sst) 257276415Sdelphij{ 258276415Sdelphij cdf_catalog_t *cat; 259276415Sdelphij size_t i; 260276415Sdelphij char buf[256]; 261276415Sdelphij cdf_catalog_entry_t *ce; 262276415Sdelphij 263276415Sdelphij if (NOTMIME(ms)) { 264276415Sdelphij if (file_printf(ms, "Microsoft Thumbs.db [") == -1) 265276415Sdelphij return -1; 266276415Sdelphij if (cdf_unpack_catalog(h, sst, &cat) == -1) 267276415Sdelphij return -1; 268276415Sdelphij ce = cat->cat_e; 269276415Sdelphij /* skip first entry since it has a , or paren */ 270276415Sdelphij for (i = 1; i < cat->cat_num; i++) 271276415Sdelphij if (file_printf(ms, "%s%s", 272276415Sdelphij cdf_u16tos8(buf, ce[i].ce_namlen, ce[i].ce_name), 273276415Sdelphij i == cat->cat_num - 1 ? "]" : ", ") == -1) { 274276415Sdelphij free(cat); 275276415Sdelphij return -1; 276276415Sdelphij } 277276415Sdelphij free(cat); 278276415Sdelphij } else { 279276415Sdelphij if (file_printf(ms, "application/CDFV2") == -1) 280276415Sdelphij return -1; 281276415Sdelphij } 282276415Sdelphij return 1; 283276415Sdelphij} 284276415Sdelphij 285276415Sdelphijprivate int 286226048Sobriencdf_file_summary_info(struct magic_set *ms, const cdf_header_t *h, 287267843Sdelphij const cdf_stream_t *sst, const cdf_directory_t *root_storage) 288191739Sobrien{ 289226048Sobrien cdf_summary_info_header_t si; 290226048Sobrien cdf_property_info_t *info; 291226048Sobrien size_t count; 292226048Sobrien int m; 293191739Sobrien 294226048Sobrien if (cdf_unpack_summary_info(sst, h, &si, &info, &count) == -1) 295226048Sobrien return -1; 296191739Sobrien 297226048Sobrien if (NOTMIME(ms)) { 298267843Sdelphij const char *str; 299267843Sdelphij 300234250Sobrien if (file_printf(ms, "Composite Document File V2 Document") 301234250Sobrien == -1) 302226048Sobrien return -1; 303191739Sobrien 304226048Sobrien if (file_printf(ms, ", %s Endian", 305226048Sobrien si.si_byte_order == 0xfffe ? "Little" : "Big") == -1) 306234250Sobrien return -2; 307226048Sobrien switch (si.si_os) { 308226048Sobrien case 2: 309226048Sobrien if (file_printf(ms, ", Os: Windows, Version %d.%d", 310226048Sobrien si.si_os_version & 0xff, 311226048Sobrien (uint32_t)si.si_os_version >> 8) == -1) 312234250Sobrien return -2; 313226048Sobrien break; 314226048Sobrien case 1: 315226048Sobrien if (file_printf(ms, ", Os: MacOS, Version %d.%d", 316226048Sobrien (uint32_t)si.si_os_version >> 8, 317226048Sobrien si.si_os_version & 0xff) == -1) 318234250Sobrien return -2; 319226048Sobrien break; 320226048Sobrien default: 321226048Sobrien if (file_printf(ms, ", Os %d, Version: %d.%d", si.si_os, 322226048Sobrien si.si_os_version & 0xff, 323226048Sobrien (uint32_t)si.si_os_version >> 8) == -1) 324234250Sobrien return -2; 325226048Sobrien break; 326226048Sobrien } 327267843Sdelphij if (root_storage) { 328267843Sdelphij str = cdf_clsid_to_mime(root_storage->d_storage_uuid, 329267843Sdelphij clsid2desc); 330276415Sdelphij if (str) { 331267843Sdelphij if (file_printf(ms, ", %s", str) == -1) 332267843Sdelphij return -2; 333267843Sdelphij } 334267843Sdelphij } 335276415Sdelphij } 336191739Sobrien 337267843Sdelphij m = cdf_file_property_info(ms, info, count, root_storage); 338226048Sobrien free(info); 339191739Sobrien 340234250Sobrien return m == -1 ? -2 : m; 341191739Sobrien} 342191739Sobrien 343267843Sdelphij#ifdef notdef 344267843Sdelphijprivate char * 345267843Sdelphijformat_clsid(char *buf, size_t len, const uint64_t uuid[2]) { 346267843Sdelphij snprintf(buf, len, "%.8" PRIx64 "-%.4" PRIx64 "-%.4" PRIx64 "-%.4" 347267843Sdelphij PRIx64 "-%.12" PRIx64, 348276415Sdelphij (uuid[0] >> 32) & (uint64_t)0x000000000ffffffffULL, 349276415Sdelphij (uuid[0] >> 16) & (uint64_t)0x0000000000000ffffULL, 350276415Sdelphij (uuid[0] >> 0) & (uint64_t)0x0000000000000ffffULL, 351276415Sdelphij (uuid[1] >> 48) & (uint64_t)0x0000000000000ffffULL, 352276415Sdelphij (uuid[1] >> 0) & (uint64_t)0x0000fffffffffffffULL); 353267843Sdelphij return buf; 354267843Sdelphij} 355267843Sdelphij#endif 356267843Sdelphij 357284778Sdelphijprivate int 358284778Sdelphijcdf_file_catalog_info(struct magic_set *ms, const cdf_info_t *info, 359284778Sdelphij const cdf_header_t *h, const cdf_sat_t *sat, const cdf_sat_t *ssat, 360284778Sdelphij const cdf_stream_t *sst, const cdf_dir_t *dir, cdf_stream_t *scn) 361284778Sdelphij{ 362284778Sdelphij int i; 363284778Sdelphij 364284778Sdelphij if ((i = cdf_read_user_stream(info, h, sat, ssat, sst, 365284778Sdelphij dir, "Catalog", scn)) == -1) 366284778Sdelphij return i; 367284778Sdelphij#ifdef CDF_DEBUG 368284778Sdelphij cdf_dump_catalog(&h, &scn); 369284778Sdelphij#endif 370284778Sdelphij if ((i = cdf_file_catalog(ms, h, scn)) == -1) 371284778Sdelphij return -1; 372284778Sdelphij return i; 373284778Sdelphij} 374284778Sdelphij 375284778Sdelphijprivate struct sinfo { 376284778Sdelphij const char *name; 377284778Sdelphij const char *mime; 378284778Sdelphij const char *sections[5]; 379284778Sdelphij const int types[5]; 380284778Sdelphij} sectioninfo[] = { 381284778Sdelphij { "Encrypted", "encrypted", 382284778Sdelphij { 383284778Sdelphij "EncryptedPackage", NULL, NULL, NULL, NULL, 384284778Sdelphij }, 385284778Sdelphij { 386284778Sdelphij CDF_DIR_TYPE_USER_STREAM, 0, 0, 0, 0, 387284778Sdelphij 388284778Sdelphij }, 389284778Sdelphij }, 390284778Sdelphij { "QuickBooks", "quickbooks", 391284778Sdelphij { 392284778Sdelphij#if 0 393284778Sdelphij "TaxForms", "PDFTaxForms", "modulesInBackup", 394284778Sdelphij#endif 395284778Sdelphij "mfbu_header", NULL, NULL, NULL, NULL, 396284778Sdelphij }, 397284778Sdelphij { 398284778Sdelphij#if 0 399284778Sdelphij CDF_DIR_TYPE_USER_STORAGE, 400284778Sdelphij CDF_DIR_TYPE_USER_STORAGE, 401284778Sdelphij CDF_DIR_TYPE_USER_STREAM, 402284778Sdelphij#endif 403284778Sdelphij CDF_DIR_TYPE_USER_STREAM, 404284778Sdelphij 0, 0, 0, 0 405284778Sdelphij }, 406284778Sdelphij }, 407284778Sdelphij}; 408284778Sdelphij 409284778Sdelphijprivate int 410284778Sdelphijcdf_file_dir_info(struct magic_set *ms, const cdf_dir_t *dir) 411284778Sdelphij{ 412284778Sdelphij size_t sd, j; 413284778Sdelphij 414284778Sdelphij for (sd = 0; sd < __arraycount(sectioninfo); sd++) { 415284778Sdelphij const struct sinfo *si = §ioninfo[sd]; 416284778Sdelphij for (j = 0; si->sections[j]; j++) { 417284778Sdelphij if (cdf_find_stream(dir, si->sections[j], si->types[j]) 418284778Sdelphij <= 0) { 419284778Sdelphij#ifdef CDF_DEBUG 420284778Sdelphij fprintf(stderr, "Can't read %s\n", 421284778Sdelphij si->sections[j]); 422284778Sdelphij#endif 423284778Sdelphij break; 424284778Sdelphij } 425284778Sdelphij } 426284778Sdelphij if (si->sections[j] != NULL) 427284778Sdelphij continue; 428284778Sdelphij if (NOTMIME(ms)) { 429284778Sdelphij if (file_printf(ms, "CDFV2 %s", si->name) == -1) 430284778Sdelphij return -1; 431284778Sdelphij } else { 432284778Sdelphij if (file_printf(ms, "application/CDFV2-%s", 433284778Sdelphij si->mime) == -1) 434284778Sdelphij return -1; 435284778Sdelphij } 436284778Sdelphij return 1; 437284778Sdelphij } 438284778Sdelphij return -1; 439284778Sdelphij} 440284778Sdelphij 441191739Sobrienprotected int 442191739Sobrienfile_trycdf(struct magic_set *ms, int fd, const unsigned char *buf, 443191739Sobrien size_t nbytes) 444191739Sobrien{ 445226048Sobrien cdf_info_t info; 446226048Sobrien cdf_header_t h; 447226048Sobrien cdf_sat_t sat, ssat; 448226048Sobrien cdf_stream_t sst, scn; 449226048Sobrien cdf_dir_t dir; 450226048Sobrien int i; 451226048Sobrien const char *expn = ""; 452276415Sdelphij const cdf_directory_t *root_storage; 453191739Sobrien 454226048Sobrien info.i_fd = fd; 455226048Sobrien info.i_buf = buf; 456226048Sobrien info.i_len = nbytes; 457284778Sdelphij if (ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION)) 458226048Sobrien return 0; 459226048Sobrien if (cdf_read_header(&info, &h) == -1) 460226048Sobrien return 0; 461191739Sobrien#ifdef CDF_DEBUG 462226048Sobrien cdf_dump_header(&h); 463191739Sobrien#endif 464191739Sobrien 465226048Sobrien if ((i = cdf_read_sat(&info, &h, &sat)) == -1) { 466226048Sobrien expn = "Can't read SAT"; 467226048Sobrien goto out0; 468226048Sobrien } 469191739Sobrien#ifdef CDF_DEBUG 470226048Sobrien cdf_dump_sat("SAT", &sat, CDF_SEC_SIZE(&h)); 471191739Sobrien#endif 472191739Sobrien 473226048Sobrien if ((i = cdf_read_ssat(&info, &h, &sat, &ssat)) == -1) { 474226048Sobrien expn = "Can't read SSAT"; 475226048Sobrien goto out1; 476226048Sobrien } 477191739Sobrien#ifdef CDF_DEBUG 478226048Sobrien cdf_dump_sat("SSAT", &ssat, CDF_SHORT_SEC_SIZE(&h)); 479191739Sobrien#endif 480191739Sobrien 481226048Sobrien if ((i = cdf_read_dir(&info, &h, &sat, &dir)) == -1) { 482226048Sobrien expn = "Can't read directory"; 483226048Sobrien goto out2; 484226048Sobrien } 485191739Sobrien 486267843Sdelphij if ((i = cdf_read_short_stream(&info, &h, &sat, &dir, &sst, 487267843Sdelphij &root_storage)) == -1) { 488226048Sobrien expn = "Cannot read short stream"; 489226048Sobrien goto out3; 490226048Sobrien } 491191739Sobrien#ifdef CDF_DEBUG 492226048Sobrien cdf_dump_dir(&info, &h, &sat, &ssat, &sst, &dir); 493191739Sobrien#endif 494267843Sdelphij#ifdef notdef 495267843Sdelphij if (root_storage) { 496267843Sdelphij if (NOTMIME(ms)) { 497267843Sdelphij char clsbuf[128]; 498267843Sdelphij if (file_printf(ms, "CLSID %s, ", 499267843Sdelphij format_clsid(clsbuf, sizeof(clsbuf), 500267843Sdelphij root_storage->d_storage_uuid)) == -1) 501267843Sdelphij return -1; 502267843Sdelphij } 503267843Sdelphij } 504267843Sdelphij#endif 505192348Sdelphij 506267843Sdelphij if ((i = cdf_read_user_stream(&info, &h, &sat, &ssat, &sst, &dir, 507267843Sdelphij "FileHeader", &scn)) != -1) { 508267843Sdelphij#define HWP5_SIGNATURE "HWP Document File" 509267843Sdelphij if (scn.sst_dirlen >= sizeof(HWP5_SIGNATURE) - 1 510267843Sdelphij && memcmp(scn.sst_tab, HWP5_SIGNATURE, 511267843Sdelphij sizeof(HWP5_SIGNATURE) - 1) == 0) { 512267843Sdelphij if (NOTMIME(ms)) { 513267843Sdelphij if (file_printf(ms, 514267843Sdelphij "Hangul (Korean) Word Processor File 5.x") == -1) 515267843Sdelphij return -1; 516267843Sdelphij } else { 517267843Sdelphij if (file_printf(ms, "application/x-hwp") == -1) 518267843Sdelphij return -1; 519267843Sdelphij } 520267843Sdelphij i = 1; 521267843Sdelphij goto out5; 522267843Sdelphij } else { 523267843Sdelphij free(scn.sst_tab); 524267843Sdelphij scn.sst_tab = NULL; 525267843Sdelphij scn.sst_len = 0; 526267843Sdelphij scn.sst_dirlen = 0; 527267843Sdelphij } 528267843Sdelphij } 529267843Sdelphij 530226048Sobrien if ((i = cdf_read_summary_info(&info, &h, &sat, &ssat, &sst, &dir, 531226048Sobrien &scn)) == -1) { 532284778Sdelphij if (errno != ESRCH) { 533226048Sobrien expn = "Cannot read summary info"; 534284778Sdelphij goto out4; 535284778Sdelphij } 536284778Sdelphij i = cdf_file_catalog_info(ms, &info, &h, &sat, &ssat, &sst, 537284778Sdelphij &dir, &scn); 538284778Sdelphij if (i > 0) 539284778Sdelphij goto out4; 540284778Sdelphij i = cdf_file_dir_info(ms, &dir); 541284778Sdelphij if (i < 0) 542284778Sdelphij expn = "Cannot read section info"; 543284778Sdelphij goto out4; 544284778Sdelphij } 545284778Sdelphij 546284778Sdelphij 547191739Sobrien#ifdef CDF_DEBUG 548226048Sobrien cdf_dump_summary_info(&h, &scn); 549191739Sobrien#endif 550267843Sdelphij if ((i = cdf_file_summary_info(ms, &h, &scn, root_storage)) < 0) 551267843Sdelphij expn = "Can't expand summary_info"; 552267843Sdelphij 553226048Sobrien if (i == 0) { 554267843Sdelphij const char *str = NULL; 555226048Sobrien cdf_directory_t *d; 556226048Sobrien char name[__arraycount(d->d_name)]; 557226048Sobrien size_t j, k; 558267843Sdelphij 559267843Sdelphij for (j = 0; str == NULL && j < dir.dir_len; j++) { 560267843Sdelphij d = &dir.dir_tab[j]; 561267843Sdelphij for (k = 0; k < sizeof(name); k++) 562267843Sdelphij name[k] = (char)cdf_tole2(d->d_name[k]); 563267843Sdelphij str = cdf_app_to_mime(name, 564267843Sdelphij NOTMIME(ms) ? name2desc : name2mime); 565226048Sobrien } 566267843Sdelphij if (NOTMIME(ms)) { 567267843Sdelphij if (str != NULL) { 568267843Sdelphij if (file_printf(ms, "%s", str) == -1) 569267843Sdelphij return -1; 570267843Sdelphij i = 1; 571267843Sdelphij } 572267843Sdelphij } else { 573267843Sdelphij if (str == NULL) 574267843Sdelphij str = "vnd.ms-office"; 575267843Sdelphij if (file_printf(ms, "application/%s", str) == -1) 576267843Sdelphij return -1; 577267843Sdelphij i = 1; 578267843Sdelphij } 579226048Sobrien } 580267843Sdelphijout5: 581226048Sobrien free(scn.sst_tab); 582191739Sobrienout4: 583226048Sobrien free(sst.sst_tab); 584191739Sobrienout3: 585226048Sobrien free(dir.dir_tab); 586191739Sobrienout2: 587226048Sobrien free(ssat.sat_tab); 588191739Sobrienout1: 589226048Sobrien free(sat.sat_tab); 590192348Sdelphijout0: 591267843Sdelphij if (i == -1) { 592267843Sdelphij if (NOTMIME(ms)) { 593267843Sdelphij if (file_printf(ms, 594267843Sdelphij "Composite Document File V2 Document") == -1) 595267843Sdelphij return -1; 596267843Sdelphij if (*expn) 597284778Sdelphij if (file_printf(ms, ", %s", expn) == -1) 598267843Sdelphij return -1; 599267843Sdelphij } else { 600284778Sdelphij if (file_printf(ms, "application/CDFV2-unknown") == -1) 601267843Sdelphij return -1; 602267843Sdelphij } 603267843Sdelphij i = 1; 604267843Sdelphij } 605226048Sobrien return i; 606191739Sobrien} 607