Logo Search packages:      
Sourcecode: ksh version File versions  Download package

pax-tnef.c

/***********************************************************************
*                                                                      *
*               This software is part of the ast package               *
*          Copyright (c) 1987-2007 AT&T Intellectual Property          *
*                      and is licensed under the                       *
*                  Common Public License, Version 1.0                  *
*                    by AT&T Intellectual Property                     *
*                                                                      *
*                A copy of the License is available at                 *
*            http://www.opensource.org/licenses/cpl1.0.txt             *
*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
*                                                                      *
*              Information and Software Systems Research               *
*                            AT&T Research                             *
*                           Florham Park NJ                            *
*                                                                      *
*                 Glenn Fowler <gsf@research.att.com>                  *
*                                                                      *
***********************************************************************/
#pragma prototyped

/*
 * pax tnef format
 */

#include "format.h"

#include <tm.h>

#define TNEF_MAGIC      0x223e9f78

typedef struct Tnef_s
{
      char*       format;
      off_t       offset;
} Tnef_t;

static int
tnef_getprologue(Pax_t* pax, Format_t* fp, register Archive_t* ap, File_t* f, unsigned char* buf, size_t size)
{
      Tnef_t*           tnef;
      uint32_t    magic;

      if (size < 6)
            return 0;
      magic = TNEF_MAGIC;
      if ((ap->swap = swapop(&magic, buf, 4)) < 0 || paxread(pax, ap, NiL, (off_t)6, (off_t)6, 0) != 6)
            return 0;
      if (!(tnef = newof(0, Tnef_t, 1, 0)))
            nospace();
      ap->data = (void*)tnef;
      ap->swap = 3;
      return 1;
}

