/*
 *  MicroDot PGP Interface
 */

#include "microdot.h"
#include "ogre.h"
#include "ogre_protos.h"

#include "asyncio.h"

#include <dos/dostags.h>

static char *passphrase;
static ULONG passphrasesize;

static UBYTE *mykey;
static ULONG mykeysize;

int pgpavail;

static char pgppath[ 128 ];
static char pgpcmdpath[ 256 ];

#define PGPWARN "PGP-`Pass phrase' setzen.\n\n\
WARNUNG! Diese Option setzt das Passwort,\n\
mit dem PGP Ihre Keyrings schützt!\n\
Verwenden Sie diese Option nicht, ohne sich\n\
vorher in der Anleitung von MicroDot über die\n\
Implikationen informiert zu haben."

#define CODE(c) ((int)sextet[((c) & 077)])
#define FUELL   '='

void pgp_addb64hl( struct hlist *hl, char *header, UBYTE *data, int size  )
{
        char buffer[ 8192 ];
        static char sextet[] =  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                        "abcdefghijklmnopqrstuvwxyz"
                        "0123456789+/";
        int count = size, cnt;
        UBYTE buf[ 4 ], *bp = data, *to = buffer;
        int a, b, c, d;

        while( count )
        {
                memset(buf, 0, 3);
                /*
                 *  3 Byte einlesen:
                 */
        
                cnt = min( count, 3 );
                count -= cnt;
                memcpy( buf, bp, cnt );
                bp += cnt;

                /*
                 *  und als 4 sextets ausgeben
                 */
                a = buf[0] >> 2;
                b = ((buf[0] << 4) & 060)   | ((buf[1] >> 4) & 017);
                c = ((buf[1] << 2) & 074) | ((buf[2] >> 6) & 03);
                d = buf[2] & 077;
                *to++ = CODE( a );
                *to++ = CODE( b );
                if (cnt == 1)   {
                        *to++ = FUELL;
                        *to++ = FUELL;
                } else {
                        *to++ = CODE( c );
                        if (cnt == 2)
                                *to++ = FUELL;
                        else
                                *to++ = CODE( d );
                }
        }
        *to = 0;
        hl_addheader( hl, header, buffer );
}

void pgp_addb64hlfile( struct hlist *hl, char *header, char *filename )
{
        BPTR f;
        int len = getfilelen( filename );
        APTR mem;

        if( len < 1 )
                return;

        mem = myAllocVec( len, MEMF_ANY );
        if( !mem )
                return;

        f = Open( filename, MODE_OLDFILE );
        Read( f, mem, len );
        Close( f );

        pgp_addb64hl( hl, header, mem, len );

        myFreeVec( mem );

}

void pgp_addpubkey( struct hlist *hl )
{
        char buffer[ 512 ];

		if( prefs.mode == MDM_RFC )
	        sprintf( buffer, "%s <%s@%s%s>",
                prefs.userrealname,
                prefs.username,
                prefs.pointname,
                prefs.boxdomain
	        );

		else
	        sprintf( buffer, "%s <%s@%s%s>",
                prefs.userrealname,
                prefs.username,
                prefs.boxname,
                prefs.boxdomain
	        );

        if( stricmp( buffer, prefs.pgp_userid ) )
                hl_addheader( hl, "PGP-ID", prefs.pgp_userid );

        pgp_addb64hl( hl, "PGP-PUBLIC-KEY", mykey, mykeysize );
}


void pgp_setpassphrase( void )
{
        char *tempbuff = myAllocVec( 4096, 0 );
		ULONG pcrc;

        if( !tempbuff )
        {
                displaybeep();
                return;
        }

		if( GetVar( "PGPPASS", tempbuff, 127, 0 ) > 0 )
		{
			FreeVec( tempbuff );
			return;
		}

redo:
		tempbuff[ 0 ] = 0;
        switch( rtGetString( tempbuff, 4095, NULL, rinfo,
                RTGS_Invisible, TRUE,
                RTGS_TextFmt, PGPWARN,
                RTGS_GadFmt, "OK|Hilfe|Abbruch",
                TAG_DONE ) )
        {
                case 1:
                        if( passphrase )
                                LibFreePooled( miscmempool, passphrase, passphrasesize );
                        passphrasesize = strlen( tempbuff ) + 1;
                        passphrase = NULL;
                        if( passphrasesize < 2 )
                        {
                                askreq( "PGP 'Pass phrase' gelöscht.", "Weiter" );
                                myFreeVec( tempbuff );
                                return;
                        }

						pcrc = crc32( tempbuff, strlen( tempbuff ) );
						if( prefs.pgp_lastpassphrase && ( pcrc != prefs.pgp_lastpassphrase ) )
						{
							if( askreq( "Die eingegebene Passphrase stimmt nicht mit der\nüberein, die Sie zuletzt an dieser Stelle eingegeben haben.",
								"Nochmal eingeben|Trotzdem benutzen"
							)) goto redo;
						}

                        passphrase = LibAllocPooled( miscmempool, passphrasesize );
                        if( !passphrase )
                        {
                                displaybeep();
                                myFreeVec( tempbuff );
                                return;
                        }
                        strcpy( passphrase, tempbuff );
						prefs.pgp_lastpassphrase = pcrc;
                        myFreeVec( tempbuff );
                        break;

                case 2:
                        showguide( "pgp_setpassphrase" );
                        goto redo;
        }
}

int runpgp( char *cmd, int pp, int flags )
{
        char tmp[ 256 ];
        BPTR outwin, oldcd, pgpcd, outwin2 = NULL;
        int rc;
		char *textmode = ( flags & 16 ) ? "on" : "off";
		char *armor = ( flags & 8 ) ? "on" : "off";

        if( pp && !passphrase && prefs.pgp_autoaskpp )
                pgp_setpassphrase();

        /* Kein Quiet, falls Passphrase per PGP eingegeben werden muß */
        if( pp && !passphrase )
                flags &= ~2;

        if( ! ( flags & 2 ) )
        {
                strcpy( tmp, prefs.pgp_win );
                if( flags & 1 )
                        strcat( tmp, "/WAIT/CLOSE" );
                outwin = OpenCon( tmp );
                if( !outwin )
                {
                        displaybeep();
                        return( -2 );
                }
        }
        else
        {
                outwin = Open( "NIL:", MODE_OLDFILE );
				outwin2 = Open( "NIL:", MODE_OLDFILE );
        }

        pgpcd = Lock( pgppath, SHARED_LOCK );
        if( !pgpcd )
        {
                displaybeep();
                Close( outwin );
                return( -3 );
        }

        oldcd = CurrentDir( pgpcd );

        if( !pp )
                sprintf( tmp, "\"%s\" +armor=%s +textmode=%s %s%s", pgpcmdpath, armor, textmode, ( flags & 4 ) ? "" : "+batchmode +force ", cmd );
        else if( pp && !passphrase )
                sprintf( tmp, "\"%s\" +armor=%s +textmode=%s %s", pgpcmdpath, armor, textmode, cmd );
        else
                sprintf( tmp, "\"%s\" +armor=%s +textmode=%s %s\"-z%s\" %s",
                        pgpcmdpath,
						armor, textmode,
                        pp != 2 ? "+batchmode " : "",
                        passphrase,
                        cmd
                );

		if( flags & 1 )
	        FPrintf( outwin, "·\x08" );

		//FPrintf( outwin, "EXEC: '%s'\n", tmp );

        rc = SystemTags( tmp,
                NP_StackSize, 10240,
                SYS_Input, outwin,
                SYS_Output, outwin2,
                TAG_DONE
        );

        if( flags & 1 )
		{
        	FPrintf( outwin, "\n\nPGP-Aufruf abgeschlossen (rc %ld).\nBitte dieses Fenster per CLOSE-Gadget oder CTRL-\\ schließen.", rc );
		}

        Close( outwin );
        if( outwin2 )
        	Close( outwin2 );

        UnLock( CurrentDir( oldcd ) );

        return( rc );
}


static char *krentries[] = { "Nie", "Immer", "Nachfragen", NULL };

#define PP_OK 1
#define PP_CANCEL 2
#define PP_UID 3
#define PP_AVAIL 4
#define PP_KEYREQ 5
#define PP_EB 6
#define PP_WIN 7
#define PP_AUTOASKPP 8
#define PP_RING1 9
#define PP_RING2 10

void pgp_prefs( void )
{
        struct ogwin *ogw;
        struct Window *iw;
        struct IntuiMessage *im;
        int Done = FALSE;

        ogw = ogreInitWindow( scr, 0, 0, "PGP-Voreinstellungen" );

        ogreAddGroup( ogw, 0, OGFRAME_OUTLINE, " Info " );
        ogreAddString( ogw, 0, 'u', "Eigene _UserID:", PP_UID, prefs.pgp_userid, 40, 256 );
        ogreAddString( ogw, 1, 'i', "PGP-KEY-AVAIL:-_Info", PP_AVAIL, prefs.pgp_avail, 40, 128 );

        ogreAddGroup( ogw, 1, OGFRAME_OUTLINE, " Optionen " );
        ogreAddCheckbox( ogw, 0, 'p', "`_Pass phrase' automatisch erfragen:", PP_AUTOASKPP, prefs.pgp_autoaskpp );
        ogreAddCheckbox( ogw, 1, 'e', "Eigenen Key bei _Empfangsbestätigungen mitschicken:", PP_EB, prefs.pgp_sendoneb );
        ogreAddCycle( ogw, 2, 'r', "Key-_Requests beantworten:", PP_KEYREQ, krentries, 12, prefs.pgp_request );

        ogreAddGroup( ogw, 2, OGFRAME_OUTLINE, " Sonstiges " );
        ogreAddString( ogw, 0, 'f', "_Fenster für PGP-Aufruf:", PP_WIN, prefs.pgp_win, 40, 128 );
        ogreAddString( ogw, 1, 0, "Keyring:", PP_RING1, prefs.pgp_ring1, 40, 128 );
        //ogreAddString( ogw, 2, 0, "Sekundärer Keyring:", PP_RING2, prefs.pgp_ring2, 40, 128 );

        ogreAddGroup( ogw, 3, OGFRAME_NONE, NULL );
        ogreAddButton( ogw, 0 | OGB_ONENTER, 'o', "_OK", PP_OK );
        ogreAddHelp( ogw, 0 );
        ogreAddButton( ogw, 0 | OGB_ONESC, 'a', "_Abbruch", PP_CANCEL );

        iw = ogreOpenWindow( ogw );
        if( !iw )
            return;

        while( !Done )
        {
                im = ogreWaitIM( ogw );

                if( im->Class == IDCMP_GADGETHELP)
                        showguidenum( "pgp_prefsgads", im->Code );
                else if( im->Class == IDCMP_GADGETUP )
                {
                        switch( im->Code )
                        {
                                case PP_OK:
                                        Done = 2;
                                        break;

                                case PP_CANCEL:
                                        Done = 1;
                                        break;
                        }
                }
                ogreIMReply( ogw, im );
        }

        if( Done == 2 )
        {
                ogreCopyStringValue( ogw, PP_UID, prefs.pgp_userid );
                ogreCopyStringValue( ogw, PP_AVAIL, prefs.pgp_avail );
                ogreCopyStringValue( ogw, PP_WIN, prefs.pgp_win );
                ogreCopyStringValue( ogw, PP_RING1, prefs.pgp_ring1 );
                // ogreCopyStringValue( ogw, PP_RING2, prefs.pgp_ring2 );
                prefs.pgp_sendoneb = ogreValue( ogw, PP_EB );
                prefs.pgp_request = ogreValue( ogw, PP_KEYREQ );
                prefs.pgp_autoaskpp = ogreValue( ogw, PP_AUTOASKPP );
        }

        ogreExitWindow( ogw );
}

