sub now () { clock_gettime(CLOCK_MONOTONIC) };
-my @OVERVIEW = qw(Subject From Date Message-ID References);
+my @OVERVIEW = qw(Subject From Date Message-ID References Xref);
my $OVERVIEW_FMT = join(":\r\n", @OVERVIEW, qw(Bytes Lines)) . ":\r\n";
my $LIST_HEADERS = join("\r\n", @OVERVIEW,
qw(:bytes :lines Xref To Cc)) . "\r\n";
my $self = fields::new($class);
$self->SUPER::new($sock);
$self->{nntpd} = $nntpd;
- res($self, '201 server ready - post via email');
+ res($self, '201 ' . $nntpd->{servername} . ' ready - post via email');
$self->{rbuf} = '';
$self->watch_read(1);
update_idle_time($self);
sub process_line ($$) {
my ($self, $l) = @_;
my ($req, @args) = split(/\s+/, $l);
+ return unless defined($req);
$req = lc($req);
$req = eval {
no strict 'refs';
sub xref ($$$$) {
my ($self, $ng, $n, $mid) = @_;
- my $ret = "$ng->{domain} $ng->{newsgroup}:$n";
+ my $ret = $self->{nntpd}->{servername} . " $ng->{newsgroup}:$n";
# num_for is pretty cheap and sometimes we'll lookup the existence
# of an article without getting even the OVER info. In other words,
});
}
-sub over_line ($$) {
- my ($num, $smsg) = @_;
+sub over_line ($$$$) {
+ my ($self, $ng, $num, $smsg) = @_;
# n.b. field access and procedural calls can be
# 10%-15% faster than OO method calls:
my $s = join("\t", $num,
"<$smsg->{mid}>",
$smsg->{references},
$smsg->{bytes},
- $smsg->{lines});
+ $smsg->{lines},
+ "Xref: " . xref($self, $ng, $num, $smsg->{mid}));
utf8::encode($s);
$s
}
# Only set article number column if it's the current group
my $self_ng = $self->{ng};
$n = 0 if (!$self_ng || $self_ng ne $ng);
- more($self, over_line($n, $smsg));
+ more($self, over_line($self, $ng, $n, $smsg));
'.';
} else {
cmd_xover($self, $range);
# OVERVIEW.FMT
more($self, join("\r\n", map {
- over_line($_->{num}, $_);
+ over_line($self, $self->{ng}, $_->{num}, $_);
} @$msgs));
$cur = $msgs->[-1]->{num} + 1;
});
sub event_read {
my ($self) = @_;
use constant LINE_MAX => 512; # RFC 977 section 2.3
- my $r = 1;
- my $buf = $self->read(LINE_MAX) or return $self->close;
- $self->{rbuf} .= $$buf;
- while ($r > 0 && $self->{rbuf} =~ s/\A\s*([^\r\n]+)\r?\n//) {
+ if (index($self->{rbuf}, "\n") < 0) {
+ my $buf = $self->read(LINE_MAX) or return $self->close;
+ $self->{rbuf} .= $$buf;
+ }
+ my $r = 1;
+ while ($r > 0 && $self->{rbuf} =~ s/\A\s*([^\r\n]*)\r?\n//) {
my $line = $1;
return $self->close if $line =~ /[[:cntrl:]]/s;
my $t0 = now();
sub watch_read {
my ($self, $bool) = @_;
my $rv = $self->SUPER::watch_read($bool);
- if ($bool && $self->{rbuf} ne '') {
+ if ($bool && index($self->{rbuf}, "\n") >= 0) {
# Force another read if there is a pipelined request.
# We don't know if the socket has anything for us to read,
# and we must double-check again by the time the timer fires