示例#1
0
  @Override
  protected void service(final HttpServletRequest req, final 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);
    }

    final Project.NameKey nameKey = new Project.NameKey(name);
    final ProjectControl project;
    try {
      project = projectControl.validateFor(nameKey);
      if (!project.allRefsAreVisible() && !project.isOwner()) {
        // Pretend the project doesn't exist
        throw new NoSuchProjectException(nameKey);
      }
    } catch (NoSuchProjectException e) {
      if (userProvider.get().isIdentifiedUser()) {
        rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
      } else {
        // Allow anonymous users a chance to login.
        // Avoid leaking information by not distinguishing between
        // project not existing and no access rights.
        rsp.sendRedirect(getLoginRedirectUrl(req));
      }
      return;
    }

    try (Repository repo = repoManager.openRepository(nameKey)) {
      CacheHeaders.setNotCacheable(rsp);
      exec(req, rsp, project);
    } catch (RepositoryNotFoundException e) {
      getServletContext().log("Cannot open repository", e);
      rsp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    }
  }
示例#2
0
  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("  $http_url .= qq{$ENV{'GERRIT_CONTEXT_PATH'}p};\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($cgi->param('hb'));\n");
      p.print("} elsif ($cgi->param('h')) {\n");
      p.print("  add_review_link($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");
      }

      Path root = repoManager.getBasePath();
      p.print("$projectroot = " + quoteForPerl(root) + ";\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();
  }