static int
tnef_getheader(Pax_t* pax, Archive_t* ap, register File_t* f)
{
      Tnef_t*                 tnef = (Tnef_t*)ap->data;
      char*             s;
      char*             e;
      unsigned char*          x;
      size_t                  n;
      size_t                  m;
      size_t                  z;
      unsigned int            level;
      unsigned int            type;
      unsigned int            name;
      unsigned int            checksum;
      size_t                  size;
      size_t                  part;
      Tm_t              tm;

      *(f->name = paxstash(pax, &ap->stash.head, NiL, PATH_MAX)) = 0;
      f->st->st_dev = 0;
      f->st->st_ino = 0;
      f->st->st_mode = X_IFREG|X_IRUSR|X_IWUSR|X_IRGRP|X_IROTH;
      f->st->st_uid = state.uid;
      f->st->st_gid = state.gid;
      f->st->st_nlink = 1;
      IDEVICE(f->st, 0);
      f->st->st_mtime = f->st->st_ctime = f->st->st_atime = NOW;
      f->st->st_size = 0;
      while (paxread(pax, ap, s = state.tmp.buffer, (off_t)0, (off_t)9, 0) > 0)
      {
            level = swapget(ap->swap, s + 0, 1);
            n = swapget(ap->swap, s + 1, 4);
            type = n >> 16;
            name = n & ((1<<16)-1);
            n = 0;
            size = swapget(ap->swap, s + 5, 4);
            part = ap->io->buffersize;
            if (size > part)
            {
                  if (level == 2)
                  {
                        level = 0;
                        if (name == 0x800f)
                        {
                              f->st->st_size = size;
                              tnef->offset = paxseek(pax, ap, (off_t)0, SEEK_CUR, 0);
                        }
                        else
                              error(1, "%s: %s format 0x%04x attribute ignored", ap->name, ap->format->name, name);
                  }
                  while (size > part)
                  {
                        size -= part;
                        if (!(s = paxget(pax, ap, part, NiL)))
                              error(3, "%s: %s format 0x%04x attribute data truncated -- %d expected", ap->name, ap->format->name, name, part);
                        x = (unsigned char*)s;
                        e = s + part;
                        while (x < (unsigned char*)e)
                              n += *x++;
                  }
            }
            if (!(s = paxget(pax, ap, size + 2, NiL)))
                  error(3, "%s: %s format 0x%04x attribute data truncated -- %d expected", ap->name, ap->format->name, name, size);
            checksum = swapget(ap->swap, s + size, 2);
            x = (unsigned char*)s;
            e = s + size;
            while (x < (unsigned char*)e)
                  n += *x++;
            n &= ((1<<16)-1);
            if (checksum != n)
                  error(3, "%s: %s format attribute data checksum error", ap->name, ap->format->name);
            if (level == 2)
                  switch (name)
                  {
                  case 0x800f: /* data */
                        f->st->st_size = size;
                        tnef->offset = paxseek(pax, ap, (off_t)0, SEEK_CUR, 0) - size - 2;
                        break;
                  case 0x8010: /* title */
                        if (!f->name)
                              f->name = paxstash(pax, &ap->stash.head, s, size);
                        break;
                  case 0x8013: /* date */
                        if (type == 0x0003 && size >= 12)
                        {
                              tm.tm_year = swapget(ap->swap, s +  0, 2) - 1900;
                              tm.tm_mon  = swapget(ap->swap, s +  2, 2) - 1;
                              tm.tm_mday = swapget(ap->swap, s +  4, 2);
                              tm.tm_hour = swapget(ap->swap, s +  6, 2);
                              tm.tm_min  = swapget(ap->swap, s +  8, 2);
                              tm.tm_sec  = swapget(ap->swap, s + 10, 2);
                              f->st->st_mtime = tmtime(&tm, TM_LOCALZONE);
                        }
                        break;
                  case 0x9005: /* attachment */
                        if (size >= 4)
                        {
                              e = s + size - 4;
                              n = swapget(ap->swap, s, 4); s += 4;
                              while (n-- && s < e)
                              {
                                    type = swapget(ap->swap, s, 2); s += 2;
                                    name = swapget(ap->swap, s, 2); s += 2;
                                    switch (type)
                                    {
                                    case 0x0002:
                                    case 0x000b:
                                          s += 2;
                                          break;
                                    case 0x0003:
                                    case 0x0004:
                                    case 0x0007:
                                    case 0x000a:
                                    case 0x000d:
                                    case 0x0048:
                                          s += 4;
                                          break;
                                    case 0x0005:
                                    case 0x0006:
                                    case 0x0014:
                                    case 0x0040:
                                          s += 8;
                                          break;
                                    case 0x001e:
                                    case 0x001f:
                                    case 0x0102:
                                          m = swapget(ap->swap, s, 4); s += 4;
                                          while (m--)
                                          {
                                                z = swapget(ap->swap, s, 4); s += 4;
                                                z = roundof(z, 4);
                                                if (name == 0x3707)
                                                      f->name = paxstash(pax, &ap->stash.head, s, z);
                                                s += z;
                                          }
                                          break;
                                    }
                              }
                        }
                        n = tnef->offset;
                        tnef->offset = paxseek(pax, ap, (off_t)0, SEEK_CUR, 0);
                        if (paxseek(pax, ap, n, SEEK_SET, 1) != n)
                              error(3, "%s: %s input must be seekable", ap->name, ap->format->name);
                        return 1;
                  }
      }
      if (ap->io->eof && ap->entry == 1)
            error(1, "%s: no members in %s file", ap->name, ap->format->name);
      return 0;
}

static int
tnef_done(Pax_t* pax, register Archive_t* ap)
{
      if (ap->data)
      {
            free(ap->data);
            ap->data = 0;
      }
      return 0;
}

static int
tnef_gettrailer(Pax_t* pax, Archive_t* ap, File_t* f)
{
      register Tnef_t*  tnef = (Tnef_t*)ap->data;

      if (paxseek(pax, ap, tnef->offset, SEEK_SET, 1) != tnef->offset)
            error(3, "%s: %s format seek error", ap->name, ap->format->name);
      return 1;
}

Format_t    pax_tnef_format =
{
      "tnef",
      0,
      "MS outlook transport neutral encapsulation format",
      0,
      ARCHIVE|DOS|NOHARDLINKS|IN,
      DEFBUFFER,
      DEFBLOCKS,
      0,
      PAXNEXT(pax_tnef_next),
      0,
      tnef_done,
      tnef_getprologue,
      tnef_getheader,
      0,
      tnef_gettrailer,
};

PAXLIB(&pax_tnef_format)

Generated by  Doxygen 1.6.0   Back to index