user/dev discussion of public-inbox itself
 help / color / mirror / Atom feed
a7c7cbc1239e6025e6594524a68ed803263dfcb1 blob 3324 bytes (raw)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
 
# Copyright (C) 2019-2020 all contributors <meta@public-inbox.org>
# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>

# Provide an HTTP-accessible listing of inboxes.
# Used by PublicInbox::WWW
package PublicInbox::WwwListing;
use strict;
use PublicInbox::Hval qw(ascii_html prurl fmt_ts);
use PublicInbox::Linkify;
use PublicInbox::GzipFilter qw(gzf_maybe);
use PublicInbox::ManifestJsGz;
use bytes (); # bytes::length

sub list_all_i {
	my ($ibx, $list, $hide_key) = @_;
	push @$list, $ibx unless $ibx->{-hide}->{$hide_key};
}

sub list_all ($$$) {
	my ($self, $env, $hide_key) = @_;
	my $list = [];
	$self->{pi_config}->each_inbox(\&list_all_i, $list, $hide_key);
	$list;
}

sub list_match_domain_i {
	my ($ibx, $list, $hide_key, $re) = @_;
	if (!$ibx->{-hide}->{$hide_key} && grep(/$re/, @{$ibx->{url}})) {
		push @$list, $ibx;
	}
}

sub list_match_domain ($$$) {
	my ($self, $env, $hide_key) = @_;
	my $list = [];
	my $host = $env->{HTTP_HOST} // $env->{SERVER_NAME};
	$host =~ s/:[0-9]+\z//;
	$self->{pi_config}->each_inbox(\&list_match_domain_i, $list, $hide_key,
				qr!\A(?:https?:)?//\Q$host\E(?::[0-9]+)?/!i);
	$list;
}

sub list_404 ($$) { [] }

# TODO: +cgit
my %VALID = (
	all => \&list_all,
	'match=domain' => \&list_match_domain,
	404 => \&list_404,
);

sub set_cb ($$$) {
	my ($pi_config, $k, $default) = @_;
	my $v = $pi_config->{lc $k} // $default;
	$VALID{$v} || do {
		warn <<"";
`$v' is not a valid value for `$k'
$k be one of `all', `match=domain', or `404'

		$VALID{$default};
	};
}

sub new {
	my ($class, $www) = @_;
	my $pi_config = $www->{pi_config};
	bless {
		pi_config => $pi_config,
		style => $www->style("\0"),
		www_cb => set_cb($pi_config, 'publicInbox.wwwListing', 404),
		manifest_cb => set_cb($pi_config, 'publicInbox.grokManifest',
					'match=domain'),
	}, $class;
}

sub ibx_entry {
	my ($mtime, $ibx, $env) = @_;
	my $ts = fmt_ts($mtime);
	my $url = prurl($env, $ibx->{url});
	my $tmp = <<"";
* $ts - $url
  ${\$ibx->description}

	if (defined(my $info_url = $ibx->{infourl})) {
		$tmp .= '  ' . prurl($env, $info_url) . "\n";
	}
	$tmp;
}

sub html ($$) {
	my ($env, $list) = @_;
	my $h = [ 'Content-Type', 'text/html; charset=UTF-8',
			'Content-Length', undef ];
	my $gzf = gzf_maybe($h, $env);
	$gzf->zmore('<html><head><title>' .
				'public-inbox listing</title>' .
				'</head><body><pre>');
	my $code = 404;
	if (@$list) {
		$code = 200;
		# Schwartzian transform since Inbox->modified is expensive
		@$list = sort {
			$b->[0] <=> $a->[0]
		} map { [ $_->modified, $_ ] } @$list;

		my $tmp = join("\n", map { ibx_entry(@$_, $env) } @$list);
		my $l = PublicInbox::Linkify->new;
		$gzf->zmore($l->to_html($tmp));
	} else {
		$gzf->zmore('no inboxes, yet');
	}
	my $out = $gzf->zflush('</pre><hr><pre>'.
				PublicInbox::WwwStream::code_footer($env) .
				'</pre></body></html>');
	$h->[3] = bytes::length($out);
	[ $code, $h, [ $out ] ];
}

# not really a stand-alone PSGI app, but maybe it could be...
sub call {
	my ($self, $env) = @_;

	if ($env->{PATH_INFO} eq '/manifest.js.gz') {
		# grokmirror uses relative paths, so it's domain-dependent
		my $list = $self->{manifest_cb}->($self, $env, 'manifest');
		PublicInbox::ManifestJsGz::response($env, $list);
	} else { # /
		my $list = $self->{www_cb}->($self, $env, 'www');
		html($env, $list);
	}
}

1;
debug log:

solving a7c7cbc1 ...
found a7c7cbc1 in https://80x24.org/public-inbox.git

user/dev discussion of public-inbox itself

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://public-inbox.org/meta
	git clone --mirror http://czquwvybam4bgbro.onion/meta
	git clone --mirror http://hjrcffqmbrq6wope.onion/meta
	git clone --mirror http://ou63pmih66umazou.onion/meta

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V1 meta meta/ https://public-inbox.org/meta \
		meta@public-inbox.org
	public-inbox-index meta

Example config snippet for mirrors.
Newsgroups are available over NNTP:
	nntp://news.public-inbox.org/inbox.comp.mail.public-inbox.meta
	nntp://ou63pmih66umazou.onion/inbox.comp.mail.public-inbox.meta
	nntp://czquwvybam4bgbro.onion/inbox.comp.mail.public-inbox.meta
	nntp://hjrcffqmbrq6wope.onion/inbox.comp.mail.public-inbox.meta
	nntp://news.gmane.io/gmane.mail.public-inbox.general
 note: .onion URLs require Tor: https://www.torproject.org/

code repositories for the project(s) associated with this inbox:

	https://80x24.org/public-inbox.git

AGPL code for this site: git clone https://public-inbox.org/public-inbox.git