#include "libopgp.h"
#include <zlib.h>

#define BSIZ 256

int PGP_unzip(FILE * inf, FILE * outf)
{
  u32_t neof, ll;
  int got, firstflag = 1, k = 0;
  u8_t ibuf[BSIZ], obuf[BSIZ];
  z_stream pgpz;

  ll = fgetc(inf);
  if ((ll & 0xfc) == 0xa0) {    /* Old CTB type */
    if (ll != 0xa3)             /* bypass length if it exists */
      fread(ibuf, 1, 1 << (ll & 3), inf);
    neof = 0;
    ll = 0x7fffffff;
  } else if (ll == 0xc8)
    ll = 0, neof = 1;
  else
    return -1;
  do {
    if (!ll && neof)
      ll = PGP_nxpkt(&neof, inf);
    if (firstflag) {            /* snag algorithm byte */
      firstflag = 0;
      ll--;
      got = fgetc(inf);
      if (got != 1 && got != 2)
        return -1;
      memset(&pgpz, 0, sizeof(pgpz));
      inflateInit2(&pgpz, got == 1 ? -15 : 15);
    }
    while (ll && !feof(inf)) {
      if (0 > (got = fread(ibuf, 1, ll > BSIZ ? BSIZ : ll, inf)))
        break;
      ll -= got;
      pgpz.next_in = ibuf;
      pgpz.avail_in = got;
      while (pgpz.avail_in || !(ll || neof) || feof(inf)) {
        pgpz.next_out = obuf;
        pgpz.avail_out = BSIZ;
        k = inflate(&pgpz, neof || !feof(inf) ? 0 : Z_FINISH);
        fwrite(obuf, 1, BSIZ - pgpz.avail_out, outf);
        if (k == Z_BUF_ERROR && pgpz.avail_out != BSIZ
            && (!(ll || neof) || feof(inf)))
          continue;             /* for undoc zlib */
        if (k != Z_OK)
          break;
      }
    }
  } while (neof && !feof(inf));
  inflateEnd(&pgpz);
  return (k == Z_STREAM_END);
}
