/* OpenPGP for Palm III */

#pragma pack(2)
#include <Common.h>
#include <System/SysAll.h>
#include <UI/UIAll.h>
#include <System/SysEvtMgr.h>

#include "opgptst.h"
#if 0
#define OpgptstAppID    'OPGP'
#define OpgptstDBType   'Data'
#endif

int getkey(void);
extern FormPtr form;

#include <System/FileStream.h>
#include <libopgp.h>

static const char hbnr[5][24] =
{"SHA1", "RIPEMD160", ",", "MD2", ","};

static int syma = 2, diga = 2;

#define PipeSwap { \
    if( file ) FileClose(file); \
    EvtResetAutoOffTimer(); \
    FileRewind(ofile); \
    FileRead(ofile, &ctb, 1, 1, NULL); \
    FileRewind(ofile); \
    FileControl(fileOpDestructiveReadMode, ofile, NULL, NULL); \
    file = ofile; }

static ULong len1;
static UInt dbrec;
static VoidHand hand1;
static unsigned char *ptr1;

#define PGP_close()

void procmsg()
{
  FileHand file = NULL, ofile;
  unsigned char ctb;
  int i, j;
  ULong ll;
  char litfname[256];

  WinDrawChars("Processing Message  ", 20, 0, 20);

  ofile = FileOpen(0, "TEMPX", 'DATA', 'OPGP', TEMPF, NULL);
  FileWrite(ofile, ptr1, 1, len1, NULL);

  PipeSwap;
  WinDrawChars("Dearmoring          ", 20, 0, 20);
  ofile = FileOpen(0, "TEMPA", 'DATA', 'OPGP', TEMPF, NULL);
  PGP_dearmor(file, ofile);
  for (;;) {

PGP_close();

    PipeSwap;

    if (ctb < 0xc0)
      ctb = ((ctb & 0x3c) >> 2);
    else
      ctb -= 0xc0;

    if (ctb == 1 || ctb == 3 || ctb == 10) {  /* incl 0xa8,3,PGP */
      WinDrawChars("PK Decrypt          ", 20, 0, 20);
      ofile = FileOpen(0, "TEMPB", 'DATA', 'OPGP', TEMPF, NULL);

      if (PGP_decry(file, ofile, ""))
        break;
      continue;

    } else if (ctb == 8) {
      WinDrawChars("Decompressing       ", 20, 0, 20);
      ofile = FileOpen(0, "TEMPC", 'DATA', 'OPGP', TEMPF, NULL);
      PGP_unzip(file, ofile);
      continue;

    } else if (ctb == 9) {      /* naked symmetrical */
      void *hctx;
      unsigned char *bp, xfix[] =
      {4, 1, 0, 1};
      WinDrawChars("Conventional Decrypt", 20, 0, 20);
      bp = xfix;

      PGP_gts2k(&bp, "", &hctx);
      PGP_cdec(file, ofile, &hctx, 1);

      continue;

    } else if (ctb == 2 || ctb == 4 || ctb == 11) {  /* lit or sig */
      WinDrawChars("Extract/Sigcheck    ", 20, 0, 20);
      ofile = FileOpen(0, "TEMPD", 'DATA', 'OPGP', TEMPF, NULL);
      i = PGP_delcs(file, ofile, &j, litfname);
      if (j) {
        if (i)
          WinDrawChars("Sigcheck Failed     ", 20, 0, 70);
        else
          WinDrawChars("Signature Verified  ", 20, 0, 70);
      }
      FileClose(file);

      ll = FileTell(ofile, NULL, NULL) - 1;

      file = ofile;
      FileRewind(file);

      WinDrawChars("Saving:             ", 20, 20, 20);
      WinDrawChars(litfname, StrLen(litfname), 20, 35);

      if (!(hand1 = MemHandleNew(ll + StrLen(litfname) + 1)))
        return;
      ptr1 = MemHandleLock(hand1);
      MemMove(ptr1, litfname, StrLen(litfname));
      StrCat(ptr1, "\n");

      FileControl(fileOpDestructiveReadMode, file, NULL, NULL);
      ll = FileRead(file, &ptr1[StrLen(litfname) + 1], 1, ll, NULL);

      FileClose(file);
      break;
    } else
      break;
  }
}

