static char rcsid[] = "@(#)$Id: pgp_decode.c,v 1.51 2007/08/18 06:48:24 hurtta Exp $";

/******************************************************************************
 *  The Elm (ME+) Mail System  -  $Revision: 1.51 $   $State: Exp $
 *
 *  Modified by: Kari Hurtta <hurtta+elm@posti.FMI.FI> 
 *                           (was hurtta+elm@ozone.FMI.FI)
 *
 *  Initially written by: Michael Elkins <elkins@aero.org>, 1995
 *****************************************************************************/

#include "def_melib.h"
#include "s_me.h"
#include "s_elm.h"

DEBUG_VAR(Debug,__FILE__,"pgp");

#ifdef USE_PGP
#include <sys/time.h>

#include <errno.h>
#ifndef ANSI_C
extern int errno;
#endif       

extern int pgp_keeppassfor; /* 5 minutes */
char pgp_passphrase[PGP_NUM][STRING];
int pgp_expires;

static CONST char * pgp_names[PGP_NUM] = {
    "*none*",
    "PGP 2",
    "PGP 5",
    "GnuPG"
};

/* if v >= pgp2 returns gives available pgp version */

enum pgp_version have_pgp (v)
     enum pgp_version v;
{
    enum pgp_version return_value = v;
    
    switch(v) {
    case pgp_none:
	return_value = pgp_none;
	;;
    case pgp2: {
	char * pgp2_path_val = give_dt_estr_as_str(&pgp2_path_e, "pgp2");

	if (! pgp2_path_val ||
	    strcmp(pgp2_path_val,"none") == 0 || 
	    pgp2_path_val[0] == '\0') {
	    return_value = pgp_none;
	} else if (pgp2_path_val[0] == '/') {
	    if (-1 == access(pgp2_path_val,EXECUTE_ACCESS)) {
		int err = errno;
		lib_error(CATGETS(elm_msg_cat, MeSet, MePgpCantExecute,
				  "Can't execute pgp: %.50s: %.30s"),
			  pgp2_path_val, error_description(err));
	    
		DPRINT(Debug,5,(&Debug,
				"have_pgp: no access %s: %s\n",pgp2_path_val,
				error_description(err)));
		return_value = pgp_none;
	    }
	} else {
	    lib_error(CATGETS(elm_msg_cat, MeSet, MePgpPath,
			      "PGP path must start with '/': %.60s"),
		      pgp2_path_val);
	    DPRINT(Debug,5,(&Debug,
			    "have_pgp: bad path: %s\n",pgp2_path_val));
	    return_value = pgp_none;
	}
	if (return_value != pgp_none)
	    break;

	return_value = pgp5;
	/* FALLTROUGH */    
    }

    case pgp5: try_pgp5: {
	/* give_dt_estr_as_str adds / to end */
	char * pgp5_dir_val  = give_dt_estr_as_str(&pgp5_dir_e, "pgp5-dir");

	if (! pgp5_dir_val ||
	    strcmp(pgp5_dir_val,"none") == 0 || 
	    pgp5_dir_val[0] == '\0') {
	    return_value = pgp_none;
	} else if (pgp5_dir_val[0] == '/') {
	    char * path = elm_message(FRM("%spgpv"),pgp5_dir_val);
	    if (-1 == access(path,EXECUTE_ACCESS)) {
		int err = errno;
		lib_error(CATGETS(elm_msg_cat, MeSet, MePgpCantExecute,
				  "Can't execute pgp: %.50s: %.30s"),
			  path, error_description(err));
		
		DPRINT(Debug,5,(&Debug,			           
				"have_pgp: no access %s: %s\n",path,
				error_description(err)));
		return_value = pgp_none;
	    }
	    free(path);
	} else {
	    lib_error(CATGETS(elm_msg_cat, MeSet, MePgpPath,
			      "PGP path must start with '/': %.60s"),
		      pgp5_dir_val);
	    DPRINT(Debug,5,(&Debug,			      
			    "have_pgp: bad path: %s\n",pgp5_dir_val));
	    return_value = pgp_none;
	}
    }
	break;
    case gpg: {
	char * gpg_path_val = give_dt_estr_as_str(&gpg_path_e, "gpg");

	if (! gpg_path_val ||
	    strcmp(gpg_path_val,"none") == 0 || 
	    gpg_path_val[0] == '\0') {
	    return_value = pgp_none;
	} else if (gpg_path_val[0] == '/') {
	    if (-1 == access(gpg_path_val,EXECUTE_ACCESS)) {
		int err = errno;
		lib_error(CATGETS(elm_msg_cat, MeSet, MePgpCantExecute,
				  "Can't execute pgp: %.50s: %.30s"),
			  gpg_path_val, error_description(err));
	    
		DPRINT(Debug,5,(&Debug,
				"have_pgp: no access %s: %s\n",gpg_path_val,
				error_description(err)));
		return_value = pgp_none;
	    }
	} else {
	    lib_error(CATGETS(elm_msg_cat, MeSet, MePgpPath,
			      "PGP path must start with '/': %.60s"),
		      gpg_path_val);
	    DPRINT(Debug,5,(&Debug,
			    "have_pgp: bad path: %s\n",gpg_path_val));
	    return_value = pgp_none;
	}
	if (return_value != pgp_none)
	    break;

	return_value = pgp5;
	goto try_pgp5;
    }
    }
    DPRINT(Debug,5,(&Debug,
		    "have_pgp(%d)=%d\n",v,return_value));
    return return_value;
}

int pgp_void_passphrase ()
{
    int i;
    enum pgp_version v;
    int X = 0;
 
    for (v = pgp_none; v < PGP_NUM; v++) {
	if (pgp_passphrase[v][0])
	    X++;
	for (i = 0 ; i < sizeof pgp_passphrase[v] ; i++)
	    pgp_passphrase[v][i] = '\0';
	pgp_expires = 0;
    }
    return X;
}

static int QueryExpirePassphrase P_((void));

static int QueryExpirePassphrase()
{
    struct timeval now;

    /* negative implies never expire */
    if (pgp_keeppassfor < 0)
	return(0);
    gettimeofday(&now, 0);
    if (now.tv_sec < pgp_expires) {
	pgp_expires = now.tv_sec + pgp_keeppassfor;
	return(0);
    }
    pgp_void_passphrase ();
    return(1);
}

static int GetPassphrase P_((enum pgp_version v));

static int GetPassphrase (v)
     enum pgp_version v;
{
    char * buffer;
    struct timeval now;
    int r;

    DPRINT(Debug,2,(&Debug,
		    "GetPassphrase(%d) -- pgp_names[%d]=%s\n",
		    v,v,pgp_names[v]));

