X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FNNTP.pm;h=aea04c05464b28b30d5e8d7a713e5da0446c9282;hb=5c8909925072804901e9c3b45bbf25446d379e7b;hp=e0916011902e6279c8f07db86bdf4b22cf6c0526;hpb=82ffb3c183ac20e00effa8a5a7b664eda59672de;p=public-inbox.git diff --git a/lib/PublicInbox/NNTP.pm b/lib/PublicInbox/NNTP.pm index e0916011..aea04c05 100644 --- a/lib/PublicInbox/NNTP.pm +++ b/lib/PublicInbox/NNTP.pm @@ -1,11 +1,11 @@ -# Copyright (C) 2015-2020 all contributors +# Copyright (C) 2015-2021 all contributors # License: AGPL-3.0+ # # Each instance of this represents a NNTP client socket # fields: # nntpd: PublicInbox::NNTPD ref # article: per-session current article number -# ng: PublicInbox::Inbox ref +# ibx: PublicInbox::Inbox ref # long_cb: long_response private data package PublicInbox::NNTP; use strict; @@ -129,7 +129,7 @@ sub list_active_i { # "LIST ACTIVE" and also just "LIST" (no args) my ($self, $groupnames) = @_; my @window = splice(@$groupnames, 0, 100) or return 0; my $ibx; - my $groups = $self->{nntpd}->{pi_config}->{-by_newsgroup}; + my $groups = $self->{nntpd}->{pi_cfg}->{-by_newsgroup}; for my $ngname (@window) { $ibx = $groups->{$ngname} and group_line($self, $ibx); } @@ -146,7 +146,7 @@ sub list_active ($;$) { # called by cmd_list sub list_active_times_i { my ($self, $groupnames) = @_; my @window = splice(@$groupnames, 0, 100) or return 0; - my $groups = $self->{nntpd}->{pi_config}->{-by_newsgroup}; + my $groups = $self->{nntpd}->{pi_cfg}->{-by_newsgroup}; for my $ngname (@window) { my $ibx = $groups->{$ngname} or next; my $c = eval { $ibx->uidvalidity } // time; @@ -165,7 +165,7 @@ sub list_active_times ($;$) { # called by cmd_list sub list_newsgroups_i { my ($self, $groupnames) = @_; my @window = splice(@$groupnames, 0, 100) or return 0; - my $groups = $self->{nntpd}->{pi_config}->{-by_newsgroup}; + my $groups = $self->{nntpd}->{pi_cfg}->{-by_newsgroup}; my $ibx; for my $ngname (@window) { $ibx = $groups->{$ngname} and @@ -202,15 +202,15 @@ sub cmd_list ($;$$) { sub listgroup_range_i { my ($self, $beg, $end) = @_; - my $r = $self->{ng}->mm->msg_range($beg, $end, 'num'); + my $r = $self->{ibx}->mm(1)->msg_range($beg, $end, 'num'); scalar(@$r) or return; - more($self, join("\r\n", map { $_->[0] } @$r)); + $self->msg_more(join('', map { "$_->[0]\r\n" } @$r)); 1; } sub listgroup_all_i { my ($self, $num) = @_; - my $ary = $self->{ng}->mm->ids_after($num); + my $ary = $self->{ibx}->mm(1)->ids_after($num); scalar(@$ary) or return; more($self, join("\r\n", @$ary)); 1; @@ -223,7 +223,7 @@ sub cmd_listgroup ($;$$) { return $res if ($res !~ /\A211 /); more($self, $res); } - $self->{ng} or return '412 no newsgroup selected'; + $self->{ibx} or return '412 no newsgroup selected'; if (defined $range) { my $r = get_range($self, $range); return $r unless ref $r; @@ -241,7 +241,7 @@ sub parse_time ($$;$) { $gmt = 1; } my ($YYYY, $MM, $DD); - if (bytes::length($date) == 8) { # RFC 3977 allows YYYYMMDD + if (length($date) == 8) { # RFC 3977 allows YYYYMMDD ($YYYY, $MM, $DD) = unpack('A4A2A2', $date); } else { # legacy clients send YYMMDD my $YY; @@ -260,15 +260,15 @@ sub parse_time ($$;$) { } sub group_line ($$) { - my ($self, $ng) = @_; - my ($min, $max) = $ng->mm->minmax; - more($self, "$ng->{newsgroup} $max $min n"); + my ($self, $ibx) = @_; + my ($min, $max) = $ibx->mm(1)->minmax; + more($self, "$ibx->{newsgroup} $max $min n"); } sub newgroups_i { my ($self, $ts, $i, $groupnames) = @_; my $end = $$i + 100; - my $groups = $self->{nntpd}->{pi_config}->{-by_newsgroup}; + my $groups = $self->{nntpd}->{pi_cfg}->{-by_newsgroup}; while ($$i < $end) { my $ngname = $groupnames->[$$i++] // return; my $ibx = $groups->{$ngname} or next; # expired on reload @@ -323,14 +323,13 @@ sub ngpat2re (;$) { sub newnews_i { my ($self, $names, $ts, $prev) = @_; my $ngname = $names->[0]; - if (my $ibx = $self->{nntpd}->{pi_config}->{-by_newsgroup}->{$ngname}) { + if (my $ibx = $self->{nntpd}->{pi_cfg}->{-by_newsgroup}->{$ngname}) { if (my $over = $ibx->over) { my $msgs = $over->query_ts($ts, $$prev); if (scalar @$msgs) { - more($self, '<' . - join(">\r\n<", - map { $_->{mid} } @$msgs ) . - '>'); + $self->msg_more(join('', map { + "<$_->{mid}>\r\n"; + } @$msgs)); $$prev = $msgs->[-1]->{num}; return 1; # continue on current group } @@ -363,12 +362,12 @@ sub cmd_newnews ($$$$;$$) { sub cmd_group ($$) { my ($self, $group) = @_; my $nntpd = $self->{nntpd}; - my $ibx = $nntpd->{pi_config}->{-by_newsgroup}->{$group} or + my $ibx = $nntpd->{pi_cfg}->{-by_newsgroup}->{$group} or return '411 no such news group'; $nntpd->idler_start; - $self->{ng} = $ibx; - my ($min, $max) = $ibx->mm->minmax; + $self->{ibx} = $ibx; + my ($min, $max) = $ibx->mm(1)->minmax; $self->{article} = $min; my $est_size = $max - $min; "211 $est_size $min $max $group"; @@ -376,13 +375,13 @@ sub cmd_group ($$) { sub article_adj ($$) { my ($self, $off) = @_; - my $ng = $self->{ng} or return '412 no newsgroup selected'; + my $ibx = $self->{ibx} or return '412 no newsgroup selected'; my $n = $self->{article}; defined $n or return '420 no current article has been selected'; $n += $off; - my $mid = $ng->mm->mid_for($n); + my $mid = $ibx->mm(1)->mid_for($n); unless ($mid) { $n = $off > 0 ? 'next' : 'previous'; return "421 no $n article in this group"; @@ -398,8 +397,8 @@ sub cmd_last ($) { article_adj($_[0], -1) } # the single-point-of-failure a single server provides. sub cmd_post ($) { my ($self) = @_; - my $ng = $self->{ng}; - $ng ? "440 mailto:$ng->{-primary_address} to post" + my $ibx = $self->{ibx}; + $ibx ? "440 mailto:$ibx->{-primary_address} to post" : '440 posting not allowed' } @@ -410,28 +409,17 @@ sub cmd_quit ($) { undef; } -sub header_append ($$$) { - my ($hdr, $k, $v) = @_; - my @v = $hdr->header_raw($k); - foreach (@v) { - return if $v eq $_; - } - $hdr->header_set($k, @v, $v); -} - sub xref_by_tc ($$$) { my ($xref, $pi_cfg, $smsg) = @_; my $by_addr = $pi_cfg->{-by_addr}; - my $groups = $pi_cfg->{-by_newsgroup}; my $mid = $smsg->{mid}; for my $f (qw(to cc)) { my @ibxs = map { $by_addr->{lc($_)} // () } (PublicInbox::Address::emails($smsg->{$f} // '')); for my $ibx (@ibxs) { - $groups->{my $ngname = $ibx->{newsgroup}} or next; - next if defined $xref->{$ngname}; - $xref->{$ngname} = eval { $ibx->mm->num_for($mid) }; + $xref->{$ibx->{newsgroup}} //= + $ibx->mm(1)->num_for($mid); } } } @@ -441,20 +429,22 @@ sub xref ($$$) { my $nntpd = $self->{nntpd}; my $cur_ng = $cur_ibx->{newsgroup}; my $xref; - if (my $ALL = $nntpd->{pi_config}->ALL) { + if (my $ALL = $nntpd->{pi_cfg}->ALL) { $xref = $ALL->nntp_xref_for($cur_ibx, $smsg); - xref_by_tc($xref, $nntpd->{pi_config}, $smsg); + xref_by_tc($xref, $nntpd->{pi_cfg}, $smsg); } else { # slow path $xref = { $cur_ng => $smsg->{num} }; my $mid = $smsg->{mid}; - for my $ibx (values %{$nntpd->{pi_config}->{-by_newsgroup}}) { - next if defined($xref->{$ibx->{newsgroup}}); - my $num = eval { $ibx->mm->num_for($mid) } // next; - $xref->{$ibx->{newsgroup}} = $num; + for my $ibx (values %{$nntpd->{pi_cfg}->{-by_newsgroup}}) { + $xref->{$ibx->{newsgroup}} //= + $ibx->mm(1)->num_for($mid); } } my $ret = "$nntpd->{servername} $cur_ng:".delete($xref->{$cur_ng}); - $ret .= " $_:$xref->{$_}" for (sort keys %$xref); + for my $ng (sort keys %$xref) { + my $num = $xref->{$ng} // next; + $ret .= " $ng:$num"; + } $ret; } @@ -489,13 +479,6 @@ sub set_nntp_headers ($$) { # *something* here is required for leafnode, try to follow # RFC 5536 3.1.5... $hdr->header_set('Path', $server_name . '!not-for-mail'); - - header_append($hdr, 'List-Post', "{-primary_address}>"); - if (my $url = $ibx->base_url) { - $mid = mid_escape($mid); - header_append($hdr, 'Archived-At', "<$url$mid/>"); - header_append($hdr, 'List-Archive', "<$url>"); - } } sub art_lookup ($$$) { @@ -518,11 +501,11 @@ sub art_lookup ($$$) { $err = '420 no current article has been selected'; $n = $self->{article} // return $err; find_ibx: - $ibx = $self->{ng} or + $ibx = $self->{ibx} or return '412 no newsgroup has been selected'; } found: - my $smsg = $ibx->over->get_art($n) or return $err; + my $smsg = $ibx->over(1)->get_art($n) or return $err; $smsg->{-ibx} = $ibx; if ($code == 223) { # STAT set_art($self, $n); @@ -533,7 +516,7 @@ found: $smsg->{nntp_code} = $code; set_art($self, $art); # this dereferences to `undef' - ${git_async_cat($ibx->git, $smsg->{blob}, \&blob_cb, $smsg)}; + ${ibx_async_cat($ibx, $smsg->{blob}, \&blob_cb, $smsg)}; } } @@ -567,7 +550,7 @@ sub msg_hdr_write ($$) { $smsg->{nntp}->msg_more($$hdr); } -sub blob_cb { # called by git->cat_async via git_async_cat +sub blob_cb { # called by git->cat_async via ibx_async_cat my ($bref, $oid, $type, $size, $smsg) = @_; my $self = $smsg->{nntp}; my $code = $smsg->{nntp_code}; @@ -633,10 +616,10 @@ sub cmd_help ($) { sub get_range ($$) { my ($self, $range) = @_; - my $ng = $self->{ng} or return '412 no news group has been selected'; + my $ibx = $self->{ibx} or return '412 no news group has been selected'; defined $range or return '420 No article(s) selected'; my ($beg, $end); - my ($min, $max) = $ng->mm->minmax; + my ($min, $max) = $ibx->mm(1)->minmax; if ($range =~ /\A([0-9]+)\z/) { $beg = $end = $1; } elsif ($range =~ /\A([0-9]+)-\z/) { @@ -706,9 +689,9 @@ sub long_response ($$;@) { sub hdr_msgid_range_i { my ($self, $beg, $end) = @_; - my $r = $self->{ng}->mm->msg_range($beg, $end); + my $r = $self->{ibx}->mm(1)->msg_range($beg, $end); @$r or return; - more($self, join("\r\n", map { "$_->[0] <$_->[1]>" } @$r)); + $self->msg_more(join('', map { "$_->[0] <$_->[1]>\r\n" } @$r)); 1; } @@ -716,9 +699,9 @@ sub hdr_message_id ($$$) { # optimize XHDR Message-ID [range] for slrnpull. my ($self, $xhdr, $range) = @_; if (defined $range && $range =~ $ONE_MSGID) { - my ($ng, $n) = mid_lookup($self, $1); + my ($ibx, $n) = mid_lookup($self, $1); return r430 unless $n; - hdr_mid_response($self, $xhdr, $ng, $n, $range, $range); + hdr_mid_response($self, $xhdr, $ibx, $n, $range, $range); } else { # numeric range $range = $self->{article} unless defined $range; my $r = get_range($self, $range); @@ -730,12 +713,12 @@ sub hdr_message_id ($$$) { # optimize XHDR Message-ID [range] for slrnpull. sub mid_lookup ($$) { my ($self, $mid) = @_; - my $self_ng = $self->{ng}; - if ($self_ng) { - my $n = $self_ng->mm->num_for($mid); - return ($self_ng, $n) if defined $n; + my $cur_ibx = $self->{ibx}; + if ($cur_ibx) { + my $n = $cur_ibx->mm(1)->num_for($mid); + return ($cur_ibx, $n) if defined $n; } - my $pi_cfg = $self->{nntpd}->{pi_config}; + my $pi_cfg = $self->{nntpd}->{pi_cfg}; if (my $ALL = $pi_cfg->ALL) { my ($id, $prev); while (my $smsg = $ALL->over->next_by_mid($mid, \$id, \$prev)) { @@ -761,8 +744,8 @@ EOF # no warning here, $mid is just invalid } else { # slow path for non-ALL users for my $ibx (values %{$pi_cfg->{-by_newsgroup}}) { - next if defined $self_ng && $ibx eq $self_ng; - my $n = $ibx->mm->num_for($mid); + next if defined $cur_ibx && $ibx eq $cur_ibx; + my $n = $ibx->mm(1)->num_for($mid); return ($ibx, $n) if defined $n; } } @@ -771,12 +754,12 @@ EOF sub xref_range_i { my ($self, $beg, $end) = @_; - my $ng = $self->{ng}; - my $msgs = $ng->over->query_xover($$beg, $end); + my $ibx = $self->{ibx}; + my $msgs = $ibx->over(1)->query_xover($$beg, $end); scalar(@$msgs) or return; $$beg = $msgs->[-1]->{num} + 1; - more($self, join("\r\n", map { - "$_->{num} ".xref($self, $ng, $_); + $self->msg_more(join('', map { + "$_->{num} ".xref($self, $ibx, $_) . "\r\n"; } @$msgs)); 1; } @@ -786,11 +769,11 @@ sub hdr_xref ($$$) { # optimize XHDR Xref [range] for rtin if (defined $range && $range =~ $ONE_MSGID) { my $mid = $1; - my ($ng, $n) = mid_lookup($self, $mid); + my ($ibx, $n) = mid_lookup($self, $mid); return r430 unless $n; - my $smsg = $ng->over->get_art($n) or return; - hdr_mid_response($self, $xhdr, $ng, $n, $range, - xref($self, $ng, $smsg)); + my $smsg = $ibx->over(1)->get_art($n) or return; + hdr_mid_response($self, $xhdr, $ibx, $n, $range, + xref($self, $ibx, $smsg)); } else { # numeric range $range = $self->{article} unless defined $range; my $r = get_range($self, $range); @@ -801,16 +784,15 @@ sub hdr_xref ($$$) { # optimize XHDR Xref [range] for rtin } sub over_header_for { - my ($over, $num, $field) = @_; - my $smsg = $over->get_art($num) or return; + my ($ibx, $num, $field) = @_; + my $smsg = $ibx->over(1)->get_art($num) or return; return PublicInbox::Smsg::date($smsg) if $field eq 'date'; $smsg->{$field}; } sub smsg_range_i { my ($self, $beg, $end, $field) = @_; - my $over = $self->{ng}->over; - my $msgs = $over->query_xover($$beg, $end); + my $msgs = $self->{ibx}->over(1)->query_xover($$beg, $end); scalar(@$msgs) or return; my $tmp = ''; @@ -832,10 +814,10 @@ sub smsg_range_i { sub hdr_smsg ($$$$) { my ($self, $xhdr, $field, $range) = @_; if (defined $range && $range =~ $ONE_MSGID) { - my ($ng, $n) = mid_lookup($self, $1); + my ($ibx, $n) = mid_lookup($self, $1); return r430 unless defined $n; - my $v = over_header_for($ng->over, $n, $field); - hdr_mid_response($self, $xhdr, $ng, $n, $range, $v); + my $v = over_header_for($ibx, $n, $field); + hdr_mid_response($self, $xhdr, $ibx, $n, $range, $v); } else { # numeric range $range = $self->{article} unless defined $range; my $r = get_range($self, $range); @@ -875,26 +857,26 @@ sub cmd_xhdr ($$;$) { } sub hdr_mid_prefix ($$$$$) { - my ($self, $xhdr, $ng, $n, $mid) = @_; + my ($self, $xhdr, $ibx, $n, $mid) = @_; return $mid if $xhdr; # HDR for RFC 3977 users - if (my $self_ng = $self->{ng}) { - ($self_ng eq $ng) ? $n : '0'; + if (my $cur_ibx = $self->{ibx}) { + ($cur_ibx eq $ibx) ? $n : '0'; } else { '0'; } } sub hdr_mid_response ($$$$$$) { - my ($self, $xhdr, $ng, $n, $mid, $v) = @_; + my ($self, $xhdr, $ibx, $n, $mid, $v) = @_; my $res = ''; if ($xhdr) { $res .= r221 . "\r\n"; $res .= "$mid $v\r\n"; } else { $res .= r225 . "\r\n"; - my $pfx = hdr_mid_prefix($self, $xhdr, $ng, $n, $mid); + my $pfx = hdr_mid_prefix($self, $xhdr, $ibx, $n, $mid); $res .= "$pfx $v\r\n"; } res($self, $res .= '.'); @@ -903,14 +885,14 @@ sub hdr_mid_response ($$$$$$) { sub xrover_i { my ($self, $beg, $end) = @_; - my $h = over_header_for($self->{ng}->over, $$beg, 'references'); + my $h = over_header_for($self->{ibx}, $$beg, 'references'); more($self, "$$beg $h") if defined($h); $$beg++ < $end; } sub cmd_xrover ($;$) { my ($self, $range) = @_; - my $ng = $self->{ng} or return '412 no newsgroup selected'; + my $ibx = $self->{ibx} or return '412 no newsgroup selected'; (defined $range && $range =~ /[<>]/) and return '420 No article(s) selected'; # no message IDs @@ -922,7 +904,7 @@ sub cmd_xrover ($;$) { } sub over_line ($$$) { - my ($self, $ng, $smsg) = @_; + my ($self, $ibx, $smsg) = @_; # n.b. field access and procedural calls can be # 10%-15% faster than OO method calls: my $s = join("\t", $smsg->{num}, @@ -933,28 +915,28 @@ sub over_line ($$$) { $smsg->{references}, $smsg->{bytes}, $smsg->{lines}, - "Xref: " . xref($self, $ng, $smsg)); + "Xref: " . xref($self, $ibx, $smsg)); utf8::encode($s); - $s + $s .= "\r\n"; } sub cmd_over ($;$) { my ($self, $range) = @_; if ($range && $range =~ $ONE_MSGID) { - my ($ng, $n) = mid_lookup($self, $1); + my ($ibx, $n) = mid_lookup($self, $1); defined $n or return r430; - my $smsg = $ng->over->get_art($n) or return r430; + my $smsg = $ibx->over(1)->get_art($n) or return r430; more($self, '224 Overview information follows (multi-line)'); # Only set article number column if it's the current group # (RFC 3977 8.3.2) - my $self_ng = $self->{ng}; - if (!$self_ng || $self_ng ne $ng) { + my $cur_ibx = $self->{ibx}; + if (!$cur_ibx || $cur_ibx ne $ibx) { # set {-orig_num} for nntp_xref_for $smsg->{-orig_num} = $smsg->{num}; $smsg->{num} = 0; } - more($self, over_line($self, $ng, $smsg)); + $self->msg_more(over_line($self, $ibx, $smsg)); '.'; } else { cmd_xover($self, $range); @@ -963,13 +945,13 @@ sub cmd_over ($;$) { sub xover_i { my ($self, $beg, $end) = @_; - my $ng = $self->{ng}; - my $msgs = $ng->over->query_xover($$beg, $end); + my $ibx = $self->{ibx}; + my $msgs = $ibx->over(1)->query_xover($$beg, $end); my $nr = scalar @$msgs or return; # OVERVIEW.FMT - more($self, join("\r\n", map { - over_line($self, $ng, $_); + $self->msg_more(join('', map { + over_line($self, $ibx, $_); } @$msgs)); $$beg = $msgs->[-1]->{num} + 1; } @@ -1016,7 +998,7 @@ sub cmd_xpath ($$) { return r501 unless $mid =~ $ONE_MSGID; $mid = $1; my @paths; - my $pi_cfg = $self->{nntpd}->{pi_config}; + my $pi_cfg = $self->{nntpd}->{pi_cfg}; my $groups = $pi_cfg->{-by_newsgroup}; if (my $ALL = $pi_cfg->ALL) { my ($id, $prev, %seen); @@ -1032,7 +1014,7 @@ sub cmd_xpath ($$) { } } else { # slow path, no point in using long_response for my $ibx (values %$groups) { - my $n = $ibx->mm->num_for($mid) // next; + my $n = $ibx->mm(1)->num_for($mid) // next; push @paths, "$ibx->{newsgroup}/$n"; } }