keyid_t keys[16];
void doenc()
{
  FileHand file = NULL, ofile;
  ULong ll, ll2;
  unsigned char ctb;
  char *cp = ptr1;
  char litfname[256];

  /* parse command line - get key and optional fname */
  ofile = FileOpen(0, "TEMP1", 'DATA', 'OPGP', TEMPF, NULL);
  cp = StrStr(cp, "\n");
  ll = (ULong) (++cp);
  ll2 = (ULong) ptr1;
  ll -= ll2;
  FileWrite(ofile, cp, 1, len1 - ll, NULL);

  PipeSwap;

  cp = ptr1;
  if (CtlGetValue(FrmGetObjectPtr(form, FrmGetObjectIndex(form, bsign))))
    WinDrawChars("Literaling/Signing  ", 20, 0, 20);
  else
    WinDrawChars("Literaling          ", 20, 0, 20);

{
ULong ll, lm;
unsigned char obuf[40];

MemHeapFreeBytes(0, &ll, &lm);
StrIToA(obuf,ll);
StrCat(obuf,"   ");
StrIToA(&obuf[StrLen(obuf)],lm);
StrCat(obuf,"   ");
WinDrawChars(obuf,StrLen(obuf),0,50);
SysTaskDelay(200);
}

  {
    FormPtr renf;
    FieldPtr textf;
    VoidHand thand;
    char *filen;

    StrCopy(litfname, "_CONSOLE");
    renf = FrmInitForm(ffilen);
    textf = FrmGetObjectPtr(renf, FrmGetObjectIndex(renf, tfilen));

    FrmDoDialog(renf);

    if ((thand = (VoidHand) FldGetTextHandle(textf))) {
      filen = MemHandleLock(thand);
      StrCopy(litfname, filen);
      MemHandleUnlock(thand);
    }
    FrmDeleteForm(renf);
  }

  ofile = FileOpen(0, "TEMP2", 'DATA', 'OPGP', TEMPF, NULL);

  if (CtlGetValue(FrmGetObjectPtr(form, FrmGetObjectIndex(form, bsign)))) {

    /* technically, I should use 'b' since it is not canonical text */
    if (PGP_elsgm(file, ofile, litfname, 1, 't', diga, 0, ""))
      return;
  } else {
    if (PGP_elsgm(file, ofile, litfname, 0, 't', 0, 0, NULL))
      return;
  }
PGP_close();

{
ULong ll, lm;
unsigned char obuf[40];

MemHeapFreeBytes(0, &ll, &lm);
StrIToA(obuf,ll);
StrCat(obuf,"   ");
StrIToA(&obuf[StrLen(obuf)],lm);
StrCat(obuf,"   ");
WinDrawChars(obuf,StrLen(obuf),0,50);
SysTaskDelay(200);
}

  if (CtlGetValue(FrmGetObjectPtr(form, FrmGetObjectIndex(form, bcomp)))) {

    PipeSwap;
    WinDrawChars("Compressing         ", 20, 0, 20);
    ofile = FileOpen(0, "TEMP3", 'DATA', 'OPGP', TEMPF, NULL);
    PGP_zip(file, ofile, 1);
  }
PGP_close();


{
ULong ll, lm;
unsigned char obuf[40];

MemHeapFreeBytes(0, &ll, &lm);
StrIToA(obuf,ll);
StrCat(obuf,"   ");
StrIToA(&obuf[StrLen(obuf)],lm);
StrCat(obuf,"   ");
WinDrawChars(obuf,StrLen(obuf),0,50);
SysTaskDelay(200);
}

  if (CtlGetValue(FrmGetObjectPtr(form, FrmGetObjectIndex(form, benc)))) {
    PipeSwap;
    WinDrawChars("Encrypting          ", 20, 0, 20);
    ofile = FileOpen(0, "ENCRY", 'DATA', 'OPGP', TEMPF, NULL);
    /* conventional or public */

    if (CtlGetValue(FrmGetObjectPtr(form, FrmGetObjectIndex(form, bnpk)))) {
      FormPtr renf;
      FieldPtr textf;
      VoidHand thand;
      char *passph;

      renf = FrmInitForm(fpassph);

      textf = FrmGetObjectPtr(renf, FrmGetObjectIndex(renf, tpassph));

      FrmDoDialog(renf);
      thand = (VoidHand) FldGetTextHandle(textf);
      passph = MemHandleLock(thand);

      ll = PGP_encry(file, ofile, 0, -1, NULL, syma, &passph);

      MemSet(passph, StrLen(passph), 0);
      MemHandleUnlock(thand);
      FrmDeleteForm(renf);

    } else
      ll = PGP_encry(file, ofile, 1, 0, keys, syma, NULL);

    if (ll)
      return;
  }
PGP_close();


{
ULong ll, lm;
unsigned char obuf[40];

MemHeapFreeBytes(0, &ll, &lm);
StrIToA(obuf,ll);
StrCat(obuf,"   ");
StrIToA(&obuf[StrLen(obuf)],lm);
StrCat(obuf,"   ");
WinDrawChars(obuf,StrLen(obuf),0,50);
SysTaskDelay(200);
}


  if (CtlGetValue(FrmGetObjectPtr(form, FrmGetObjectIndex(form, barm)))) {
    PipeSwap;
    WinDrawChars("Armoring            ", 20, 0, 20);
    ofile = FileOpen(0, "ARMOUT", 'DATA', 'OPGP', TEMPF, NULL);
    PGP_armor(file, ofile, NULL, NULL);
  }
PGP_close();
  FileClose(file);

  ll = FileTell(ofile, NULL, NULL) - 1;
  file = ofile;
  FileRewind(file);
  FileControl(fileOpDestructiveReadMode, file, NULL, NULL);

  if (!(hand1 = MemHandleNew(ll)))
    return;
  if (!(ptr1 = MemHandleLock(hand1)))
    return;

  FileRead(file, ptr1, 1, ll, NULL);
  FileClose(file);
}

