Annotation of embedaddon/php/ext/fileinfo/libmagic/cdf.c, revision 1.1.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>