int getpubkey( char *userid, char *toname )
{
        char tmp[ 128 ];
        int rc;

        DeleteFile( toname );

        /* Ersten Ring versuchen */
        sprintf( tmp, "-kx \"%s\" %s \"%s\"",
                userid,
                toname,
                prefs.pgp_ring1 );

        rc = runpgp( tmp, 0, 2 );

        if( rc && prefs.pgp_ring2[ 0 ] )
        {
                /* Zweiten Ring versuchen */
                sprintf( tmp, "-kx \"%s\" %s \"%s\"",
                        userid,
                        toname,
                        prefs.pgp_ring2 );

                rc = runpgp( tmp, 0, 2 );
                if( !rc && ( getfilelen( toname ) > 0 ) )
                        return( 2 );
        }

        if( !rc && ( getfilelen( toname ) > 0 ) )
                return( 1 );
        else
                return( 0 );

}

static int readmykey( char *filename )
{
        BPTR f;

        mykeysize = getfilelen( filename );
        if( mykeysize < 1 )
                return( -1 );
        mykey = LibAllocPooled( miscmempool, mykeysize );
        if( !mykey )
                return( -2 );

        f = Open( filename, MODE_OLDFILE );
        if( !f )
                return( -3 );

        Read( f, mykey, mykeysize );
        Close( f );

        return( 0 );
}


void pgp_init( void )
{
        char tmp[ 256 ];
        BPTR f;

        if( GetVar( "PGPPath", pgppath, 128, 0 ) < 1 )
                return;

        if( !checkprograminpathfull( "PGP", pgpcmdpath ) )
        {
                strcpy( tmp, pgppath );
                AddPart( tmp, "PGP", 256 );
                if( getfilelen( tmp ) < 1 )
                        return;
                strcpy( pgpcmdpath, tmp );
        }

        pgpavail = TRUE;

        /* Userid? */
        if( !prefs.pgp_userid[ 0 ] )
		{
				if( prefs.mode == MDM_RFC )
	                sprintf( prefs.pgp_userid, "%s <%s@%s%s>",
                        prefs.userrealname,
                        prefs.username,
                        prefs.pointname,
                        prefs.boxdomain
    	            );
				else
	                sprintf( prefs.pgp_userid, "%s <%s@%s%s>",
                        prefs.userrealname,
                        prefs.username,
                        prefs.boxname,
                        prefs.boxdomain
    	            );
		}

        if( !prefs.pgp_win[ 0 ] )
                strcpy( prefs.pgp_win, "CON://1024/1024/MicroDot-PGP-Shell/AUTO" );

        if( !prefs.pgp_ring1[ 0 ] )
                strcpy( prefs.pgp_ring1, "pubring.pgp" );

        prefs.pgp_ring2[ 0 ] = 0;

        /* Gut. Eigenen Public-Key einlesen */
        pushhomedir();
        if( !readmykey( "microdot.pgpkey" ) )
        {
                popdir();
                return;
        }
        popdir();

retry:
        if( !getpubkey( prefs.pgp_userid, "T:mdpgpkey.pgp" ) )
        {
reask:
                switch( askreq( "Ihr eigener Public-Key unter der UserID\n\"%s\"\nwurde nicht gefunden. Wollen Sie jetzt\nein Key-Paar generieren?",
                                "Keys generieren|PGP-Voreinstellungen|Hilfe|Abbruch",
                                prefs.pgp_userid ) )
                {
                        case 0:
                                pgpavail = 0;
                                return;

                        case 1:
                                if( !runpgp( "-kg", 0, 5 ) )
                                {
                                        sprintf( tmp, "-ks \"%s\"", prefs.pgp_userid );
                                        runpgp( tmp, 1, 5 );
                                }
                                goto retry;
                                break;

                        case 2:
                                pgp_prefs();
                                goto retry;

                        case 3:
                                showguide( "pgp_genkeys" );
                                goto reask;
                }
        }

        readmykey( "T:mdpgpkey.pgp" );
        pushhomedir();
        f = Open( "microdot.pgpkey", MODE_NEWFILE );
        if( f )
        {
                Write( f, mykey, mykeysize );
                Close( f );
        }
        popdir();

        DeleteFile( "T:mdpgpkey.pgp" );

}

