/* clearsign.c - show how to create a clearsign signature of a file
 *      Copyright (c) 1999 by Michael Roth <mroth@gnupg.org>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * MICHALE ROTH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Except as contained in this notice, the name of Michael Roth shall not be
 * used in advertising or otherwise to promote the sale, use or other dealings
 * in this Software without prior written authorization from Michael Roth.
 */


#include <stdio.h>
#include <string.h>
#include <pgg.h>


/*
 * This is the callback used by the PggPasscache. A PggPasscache manages
 * keyid->passphrase entries. This callback is used to ask the user a
 * passphrase of a specific keyid to fill the passcache when needed.
 */
int callback(PggPasscache pc, PggPasscache_CbCmd cmd, const char * keyid)
{
    char		buffer[256];
    char *		tmp;
    
    switch (cmd) {
        /*
         * The Passcache callback will be called with three different
         * events. Two of them are only for managing resources. In our
         * example the callback doesn't have to manage any resources, so
         * we don't need these events and simply ignore them.
         */
        case PGG_PASSCACHE_CBCMD_INIT:
        case PGG_PASSCACHE_CBCMD_RELEASE:
            break;
        
        /*
         * This is the event when used by the passcache asking for a passphrase
         * it doesn't have already. The callback can use any function of the
         * given PggPasscache object. However, the function which makes most
         * sense is pgg_passcache_set_passphrase() to set a new keyid->passphrase
         * association.
         * The callback can set none, one or more keyid->passphrase entries. This
         * doesn't matters because after a call to the callback with this event
         * the calling passcache simply try to find the passphrase for a keyid
         * a second time.
         */
        case PGG_PASSCACHE_CBCMD_ASK:
            printf("Enter passphrase for keyid 0x%s: ", keyid);
            
            fgets(buffer, 256, stdin);
            
            /*
             * Kill the trailing linefeed
             */
            if ((tmp = strchr(buffer, '\n') ))
                *tmp = 0;
            
            /*
             * If the user pressed only return, we don't set a passphrase of course.
             */    
            if (strlen(buffer) > 0)
                pgg_passcache_set_passphrase(pc, keyid, buffer, NULL);
            
            break;
    }
    
    return 0;	/* We don't return an error */
}


/*
 * This example show how to sign a file in clearsign mode. The output is
 * written in memory and then printed to stdout.
 */
int main(int argc, char *argv[])
{
    PggSign		sign = NULL;
    PggStdio		stdio = NULL;
    PggInput		input = NULL;
    PggOutput		output = NULL;
    PggBuffer		buffer = NULL;
    PggPasscache	passcache = NULL;
    PggErrenv		errenv;
    
    if (argc < 2 || argc > 3) {
        fprintf(stderr, "Usage: clearsign FILE [LOCAL-USER]\n");
        return 1;
    }
    
    pgg_errenv_reset(errenv);
    
    /*
     * As usual, a PggStdio object carries the source and destination
     * of data.
     */
    stdio = pgg_stdio_new(errenv);
    
    /*
     * In this example we use a filename as source
     */
    input = pgg_input_new(errenv);
    pgg_input_set_filename(input, argv[1], errenv);
    pgg_stdio_set_input(stdio, input, errenv);
    
    
    /*
     * The resulting signed data should be written to a memory chunk.
     * We use a PggBuffer object to store the resulting data and a
     * PggOutput object as "glue" between the PggStdio object and
     * the buffer.
     */
    buffer = pgg_buffer_new(errenv);
    output = pgg_output_new(errenv);
    pgg_output_set_buffer(output, buffer, errenv);
    pgg_stdio_set_output(stdio, output, errenv);
    
    
    /*
     * This is the cache for passphrases. We set our callback to ask
     * the user for the passphrase if one is needed. We couldn't
     * set the callback directly to the object which creates the
     * signature. Instead that object uses a PggPasscache object and
     * indirectly calls its callback if needed.
     */
    passcache = pgg_passcache_new(errenv);
    pgg_passcache_set_callback(passcache, callback, errenv);
    
    
    /*
     * This is the workhorse for creating signatures. We supply a
     * PggStdio object and a PggPasscache object. Additionally we
     * set the type of the signature we would like to have. If a second
     * argument was given on the command line, we set this argument
     * as the user as we wish to sign the data.
     */
    sign = pgg_sign_new(errenv);
    pgg_sign_set_stdio(sign, stdio, errenv);
    pgg_sign_set_passcache(sign, passcache, errenv);
    pgg_sign_set_mode(sign, PGG_SIGN_MODE_CLEARSIGN, errenv);
    if (argc == 3)
        pgg_sign_set_signer(sign, argv[2], errenv);
    
    
    /*
     * By calling pgg_sign_execute() all the magic happens. As usual this
     * call handle GnuPG in all known ways.
     */
    pgg_sign_execute(sign, errenv);
    
    
    /*
     * We would like to have a C string so we add a trailing 0 character
     * to the created output of the sign process.
     */
    pgg_buffer_append(buffer, "", 1, errenv);
    
    
    /*
     * Check if their was an error...
     */
    if (pgg_errenv_is_set(errenv)) {
        printf("An error occured\n");
        return 1;
    }
    
    
    /*
     * Print the result to stdout
     */
    printf("%s", (char *)pgg_buffer_get_data(buffer, NULL));
    
    
    /*
     * When the various Pgg Objects are no longer needed, don't forgett to
     * release them to prevent memory leaks. Because we are not interested
     * in errors caused by releasing objects we set the error environment
     * to NULL.
     */
    pgg_buffer_release(buffer, NULL);
    pgg_output_release(output, NULL);
    pgg_input_release(input, NULL);
    pgg_stdio_release(stdio, NULL);
    pgg_sign_release(sign, NULL);
    pgg_passcache_release(passcache, NULL);
    
    return 0;
}