    buffer = lib_prompt(1,
			CATGETS(elm_msg_cat, MeSet, MePgpEnterPassphrase,
				"Please enter your %s passphrase: "),
			pgp_names[v]);
    if (!buffer) {
	DPRINT(Debug,2,(&Debug,
			"GetPassphrase=0  -- lib_prompt failed\n"));
	return 0;
    }
    
    strfcpy(pgp_passphrase[v],buffer,sizeof pgp_passphrase[v]);
    
    gettimeofday(&now, 0);
    if (pgp_keeppassfor > 0)
	pgp_expires = now.tv_sec + pgp_keeppassfor;

    free(buffer);
    r = pgp_passphrase[v][0] != '\0';
    DPRINT(Debug,2,(&Debug,
		    "GetPassphrase=%d\n",r));

    return(r);
}

int pgp_goodPassphrase(v)
     enum pgp_version v;
{
    if (pgp_passphrase[v][0] == '\0' || QueryExpirePassphrase())
	return(GetPassphrase(v));
    else
	return(1);
}

static void close_them P_((struct run_state *rs));
static void close_them(rs)
     struct run_state *rs;
{
    int *array = rs->ext_init_data;

    close(array[0]);
    close(array[1]);
    if (array[2] != -1)
	close(array[2]);
}

/* opens up a PGP process as a child and returns its stdin and stdout */
int pgp_decrypt_init (fpin, fpout, opts, v, rs)
     FILE **fpin, **fpout;
     int opts;              /* PGP_MESSAGE, PGP_SIGNED_MESSAGE, or
			       PGP_PUBLIC_KEY */
     enum pgp_version v;    /* 'minimum version' */
     struct run_state *rs;
{
    int pgp_child_in[2];
    int pgp_child_out[2];
    int array[3];       
    CONST char * argv[10];
    char * env[2];
    int passpipe[2];
    int usepass=FALSE;
    int code;

    DPRINT(Debug,2,(&Debug,		      
		    "pgp_descrypt_init() called with opts=%d\n", opts));
    

    rs->save_errno = 0;
    
    if (pipe(pgp_child_in) == -1) {
	rs->save_errno = errno;    
	return(0);
    }
    if (pipe(pgp_child_out) == -1) {
	rs->save_errno = errno;    
	close(pgp_child_in[0]);
	close(pgp_child_in[1]);
	return(0);    
    }
    if ((opts & PGP_MESSAGE) && pgp_keeppass) {
	if (pipe(passpipe) == -1) {
	    rs->save_errno = errno;
    
	    close(pgp_child_in[0]);
	    close(pgp_child_out[0]);
	    close(pgp_child_in[1]);
	    close(pgp_child_out[1]);
	    return(0);
	}
	usepass = TRUE;
    }
    DPRINT(Debug,3,(&Debug,
		    "usepass = %d.\n", usepass));
  
    sr_call_Raw(OFF);
    sr_call_ClearScreen();
    
    /* Tell the user why they are waiting */
    if (opts & PGP_MESSAGE) {
	sr_call_Write_to_screen(CATGETS(elm_msg_cat, MeSet, MePgpDecryptMes,
				"Running pgp: Decrypting message...\n"));
    } else if (opts & PGP_SIGNED_MESSAGE) {
	sr_call_Write_to_screen(CATGETS(elm_msg_cat, MeSet, MePgpCheckSig,
				"Running pgp: Checking signature...\n"));
    } else if (opts & PGP_PUBLIC_KEY) {
	sr_call_Write_to_screen(CATGETS(elm_msg_cat, MeSet, MePgpExtractKeys,
				"Running pgp: Extracting keys...\n"));
    } else {
	sr_call_Write_to_screen(CATGETS(elm_msg_cat, MeSet, MePgpRun,
				"Running pgp ...\n"));
    }
    
    array[0] = pgp_child_in[1];
    array[1] = pgp_child_out[0];
    array[2] = -1;

    rs->ext_init_data = array;
    rs->ext_init      = close_them;
    
    env[0] = NULL;
    rs->ext_env = env; 

    switch(v) {
    case pgp2:
    case pgp5:
	if (usepass) {
	    static char buffer[20];
	    elm_sfprintf(buffer, sizeof buffer,FRM("PGPPASSFD=%d"),
			 passpipe[0]);
	    env[0] = buffer;
	    array[2] = passpipe[1];
	}
	env[1] = NULL;
    }

    switch(v) {
	static char path[1000];
	int n;
    case pgp2:	
	n = 0;
	{
	    char * pgp2_path_val = give_dt_estr_as_str(&pgp2_path_e, "pgp2");
		
	    if (! pgp2_path_val)
		return 0;
	    argv[n++] = pgp2_path_val;
	}
	argv[n++] = "-f";
	argv[n++] = "+verbose=0";
	argv[n++] = "+KEEPBINARY=OFF";
	if (usepass || opts == PGP_SIGNED_MESSAGE || opts == PGP_PUBLIC_KEY)
	    argv[n++] = "+batchmode";
	if (opts == PGP_PUBLIC_KEY)
	    argv[n++] = "-ka";
	argv[n] = NULL;
	break;
    case pgp5:
	n = 0; 
	{
	    /* give_dt_estr_as_str adds / to end */
	    char * pgp5_dir_val  = give_dt_estr_as_str(&pgp5_dir_e, 
						       "pgp5-dir");
	    if (! pgp5_dir_val)
		return 0;
	    elm_sfprintf(path, sizeof path,FRM("%spgpv"),pgp5_dir_val);

	}
	argv[n++] = path;
	if (opts != PGP_PUBLIC_KEY)
	    argv[n++] = "-f";
	argv[n++] = "+verbose=0";
	if (usepass || opts == PGP_SIGNED_MESSAGE || opts == PGP_PUBLIC_KEY)
	    argv[n++] = "+batchmode";
	argv[n] = NULL;
	break;
    case gpg:	
	n = 0;
	{
	    char * gpg_path_val = give_dt_estr_as_str(&gpg_path_e, "gpg");
	    if (! gpg_path_val)
		return 0;
	    argv[n++] = gpg_path_val;
	}
	if (usepass) {
	    static char buffer[10];
	    argv[n++] = "--passphrase-fd";
	    elm_sfprintf(buffer, sizeof buffer,FRM("%d"),
			 passpipe[0]);
	    argv[n++] = buffer;
	    array[2] = passpipe[1];
	}	
	if (usepass || opts == PGP_SIGNED_MESSAGE || opts == PGP_PUBLIC_KEY)
	    argv[n++] = "--batch";
	if (opts == PGP_PUBLIC_KEY)
	    argv[n++] = "--import";
	else 
	    argv[n++] = "--decrypt";
	argv[n] = NULL;
	break;
    }

