#  Config.pm
#    - provide access to configuration parameters
#
#  Copyright (C) 2000 Frank J. Tobin <ftobin@uiuc.edu>
#
#  This file is part of pgpenvelope
#
#  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, visit the following URL:
#  http://www.gnu.org/copyleft/gpl.html
#
#  $Id: Config.pm,v 1.15 2001/05/07 23:38:48 ftobin Exp $
#

package PGPEnvelope::Config;

use strict;
use English;
use File::Copy;
use IO::File;
use File::Spec;

use AppConfig;

use PGPEnvelope::Common;

use Class::MakeMethods::Emulator::MethodMaker
  hash            => 'config_definitions',
  object          => [ 'AppConfig'  => {
					'slot'       => 'config',
					'comp_mthds' => [ 'get', 'getopt' ],
				       }
		     ],
  new_with_init   => 'new';


sub init
{
    my ( $self ) = @_;
    
    $self->config_definitions
      (
       'encryption-program'
       => PGPEnvelope::Config::Definition->new
       ( ALIAS    => 'EncryptionProgram',
	 ARGCOUNT => 1,
	 DEFAULT  => 'GnuPG',
       ),
       
       'decryption-program'
       => PGPEnvelope::Config::Definition->new
       ( ALIAS    => 'DecryptionProgram',
	 ARGCOUNT => 1,
	 DEFAULT  => 'GnuPG',
       ),
       
       'encryption-program-call'
       => PGPEnvelope::Config::Definition->new
       ( ALIAS    => 'EncryptionProgram',
	 ARGCOUNT => 1,
	 DEFAULT  => 'gpg',
       ),
       
       'decryption-program-call'
       => PGPEnvelope::Config::Definition->new
       ( ALIAS    => 'DecryptionProgram',
	 ARGCOUNT => 1,
	 DEFAULT  => 'gpg',
       ),
       
       'encrypt-to-recipients'
       => PGPEnvelope::Config::Definition->new
       ( ALIAS   => [ 'EncryptToRecipients', 'encrypt_to_recipients' ],
	 DEFAULT => 0,
       ),
       
       'sign-for-recipients'
       => PGPEnvelope::Config::Definition->new
       ( ALIAS   => 'SignForRecipients',
	 DEFAULT => 1,
       ),
       
       'encrypt-to-extra-key'
       => PGPEnvelope::Config::Definition->new
       ( ALIAS    => [ 'EncryptToExtraKeys', 'encrypt_to_extra_keys' ],
	 ARGCOUNT => AppConfig::ARGCOUNT_LIST,
       ),
       
       'ignore-revoked-keys'
       => PGPEnvelope::Config::Definition->new
       ( DEFAULT => 0 ),
       
       'ignore-disabled-keys'
       => PGPEnvelope::Config::Definition->new
       ( DEFAULT => 0 ),
       
       'ignore-expired-keys'
       => PGPEnvelope::Config::Definition->new
       ( DEFAULT => 0 ),
       
       'pgp-5-compatible'
       => PGPEnvelope::Config::Definition->new
       ( ALIAS   => [ 'PGP50compatible', 'pgp_50_compatible' ],
	 DEFAULT => 0,
       ),
       
       'comment'
       => PGPEnvelope::Config::Definition->new
       ( ARGCOUNT => 1,
	 DEFAULT  => join( ' ',
			   'pgpenvelope',
			   PGPEnvelope::Common->version(),
			   '- http://pgpenvelope.sourceforge.net/' ),
       ),
       
       'do-comment'
       => PGPEnvelope::Config::Definition->new
       ( DEFAULT => 1 ),
       
       'top-border'
       => PGPEnvelope::Config::Definition->new
       ( ALIAS    => [ 'TopBorder',
		       'ProcessedMessageTopBorder' ],
	 ARGCOUNT => 1,
	 DEFAULT  => '-----pgpenvelope processed message',
       ),
       
       'info-top-border'
       => PGPEnvelope::Config::Definition->new
       ( ALIAS    => [ 'InfoTopBorder',
		       'ProcessedMessageInformationTopBorder' ],
	 ARGCOUNT => 1,
	 DEFAULT  => '-----pgpenvelope information',
       ),
       
       'info-bottom-border'
       => PGPEnvelope::Config::Definition->new
       ( ALIAS   => [ 'InfoBottomBorder',
		      'ProcessedMessageInformationBottomBorder' ],
	 ARGCOUNT => 1,
	 DEFAULT => '-----end pgpenvelope information',
       ),
       
       'show-short-key-info'
       => PGPEnvelope::Config::Definition->new
       ( DEFAULT => 0 ),
       
       'confirm-decryption'
       => PGPEnvelope::Config::Definition->new
       ( DEFAULT => 0 ),
       
       'filter'
       => PGPEnvelope::Config::Definition->new
       ( DEFAULT => 0 ),
       
       'message-prefix-nullifier'
       => PGPEnvelope::Config::Definition->new
       ( ARGCOUNT => 1,
	 DEFAULT => '#####',
       ),

       'signing-key'
       => PGPEnvelope::Config::Definition->new
       ( ARGCOUNT => 1 ),

       'do-forgery-check'
       => PGPEnvelope::Config::Definition->new
       ( DEFAULT => 1 ),
       
       'forgery-warning'
       => PGPEnvelope::Config::Definition->new
       ( ARGCOUNT => 1,
         DEFAULT => '[WARNING: not from pgpenvelope]: ',
       ),

       'forgery-threshold'
       => PGPEnvelope::Config::Definition->new
       ( ARGCOUNT => 1,
         DEFAULT => '10%',
       ),
       
       'homedir'
       => PGPEnvelope::Config::Definition->new
       ( ARGCOUNT => 1,
	 DEFAULT =>  File::Spec->catdir( $ENV{HOME}, '.pgpenvelope' ),
       ),
       
       'version'
       => PGPEnvelope::Config::Definition->new
       ( DEFAULT => 0 ),

       'quiet'
       => PGPEnvelope::Config::Definition->new
       ( DEFAULT => 0 ),
       
      );
    
    # dump AppConfig module actually looks to see
    # if what I'm passing is a hash of hashrefs
    # It totally destroys being able to pass in things
    # that are blessed hashrefs
    foreach my $key ( $self->config_definitions_keys() )
    {
	$self->config->define( $key,
			       { %{ $self->config_definitions( $key ) } }
			     );
    }
}



