]> Sergey Matveev's repositories - public-inbox.git/blobdiff - lib/PublicInbox/GitHTTPBackend.pm
githttpbackend: use REMOTE_ADDR for deleted identifier
[public-inbox.git] / lib / PublicInbox / GitHTTPBackend.pm
index 09411048db25a8d4fcb41237d4285fa46abd9960..c9a7cff88cc419bc71241006511d42ac7b4ec4d5 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 2016-2018 all contributors <meta@public-inbox.org>
+# Copyright (C) 2016-2019 all contributors <meta@public-inbox.org>
 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
 
 # when no endpoints match, fallback to this and serve a static file
@@ -12,6 +12,7 @@ use HTTP::Date qw(time2str);
 use HTTP::Status qw(status_message);
 use Plack::Util;
 use PublicInbox::Qspawn;
+use PublicInbox::Tmpfile;
 
 # 32 is same as the git-daemon connection limit
 my $default_limiter = PublicInbox::Qspawn::Limiter->new(32);
@@ -51,8 +52,8 @@ sub serve {
 
        # Documentation/technical/http-protocol.txt in git.git
        # requires one and exactly one query parameter:
-       if ($env->{QUERY_STRING} =~ /\Aservice=git-\w+-pack\z/ ||
-                               $path =~ /\Agit-\w+-pack\z/) {
+       if ($env->{QUERY_STRING} =~ /\Aservice=git-[A-Za-z0-9_]+-pack\z/ ||
+                               $path =~ /\Agit-[A-Za-z0-9_]+-pack\z/) {
                my $ok = serve_smart($env, $git, $path);
                return $ok if $ok;
        }
@@ -90,7 +91,7 @@ sub static_result ($$$$) {
        my $len = $size;
        my $code = 200;
        push @$h, 'Content-Type', $type;
-       if (($env->{HTTP_RANGE} || '') =~ /\bbytes=(\d*)-(\d*)\z/) {
+       if (($env->{HTTP_RANGE} || '') =~ /\bbytes=([0-9]*)-([0-9]*)\z/) {
                ($code, $len) = prepare_range($env, $in, $h, $1, $2, $size);
                if ($code == 416) {
                        push @$h, 'Content-Range', "bytes */$size";
@@ -218,7 +219,8 @@ sub input_prepare {
        if (defined $fd && $fd >= 0) {
                return { 0 => $fd };
        }
-       open(my $in, '+>', undef);
+       my $id = "git-http.input.$env->{REMOTE_ADDR}:$env->{REMOTE_PORT}";
+       my $in = tmpfile($id);
        unless (defined $in) {
                err($env, "could not open temporary file: $!");
                return;
@@ -231,18 +233,16 @@ sub input_prepare {
                        return;
                }
                last if $r == 0;
-               my $off = 0;
-               while ($r > 0) {
-                       my $w = syswrite($in, $buf, $r, $off);
-                       if (defined $w) {
-                               $r -= $w;
-                               $off += $w;
-                       } else {
-                               err($env, "error writing temporary file: $!");
-                               return;
-                       }
+               unless (print $in $buf) {
+                       err($env, "error writing temporary file: $!");
+                       return;
                }
        }
+       # ensure it's visible to git-http-backend(1):
+       unless ($in->flush) {
+               err($env, "error writing temporary file: $!");
+               return;
+       }
        unless (defined(sysseek($in, 0, SEEK_SET))) {
                err($env, "error seeking temporary file: $!");
                return;
@@ -260,7 +260,7 @@ sub parse_cgi_headers {
        foreach my $l (split(/\r?\n/, $h)) {
                my ($k, $v) = split(/:\s*/, $l, 2);
                if ($k =~ /\AStatus\z/i) {
-                       ($code) = ($v =~ /\b(\d+)\b/);
+                       ($code) = ($v =~ /\b([0-9]+)\b/);
                } else {
                        push @h, $k, $v;
                }