    code = start_run(rs, SY_RUN_STATE_INIT|SY_RUN_STATE_ENV , argv ,
		     pgp_child_in[0],pgp_child_out[1]);
	  
    close (pgp_child_in[0]);
    close (pgp_child_out[1]);
  
    if (!code)
	return 0;

    /* now send the passphrase if needed */
    if (usepass) {
	DPRINT(Debug,3,(&Debug,			   
			"pgp_decrypt_init: sending pgp passphrase.\n"));
	close (passpipe[0]);
	write (passpipe[1], pgp_passphrase[v], 
	       strlen(pgp_passphrase[v]));
	write (passpipe[1], "\n", 1);
	close (passpipe[1]);
    }
  
    if ((*fpin = fdopen(pgp_child_out[0], "r")) == 0) {
	int tmp;
	int err = errno;

	DPRINT(Debug,3,(&Debug,
			"pgp_decrypt_init: fdopen(%d) failed, errno=%d\n",
			pgp_child_out[0],err));

	kill(rs->pid,SIGTERM);
	wait_end(rs,&tmp);	    
	rs->save_errno = err;
	sr_call_Raw(ON);

	return(0);
    }
    if ((*fpout = fdopen(pgp_child_in[1], "w")) == 0) {
	int err = errno;
	int tmp;

	DPRINT(Debug,3,(&Debug,
			"pgp_decrypt_init: fdopen(%d) failed, errno=%d\n",
			pgp_child_out[0],err));

	kill(rs->pid,SIGTERM);
	wait_end(rs,&tmp);	    
	rs->save_errno = err;
	sr_call_Raw(ON);

	return(0);
    }
  
    return(code);
}

static int pgp_mime_opts P_((struct mime_param *s));

static int pgp_mime_opts (s)
     struct mime_param *s;
{        
    if (s) {
	CONST char *pv;
	
	pv = get_mime_param_compat(s,"format");
	if (pv) {
	    if (istrcmp (pv, "keys-only") ==  0)
		return PGP_PUBLIC_KEY;
	}

	pv = get_mime_param_compat(s,"x-action");
	if (pv) {
	    if (istrcmp (pv, "encryptsign") == 0)
		return (PGP_MESSAGE | PGP_SIGNED_MESSAGE);
	    else if (istrcmp (pv, "encrypt") == 0)
		return PGP_MESSAGE;
	    else if (istrcmp (pv, "sign") == 0)
		return PGP_SIGNED_MESSAGE;
	    else if (istrcmp (pv, "signclear") == 0)
		return PGP_SIGNED_MESSAGE;
	}
    }
    return PGP_MESSAGE;
}

enum pgp_version decode_pgp_version(c)
     char * c;
{
    int se =  give_dt_enumerate_as_int(&send_pgp_version);

    if (0 == strncmp(c,"2.",2)) {
	DPRINT(Debug,4,(&Debug,
			"decode_pgp_version: Version -- PGP 2\n"));
	return pgp2;
    } else if (0 == strncmp(c,"GnuPG",5)) {
	DPRINT(Debug,4,(&Debug,			   
			"decode_pgp_version: Version -- GnuPG\n"));
	return gpg;
    } else {
	/* give_dt_estr_as_str adds / to end */
	char * pgp5_dir_val  = give_dt_estr_as_str(&pgp5_dir_e, "pgp5-dir");

	DPRINT(Debug,4,(&Debug,
			"decode_pgp_version: Version -- PGP 5?\n"));
	if (pgp5_dir_val &&
	    '/' == pgp5_dir_val[0])
	    return pgp5;
	else
	    return (enum pgp_version) se;
    }
}


/* Returns -1 on failure otherwise same mask than mime_classify_media() */
#if ANSI_C
mime_run_selector pgp_selector;
#endif
int pgp_selector(p,hdr)     
     mime_t *p;
     struct header_rec * hdr;
{
    int flags = 0;


    DPRINT(Debug,11,(&Debug, 
		     "pgp_selector(%p) -- type: %p=%s/%s\n",
		     p,
		     p->TYPE,
		     get_major_type_name(p->TYPE), 
		     get_subtype_name(p->TYPE)));

    DPRINT(Debug,11,(&Debug, 
		     "pgp_selector(%p) = %d\n",
		     p,
		     flags));


    return flags;
}