#define IGID_LV 1
#define IGID_OK 2
#define IGID_CANCEL 3

#define IGID_DEL 4
#define IGID_ADD1 5
#define IGID_ADD2 6
#define IGID_VIEW 7
#define IGID_ALL 8

struct keymem {
        char *userid;
        UBYTE *key;
        ULONG keysize;
		char label[ 128 ];
};

static void doviewfingerprint( struct keymem *km )
{
        char exec[ 128 ], tmpkey[ 64 ], tmpring[ 64 ];
        BPTR f;

        sprintf( tmpkey, "T:mdkeytmp%lx.pgp", time( 0 ) );
        sprintf( tmpring, "T:mdringtmp%lx.pgp", time( 0 ) );

        f = Open( tmpkey, MODE_NEWFILE );
        if( !f )
        {
                displaybeep();
                return;
        }
        Write( f, km->key, km->keysize );
        Close( f );

        sprintf( exec, "-ka %s %s", tmpkey, tmpring );
        runpgp( exec, 0, 2 );
        sprintf( exec, "-kvc \"%s\" %s", km->userid, tmpring );
        runpgp( exec, 0, 1 );


        // Tempfiles löschen

        DeleteFile( tmpring );
        strcpy( strchr( tmpring, '.' ), ".bak" );
        DeleteFile( tmpring );
        DeleteFile( tmpkey );
}

#if 0
static void doaddkey( struct keymem *km, int keyring )
{
        char exec[ 128 ], tmpkey[ 64 ];
        BPTR f;

        sprintf( tmpkey, "T:mdkeytmp%lx.pgp", time( 0 ) );

        f = Open( tmpkey, MODE_NEWFILE );
        if( !f )
        {
                displaybeep();
                return;
        }
        Write( f, km->key, km->keysize );
        Close( f );

        sprintf( exec, "-ka %s \"%s\"", tmpkey, keyring ? prefs.pgp_ring2 : prefs.pgp_ring1 );
        runpgp( exec, 0, 0 );

        // Tempfiles löschen

        DeleteFile( tmpkey );
}
#endif

