X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FNetReader.pm;h=eab7320e913aefc9441c63cb4b0b1bf441f30996;hb=41c3eed65eb03256b0916cfdbf43723e070a633a;hp=a0e52fc5abd18fccc2d600893f72559a3562883e;hpb=bbc43425b6710d5687365956764dffc8590a7c58;p=public-inbox.git diff --git a/lib/PublicInbox/NetReader.pm b/lib/PublicInbox/NetReader.pm index a0e52fc5..eab7320e 100644 --- a/lib/PublicInbox/NetReader.pm +++ b/lib/PublicInbox/NetReader.pm @@ -35,6 +35,7 @@ sub socks_args ($) { eval { require IO::Socket::Socks } or die < $h, ProxyPort => $p }; } die "$val not understood (only socks5h:// is supported)\n"; @@ -42,20 +43,64 @@ EOM sub mic_new ($$$$) { my ($self, $mic_arg, $sec, $uri) = @_; - my %mic_arg = %$mic_arg; + my %mic_arg = (%$mic_arg, Keepalive => 1); my $sa = $self->{cfg_opt}->{$sec}->{-proxy_cfg} || $self->{-proxy_cli}; if ($sa) { - my %opt = %$sa; + # this `require' needed for worker[1..Inf], since socks_args + # only got called in worker[0] + require IO::Socket::Socks; + my %opt = (%$sa, Keepalive => 1); + $opt{SocksDebug} = 1 if $mic_arg{Debug}; $opt{ConnectAddr} = delete $mic_arg{Server}; $opt{ConnectPort} = delete $mic_arg{Port}; - $mic_arg{Socket} = IO::Socket::Socks->new(%opt) or die - "E: <$$uri> ".eval('$IO::Socket::Socks::SOCKS_ERROR'); + my $s = IO::Socket::Socks->new(%opt) or die + "E: <$uri> ".eval('$IO::Socket::Socks::SOCKS_ERROR'); + if ($mic_arg->{Ssl}) { # for imaps:// + require IO::Socket::SSL; + $s = IO::Socket::SSL->start_SSL($s) or die + "E: <$uri> ".(IO::Socket::SSL->errstr // ''); + } + $mic_arg{Socket} = $s; } - PublicInbox::IMAPClient->new(%mic_arg, Keepalive => 1); + PublicInbox::IMAPClient->new(%mic_arg); } sub auth_anon_cb { '' }; # for Mail::IMAPClient::Authcallback +sub onion_hint ($$) { + my ($lei, $uri) = @_; + $uri->host =~ /\.onion\z/i or return "\n"; + my $t = $uri->isa('PublicInbox::URIimap') ? 'imap' : 'nntp'; + my $url = PublicInbox::Config::squote_maybe(uri_section($uri)); + my $set_cfg = 'lei config'; + if (!$lei) { # public-inbox-watch + my $f = PublicInbox::Config::squote_maybe( + $ENV{PI_CONFIG} || '~/.public-inbox/config'); + $set_cfg = "git config -f $f"; + } + my $dq = substr($url, 0, 1) eq "'" ? '"' : ''; + < $uri->port, Server => $host, - Ssl => $uri->scheme eq 'imaps', %$common, # may set Starttls, Compress, Debug .... }; $mic_arg->{Ssl} = 1 if $uri->scheme eq 'imaps'; require PublicInbox::IMAPClient; - my $mic = mic_new($self, $mic_arg, $sec, $uri) or - die "E: <$uri> new: $@\n"; + my $mic = mic_new($self, $mic_arg, $sec, $uri); + ($mic && $mic->IsConnected) or + die "E: <$uri> new: $@".onion_hint($lei, $uri); + # default to using STARTTLS if it's available, but allow # it to be disabled since I usually connect to localhost if (!$mic_arg->{Ssl} && !defined($mic_arg->{Starttls}) && $mic->has_capability('STARTTLS') && + try_starttls($host) && $mic->can('starttls')) { $mic->starttls or die "E: <$uri> STARTTLS: $@\n"; } @@ -96,7 +143,7 @@ sub mic_for ($$$$) { # mic = Mail::IMAPClient $cred = undef; } if ($cred) { - my $p = $cred->{password} // $cred->check_netrc; + my $p = $cred->{password} // $cred->check_netrc($lei); $cred->fill($lei) unless defined($p); # may prompt user here $mic->User($mic_arg->{User} = $cred->{username}); $mic->Password($mic_arg->{Password} = $cred->{password}); @@ -128,25 +175,18 @@ sub mic_for ($$$$) { # mic = Mail::IMAPClient $mic; } -# Net::NNTP doesn't support CAPABILITIES, yet -sub try_starttls ($) { - my ($host) = @_; - return if $host =~ /\.onion\z/s; - return if $host =~ /\A127\.[0-9]+\.[0-9]+\.[0-9]+\z/s; - return if $host eq '::1'; - 1; -} - sub nn_new ($$$) { my ($nn_arg, $nntp_cfg, $uri) = @_; my $nn; if (defined $nn_arg->{ProxyAddr}) { require PublicInbox::NetNNTPSocks; + $nn_arg->{SocksDebug} = 1 if $nn_arg->{Debug}; eval { $nn = PublicInbox::NetNNTPSocks->new_socks(%$nn_arg) }; die "E: <$uri> $@\n" if $@; } else { - $nn = Net::NNTP->new(%$nn_arg) or die "E: <$uri> new: $!\n"; + $nn = Net::NNTP->new(%$nn_arg) or return; } + setsockopt($nn, Socket::SOL_SOCKET(), Socket::SO_KEEPALIVE(), 1); # default to using STARTTLS if it's available, but allow # it to be disabled for localhost/VPN users @@ -191,7 +231,7 @@ sub nn_for ($$$$) { # nn = Net::NNTP }, 'PublicInbox::GitCredential'; ($u, $p) = split(/:/, $ui, 2); ($cred->{username}, $cred->{password}) = ($u, $p); - $p //= $cred->check_netrc; + $p //= $cred->check_netrc($lei); } my $common = $nn_common->{$sec} // {}; my $nn_arg = { @@ -202,7 +242,8 @@ sub nn_for ($$$$) { # nn = Net::NNTP $nn_arg->{SSL} = 1 if $uri->secure; # snews == nntps my $sa = $self->{-proxy_cli}; %$nn_arg = (%$nn_arg, %$sa) if $sa; - my $nn = nn_new($nn_arg, $nntp_cfg, $uri); + my $nn = nn_new($nn_arg, $nntp_cfg, $uri) or + die "E: <$uri> new: $@".onion_hint($lei, $uri); if ($cred) { $cred->fill($lei) unless defined($p); # may prompt user here if ($nn->authinfo($u, $p)) { @@ -303,10 +344,10 @@ sub imap_common_init ($;$) { } my $k = 'imap.fetchBatchSize'; my $bs = $cfg->urlmatch($k, $$uri) // next; - if ($bs =~ /\A([0-9]+)\z/) { + if ($bs =~ /\A([0-9]+)\z/ && $bs > 0) { $self->{cfg_opt}->{$sec}->{batch_size} = $bs; } else { - warn "$k=$bs is not an integer\n"; + warn "$k=$bs is not a positive integer\n"; } } # make sure we can connect and cache the credentials in memory @@ -686,21 +727,27 @@ sub _nntp_fetch_all ($$$) { my $msg = ndump($nn->message); return "E: GROUP $group <$sec> $msg"; } - + (defined($num_a) && defined($num_b) && $num_a > $num_b) and + return "E: $uri: backwards range: $num_a > $num_b"; + if (defined($num_a)) { # no article numbers in mail_sync.sqlite3 + $uri = $uri->clone; + $uri->group($group); + } # IMAPTracker is also used for tracking NNTP, UID == article number # LIST.ACTIVE can get the equivalent of UIDVALIDITY, but that's # expensive. So we assume newsgroups don't change: my ($itrk, $l_art) = itrk_last($self, $uri); - # allow users to specify articles to refetch - # cf. https://tools.ietf.org/id/draft-gilman-news-url-01.txt - # nntp://example.com/inbox.foo/$num_a-$num_b - $beg = $num_a if defined($num_a) && $num_a < $beg; - $end = $num_b if defined($num_b) && $num_b < $end; - if (defined $l_art) { + if (defined($l_art) && !defined($num_a)) { return if $l_art >= $end; # nothing to do $beg = $l_art + 1; } + # allow users to specify articles to refetch + # cf. https://tools.ietf.org/id/draft-gilman-news-url-01.txt + # nntp://example.com/inbox.foo/$num_a-$num_b + $beg = $num_a if defined($num_a) && $num_a > $beg && $num_a <= $end; + $end = $num_b if defined($num_b) && $num_b >= $beg && $num_b < $end; + $end = $beg if defined($num_a) && !defined($num_b); my ($err, $art, $last_art, $kw); # kw stays undef, no keywords in NNTP unless ($self->{quiet}) { warn "# $uri fetching ARTICLE $beg..$end\n";