// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// CGI environment and execution management portions are:
//
// ========================================================================
// Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================

package com.google.gerrit.httpd.gitweb;

import static java.nio.charset.StandardCharsets.ISO_8859_1;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.base.CharMatcher;
import com.google.common.base.Splitter;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.Url;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.AnonymousUser;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.GitwebCgiConfig;
import com.google.gerrit.server.config.GitwebConfig;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.LocalDiskRepositoryManager;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.permissions.ProjectPermission;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.ssh.SshInfo;
import com.google.gerrit.util.http.CacheHeaders;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.ProvisionException;
import com.google.inject.Singleton;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Repository;

/** Invokes {@code gitweb.cgi} for the project given in {@code p}. */
@Singleton
class GitwebServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private static final String PROJECT_LIST_ACTION = "project_list";

  private final Set<String> deniedActions;
  private final int bufferSize = 8192;
  private final Path gitwebCgi;
  private final URI gitwebUrl;
  private final LocalDiskRepositoryManager repoManager;
  private final ProjectCache projectCache;
  private final PermissionBackend permissionBackend;
  private final Provider<AnonymousUser> anonymousUserProvider;
  private final Provider<CurrentUser> userProvider;
  private final EnvList _env;

  @Inject
  GitwebServlet(
      GitRepositoryManager repoManager,
      ProjectCache projectCache,
      PermissionBackend permissionBackend,
      Provider<CurrentUser> userProvider,
      SitePaths site,
      @GerritServerConfig Config cfg,
      SshInfo sshInfo,
      Provider<AnonymousUser> anonymousUserProvider,
      GitwebConfig gitwebConfig,
      GitwebCgiConfig gitwebCgiConfig)
      throws IOException {
    if (!(repoManager instanceof LocalDiskRepositoryManager)) {
      throw new ProvisionException("Gitweb can only be used with LocalDiskRepositoryManager");
    }
    this.repoManager = (LocalDiskRepositoryManager) repoManager;
    this.projectCache = projectCache;
    this.permissionBackend = permissionBackend;
    this.anonymousUserProvider = anonymousUserProvider;
    this.userProvider = userProvider;
    this.gitwebCgi = gitwebCgiConfig.getGitwebCgi();
    this.deniedActions = new HashSet<>();

    final String url = gitwebConfig.getUrl();
    if ((url != null) && (!url.equals("gitweb"))) {
      URI uri = null;
      try {
        uri = new URI(url);
      } catch (URISyntaxException e) {
        logger.atSevere().log("Invalid gitweb.url: %s", url);
      }
      gitwebUrl = uri;
    } else {
      gitwebUrl = null;
    }

    deniedActions.add("forks");
    deniedActions.add("opml");
    deniedActions.add("project_index");

    _env = new EnvList();
    makeSiteConfig(site, cfg, sshInfo);

    if (!_env.envMap.containsKey("SystemRoot")) {
      String os = System.getProperty("os.name");
      if (os != null && os.toLowerCase().contains("windows")) {
        String sysroot = System.getenv("SystemRoot");
        if (sysroot == null || sysroot.isEmpty()) {
          sysroot = "C:\\WINDOWS";
        }
        _env.set("SystemRoot", sysroot);
      }
    }

    if (!_env.envMap.containsKey("PATH")) {
      _env.set("PATH", System.getenv("PATH"));
    }
  }

  private void makeSiteConfig(SitePaths site, Config cfg, SshInfo sshInfo) throws IOException {
    if (!Files.exists(site.tmp_dir)) {
      Files.createDirectories(site.tmp_dir);
    }
    Path myconf = Files.createTempFile(site.tmp_dir, "gitweb_config", ".perl");

    // To make our configuration file only readable or writable by us;
    // this reduces the chances of someone tampering with the file.
    //
    // TODO(dborowitz): Is there a portable way to do this with NIO?
    File myconfFile = myconf.toFile();
    myconfFile.setWritable(false, false /* all */);
    myconfFile.setReadable(false, false /* all */);
    myconfFile.setExecutable(false, false /* all */);

    myconfFile.setWritable(true, true /* owner only */);
    myconfFile.setReadable(true, true /* owner only */);

    myconfFile.deleteOnExit();

    _env.set("GIT_DIR", ".");
    _env.set("GITWEB_CONFIG", myconf.toAbsolutePath().toString());

    try (PrintWriter p = new PrintWriter(Files.newBufferedWriter(myconf, UTF_8))) {
      p.print("# Autogenerated by Gerrit Code Review \n");
      p.print("# DO NOT EDIT\n");
      p.print("\n");

      // We are mounted at the same level in the context as the main
      // UI, so we can include the same header and footer scheme.
      //
      Path hdr = site.site_header;
      if (Files.isRegularFile(hdr)) {
        p.print("$site_header = " + quoteForPerl(hdr) + ";\n");
      }
      Path ftr = site.site_footer;
      if (Files.isRegularFile(ftr)) {
        p.print("$site_footer = " + quoteForPerl(ftr) + ";\n");
      }

      // Top level should return to Gerrit's UI.
      //
      p.print("$home_link = $ENV{'GERRIT_CONTEXT_PATH'};\n");
      p.print("$home_link_str = 'Code Review';\n");

      p.print("$favicon = 'favicon.ico';\n");
      p.print("$logo = 'gitweb-logo.png';\n");
      p.print("$javascript = 'gitweb.js';\n");
      p.print("@stylesheets = ('gitweb-default.css');\n");
      Path css = site.site_css;
      if (Files.isRegularFile(css)) {
        p.print("push @stylesheets, 'gitweb-site.css';\n");
      }

      // Try to make the title match Gerrit's normal window title
      // scheme of host followed by 'Code Review'.
      //
      p.print("$site_name = $home_link_str;\n");
      p.print("$site_name = qq{$1 $site_name} if ");
      p.print("$ENV{'SERVER_NAME'} =~ m,^([^.]+(?:\\.[^.]+)?)(?:\\.|$),;\n");

      // Assume by default that XSS is a problem, and try to prevent it.
      //
      p.print("$prevent_xss = 1;\n");

      // Generate URLs using smart http://
      //
      p.print("{\n");
      p.print("  my $secure = $ENV{'HTTPS'} =~ /^ON$/i;\n");
      p.print("  my $http_url = $secure ? 'https://' : 'http://';\n");
      p.print("  $http_url .= qq{$ENV{'GERRIT_USER_NAME'}@}\n");
      p.print("    unless $ENV{'GERRIT_ANONYMOUS_READ'};\n");
      p.print("  $http_url .= $ENV{'SERVER_NAME'};\n");
      p.print("  $http_url .= qq{:$ENV{'SERVER_PORT'}}\n");
      p.print("    if (( $secure && $ENV{'SERVER_PORT'} != 443)\n");
      p.print("     || (!$secure && $ENV{'SERVER_PORT'} != 80)\n");
      p.print("    );\n");
      p.print("  my $context = $ENV{'GERRIT_CONTEXT_PATH'};\n");
      p.print("  chop($context);\n");
      p.print("  $http_url .= qq{$context};\n");
      p.print("  $http_url .= qq{/a}\n");
      p.print("    unless $ENV{'GERRIT_ANONYMOUS_READ'};\n");
      p.print("  push @git_base_url_list, $http_url;\n");
      p.print("}\n");

      // Generate URLs using anonymous git://
      //
      String url = cfg.getString("gerrit", null, "canonicalGitUrl");
      if (url != null) {
        if (url.endsWith("/")) {
          url = url.substring(0, url.length() - 1);
        }
        p.print("if ($ENV{'GERRIT_ANONYMOUS_READ'}) {\n");
        p.print("  push @git_base_url_list, ");
        p.print(quoteForPerl(url));
        p.print(";\n");
        p.print("}\n");
      }

      // Generate URLs using authenticated ssh://
      //
      if (sshInfo != null && !sshInfo.getHostKeys().isEmpty()) {
        String sshAddr = sshInfo.getHostKeys().get(0).getHost();
        p.print("if ($ENV{'GERRIT_USER_NAME'}) {\n");
        p.print("  push @git_base_url_list, join('', 'ssh://'");
        p.print(", $ENV{'GERRIT_USER_NAME'}");
        p.print(", '@'");
        if (sshAddr.startsWith("*:") || "".equals(sshAddr)) {
          p.print(", $ENV{'SERVER_NAME'}");
        }
        if (sshAddr.startsWith("*")) {
          sshAddr = sshAddr.substring(1);
        }
        p.print(", " + quoteForPerl(sshAddr));
        p.print(");\n");
        p.print("}\n");
      }

      // Link back to Gerrit (when possible, to matching review record).
      // Supported gitweb's hash values are:
      // - (missing),
      // - HEAD,
      // - refs/heads/<branch>,
      // - refs/changes/*/<change>/*,
      // - <revision>.
      //
      p.print("sub add_review_link {\n");
      p.print("  my $h = shift;\n");
      p.print("  my $q;\n");
      p.print("  if (!$h || $h eq 'HEAD') {\n");
      p.print("    $q = qq{#/q/project:$ENV{'GERRIT_PROJECT_NAME'}};\n");
      p.print("  } elsif ($h =~ /^refs\\/heads\\/([-\\w]+)$/) {\n");
      p.print("    $q = qq{#/q/project:$ENV{'GERRIT_PROJECT_NAME'}");
      p.print("+branch:$1};\n"); // wrapped
      p.print("  } elsif ($h =~ /^refs\\/changes\\/\\d{2}\\/(\\d+)\\/\\d+$/) ");
      p.print("{\n"); // wrapped
      p.print("    $q = qq{#/c/$1};\n");
      p.print("  } else {\n");
      p.print("    $q = qq{#/q/$h};\n");
      p.print("  }\n");
      p.print("  my $r = qq{$ENV{'GERRIT_CONTEXT_PATH'}$q};\n");
      p.print("  push @{$feature{'actions'}{'default'}},\n");
      p.print("      ('review',$r,'commitdiff');\n");
      p.print("}\n");
      p.print("if ($cgi->param('hb')) {\n");
      p.print("  add_review_link(scalar $cgi->param('hb'));\n");
      p.print("} elsif ($cgi->param('h')) {\n");
      p.print("  add_review_link(scalar $cgi->param('h'));\n");
      p.print("} else {\n");
      p.print("  add_review_link();\n");
      p.print("}\n");

      // If the administrator has created a site-specific gitweb_config,
      // load that before we perform any final overrides.
      //
      Path sitecfg = site.site_gitweb;
      if (Files.isRegularFile(sitecfg)) {
        p.print("$GITWEB_CONFIG = " + quoteForPerl(sitecfg) + ";\n");
        p.print("if (-e $GITWEB_CONFIG) {\n");
        p.print("  do " + quoteForPerl(sitecfg) + ";\n");
        p.print("}\n");
      }

      p.print("$projectroot = $ENV{'GITWEB_PROJECTROOT'};\n");

      // Permit exporting only the project we were started for.
      // We use the name under $projectroot in case symlinks
      // were involved in the path.
      //
      p.print("$export_auth_hook = sub {\n");
      p.print("    my $dir = shift;\n");
      p.print("    my $name = $ENV{'GERRIT_PROJECT_NAME'};\n");
      p.print("    my $allow = qq{$projectroot/$name.git};\n");
      p.print("    return $dir eq $allow;\n");
      p.print("  };\n");

      // Do not allow the administrator to enable path info, its
      // not a URL format we currently support.
      //
      p.print("$feature{'pathinfo'}{'override'} = 0;\n");
      p.print("$feature{'pathinfo'}{'default'} = [0];\n");

      // We don't do forking, so don't allow it to be enabled.
      //
      p.print("$feature{'forks'}{'override'} = 0;\n");
      p.print("$feature{'forks'}{'default'} = [0];\n");
    }

    myconfFile.setReadOnly();
  }

  private static String quoteForPerl(Path value) {
    return quoteForPerl(value.toAbsolutePath().toString());
  }

  private static String quoteForPerl(String value) {
    if (value == null || value.isEmpty()) {
      return "''";
    }
    if (!value.contains("'")) {
      return "'" + value + "'";
    }
    if (!value.contains("{") && !value.contains("}")) {
      return "q{" + value + "}";
    }
    throw new IllegalArgumentException("Cannot quote in Perl: " + value);
  }

  @Override
  protected void service(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
    if (req.getQueryString() == null || req.getQueryString().isEmpty()) {
      // No query string? They want the project list, which we don't
      // currently support. Return to Gerrit's own web UI.
      //
      rsp.sendRedirect(req.getContextPath() + "/");
      return;
    }

    final Map<String, String> params = getParameters(req);
    String a = params.get("a");
    if (a != null) {
      if (deniedActions.contains(a)) {
        rsp.sendError(HttpServletResponse.SC_FORBIDDEN);
        return;
      }

      if (a.equals(PROJECT_LIST_ACTION)) {
        rsp.sendRedirect(
            req.getContextPath()
                + "/#"
                + PageLinks.ADMIN_PROJECTS
                + "?filter="
                + Url.encode(params.get("pf") + "/"));
        return;
      }
    }

    String name = params.get("p");
    if (name == null) {
      rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
      return;
    }
    if (name.endsWith(".git")) {
      name = name.substring(0, name.length() - 4);
    }

    Project.NameKey nameKey = Project.nameKey(name);
    ProjectState projectState;
    try {
      projectState = projectCache.checkedGet(nameKey);
      if (projectState == null) {
        sendErrorOrRedirect(req, rsp, HttpServletResponse.SC_NOT_FOUND);
        return;
      }

      projectState.checkStatePermitsRead();
      permissionBackend.user(userProvider.get()).project(nameKey).check(ProjectPermission.READ);
    } catch (AuthException e) {
      sendErrorOrRedirect(req, rsp, HttpServletResponse.SC_NOT_FOUND);
      return;
    } catch (IOException | PermissionBackendException err) {
      logger.atSevere().withCause(err).log("cannot load %s", name);
      rsp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
      return;
    } catch (ResourceConflictException e) {
      sendErrorOrRedirect(req, rsp, HttpServletResponse.SC_CONFLICT);
      return;
    }

    try (Repository repo = repoManager.openRepository(nameKey)) {
      CacheHeaders.setNotCacheable(rsp);
      exec(req, rsp, projectState);
    } catch (RepositoryNotFoundException e) {
      getServletContext().log("Cannot open repository", e);
      rsp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    }
  }

  /**
   * Sends error response if the user is authenticated. Or redirect the user to the login page. By
   * doing this, anonymous users cannot infer the existence of a resource from the status code.
   */
  private void sendErrorOrRedirect(HttpServletRequest req, HttpServletResponse rsp, int statusCode)
      throws IOException {
    if (userProvider.get().isIdentifiedUser()) {
      rsp.sendError(statusCode);
    } else {
      rsp.sendRedirect(getLoginRedirectUrl(req));
    }
  }

  private static String getLoginRedirectUrl(HttpServletRequest req) {
    String contextPath = req.getContextPath();
    String loginUrl = contextPath + "/login/";
    String token = req.getRequestURI();
    if (!contextPath.isEmpty()) {
      token = token.substring(contextPath.length());
    }

    String queryString = req.getQueryString();
    if (queryString != null && !queryString.isEmpty()) {
      token = token + "?" + queryString;
    }
    return (loginUrl + Url.encode(token));
  }

  private static Map<String, String> getParameters(HttpServletRequest req) {
    final Map<String, String> params = new HashMap<>();
    for (String pair : Splitter.on(CharMatcher.anyOf("&;")).split(req.getQueryString())) {
      final int eq = pair.indexOf('=');
      if (0 < eq) {
        String name = pair.substring(0, eq);
        String value = pair.substring(eq + 1);

        name = Url.decode(name);
        value = Url.decode(value);
        params.put(name, value);
      }
    }
    return params;
  }

  private void exec(HttpServletRequest req, HttpServletResponse rsp, ProjectState projectState)
      throws IOException {
    final Process proc =
        Runtime.getRuntime()
            .exec(
                new String[] {gitwebCgi.toAbsolutePath().toString()},
                makeEnv(req, projectState),
                gitwebCgi.toAbsolutePath().getParent().toFile());

    copyStderrToLog(proc.getErrorStream());
    if (0 < req.getContentLength()) {
      copyContentToCGI(req, proc.getOutputStream());
    } else {
      proc.getOutputStream().close();
    }

    try (InputStream in = new BufferedInputStream(proc.getInputStream(), bufferSize)) {
      readCgiHeaders(rsp, in);

      try (OutputStream out = rsp.getOutputStream()) {
        final byte[] buf = new byte[bufferSize];
        int n;
        while ((n = in.read(buf)) > 0) {
          out.write(buf, 0, n);
        }
      }
    } catch (IOException e) {
      // The browser has probably closed its input stream. We don't
      // want to continue executing this request.
      //
      proc.destroy();
      return;
    }

    try {
      proc.waitFor();

      final int status = proc.exitValue();
      if (0 != status) {
        logger.atSevere().log("Non-zero exit status (%d) from %s", status, gitwebCgi);
        if (!rsp.isCommitted()) {
          rsp.sendError(500);
        }
      }
    } catch (InterruptedException ie) {
      logger.atFine().log("CGI: interrupted waiting for CGI to terminate");
    }
  }

  private String[] makeEnv(HttpServletRequest req, ProjectState projectState) {
    final EnvList env = new EnvList(_env);
    final int contentLength = Math.max(0, req.getContentLength());

    // These ones are from "The WWW Common Gateway Interface Version 1.1"
    //
    env.set("AUTH_TYPE", req.getAuthType());
    env.set("CONTENT_LENGTH", Integer.toString(contentLength));
    env.set("CONTENT_TYPE", req.getContentType());
    env.set("GATEWAY_INTERFACE", "CGI/1.1");
    env.set("PATH_INFO", req.getPathInfo());
    env.set("PATH_TRANSLATED", null);
    env.set("QUERY_STRING", req.getQueryString());
    env.set("REMOTE_ADDR", req.getRemoteAddr());
    env.set("REMOTE_HOST", req.getRemoteHost());
    env.set("HTTPS", req.isSecure() ? "ON" : "OFF");

    // The identity information reported about the connection by a
    // RFC 1413 [11] request to the remote agent, if
    // available. Servers MAY choose not to support this feature, or
    // not to request the data for efficiency reasons.
    // "REMOTE_IDENT" => "NYI"
    //
    env.set("REQUEST_METHOD", req.getMethod());
    env.set("SCRIPT_NAME", req.getContextPath() + req.getServletPath());
    env.set("SCRIPT_FILENAME", gitwebCgi.toAbsolutePath().toString());
    env.set("SERVER_NAME", req.getServerName());
    env.set("SERVER_PORT", Integer.toString(req.getServerPort()));
    env.set("SERVER_PROTOCOL", req.getProtocol());
    env.set("SERVER_SOFTWARE", getServletContext().getServerInfo());

    final Enumeration<String> hdrs = enumerateHeaderNames(req);
    while (hdrs.hasMoreElements()) {
      final String name = hdrs.nextElement();
      final String value = req.getHeader(name);
      env.set("HTTP_" + name.toUpperCase().replace('-', '_'), value);
    }

    Project.NameKey nameKey = projectState.getNameKey();
    env.set("GERRIT_CONTEXT_PATH", req.getContextPath() + "/");
    env.set("GERRIT_PROJECT_NAME", nameKey.get());

    env.set("GITWEB_PROJECTROOT", repoManager.getBasePath(nameKey).toAbsolutePath().toString());

    if (projectState.statePermitsRead()
        && permissionBackend
            .user(anonymousUserProvider.get())
            .project(nameKey)
            .testOrFalse(ProjectPermission.READ)) {
      env.set("GERRIT_ANONYMOUS_READ", "1");
    }

    String remoteUser = null;
    if (userProvider.get().isIdentifiedUser()) {
      IdentifiedUser u = userProvider.get().asIdentifiedUser();
      Optional<String> user = u.getUserName();
      env.set("GERRIT_USER_NAME", user.orElse(null));
      remoteUser = user.orElseGet(() -> "account-" + u.getAccountId());
    }
    env.set("REMOTE_USER", remoteUser);

    // Override CGI settings using alternative URI provided by gitweb.url.
    // This is required to trick gitweb into thinking that it's served under
    // different URL. Setting just $my_uri on the perl's side isn't enough,
    // because few actions (atom, blobdiff_plain, commitdiff_plain) rely on
    // URL returned by $cgi->self_url().
    //
    if (gitwebUrl != null) {
      int schemePort = -1;

      if (gitwebUrl.getScheme() != null) {
        if (gitwebUrl.getScheme().equals("http")) {
          env.set("HTTPS", "OFF");
          schemePort = 80;
        } else {
          env.set("HTTPS", "ON");
          schemePort = 443;
        }
      }

      if (gitwebUrl.getHost() != null) {
        env.set("SERVER_NAME", gitwebUrl.getHost());
        env.set("HTTP_HOST", gitwebUrl.getHost());
      }

      if (gitwebUrl.getPort() != -1) {
        env.set("SERVER_PORT", Integer.toString(gitwebUrl.getPort()));
      } else if (schemePort != -1) {
        env.set("SERVER_PORT", Integer.toString(schemePort));
      }

      if (gitwebUrl.getPath() != null) {
        env.set("SCRIPT_NAME", gitwebUrl.getPath().isEmpty() ? "/" : gitwebUrl.getPath());
      }
    }

    return env.getEnvArray();
  }

  private void copyContentToCGI(HttpServletRequest req, OutputStream dst) throws IOException {
    final int contentLength = req.getContentLength();
    final InputStream src = req.getInputStream();
    new Thread(
            () -> {
              try {
                try {
                  final byte[] buf = new byte[bufferSize];
                  int remaining = contentLength;
                  while (0 < remaining) {
                    final int max = Math.max(buf.length, remaining);
                    final int n = src.read(buf, 0, max);
                    if (n < 0) {
                      throw new EOFException("Expected " + remaining + " more bytes");
                    }
                    dst.write(buf, 0, n);
                    remaining -= n;
                  }
                } finally {
                  dst.close();
                }
              } catch (IOException e) {
                logger.atSevere().withCause(e).log("Unexpected error copying input to CGI");
              }
            },
            "Gitweb-InputFeeder")
        .start();
  }

  private void copyStderrToLog(InputStream in) {
    new Thread(
            () -> {
              try (BufferedReader br =
                  new BufferedReader(new InputStreamReader(in, ISO_8859_1.name()))) {
                String err =
                    br.lines()
                        .filter(s -> !s.isEmpty())
                        .map(s -> "CGI: " + s)
                        .collect(Collectors.joining("\n"))
                        .trim();
                if (!err.isEmpty()) {
                  logger.atSevere().log(err);
                }
              } catch (IOException e) {
                logger.atSevere().withCause(e).log("Unexpected error copying stderr from CGI");
              }
            },
            "Gitweb-ErrorLogger")
        .start();
  }

  private static Enumeration<String> enumerateHeaderNames(HttpServletRequest req) {
    return req.getHeaderNames();
  }

  private void readCgiHeaders(HttpServletResponse res, InputStream in) throws IOException {
    String line;
    while (!(line = readLine(in)).isEmpty()) {
      if (line.startsWith("HTTP")) {
        // CGI believes it is a non-parsed-header CGI. We refuse
        // to support that here so abort.
        //
        throw new IOException("NPH CGI not supported: " + line);
      }

      final int sep = line.indexOf(':');
      if (sep < 0) {
        throw new IOException("CGI returned invalid header: " + line);
      }

      final String key = line.substring(0, sep).trim();
      final String value = line.substring(sep + 1).trim();
      if ("Location".equalsIgnoreCase(key)) {
        res.sendRedirect(value);

      } else if ("Status".equalsIgnoreCase(key)) {
        final List<String> token = Splitter.on(' ').splitToList(value);
        final int status = Integer.parseInt(token.get(0));
        res.setStatus(status);

      } else {
        res.addHeader(key, value);
      }
    }
  }

  private String readLine(InputStream in) throws IOException {
    final StringBuilder buf = new StringBuilder();
    int b;
    while ((b = in.read()) != -1 && b != '\n') {
      buf.append((char) b);
    }
    return buf.toString().trim();
  }

  /** private utility class that manages the Environment passed to exec. */
  private static class EnvList {
    private Map<String, String> envMap;

    EnvList() {
      envMap = new HashMap<>();
    }

    EnvList(EnvList l) {
      envMap = new HashMap<>(l.envMap);
    }

    /** Set a name/value pair, null values will be treated as an empty String */
    public void set(String name, String value) {
      if (value == null) {
        value = "";
      }
      envMap.put(name, name + "=" + value);
    }

    /** Get representation suitable for passing to exec. */
    public String[] getEnvArray() {
      return envMap.values().toArray(new String[envMap.size()]);
    }

    @Override
    public String toString() {
      return envMap.toString();
    }
  }
}
