[Rt-commit] r7606 - in rt/branches/3.7-EXPERIMENTAL: .

ruz at bestpractical.com ruz at bestpractical.com
Sat Apr 21 22:24:38 EDT 2007


Author: ruz
Date: Sat Apr 21 22:24:37 2007
New Revision: 7606

Modified:
   rt/branches/3.7-EXPERIMENTAL/   (props changed)
   rt/branches/3.7-EXPERIMENTAL/lib/RT/Crypt/GnuPG.pm

Log:
 r5061 at cubic-pc:  cubic | 2007-04-22 06:23:05 +0400
 * preparse recipients
 * encrypt/sign attachments inline


Modified: rt/branches/3.7-EXPERIMENTAL/lib/RT/Crypt/GnuPG.pm
==============================================================================
--- rt/branches/3.7-EXPERIMENTAL/lib/RT/Crypt/GnuPG.pm	(original)
+++ rt/branches/3.7-EXPERIMENTAL/lib/RT/Crypt/GnuPG.pm	Sat Apr 21 22:24:37 2007
@@ -67,7 +67,7 @@
     local *STDERR = $stderr;
 
     local @ENV{'LANG', 'LC_ALL'} = ('C', 'C');
-    shift->();
+    return shift->();
 }
 
 sub SignEncrypt {
@@ -224,7 +224,7 @@
         );
         $entity->parts(-1)->bodyhandle->{'_dirty_hack_to_save_a_ref_tmp_fh'} = $tmp_fh;
     }
