From d9563ea5516e8e786debf223e10ec11695aee9d7 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Thu, 9 Feb 2017 01:37:03 +0000 Subject: repobrowse: shorten internal names We'll still be keeping "repobrowse" for the public API for use with .psgi files, but shortening the name means less typing and we may have command-line tools, too. --- lib/PublicInbox/RepoBase.pm | 115 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 lib/PublicInbox/RepoBase.pm (limited to 'lib/PublicInbox/RepoBase.pm') diff --git a/lib/PublicInbox/RepoBase.pm b/lib/PublicInbox/RepoBase.pm new file mode 100644 index 00000000..e60677d6 --- /dev/null +++ b/lib/PublicInbox/RepoBase.pm @@ -0,0 +1,115 @@ +# Copyright (C) 2015 all contributors +# License: AGPL-3.0+ +package PublicInbox::RepoBase; +use strict; +use warnings; +require PublicInbox::RepoGitQuery; +use PublicInbox::Hval; +our %MIME_TYPE_WHITELIST = ('application/pdf' => 1); + +sub new { bless {}, shift } + +sub call { + my ($self, $cmd, $req) = @_; + my $vcs = $req->{repo_info}->{vcs}; + my $rv = eval { + no strict 'refs'; + my $sub = "call_${vcs}_$cmd"; + $self->$sub($req); + }; + $@ ? [ 500, ['Content-Type'=>'text/plain'], [] ] : $rv; +} + +sub mime_load { + my ($self, $file) = @_; + my %rv; + open my $fh, '<', $file or return \%rv; + while (<$fh>) { + next if /^#/; # no comments + my ($type, @ext) = split(/\s+/); + + if (defined $type) { + $rv{$_} = $type foreach @ext; + } + } + \%rv; +} + +# returns undef if missing, so users can scan the blob if needed +sub mime_type_unsafe { + my ($self, $fn) = @_; + $fn =~ /\.([^\.]+)\z/ or return; + my $ext = $1; + my $m = $self->{mime_types} ||= $self->mime_load('/etc/mime.types'); + $m->{$ext}; +} + +sub mime_type { + my ($self, $fn) = @_; + my $ct = $self->mime_type_unsafe($fn); + return unless defined $ct; + + # XSS protection. Assume the browser knows what to do + # with images/audio/video; but don't allow random HTML from + # a repository to be served + ($ct =~ m!\A(?:image|audio|video)/! || $MIME_TYPE_WHITELIST{$ct}) ? + $ct : undef; +} + +# starts an HTML page for Repobrowse in a consistent way +sub html_start { + my ($self, $req, $title_html, $opts) = @_; + my $desc = $req->{repo_info}->{desc_html}; + my $meta = ''; + + if ($opts) { + my @robots; + foreach (qw(nofollow noindex)) { + push @robots, $_ if $opts->{$_}; + } + $meta = qq('; + } + + "$title_html" . + PublicInbox::Hval::STYLE . $meta . + "
$desc";
+}
+
+sub r {
+	my ($self, $status, $req, @extra) = @_;
+	my @h;
+
+	my $body = '';
+	if ($status == 301 || $status == 302) {
+		# The goal is to be able to make redirects like we make
+		#  tags with '../'
+		my $env = $req->{env};
+		my $base = PublicInbox::Repobrowse::base_url($env);
+		my ($redir) = @extra;
+		if ($redir =~ m!\A\.\./!) { # relative redirect
+			my @orig = split(m!/+!, $env->{PATH_INFO});
+			my @dest = split(m!/+!, $redir);
+
+			while ($dest[0] eq '..') {
+				pop @orig;
+				shift @dest;
+			}
+			my $end = '';
+			$end = pop @dest if $dest[-1] =~ /\A[#\?]/;
+			$redir = $base . join('/', @orig, @dest) . $end;
+		} else {
+			$redir = $base . '/' . $redir;
+		}
+		push @h, qw(Content-Type text/plain Location), $redir;
+
+		# mainly for curl (no-'-L') users:
+		$body = "Redirecting to $redir\n";
+	} else {
+		push @h, qw(Content-Type text/plain);
+	}
+
+	[ $status, \@h, [ $body ] ]
+}
+
+1;
-- 
cgit v1.2.3-24-ge0c7