void pgp_decode (m, s_in, s_out, defcharset, mss, badtype)
     mime_t *m;
     in_state_t  *s_in;
     out_state_t *s_out;
     charset_t defcharset;
     struct header_rec * mss;
     type_mismatch_prompt *badtype;
{
    /* This procedure implements the de-facto standard for using PGP with MIME.
     * Content-Type: application/pgp
     * Required-Parameters: none
     * Optional parameters: format, x-action
     *     format = mime | text | keys-only
     *         mime : indicates that the signed/encrypted body contains a MIME
     *                compliant body and should be parsed recursively.
     *         text : [DEFAULT if there is no format option].  This option
     *                means that the encrypted/signed data should be presented
     *                to the user after processing, no additional processing
     *                needed.
     *         keys-only:
     *                The data in the body represents public key data only
     *     x-action = encryptsign | encrypt | sign
     *         This keyword is meant to be helpful to the application, but is
     *         not required, and may not even be necessary to look at.
     *
     *         encryptsign : the application/pgp data is both signed and
     *                       encrypted.
     *         encrypt     : the data is encrypted only
     *         sign        : the data is signed only
     */
    
    char buffer[LONG_STRING];
    FILE *pgpout, *pgpin, *tmpfp=NULL, *decode_fp = NULL;
    int
	code = 0,
	inbody = FALSE,
	opts,
	len,
	raw,
	stat = -1,
	bytes = 0,
	nested = FALSE; /* PGP output should be parsed as a MIME body */

    int skip_flag = 0;
    mime_t *tmpmt;
    enum pgp_version v = pgp2;
    int armor_header = 0;

    struct run_state RS;
    
    int was_binary = 0;
    in_state_t newstate2;
    enum pgp_version version;
    char *tmp;
    CONST char *pv;

    int was_text = 0;

    tmp = give_dt_estr_as_str(&temp_dir_e,"tmpdir");
    if (!tmp)
	return;


    in_state_clear(&newstate2,STATE_in_file);

    raw = sr_call_RawState ();
    
    if (
	(pv = get_mime_param_compat(m->TYPE_opts,"format")) &&
	(istrcmp (pv, "mime") == 0)) {
	char * tempfile = elm_message(FRM("%selmPT%d"), 
				      tmp, getpid ());
	
	nested = TRUE;
	DPRINT(Debug,3,(&Debug,			   
			"pgp_decode: format=mime\n"));
	
	
	if (NULL == (tmpfp = safeopen_rdwr(tempfile))) {
	    lib_error(CATGETS(elm_msg_cat, MeSet, MePgpCantCreate,
			      "Failed to create file for decoding."));
	    state_puts("[ ",s_out);
	    state_printf(s_out,
			 CATGETS(elm_msg_cat, MeSet, MePgpCantCreate,
				 "Failed to create file for decoding."));      
	    state_puts(" ]\n",s_out);
	    free(tempfile);
	    return;
	}
	
	unlink (tempfile); /* Filename is no longer needed ... */
	free(tempfile);
    }
    else
	tmpfp = NULL;

    opts = pgp_mime_opts(m->TYPE_opts);
        
    buffer[0] = '\0';
    if (opts & PGP_PUBLIC_KEY) {
	state_printf (s_out,
		      CATGETS(elm_msg_cat, MeSet, MePgpPublicKeys,
			      "(** This message contains PGP public key(s) **)\n"));
	state_putc('\n',s_out);
    }

    /* Decode Content-transfer-encoding */
    
    if (NULL != (decode_fp = 
		 arrange_decoded(m,s_in,s_out,&newstate2,NULL))) {  
	/* If arrange_decoded was treated this as text, don't consider
	 * about binary PGP files -- that happens when type is text/x-pgp
	 */


	if (check_type_pattern) {
	    if (!check_type_magic(m,&newstate2, s_out, badtype)) {
		DPRINT(Debug,11,(&Debug, 
				 "pgp_decode: mime_type_rejected\n"));
		goto FAILTYPE;
	    }
	}

	/* 7bit and 8bit are only allowed for line orienteed types */
	if (m->encoding == ENCODING_NONE || 
	    m->encoding == ENCODING_7BIT || 
	    m->encoding == ENCODING_8BIT) {
	    DPRINT(Debug,11,(&Debug,
			     "pgp_decode: textual encoding (%s)\n",
			     ENCODING(m->encoding)));
	    was_text = 1;
	} else
	    was_text = give_text_type_code(m->TYPE);

	
	DPRINT(Debug,4,(&Debug,
			"pgp_decode: was_text = %d\n", was_text));
	
	/* Print text before PGP armor 
	 *
	 */

	len = state_getl (buffer, sizeof (buffer), &newstate2);    
	if ( len < 1) {
	    state_printf(s_out,
			 CATGETS(elm_msg_cat, MeSet, MePgpNoText1,
				 "[ No text in PGP section. ]\n"));
	} else {
	    int c = (unsigned char) buffer[0],i;
	    
	    if (!pgp_noarmor && opts != PGP_PUBLIC_KEY) {
		was_binary = 1; /* default assumption */
		goto pgp_found;
	    }
	    
	    if (!was_text) {
		/* Check if that is binary PGP file */
		if (c & 0x80) {
		    /* In PGP block have type byte which have higgest bit set 
		     * always. so if in first byte have higgest bit set assume
		     * PGP binary file.
		     */
		    DPRINT(Debug,4,(&Debug, 
				    "pgp_decode: first byte = %d -- assume binary PGP file\n",
				c));
		    was_binary = 1; 
		    goto pgp_found;
		}
		/* Another check */
		for (i = 0; i < len; i++) {
		    if (buffer[i] == 0) {
			DPRINT(Debug,4,(&Debug,
					"pgp_decode: byte idx=%d is zero -- binary file?\n",
					i));
			state_printf(s_out,
				     CATGETS(elm_msg_cat, MeSet, MePgpBinary,
					     "[ Binary file, but does not look like PGP ]\n"));
			was_binary = 1; 
			goto pgp_found;
		    }
		}
	    }
	    if (strncmp(buffer, "-----BEGIN PGP", 14) == 0) 
		goto pgp_found;
	    
	    state_printf(s_out,
			 CATGETS(elm_msg_cat, MeSet, MePgpBefore,
				 "[ There is text before PGP section. ]\n"));

	    if (set_filter(m,s_out,NULL,
			   mss ? mss->override_charset : NULL)
		) { /* Character set filtering */
		do {
		    state_add_prefix(s_out);

		    /* Take care of CRLF => LF conversion in here because
		     * arrange_decoded() is treating application/pgp as
		     * binary type (it need to treate it as binary because
		     * it may be binary)
		     */
		    if (!was_text &&
			len > 1 &&
			buffer[len - 1] == '\n' &&
			buffer[len - 2] == '\r') {
			buffer[len - 2] = '\n';
			buffer[len - 1] = '\0';
			len--;
		    }

		    state_put(buffer,len,s_out);
		    
		} while ((len = state_getl (buffer, sizeof (buffer), 
					    &newstate2)) > 0
			 && strncmp(buffer, "-----BEGIN PGP", 14) != 0);
		
	    } else {
		DPRINT(Debug,4,(&Debug, 
				"pgp_decode: Unsupported character set?\n"));
	    }
	    
	pgp_found:
	    s_out -> filter = NULL;
	}

    } else { 
	char * msg = NULL;
	if (opts & PGP_MESSAGE)
	    msg = elm_message(CATGETS(elm_msg_cat, MeSet, 
				      MePgpEncodedCantEncoding,
				      "-- Start of PGP encoded section -- can't decode content-transfer-encoding\n"));
	else if (opts & PGP_SIGNED_MESSAGE)
	    msg = elm_message(CATGETS(elm_msg_cat, MeSet, 
				      MePgpSignedCantEncoding,
				      "-- Start of PGP signed section -- can't decode content-transfer-encoding\n"));
	else
	    msg = elm_message(CATGETS(elm_msg_cat, MeSet, MePgpCantEncoding,
				      "-- Start of PGP section -- can't decode content-transfer-encoding\n"));
	state_puts(msg,s_out);    
	free(msg);
	return;
    }

  if ( len < 1) {
      char * msg = NULL;
      if (opts & PGP_MESSAGE)
	  msg = elm_message(CATGETS(elm_msg_cat, MeSet, MePgpNoTextEncoded,
				    "[ No text in PGP encoded section ]\n"));
      else if (opts & PGP_SIGNED_MESSAGE)
	  msg = elm_message(CATGETS(elm_msg_cat, MeSet, MePgpNoTextSigned,
				    "[ No text in PGP signed section ]\n"));
    else
	msg = elm_message(CATGETS(elm_msg_cat, MeSet, MePgpNoText,
				  "[ No text in PGP section ]\n"));
      state_puts(msg,s_out);    
      free(msg);
      return;
  }
  
  if (!was_binary) {
      int l = in_state_ftell(&newstate2);
      int len1;
      char buf[STRING];

      /* 
       * On PGP 2 messages these is empty line immediately after
       * -----BEGIN PGP SIGNED MESSAGE----
       * 
       * If there is something other such as 
       * Hash: SHA1
       * PGP 2 does not understand message.
       */

      while ((len1 = state_getl (buf, sizeof (buf), &newstate2)) > 0) {
	  if ((len1 == 1 && buf[0] == '\n') ||
	      (len1 == 2 && buf[0] == '\r' && buf[1] == '\n'))
	      break;
	    if (opts == PGP_SIGNED_MESSAGE) {
		DPRINT(Debug,4,(&Debug, 
				"pgp_decode: peek: Header on armor -- requires PGP 5 or GnuPG\n" ));
		v = gpg;
		armor_header++;
		break;
	    }
	    if (0 == strncmp("Version: ",buf,9)) {
		char *c = buf+9;
		
		v = decode_pgp_version(c);
		if (armor_header && pgp2 == v) 
		    v = gpg;
	    }
      }

      /* Look also for -----BEGIN PGP SIGNATURE----- ... */
      if (opts == PGP_SIGNED_MESSAGE && len1 > 0) {
	  DPRINT(Debug,4,(&Debug,			     
			  "pgp_decode: Looking for -----BEGIN PGP SIGNATURE\n"));
	  
	  while ((len1 = state_getl (buf, sizeof (buf), &newstate2)) > 0) {
	      if (len1 > 24 &&
		  0 == strncmp(buf,
			       "-----BEGIN PGP SIGNATURE",24))
		  break;
	  }
	  
	  while ((len1 = state_getl (buf, sizeof (buf), 
				     &newstate2)) > 0) {
	      if ((len1 == 1 && buf[0] == '\n') ||
		  (len1 == 2 && buf[0] == '\r' && buf[1] == '\n'))
		  break;
	      
	      if (0 == strncmp("Version: ",buf,9)) {
		  char *c = buf+9;
		  
		  v = decode_pgp_version(c);
		  if (armor_header && pgp2 == v) 
		      v = gpg;
	      }
	  }
      }

      in_state_fseek(&newstate2,l);
  }

  version = have_pgp(v);
  if (!version) {
      if (was_binary) {
	  state_printf(s_out,
		       CATGETS(elm_msg_cat, MeSet, MePgpNotAvailSkipping,
			       "[ PGP not available, skipping... ]\n"));
	  return;
      } else 
	  state_printf (s_out,
		      CATGETS(elm_msg_cat, MeSet, MePgpNotAvailRawdata,
			      "[ PGP not available, raw data follows ]\n"));
      goto fail;
  }

  if ((opts & PGP_MESSAGE) && pgp_keeppass) {
      if (!pgp_goodPassphrase(version)) {
	  lib_error(CATGETS(elm_msg_cat, MeSet, MePgpBadPassphrase,
			    "Decrypting message... Bad PGP passphrase."));
	  state_putc('[',s_out);
	  state_printf(s_out,
		     CATGETS(elm_msg_cat, MeSet, MePgpBadPassphrase,
			     "Decrypting message... Bad PGP passphrase."));
	  state_puts("]\n",s_out);
	  return;
      }
  }

  if (!pgp_decrypt_init (&pgpout, &pgpin, opts, version, &RS)) {
      if (was_binary) 
	  state_printf(s_out,
		       CATGETS(elm_msg_cat, MeSet, MePgpInternalSkipping,
			      "[ Internal error while calling pgp, skipping... ]\n"));
      else {
	  state_printf(s_out,
		       CATGETS(elm_msg_cat, MeSet, MePgpInternalRawdata,
			      "[ Internal error while calling pgp, raw data follows ]\n"));
	  
      fail:

	  do {
	      state_add_prefix(s_out);
	
	      if (len > 1 &&
		  buffer[len - 1] == '\n' &&
		  buffer[len - 2] == '\r') {
		  buffer[len - 2] = '\n';
		  buffer[len - 1] = '\0';
		  len--;
	      }
	      
	      state_put(buffer,len,s_out);
	      bytes += len;
	  }  while ((len = state_getl (buffer, sizeof (buffer), 
				       &newstate2)) > 0);
	  
	  state_printf(s_out,
		       CATGETS(elm_msg_cat, MeSet, MePgpRawEnd,
			       "[ End of raw data. ]\n"));
      }
      return;
  }
 

  do {
      fwrite(buffer,1,len,pgpin);
      bytes += len;
  }  while ((len = state_getl (buffer, sizeof (buffer), 
			       &newstate2)) > 0);

  fclose (pgpin);
  
  code = run_already_done(&RS,&stat);
	     
  if (code != 0) {
      char * msg = NULL;
      if (opts & PGP_MESSAGE)
	  msg = elm_message(CATGETS(elm_msg_cat, MeSet, MePgpStartEncoded1,
				    "-- Start of PGP encoded section%s\n"),
			    code < 0 || stat ? catgets(elm_msg_cat, MeSet, 
						       MePgpFail,
						       ", PGP failed!") : ".");
      else if (opts & PGP_SIGNED_MESSAGE)
	  msg = elm_message(CATGETS(elm_msg_cat, MeSet, MePgpStartSigned1,
				    "-- Start of PGP signed section%s\n"),
			    code < 0 || stat ? catgets(elm_msg_cat, MeSet, 
						       MePgpFail,
						       ", PGP failed!") : ".");
      else if (opts & PGP_PUBLIC_KEY)
	  msg = elm_message(CATGETS(elm_msg_cat, MeSet, MePgpStartOutput1,
				    "-- Start of PGP output%s\n"),
			    code < 0 || stat ? catgets(elm_msg_cat, MeSet, 
						       MePgpFail,
						       ", PGP failed!") : ".");
      else
	  msg = elm_message(CATGETS(elm_msg_cat, MeSet, MePgpStart1,
				    "-- Start of PGP section%s\n"),
			    code < 0 || stat ? catgets(elm_msg_cat, MeSet, 
						       MePgpFail,
						       ", PGP failed!") : ".");
      state_puts(msg,s_out);
      free(msg);
  } else {
      if (opts & PGP_MESSAGE)
	  state_printf(s_out,
		       CATGETS(elm_msg_cat, MeSet, MePgpStartEncoded,
			       "-- Start of PGP encoded section.\n"));
      else if (opts & PGP_SIGNED_MESSAGE)
	  state_printf(s_out,
		       CATGETS(elm_msg_cat, MeSet, MePgpStartSigned,
			       "-- Start of PGP signed section.\n"));
      else if (opts & PGP_PUBLIC_KEY)
	  state_printf(s_out,
		     CATGETS(elm_msg_cat, MeSet, MePgpStartOutput,
			     "-- Start of PGP output.\n"));
      else
	  state_printf(s_out,
		     CATGETS(elm_msg_cat, MeSet, MePgpStart,
			     "-- Start of PGP section.\n"));
  }

  bytes = 0;

  if (was_text && !nested) {

      if (set_filter(m,s_out,NULL,
		     mss ? mss->override_charset : NULL)) {

	  DPRINT(Debug,4,(&Debug, 
			  "pgp_decode: Filtering according of charset enabled.\n"));
  
      } else {
	  DPRINT(Debug,4,(&Debug, 
			  "pgp_decode: Unsupported character set?\n"));

	  skip_flag++;
      }
      
  }

 retry:

  while ((len = mail_gets (buffer, sizeof (buffer), pgpout)) > 0) {
      if (nested) {
	  if (buffer[0] == '\n' || (buffer[0] == '\r' && buffer[1] == '\n'))
	      inbody = TRUE;
	  fputs (buffer, tmpfp);
	  if (inbody)
	      bytes += len;
      } else if (!skip_flag) {
	  state_add_prefix(s_out);
	  state_puts(buffer,s_out);
      }
  }
 
  s_out -> filter = NULL;
 
  if (ferror(pgpout) && EINTR == errno) {
      clearerr(pgpout);
      DPRINT(Debug,5,(&Debug,
		      "Reading of result interrupted (EINTR) -- retrying\n"));

      if (0 == code) {
	  code = run_already_done(&RS,&stat);
	  if (0 != code) {
	      DPRINT(Debug,5,(&Debug,
			  "now pgp/gpg is completing\n"));
	  }      
      }

      goto retry;
  }
  

  fclose (pgpout); pgpout = NULL;

  if (nested) {
      struct in_state s2_in;
      in_state_clear(&s2_in,STATE_in_file);
      
      DPRINT(Debug,3,(&Debug,
		      "pgp_decode: parsing decrypted data as MIME\n"));
      
      if (EOF == fflush(tmpfp)) {
	  lib_error(CATGETS(elm_msg_cat, MeSet, MePgpErrorFlush,
			    "Error when flushing temporary file."));
	  state_putc('[',s_out);
	  state_printf(s_out,
		       CATGETS(elm_msg_cat, MeSet, MePgpErrorFlush,
			       "Error when flushing temporary file."));
	  state_puts("]\n",s_out);
      }
      rewind(tmpfp); /* Rewind it for reading */
      
      tmpmt = mime_read_header (tmpfp, 0, defcharset, & (mss->header_error));
      tmpmt->length = bytes;

      mime_parser_parse(tmpmt,defcharset,tmpfp, & (mss->header_error));
  
      set_in_state_file(tmpfp,&s2_in);
      
      /* Pass NULL as message, because this is decryoted contetnt */
      mime_decode (tmpmt, &s2_in, s_out, defcharset, NULL, badtype);

      mime_t_clear(tmpmt);
 
      in_state_destroy(&s2_in);
      
      fclose (tmpfp);
  }
  
  if (0 == code)
      code = wait_end(&RS,&stat);

  call_print_status_cooked(&RS,code < 0 ? -code : 0,stat);

  if (raw)
      sr_call_Raw (ON);

  if (opts & PGP_MESSAGE)
      elm_sfprintf(buffer,sizeof buffer,
		   CATGETS(elm_msg_cat, MeSet, MePgpEndEncoded,
			   "-- End of PGP encoded section%s\n"),
		   code < 0 || stat ? catgets(elm_msg_cat, MeSet, MePgpFail,
					      ", PGP failed!") : ".");
  else if (opts & PGP_SIGNED_MESSAGE)
      elm_sfprintf(buffer,sizeof buffer,
		   CATGETS(elm_msg_cat, MeSet, MePgpEndSigned,
			   "-- End of PGP signed section%s\n"),
		   code < 0 || stat ?  catgets(elm_msg_cat, MeSet, MePgpFail,
					       ", PGP failed!") : ".");
  else if (opts & PGP_PUBLIC_KEY)
      elm_sfprintf(buffer,sizeof buffer,
		   CATGETS(elm_msg_cat, MeSet, MePgpEndOutput,
			   "-- End of PGP output%s\n"),
		   code < 0 || stat ?  catgets(elm_msg_cat, MeSet, MePgpFail,
					       ", PGP failed!") : ".");
  else
      elm_sfprintf(buffer,sizeof buffer,
		   CATGETS(elm_msg_cat, MeSet, MePgpEnd,
			   "-- End of PGP section%s\n"),
		   code < 0 || stat ? catgets(elm_msg_cat, MeSet, MePgpFail,
				  ", PGP failed!") : ".");
  state_puts(buffer,s_out);


 FAILTYPE:
  in_state_destroy(&newstate2);
  if (decode_fp)        /* in_state_destroy does not close file!! */
      fclose(decode_fp);
}

