#include <stdio.h>
#include <string.h>

extern unsigned long crctab[256];
unsigned char dmtab[84] =
{0xff, 0xff, 0xff, 0x3e, 0xff, 0x41, 0xff, 0x3f, 0x34, 0x35, 0x36, 0x37,
 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff, 0xff, 0x40, 0xff, 0xff,
 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1a, 0x1b, 0x1c,
 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0xff};

/*-------------------------*/
/* called by dearmor, with NULL ofd to get crc */
static unsigned char inbuf[256], *ip = inbuf;
long unmime(FILE * ifd, FILE * ofd)
{
  unsigned char obuf[800], *c = obuf;
  int i = 3, ocnt = 0, j;
  unsigned long t, ccrc = 0xB704CE;

  inbuf[0] = 0;
  while (i == 3) {
    for (i = 0; i < 4; i++) {
      while (!(j = *ip++) || j > 124 || j < 40 || (c[i] = dmtab[j - 40]) > 65)
        if (!j && !fgets(ip = inbuf, 255, ifd))
          return -1;
      if (c[i] < 64)
        continue;
      if (ofd)
        break;
      i--;
    }
    t = (c[0] << 18) | (c[1] << 12) | (c[2] << 6) | c[3];
    if (!ofd)
      return t;
    c[0] = t >> 16, c[1] = t >> 8, c[2] = t;
    i -= (i > 1);
    c += i, ocnt += i;
    if (i != 3 || ocnt > 768) {
      for (t = 0; t < ocnt; t++)
        ccrc = ccrc << 8 ^ crctab[0xff & ((ccrc >> 16) ^ obuf[t])];
      fwrite(obuf, 1, ocnt, ofd);
      c = obuf, ocnt = 0;
    }
  }
  return ccrc & 0xffffff;
}

/*-------------------------*/
/* dearmor - should also return cert type and headers... */
int dearmor(FILE * ifd, FILE * ofd)
{
  unsigned char dbuf[256];

  while (!feof(ifd)) {
    fgets(dbuf, 255, ifd);
    if (strncmp(dbuf, "-----BEGIN PGP ", 15) ||
        !strncmp(dbuf, "-----BEGIN PGP SIGNED MESSAGE-----", 34))
      continue;                 /* skip to message */
    while (dbuf[0] != '\n' && dbuf[0] != '\r')
      fgets(dbuf, 255, ifd);
    if (unmime(ifd, ofd) != unmime(ifd, NULL))
      return -1;
    /* scan past -----END ? */
  }
  return 0;
}
