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 29284193SdelphijFILE_RCSID("@(#)$File: readcdf.c,v 1.49 2014/12/04 15:56:46 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 42191739Sobrien#define NOTMIME(ms) (((ms)->flags & MAGIC_MIME) == 0) 43191739Sobrien 44267843Sdelphijstatic const struct nv { 45267843Sdelphij const char *pattern; 46267843Sdelphij const char *mime; 47267843Sdelphij} app2mime[] = { 48267843Sdelphij { "Word", "msword", }, 49267843Sdelphij { "Excel", "vnd.ms-excel", }, 50267843Sdelphij { "Powerpoint", "vnd.ms-powerpoint", }, 51267843Sdelphij { "Crystal Reports", "x-rpt", }, 52267843Sdelphij { "Advanced Installer", "vnd.ms-msi", }, 53267843Sdelphij { "InstallShield", "vnd.ms-msi", }, 54267843Sdelphij { "Microsoft Patch Compiler", "vnd.ms-msi", }, 55267843Sdelphij { "NAnt", "vnd.ms-msi", }, 56267843Sdelphij { "Windows Installer", "vnd.ms-msi", }, 57267843Sdelphij { NULL, NULL, }, 58267843Sdelphij}, name2mime[] = { 59267843Sdelphij { "WordDocument", "msword", }, 60267843Sdelphij { "PowerPoint", "vnd.ms-powerpoint", }, 61267843Sdelphij { "DigitalSignature", "vnd.ms-msi", }, 62267843Sdelphij { NULL, NULL, }, 63267843Sdelphij}, name2desc[] = { 64267843Sdelphij { "WordDocument", "Microsoft Office Word",}, 65267843Sdelphij { "PowerPoint", "Microsoft PowerPoint", }, 66267843Sdelphij { "DigitalSignature", "Microsoft Installer", }, 67267843Sdelphij { NULL, NULL, }, 68267843Sdelphij}; 69267843Sdelphij 70267843Sdelphijstatic const struct cv { 71267843Sdelphij uint64_t clsid[2]; 72267843Sdelphij const char *mime; 73267843Sdelphij} clsid2mime[] = { 74267843Sdelphij { 75284193Sdelphij { 0x00000000000c1084ULL, 0x46000000000000c0ULL }, 76267843Sdelphij "x-msi", 77267843Sdelphij }, 78267843Sdelphij { { 0, 0 }, 79267843Sdelphij NULL, 80267843Sdelphij }, 81267843Sdelphij}, clsid2desc[] = { 82267843Sdelphij { 83284193Sdelphij { 0x00000000000c1084ULL, 0x46000000000000c0ULL }, 84267843Sdelphij "MSI Installer", 85267843Sdelphij }, 86267843Sdelphij { { 0, 0 }, 87267843Sdelphij NULL, 88267843Sdelphij }, 89267843Sdelphij}; 90267843Sdelphij 91267843Sdelphijprivate const char * 92267843Sdelphijcdf_clsid_to_mime(const uint64_t clsid[2], const struct cv *cv) 93267843Sdelphij{ 94267843Sdelphij size_t i; 95267843Sdelphij for (i = 0; cv[i].mime != NULL; i++) { 96267843Sdelphij if (clsid[0] == cv[i].clsid[0] && clsid[1] == cv[i].clsid[1]) 97267843Sdelphij return cv[i].mime; 98267843Sdelphij } 99267843Sdelphij return NULL; 100267843Sdelphij} 101267843Sdelphij 102267843Sdelphijprivate const char * 103267843Sdelphijcdf_app_to_mime(const char *vbuf, const struct nv *nv) 104267843Sdelphij{ 105267843Sdelphij size_t i; 106267843Sdelphij const char *rv = NULL; 107284193Sdelphij#ifdef USE_C_LOCALE 108284193Sdelphij locale_t old_lc_ctype, c_lc_ctype; 109267843Sdelphij 110284193Sdelphij c_lc_ctype = newlocale(LC_CTYPE_MASK, "C", 0); 111284193Sdelphij assert(c_lc_ctype != NULL); 112284193Sdelphij old_lc_ctype = uselocale(c_lc_ctype); 113267843Sdelphij assert(old_lc_ctype != NULL); 114284193Sdelphij#endif 115267843Sdelphij for (i = 0; nv[i].pattern != NULL; i++) 116267843Sdelphij if (strcasestr(vbuf, nv[i].pattern) != NULL) { 117267843Sdelphij rv = nv[i].mime; 118267843Sdelphij break; 119267843Sdelphij } 120284193Sdelphij#ifdef USE_C_LOCALE 121284193Sdelphij (void)uselocale(old_lc_ctype); 122284193Sdelphij freelocale(c_lc_ctype); 123284193Sdelphij#endif 124267843Sdelphij return rv; 125267843Sdelphij} 126267843Sdelphij 127191739Sobrienprivate int 128191739Sobriencdf_file_property_info(struct magic_set *ms, const cdf_property_info_t *info, 129267843Sdelphij size_t count, const cdf_directory_t *root_storage) 130191739Sobrien{ 131226048Sobrien size_t i; 132226048Sobrien cdf_timestamp_t tp; 133226048Sobrien struct timespec ts; 134226048Sobrien char buf[64]; 135226048Sobrien const char *str = NULL; 136226048Sobrien const char *s; 137226048Sobrien int len; 138191739Sobrien 139267843Sdelphij if (!NOTMIME(ms) && root_storage) 140267843Sdelphij str = cdf_clsid_to_mime(root_storage->d_storage_uuid, 141267843Sdelphij clsid2mime); 142267843Sdelphij 143226048Sobrien for (i = 0; i < count; i++) { 144226048Sobrien cdf_print_property_name(buf, sizeof(buf), info[i].pi_id); 145226048Sobrien switch (info[i].pi_type) { 146226048Sobrien case CDF_NULL: 147226048Sobrien break; 148226048Sobrien case CDF_SIGNED16: 149226048Sobrien if (NOTMIME(ms) && file_printf(ms, ", %s: %hd", buf, 150226048Sobrien info[i].pi_s16) == -1) 151226048Sobrien return -1; 152226048Sobrien break; 153226048Sobrien case CDF_SIGNED32: 154226048Sobrien if (NOTMIME(ms) && file_printf(ms, ", %s: %d", buf, 155226048Sobrien info[i].pi_s32) == -1) 156226048Sobrien return -1; 157226048Sobrien break; 158226048Sobrien case CDF_UNSIGNED32: 159226048Sobrien if (NOTMIME(ms) && file_printf(ms, ", %s: %u", buf, 160226048Sobrien info[i].pi_u32) == -1) 161226048Sobrien return -1; 162226048Sobrien break; 163234250Sobrien case CDF_FLOAT: 164234250Sobrien if (NOTMIME(ms) && file_printf(ms, ", %s: %g", buf, 165234250Sobrien info[i].pi_f) == -1) 166234250Sobrien return -1; 167234250Sobrien break; 168234250Sobrien case CDF_DOUBLE: 169234250Sobrien if (NOTMIME(ms) && file_printf(ms, ", %s: %g", buf, 170234250Sobrien info[i].pi_d) == -1) 171234250Sobrien return -1; 172234250Sobrien break; 173226048Sobrien case CDF_LENGTH32_STRING: 174226048Sobrien case CDF_LENGTH32_WSTRING: 175226048Sobrien len = info[i].pi_str.s_len; 176226048Sobrien if (len > 1) { 177226048Sobrien char vbuf[1024]; 178226048Sobrien size_t j, k = 1; 179191739Sobrien 180226048Sobrien if (info[i].pi_type == CDF_LENGTH32_WSTRING) 181226048Sobrien k++; 182226048Sobrien s = info[i].pi_str.s_buf; 183267843Sdelphij for (j = 0; j < sizeof(vbuf) && len--; s += k) { 184226048Sobrien if (*s == '\0') 185226048Sobrien break; 186226048Sobrien if (isprint((unsigned char)*s)) 187267843Sdelphij vbuf[j++] = *s; 188226048Sobrien } 189226048Sobrien if (j == sizeof(vbuf)) 190226048Sobrien --j; 191226048Sobrien vbuf[j] = '\0'; 192226048Sobrien if (NOTMIME(ms)) { 193226048Sobrien if (vbuf[0]) { 194226048Sobrien if (file_printf(ms, ", %s: %s", 195226048Sobrien buf, vbuf) == -1) 196226048Sobrien return -1; 197226048Sobrien } 198267843Sdelphij } else if (str == NULL && info[i].pi_id == 199267843Sdelphij CDF_PROPERTY_NAME_OF_APPLICATION) { 200267843Sdelphij str = cdf_app_to_mime(vbuf, app2mime); 201267843Sdelphij } 202267843Sdelphij } 203226048Sobrien break; 204226048Sobrien case CDF_FILETIME: 205226048Sobrien tp = info[i].pi_tp; 206226048Sobrien if (tp != 0) { 207267843Sdelphij char tbuf[64]; 208226048Sobrien if (tp < 1000000000000000LL) { 209226048Sobrien cdf_print_elapsed_time(tbuf, 210226048Sobrien sizeof(tbuf), tp); 211226048Sobrien if (NOTMIME(ms) && file_printf(ms, 212226048Sobrien ", %s: %s", buf, tbuf) == -1) 213226048Sobrien return -1; 214226048Sobrien } else { 215226048Sobrien char *c, *ec; 216226048Sobrien cdf_timestamp_to_timespec(&ts, tp); 217267843Sdelphij c = cdf_ctime(&ts.tv_sec, tbuf); 218267843Sdelphij if (c != NULL && 219267843Sdelphij (ec = strchr(c, '\n')) != NULL) 220267843Sdelphij *ec = '\0'; 221226048Sobrien 222226048Sobrien if (NOTMIME(ms) && file_printf(ms, 223226048Sobrien ", %s: %s", buf, c) == -1) 224226048Sobrien return -1; 225226048Sobrien } 226226048Sobrien } 227226048Sobrien break; 228226048Sobrien case CDF_CLIPBOARD: 229226048Sobrien break; 230226048Sobrien default: 231226048Sobrien return -1; 232226048Sobrien } 233226048Sobrien } 234226048Sobrien if (!NOTMIME(ms)) { 235226048Sobrien if (str == NULL) 236226048Sobrien return 0; 237234250Sobrien if (file_printf(ms, "application/%s", str) == -1) 238234250Sobrien return -1; 239226048Sobrien } 240226048Sobrien return 1; 241191739Sobrien} 242191739Sobrien 243191739Sobrienprivate int 244284193Sdelphijcdf_file_catalog(struct magic_set *ms, const cdf_header_t *h, 245284193Sdelphij const cdf_stream_t *sst) 246284193Sdelphij{ 247284193Sdelphij cdf_catalog_t *cat; 248284193Sdelphij size_t i; 249284193Sdelphij char buf[256]; 250284193Sdelphij cdf_catalog_entry_t *ce; 251284193Sdelphij 252284193Sdelphij if (NOTMIME(ms)) { 253284193Sdelphij if (file_printf(ms, "Microsoft Thumbs.db [") == -1) 254284193Sdelphij return -1; 255284193Sdelphij if (cdf_unpack_catalog(h, sst, &cat) == -1) 256284193Sdelphij return -1; 257284193Sdelphij ce = cat->cat_e; 258284193Sdelphij /* skip first entry since it has a , or paren */ 259284193Sdelphij for (i = 1; i < cat->cat_num; i++) 260284193Sdelphij if (file_printf(ms, "%s%s", 261284193Sdelphij cdf_u16tos8(buf, ce[i].ce_namlen, ce[i].ce_name), 262284193Sdelphij i == cat->cat_num - 1 ? "]" : ", ") == -1) { 263284193Sdelphij free(cat); 264284193Sdelphij return -1; 265284193Sdelphij } 266284193Sdelphij free(cat); 267284193Sdelphij } else { 268284193Sdelphij if (file_printf(ms, "application/CDFV2") == -1) 269284193Sdelphij return -1; 270284193Sdelphij } 271284193Sdelphij return 1; 272284193Sdelphij} 273284193Sdelphij 274284193Sdelphijprivate int 275226048Sobriencdf_file_summary_info(struct magic_set *ms, const cdf_header_t *h, 276267843Sdelphij const cdf_stream_t *sst, const cdf_directory_t *root_storage) 277191739Sobrien{ 278226048Sobrien cdf_summary_info_header_t si; 279226048Sobrien cdf_property_info_t *info; 280226048Sobrien size_t count; 281226048Sobrien int m; 282191739Sobrien 283226048Sobrien if (cdf_unpack_summary_info(sst, h, &si, &info, &count) == -1) 284226048Sobrien return -1; 285191739Sobrien 286226048Sobrien if (NOTMIME(ms)) { 287267843Sdelphij const char *str; 288267843Sdelphij 289234250Sobrien if (file_printf(ms, "Composite Document File V2 Document") 290234250Sobrien == -1) 291226048Sobrien return -1; 292191739Sobrien 293226048Sobrien if (file_printf(ms, ", %s Endian", 294226048Sobrien si.si_byte_order == 0xfffe ? "Little" : "Big") == -1) 295234250Sobrien return -2; 296226048Sobrien switch (si.si_os) { 297226048Sobrien case 2: 298226048Sobrien if (file_printf(ms, ", Os: Windows, Version %d.%d", 299226048Sobrien si.si_os_version & 0xff, 300226048Sobrien (uint32_t)si.si_os_version >> 8) == -1) 301234250Sobrien return -2; 302226048Sobrien break; 303226048Sobrien case 1: 304226048Sobrien if (file_printf(ms, ", Os: MacOS, Version %d.%d", 305226048Sobrien (uint32_t)si.si_os_version >> 8, 306226048Sobrien si.si_os_version & 0xff) == -1) 307234250Sobrien return -2; 308226048Sobrien break; 309226048Sobrien default: 310226048Sobrien if (file_printf(ms, ", Os %d, Version: %d.%d", si.si_os, 311226048Sobrien si.si_os_version & 0xff, 312226048Sobrien (uint32_t)si.si_os_version >> 8) == -1) 313234250Sobrien return -2; 314226048Sobrien break; 315226048Sobrien } 316267843Sdelphij if (root_storage) { 317267843Sdelphij str = cdf_clsid_to_mime(root_storage->d_storage_uuid, 318267843Sdelphij clsid2desc); 319284193Sdelphij if (str) { 320267843Sdelphij if (file_printf(ms, ", %s", str) == -1) 321267843Sdelphij return -2; 322267843Sdelphij } 323267843Sdelphij } 324284193Sdelphij } 325191739Sobrien 326267843Sdelphij m = cdf_file_property_info(ms, info, count, root_storage); 327226048Sobrien free(info); 328191739Sobrien 329234250Sobrien return m == -1 ? -2 : m; 330191739Sobrien} 331191739Sobrien 332267843Sdelphij#ifdef notdef 333267843Sdelphijprivate char * 334267843Sdelphijformat_clsid(char *buf, size_t len, const uint64_t uuid[2]) { 335267843Sdelphij snprintf(buf, len, "%.8" PRIx64 "-%.4" PRIx64 "-%.4" PRIx64 "-%.4" 336267843Sdelphij PRIx64 "-%.12" PRIx64, 337284193Sdelphij (uuid[0] >> 32) & (uint64_t)0x000000000ffffffffULL, 338284193Sdelphij (uuid[0] >> 16) & (uint64_t)0x0000000000000ffffULL, 339284193Sdelphij (uuid[0] >> 0) & (uint64_t)0x0000000000000ffffULL, 340284193Sdelphij (uuid[1] >> 48) & (uint64_t)0x0000000000000ffffULL, 341284193Sdelphij (uuid[1] >> 0) & (uint64_t)0x0000fffffffffffffULL); 342267843Sdelphij return buf; 343267843Sdelphij} 344267843Sdelphij#endif 345267843Sdelphij 346191739Sobrienprotected int 347191739Sobrienfile_trycdf(struct magic_set *ms, int fd, const unsigned char *buf, 348191739Sobrien size_t nbytes) 349191739Sobrien{ 350226048Sobrien cdf_info_t info; 351226048Sobrien cdf_header_t h; 352226048Sobrien cdf_sat_t sat, ssat; 353226048Sobrien cdf_stream_t sst, scn; 354226048Sobrien cdf_dir_t dir; 355226048Sobrien int i; 356226048Sobrien const char *expn = ""; 357226048Sobrien const char *corrupt = "corrupt: "; 358284193Sdelphij const cdf_directory_t *root_storage; 359191739Sobrien 360226048Sobrien info.i_fd = fd; 361226048Sobrien info.i_buf = buf; 362226048Sobrien info.i_len = nbytes; 363226048Sobrien if (ms->flags & MAGIC_APPLE) 364226048Sobrien return 0; 365226048Sobrien if (cdf_read_header(&info, &h) == -1) 366226048Sobrien return 0; 367191739Sobrien#ifdef CDF_DEBUG 368226048Sobrien cdf_dump_header(&h); 369191739Sobrien#endif 370191739Sobrien 371226048Sobrien if ((i = cdf_read_sat(&info, &h, &sat)) == -1) { 372226048Sobrien expn = "Can't read SAT"; 373226048Sobrien goto out0; 374226048Sobrien } 375191739Sobrien#ifdef CDF_DEBUG 376226048Sobrien cdf_dump_sat("SAT", &sat, CDF_SEC_SIZE(&h)); 377191739Sobrien#endif 378191739Sobrien 379226048Sobrien if ((i = cdf_read_ssat(&info, &h, &sat, &ssat)) == -1) { 380226048Sobrien expn = "Can't read SSAT"; 381226048Sobrien goto out1; 382226048Sobrien } 383191739Sobrien#ifdef CDF_DEBUG 384226048Sobrien cdf_dump_sat("SSAT", &ssat, CDF_SHORT_SEC_SIZE(&h)); 385191739Sobrien#endif 386191739Sobrien 387226048Sobrien if ((i = cdf_read_dir(&info, &h, &sat, &dir)) == -1) { 388226048Sobrien expn = "Can't read directory"; 389226048Sobrien goto out2; 390226048Sobrien } 391191739Sobrien 392267843Sdelphij if ((i = cdf_read_short_stream(&info, &h, &sat, &dir, &sst, 393267843Sdelphij &root_storage)) == -1) { 394226048Sobrien expn = "Cannot read short stream"; 395226048Sobrien goto out3; 396226048Sobrien } 397191739Sobrien#ifdef CDF_DEBUG 398226048Sobrien cdf_dump_dir(&info, &h, &sat, &ssat, &sst, &dir); 399191739Sobrien#endif 400267843Sdelphij#ifdef notdef 401267843Sdelphij if (root_storage) { 402267843Sdelphij if (NOTMIME(ms)) { 403267843Sdelphij char clsbuf[128]; 404267843Sdelphij if (file_printf(ms, "CLSID %s, ", 405267843Sdelphij format_clsid(clsbuf, sizeof(clsbuf), 406267843Sdelphij root_storage->d_storage_uuid)) == -1) 407267843Sdelphij return -1; 408267843Sdelphij } 409267843Sdelphij } 410267843Sdelphij#endif 411192348Sdelphij 412267843Sdelphij if ((i = cdf_read_user_stream(&info, &h, &sat, &ssat, &sst, &dir, 413267843Sdelphij "FileHeader", &scn)) != -1) { 414267843Sdelphij#define HWP5_SIGNATURE "HWP Document File" 415267843Sdelphij if (scn.sst_dirlen >= sizeof(HWP5_SIGNATURE) - 1 416267843Sdelphij && memcmp(scn.sst_tab, HWP5_SIGNATURE, 417267843Sdelphij sizeof(HWP5_SIGNATURE) - 1) == 0) { 418267843Sdelphij if (NOTMIME(ms)) { 419267843Sdelphij if (file_printf(ms, 420267843Sdelphij "Hangul (Korean) Word Processor File 5.x") == -1) 421267843Sdelphij return -1; 422267843Sdelphij } else { 423267843Sdelphij if (file_printf(ms, "application/x-hwp") == -1) 424267843Sdelphij return -1; 425267843Sdelphij } 426267843Sdelphij i = 1; 427267843Sdelphij goto out5; 428267843Sdelphij } else { 429267843Sdelphij free(scn.sst_tab); 430267843Sdelphij scn.sst_tab = NULL; 431267843Sdelphij scn.sst_len = 0; 432267843Sdelphij scn.sst_dirlen = 0; 433267843Sdelphij } 434267843Sdelphij } 435267843Sdelphij 436226048Sobrien if ((i = cdf_read_summary_info(&info, &h, &sat, &ssat, &sst, &dir, 437226048Sobrien &scn)) == -1) { 438226048Sobrien if (errno == ESRCH) { 439284193Sdelphij if ((i = cdf_read_catalog(&info, &h, &sat, &ssat, &sst, 440284193Sdelphij &dir, &scn)) == -1) { 441284193Sdelphij corrupt = expn; 442284193Sdelphij if ((i = cdf_read_encrypted_package(&info, &h, 443284193Sdelphij &sat, &ssat, &sst, &dir, &scn)) == -1) 444284193Sdelphij expn = "No summary info"; 445284193Sdelphij else { 446284193Sdelphij expn = "Encrypted"; 447284193Sdelphij i = -1; 448284193Sdelphij } 449284193Sdelphij goto out4; 450284193Sdelphij } 451284193Sdelphij#ifdef CDF_DEBUG 452284193Sdelphij cdf_dump_catalog(&h, &scn); 453284193Sdelphij#endif 454284193Sdelphij if ((i = cdf_file_catalog(ms, &h, &scn)) 455284193Sdelphij < 0) 456284193Sdelphij expn = "Can't expand catalog"; 457226048Sobrien } else { 458226048Sobrien expn = "Cannot read summary info"; 459226048Sobrien } 460226048Sobrien goto out4; 461226048Sobrien } 462191739Sobrien#ifdef CDF_DEBUG 463226048Sobrien cdf_dump_summary_info(&h, &scn); 464191739Sobrien#endif 465267843Sdelphij if ((i = cdf_file_summary_info(ms, &h, &scn, root_storage)) < 0) 466267843Sdelphij expn = "Can't expand summary_info"; 467267843Sdelphij 468226048Sobrien if (i == 0) { 469267843Sdelphij const char *str = NULL; 470226048Sobrien cdf_directory_t *d; 471226048Sobrien char name[__arraycount(d->d_name)]; 472226048Sobrien size_t j, k; 473267843Sdelphij 474267843Sdelphij for (j = 0; str == NULL && j < dir.dir_len; j++) { 475267843Sdelphij d = &dir.dir_tab[j]; 476267843Sdelphij for (k = 0; k < sizeof(name); k++) 477267843Sdelphij name[k] = (char)cdf_tole2(d->d_name[k]); 478267843Sdelphij str = cdf_app_to_mime(name, 479267843Sdelphij NOTMIME(ms) ? name2desc : name2mime); 480226048Sobrien } 481267843Sdelphij if (NOTMIME(ms)) { 482267843Sdelphij if (str != NULL) { 483267843Sdelphij if (file_printf(ms, "%s", str) == -1) 484267843Sdelphij return -1; 485267843Sdelphij i = 1; 486267843Sdelphij } 487267843Sdelphij } else { 488267843Sdelphij if (str == NULL) 489267843Sdelphij str = "vnd.ms-office"; 490267843Sdelphij if (file_printf(ms, "application/%s", str) == -1) 491267843Sdelphij return -1; 492267843Sdelphij i = 1; 493267843Sdelphij } 494226048Sobrien } 495267843Sdelphijout5: 496226048Sobrien free(scn.sst_tab); 497191739Sobrienout4: 498226048Sobrien free(sst.sst_tab); 499191739Sobrienout3: 500226048Sobrien free(dir.dir_tab); 501191739Sobrienout2: 502226048Sobrien free(ssat.sat_tab); 503191739Sobrienout1: 504226048Sobrien free(sat.sat_tab); 505192348Sdelphijout0: 506267843Sdelphij if (i == -1) { 507267843Sdelphij if (NOTMIME(ms)) { 508267843Sdelphij if (file_printf(ms, 509267843Sdelphij "Composite Document File V2 Document") == -1) 510267843Sdelphij return -1; 511267843Sdelphij if (*expn) 512267843Sdelphij if (file_printf(ms, ", %s%s", corrupt, expn) == -1) 513267843Sdelphij return -1; 514267843Sdelphij } else { 515284193Sdelphij if (file_printf(ms, "application/CDFV2-%s", 516284193Sdelphij *corrupt ? "corrupt" : "encrypted") == -1) 517267843Sdelphij return -1; 518267843Sdelphij } 519267843Sdelphij i = 1; 520267843Sdelphij } 521226048Sobrien return i; 522191739Sobrien} 523