void pgp_SG_decoder(body,sign,state_in,state_out,micalg, defcharset, mss,
		    badtype)
     mime_t *body; 
     mime_t *sign;
     in_state_t   *state_in;
     out_state_t  *state_out;     
     const char         *micalg;
     charset_t    defcharset;
     struct header_rec *mss;
     type_mismatch_prompt *badtype;
{
    int exit_code = -1;
    FILE *binary_fp;
    char *body_name = NULL;
    in_state_t newstate2;
    char * buffer;
    enum pgp_version v = pgp2;
    enum pgp_version version;

    in_state_clear(&newstate2,STATE_in_file);

    if (0 == istrcmp(micalg,"pgp-md5")) {
	DPRINT(Debug,4,(&Debug,
			"pgp_SG_decoder: micalg=%s, PGP 2\n",
			micalg));
	v = pgp2;
    } else { 
	DPRINT(Debug,4,(&Debug, 
			"pgp_SG_decoder: micalg=%s, GPG\n",
			micalg));
	v = gpg;
    }

    if (NULL != (binary_fp = arrange_binary(body,state_in,state_out,&newstate2,
					    &body_name))) {	
	in_state_t newstate3;
	FILE *decode_fp = NULL;
	char *sign_name = NULL;
	
	in_state_clear(&newstate3,STATE_in_file);
	
	if (in_state_fseek(state_in,sign->offset) != 0) {
	    lib_error(CATGETS(elm_msg_cat, MeSet, MePgpSGSeekFail,
			      "pgp_SG_decoder: seek failed"));
	    state_putc('[',state_out);
	    state_printf(state_out,
			 CATGETS(elm_msg_cat, MeSet, MePgpSGSeekFail,
				 "pgp_SG_decoder: seek failed"));
	    state_puts("]\n",state_out);	    
	}
	    
	if (NULL != (decode_fp = 
		     arrange_decoded(sign,state_in,state_out,&newstate3,
				     &sign_name))) {  

	    int i = 0;
	    int len1;
	    char buf[STRING];
	    
	    while ((len1 = state_getl (buf, sizeof (buf), &newstate3)) > 0) {
		if (i == 0) {
		    if (strncmp(buf, "-----BEGIN PGP", 14) != 0)
			break;
		    i++;
		    continue;
		}
		if ((len1 == 1 && buf[0] == '\n') ||
		    (len1 == 2 && buf[0] == '\r' && buf[1] == '\n'))
		    break;
		if (0 == strncmp("Version: ",buf,9)) {
		    char *c = buf+9;

		    v = decode_pgp_version(c);
		}
	    }
	    in_state_fseek(&newstate3,0);

	    if ((version=have_pgp(v))) {

		struct run_state RS;
		int stat;
		CONST char * argv[10];
		int raw = sr_call_RawState ();
		
		
		switch(version) {
		    static char path[1000];
		case pgp2:	
		    {
			char * pgp2_path_val = 
			    give_dt_estr_as_str(&pgp2_path_e, "pgp2");
			if (! pgp2_path_val)
			    return;
			
			argv[0] = pgp2_path_val;
		    }
		    argv[1] = "+batchmode";
		    argv[2] = "+TEXTMODE=off";
		    argv[3] = "+CHARSET=noconv";
		    argv[4] = sign_name;
		    argv[5] = body_name;
		    argv[6] = NULL;
		    break;
		case pgp5:
		    {
			/* give_dt_estr_as_str adds / to end */
			char * pgp5_dir_val  = give_dt_estr_as_str(&pgp5_dir_e,
								   "pgp5-dir");
			if (! pgp5_dir_val)
			    return;
			elm_sfprintf(path, sizeof path,FRM("%spgpv"),
				     pgp5_dir_val);
		    }
		    argv[0] = path;
		    argv[1] = "+batchmode";
		    argv[2] = "+TEXTMODE=off";
		    argv[3] = "+CHARSET=noconv";
		    argv[4] = sign_name;
		    argv[5] = body_name;
		    argv[6] = NULL;
		    break;
		case gpg: 
		    {
			char * gpg_path_val = give_dt_estr_as_str(&gpg_path_e, 
								  "gpg");
			if (! gpg_path_val)
			    return;

			argv[0] = gpg_path_val;
		    }
		    argv[1] = "--batch";
		    argv[2] = "--verify";
		    argv[3] = sign_name;
		    argv[4] = body_name;
		    argv[5] = NULL;
		    break;
		}
		    
		sr_call_Raw(OFF);
		sr_call_ClearScreen();
		sr_call_Write_to_screen(CATGETS(elm_msg_cat, MeSet, MePgpCheckSig,
					"Running pgp: Checking signature...\n"));

		stat = start_run(&RS,0,argv,-1,-1);
		if (stat)
		    stat = wait_end(&RS,&exit_code);
		
		call_print_status_cooked(&RS,stat < 0 ? -stat : 0,exit_code);
		
		if (raw)
		    sr_call_Raw (ON);
		
		if (stat) {
		    if (state_out->displaying) {
			state_puts("\n[",state_out);		
			if (exit_code == 0)
			    state_printf(state_out,
					 CATGETS(elm_msg_cat, MeSet,MePgpSigOK,
						 "Checking application/pgp-signature: OK"));
			else
			    state_printf(state_out,
					 CATGETS(elm_msg_cat, MeSet,MePgpSigFAILURE,
						 "Checking application/pgp-signature: FAILURE"));		
			state_puts("]\n\n",state_out);
		    } else if (exit_code != 0) {
			state_puts("\n",state_out);
			state_printf(state_out,
				     CATGETS(elm_msg_cat, MeSet,MePgpSigFAILURE,
					     "Checking application/pgp-signature: FAILURE"));		
			state_puts("\n",state_out);
		    }
		} else {
		    if (RS.save_errno) {
			lib_error(CATGETS(elm_msg_cat, ElmSet, ElmFailErrno,
					  "Failed: %.30s: %.40s"),
				  argv[0],error_description(RS.save_errno));
		    } else
			lib_error(CATGETS(elm_msg_cat, ElmSet, ElmCantStart,
				      "Can't start %.30s"),
				  argv[0]);
		}
	    }
	    unlink(sign_name);
	    free(sign_name);
	    in_state_destroy(&newstate3);
	    if (decode_fp)        /* in_state_destroy does not close file!! */
		fclose(decode_fp);
	}
	
	unlink(body_name);
	free(body_name);
	in_state_destroy(&newstate2);
	if (binary_fp)        /* in_state_destroy does not close file!! */
	    fclose(binary_fp);
    }

    state_printf(state_out,
		 CATGETS(elm_msg_cat, MeSet, MePgpStartSigned,
			 "-- Start of PGP signed section.\n"));

    /* Pass mss as message, because this is NOT decrypted (only signed) */
    mime_decode(body,state_in,state_out, defcharset, mss,
		badtype);

    buffer = elm_message(CATGETS(elm_msg_cat, MeSet, MePgpEnd,
				 "-- End of PGP section%s\n"),
			 exit_code ? catgets(elm_msg_cat, MeSet, MePgpFail,
					     ", PGP failed!") : ".");
    state_puts(buffer,state_out);
    free(buffer);
}  

