#include <stdio.h>
#include <string.h>
#include "libpgp5.h"
#include <zlib.h>

#define BSIZ 10240

int pgpdcom5(FILE * inf, FILE * outf)
{
  unsigned int noteof, inlen;
  int readlen, readgot, firstflag = 0, isav;
  unsigned char ibuf[BSIZ], obuf[BSIZ];
  z_stream pgpz;

  pgpz.zalloc = (alloc_func) 0;
  pgpz.zfree = (free_func) 0;
  pgpz.opaque = (voidpf) 0;

  inlen = fgetc(inf);

  if ((inlen & 0xfc) == 0xa0) {
    if (inlen != 0xa3)          /* bypass length if it exists */
      fread(ibuf, 1, 1 << (inlen & 3), inf);
    if (fgetc(inf) != 1)
      return -1;
    inflateInit2(&pgpz, -13);   /* for pgp */
    do {
      pgpz.next_in = ibuf;
      pgpz.avail_in = inlen = fread(ibuf, 1, BSIZ, inf);
      while (pgpz.avail_in) {
        pgpz.next_out = obuf, pgpz.avail_out = BSIZ;
        noteof = inflate(&pgpz, 0);
        fwrite(obuf, 1, BSIZ - pgpz.avail_out, outf);
        if (noteof != Z_OK)
          break;
      }
    } while (inlen == BSIZ);
    do {                        /* finish any further output */
      pgpz.next_out = obuf, pgpz.avail_out = BSIZ;
      noteof = inflate(&pgpz, Z_FINISH);
      fwrite(obuf, 1, BSIZ - pgpz.avail_out, outf);
    } while (noteof == Z_OK && pgpz.avail_out != BSIZ);
    return (noteof == Z_STREAM_END);

  }
  if (inlen != 0xc8)
    return -1;

  pgpz.next_out = obuf, pgpz.avail_out = BSIZ;

  inflateInit2(&pgpz, -13);     /* for pgp */

  inlen = 0;
  noteof = 1;
  firstflag = 1;

  while (!feof(inf) && noteof) {

    if (!inlen && noteof) {
      noteof = 0;
      inlen = 0xff & fgetc(inf);
      if (inlen >= 0xc0) {
        if (inlen >= 0xe0) {
          if (inlen == 0xff) {
            inlen = fgetc(inf) << 24;
            inlen += fgetc(inf) << 16;
            inlen += fgetc(inf) << 8;
            inlen += fgetc(inf);
          } else {
            noteof = 1;
            inlen = 1 << (inlen & 31);
          }
        } else {
          inlen = ((inlen & 31) << 8) + 192;
          inlen += 0xff & fgetc(inf);
        }
      }
    }
    while (inlen) {
      if (firstflag) {
        firstflag = 0;
        fgetc(inf);
        inlen--;
      }
      readlen = inlen;
      if (readlen > BSIZ)
        readlen = BSIZ;
      readgot = fread(ibuf, 1, readlen, inf);
      if (readgot <= 0)
        break;
      inlen -= readgot;

      pgpz.next_in = ibuf;
      pgpz.avail_in = readgot;
      while (pgpz.avail_in) {
        inflate(&pgpz, 0);
        fwrite(obuf, 1, BSIZ - pgpz.avail_out, outf);
        pgpz.avail_out = BSIZ;
        pgpz.next_out = obuf;
      }
    }
  }
  do {
    isav = inflate(&pgpz, Z_FINISH);
    fwrite(obuf, 1, BSIZ - pgpz.avail_out, outf);
    pgpz.avail_out = BSIZ;
    pgpz.next_out = obuf;
  } while (isav == Z_OK);

  return 0;
}
