/usr/local/CPAN/Brackup/Brackup/Decrypt.pm


package Brackup::Decrypt;

use strict;
use warnings;
use Carp qw(croak);
use Brackup::Util qw(slurp tempfile);

# Decrypt a dataref into a dataref
sub decrypt_data {
    my ($dataref, %opts) = @_;

    my $meta = $opts{meta};

    # do nothing if the data is not encrypted
    return $dataref unless $meta && $meta->{"GPG-Recipient"};

    my $dataref_temp    = ( (tempfile())[1] || die );
    write_to_file($dataref_temp, $dataref);

    my $decrypted_temp = decrypt_file($dataref_temp,%opts);
    unlink($dataref_temp);

    my $data = slurp($decrypted_temp);
    unlink($decrypted_temp);

    return \$data;
}

sub write_to_file {
    my ($file, $ref) = @_;
    open (my $fh, '>', $file) or die "Failed to open $file for writing: $!\n";
    print $fh $$ref;
    close($fh) or die;
    die "File is not of the correct size" unless -s $file == length $$ref;
    return 1;
}

sub decrypt_file_if_needed {
    my ($filename) = @_;

    my $meta = slurp($filename, decompress => 1);
    if ($meta =~ /[\x00-\x08]/) {  # silly is-binary heuristic
        my $new_file = decrypt_file($filename,no_batch => 1);
        if (defined $new_file) {
          warn "Decrypted ${filename} to ${new_file}.\n";
        }
        return $new_file;
    }
    return undef;
}

# Decrypt a file into a new file
# Return the new file's name, or undef.

our $warned_about_gpg_agent = 0;

sub decrypt_file {
  my ($encrypted_file,%opts) = @_;

  my $no_batch = delete $opts{no_batch};
  my $meta     = delete $opts{meta};
  croak("Unknown options: " . join(', ', keys %opts)) if %opts;

  # find which key we're using to decrypt it
  if ($meta) {
      my $rcpt = $meta->{"GPG-Recipient"} or
          return undef;
  }

  unless ($ENV{'GPG_AGENT_INFO'} ||
          @Brackup::GPG_ARGS ||
          $warned_about_gpg_agent++)
  {
      my $err = q{
                                            #
                                            # WARNING: trying to restore encrypted files,
                                            # but $ENV{'GPG_AGENT_INFO'} not present.
                                            # Are you running gpg-agent?
                                            #
                                    };
      $err =~ s/^\s+//gm;
      warn $err;
  }

  my $output_temp = ( (tempfile())[1] || die );

  my @list = ("gpg", @Brackup::GPG_ARGS,
              "--use-agent",
              !$opts{no_batch} ? ("--batch") : (),
              "--trust-model=always",
              "--output",  $output_temp,
              "--yes", "--quiet",
              "--decrypt", $encrypted_file);
  system(@list)
      and die "Failed to decrypt with gpg: $!\n";

  return $output_temp;
}

1;