=head1 crypter

Diese Funktion ver- bzw. entschlüsselt einen Text.

=head2 Argumente

=over 4

=item *

Die Daten, als Stringvariable.

=item *

Das Password.

=item *

Flag:

=over 4

=item 1

Entschlüsseln.

=item 2

Verschlüsseln.

=back

=back

=head2 TODO

Public Key. Momentan wird nur symmetrisch verschlüsselt.

=cut

use utf8;
use strict;
use warnings; no warnings "redefine";

use Dbase::Globals qw(explain_child_error);
use Fehler qw(fehler);
use IO::Pipe;
use POSIX qw(_exit);
use Loader qw(check_gpg);
use Umlaut qw(binmodus);
use UTFkram qw(safe_encode_utf8 decode_anything);

sub crypter($$$) {
	local $^F = 999;
	my($data,$pw,$flag) = @_;
	$flag=0 unless defined $flag;

	check_gpg();

	my $what;
	if($flag & 1) {
		fehler "Flag&3" if $flag & 2; # beides geht nicht
		$what = '-d';
	} elsif($flag & 2) {
		$what = '-c';
	} else {
		fehler "Modus '$flag' unbekannt.\n";
		return undef;
	}

	local $^F = 999;
	my $pass = new IO::Pipe;
	my $dat1 = new IO::Pipe;
	my $dat2 = new IO::Pipe;
	my $pid = fork();
	fehler "Cannot fork: $!\n" unless defined $pid;
	
	unless($pid) {
		$pass->reader;
		$dat1->reader;
		$dat2->writer;

		use POSIX 'dup2';
		dup2($dat1->fileno,0);
		dup2($dat2->fileno,1);
		$dat1->close;
		$dat2->close;

		exec("gpg",$what,"--no-secmem-warning","--yes","--batch","--passphrase-fd=".$pass->fileno);
		die "No GPG: $!\n";
	}
	$pass->writer;
	$dat1->writer;
	$dat2->reader;

	binmodus($pass);
	print $pass safe_encode_utf8($pw);
	$pass->close;

	my $xpid = fork();
	fehler "Cannot fork: $!\n" unless defined $xpid;

	binmodus($dat1);
	binmodus($dat2);

	unless($xpid) {
		$data = safe_encode_utf8($data) if $flag & 2;
		print $dat1 $data;
		$dat1->close;
		_exit(0);
	}
	$dat1->close;

	{
		local $/ = undef;
		$data = <$dat2>;
		$data = decode_anything($data) if $flag & 1;
	}
	$dat2->close;
	waitpid($xpid,0);
	fehler( explain_child_error() ) if $?;
	waitpid($pid,0);
	fehler( explain_child_error() ) if $?;
	$data;
}

1;
