All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gerrit.httpd.GitWebConfig Maven / Gradle / Ivy

There is a newer version: 3.10.0-rc5
Show newest version
// 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.

package com.google.gerrit.httpd;

import com.google.gerrit.common.data.GitWebType;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.SitePaths;
import com.google.inject.Inject;

import org.eclipse.jgit.lib.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;

public class GitWebConfig {
  private static final Logger log = LoggerFactory.getLogger(GitWebConfig.class);

  private final String url;
  private final File gitweb_cgi;
  private final File gitweb_css;
  private final File gitweb_js;
  private final File git_logo_png;
  private GitWebType type;

  @Inject
  GitWebConfig(final SitePaths sitePaths, @GerritServerConfig final Config cfg) {
    final String cfgUrl = cfg.getString("gitweb", null, "url");
    final String cfgCgi = cfg.getString("gitweb", null, "cgi");

    type = GitWebType.fromName(cfg.getString("gitweb", null, "type"));
    if (type == null) {
      url = null;
      gitweb_cgi = null;
      gitweb_css = null;
      gitweb_js = null;
      git_logo_png = null;
      return;
    }

    type.setLinkName(cfg.getString("gitweb", null, "linkname"));
    type.setBranch(cfg.getString("gitweb", null, "branch"));
    type.setProject(cfg.getString("gitweb", null, "project"));
    type.setRevision(cfg.getString("gitweb", null, "revision"));
    type.setRootTree(cfg.getString("gitweb", null, "roottree"));
    type.setFile(cfg.getString("gitweb", null, "file"));
    type.setFileHistory(cfg.getString("gitweb", null, "filehistory"));
    type.setLinkDrafts(cfg.getBoolean("gitweb", null, "linkdrafts", true));
    type.setUrlEncode(cfg.getBoolean("gitweb", null, "urlencode", true));
    String pathSeparator = cfg.getString("gitweb", null, "pathSeparator");
    if (pathSeparator != null) {
      if (pathSeparator.length() == 1) {
        char c = pathSeparator.charAt(0);
        if (isValidPathSeparator(c)) {
          type.setPathSeparator(c);
        } else {
          log.warn("Invalid value specified for gitweb.pathSeparator: " + c);
        }
      } else {
        log.warn("Value specified for gitweb.pathSeparator is not a single character:" + pathSeparator);
      }
    }

    if (type.getBranch() == null) {
      log.warn("No Pattern specified for gitweb.branch, disabling.");
      type = null;
    } else if (type.getProject() == null) {
      log.warn("No Pattern specified for gitweb.project, disabling.");
      type = null;
    } else if (type.getRevision() == null) {
      log.warn("No Pattern specified for gitweb.revision, disabling.");
      type = null;
    } else if (type.getRootTree() == null) {
      log.warn("No Pattern specified for gitweb.roottree, disabling.");
      type = null;
    } else if (type.getFile() == null) {
      log.warn("No Pattern specified for gitweb.file, disabling.");
      type = null;
    } else if (type.getFileHistory() == null) {
      log.warn("No Pattern specified for gitweb.filehistory, disabling.");
      type = null;
    }

    if ((cfgUrl != null && cfgUrl.isEmpty())
        || (cfgCgi != null && cfgCgi.isEmpty())) {
      // Either setting was explicitly set to the empty string disabling
      // gitweb for this server. Disable the configuration.
      //
      url = null;
      gitweb_cgi = null;
      gitweb_css = null;
      gitweb_js = null;
      git_logo_png = null;
      return;
    }

    if ((cfgUrl != null) && (cfgCgi == null || cfgCgi.isEmpty())) {
      // Use an externally managed gitweb instance, and not an internal one.
      //
      url = cfgUrl;
      gitweb_cgi = null;
      gitweb_css = null;
      gitweb_js = null;
      git_logo_png = null;
      return;
    }

    final File pkgCgi = new File("/usr/lib/cgi-bin/gitweb.cgi");
    String[] resourcePaths = {"/usr/share/gitweb/static", "/usr/share/gitweb",
        "/var/www/static", "/var/www"};
    File cgi;

    if (cfgCgi != null) {
      // Use the CGI script configured by the administrator, failing if it
      // cannot be used as specified.
      //
      cgi = sitePaths.resolve(cfgCgi);
      if (!cgi.isFile()) {
        throw new IllegalStateException("Cannot find gitweb.cgi: " + cgi);
      }
      if (!cgi.canExecute()) {
        throw new IllegalStateException("Cannot execute gitweb.cgi: " + cgi);
      }

      if (!cgi.equals(pkgCgi)) {
        // Assume the administrator pointed us to the distribution,
        // which also has the corresponding CSS and logo file.
        //
        String absPath = cgi.getParentFile().getAbsolutePath();
        resourcePaths = new String[] {absPath + "/static", absPath};
      }

    } else if (pkgCgi.isFile() && pkgCgi.canExecute()) {
      // Use the OS packaged CGI.
      //
      log.debug("Assuming gitweb at " + pkgCgi);
      cgi = pkgCgi;

    } else {
      log.warn("gitweb not installed (no " + pkgCgi + " found)");
      cgi = null;
      resourcePaths = new String[] {};
    }

    File css = null, js = null, logo = null;
    for (String path : resourcePaths) {
      File dir = new File(path);
      css = new File(dir, "gitweb.css");
      js = new File(dir, "gitweb.js");
      logo = new File(dir, "git-logo.png");
      if (css.isFile() && logo.isFile()) {
        break;
      }
    }

    if (cfgUrl == null || cfgUrl.isEmpty()) {
      url = cgi != null ? "gitweb" : null;
    } else {
      url = cgi != null ? cfgUrl : null;
    }
    gitweb_cgi = cgi;
    gitweb_css = css;
    gitweb_js = js;
    git_logo_png = logo;
  }

  /** @return GitWebType for gitweb viewer. */
  public GitWebType getGitWebType() {
    return type;
  }

  /**
   * @return URL of the entry point into gitweb. This URL may be relative to our
   *         context if gitweb is hosted by ourselves; or absolute if its hosted
   *         elsewhere; or null if gitweb has not been configured.
   */
  public String getUrl() {
    return url;
  }

  /** @return local path to the CGI executable; null if we shouldn't execute. */
  public File getGitwebCGI() {
    return gitweb_cgi;
  }

  /** @return local path of the {@code gitweb.css} matching the CGI. */
  public File getGitwebCSS() {
    return gitweb_css;
  }

  /** @return local path of the {@code gitweb.js} for the CGI. */
  public File getGitwebJS() {
    return gitweb_js;
  }

  /** @return local path of the {@code git-logo.png} for the CGI. */
  public File getGitLogoPNG() {
    return git_logo_png;
  }

  /**
   * Determines if a given character can be used unencoded in an URL as a
   * replacement for the path separator '/'.
   *
   * Reasoning: http://www.ietf.org/rfc/rfc1738.txt § 2.2:
   *
   * ... only alphanumerics, the special characters "$-_.+!*'(),", and
   *  reserved characters used for their reserved purposes may be used
   * unencoded within a URL.
   *
   * The following characters might occur in file names, however:
   *
   * alphanumeric characters,
   *
   * "$-_.+!',"
   */
  static boolean isValidPathSeparator(char c) {
    switch (c) {
      case '*':
      case '(':
      case ')':
        return true;
      default:
        return false;
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy