package Test::Qpsmtpd::Plugin;
1;

# Additional plugin methods used during testing
package Qpsmtpd::Plugin;

use strict;
use warnings;

use Qpsmtpd::Constants;
use Test::More;

sub register_tests {
    # Virtual base method - implement in plugin
}

sub register_test {
    my ($plugin, $test, $num_tests) = @_;
    $num_tests = 1 unless defined($num_tests);
    # print STDERR "Registering test $test ($num_tests)\n";
    push @{$plugin->{_tests}}, { name => $test, num => $num_tests };
}

sub total_tests {
    my ($plugin) = @_;
    my $total = 0;
    foreach my $t (@{$plugin->{_tests}}) {
        $total += $t->{num};
    }
    return $total;
}

sub run_tests {
    my ($plugin, $qp) = @_;
    foreach my $t (@{$plugin->{_tests}}) {
        my $method = $t->{name};
        print "# Running $method tests for plugin " . $plugin->plugin_name . "\n";
        local $plugin->{_qp} = $qp;
        $plugin->$method();
    }
}

sub validate_password {
    my ( $self, %a ) = @_;

    my ($pkg, $file, $line) = caller();

    my $src_clear     = $a{src_clear};
    my $src_crypt     = $a{src_crypt};
    my $attempt_clear = $a{attempt_clear};
    my $attempt_hash  = $a{attempt_hash};
    my $method        = $a{method} or die "missing method";
    my $ticket        = $a{ticket};
    my $deny          = $a{deny} || DENY;

    if ( ! $src_crypt && ! $src_clear ) {
        $self->log(LOGINFO, "fail: missing password");
        return ( $deny, "$file - no such user" );
    };

    if ( ! $src_clear && $method =~ /CRAM-MD5/i ) {
        $self->log(LOGINFO, "skip: cram-md5 not supported w/o clear pass");
        return ( DECLINED, $file );
    }

    if ( defined $attempt_clear ) {
        if ( $src_clear && $src_clear eq $attempt_clear ) {
            $self->log(LOGINFO, "pass: clear match");
            return ( OK, $file );
        };

        if ( $src_crypt && $src_crypt eq crypt( $attempt_clear, $src_crypt ) ) {
            $self->log(LOGINFO, "pass: crypt match");
            return ( OK, $file );
        }
    };

    if ( defined $attempt_hash && $src_clear ) {
        if ( ! $ticket ) {
            $self->log(LOGERROR, "skip: missing ticket");
            return ( DECLINED, $file );
        };

        if ( $attempt_hash eq hmac_md5_hex( $ticket, $src_clear ) ) {
            $self->log(LOGINFO, "pass: hash match");
            return ( OK, $file );
        };
    };

    $self->log(LOGINFO, "fail: wrong password");
    return ( $deny, "$file - wrong password" );
};

1;