Net-Doveadm

 view release on metacpan or  search on metacpan

lib/Net/Doveadm.pm  view on Meta::CPAN

        return $self if !$self->_do_handshake();
    }

    $self->_flush_request_queue();

    return $self;
}

sub _validate_command_pieces {
    my ($username, $command_ar) = @_;

    for my $piece ($username, @$command_ar) {
        if ($piece =~ tr<\t\x0a><>) {
            die Net::Doveadm::X->create('Generic', "Invalid string in command: “$piece”");
        }
    }

    return;
}

#----------------------------------------------------------------------

=head2 $RESULT = I<OBJ>->receive()

Looks for a response to a previously-sent command. If such a response is
ready,
it will be returned as an array reference; otherwise, undef is returned.

Note that, if the server handshake is not yet complete, this will
attempt to finish that before actually trying to retrieve a message.

=cut

sub receive {
    my ($self) = @_;

    if (!$self->{'_handshake_done'}) {
        return undef if !$self->_do_handshake();

        # If we just finished the handshake, then send any pending requests
        # before we see about responses to them.
        $self->_flush_request_queue();
    }

    if ( !@{ $self->{'_requests'} } && !$self->{'_sent_requests'} ) {
        die Net::Doveadm::X->create('Generic', "No requests pending!");
    }

    $self->{'_line1'} ||= $self->_read_line() or return undef;

    $self->{'_line2'} ||= $self->_read_line() or return undef;

    $self->{'_sent_requests'}--;

    my ($line1, $line2) = delete @{$self}{'_line1', '_line2'};

    if ($line2 ne '+') {
        die Net::Doveadm::X->create('Response', "Error: $line2 ($line1)");
    }

    return [ split m<\t>, $line1, -1 ];
}

#----------------------------------------------------------------------

sub _flush_request_queue {
    my ($self) = @_;

    while ($self->_write($self->{'_requests'}[0])) {
        shift @{ $self->{'_requests'} };
        $self->{'_sent_requests'}++;
    }

    return;
}

sub _do_handshake {
    my ($self) = @_;

    if (!$self->{'_sent_hello'}) {
        $self->_write( [ 'VERSION', 'doveadm-server', 1, 0 ] );
        $self->{'_sent_hello'} = 1;
        return undef;
    }

    $self->{'_received_hello'} ||= $self->_read_line() or return undef;

    if ($self->{'_received_hello'} eq '+') {
        $self->{'_handshake_done'} = 1;

        for my $key ( qw( username  password ) ) {
            if ($self->{"_$key"}) {
                warn "“$key” submitted, but server says unneeded.";
            }
        }
    }
    elsif ($self->{'_received_hello'} eq '-') {

        if (!$self->{'_authn_sent'}) {
            $self->_send_authn();

            $self->{'_authn_sent'} = 1;

            return undef;
        }

        $self->{'_received_authn'} ||= $self->_read_line() or return undef;

        if ($self->{'_received_authn'} eq '+') {

            $self->{'_handshake_done'} = 1;
        }
        else {
            die Net::Doveadm::X->create('Authn', "Failed authn: “$self->{'_received_authn'}”");
        }
    }

    return 1;
}

sub _send_authn {



( run in 0.592 second using v1.01-cache-2.11-cpan-71847e10f99 )