#define HALG 2
void dosign()
{
  void *hctx, *signkey;
  char *cpt, *cptr = ptr1;
  keyid_t key = 0;
  int salg;
  ULong ll;
  char linebuf[512];
  FileHand file = NULL, ofile;

  WinDrawChars("Signing             ", 20, 0, 20);

  if (0 >= (salg = PGP_gtkey(&signkey, "", &key)))
    return;

  ofile = FileOpen(0, "TEMP1", 'DATA', 'OPGP', TEMPF, NULL);
  FileWrite(ofile, "-----BEGIN PGP SIGNED MESSAGE-----\nHash: SHA1\n\n",
            1, 47, NULL);
  hctx = PGP_hini(HALG);
  ll = len1;

  while (ll) {                  /* doubled - don't hash last TWO lines */
    cpt = linebuf;
    while (ll && *cptr != '\n')
      *cpt++ = *cptr++, ll--;
    if (ll)
      *cpt++ = *cptr++, ll--;
    *cpt = 0;
    PGP_ctln(linebuf);

    PGP_hblk(hctx, linebuf, StrLen(linebuf));
    cpt = linebuf;
    cpt[StrLen(cpt) - 1] = 0;
    cpt[StrLen(cpt) - 1] = '\n';
    FileWrite(ofile, cpt, 1, StrLen(cpt), NULL);
  }
  FileWrite(ofile, "\n", 1, 1, NULL);

  /* 2 hardcoded in next because SHA1 is hardcoded above */
  ll = PGP_sigmk(signkey, hctx, linebuf, key, 2, HALG, salg, NULL);
  file = FileOpen(0, "TEMP2", 'DATA', 'OPGP', TEMPF, NULL);
  FileWrite(file, linebuf, 1, ll, NULL);
  FileRewind(file);
  FileControl(fileOpDestructiveReadMode, file, NULL, NULL);
  PGP_armor(file, ofile, "SIGNATURE", NULL);
  FileClose(file);
  ll = FileTell(ofile, NULL, NULL) - 1;
  file = ofile;
  FileRewind(file);
  FileControl(fileOpDestructiveReadMode, file, NULL, NULL);

  if (!(hand1 = MemHandleNew(ll)))
    return;
  if (!(ptr1 = MemHandleLock(hand1)))
    return;
  FileRead(file, ptr1, 1, ll, NULL);
  FileClose(file);
}

void dover()
{
  int cnt, halg = 1;
  int i;
  void *hctx;
  char *cpt, *cptr = ptr1;
  FileHand file = NULL, ofile;
  ULong ll, ll2;
  unsigned char ctb;
  char linebuf[512];

  WinDrawChars("Checking Signature  ", 20, 0, 20);

  if (cpt = StrStr(cptr, "\nHash:")) {
    cpt += 7;
    for (cnt = 0; cnt < 5; cnt++)
      if (!StrNCompare(cpt, hbnr[cnt], 4))
        halg = cnt + 2;
  }
  if (cptr = StrStr(cptr, "\n\n"))
    cptr += 2;
  else
    return;

  hctx = PGP_hini(halg);

  while (*cptr) {               /* doubled - don't hash last TWO lines */
    if (!StrNCompare(cptr, "\n-----BEGIN PGP SIGNATURE", 25))
      break;
    cpt = linebuf;
    while (*cptr && *cptr != '\n')
      *cpt++ = *cptr++;
    if (!*cptr)
      break;
    *cpt++ = *cptr++;
    *cpt = 0;
    PGP_ctln(linebuf);
    PGP_hblk(hctx, linebuf, StrLen(linebuf));
  }
  if (!*cptr)
    return;

  cptr++;
  ofile = FileOpen(0, "TEMPX", 'DATA', 'OPGP', TEMPF, NULL);
  ll = (ULong) cptr;
  ll2 = (ULong) ptr1;
  FileWrite(ofile, cptr, 1, len1 - (ll - ll2), NULL);

  PipeSwap;

  ofile = FileOpen(0, "TEMPA", 'DATA', 'OPGP', TEMPF, NULL);
  PGP_dearmor(file, ofile);

  FileRewind(ofile);
  FileControl(fileOpDestructiveReadMode, ofile, NULL, NULL);
  FileRead(ofile, linebuf, 1, 512, NULL);
  FileClose(ofile);

  i = PGP_sigck(&linebuf[1 + (1 << (linebuf[0] & 3))], hctx);

  if (i && i != -1 && i != -5)
    i = -4;
  if (i == -1)
    WinDrawChars("BAD SIGNATURE       ", 20, 0, 40);
  else if (!i)
    WinDrawChars("Signature Verified  ", 20, 0, 40);
  else
    WinDrawChars("Sig Did Not Verify  ", 20, 0, 40);
}