-    %res;
+    return %res;
 }
 
 sub SignEncryptInline {
@@ -234,6 +234,14 @@
     if ( $args{'Sign'} && !defined $args{'Signer'} ) {
         $args{'Signer'} = (Mail::Address->parse( $entity->head->get( 'From' ) ))[0]->address;
     }
+    if ( $args{'Encrypt'} && !$args{'Recipients'} ) {
+        my %seen;
+        $args{'Recipients'} = [
+            grep $_ && !$seen{ $_ }++, map $_->address,
+            map Mail::Address->parse( $entity->head->get( $_ ) ),
+            qw(To Cc Bcc)
+        ];
+    }
 
     my %res;
 
@@ -255,10 +263,14 @@
 sub _SignEncryptTextInline {
     my %args = (
         Entity => undef,
-        Encrypt => 1,
+
         Sign => 1,
         Signer => undef,
         Passphrase => undef,
+
+        Encrypt => 1,
+        Recipients => undef,
+
         @_
     );
     return unless $args{'Sign'} || $args{'Encrypt'};
@@ -279,11 +291,16 @@
 
     my $entity = $args{'Entity'};
     if ( $args{'Encrypt'} ) {
-        my %seen;
-        $gnupg->options->push_recipients( $_ )
-            foreach grep $_ && !$seen{ $_ }++, map $_->address,
-                map Mail::Address->parse( $entity->head->get( $_ ) ),
-                qw(To Cc Bcc);
+        unless ( $args{'Recipients'} ) {
+            my %seen;
+            $gnupg->options->push_recipients( $_ )
+                foreach grep $_ && !$seen{ $_ }++, map $_->address,
+                    map Mail::Address->parse( $entity->head->get( $_ ) ),
+                    qw(To Cc Bcc);
+        } else {
+            $gnupg->options->push_recipients( $_ )
+                foreach @{ $args{'Recipients'} };
+        }
     }
 
     my %res;
@@ -335,6 +352,109 @@
 }
 
 sub _SignEncryptAttachmentInline {
+    my %args = (
+        Entity => undef,
+
+        Sign => 1,
+        Signer => undef,
+        Passphrase => undef,
+
+        Encrypt => 1,
+        Recipients => undef,
+
+        @_
+    );
+    return unless $args{'Sign'} || $args{'Encrypt'};
+
+    if ( $args{'Sign'} && !defined $args{'Passphrase'} ) {
+        $args{'Passphrase'} = GetPassphrase();
+    }
+
+    my $gnupg = new GnuPG::Interface;
+    my %opt = RT->Config->Get('GnuPGOptions');
+    $opt{'digest-algo'} ||= 'SHA1';
+    $gnupg->options->hash_init(
+        _PrepareGnuPGOptions( %opt ),
+        armor => 1,
+        meta_interactive => 0,
+        ( $args{'Sign'} && $args{'Signer'}? (default_key => $args{'Signer'}): () ),
+    );
+
+    my $entity = $args{'Entity'};
+    if ( $args{'Encrypt'} ) {
+        unless ( $args{'Recipients'} ) {
+            my %seen;
+            $gnupg->options->push_recipients( $_ )
+                foreach grep $_ && !$seen{ $_ }++, map $_->address,
+                    map Mail::Address->parse( $entity->head->get( $_ ) ),
+                    qw(To Cc Bcc);
+        } else {
+            $gnupg->options->push_recipients( $_ )
+                foreach @{ $args{'Recipients'} };
+        }
+    }
+
+    my %res;
+
+    my ($tmp_fh, $tmp_fn) = File::Temp::tempfile();
+    binmode $tmp_fh, ':raw';
+
+    my %handle;
+    my $handles = GnuPG::Handles->new(
+        stdin  => ($handle{'input'}  = new IO::Handle),
+        stdout => $tmp_fh,
+        stderr => ($handle{'error'}  = new IO::Handle),
+        logger => ($handle{'logger'} = new IO::Handle),
+        status => ($handle{'status'} = new IO::Handle),
+    );
+    $handles->options( 'stdout'  )->{'direct'} = 1;
+    $gnupg->passphrase( $args{'Passphrase'} ) if $args{'Sign'};
+
+    eval {
+        local $SIG{'CHLD'} = 'DEFAULT';
+        my $method = $args{'Sign'} && $args{'Encrypt'}
+            ? 'sign_and_encrypt'
+            : ($args{'Sign'}? 'detach_sign': 'encrypt');
+        my $pid = _safe_run_child { $gnupg->$method( handles => $handles ) };
+        $entity->bodyhandle->print( $handle{'input'} );
+        close $handle{'input'};
+        waitpid $pid, 0;
+    };
+    $res{'exit_code'} = $?;
+    my $err = $@;
+
+    foreach ( qw(error logger status) ) {
+        $res{$_} = do { local $/; readline $handle{$_} };
+        delete $res{$_} unless $res{$_} && $res{$_} =~ /\S/s;
+        close $handle{$_};
+    }
+    $RT::Logger->debug( $res{'status'} ) if $res{'status'};
+    $RT::Logger->warning( $res{'error'} ) if $res{'error'};
+    $RT::Logger->error( $res{'logger'} ) if $res{'logger'} && $?;
+    if ( $err || $res{'exit_code'} ) {
+        $res{'message'} = $err? $err : "gpg exitted with error code ". ($res{'exit_code'} >> 8);
+        return %res;
+    }
+
+    my $filename = $entity->head->recommended_filename || 'no_name';
+    if ( $args{'Sign'} && !$args{'Encrypt'} ) {
+        $entity->make_multipart;
+        $entity->attach(
+            Type     => 'application/octeat-stream',
+            Path     => $tmp_fn,
+            Filename => "$filename.sig",
+            Disposition => 'attachment',
+        );
+    } else {
+        $entity->bodyhandle( new MIME::Body::File $tmp_fn );
+        $entity->effective_type('application/octeat-stream');
+        $args{'Data'}->head->mime_attr( $_ => "$filename.pgp" )
+            foreach (qw(Content-Type.name Content-Disposition.filename));
+
+    }
+    $entity->{'__store_tmp_handle_to_avoid_early_cleanup'} = $tmp_fh;
+
+    return %res;
 
 }
 


More information about the Rt-commit mailing list