Back to index

php5  5.3.10
readcdf.c
Go to the documentation of this file.
00001 /*-
00002  * Copyright (c) 2008 Christos Zoulas
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  *
00014  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
00015  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00016  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00017  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
00018  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00019  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00020  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00021  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00022  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00023  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00024  * POSSIBILITY OF SUCH DAMAGE.
00025  */
00026 #include "file.h"
00027 
00028 #ifndef lint
00029 FILE_RCSID("@(#)$File: readcdf.c,v 1.18 2009/05/06 20:48:22 christos Exp $")
00030 #endif
00031 
00032 #include <stdlib.h>
00033 #ifdef PHP_WIN32
00034 #include "win32/unistd.h"
00035 #else
00036 #include <unistd.h>
00037 #endif
00038 #include <string.h>
00039 #include <time.h>
00040 #include <ctype.h>
00041 
00042 #include "cdf.h"
00043 #include "magic.h"
00044 
00045 #define NOTMIME(ms) (((ms)->flags & MAGIC_MIME) == 0)
00046 
00047 private int
00048 cdf_file_property_info(struct magic_set *ms, const cdf_property_info_t *info,
00049     size_t count)
00050 {
00051        size_t i;
00052        cdf_timestamp_t tp;
00053        struct timeval ts;
00054        char buf[64];
00055        const char *str = "vnd.ms-office";
00056        const char *s;
00057        int len;
00058 
00059        for (i = 0; i < count; i++) {
00060               cdf_print_property_name(buf, sizeof(buf), info[i].pi_id);
00061               switch (info[i].pi_type) {
00062               case CDF_SIGNED16:
00063                      if (NOTMIME(ms) && file_printf(ms, ", %s: %hd", buf,
00064                          info[i].pi_s16) == -1)
00065                             return -1;
00066                      break;
00067               case CDF_SIGNED32:
00068                      if (NOTMIME(ms) && file_printf(ms, ", %s: %d", buf,
00069                          info[i].pi_s32) == -1)
00070                             return -1;
00071                      break;
00072               case CDF_UNSIGNED32:
00073                      if (NOTMIME(ms) && file_printf(ms, ", %s: %u", buf,
00074                          info[i].pi_u32) == -1)
00075                             return -1;
00076                      break;
00077               case CDF_LENGTH32_STRING:
00078                      len = info[i].pi_str.s_len;
00079                      if (len > 1) {
00080                             s = info[i].pi_str.s_buf;
00081                             if (NOTMIME(ms)) {
00082                                    char vbuf[1024];
00083                                    size_t j;
00084                                    for (j = 0; j < sizeof(vbuf) && len--;
00085                                        j++, s++) {
00086                                           if (*s == '\0')
00087                                                  break;
00088                                           if (isprint((unsigned char)*s))
00089                                                  vbuf[j] = *s;
00090                                    }
00091                                    if (j == sizeof(vbuf))
00092                                           --j;
00093                                    vbuf[j] = '\0';
00094                                    if (vbuf[0]) {
00095                                           if (file_printf(ms, ", %s: %s",
00096                                               buf, vbuf) == -1)
00097                                                  return -1;
00098                                    }
00099                             } else if (info[i].pi_id == 
00100                                    CDF_PROPERTY_NAME_OF_APPLICATION) {
00101                                    if (strstr(s, "Word"))
00102                                           str = "msword";
00103                                    else if (strstr(s, "Excel"))
00104                                           str = "vnd.ms-excel";
00105                                    else if (strstr(s, "Powerpoint"))
00106                                           str = "vnd.ms-powerpoint";
00107                             }
00108                      }
00109                      break;
00110               case CDF_FILETIME:
00111                      tp = info[i].pi_tp;
00112                      if (tp != 0) {
00113 #if defined(PHP_WIN32) && _MSC_VER <= 1500
00114                             if (tp < 1000000000000000i64) {
00115 #else
00116                             if (tp < 1000000000000000LL) {
00117 #endif
00118                                    char tbuf[64];
00119                                    cdf_print_elapsed_time(tbuf,
00120                                        sizeof(tbuf), tp);
00121                                    if (NOTMIME(ms) && file_printf(ms,
00122                                        ", %s: %s", buf, tbuf) == -1)
00123                                           return -1;
00124                             } else {
00125                                    char *c, *ec;
00126 
00127                                    if (cdf_timestamp_to_timespec(&ts, tp) == -1) {
00128                                           return -1;
00129                                    }
00130                                    c = ctime(&ts.tv_sec);
00131                                    if ((ec = strchr(c, '\n')) != NULL)
00132                                           *ec = '\0';
00133 
00134                                    if (NOTMIME(ms) && file_printf(ms,
00135                                        ", %s: %s", buf, c) == -1)
00136                                           return -1;
00137                             }
00138                      }
00139                      break;
00140               case CDF_CLIPBOARD:
00141                      break;
00142               default:
00143                      return -1;
00144               }
00145        }
00146        if (!NOTMIME(ms)) {
00147               if (file_printf(ms, "application/%s", str) == -1)
00148                      return -1;
00149        }
00150        return 1;
00151 }
00152 
00153 private int
00154 cdf_file_summary_info(struct magic_set *ms, const cdf_stream_t *sst)
00155 {
00156        cdf_summary_info_header_t si;
00157        cdf_property_info_t *info;
00158        size_t count;
00159        int m;
00160 
00161        if (cdf_unpack_summary_info(sst, &si, &info, &count) == -1)
00162               return -1;
00163 
00164        if (NOTMIME(ms)) {
00165               if (file_printf(ms, "CDF V2 Document") == -1)
00166                      return -1;
00167 
00168               if (file_printf(ms, ", %s Endian",
00169                   si.si_byte_order == 0xfffe ?  "Little" : "Big") == -1)
00170                      return -1;
00171               switch (si.si_os) {
00172               case 2:
00173                      if (file_printf(ms, ", Os: Windows, Version %d.%d",
00174                          si.si_os_version & 0xff, si.si_os_version >> 8)
00175                          == -1)
00176                             return -1;
00177                      break;
00178               case 1:
00179                      if (file_printf(ms, ", Os: MacOS, Version %d.%d",
00180                          si.si_os_version >> 8, si.si_os_version & 0xff)
00181                          == -1)
00182                             return -1;
00183                      break;
00184               default:
00185                      if (file_printf(ms, ", Os %d, Version: %d.%d", si.si_os,
00186                          si.si_os_version & 0xff, si.si_os_version >> 8)
00187                          == -1)
00188                             return -1;
00189                      break;
00190               }
00191        }
00192 
00193        m = cdf_file_property_info(ms, info, count);
00194        free(info);
00195 
00196        return m;
00197 }
00198 
00199 protected int
00200 file_trycdf(struct magic_set *ms, int fd, const unsigned char *buf,
00201     size_t nbytes)
00202 {
00203        cdf_info_t info;
00204        cdf_header_t h;
00205        cdf_sat_t sat, ssat;
00206        cdf_stream_t sst, scn;
00207        cdf_dir_t dir;
00208        int i;
00209        const char *expn = "";
00210 
00211        info.i_fd = fd;
00212        info.i_buf = buf;
00213        info.i_len = nbytes;
00214        if (ms->flags & MAGIC_APPLE)
00215               return 0;
00216        if (cdf_read_header(&info, &h) == -1)
00217               return 0;
00218 #ifdef CDF_DEBUG
00219        cdf_dump_header(&h);
00220 #endif
00221 
00222        if ((i = cdf_read_sat(&info, &h, &sat)) == -1) {
00223               expn = "Can't read SAT";
00224               goto out0;
00225        }
00226 #ifdef CDF_DEBUG
00227        cdf_dump_sat("SAT", &sat, CDF_SEC_SIZE(&h));
00228 #endif
00229 
00230        if ((i = cdf_read_ssat(&info, &h, &sat, &ssat)) == -1) {
00231               expn = "Can't read SSAT";
00232               goto out1;
00233        }
00234 #ifdef CDF_DEBUG
00235        cdf_dump_sat("SSAT", &ssat, CDF_SHORT_SEC_SIZE(&h));
00236 #endif
00237 
00238        if ((i = cdf_read_dir(&info, &h, &sat, &dir)) == -1) {
00239               expn = "Can't read directory";
00240               goto out2;
00241        }
00242 
00243        if ((i = cdf_read_short_stream(&info, &h, &sat, &dir, &sst)) == -1) {
00244               expn = "Cannot read short stream";
00245               goto out3;
00246        }
00247 #ifdef CDF_DEBUG
00248        cdf_dump_dir(&info, &h, &sat, &ssat, &sst, &dir);
00249 #endif
00250 
00251        if ((i = cdf_read_summary_info(&info, &h, &sat, &ssat, &sst, &dir,
00252            &scn)) == -1) {
00253               expn = "Cannot read summary info";
00254               goto out4;
00255        }
00256 #ifdef CDF_DEBUG
00257        cdf_dump_summary_info(&h, &scn);
00258 #endif
00259        if ((i = cdf_file_summary_info(ms, &scn)) == -1)
00260               expn = "Can't expand summary_info";
00261        free(scn.sst_tab);
00262 out4:
00263        free(sst.sst_tab);
00264 out3:
00265        free(dir.dir_tab);
00266 out2:
00267        free(ssat.sat_tab);
00268 out1:
00269        free(sat.sat_tab);
00270 out0:
00271        if (i != 1) {
00272               if (file_printf(ms, "CDF V2 Document") == -1)
00273                      return -1;
00274               if (*expn)
00275                      if (file_printf(ms, ", corrupt: %s", expn) == -1)
00276                             return -1;
00277               i = 1;
00278        }
00279        return i;
00280 }