Annotation of embedaddon/php/ext/fileinfo/libmagic/cdf.c, revision 1.1
1.1 ! misho 1: /*-
! 2: * Copyright (c) 2008 Christos Zoulas
! 3: * All rights reserved.
! 4: *
! 5: * Redistribution and use in source and binary forms, with or without
! 6: * modification, are permitted provided that the following conditions
! 7: * are met:
! 8: * 1. Redistributions of source code must retain the above copyright
! 9: * notice, this list of conditions and the following disclaimer.
! 10: * 2. Redistributions in binary form must reproduce the above copyright
! 11: * notice, this list of conditions and the following disclaimer in the
! 12: * documentation and/or other materials provided with the distribution.
! 13: *
! 14: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
! 15: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 16: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 17: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
! 18: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 19: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 20: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 21: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 22: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 23: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 24: * POSSIBILITY OF SUCH DAMAGE.
! 25: */
! 26: /*
! 27: * Parse composite document files, the format used in Microsoft Office
! 28: * document files before they switched to zipped xml.
! 29: * Info from: http://sc.openoffice.org/compdocfileformat.pdf
! 30: */
! 31:
! 32: #include "file.h"
! 33:
! 34: #ifndef lint
! 35: FILE_RCSID("@(#)$File: cdf.c,v 1.30 2009/05/06 14:29:47 christos Exp $")
! 36: #endif
! 37:
! 38: #include <assert.h>
! 39: #ifdef CDF_DEBUG
! 40: #include <err.h>
! 41: #endif
! 42: #include <stdlib.h>
! 43:
! 44: #ifdef PHP_WIN32
! 45: #include "win32/unistd.h"
! 46: #else
! 47: #include <unistd.h>
! 48: #endif
! 49:
! 50: #ifndef UINT32_MAX
! 51: # define UINT32_MAX (0xffffffff)
! 52: #endif
! 53:
! 54: #include <string.h>
! 55: #include <time.h>
! 56: #include <ctype.h>
! 57:
! 58: #ifndef EFTYPE
! 59: #define EFTYPE EINVAL
! 60: #endif
! 61:
! 62: #include "cdf.h"
! 63:
! 64: #ifndef __arraycount
! 65: #define __arraycount(a) (sizeof(a) / sizeof(a[0]))
! 66: #endif
! 67:
! 68: #ifdef CDF_DEBUG
! 69: #define DPRINTF(a) printf a, fflush(stdout)
! 70: #else
! 71: #define DPRINTF(a)
! 72: #endif
! 73:
! 74: static union {
! 75: char s[4];
! 76: uint32_t u;
! 77: } cdf_bo;
! 78:
! 79: #define NEED_SWAP (cdf_bo.u == (uint32_t)0x01020304)
! 80:
! 81: #define CDF_TOLE8(x) (NEED_SWAP ? cdf_tole8(x) : (uint64_t)(x))
! 82: #define CDF_TOLE4(x) (NEED_SWAP ? cdf_tole4(x) : (uint32_t)(x))
! 83: #define CDF_TOLE2(x) (NEED_SWAP ? cdf_tole2(x) : (uint16_t)(x))
! 84:
! 85: /*
! 86: * swap a short
! 87: */
! 88: uint16_t
! 89: cdf_tole2(uint16_t sv)
! 90: {
! 91: uint16_t rv;
! 92: uint8_t *s = (uint8_t *)(void *)&sv;
! 93: uint8_t *d = (uint8_t *)(void *)&rv;
! 94: d[0] = s[1];
! 95: d[1] = s[0];
! 96: return rv;
! 97: }
! 98:
! 99: /*
! 100: * swap an int
! 101: */
! 102: uint32_t
! 103: cdf_tole4(uint32_t sv)
! 104: {
! 105: uint32_t rv;
! 106: uint8_t *s = (uint8_t *)(void *)&sv;
! 107: uint8_t *d = (uint8_t *)(void *)&rv;
! 108: d[0] = s[3];
! 109: d[1] = s[2];
! 110: d[2] = s[1];
! 111: d[3] = s[0];
! 112: return rv;
! 113: }
! 114:
! 115: /*
! 116: * swap a quad
! 117: */
! 118: uint64_t
! 119: cdf_tole8(uint64_t sv)
! 120: {
! 121: uint64_t rv;
! 122: uint8_t *s = (uint8_t *)(void *)&sv;
! 123: uint8_t *d = (uint8_t *)(void *)&rv;
! 124: d[0] = s[7];
! 125: d[1] = s[6];
! 126: d[2] = s[5];
! 127: d[3] = s[4];
! 128: d[4] = s[3];
! 129: d[5] = s[2];
! 130: d[6] = s[1];
! 131: d[7] = s[0];
! 132: return rv;
! 133: }
! 134:
! 135: #define CDF_UNPACK(a) \
! 136: (void)memcpy(&(a), &buf[len], sizeof(a)), len += sizeof(a)
! 137: #define CDF_UNPACKA(a) \
! 138: (void)memcpy((a), &buf[len], sizeof(a)), len += sizeof(a)
! 139:
! 140: void
! 141: cdf_swap_header(cdf_header_t *h)
! 142: {
! 143: size_t i;
! 144:
! 145: h->h_magic = CDF_TOLE8(h->h_magic);
! 146: h->h_uuid[0] = CDF_TOLE8(h->h_uuid[0]);
! 147: h->h_uuid[1] = CDF_TOLE8(h->h_uuid[1]);
! 148: h->h_revision = CDF_TOLE2(h->h_revision);
! 149: h->h_version = CDF_TOLE2(h->h_version);
! 150: h->h_byte_order = CDF_TOLE2(h->h_byte_order);
! 151: h->h_sec_size_p2 = CDF_TOLE2(h->h_sec_size_p2);
! 152: h->h_short_sec_size_p2 = CDF_TOLE2(h->h_short_sec_size_p2);
! 153: h->h_num_sectors_in_sat = CDF_TOLE4(h->h_num_sectors_in_sat);
! 154: h->h_secid_first_directory = CDF_TOLE4(h->h_secid_first_directory);
! 155: h->h_min_size_standard_stream =
! 156: CDF_TOLE4(h->h_min_size_standard_stream);
! 157: h->h_secid_first_sector_in_short_sat =
! 158: CDF_TOLE4(h->h_secid_first_sector_in_short_sat);
! 159: h->h_num_sectors_in_short_sat =
! 160: CDF_TOLE4(h->h_num_sectors_in_short_sat);
! 161: h->h_secid_first_sector_in_master_sat =
! 162: CDF_TOLE4(h->h_secid_first_sector_in_master_sat);
! 163: h->h_num_sectors_in_master_sat =
! 164: CDF_TOLE4(h->h_num_sectors_in_master_sat);
! 165: for (i = 0; i < __arraycount(h->h_master_sat); i++)
! 166: h->h_master_sat[i] = CDF_TOLE4(h->h_master_sat[i]);
! 167: }
! 168:
! 169: void
! 170: cdf_unpack_header(cdf_header_t *h, char *buf)
! 171: {
! 172: size_t i;
! 173: size_t len = 0;
! 174:
! 175: CDF_UNPACK(h->h_magic);
! 176: CDF_UNPACKA(h->h_uuid);
! 177: CDF_UNPACK(h->h_revision);
! 178: CDF_UNPACK(h->h_version);
! 179: CDF_UNPACK(h->h_byte_order);
! 180: CDF_UNPACK(h->h_sec_size_p2);
! 181: CDF_UNPACK(h->h_short_sec_size_p2);
! 182: CDF_UNPACKA(h->h_unused0);
! 183: CDF_UNPACK(h->h_num_sectors_in_sat);
! 184: CDF_UNPACK(h->h_secid_first_directory);
! 185: CDF_UNPACKA(h->h_unused1);
! 186: CDF_UNPACK(h->h_min_size_standard_stream);
! 187: CDF_UNPACK(h->h_secid_first_sector_in_short_sat);
! 188: CDF_UNPACK(h->h_num_sectors_in_short_sat);
! 189: CDF_UNPACK(h->h_secid_first_sector_in_master_sat);
! 190: CDF_UNPACK(h->h_num_sectors_in_master_sat);
! 191: for (i = 0; i < __arraycount(h->h_master_sat); i++)
! 192: CDF_UNPACK(h->h_master_sat[i]);
! 193: }
! 194:
! 195: void
! 196: cdf_swap_dir(cdf_directory_t *d)
! 197: {
! 198: d->d_namelen = CDF_TOLE2(d->d_namelen);
! 199: d->d_left_child = CDF_TOLE4(d->d_left_child);
! 200: d->d_right_child = CDF_TOLE4(d->d_right_child);
! 201: d->d_storage = CDF_TOLE4(d->d_storage);
! 202: d->d_storage_uuid[0] = CDF_TOLE8(d->d_storage_uuid[0]);
! 203: d->d_storage_uuid[1] = CDF_TOLE8(d->d_storage_uuid[1]);
! 204: d->d_flags = CDF_TOLE4(d->d_flags);
! 205: d->d_created = CDF_TOLE8(d->d_created);
! 206: d->d_modified = CDF_TOLE8(d->d_modified);
! 207: d->d_stream_first_sector = CDF_TOLE4(d->d_stream_first_sector);
! 208: d->d_size = CDF_TOLE4(d->d_size);
! 209: }
! 210:
! 211: void
! 212: cdf_swap_class(cdf_classid_t *d)
! 213: {
! 214: d->cl_dword = CDF_TOLE4(d->cl_dword);
! 215: d->cl_word[0] = CDF_TOLE2(d->cl_word[0]);
! 216: d->cl_word[1] = CDF_TOLE2(d->cl_word[1]);
! 217: }
! 218:
! 219: void
! 220: cdf_unpack_dir(cdf_directory_t *d, char *buf)
! 221: {
! 222: size_t len = 0;
! 223:
! 224: CDF_UNPACKA(d->d_name);
! 225: CDF_UNPACK(d->d_namelen);
! 226: CDF_UNPACK(d->d_type);
! 227: CDF_UNPACK(d->d_color);
! 228: CDF_UNPACK(d->d_left_child);
! 229: CDF_UNPACK(d->d_right_child);
! 230: CDF_UNPACK(d->d_storage);
! 231: CDF_UNPACKA(d->d_storage_uuid);
! 232: CDF_UNPACK(d->d_flags);
! 233: CDF_UNPACK(d->d_created);
! 234: CDF_UNPACK(d->d_modified);
! 235: CDF_UNPACK(d->d_stream_first_sector);
! 236: CDF_UNPACK(d->d_size);
! 237: CDF_UNPACK(d->d_unused0);
! 238: }
! 239:
! 240: static int
! 241: cdf_check_stream_offset(const cdf_stream_t *sst, const void *p, size_t tail)
! 242: {
! 243: const char *b = (const char *)sst->sst_tab;
! 244: const char *e = ((const char *)p) + tail;
! 245: if (e >= b && (size_t)(e - b) < sst->sst_dirlen * sst->sst_len)
! 246: return 0;
! 247: DPRINTF((stderr, "offset begin %p end %p %zu >= %zu\n", b, e,
! 248: (size_t)(e - b), sst->sst_dirlen * sst->sst_len));
! 249: errno = EFTYPE;
! 250: return -1;
! 251: }
! 252:
! 253: static ssize_t
! 254: cdf_read(const cdf_info_t *info, off_t off, void *buf, size_t len)
! 255: {
! 256: size_t siz = (size_t)off + len;
! 257:
! 258: if ((off_t)(off + len) != (off_t)siz) {
! 259: errno = EINVAL;
! 260: return -1;
! 261: }
! 262:
! 263: if (info->i_buf != NULL && info->i_len >= siz) {
! 264: (void)memcpy(buf, &info->i_buf[off], len);
! 265: return (ssize_t)len;
! 266: }
! 267:
! 268: if (info->i_fd == -1)
! 269: return -1;
! 270:
! 271: if (lseek(info->i_fd, off, SEEK_SET) == (off_t)-1)
! 272: return -1;
! 273:
! 274: if (read(info->i_fd, buf, len) != (ssize_t)len)
! 275: return -1;
! 276:
! 277: return (ssize_t)len;
! 278: }
! 279:
! 280: int
! 281: cdf_read_header(const cdf_info_t *info, cdf_header_t *h)
! 282: {
! 283: char buf[512];
! 284:
! 285: (void)memcpy(cdf_bo.s, "\01\02\03\04", 4);
! 286: if (cdf_read(info, (off_t)0, buf, sizeof(buf)) == -1)
! 287: return -1;
! 288: cdf_unpack_header(h, buf);
! 289: cdf_swap_header(h);
! 290: if (h->h_magic != CDF_MAGIC) {
! 291: DPRINTF(("Bad magic 0x%llx != 0x%llx\n",
! 292: (unsigned long long)h->h_magic,
! 293: (unsigned long long)CDF_MAGIC));
! 294: goto out;
! 295: }
! 296: if (h->h_sec_size_p2 > 20) {
! 297: DPRINTF(("Bad sector size 0x%u\n", h->h_sec_size_p2));
! 298: goto out;
! 299: }
! 300: if (h->h_short_sec_size_p2 > 20) {
! 301: DPRINTF(("Bad short sector size 0x%u\n",
! 302: h->h_short_sec_size_p2));
! 303: goto out;
! 304: }
! 305: return 0;
! 306: out:
! 307: errno = EFTYPE;
! 308: return -1;
! 309: }
! 310:
! 311:
! 312: ssize_t
! 313: cdf_read_sector(const cdf_info_t *info, void *buf, size_t offs, size_t len,
! 314: const cdf_header_t *h, cdf_secid_t id)
! 315: {
! 316: assert((size_t)CDF_SEC_SIZE(h) == len);
! 317: return cdf_read(info, (off_t)CDF_SEC_POS(h, id),
! 318: ((char *)buf) + offs, len);
! 319: }
! 320:
! 321: ssize_t
! 322: cdf_read_short_sector(const cdf_stream_t *sst, void *buf, size_t offs,
! 323: size_t len, const cdf_header_t *h, cdf_secid_t id)
! 324: {
! 325: assert((size_t)CDF_SHORT_SEC_SIZE(h) == len);
! 326: (void)memcpy(((char *)buf) + offs,
! 327: ((const char *)sst->sst_tab) + CDF_SHORT_SEC_POS(h, id), len);
! 328: return len;
! 329: }
! 330:
! 331: /*
! 332: * Read the sector allocation table.
! 333: */
! 334: int
! 335: cdf_read_sat(const cdf_info_t *info, cdf_header_t *h, cdf_sat_t *sat)
! 336: {
! 337: size_t i, j, k;
! 338: size_t ss = CDF_SEC_SIZE(h);
! 339: cdf_secid_t *msa, mid, sec;
! 340: size_t nsatpersec = (ss / sizeof(mid)) - 1;
! 341:
! 342: for (i = 0; i < __arraycount(h->h_master_sat); i++)
! 343: if (h->h_master_sat[i] == CDF_SECID_FREE)
! 344: break;
! 345:
! 346: #define CDF_SEC_LIMIT (UINT32_MAX / (4 * ss))
! 347: if (h->h_num_sectors_in_master_sat > CDF_SEC_LIMIT / nsatpersec ||
! 348: i > CDF_SEC_LIMIT) {
! 349: DPRINTF(("Number of sectors in master SAT too big %u %zu\n",
! 350: h->h_num_sectors_in_master_sat, i));
! 351: errno = EFTYPE;
! 352: return -1;
! 353: }
! 354:
! 355: sat->sat_len = h->h_num_sectors_in_master_sat * nsatpersec + i;
! 356: DPRINTF(("sat_len = %zu ss = %zu\n", sat->sat_len, ss));
! 357: if ((sat->sat_tab = calloc(sat->sat_len, ss)) == NULL)
! 358: return -1;
! 359:
! 360: for (i = 0; i < __arraycount(h->h_master_sat); i++) {
! 361: if (h->h_master_sat[i] < 0)
! 362: break;
! 363: if (cdf_read_sector(info, sat->sat_tab, ss * i, ss, h,
! 364: h->h_master_sat[i]) != (ssize_t)ss) {
! 365: DPRINTF(("Reading sector %d", h->h_master_sat[i]));
! 366: goto out1;
! 367: }
! 368: }
! 369:
! 370: if ((msa = calloc(1, ss)) == NULL)
! 371: goto out1;
! 372:
! 373: mid = h->h_secid_first_sector_in_master_sat;
! 374: for (j = 0; j < h->h_num_sectors_in_master_sat; j++) {
! 375: if (mid < 0)
! 376: goto out;
! 377: if (j >= CDF_LOOP_LIMIT) {
! 378: DPRINTF(("Reading master sector loop limit"));
! 379: errno = EFTYPE;
! 380: goto out2;
! 381: }
! 382: if (cdf_read_sector(info, msa, 0, ss, h, mid) != (ssize_t)ss) {
! 383: DPRINTF(("Reading master sector %d", mid));
! 384: goto out2;
! 385: }
! 386: for (k = 0; k < nsatpersec; k++, i++) {
! 387: sec = CDF_TOLE4(msa[k]);
! 388: if (sec < 0)
! 389: goto out;
! 390: if (i >= sat->sat_len) {
! 391: DPRINTF(("Out of bounds reading MSA %u >= %u",
! 392: i, sat->sat_len));
! 393: errno = EFTYPE;
! 394: goto out2;
! 395: }
! 396: if (cdf_read_sector(info, sat->sat_tab, ss * i, ss, h,
! 397: sec) != (ssize_t)ss) {
! 398: DPRINTF(("Reading sector %d",
! 399: CDF_TOLE4(msa[k])));
! 400: goto out2;
! 401: }
! 402: }
! 403: mid = CDF_TOLE4(msa[nsatpersec]);
! 404: }
! 405: out:
! 406: sat->sat_len = i;
! 407: free(msa);
! 408: return 0;
! 409: out2:
! 410: free(msa);
! 411: out1:
! 412: free(sat->sat_tab);
! 413: return -1;
! 414: }
! 415:
! 416: size_t
! 417: cdf_count_chain(const cdf_sat_t *sat, cdf_secid_t sid, size_t size)
! 418: {
! 419: size_t i, j;
! 420: cdf_secid_t maxsector = (cdf_secid_t)(sat->sat_len * size);
! 421:
! 422: DPRINTF(("Chain:"));
! 423: for (j = i = 0; sid >= 0; i++, j++) {
! 424: DPRINTF((" %d", sid));
! 425: if (j >= CDF_LOOP_LIMIT) {
! 426: DPRINTF(("Counting chain loop limit"));
! 427: errno = EFTYPE;
! 428: return (size_t)-1;
! 429: }
! 430: if (sid > maxsector) {
! 431: DPRINTF(("Sector %d > %d\n", sid, maxsector));
! 432: errno = EFTYPE;
! 433: return (size_t)-1;
! 434: }
! 435: sid = CDF_TOLE4(sat->sat_tab[sid]);
! 436: }
! 437: DPRINTF(("\n"));
! 438: return i;
! 439: }
! 440:
! 441: int
! 442: cdf_read_long_sector_chain(const cdf_info_t *info, const cdf_header_t *h,
! 443: const cdf_sat_t *sat, cdf_secid_t sid, size_t len, cdf_stream_t *scn)
! 444: {
! 445: size_t ss = CDF_SEC_SIZE(h), i, j;
! 446: ssize_t nr;
! 447: scn->sst_len = cdf_count_chain(sat, sid, ss);
! 448: scn->sst_dirlen = len;
! 449:
! 450: if (scn->sst_len == (size_t)-1)
! 451: return -1;
! 452:
! 453: scn->sst_tab = calloc(scn->sst_len, ss);
! 454: if (scn->sst_tab == NULL)
! 455: return -1;
! 456:
! 457: for (j = i = 0; sid >= 0; i++, j++) {
! 458: if (j >= CDF_LOOP_LIMIT) {
! 459: DPRINTF(("Read long sector chain loop limit"));
! 460: errno = EFTYPE;
! 461: goto out;
! 462: }
! 463: if (i >= scn->sst_len) {
! 464: DPRINTF(("Out of bounds reading long sector chain "
! 465: "%u > %u\n", i, scn->sst_len));
! 466: errno = EFTYPE;
! 467: goto out;
! 468: }
! 469: if ((nr = cdf_read_sector(info, scn->sst_tab, i * ss, ss, h,
! 470: sid)) != (ssize_t)ss) {
! 471: if (i == scn->sst_len - 1 && nr > 0) {
! 472: /* Last sector might be truncated */
! 473: return 0;
! 474: }
! 475: DPRINTF(("Reading long sector chain %d", sid));
! 476: goto out;
! 477: }
! 478: sid = CDF_TOLE4(sat->sat_tab[sid]);
! 479: }
! 480: return 0;
! 481: out:
! 482: free(scn->sst_tab);
! 483: return -1;
! 484: }
! 485:
! 486: int
! 487: cdf_read_short_sector_chain(const cdf_header_t *h,
! 488: const cdf_sat_t *ssat, const cdf_stream_t *sst,
! 489: cdf_secid_t sid, size_t len, cdf_stream_t *scn)
! 490: {
! 491: size_t ss = CDF_SHORT_SEC_SIZE(h), i, j;
! 492: scn->sst_len = cdf_count_chain(ssat, sid, CDF_SEC_SIZE(h));
! 493: scn->sst_dirlen = len;
! 494:
! 495: if (sst->sst_tab == NULL || scn->sst_len == (size_t)-1)
! 496: return -1;
! 497:
! 498: scn->sst_tab = calloc(scn->sst_len, ss);
! 499: if (scn->sst_tab == NULL)
! 500: return -1;
! 501:
! 502: for (j = i = 0; sid >= 0; i++, j++) {
! 503: if (j >= CDF_LOOP_LIMIT) {
! 504: DPRINTF(("Read short sector chain loop limit"));
! 505: errno = EFTYPE;
! 506: goto out;
! 507: }
! 508: if (i >= scn->sst_len) {
! 509: DPRINTF(("Out of bounds reading short sector chain "
! 510: "%u > %u\n", i, scn->sst_len));
! 511: errno = EFTYPE;
! 512: goto out;
! 513: }
! 514: if (cdf_read_short_sector(sst, scn->sst_tab, i * ss, ss, h,
! 515: sid) != (ssize_t)ss) {
! 516: DPRINTF(("Reading short sector chain %d", sid));
! 517: goto out;
! 518: }
! 519: sid = CDF_TOLE4(ssat->sat_tab[sid]);
! 520: }
! 521: return 0;
! 522: out:
! 523: free(scn->sst_tab);
! 524: return -1;
! 525: }
! 526:
! 527: int
! 528: cdf_read_sector_chain(const cdf_info_t *info, const cdf_header_t *h,
! 529: const cdf_sat_t *sat, const cdf_sat_t *ssat, const cdf_stream_t *sst,
! 530: cdf_secid_t sid, size_t len, cdf_stream_t *scn)
! 531: {
! 532:
! 533: if (len < h->h_min_size_standard_stream)
! 534: return cdf_read_short_sector_chain(h, ssat, sst, sid, len,
! 535: scn);
! 536: else
! 537: return cdf_read_long_sector_chain(info, h, sat, sid, len, scn);
! 538: }
! 539:
! 540: int
! 541: cdf_read_dir(const cdf_info_t *info, const cdf_header_t *h,
! 542: const cdf_sat_t *sat, cdf_dir_t *dir)
! 543: {
! 544: size_t i, j;
! 545: size_t ss = CDF_SEC_SIZE(h), ns, nd;
! 546: char *buf;
! 547: cdf_secid_t sid = h->h_secid_first_directory;
! 548:
! 549: ns = cdf_count_chain(sat, sid, ss);
! 550: if (ns == (size_t)-1)
! 551: return -1;
! 552:
! 553: nd = ss / CDF_DIRECTORY_SIZE;
! 554:
! 555: dir->dir_len = ns * nd;
! 556: dir->dir_tab = calloc(dir->dir_len, sizeof(dir->dir_tab[0]));
! 557: if (dir->dir_tab == NULL)
! 558: return -1;
! 559:
! 560: if ((buf = malloc(ss)) == NULL) {
! 561: free(dir->dir_tab);
! 562: return -1;
! 563: }
! 564:
! 565: for (j = i = 0; i < ns; i++, j++) {
! 566: if (j >= CDF_LOOP_LIMIT) {
! 567: DPRINTF(("Read dir loop limit"));
! 568: errno = EFTYPE;
! 569: goto out;
! 570: }
! 571: if (cdf_read_sector(info, buf, 0, ss, h, sid) != (ssize_t)ss) {
! 572: DPRINTF(("Reading directory sector %d", sid));
! 573: goto out;
! 574: }
! 575: for (j = 0; j < nd; j++) {
! 576: cdf_unpack_dir(&dir->dir_tab[i * nd + j],
! 577: &buf[j * CDF_DIRECTORY_SIZE]);
! 578: }
! 579: sid = CDF_TOLE4(sat->sat_tab[sid]);
! 580: }
! 581: if (NEED_SWAP)
! 582: for (i = 0; i < dir->dir_len; i++)
! 583: cdf_swap_dir(&dir->dir_tab[i]);
! 584: free(buf);
! 585: return 0;
! 586: out:
! 587: free(dir->dir_tab);
! 588: free(buf);
! 589: return -1;
! 590: }
! 591:
! 592:
! 593: int
! 594: cdf_read_ssat(const cdf_info_t *info, const cdf_header_t *h,
! 595: const cdf_sat_t *sat, cdf_sat_t *ssat)
! 596: {
! 597: size_t i, j;
! 598: size_t ss = CDF_SEC_SIZE(h);
! 599: cdf_secid_t sid = h->h_secid_first_sector_in_short_sat;
! 600:
! 601: ssat->sat_len = cdf_count_chain(sat, sid, CDF_SEC_SIZE(h));
! 602: if (ssat->sat_len == (size_t)-1)
! 603: return -1;
! 604:
! 605: ssat->sat_tab = calloc(ssat->sat_len, ss);
! 606: if (ssat->sat_tab == NULL)
! 607: return -1;
! 608:
! 609: for (j = i = 0; sid >= 0; i++, j++) {
! 610: if (j >= CDF_LOOP_LIMIT) {
! 611: DPRINTF(("Read short sat sector loop limit"));
! 612: errno = EFTYPE;
! 613: goto out;
! 614: }
! 615: if (i >= ssat->sat_len) {
! 616: DPRINTF(("Out of bounds reading short sector chain "
! 617: "%u > %u\n", i, ssat->sat_len));
! 618: errno = EFTYPE;
! 619: goto out;
! 620: }
! 621: if (cdf_read_sector(info, ssat->sat_tab, i * ss, ss, h, sid) !=
! 622: (ssize_t)ss) {
! 623: DPRINTF(("Reading short sat sector %d", sid));
! 624: goto out;
! 625: }
! 626: sid = CDF_TOLE4(sat->sat_tab[sid]);
! 627: }
! 628: return 0;
! 629: out:
! 630: free(ssat->sat_tab);
! 631: return -1;
! 632: }
! 633:
! 634: int
! 635: cdf_read_short_stream(const cdf_info_t *info, const cdf_header_t *h,
! 636: const cdf_sat_t *sat, const cdf_dir_t *dir, cdf_stream_t *scn)
! 637: {
! 638: size_t i;
! 639: const cdf_directory_t *d;
! 640:
! 641: for (i = 0; i < dir->dir_len; i++)
! 642: if (dir->dir_tab[i].d_type == CDF_DIR_TYPE_ROOT_STORAGE)
! 643: break;
! 644:
! 645: /* If the it is not there, just fake it; some docs don't have it */
! 646: if (i == dir->dir_len)
! 647: goto out;
! 648: d = &dir->dir_tab[i];
! 649:
! 650: /* If the it is not there, just fake it; some docs don't have it */
! 651: if (d->d_stream_first_sector < 0)
! 652: goto out;
! 653:
! 654: return cdf_read_long_sector_chain(info, h, sat,
! 655: d->d_stream_first_sector, d->d_size, scn);
! 656: out:
! 657: scn->sst_tab = NULL;
! 658: scn->sst_len = 0;
! 659: scn->sst_dirlen = 0;
! 660: return 0;
! 661: }
! 662:
! 663: static int
! 664: cdf_namecmp(const char *d, const uint16_t *s, size_t l)
! 665: {
! 666: for (; l--; d++, s++)
! 667: if (*d != CDF_TOLE2(*s))
! 668: return (unsigned char)*d - CDF_TOLE2(*s);
! 669: return 0;
! 670: }
! 671:
! 672: int
! 673: cdf_read_summary_info(const cdf_info_t *info, const cdf_header_t *h,
! 674: const cdf_sat_t *sat, const cdf_sat_t *ssat, const cdf_stream_t *sst,
! 675: const cdf_dir_t *dir, cdf_stream_t *scn)
! 676: {
! 677: size_t i;
! 678: const cdf_directory_t *d;
! 679: static const char name[] = "\05SummaryInformation";
! 680:
! 681: for (i = 0; i < dir->dir_len; i++)
! 682: if (dir->dir_tab[i].d_type == CDF_DIR_TYPE_USER_STREAM &&
! 683: cdf_namecmp(name, dir->dir_tab[i].d_name, sizeof(name))
! 684: == 0)
! 685: break;
! 686:
! 687: if (i == dir->dir_len) {
! 688: DPRINTF(("Cannot find summary information section\n"));
! 689: errno = EFTYPE;
! 690: return -1;
! 691: }
! 692: d = &dir->dir_tab[i];
! 693: return cdf_read_sector_chain(info, h, sat, ssat, sst,
! 694: d->d_stream_first_sector, d->d_size, scn);
! 695: }
! 696:
! 697: int
! 698: cdf_read_property_info(const cdf_stream_t *sst, uint32_t offs,
! 699: cdf_property_info_t **info, size_t *count, size_t *maxcount)
! 700: {
! 701: const cdf_section_header_t *shp;
! 702: cdf_section_header_t sh;
! 703: const uint32_t *p, *q, *e;
! 704: int16_t s16;
! 705: int32_t s32;
! 706: uint32_t u32;
! 707: int64_t s64;
! 708: uint64_t u64;
! 709: cdf_timestamp_t tp;
! 710: size_t i, o, nelements, j;
! 711: cdf_property_info_t *inp;
! 712:
! 713: if (offs > UINT32_MAX / 4) {
! 714: errno = EFTYPE;
! 715: goto out;
! 716: }
! 717: shp = (const void *)((const char *)sst->sst_tab + offs);
! 718: if (cdf_check_stream_offset(sst, shp, sizeof(*shp)) == -1)
! 719: goto out;
! 720: sh.sh_len = CDF_TOLE4(shp->sh_len);
! 721: #define CDF_SHLEN_LIMIT (UINT32_MAX / 8)
! 722: if (sh.sh_len > CDF_SHLEN_LIMIT) {
! 723: errno = EFTYPE;
! 724: goto out;
! 725: }
! 726: sh.sh_properties = CDF_TOLE4(shp->sh_properties);
! 727: #define CDF_PROP_LIMIT (UINT32_MAX / (4 * sizeof(*inp)))
! 728: if (sh.sh_properties > CDF_PROP_LIMIT)
! 729: goto out;
! 730: DPRINTF(("section len: %u properties %u\n", sh.sh_len,
! 731: sh.sh_properties));
! 732: if (*maxcount) {
! 733: if (*maxcount > CDF_PROP_LIMIT)
! 734: goto out;
! 735: *maxcount += sh.sh_properties;
! 736: inp = realloc(*info, *maxcount * sizeof(*inp));
! 737: } else {
! 738: *maxcount = sh.sh_properties;
! 739: inp = malloc(*maxcount * sizeof(*inp));
! 740: }
! 741: if (inp == NULL)
! 742: goto out;
! 743: *info = inp;
! 744: inp += *count;
! 745: *count += sh.sh_properties;
! 746: p = (const void *)((const char *)sst->sst_tab + offs + sizeof(sh));
! 747: e = (const void *)(((const char *)shp) + sh.sh_len);
! 748: if (cdf_check_stream_offset(sst, e, 0) == -1)
! 749: goto out;
! 750: for (i = 0; i < sh.sh_properties; i++) {
! 751: q = (const uint32_t *)((const char *)p +
! 752: CDF_TOLE4(p[(i << 1) + 1])) - 2;
! 753: if (q > e) {
! 754: DPRINTF(("Ran of the end %p > %p\n", q, e));
! 755: goto out;
! 756: }
! 757: inp[i].pi_id = CDF_TOLE4(p[i << 1]);
! 758: inp[i].pi_type = CDF_TOLE4(q[0]);
! 759: DPRINTF(("%d) id=%x type=%x offs=%x\n", i, inp[i].pi_id,
! 760: inp[i].pi_type, (const char *)q - (const char *)p));
! 761: if (inp[i].pi_type & CDF_VECTOR) {
! 762: nelements = CDF_TOLE4(q[1]);
! 763: o = 2;
! 764: } else {
! 765: nelements = 1;
! 766: o = 1;
! 767: }
! 768: if (inp[i].pi_type & (CDF_ARRAY|CDF_BYREF|CDF_RESERVED))
! 769: goto unknown;
! 770: switch (inp[i].pi_type & CDF_TYPEMASK) {
! 771: case CDF_EMPTY:
! 772: break;
! 773: case CDF_SIGNED16:
! 774: if (inp[i].pi_type & CDF_VECTOR)
! 775: goto unknown;
! 776: (void)memcpy(&s16, &q[o], sizeof(s16));
! 777: inp[i].pi_s16 = CDF_TOLE2(s16);
! 778: break;
! 779: case CDF_SIGNED32:
! 780: if (inp[i].pi_type & CDF_VECTOR)
! 781: goto unknown;
! 782: (void)memcpy(&s32, &q[o], sizeof(s32));
! 783: inp[i].pi_s32 = CDF_TOLE4(s32);
! 784: break;
! 785: case CDF_BOOL:
! 786: case CDF_UNSIGNED32:
! 787: if (inp[i].pi_type & CDF_VECTOR)
! 788: goto unknown;
! 789: (void)memcpy(&u32, &q[o], sizeof(u32));
! 790: inp[i].pi_u32 = CDF_TOLE4(u32);
! 791: break;
! 792: case CDF_SIGNED64:
! 793: if (inp[i].pi_type & CDF_VECTOR)
! 794: goto unknown;
! 795: (void)memcpy(&s64, &q[o], sizeof(s64));
! 796: inp[i].pi_s64 = CDF_TOLE4(s64);
! 797: break;
! 798: case CDF_UNSIGNED64:
! 799: if (inp[i].pi_type & CDF_VECTOR)
! 800: goto unknown;
! 801: (void)memcpy(&u64, &q[o], sizeof(u64));
! 802: inp[i].pi_u64 = CDF_TOLE4(u64);
! 803: break;
! 804: case CDF_LENGTH32_STRING:
! 805: if (nelements > 1) {
! 806: size_t nelem = inp - *info;
! 807: if (*maxcount > CDF_PROP_LIMIT
! 808: || nelements > CDF_PROP_LIMIT)
! 809: goto out;
! 810: *maxcount += nelements;
! 811: inp = realloc(*info, *maxcount * sizeof(*inp));
! 812: if (inp == NULL)
! 813: goto out;
! 814: *info = inp;
! 815: inp = *info + nelem;
! 816: }
! 817: DPRINTF(("nelements = %d\n", nelements));
! 818: for (j = 0; j < nelements; j++, i++) {
! 819: uint32_t l = CDF_TOLE4(q[o]);
! 820: inp[i].pi_str.s_len = l;
! 821: inp[i].pi_str.s_buf = (const char *)(&q[o+1]);
! 822: DPRINTF(("l = %d, r = %d, s = %s\n", l,
! 823: CDF_ROUND(l, sizeof(l)),
! 824: inp[i].pi_str.s_buf));
! 825: l = 4 + CDF_ROUND(l, sizeof(l));
! 826: o += l >> 2;
! 827: }
! 828: i--;
! 829: break;
! 830: case CDF_FILETIME:
! 831: if (inp[i].pi_type & CDF_VECTOR)
! 832: goto unknown;
! 833: (void)memcpy(&tp, &q[o], sizeof(tp));
! 834: inp[i].pi_tp = CDF_TOLE8(tp);
! 835: break;
! 836: case CDF_CLIPBOARD:
! 837: if (inp[i].pi_type & CDF_VECTOR)
! 838: goto unknown;
! 839: break;
! 840: default:
! 841: unknown:
! 842: DPRINTF(("Don't know how to deal with %x\n",
! 843: inp[i].pi_type));
! 844: goto out;
! 845: }
! 846: }
! 847: return 0;
! 848: out:
! 849: free(*info);
! 850: return -1;
! 851: }
! 852:
! 853: int
! 854: cdf_unpack_summary_info(const cdf_stream_t *sst, cdf_summary_info_header_t *ssi,
! 855: cdf_property_info_t **info, size_t *count)
! 856: {
! 857: size_t i, maxcount;
! 858: const cdf_summary_info_header_t *si = sst->sst_tab;
! 859: const cdf_section_declaration_t *sd = (const void *)
! 860: ((const char *)sst->sst_tab + CDF_SECTION_DECLARATION_OFFSET);
! 861:
! 862: if (cdf_check_stream_offset(sst, si, sizeof(*si)) == -1 ||
! 863: cdf_check_stream_offset(sst, sd, sizeof(*sd)) == -1)
! 864: return -1;
! 865: ssi->si_byte_order = CDF_TOLE2(si->si_byte_order);
! 866: ssi->si_os_version = CDF_TOLE2(si->si_os_version);
! 867: ssi->si_os = CDF_TOLE2(si->si_os);
! 868: ssi->si_class = si->si_class;
! 869: cdf_swap_class(&ssi->si_class);
! 870: ssi->si_count = CDF_TOLE2(si->si_count);
! 871: *count = 0;
! 872: maxcount = 0;
! 873: *info = NULL;
! 874: for (i = 0; i < CDF_TOLE4(si->si_count); i++) {
! 875: if (i >= CDF_LOOP_LIMIT) {
! 876: DPRINTF(("Unpack summary info loop limit"));
! 877: errno = EFTYPE;
! 878: return -1;
! 879: }
! 880: if (cdf_read_property_info(sst, CDF_TOLE4(sd->sd_offset),
! 881: info, count, &maxcount) == -1)
! 882: return -1;
! 883: }
! 884: return 0;
! 885: }
! 886:
! 887:
! 888:
! 889: int
! 890: cdf_print_classid(char *buf, size_t buflen, const cdf_classid_t *id)
! 891: {
! 892: return snprintf(buf, buflen, "%.8x-%.4x-%.4x-%.2x%.2x-"
! 893: "%.2x%.2x%.2x%.2x%.2x%.2x", id->cl_dword, id->cl_word[0],
! 894: id->cl_word[1], id->cl_two[0], id->cl_two[1], id->cl_six[0],
! 895: id->cl_six[1], id->cl_six[2], id->cl_six[3], id->cl_six[4],
! 896: id->cl_six[5]);
! 897: }
! 898:
! 899: static const struct {
! 900: uint32_t v;
! 901: const char *n;
! 902: } vn[] = {
! 903: { CDF_PROPERTY_CODE_PAGE, "Code page" },
! 904: { CDF_PROPERTY_TITLE, "Title" },
! 905: { CDF_PROPERTY_SUBJECT, "Subject" },
! 906: { CDF_PROPERTY_AUTHOR, "Author" },
! 907: { CDF_PROPERTY_KEYWORDS, "Keywords" },
! 908: { CDF_PROPERTY_COMMENTS, "Comments" },
! 909: { CDF_PROPERTY_TEMPLATE, "Template" },
! 910: { CDF_PROPERTY_LAST_SAVED_BY, "Last Saved By" },
! 911: { CDF_PROPERTY_REVISION_NUMBER, "Revision Number" },
! 912: { CDF_PROPERTY_TOTAL_EDITING_TIME, "Total Editing Time" },
! 913: { CDF_PROPERTY_LAST_PRINTED, "Last Printed" },
! 914: { CDF_PROPERTY_CREATE_TIME, "Create Time/Date" },
! 915: { CDF_PROPERTY_LAST_SAVED_TIME, "Last Saved Time/Date" },
! 916: { CDF_PROPERTY_NUMBER_OF_PAGES, "Number of Pages" },
! 917: { CDF_PROPERTY_NUMBER_OF_WORDS, "Number of Words" },
! 918: { CDF_PROPERTY_NUMBER_OF_CHARACTERS, "Number of Characters" },
! 919: { CDF_PROPERTY_THUMBNAIL, "Thumbnail" },
! 920: { CDF_PROPERTY_NAME_OF_APPLICATION, "Name of Creating Application" },
! 921: { CDF_PROPERTY_SECURITY, "Security" },
! 922: { CDF_PROPERTY_LOCALE_ID, "Locale ID" },
! 923: };
! 924:
! 925: int
! 926: cdf_print_property_name(char *buf, size_t bufsiz, uint32_t p)
! 927: {
! 928: size_t i;
! 929:
! 930: for (i = 0; i < __arraycount(vn); i++)
! 931: if (vn[i].v == p)
! 932: return snprintf(buf, bufsiz, "%s", vn[i].n);
! 933: return snprintf(buf, bufsiz, "0x%x", p);
! 934: }
! 935:
! 936: int
! 937: cdf_print_elapsed_time(char *buf, size_t bufsiz, cdf_timestamp_t ts)
! 938: {
! 939: size_t len = 0;
! 940: int days, hours, mins, secs;
! 941:
! 942: ts /= CDF_TIME_PREC;
! 943: secs = ts % 60;
! 944: ts /= 60;
! 945: mins = ts % 60;
! 946: ts /= 60;
! 947: hours = ts % 24;
! 948: ts /= 24;
! 949: days = ts;
! 950:
! 951: if (days) {
! 952: len += snprintf(buf + len, bufsiz - len, "%dd+", days);
! 953: if (len >= bufsiz)
! 954: return len;
! 955: }
! 956:
! 957: if (days || hours) {
! 958: len += snprintf(buf + len, bufsiz - len, "%.2d:", hours);
! 959: if (len >= bufsiz)
! 960: return len;
! 961: }
! 962:
! 963: len += snprintf(buf + len, bufsiz - len, "%.2d:", mins);
! 964: if (len >= bufsiz)
! 965: return len;
! 966:
! 967: len += snprintf(buf + len, bufsiz - len, "%.2d", secs);
! 968: return len;
! 969: }
! 970:
! 971:
! 972: #ifdef CDF_DEBUG
! 973: void
! 974: cdf_dump_header(const cdf_header_t *h)
! 975: {
! 976: size_t i;
! 977:
! 978: #define DUMP(a, b) (void)fprintf(stderr, "%40.40s = " a "\n", # b, h->h_ ## b)
! 979: #define DUMP2(a, b) (void)fprintf(stderr, "%40.40s = " a " (" a ")\n", # b, \
! 980: h->h_ ## b, 1 << h->h_ ## b)
! 981: DUMP("%d", revision);
! 982: DUMP("%d", version);
! 983: DUMP("0x%x", byte_order);
! 984: DUMP2("%d", sec_size_p2);
! 985: DUMP2("%d", short_sec_size_p2);
! 986: DUMP("%d", num_sectors_in_sat);
! 987: DUMP("%d", secid_first_directory);
! 988: DUMP("%d", min_size_standard_stream);
! 989: DUMP("%d", secid_first_sector_in_short_sat);
! 990: DUMP("%d", num_sectors_in_short_sat);
! 991: DUMP("%d", secid_first_sector_in_master_sat);
! 992: DUMP("%d", num_sectors_in_master_sat);
! 993: for (i = 0; i < __arraycount(h->h_master_sat); i++) {
! 994: if (h->h_master_sat[i] == CDF_SECID_FREE)
! 995: break;
! 996: (void)fprintf(stderr, "%35.35s[%.3zu] = %d\n",
! 997: "master_sat", i, h->h_master_sat[i]);
! 998: }
! 999: }
! 1000:
! 1001: void
! 1002: cdf_dump_sat(const char *prefix, const cdf_sat_t *sat, size_t size)
! 1003: {
! 1004: size_t i, j, s = size / sizeof(cdf_secid_t);
! 1005:
! 1006: for (i = 0; i < sat->sat_len; i++) {
! 1007: (void)fprintf(stderr, "%s[%zu]:\n%.6d: ", prefix, i, i * s);
! 1008: for (j = 0; j < s; j++) {
! 1009: (void)fprintf(stderr, "%5d, ",
! 1010: CDF_TOLE4(sat->sat_tab[s * i + j]));
! 1011: if ((j + 1) % 10 == 0)
! 1012: (void)fprintf(stderr, "\n%.6d: ",
! 1013: i * s + j + 1);
! 1014: }
! 1015: (void)fprintf(stderr, "\n");
! 1016: }
! 1017: }
! 1018:
! 1019: void
! 1020: cdf_dump(void *v, size_t len)
! 1021: {
! 1022: size_t i, j;
! 1023: unsigned char *p = v;
! 1024: char abuf[16];
! 1025: (void)fprintf(stderr, "%.4x: ", 0);
! 1026: for (i = 0, j = 0; i < len; i++, p++) {
! 1027: (void)fprintf(stderr, "%.2x ", *p);
! 1028: abuf[j++] = isprint(*p) ? *p : '.';
! 1029: if (j == 16) {
! 1030: j = 0;
! 1031: abuf[15] = '\0';
! 1032: (void)fprintf(stderr, "%s\n%.4x: ", abuf, i + 1);
! 1033: }
! 1034: }
! 1035: (void)fprintf(stderr, "\n");
! 1036: }
! 1037:
! 1038: void
! 1039: cdf_dump_stream(const cdf_header_t *h, const cdf_stream_t *sst)
! 1040: {
! 1041: size_t ss = sst->sst_dirlen < h->h_min_size_standard_stream ?
! 1042: CDF_SHORT_SEC_SIZE(h) : CDF_SEC_SIZE(h);
! 1043: cdf_dump(sst->sst_tab, ss * sst->sst_len);
! 1044: }
! 1045:
! 1046: void
! 1047: cdf_dump_dir(const cdf_info_t *info, const cdf_header_t *h,
! 1048: const cdf_sat_t *sat, const cdf_sat_t *ssat, const cdf_stream_t *sst,
! 1049: const cdf_dir_t *dir)
! 1050: {
! 1051: size_t i, j;
! 1052: cdf_directory_t *d;
! 1053: char name[__arraycount(d->d_name)];
! 1054: cdf_stream_t scn;
! 1055: struct timeval ts;
! 1056:
! 1057: static const char *types[] = { "empty", "user storage",
! 1058: "user stream", "lockbytes", "property", "root storage" };
! 1059:
! 1060: for (i = 0; i < dir->dir_len; i++) {
! 1061: d = &dir->dir_tab[i];
! 1062: for (j = 0; j < sizeof(name); j++)
! 1063: name[j] = (char)CDF_TOLE2(d->d_name[j]);
! 1064: (void)fprintf(stderr, "Directory %zu: %s\n", i, name);
! 1065: if (d->d_type < __arraycount(types))
! 1066: (void)fprintf(stderr, "Type: %s\n", types[d->d_type]);
! 1067: else
! 1068: (void)fprintf(stderr, "Type: %d\n", d->d_type);
! 1069: (void)fprintf(stderr, "Color: %s\n",
! 1070: d->d_color ? "black" : "red");
! 1071: (void)fprintf(stderr, "Left child: %d\n", d->d_left_child);
! 1072: (void)fprintf(stderr, "Right child: %d\n", d->d_right_child);
! 1073: (void)fprintf(stderr, "Flags: 0x%x\n", d->d_flags);
! 1074: cdf_timestamp_to_timespec(&ts, d->d_created);
! 1075: (void)fprintf(stderr, "Created %s", ctime(&ts.tv_sec));
! 1076: cdf_timestamp_to_timespec(&ts, d->d_modified);
! 1077: (void)fprintf(stderr, "Modified %s", ctime(&ts.tv_sec));
! 1078: (void)fprintf(stderr, "Stream %d\n", d->d_stream_first_sector);
! 1079: (void)fprintf(stderr, "Size %d\n", d->d_size);
! 1080: switch (d->d_type) {
! 1081: case CDF_DIR_TYPE_USER_STORAGE:
! 1082: (void)fprintf(stderr, "Storage: %d\n", d->d_storage);
! 1083: break;
! 1084: case CDF_DIR_TYPE_USER_STREAM:
! 1085: if (sst == NULL)
! 1086: break;
! 1087: if (cdf_read_sector_chain(info, h, sat, ssat, sst,
! 1088: d->d_stream_first_sector, d->d_size, &scn) == -1) {
! 1089: warn("Can't read stream for %s at %d len %d",
! 1090: name, d->d_stream_first_sector, d->d_size);
! 1091: break;
! 1092: }
! 1093: cdf_dump_stream(h, &scn);
! 1094: free(scn.sst_tab);
! 1095: break;
! 1096: default:
! 1097: break;
! 1098: }
! 1099:
! 1100: }
! 1101: }
! 1102:
! 1103: void
! 1104: cdf_dump_property_info(const cdf_property_info_t *info, size_t count)
! 1105: {
! 1106: cdf_timestamp_t tp;
! 1107: struct timeval ts;
! 1108: char buf[64];
! 1109: size_t i;
! 1110:
! 1111: for (i = 0; i < count; i++) {
! 1112: cdf_print_property_name(buf, sizeof(buf), info[i].pi_id);
! 1113: (void)fprintf(stderr, "%zu) %s: ", i, buf);
! 1114: switch (info[i].pi_type) {
! 1115: case CDF_SIGNED16:
! 1116: (void)fprintf(stderr, "signed 16 [%hd]\n",
! 1117: info[i].pi_s16);
! 1118: break;
! 1119: case CDF_SIGNED32:
! 1120: (void)fprintf(stderr, "signed 32 [%d]\n",
! 1121: info[i].pi_s32);
! 1122: break;
! 1123: case CDF_UNSIGNED32:
! 1124: (void)fprintf(stderr, "unsigned 32 [%u]\n",
! 1125: info[i].pi_u32);
! 1126: break;
! 1127: case CDF_LENGTH32_STRING:
! 1128: (void)fprintf(stderr, "string %u [%.*s]\n",
! 1129: info[i].pi_str.s_len,
! 1130: info[i].pi_str.s_len, info[i].pi_str.s_buf);
! 1131: break;
! 1132: case CDF_FILETIME:
! 1133: tp = info[i].pi_tp;
! 1134: #if defined(PHP_WIN32) && _MSC_VER <= 1500
! 1135: if (tp < 1000000000000000i64) {
! 1136: #else
! 1137: if (tp < 1000000000000000LL) {
! 1138: #endif
! 1139: cdf_print_elapsed_time(buf, sizeof(buf), tp);
! 1140: (void)fprintf(stderr, "timestamp %s\n", buf);
! 1141: } else {
! 1142: cdf_timestamp_to_timespec(&ts, tp);
! 1143: (void)fprintf(stderr, "timestamp %s",
! 1144: ctime(&ts.tv_sec));
! 1145: }
! 1146: break;
! 1147: case CDF_CLIPBOARD:
! 1148: (void)fprintf(stderr, "CLIPBOARD %u\n", info[i].pi_u32);
! 1149: break;
! 1150: default:
! 1151: DPRINTF(("Don't know how to deal with %x\n",
! 1152: info[i].pi_type));
! 1153: break;
! 1154: }
! 1155: }
! 1156: }
! 1157:
! 1158:
! 1159: void
! 1160: cdf_dump_summary_info(const cdf_header_t *h, const cdf_stream_t *sst)
! 1161: {
! 1162: char buf[128];
! 1163: cdf_summary_info_header_t ssi;
! 1164: cdf_property_info_t *info;
! 1165: size_t count;
! 1166:
! 1167: (void)&h;
! 1168: if (cdf_unpack_summary_info(sst, &ssi, &info, &count) == -1)
! 1169: return;
! 1170: (void)fprintf(stderr, "Endian: %x\n", ssi.si_byte_order);
! 1171: (void)fprintf(stderr, "Os Version %d.%d\n", ssi.si_os_version & 0xff,
! 1172: ssi.si_os_version >> 8);
! 1173: (void)fprintf(stderr, "Os %d\n", ssi.si_os);
! 1174: cdf_print_classid(buf, sizeof(buf), &ssi.si_class);
! 1175: (void)fprintf(stderr, "Class %s\n", buf);
! 1176: (void)fprintf(stderr, "Count %d\n", ssi.si_count);
! 1177: cdf_dump_property_info(info, count);
! 1178: free(info);
! 1179: }
! 1180:
! 1181: #endif
! 1182:
! 1183: #ifdef TEST
! 1184: int
! 1185: main(int argc, char *argv[])
! 1186: {
! 1187: int i;
! 1188: cdf_header_t h;
! 1189: cdf_sat_t sat, ssat;
! 1190: cdf_stream_t sst, scn;
! 1191: cdf_dir_t dir;
! 1192: cdf_info_t info;
! 1193:
! 1194: if (argc < 2) {
! 1195: (void)fprintf(stderr, "Usage: %s <filename>\n", getprogname());
! 1196: return -1;
! 1197: }
! 1198:
! 1199: info.i_buf = NULL;
! 1200: info.i_len = 0;
! 1201: for (i = 1; i < argc; i++) {
! 1202: if ((info.i_fd = open(argv[1], O_RDONLY)) == -1)
! 1203: err(1, "Cannot open `%s'", argv[1]);
! 1204:
! 1205: if (cdf_read_header(&info, &h) == -1)
! 1206: err(1, "Cannot read header");
! 1207: #ifdef CDF_DEBUG
! 1208: cdf_dump_header(&h);
! 1209: #endif
! 1210:
! 1211: if (cdf_read_sat(&info, &h, &sat) == -1)
! 1212: err(1, "Cannot read sat");
! 1213: #ifdef CDF_DEBUG
! 1214: cdf_dump_sat("SAT", &sat, CDF_SEC_SIZE(&h));
! 1215: #endif
! 1216:
! 1217: if (cdf_read_ssat(&info, &h, &sat, &ssat) == -1)
! 1218: err(1, "Cannot read ssat");
! 1219: #ifdef CDF_DEBUG
! 1220: cdf_dump_sat("SSAT", &h, &ssat, CDF_SHORT_SEC_SIZE(&h));
! 1221: #endif
! 1222:
! 1223: if (cdf_read_dir(&info, &h, &sat, &dir) == -1)
! 1224: err(1, "Cannot read dir");
! 1225:
! 1226: if (cdf_read_short_stream(&info, &h, &sat, &dir, &sst) == -1)
! 1227: err(1, "Cannot read short stream");
! 1228: #ifdef CDF_DEBUG
! 1229: cdf_dump_stream(&h, &sst);
! 1230: #endif
! 1231:
! 1232: #ifdef CDF_DEBUG
! 1233: cdf_dump_dir(&info, &h, &sat, &ssat, &sst, &dir);
! 1234: #endif
! 1235:
! 1236:
! 1237: if (cdf_read_summary_info(&info, &h, &sat, &ssat, &sst, &dir,
! 1238: &scn) == -1)
! 1239: err(1, "Cannot read summary info");
! 1240: #ifdef CDF_DEBUG
! 1241: cdf_dump_summary_info(&h, &scn);
! 1242: #endif
! 1243:
! 1244: (void)close(info.i_fd);
! 1245: }
! 1246:
! 1247: return 0;
! 1248: }
! 1249: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>