void pgp_EC_decoder(init,data,state_in,state_out, defcharset, mss, badtype)
     mime_t *init;
     mime_t *data;
     in_state_t   *state_in;
     out_state_t  *state_out;
     charset_t     defcharset;
     struct header_rec *mss;
     type_mismatch_prompt *badtype;
{
    char * tempfile = NULL;
    FILE *decode_fp;
    FILE *tmpfp;
    in_state_t newstate2;
    char *tmp;

    tmp = give_dt_estr_as_str(&temp_dir_e,"tmpdir");


    in_state_clear(&newstate2,STATE_in_file);

    if (in_state_fseek(state_in,data->offset) != 0) {
	lib_error(CATGETS(elm_msg_cat, MeSet, MePgpECSeekFail,
			  "pgp_EC_decoder: seek failed"));
	state_putc('[',state_out);
	state_printf(state_out,
		     CATGETS(elm_msg_cat, MeSet, MePgpECSeekFail,
			     "pgp_EC_decoder: seek failed"));
	state_puts("]\n",state_out);	    
    }

    tempfile = elm_message(FRM("%selmPT%d"), 
			   tmp, getpid ());
	
    if (NULL == (tmpfp = safeopen_rdwr(tempfile))) {
	lib_error(CATGETS(elm_msg_cat, MeSet, MePgpCantCreate,
			  "Failed to create file for decoding."));
	state_putc('[',state_out);
	state_printf(state_out,
		     CATGETS(elm_msg_cat, MeSet, MePgpCantCreate,
			     "Failed to create file for decoding."));      
	state_puts("]\n",state_out);
	free(tempfile);
	return;
    }
    unlink (tempfile); /* Filename is no longer needed ... */
    free(tempfile); tempfile = NULL;


    if (NULL != (decode_fp = 
		 arrange_decoded(data,state_in,state_out,&newstate2,NULL))) {  
	int i = 0,len1;
	char buf[STRING];
	enum pgp_version v = pgp2;
	enum pgp_version version;
	struct in_state s2_in;
	struct run_state RS;
	FILE *pgpout,*pgpin;
	int code;
	mime_t *tmpmt;
	int stat;
	long bytes = 0;
	int inbody = FALSE;
	int raw = sr_call_RawState ();
	in_state_clear(&s2_in,STATE_in_file);

	while ((len1 = state_getl (buf, sizeof (buf), &newstate2)) > 0) {
	    if (i == 0) {
		if (strncmp(buf, "-----BEGIN PGP", 14) != 0)
		    break;
		i++;
		continue;
	    }
	    if ((len1 == 1 && buf[0] == '\n') ||
		(len1 == 2 && buf[0] == '\r' && buf[1] == '\n'))
		break;
	    if (0 == strncmp("Version: ",buf,9)) {
		char *c = buf+9;
		
		v = decode_pgp_version(c);
	    }
	}
	in_state_fseek(&newstate2,0);
      
	version = have_pgp(v);
	if (!version) {
	  state_printf(state_out,
		       CATGETS(elm_msg_cat, MeSet, MePgpNotAvailSkipping,
			       "[ PGP not available, skipping... ]\n"));
	  return;
	}

	if (!pgp_goodPassphrase(version)) {
	    lib_error(CATGETS(elm_msg_cat, MeSet, MePgpBadPassphrase,
			      "Decrypting message... Bad PGP passphrase."));
	    state_puts("[ ",state_out);
	    state_printf(state_out,
			 CATGETS(elm_msg_cat, MeSet, MePgpBadPassphrase,
				 "Decrypting message... Bad PGP passphrase."));
	    state_puts(" ]\n",state_out);
	    return;
	}

	if (!pgp_decrypt_init (&pgpout, &pgpin, PGP_MESSAGE, version, &RS)) {
	    state_printf(state_out,
			 CATGETS(elm_msg_cat, MeSet, MePgpInternalSkipping,
				 "[ Internal error while calling pgp, skipping... ]\n"));
	}

	while ((len1 = state_getl (buf, sizeof (buf), 
				   &newstate2)) > 0) {
	    fwrite(buf,1,len1,pgpin);
	}  
	fclose (pgpin);
	
	code = run_already_done(&RS,&stat);	

	if (code != 0) {
	    char * msg = elm_message(CATGETS(elm_msg_cat, MeSet, 
					   MePgpStartEncoded1,
					   "-- Start of PGP encoded section%s\n"),
				   code < 0 || stat ? catgets(elm_msg_cat, 
							      MeSet, 
							      MePgpFail,
							      ", PGP failed!") 
				   : ".");
	    state_puts(msg,state_out);
	    free(msg);
	} else
	  state_printf(state_out,
		       CATGETS(elm_msg_cat, MeSet, MePgpStartEncoded,
			       "-- Start of PGP encoded section.\n"));
	
	bytes = 0;

    retry:
	while ((len1 = mail_gets (buf, sizeof (buf), pgpout)) > 0) {
	  if (buf[0] == '\n' || (buf[0] == '\r' && buf[1] == '\n'))
	      inbody = TRUE;
	  fputs (buf, tmpfp);
	  if (inbody)
	      bytes += len1;
	}

	if (ferror(pgpout) && EINTR == errno) {
	    clearerr(pgpout);
	    DPRINT(Debug,5,(&Debug,
			    "Reading of result interrupted (EINTR) -- retrying\n"));

	    if (0 == code) {
		code = run_already_done(&RS,&stat);
		if (0 != code) {
		    DPRINT(Debug,5,(&Debug,
				    "now pgp/gpg is completing\n"));
		}      
	    }

	    goto retry;
	}
  
	fclose(pgpout);

	if (EOF == fflush(tmpfp)) {
	    lib_error(CATGETS(elm_msg_cat, MeSet, MePgpErrorFlush,
			      "Error when flushing temporary file."));
	    state_puts(" [",state_out);
	    state_printf(state_out,
			 CATGETS(elm_msg_cat, MeSet, MePgpErrorFlush,
				 "Error when flushing temporary file."));
	    state_puts(" ]\n",state_out);
	}
	rewind(tmpfp); /* Rewind it for reading */
      
	tmpmt = mime_read_header (tmpfp, 0, defcharset, &(mss->header_error));
	tmpmt->length = bytes;

	mime_parser_parse(tmpmt,defcharset,tmpfp, & (mss->header_error));
 
	set_in_state_file(tmpfp,&s2_in);
	
	/* Pass NULL as message, because this is encrypted section */
	mime_decode (tmpmt, &s2_in, state_out, defcharset, NULL,
		     badtype);

	mime_t_clear(tmpmt);

	in_state_destroy(&s2_in);
	
	if (0 == code)
	    code = wait_end(&RS,&stat);

	call_print_status_cooked(&RS,code < 0 ? -code : 0,stat);

	if (raw)
	    sr_call_Raw (ON);
	
	elm_sfprintf(buf,sizeof buf,
		     CATGETS(elm_msg_cat, MeSet, MePgpEndEncoded,
			     "-- End of PGP encoded section%s\n"),
		     code < 0 || stat ? catgets(elm_msg_cat, MeSet, MePgpFail,
						", PGP failed!") : ".");
	
	state_puts(buf,state_out);
	
	in_state_destroy(&newstate2);
	if (decode_fp)        /* in_state_destroy does not close file!! */
	    fclose(decode_fp);
    } else {
	char * msg = elm_message(CATGETS(elm_msg_cat, MeSet, 
					 MePgpEncodedCantEncoding,
					 "-- Start of PGP encoded section -- can't decode content-transfer-encoding\n"));
	state_puts(msg,state_out);    
	free(msg);
    }
    fclose (tmpfp);

}

#endif /* USE_PGP */

/*
 * Local Variables:
 *  mode:c
 *  c-basic-offset:4
 *  buffer-file-coding-system: iso-8859-1
 * End:
 */


syntax highlighted by Code2HTML, v. 0.9.1