New fix for the problem of End-of-data splitted across packets.

Previous fix does not work for other cases, for example: packet ends
with CRLFdot, next packet starts with CRLF.

Danga::Client will send now full text lines to the callback.

git-svn-id: https://svn.perl.org/qpsmtpd/trunk@878 958fd67b-6ff1-0310-b445-bb7760255be9
This commit is contained in:
Radu Greab 2008-05-01 06:15:32 +00:00
parent 90e60d3d4f
commit 8dda36cf02
2 changed files with 24 additions and 11 deletions

View File

@ -54,6 +54,26 @@ sub get_bytes {
$self->{callback} = $callback; $self->{callback} = $callback;
} }
sub process_chunk {
my Danga::Client $self = shift;
my $callback = shift;
my $last_crlf = rindex($self->{line}, "\r\n");
if ($last_crlf != -1) {
if ($last_crlf + 2 == length($self->{line})) {
my $data = $self->{line};
$self->{line} = '';
$callback->($data);
}
else {
my $data = substr($self->{line}, 0, $last_crlf + 2);
$self->{line} = substr($self->{line}, $last_crlf + 2);
$callback->($data);
}
}
}
sub get_chunks { sub get_chunks {
my Danga::Client $self = shift; my Danga::Client $self = shift;
my ($bytes, $callback) = @_; my ($bytes, $callback) = @_;
@ -61,8 +81,7 @@ sub get_chunks {
die "get_bytes/get_chunks currently in progress!"; die "get_bytes/get_chunks currently in progress!";
} }
$self->{read_bytes} = $bytes; $self->{read_bytes} = $bytes;
$callback->($self->{line}) if length($self->{line}); $self->process_chunk($callback) if length($self->{line});
$self->{line} = '';
$self->{callback} = $callback; $self->{callback} = $callback;
$self->{get_chunks} = 1; $self->{get_chunks} = 1;
} }
@ -84,7 +103,8 @@ sub event_read {
if ($self->{get_chunks}) { if ($self->{get_chunks}) {
my $bref = $self->read($self->{read_bytes}); my $bref = $self->read($self->{read_bytes});
return $self->close($!) unless defined $bref; return $self->close($!) unless defined $bref;
$self->{callback}->($$bref) if length($$bref); $self->{line} .= $$bref;
$self->process_chunk($self->{callback}) if length($self->{line});
return; return;
} }
if ($self->{read_bytes} > 0) { if ($self->{read_bytes} > 0) {

View File

@ -16,7 +16,6 @@ use fields qw(
start_time start_time
cmd_timeout cmd_timeout
conn conn
prev_crlf
_auth _auth
_auth_mechanism _auth_mechanism
_auth_state _auth_state
@ -209,7 +208,6 @@ sub data_respond {
$self->{header_lines} = ''; $self->{header_lines} = '';
$self->{data_size} = 0; $self->{data_size} = 0;
$self->{in_header} = 1; $self->{in_header} = 1;
$self->{prev_crlf} = 0;
$self->{max_size} = ($self->config('databytes'))[0] || 0; $self->{max_size} = ($self->config('databytes'))[0] || 0;
$self->log(LOGDEBUG, "max_size: $self->{max_size} / size: $self->{data_size}"); $self->log(LOGDEBUG, "max_size: $self->{max_size} / size: $self->{data_size}");
@ -227,18 +225,13 @@ sub got_data {
my $done = 0; my $done = 0;
my $remainder; my $remainder;
if ($data =~ s/\r\n\.\r\n(.*)\z/\r\n/ms if ($data =~ s/^\.\r\n(.*)\z//ms) {
||
($self->{prev_crlf} && $data =~ s/^\.\r\n(.*)\z//ms)
)
{
$remainder = $1; $remainder = $1;
$done = 1; $done = 1;
} }
# add a transaction->blocked check back here when we have line by line plugin access... # add a transaction->blocked check back here when we have line by line plugin access...
unless (($self->{max_size} and $self->{data_size} > $self->{max_size})) { unless (($self->{max_size} and $self->{data_size} > $self->{max_size})) {
$self->{prev_crlf} = $data =~ /\r\n\z/;
$data =~ s/\r\n/\n/mg; $data =~ s/\r\n/\n/mg;
$data =~ s/^\.\./\./mg; $data =~ s/^\.\./\./mg;