msg2file(char *fname, ULong ftype)
{
  FileHand file, ofile;

/* add2f for pubring? */
  file = FileOpen(0, fname, ftype, 'OPGP', NORMF, NULL);
  ofile = FileOpen(0, "RingTemp", 'DATA', 'OPGP', TEMPF, NULL);
  FileWrite(ofile, ptr1, 1, len1, NULL);
  FileRewind(ofile);
  PGP_dearmor(ofile, file);
  FileClose(file);
  FileClose(ofile);
}

file2msg(char *fname, char *ctype)
{
  FileHand file, ofile;
  ULong ll;

/* add2f for pubring? */
  ll = 0;
  file = FileOpen(0, fname, 'DATA', 'OPGP', READF, NULL);
  {
    char obuf[20];
    FileTell(file, &ll, NULL);
    StrIToA(obuf, ll);
    WinDrawChars(obuf, StrLen(obuf), 30, 30);
  }

  ofile = FileOpen(0, "RingTemp", 'DATA', 'OPGP', TEMPF, NULL);
  PGP_armor(file, ofile, ctype, NULL);

  {
    char obuf[20];
    FileTell(file, &ll, NULL);
    StrIToA(obuf, ll);
    WinDrawChars(obuf, StrLen(obuf), 50, 32);
  }

  FileClose(file);

  ll = FileTell(ofile, NULL, NULL);
  FileRewind(ofile);
  MemHandleUnlock(hand1);
  hand1 = MemHandleNew(ll);
  ptr1 = MemHandleLock(hand1);
  FileRead(ofile, ptr1, 1, ll, NULL);
  FileClose(ofile);
}

void RunOpenPGP(void)
{
  FileHand file, ofile;
  int i;
  unsigned int j;
  char *cp;
  VoidHand hand2;
  Word lenw;

  hand2 = ClipboardGetItem(clipboardText, &lenw);
  hand1 = NULL;
  ptr1 = MemHandleLock(hand2);
  len1 = lenw;

  if (CtlGetValue(FrmGetObjectPtr(form, FrmGetObjectIndex(form, bdec)))) {
#if 0
    if (!StrNCompare("-----BEGIN PGP PUBLIC", ptr1, 21)) {
      WinDrawChars("Dearmoring Pubring  ", 20, 0, 20);  /* ADD2F */
      msg2file("pubring.pkr", 'OPKR');
    }
#endif
    if (!StrNCompare("-----BEGIN PGP PRIVATE", ptr1, 22)) {
      WinDrawChars("Dearmoring Secring  ", 20, 0, 20);
      msg2file("secring.skr", 'OSKR');
    }
    if (!StrNCompare("-----BEGIN PGP MESSAGE", ptr1, 22)) {
      procmsg();


      WinDrawChars("Function Complete   ", 20, 0, 20);
      MemHandleUnlock(hand2);
      ClipboardAddItem(clipboardText, ptr1, MemPtrSize(ptr1));
      WinDrawChars("Clipboard Complete  ", 20, 0, 20);


    }
    if (!StrNCompare("-----BEGIN PGP SIGNED", ptr1, 21))
      dover();
  } else {
    if (CtlGetValue(FrmGetObjectPtr(form, FrmGetObjectIndex(form, bclsg))))
      dosign();
    if (CtlGetValue(FrmGetObjectPtr(form, FrmGetObjectIndex(form, bencc)))) {

      if (!CtlGetValue(FrmGetObjectPtr(form, FrmGetObjectIndex(form, bnpk))) && !keys[0])
        getkey();
      if (keys[0])
        doenc();
      else {
        MemHandleUnlock(hand2);
        return;
      }
    }
    WinDrawChars("Function Complete   ", 20, 0, 20);
    MemHandleUnlock(hand2);
    ClipboardAddItem(clipboardText, ptr1, MemPtrSize(ptr1));
    WinDrawChars("Clipboard Complete  ", 20, 0, 20);

  }
  if (hand1)
    MemHandleUnlock(hand1);
  WinDrawChars("Processing Complete ", 20, 0, 20);
}
