1*b6cee71dSXin LI /*- 2*b6cee71dSXin LI * Copyright (c) 2008 Christos Zoulas 3*b6cee71dSXin LI * All rights reserved. 4*b6cee71dSXin LI * 5*b6cee71dSXin LI * Redistribution and use in source and binary forms, with or without 6*b6cee71dSXin LI * modification, are permitted provided that the following conditions 7*b6cee71dSXin LI * are met: 8*b6cee71dSXin LI * 1. Redistributions of source code must retain the above copyright 9*b6cee71dSXin LI * notice, this list of conditions and the following disclaimer. 10*b6cee71dSXin LI * 2. Redistributions in binary form must reproduce the above copyright 11*b6cee71dSXin LI * notice, this list of conditions and the following disclaimer in the 12*b6cee71dSXin LI * documentation and/or other materials provided with the distribution. 13*b6cee71dSXin LI * 14*b6cee71dSXin LI * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 15*b6cee71dSXin LI * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 16*b6cee71dSXin LI * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17*b6cee71dSXin LI * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 18*b6cee71dSXin LI * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19*b6cee71dSXin LI * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20*b6cee71dSXin LI * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21*b6cee71dSXin LI * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22*b6cee71dSXin LI * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23*b6cee71dSXin LI * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24*b6cee71dSXin LI * POSSIBILITY OF SUCH DAMAGE. 25*b6cee71dSXin LI */ 26*b6cee71dSXin LI #include "file.h" 27*b6cee71dSXin LI 28*b6cee71dSXin LI #ifndef lint 29*b6cee71dSXin LI FILE_RCSID("@(#)$File: readcdf.c,v 1.44 2014/05/14 23:22:48 christos Exp $") 30*b6cee71dSXin LI #endif 31*b6cee71dSXin LI 32*b6cee71dSXin LI #include <assert.h> 33*b6cee71dSXin LI #include <stdlib.h> 34*b6cee71dSXin LI #include <unistd.h> 35*b6cee71dSXin LI #include <string.h> 36*b6cee71dSXin LI #include <time.h> 37*b6cee71dSXin LI #include <ctype.h> 38*b6cee71dSXin LI #if defined(HAVE_LOCALE_H) 39*b6cee71dSXin LI #include <locale.h> 40*b6cee71dSXin LI #endif 41*b6cee71dSXin LI 42*b6cee71dSXin LI #include "cdf.h" 43*b6cee71dSXin LI #include "magic.h" 44*b6cee71dSXin LI 45*b6cee71dSXin LI #define NOTMIME(ms) (((ms)->flags & MAGIC_MIME) == 0) 46*b6cee71dSXin LI 47*b6cee71dSXin LI static const struct nv { 48*b6cee71dSXin LI const char *pattern; 49*b6cee71dSXin LI const char *mime; 50*b6cee71dSXin LI } app2mime[] = { 51*b6cee71dSXin LI { "Word", "msword", }, 52*b6cee71dSXin LI { "Excel", "vnd.ms-excel", }, 53*b6cee71dSXin LI { "Powerpoint", "vnd.ms-powerpoint", }, 54*b6cee71dSXin LI { "Crystal Reports", "x-rpt", }, 55*b6cee71dSXin LI { "Advanced Installer", "vnd.ms-msi", }, 56*b6cee71dSXin LI { "InstallShield", "vnd.ms-msi", }, 57*b6cee71dSXin LI { "Microsoft Patch Compiler", "vnd.ms-msi", }, 58*b6cee71dSXin LI { "NAnt", "vnd.ms-msi", }, 59*b6cee71dSXin LI { "Windows Installer", "vnd.ms-msi", }, 60*b6cee71dSXin LI { NULL, NULL, }, 61*b6cee71dSXin LI }, name2mime[] = { 62*b6cee71dSXin LI { "WordDocument", "msword", }, 63*b6cee71dSXin LI { "PowerPoint", "vnd.ms-powerpoint", }, 64*b6cee71dSXin LI { "DigitalSignature", "vnd.ms-msi", }, 65*b6cee71dSXin LI { NULL, NULL, }, 66*b6cee71dSXin LI }, name2desc[] = { 67*b6cee71dSXin LI { "WordDocument", "Microsoft Office Word",}, 68*b6cee71dSXin LI { "PowerPoint", "Microsoft PowerPoint", }, 69*b6cee71dSXin LI { "DigitalSignature", "Microsoft Installer", }, 70*b6cee71dSXin LI { NULL, NULL, }, 71*b6cee71dSXin LI }; 72*b6cee71dSXin LI 73*b6cee71dSXin LI static const struct cv { 74*b6cee71dSXin LI uint64_t clsid[2]; 75*b6cee71dSXin LI const char *mime; 76*b6cee71dSXin LI } clsid2mime[] = { 77*b6cee71dSXin LI { 78*b6cee71dSXin LI { 0x00000000000c1084LLU, 0x46000000000000c0LLU }, 79*b6cee71dSXin LI "x-msi", 80*b6cee71dSXin LI }, 81*b6cee71dSXin LI { { 0, 0 }, 82*b6cee71dSXin LI NULL, 83*b6cee71dSXin LI }, 84*b6cee71dSXin LI }, clsid2desc[] = { 85*b6cee71dSXin LI { 86*b6cee71dSXin LI { 0x00000000000c1084LLU, 0x46000000000000c0LLU }, 87*b6cee71dSXin LI "MSI Installer", 88*b6cee71dSXin LI }, 89*b6cee71dSXin LI { { 0, 0 }, 90*b6cee71dSXin LI NULL, 91*b6cee71dSXin LI }, 92*b6cee71dSXin LI }; 93*b6cee71dSXin LI 94*b6cee71dSXin LI private const char * 95*b6cee71dSXin LI cdf_clsid_to_mime(const uint64_t clsid[2], const struct cv *cv) 96*b6cee71dSXin LI { 97*b6cee71dSXin LI size_t i; 98*b6cee71dSXin LI for (i = 0; cv[i].mime != NULL; i++) { 99*b6cee71dSXin LI if (clsid[0] == cv[i].clsid[0] && clsid[1] == cv[i].clsid[1]) 100*b6cee71dSXin LI return cv[i].mime; 101*b6cee71dSXin LI } 102*b6cee71dSXin LI return NULL; 103*b6cee71dSXin LI } 104*b6cee71dSXin LI 105*b6cee71dSXin LI private const char * 106*b6cee71dSXin LI cdf_app_to_mime(const char *vbuf, const struct nv *nv) 107*b6cee71dSXin LI { 108*b6cee71dSXin LI size_t i; 109*b6cee71dSXin LI const char *rv = NULL; 110*b6cee71dSXin LI char *old_lc_ctype; 111*b6cee71dSXin LI 112*b6cee71dSXin LI old_lc_ctype = setlocale(LC_CTYPE, NULL); 113*b6cee71dSXin LI assert(old_lc_ctype != NULL); 114*b6cee71dSXin LI old_lc_ctype = strdup(old_lc_ctype); 115*b6cee71dSXin LI assert(old_lc_ctype != NULL); 116*b6cee71dSXin LI (void)setlocale(LC_CTYPE, "C"); 117*b6cee71dSXin LI for (i = 0; nv[i].pattern != NULL; i++) 118*b6cee71dSXin LI if (strcasestr(vbuf, nv[i].pattern) != NULL) { 119*b6cee71dSXin LI rv = nv[i].mime; 120*b6cee71dSXin LI break; 121*b6cee71dSXin LI } 122*b6cee71dSXin LI (void)setlocale(LC_CTYPE, old_lc_ctype); 123*b6cee71dSXin LI free(old_lc_ctype); 124*b6cee71dSXin LI return rv; 125*b6cee71dSXin LI } 126*b6cee71dSXin LI 127*b6cee71dSXin LI private int 128*b6cee71dSXin LI cdf_file_property_info(struct magic_set *ms, const cdf_property_info_t *info, 129*b6cee71dSXin LI size_t count, const cdf_directory_t *root_storage) 130*b6cee71dSXin LI { 131*b6cee71dSXin LI size_t i; 132*b6cee71dSXin LI cdf_timestamp_t tp; 133*b6cee71dSXin LI struct timespec ts; 134*b6cee71dSXin LI char buf[64]; 135*b6cee71dSXin LI const char *str = NULL; 136*b6cee71dSXin LI const char *s; 137*b6cee71dSXin LI int len; 138*b6cee71dSXin LI 139*b6cee71dSXin LI if (!NOTMIME(ms) && root_storage) 140*b6cee71dSXin LI str = cdf_clsid_to_mime(root_storage->d_storage_uuid, 141*b6cee71dSXin LI clsid2mime); 142*b6cee71dSXin LI 143*b6cee71dSXin LI for (i = 0; i < count; i++) { 144*b6cee71dSXin LI cdf_print_property_name(buf, sizeof(buf), info[i].pi_id); 145*b6cee71dSXin LI switch (info[i].pi_type) { 146*b6cee71dSXin LI case CDF_NULL: 147*b6cee71dSXin LI break; 148*b6cee71dSXin LI case CDF_SIGNED16: 149*b6cee71dSXin LI if (NOTMIME(ms) && file_printf(ms, ", %s: %hd", buf, 150*b6cee71dSXin LI info[i].pi_s16) == -1) 151*b6cee71dSXin LI return -1; 152*b6cee71dSXin LI break; 153*b6cee71dSXin LI case CDF_SIGNED32: 154*b6cee71dSXin LI if (NOTMIME(ms) && file_printf(ms, ", %s: %d", buf, 155*b6cee71dSXin LI info[i].pi_s32) == -1) 156*b6cee71dSXin LI return -1; 157*b6cee71dSXin LI break; 158*b6cee71dSXin LI case CDF_UNSIGNED32: 159*b6cee71dSXin LI if (NOTMIME(ms) && file_printf(ms, ", %s: %u", buf, 160*b6cee71dSXin LI info[i].pi_u32) == -1) 161*b6cee71dSXin LI return -1; 162*b6cee71dSXin LI break; 163*b6cee71dSXin LI case CDF_FLOAT: 164*b6cee71dSXin LI if (NOTMIME(ms) && file_printf(ms, ", %s: %g", buf, 165*b6cee71dSXin LI info[i].pi_f) == -1) 166*b6cee71dSXin LI return -1; 167*b6cee71dSXin LI break; 168*b6cee71dSXin LI case CDF_DOUBLE: 169*b6cee71dSXin LI if (NOTMIME(ms) && file_printf(ms, ", %s: %g", buf, 170*b6cee71dSXin LI info[i].pi_d) == -1) 171*b6cee71dSXin LI return -1; 172*b6cee71dSXin LI break; 173*b6cee71dSXin LI case CDF_LENGTH32_STRING: 174*b6cee71dSXin LI case CDF_LENGTH32_WSTRING: 175*b6cee71dSXin LI len = info[i].pi_str.s_len; 176*b6cee71dSXin LI if (len > 1) { 177*b6cee71dSXin LI char vbuf[1024]; 178*b6cee71dSXin LI size_t j, k = 1; 179*b6cee71dSXin LI 180*b6cee71dSXin LI if (info[i].pi_type == CDF_LENGTH32_WSTRING) 181*b6cee71dSXin LI k++; 182*b6cee71dSXin LI s = info[i].pi_str.s_buf; 183*b6cee71dSXin LI for (j = 0; j < sizeof(vbuf) && len--; s += k) { 184*b6cee71dSXin LI if (*s == '\0') 185*b6cee71dSXin LI break; 186*b6cee71dSXin LI if (isprint((unsigned char)*s)) 187*b6cee71dSXin LI vbuf[j++] = *s; 188*b6cee71dSXin LI } 189*b6cee71dSXin LI if (j == sizeof(vbuf)) 190*b6cee71dSXin LI --j; 191*b6cee71dSXin LI vbuf[j] = '\0'; 192*b6cee71dSXin LI if (NOTMIME(ms)) { 193*b6cee71dSXin LI if (vbuf[0]) { 194*b6cee71dSXin LI if (file_printf(ms, ", %s: %s", 195*b6cee71dSXin LI buf, vbuf) == -1) 196*b6cee71dSXin LI return -1; 197*b6cee71dSXin LI } 198*b6cee71dSXin LI } else if (str == NULL && info[i].pi_id == 199*b6cee71dSXin LI CDF_PROPERTY_NAME_OF_APPLICATION) { 200*b6cee71dSXin LI str = cdf_app_to_mime(vbuf, app2mime); 201*b6cee71dSXin LI } 202*b6cee71dSXin LI } 203*b6cee71dSXin LI break; 204*b6cee71dSXin LI case CDF_FILETIME: 205*b6cee71dSXin LI tp = info[i].pi_tp; 206*b6cee71dSXin LI if (tp != 0) { 207*b6cee71dSXin LI char tbuf[64]; 208*b6cee71dSXin LI if (tp < 1000000000000000LL) { 209*b6cee71dSXin LI cdf_print_elapsed_time(tbuf, 210*b6cee71dSXin LI sizeof(tbuf), tp); 211*b6cee71dSXin LI if (NOTMIME(ms) && file_printf(ms, 212*b6cee71dSXin LI ", %s: %s", buf, tbuf) == -1) 213*b6cee71dSXin LI return -1; 214*b6cee71dSXin LI } else { 215*b6cee71dSXin LI char *c, *ec; 216*b6cee71dSXin LI cdf_timestamp_to_timespec(&ts, tp); 217*b6cee71dSXin LI c = cdf_ctime(&ts.tv_sec, tbuf); 218*b6cee71dSXin LI if (c != NULL && 219*b6cee71dSXin LI (ec = strchr(c, '\n')) != NULL) 220*b6cee71dSXin LI *ec = '\0'; 221*b6cee71dSXin LI 222*b6cee71dSXin LI if (NOTMIME(ms) && file_printf(ms, 223*b6cee71dSXin LI ", %s: %s", buf, c) == -1) 224*b6cee71dSXin LI return -1; 225*b6cee71dSXin LI } 226*b6cee71dSXin LI } 227*b6cee71dSXin LI break; 228*b6cee71dSXin LI case CDF_CLIPBOARD: 229*b6cee71dSXin LI break; 230*b6cee71dSXin LI default: 231*b6cee71dSXin LI return -1; 232*b6cee71dSXin LI } 233*b6cee71dSXin LI } 234*b6cee71dSXin LI if (!NOTMIME(ms)) { 235*b6cee71dSXin LI if (str == NULL) 236*b6cee71dSXin LI return 0; 237*b6cee71dSXin LI if (file_printf(ms, "application/%s", str) == -1) 238*b6cee71dSXin LI return -1; 239*b6cee71dSXin LI } 240*b6cee71dSXin LI return 1; 241*b6cee71dSXin LI } 242*b6cee71dSXin LI 243*b6cee71dSXin LI private int 244*b6cee71dSXin LI cdf_file_summary_info(struct magic_set *ms, const cdf_header_t *h, 245*b6cee71dSXin LI const cdf_stream_t *sst, const cdf_directory_t *root_storage) 246*b6cee71dSXin LI { 247*b6cee71dSXin LI cdf_summary_info_header_t si; 248*b6cee71dSXin LI cdf_property_info_t *info; 249*b6cee71dSXin LI size_t count; 250*b6cee71dSXin LI int m; 251*b6cee71dSXin LI 252*b6cee71dSXin LI if (cdf_unpack_summary_info(sst, h, &si, &info, &count) == -1) 253*b6cee71dSXin LI return -1; 254*b6cee71dSXin LI 255*b6cee71dSXin LI if (NOTMIME(ms)) { 256*b6cee71dSXin LI const char *str; 257*b6cee71dSXin LI 258*b6cee71dSXin LI if (file_printf(ms, "Composite Document File V2 Document") 259*b6cee71dSXin LI == -1) 260*b6cee71dSXin LI return -1; 261*b6cee71dSXin LI 262*b6cee71dSXin LI if (file_printf(ms, ", %s Endian", 263*b6cee71dSXin LI si.si_byte_order == 0xfffe ? "Little" : "Big") == -1) 264*b6cee71dSXin LI return -2; 265*b6cee71dSXin LI switch (si.si_os) { 266*b6cee71dSXin LI case 2: 267*b6cee71dSXin LI if (file_printf(ms, ", Os: Windows, Version %d.%d", 268*b6cee71dSXin LI si.si_os_version & 0xff, 269*b6cee71dSXin LI (uint32_t)si.si_os_version >> 8) == -1) 270*b6cee71dSXin LI return -2; 271*b6cee71dSXin LI break; 272*b6cee71dSXin LI case 1: 273*b6cee71dSXin LI if (file_printf(ms, ", Os: MacOS, Version %d.%d", 274*b6cee71dSXin LI (uint32_t)si.si_os_version >> 8, 275*b6cee71dSXin LI si.si_os_version & 0xff) == -1) 276*b6cee71dSXin LI return -2; 277*b6cee71dSXin LI break; 278*b6cee71dSXin LI default: 279*b6cee71dSXin LI if (file_printf(ms, ", Os %d, Version: %d.%d", si.si_os, 280*b6cee71dSXin LI si.si_os_version & 0xff, 281*b6cee71dSXin LI (uint32_t)si.si_os_version >> 8) == -1) 282*b6cee71dSXin LI return -2; 283*b6cee71dSXin LI break; 284*b6cee71dSXin LI } 285*b6cee71dSXin LI if (root_storage) { 286*b6cee71dSXin LI str = cdf_clsid_to_mime(root_storage->d_storage_uuid, 287*b6cee71dSXin LI clsid2desc); 288*b6cee71dSXin LI if (str) 289*b6cee71dSXin LI if (file_printf(ms, ", %s", str) == -1) 290*b6cee71dSXin LI return -2; 291*b6cee71dSXin LI } 292*b6cee71dSXin LI } 293*b6cee71dSXin LI 294*b6cee71dSXin LI m = cdf_file_property_info(ms, info, count, root_storage); 295*b6cee71dSXin LI free(info); 296*b6cee71dSXin LI 297*b6cee71dSXin LI return m == -1 ? -2 : m; 298*b6cee71dSXin LI } 299*b6cee71dSXin LI 300*b6cee71dSXin LI #ifdef notdef 301*b6cee71dSXin LI private char * 302*b6cee71dSXin LI format_clsid(char *buf, size_t len, const uint64_t uuid[2]) { 303*b6cee71dSXin LI snprintf(buf, len, "%.8" PRIx64 "-%.4" PRIx64 "-%.4" PRIx64 "-%.4" 304*b6cee71dSXin LI PRIx64 "-%.12" PRIx64, 305*b6cee71dSXin LI (uuid[0] >> 32) & (uint64_t)0x000000000ffffffffLLU, 306*b6cee71dSXin LI (uuid[0] >> 16) & (uint64_t)0x0000000000000ffffLLU, 307*b6cee71dSXin LI (uuid[0] >> 0) & (uint64_t)0x0000000000000ffffLLU, 308*b6cee71dSXin LI (uuid[1] >> 48) & (uint64_t)0x0000000000000ffffLLU, 309*b6cee71dSXin LI (uuid[1] >> 0) & (uint64_t)0x0000fffffffffffffLLU); 310*b6cee71dSXin LI return buf; 311*b6cee71dSXin LI } 312*b6cee71dSXin LI #endif 313*b6cee71dSXin LI 314*b6cee71dSXin LI protected int 315*b6cee71dSXin LI file_trycdf(struct magic_set *ms, int fd, const unsigned char *buf, 316*b6cee71dSXin LI size_t nbytes) 317*b6cee71dSXin LI { 318*b6cee71dSXin LI cdf_info_t info; 319*b6cee71dSXin LI cdf_header_t h; 320*b6cee71dSXin LI cdf_sat_t sat, ssat; 321*b6cee71dSXin LI cdf_stream_t sst, scn; 322*b6cee71dSXin LI cdf_dir_t dir; 323*b6cee71dSXin LI int i; 324*b6cee71dSXin LI const char *expn = ""; 325*b6cee71dSXin LI const char *corrupt = "corrupt: "; 326*b6cee71dSXin LI 327*b6cee71dSXin LI info.i_fd = fd; 328*b6cee71dSXin LI info.i_buf = buf; 329*b6cee71dSXin LI info.i_len = nbytes; 330*b6cee71dSXin LI if (ms->flags & MAGIC_APPLE) 331*b6cee71dSXin LI return 0; 332*b6cee71dSXin LI if (cdf_read_header(&info, &h) == -1) 333*b6cee71dSXin LI return 0; 334*b6cee71dSXin LI #ifdef CDF_DEBUG 335*b6cee71dSXin LI cdf_dump_header(&h); 336*b6cee71dSXin LI #endif 337*b6cee71dSXin LI 338*b6cee71dSXin LI if ((i = cdf_read_sat(&info, &h, &sat)) == -1) { 339*b6cee71dSXin LI expn = "Can't read SAT"; 340*b6cee71dSXin LI goto out0; 341*b6cee71dSXin LI } 342*b6cee71dSXin LI #ifdef CDF_DEBUG 343*b6cee71dSXin LI cdf_dump_sat("SAT", &sat, CDF_SEC_SIZE(&h)); 344*b6cee71dSXin LI #endif 345*b6cee71dSXin LI 346*b6cee71dSXin LI if ((i = cdf_read_ssat(&info, &h, &sat, &ssat)) == -1) { 347*b6cee71dSXin LI expn = "Can't read SSAT"; 348*b6cee71dSXin LI goto out1; 349*b6cee71dSXin LI } 350*b6cee71dSXin LI #ifdef CDF_DEBUG 351*b6cee71dSXin LI cdf_dump_sat("SSAT", &ssat, CDF_SHORT_SEC_SIZE(&h)); 352*b6cee71dSXin LI #endif 353*b6cee71dSXin LI 354*b6cee71dSXin LI if ((i = cdf_read_dir(&info, &h, &sat, &dir)) == -1) { 355*b6cee71dSXin LI expn = "Can't read directory"; 356*b6cee71dSXin LI goto out2; 357*b6cee71dSXin LI } 358*b6cee71dSXin LI 359*b6cee71dSXin LI const cdf_directory_t *root_storage; 360*b6cee71dSXin LI if ((i = cdf_read_short_stream(&info, &h, &sat, &dir, &sst, 361*b6cee71dSXin LI &root_storage)) == -1) { 362*b6cee71dSXin LI expn = "Cannot read short stream"; 363*b6cee71dSXin LI goto out3; 364*b6cee71dSXin LI } 365*b6cee71dSXin LI #ifdef CDF_DEBUG 366*b6cee71dSXin LI cdf_dump_dir(&info, &h, &sat, &ssat, &sst, &dir); 367*b6cee71dSXin LI #endif 368*b6cee71dSXin LI #ifdef notdef 369*b6cee71dSXin LI if (root_storage) { 370*b6cee71dSXin LI if (NOTMIME(ms)) { 371*b6cee71dSXin LI char clsbuf[128]; 372*b6cee71dSXin LI if (file_printf(ms, "CLSID %s, ", 373*b6cee71dSXin LI format_clsid(clsbuf, sizeof(clsbuf), 374*b6cee71dSXin LI root_storage->d_storage_uuid)) == -1) 375*b6cee71dSXin LI return -1; 376*b6cee71dSXin LI } 377*b6cee71dSXin LI } 378*b6cee71dSXin LI #endif 379*b6cee71dSXin LI 380*b6cee71dSXin LI if ((i = cdf_read_user_stream(&info, &h, &sat, &ssat, &sst, &dir, 381*b6cee71dSXin LI "FileHeader", &scn)) != -1) { 382*b6cee71dSXin LI #define HWP5_SIGNATURE "HWP Document File" 383*b6cee71dSXin LI if (scn.sst_dirlen >= sizeof(HWP5_SIGNATURE) - 1 384*b6cee71dSXin LI && memcmp(scn.sst_tab, HWP5_SIGNATURE, 385*b6cee71dSXin LI sizeof(HWP5_SIGNATURE) - 1) == 0) { 386*b6cee71dSXin LI if (NOTMIME(ms)) { 387*b6cee71dSXin LI if (file_printf(ms, 388*b6cee71dSXin LI "Hangul (Korean) Word Processor File 5.x") == -1) 389*b6cee71dSXin LI return -1; 390*b6cee71dSXin LI } else { 391*b6cee71dSXin LI if (file_printf(ms, "application/x-hwp") == -1) 392*b6cee71dSXin LI return -1; 393*b6cee71dSXin LI } 394*b6cee71dSXin LI i = 1; 395*b6cee71dSXin LI goto out5; 396*b6cee71dSXin LI } else { 397*b6cee71dSXin LI free(scn.sst_tab); 398*b6cee71dSXin LI scn.sst_tab = NULL; 399*b6cee71dSXin LI scn.sst_len = 0; 400*b6cee71dSXin LI scn.sst_dirlen = 0; 401*b6cee71dSXin LI } 402*b6cee71dSXin LI } 403*b6cee71dSXin LI 404*b6cee71dSXin LI if ((i = cdf_read_summary_info(&info, &h, &sat, &ssat, &sst, &dir, 405*b6cee71dSXin LI &scn)) == -1) { 406*b6cee71dSXin LI if (errno == ESRCH) { 407*b6cee71dSXin LI corrupt = expn; 408*b6cee71dSXin LI expn = "No summary info"; 409*b6cee71dSXin LI } else { 410*b6cee71dSXin LI expn = "Cannot read summary info"; 411*b6cee71dSXin LI } 412*b6cee71dSXin LI goto out4; 413*b6cee71dSXin LI } 414*b6cee71dSXin LI #ifdef CDF_DEBUG 415*b6cee71dSXin LI cdf_dump_summary_info(&h, &scn); 416*b6cee71dSXin LI #endif 417*b6cee71dSXin LI if ((i = cdf_file_summary_info(ms, &h, &scn, root_storage)) < 0) 418*b6cee71dSXin LI expn = "Can't expand summary_info"; 419*b6cee71dSXin LI 420*b6cee71dSXin LI if (i == 0) { 421*b6cee71dSXin LI const char *str = NULL; 422*b6cee71dSXin LI cdf_directory_t *d; 423*b6cee71dSXin LI char name[__arraycount(d->d_name)]; 424*b6cee71dSXin LI size_t j, k; 425*b6cee71dSXin LI 426*b6cee71dSXin LI for (j = 0; str == NULL && j < dir.dir_len; j++) { 427*b6cee71dSXin LI d = &dir.dir_tab[j]; 428*b6cee71dSXin LI for (k = 0; k < sizeof(name); k++) 429*b6cee71dSXin LI name[k] = (char)cdf_tole2(d->d_name[k]); 430*b6cee71dSXin LI str = cdf_app_to_mime(name, 431*b6cee71dSXin LI NOTMIME(ms) ? name2desc : name2mime); 432*b6cee71dSXin LI } 433*b6cee71dSXin LI if (NOTMIME(ms)) { 434*b6cee71dSXin LI if (str != NULL) { 435*b6cee71dSXin LI if (file_printf(ms, "%s", str) == -1) 436*b6cee71dSXin LI return -1; 437*b6cee71dSXin LI i = 1; 438*b6cee71dSXin LI } 439*b6cee71dSXin LI } else { 440*b6cee71dSXin LI if (str == NULL) 441*b6cee71dSXin LI str = "vnd.ms-office"; 442*b6cee71dSXin LI if (file_printf(ms, "application/%s", str) == -1) 443*b6cee71dSXin LI return -1; 444*b6cee71dSXin LI i = 1; 445*b6cee71dSXin LI } 446*b6cee71dSXin LI } 447*b6cee71dSXin LI out5: 448*b6cee71dSXin LI free(scn.sst_tab); 449*b6cee71dSXin LI out4: 450*b6cee71dSXin LI free(sst.sst_tab); 451*b6cee71dSXin LI out3: 452*b6cee71dSXin LI free(dir.dir_tab); 453*b6cee71dSXin LI out2: 454*b6cee71dSXin LI free(ssat.sat_tab); 455*b6cee71dSXin LI out1: 456*b6cee71dSXin LI free(sat.sat_tab); 457*b6cee71dSXin LI out0: 458*b6cee71dSXin LI if (i == -1) { 459*b6cee71dSXin LI if (NOTMIME(ms)) { 460*b6cee71dSXin LI if (file_printf(ms, 461*b6cee71dSXin LI "Composite Document File V2 Document") == -1) 462*b6cee71dSXin LI return -1; 463*b6cee71dSXin LI if (*expn) 464*b6cee71dSXin LI if (file_printf(ms, ", %s%s", corrupt, expn) == -1) 465*b6cee71dSXin LI return -1; 466*b6cee71dSXin LI } else { 467*b6cee71dSXin LI if (file_printf(ms, "application/CDFV2-corrupt") == -1) 468*b6cee71dSXin LI return -1; 469*b6cee71dSXin LI } 470*b6cee71dSXin LI i = 1; 471*b6cee71dSXin LI } 472*b6cee71dSXin LI return i; 473*b6cee71dSXin LI } 474