/*
 * Copyright (C) 1997 Thomas Roessler <roessler@guug.de>
 * 
 *     This program is free software; you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation; either version 2 of the License, or
 *     (at your option) any later version.
 * 
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 * 
 *     You should have received a copy of the GNU General Public License
 *     along with this program; if not, write to the Free Software
 *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */ 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>

#include "mutt.h"
#include "state.h"
#include "pgp.h"


pid_t pgp_invoke_decode (FILE **pgpin, FILE **pgpout, FILE **pgperr,
			 int pgpinfd, int pgpoutfd, int pgperrfd,
			 const char *fname, int need_passphrase)
{
  char cmd[HUGE_STRING];
  
  switch(pgp_version())
  {
    case PGP2:
      snprintf(cmd, sizeof(cmd), "%scat %s%s | "
	       "%s +pubring=%s +secring=%s +verbose=0 +batchmode -f",
	       need_passphrase ? "PGPPASSFD=0; export PGPPASSFD; " : "",
	       need_passphrase ? "- " : "",
	       fname,
	       Pgp, PgpPubring, PgpSecring);
      break;

    case PGP3:
      snprintf(cmd, sizeof(cmd), "%scat %s%s | "
	       "%sv +pubring=%s +secring=%s +verbose=0 +batchmode -f "
	       "--OutputInformationFD=2",
	       need_passphrase ? "PGPPASSFD=0; export PGPPASSFD; " : "",
	       need_passphrase ? "- " : "",
	       fname,
	       Pgp, PgpPubring, PgpSecring);
      break;
    
    default:
      mutt_error("Unknown PGP version.");
      return -1;
  }
  
  return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr,
			       pgpinfd, pgpoutfd, pgperrfd);
}


pid_t pgp_invoke_verify(FILE **pgpin, FILE **pgpout, FILE **pgperr,
			int pgpinfd, int pgpoutfd, int pgperrfd,
			const char *signedstuff, const char *sigfile)
{
  char cmd[HUGE_STRING];
  
  switch(pgp_version())
  {
    case PGP2:
      snprintf(cmd, sizeof(cmd), 
	       "%s +pubring=%s +secring=%s +batchmode +verbose=0 %s %s",
	       Pgp, PgpPubring, PgpSecring, sigfile, signedstuff);
      break;
    
    case PGP3:
      snprintf(cmd, sizeof(cmd),
	       "%sv +pubring=%s +secring=%s --OutputInformationFD=1 +batchmode +verbose=0 %s %s",
	       Pgp, PgpPubring, PgpSecring, sigfile, signedstuff);
      break;

    default:
      mutt_error("Unknown PGP version.");
      return -1;
  }
  
  return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr,
			       pgpinfd, pgpoutfd, pgperrfd);
}



pid_t pgp_invoke_decrypt(FILE **pgpin, FILE **pgpout, FILE **pgperr,
			 int pgpinfd, int pgpoutfd, int pgperrfd,
			 const char *fname)
{
  char cmd[HUGE_STRING];
  
  switch(pgp_version())
  {
    case PGP2:
      snprintf(cmd, sizeof(cmd),
	       "PGPPASSFD=0; export PGPPASSFD; cat - %s | %s +pubring=%s +secring=%s "
	       "+verbose=0 +batchmode -f",
	       fname, Pgp, PgpPubring, PgpSecring);
      break;

    case PGP3:
      snprintf(cmd, sizeof(cmd),
	       "PGPPASSFD=0; export PGPPASSFD; cat - %s | %sv +pubring=%s +secring=%s "
	       "+verbose=0 +batchmode -f --OutputInformationFD=2",
	       fname, Pgp, PgpPubring, PgpSecring);
      break;

    default:
      mutt_error("Unknown PGP version.");
      return -1;

  }

  return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr,
			    pgpinfd, pgpoutfd, pgperrfd);
}


pid_t pgp_invoke_sign(FILE **pgpin, FILE **pgpout, FILE **pgperr,
		      int pgpinfd, int pgpoutfd, int pgperrfd, 
		      const char *fname)
{
  char cmd[HUGE_STRING];
  
  switch(pgp_version())
  {
    case PGP2:
      snprintf(cmd, sizeof(cmd),
	       "PGPPASSFD=0; export PGPPASSFD; cat - %s | %s "
	       "+pubring=%s +secring=%s +verbose=0 +batchmode -abfst %s %s",
	       fname, Pgp, PgpPubring, PgpSecring, 
	       PgpSignAs[0] ? "-u" : "",
	       PgpSignAs[0] ? PgpSignAs : "");
      break;

    case PGP3:
      snprintf(cmd, sizeof(cmd),
	       "PGPPASSFD=0; export PGPPASSFD; cat - %s | %ss "
	       "+pubring=%s +secring=%s +verbose=0 -abft %s %s",
	       fname, Pgp, PgpPubring, PgpSecring,
	       PgpSignAs[0] ? "-u" : "",
	       PgpSignAs[0] ? PgpSignAs : "");
      break;

    default:
      mutt_error("Unknown PGP version.");
      return -1;

  }
  
  return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr,
			       pgpinfd, pgpoutfd, pgperrfd);
}