void pgp_procincoming( void )
{
        struct ogwin *ogw;
        struct Window *iw;
        struct IntuiMessage *im;
        int Done = FALSE;
        struct ogrevn *vn;
        struct AsyncFile *f;
        ULONG lm, olm;
        struct keymem *keymem;
        APTR keypool;
        int isediting = -1, keyring = 0;
        int c;

        pushhomedir();
        f = OpenAsync( "microdot.new_pgpkeys", MODE_READ, 4096 );
        popdir();
        if( !f )
        {
                askreq( "Keine eingegangenen Keys.", "Weiter" );
                return;
        }

        keypool = LibCreatePool( 0, 4096, 2048 );

        ogw = ogreInitWindow( scr, WFLG_RMBTRAP, 0, "Eingegangene PGP-Keys verwalten:" );
        ogreAddGroup( ogw, 0, OGFRAME_NONE, NULL );
        ogreAddList( ogw, 0, 0xff, NULL, IGID_LV, 60, 12, TRUE, NULL );
        ogreLVInit( ogw, IGID_LV );

#define MDKID 0x4d44504b

        for(;;)
        {
                keymem = LibAllocPooled( keypool, sizeof( *keymem ) );
                if( !keymem )
                        break;
                if( ReadAsync( f, &olm, 4 ) != 4 )
                        break;
                if( olm != MDKID )
                {
                        askreq( "Fehler in der Datei \"microdot.new_pgpkeys\":\nFalsche ID %lx", "Abbruch", olm );
                        break;
                }
                if( ReadAsync( f, &lm, 4 ) != 4 )
                        break;
                keymem->userid = LibAllocPooled( keypool, lm + 1 );
                if( !keymem->userid )
                        break;
                ReadAsync( f, keymem->userid, lm + 1 );
                if( ReadAsync( f, &lm, 4 ) != 4 )       /* CRC */
                        break;
                if( ReadAsync( f, &lm, 4 ) != 4 )
                        break;
                keymem->key = LibAllocPooled( keypool, keymem->keysize = lm );
                ReadAsync( f, keymem->key, lm );
                if( ReadAsync( f, &lm, 4 ) != 4 )       /* CRC */
                        break;

				sprintf( keymem->label, "%s: %s", olm == MDKID ? "KEY" : "SIG", keymem->userid );

                if( ogreLVFindEntry( ogw, IGID_LV, keymem->label ) )
                {
                        struct ogrevn *vn;

                        for( c = 0; ; c++ )
                        {
                                vn = ogreLVGetEntry( ogw, IGID_LV, c );
                                if( !vn )
                                        break;
                                if( !stricmp( ( ( struct keymem * ) vn->userdata ) -> label, keymem->label ) )
                                {
                                        Remove( ( struct Node * ) vn );
                                        break;
                                }
                        }
                }

                ogreLVAddEntry( ogw, IGID_LV, keymem->label, 0, keymem );
        }
        CloseAsync( f );

        ogreAddButton( ogw, 1, 'a', "_Alle", IGID_ALL );
        ogreAddButton( ogw, 1, 'l', "_Löschen", IGID_DEL );
        ogreAddButton( ogw, 1, '1', "-> Keyring _1", IGID_ADD1 );
        if( prefs.pgp_ring2[ 0 ] )
                ogreAddButton( ogw, 1, '2', "-> Keyring _2", IGID_ADD2 );
        ogreAddButton( ogw, 1, 'f', "_Fingerprint anzeigen", IGID_VIEW );

        ogreAddButton( ogw, 2 | OGB_ONENTER, '@', "OK", IGID_OK );
        ogreAddHelp( ogw, 2 );
        ogreAddButton( ogw, 2 | OGB_ONESC, '\x1b', "Abbruch", IGID_CANCEL );

        iw = ogreOpenWindow( ogw );
        if( !iw )
        {
                LibDeletePool( keypool );
                return;
        }

        while( !Done )
        {
                ogreEnable( ogw, isediting >= 0, IGID_DEL, IGID_ADD1, IGID_ADD2, IGID_VIEW, 0 );
				ogreEnable( ogw, ogreLVGetNumEntries( ogw, IGID_LV ), IGID_ALL, 0 );

                im = ogreWaitIM( ogw );
                if( im->Class == IDCMP_GADGETHELP)
                        showguidenum( "pgpkeywin_gads", im->Code );
                else if( im->Class == IDCMP_GADGETUP )
                {
                        switch( im->Code )
                        {
                                case IGID_LV:
                                        isediting = ogreValue( ogw, IGID_LV );
                                        break;

                                case IGID_OK:
                                        Done = 2;
                                        break;

                                case IGID_CANCEL:
                                        Done = 1;
                                        break;

								case IGID_ALL:
										for( c = 0; ; c++ )
										{
											struct ogrevn *vn = ogreLVGetEntry( ogw, IGID_LV, c );
											if( !vn )
												break;
											ogreLVSelect( ogw, IGID_LV, c );
											isediting = 0;
										}
                                        ogreLVRefresh( ogw, IGID_LV );
										break;

                                case IGID_DEL:
                                        if( isediting >= 0 )
                                        {
                                                struct ogrevn *vn = ogreLVGetEntry( ogw, IGID_LV, 0 ), *next;

												while( next = ( struct ogrevn * ) vn->n.mln_Succ )
												{
													if( vn->sel )
														Remove( vn );
													vn = next;
												}
                                                ogreLVRefresh( ogw, IGID_LV );
                                                isediting = -1;
                                        }
                                        break;

                                case IGID_ADD2:
                                        keyring = 1;

                                case IGID_ADD1:
                                        if( isediting >= 0 )
                                        {
                                                struct ogrevn *vn = ogreLVGetEntry( ogw, IGID_LV, 0 ), *next;
										        char exec[ 128 ], tmpkey[ 64 ];
										        BPTR f;

										        sprintf( tmpkey, "T:mdkeytmp%lx.pgp", time( 0 ) );

										        f = Open( tmpkey, MODE_NEWFILE );

												if( !f )
												{
													displaybeep();
													break;
												}

												while( next = ( struct ogrevn * ) vn->n.mln_Succ )
												{
													if( vn->sel )
													{
														struct keymem *km = vn->userdata;

														Write( f, km->key, km->keysize );
														Remove( vn );
													}
													vn = next;
												}

												Close( f );

										        sprintf( exec, "-ka %s \"%s\"", tmpkey, keyring ? prefs.pgp_ring2 : prefs.pgp_ring1 );
										        runpgp( exec, 0, 0 );

										        // Tempfiles löschen

										        DeleteFile( tmpkey );

                                                ogreLVRefresh( ogw, IGID_LV );
                                                isediting = -1;
                                        }
                                        keyring = 0;
                                        break;

                                case IGID_VIEW:
                                        if( isediting >= 0 )
                                        {
                                                struct ogrevn *vn = ogreLVGetEntry( ogw, IGID_LV, 0 ), *next;

												while( next = ( struct ogrevn * ) vn->n.mln_Succ )
												{
													if( vn->sel )
													{
                                                        doviewfingerprint( vn->userdata );
														vn->sel = FALSE;
													}
													vn = next;
												}
                                                ogreLVRefresh( ogw, IGID_LV );
                                                isediting = -1;
                                        }
                                        break;
                        }
                }
                ogreIMReply( ogw, im );
        }

        if( Done == 2 )
        {
                struct ogrevn *vn;
                struct keymem *km;

                pushhomedir();
                DeleteFile( "microdot.new_pgpkeys.bak" );
                Rename( "microdot.new_pgpkeys", "microdot.new_pgpkeys.bak" );
                f = OpenAsync( "microdot.new_pgpkeys", MODE_WRITE, 4096 );
                if( f )
                {
                        /* Übrige Keys wieder abspeichern */
                        for( c = 0; ; c++ )
                        {
                                vn = ogreLVGetEntry( ogw, IGID_LV, c );
                                if( !vn )
                                        break;
                                km = vn->userdata;

                                lm = MDKID;
                                WriteAsync( f, &lm, 4 );
                                lm = strlen( km->userid );
                                WriteAsync( f, &lm, 4 );
                                WriteAsync( f, km->userid, lm + 1 );
                                WriteAsync( f, &lm, 4 );        /* Dummy */
                                WriteAsync( f, &km->keysize, 4 );
                                WriteAsync( f, km->key, km->keysize );
                                WriteAsync( f, &lm, 4 );        /* Dummy */
                        }
                        CloseAsync( f );
                }
                if( !c )
                        DeleteFile( "microdot.new_pgpkeys" );
                popdir();
        }

        ogreExitWindow( ogw );
        LibDeletePool( keypool );
}

void pgp_showkeys( int verbose )
{
        char exec[ 64 ];

        sprintf( exec, "-kv%s %s", verbose ? "v" : "", prefs.pgp_ring1 );
        runpgp( exec, 0, 1 );

        if( prefs.pgp_ring2[ 0 ] )
        {
                sprintf( exec, "-kv%s %s",  verbose ? "v" : "", prefs.pgp_ring2 );
                runpgp( exec, 0, 1 );
        }
}

void pgp_checkkeys( void )
{
        char exec[ 64 ];

        sprintf( exec, "-kc %s", prefs.pgp_ring1 );
        runpgp( exec, 0, 1 );

        if( prefs.pgp_ring2[ 0 ] )
        {
                sprintf( exec, "-kc %s", prefs.pgp_ring2 );
                runpgp( exec, 0, 1 );
        }
}

void pgp_changepassphrase( void )
{
        char tmp[ 256 ];

        sprintf( tmp, "-ke \"%s\"", prefs.pgp_userid );

        runpgp( tmp, 2, 0 );
}

void pgp_rereadownkey( void )
{
	pushhomedir();
	DeleteFile( "microdot.pgpkey" );
	popdir();
	pgp_init();
}
