#!/usr/bin/perl
##---------------------------------------------------------------------------##
##  File:
##	$Id: mha-p7m,v 1.1 2011/01/02 11:14:55 ehood Exp $
##  Author:
##      Earl Hood       earl@earlhood.com
##  Description:
##      Front-end to mhonarc to support processing application/x-pkcs7-mime
##      signed messages.
##
##      More Info:
##      <http://www.mhonarc.org/archive/cgi-bin/mesg.cgi?a=mhonarc-users&i=4c798002.c61fe70a.1893.5ea8%40mx.google.com>
##---------------------------------------------------------------------------##
##    Copyright (C) 2010	Earl Hood, earl@earlhood.com
##    This program is free software; you can redistribute it and/or modify
##    it under the same terms as MHonArc itself.
##---------------------------------------------------------------------------##

# Modify the following to specify pathname to mhonarc libraries.
use lib qw( /usr/lib/MHonArc );

use Symbol;
use File::Temp;

# Set to pathname of openssl executable.
my $openssl = 'openssl';

my @argv = @ARGV;
require 'mhamain.pl' || die qq/ERROR: Unable to require "mhamain.pl"\n/;

# Variable that holds the raw header text of the current message
my $current_header_txt = '';

#$mhonarc::Debug = 1;
&mhonarc::initialize();

# Message head callback function to capture raw header text.
# This is needed so we can print it out to temp file when openssl
# is used to extract signed message
#
$mhonarc::CBMessageHeadRead = sub {
    my $fields = shift;
    $current_header_txt = shift;
    $current_header_txt .= "\n";
};

# Raw message body read callback: If application/x-pkcs7-mime signed
# data, openssl used to extract contents and then we replace
# body variable to extracted contents for mhonarc to parse and archive.
#
$mhonarc::CBRawMessageBodyRead = sub {
    my $fields   = shift;
    my $data_ref = shift;
    my $ctype    = $fields->{'content-type'}[0];

    # If not signed-data, we return immediately
    if (  !$ctype
        || $ctype !~ m{application/x-pkcs7-mime}
        || $ctype !~ m{signed-data}) {
        return 1;
    }

    # Get here, use openssl to extract main data.

    # Write input data to temp file for use by openssl.
    my $tmp = new File::Temp();
    syswrite($tmp, $current_header_txt);    # openssl requires mail headers
    syswrite($tmp, $$data_ref);

    # Open pipe to openssl to extract the data: The command-line
    # options to make this work is non-intuitive.  Luckily, I found
    # a page on the web that listed the right options for extracting
    # the content w/o the need to validate the signature.
    my $handle = gensym;
    mhonarc::cmd_pipe_open($handle, $openssl, 'smime', '-verify',
        '-in', $tmp->filename, '-noverify');
    my $new_data = join('', <$handle>);
    close($handle);
    close($tmp);

    # Parse the sub-header from extracted data and update
    # main fields to use them over original fields.
    my ($sub_header, $txt) = readmail::MAILread_header(\$new_data);
    foreach my $key (keys %$sub_header) {
        $fields->{$key} = $sub_header->{$key};
    }
    if ($sub_header->{'content-type'}) {
        # Make sure update mhonarc's meta field for content-type
        my $ctype = $sub_header->{'content-type'}[0];
        if ($ctype =~ m%^\s*([\w\-\./]+)%) {
            $fields->{'x-mha-content-type'} = $1;
        }
    }
    # IMPORTANT: Make sure CTE is adjusted to reflect extracted data
    if (!$sub_header->{'content-transfer-encoding'}) {
        $fields->{'content-transfer-encoding'} = ['7bit'];
    }

    # Replace message data to what was extracted and let mhonarc parse it.
    $$data_ref = $new_data;

    return 1;
};

&mhonarc::process_input(@argv);