pid_t pgp_invoke_encrypt(FILE **pgpin, FILE **pgpout, FILE **pgperr,
			 int pgpinfd, int pgpoutfd, int pgperrfd,
			 const char *fname, const char *uids, int sign)
{
  char cmd[HUGE_STRING];
  char tmpcmd[HUGE_STRING];
  char *cp;
  char *keylist;
  
  switch(pgp_version())
  {
    case PGP2:
      snprintf(cmd, sizeof(cmd),
	       "%scat %s%s | %s +pubring=%s +secring=%s +verbose=0 %s +batchmode -aeft%s %s%s %s",
	       sign ? "PGPPASSFD=0; export PGPPASSFD; " : "",
	       sign ? "- " : "",
	       fname,
	       Pgp, PgpPubring, PgpSecring, 
	       option(OPTPGPENCRYPTSELF) ? "+encrypttoself" : "",
	       sign ? "s" : "",
	       sign && PgpSignAs[0] ? "-u " : "",
	       sign && PgpSignAs[0] ? PgpSignAs : "",
	       uids);
      break;

    case PGP3:
      snprintf(cmd, sizeof(cmd),
	       "%scat %s%s | %se +pubring=%s +secring=%s +verbose=0 %s +batchmode -aft%s %s%s",
	       sign ? "PGPPASSFD=0; export PGPPASSFD; " : "",
	       sign ? "- " : "",
	       fname,
	       Pgp, PgpPubring, PgpSecring, 
	       option(OPTPGPENCRYPTSELF) ? "+encrypttoself" : "",
	       sign ? "s" : "",
	       sign && PgpSignAs[0] ? "-u " : "",
	       sign && PgpSignAs[0] ? PgpSignAs : "");

      keylist = safe_strdup(uids);
      for(cp = strtok(keylist, " "); cp ; cp = strtok(NULL, " "))
      {
	snprintf(tmpcmd, sizeof(tmpcmd), "%s -r %s", 
		 cmd, cp);
	strcpy(cmd, tmpcmd);
      }
      safe_free((void **) &keylist);
      break;

    default:
      mutt_error("Unknown PGP version.");
      return -1;

  }
  
  return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr, 
			       pgpinfd, pgpoutfd, pgperrfd);
}


void pgp_invoke_extract(const char *fname)
{
  char cmd[HUGE_STRING];
  
  switch(pgp_version())
  {
    case PGP2:
      snprintf(cmd, sizeof(cmd), "%s +pubring=%s +secring=%s -ka %s",
	       Pgp, PgpPubring, PgpSecring, fname);
      break;

    case PGP3:
      snprintf(cmd, sizeof(cmd), "%sk +pubring=%s +secring=%s --OutputInformationFD=1 %s",
	       Pgp, PgpPubring, PgpSecring, fname);
      break;

    default:
      mutt_error("Unknown PGP version.");
      return;

  }
  mutt_system(cmd);
}


pid_t pgp_invoke_verify_key(FILE **pgpin, FILE **pgpout, FILE **pgperr,
			    int pgpinfd, int pgpoutfd, int pgperrfd, const char *id)
{
  char cmd[HUGE_STRING];
  
  switch(pgp_version())
  {
    case PGP2:
      snprintf(cmd, sizeof(cmd), "%s +pubring=%s +secring=%s +batchmode -kcc 0x%8s",
	       Pgp, PgpPubring, PgpSecring, id);
      break;

    case PGP3:
      snprintf(cmd, sizeof(cmd), "%sk +pubring=%s +secring=%s +batchmode -c --OutputInformationFD=1 0x%8s",
	       Pgp, PgpPubring, PgpSecring, id);
      break;

    default:
          mutt_error("Unknown PGP version.");
      return -1;
    
  }
  
  return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr,
			       pgpinfd, pgpoutfd, pgperrfd);
}


pid_t pgp_invoke_extract_key(FILE **pgpin, FILE **pgpout, FILE **pgperr,
			     int pgpinfd, int pgpoutfd, int pgperrfd, const char *id)
{
  char cmd[HUGE_STRING];
  
  switch(pgp_version())
  {
    case PGP2:
      snprintf(cmd, sizeof(cmd), "%s -kxaf +pubring=%s +secring=%s 0x%8s",
	       Pgp, PgpPubring, PgpSecring, id);
      break;

    case PGP3:
      snprintf(cmd, sizeof(cmd), "sk -xa +pubring=%s +secring=%s --OutputInformationFD=1 0x%8s",
	       Pgp, PgpPubring, PgpSecring, id);
      break;

    default:
      mutt_error("Unknown PGP version.");
      return -1;

  }
  
  return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr,
			       pgpinfd, pgpoutfd, pgperrfd);
}