sub parse_file
{
    my ( $self, $filename ) = @_;
    
    my $defaults_filename = "$filename.default";
    
    # check the version of the defaults file
    $self->generate_defaults_file( $defaults_filename )
      unless $self->version_check_file( $defaults_filename );
    
    # check for and parse the main prefs file if it is there
    $self->config->file( $filename ) if -e $filename;
}




sub version_check_file
{
    my ( $self, $filename ) = @_;
    
    return unless -e $filename;
    
    my $file = IO::File->new( $filename );
    
    unless ( $file )
    {
	warn "can't open $filename: $ERRNO";
	return;
    }
    
    chomp ( $_ = $file->getline() );
    $file->close;
    
    my $version = PGPEnvelope::Common->version();
    
    return /[\s\#]$version[\s\#]?/ ? 1 : 0;
}




sub generate_defaults_file
{
    my ( $self, $filename ) = @_;
    
    if ( -e $filename )
    {
	print "Copying old $filename to $filename.bak ...";
	print copy( $filename, "$filename.bak" ) ? "done\n" : "failed: $ERRNO\n";
    }
    
    print "Generating new $filename ... ";
    
    my $config_file = IO::File->new( ">$filename" );
    
    unless ( $config_file )
    {
	warn "Cannot create $filename: $ERRNO";
	return;
    }
    
    my %defs = $self->config_definitions();

    my $version = PGPEnvelope::Common->version();
    
    print $config_file <<EOF;
# $version
# Default-showing Configuration file for pgpenvelope $version
# As 'prefs.default', this file has no functionality.
# The file 'prefs' is what is read, and where changes should be made.

# These are names of the programs used for encrypting/decrypting.
# Currently only GnuPG is supported.

#encryption-program = $defs{'encryption-program'}->{DEFAULT}
#decryption-program = $defs{'decryption-program'}->{DEFAULT}

# These are the calls to the programs used for encryption/decrypting.
# These can be paths to the programs, or simply the program name,
# if they are in your path.  The rule of thumb is enter in here
# whatever you would type at the shell prompt.

#encryption-program-call = $defs{'encryption-program-call'}->{DEFAULT}
#decryption-program-call = $defs{'decryption-program-call'}->{DEFAULT}

# These are the default settings for the sending-menu.  These are
# boolean values.

#encrypt-to-recipients = $defs{'encrypt-to-recipients'}->{DEFAULT}
#sign-for-recipients   = $defs{'sign-for-recipients'}->{DEFAULT}

# This sets whether you want all outbound encrypted e-mails to be
# encrypted to a separate key.  This is useful so you can read
# your own sent encrypted mail.  To encrypt to multiple ids,
# repeat this entry for each id.  Don't use the following entries
# without changing the defaults!

#encrypt-to-extra-key = 0x334C9F14
#encrypt-to-extra-key = 0xABCD1234

# This sets which key by default you wish to use to sign messages with
#signing-key = 0xABCD1234

# This sets whether you want to ignore keys based on certain criteria.
# NOT-IMPLEMENTED YET!

#ignore-revoked-keys  = $defs{'ignore-revoked-keys'}->{DEFAULT}
#ignore-disabled-keys = $defs{'ignore-disabled-keys'}->{DEFAULT}
#ignore-expired-keys  = $defs{'ignore-expired-keys'}->{DEFAULT}

# This specificies whether you want GnuPG-created messages to be
# compatible with PGP 5.0(i), as PGP 5.0i is not OpenPGP-compatible.

#pgp-5-compatible = $defs{'pgp-5-compatible'}->{DEFAULT}

# This setting is what string, if any, put into the comment
# field of encrypted/signed messages.   This overrides any setting
# in GnuPG's configuration files.
# If you do not wish to have pgpenvelope set a comment,
# set do-comment to 0.  Please note that this means that you are
# leaving the decision up to GnuPG to set a comment.

#comment = $defs{comment}->{DEFAULT}
#do-comment = $defs{'do-comment'}->{DEFAULT}

# This specifies what sort of borders you want around GnuPG
# decryption/verification messages and information.

#top-border          = $defs{'top-border'}->{DEFAULT}
#info-top-border     = $defs{'info-top-border'}->{DEFAULT}
#info-bottom-Border  = $defs{'info-bottom-border'}->{DEFAULT}

# An attacker could try to send you a forged message that looks as
# though it had been passed through pgpenvelope_decrypt
# and been verified.
# If pgpenvelope_decrypt detects an input line matching any of your
# pgpenvelope message borders, it will prepend a warning message
# to those lines to warn you of a possible forgery unless you disable
# the forgery-warning option by setting do-forgery-check to 0.
# The match must be at least {forgery-threshold}% for the warning
# to trip.

#do-forgery-check  = $defs{'do-forgery-check'}->{DEFAULT}
#forgery-warning   = $defs{'forgery-warning'}->{DEFAULT}
#forgery-threshold = $defs{'forgery-threshold'}->{DEFAULT}

# This specifies if you only want to see the first uid and
# subkey information for keys to encrypt to when encrypting

#show-short-key-info = $defs{'show-short-key-info'}->{DEFAULT}

# Enabling this option will have pgpenvelope confirm that you
# wish to perform a message decryption when viewing messages
# which trigger pgpenvelope's decryption filter.

#confirm-decryption = $defs{'confirm-decryption'}->{DEFAULT}

# If you use confirm-decryption (above) to not process a message,
# a prefix needs to be added to OpenPGP message headers to
# prevent looping.  This defines that prefix.  Do not make this null.

#message-prefix-nullifier = $defs{'message-prefix-nullifier'}->{DEFAULT}
EOF
  
  print "done\n";
  return 1;
}


package PGPEnvelope::Config::Definition;

use strict;

use Class::MakeMethods::Emulator::MethodMaker
  get_set       => [ qw( ALIAS  DEFAULT  ARGCOUNT ) ],
  new_hash_init => 'new';


1;
