Limit archives to only enabled formats

Refactor the configuration of enabled archives to be known to the
GetArchive REST API handler so it can allow only formats that have
been enabled by the administrator.

Use the order listed in download.archive to configure the web
interface, with no formats enabled if the list is empty.

Default to all archive formats enabled, matching the schemes.

Change-Id: I29436f13bbc6fd4a20a7d9151e7f47186f5fbf4b
This commit is contained in:
Shawn Pearce
2014-03-26 22:00:26 -07:00
parent 3c63cb8463
commit 6edde31009
7 changed files with 88 additions and 68 deletions

View File

@@ -1330,7 +1330,8 @@ screen:
archive = txz
----
Defaults to no archive commands.
If `download.archive` is not specified defaults to all archive
commands. Set to `off` or empty string to disable.
[[gerrit]]
=== Section gerrit

View File

@@ -19,10 +19,10 @@ import com.google.gerrit.reviewdb.client.Account.FieldName;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.DownloadCommand;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.DownloadScheme;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.ArchiveFormat;
import com.google.gerrit.reviewdb.client.AuthType;
import com.google.gerrit.reviewdb.client.Project;
import java.util.List;
import java.util.Set;
public class GerritConfig implements Cloneable {
@@ -54,7 +54,7 @@ public class GerritConfig implements Cloneable {
protected int suggestFrom;
protected int changeUpdateDelay;
protected AccountGeneralPreferences.ChangeScreen changeScreen;
protected Set<ArchiveFormat> archiveFormats;
protected List<String> archiveFormats;
protected int largeChangeSize;
protected boolean newFeatures;
@@ -293,11 +293,11 @@ public class GerritConfig implements Cloneable {
this.largeChangeSize = largeChangeSize;
}
public Set<ArchiveFormat> getArchiveFormats() {
public List<String> getArchiveFormats() {
return archiveFormats;
}
public void setArchiveFormats(Set<ArchiveFormat> formats) {
public void setArchiveFormats(List<String> formats) {
archiveFormats = formats;
}

View File

@@ -25,7 +25,6 @@ import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.client.rpc.RestApi;
import com.google.gerrit.extensions.common.ListChangesOption;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.ArchiveFormat;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.DownloadScheme;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gwt.core.client.JavaScriptObject;
@@ -45,10 +44,8 @@ import java.util.ArrayList;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
class DownloadBox extends VerticalPanel {
private final static String ARCHIVE[] = {"tar", "tbz2", "tgz", "txz"};
private final ChangeInfo change;
private final String revision;
private final PatchSet.Id psId;
@@ -149,23 +146,22 @@ class DownloadBox extends VerticalPanel {
}
private void insertArchive() {
Set<ArchiveFormat> activated = Gerrit.getConfig().getArchiveFormats();
if (activated.contains(ArchiveFormat.OFF)) {
List<String> activated = Gerrit.getConfig().getArchiveFormats();
if (activated.isEmpty()) {
return;
}
List<Anchor> anchors = new ArrayList<>(activated.size());
for (String f : ARCHIVE) {
if (activated.contains(ArchiveFormat.valueOf(f.toUpperCase()))) {
Anchor archive = new Anchor(f);
archive.setHref(new RestApi("/changes/")
.id(psId.getParentKey().get())
.view("revisions")
.id(revision)
.view("archive")
.addParameter("format", f)
.url());
anchors.add(archive);
}
for (String f : activated) {
Anchor archive = new Anchor(f);
archive.setHref(new RestApi("/changes/")
.id(psId.getParentKey().get())
.view("revisions")
.id(revision)
.view("archive")
.addParameter("format", f)
.url());
anchors.add(archive);
}
HorizontalPanel p = new HorizontalPanel();

View File

@@ -14,12 +14,16 @@
package com.google.gerrit.httpd;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.gerrit.common.data.GerritConfig;
import com.google.gerrit.common.data.GitwebConfig;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.ArchiveFormat;
import com.google.gerrit.server.account.Realm;
import com.google.gerrit.server.change.ArchiveFormat;
import com.google.gerrit.server.change.GetArchive;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.config.AnonymousCowardName;
import com.google.gerrit.server.config.AuthConfig;
@@ -37,7 +41,6 @@ import org.eclipse.jgit.lib.Config;
import java.net.MalformedURLException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -48,6 +51,7 @@ class GerritConfigProvider implements Provider<GerritConfig> {
private final Config cfg;
private final AuthConfig authConfig;
private final DownloadConfig downloadConfig;
private final GetArchive.AllowedFormats archiveFormats;
private final GitWebConfig gitWebConfig;
private final AllProjectsName wildProject;
private final SshInfo sshInfo;
@@ -62,11 +66,13 @@ class GerritConfigProvider implements Provider<GerritConfig> {
final AuthConfig ac, final GitWebConfig gwc, final AllProjectsName wp,
final SshInfo si, final ContactStore cs,
final ServletContext sc, final DownloadConfig dc,
final GetArchive.AllowedFormats af,
final @AnonymousCowardName String acn) {
realm = r;
cfg = gsc;
authConfig = ac;
downloadConfig = dc;
archiveFormats = af;
gitWebConfig = gwc;
sshInfo = si;
wildProject = wp;
@@ -130,11 +136,14 @@ class GerritConfigProvider implements Provider<GerritConfig> {
"gerrit", null, "changeScreen",
AccountGeneralPreferences.ChangeScreen.CHANGE_SCREEN2));
config.setLargeChangeSize(cfg.getInt("change", "largeChange", 500));
List<ArchiveFormat> allArchiveFormats =
ConfigUtil.getEnumList(cfg, "download", null, "archive",
ArchiveFormat.OFF);
config.setArchiveFormats(new HashSet<>(allArchiveFormats));
config.setArchiveFormats(Lists.newArrayList(Iterables.transform(
archiveFormats.getAllowed(),
new Function<ArchiveFormat, String>() {
@Override
public String apply(ArchiveFormat in) {
return in.getShortName();
}
})));
config.setNewFeatures(cfg.getBoolean("gerrit", "enableNewFeatures", true));

View File

@@ -35,10 +35,6 @@ public final class AccountGeneralPreferences {
REPO_DOWNLOAD, PULL, CHECKOUT, CHERRY_PICK, FORMAT_PATCH, DEFAULT_DOWNLOADS
}
public static enum ArchiveFormat {
OFF, TAR, TBZ2, TGZ, TXZ
}
public static enum DateFormat {
/** US style dates: Apr 27, Feb 14, 2010 */
STD("MMM d", "MMM d, yyyy"),

View File

@@ -14,20 +14,13 @@
package com.google.gerrit.server.change;
import com.google.common.collect.Maps;
import org.eclipse.jgit.api.ArchiveCommand;
import org.eclipse.jgit.archive.TarFormat;
import org.eclipse.jgit.archive.Tbz2Format;
import org.eclipse.jgit.archive.TgzFormat;
import org.eclipse.jgit.archive.TxzFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collections;
import java.util.Map;
enum ArchiveFormat {
public enum ArchiveFormat {
TGZ("application/x-gzip", new TgzFormat()),
TAR("application/x-tar", new TarFormat()),
TBZ2("application/x-bzip2", new Tbz2Format()),
@@ -35,8 +28,6 @@ enum ArchiveFormat {
// Zip is not supported because it may be interpreted by a Java plugin as a
// valid JAR file, whose code would have access to cookies on the domain.
static final Logger log = LoggerFactory.getLogger(ArchiveFormat.class);
private final ArchiveCommand.Format<?> format;
private final String mimeType;
@@ -46,7 +37,7 @@ enum ArchiveFormat {
ArchiveCommand.registerFormat(name(), format);
}
String getShortName() {
public String getShortName() {
return name().toLowerCase();
}
@@ -61,24 +52,4 @@ enum ArchiveFormat {
Iterable<String> getSuffixes() {
return format.suffixes();
}
static Map<String, ArchiveFormat> init() {
String[] formats = new String[values().length];
for (int i = 0; i < values().length; i++) {
formats[i] = values()[i].name();
}
Map<String, ArchiveFormat> exts = Maps.newLinkedHashMap();
for (String name : formats) {
try {
ArchiveFormat format = valueOf(name.toUpperCase());
for (String ext : format.getSuffixes()) {
exts.put(ext, format);
}
} catch (IllegalArgumentException e) {
log.warn("Invalid archive.format {}", name);
}
}
return Collections.unmodifiableMap(exts);
}
}

View File

@@ -15,14 +15,19 @@
package com.google.gerrit.server.change;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.BinaryResult;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.server.config.ConfigUtil;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.eclipse.jgit.api.ArchiveCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
@@ -31,18 +36,60 @@ import org.kohsuke.args4j.Option;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
public class GetArchive implements RestReadView<RevisionResource> {
@Singleton
public static class AllowedFormats {
final ImmutableMap<String, ArchiveFormat> extensions;
final Set<ArchiveFormat> allowed;
@Inject
AllowedFormats(@GerritServerConfig Config cfg) {
Collection<ArchiveFormat> enabled;
String v = cfg.getString("download", null, "archive");
if (v == null) {
enabled = Arrays.asList(ArchiveFormat.values());
} else if (v.isEmpty() || "off".equalsIgnoreCase(v)) {
enabled = Collections.emptyList();
} else {
enabled = ConfigUtil.getEnumList(cfg,
"download", null, "archive",
ArchiveFormat.TGZ);
}
Map<String, ArchiveFormat> exts = new HashMap<>();
for (ArchiveFormat format : enabled) {
for (String ext : format.getSuffixes()) {
exts.put(ext, format);
}
exts.put(format.name().toLowerCase(), format);
}
extensions = ImmutableMap.copyOf(exts);
allowed = Collections.unmodifiableSet(new LinkedHashSet<>(enabled));
}
public Set<ArchiveFormat> getAllowed() {
return allowed;
}
}
class GetArchive implements RestReadView<RevisionResource> {
private static final Map<String, ArchiveFormat> formats = ArchiveFormat.init();
private final GitRepositoryManager repoManager;
private final AllowedFormats allowedFormats;
@Option(name = "--format")
private String format;
@Inject
GetArchive(GitRepositoryManager repoManager) {
GetArchive(GitRepositoryManager repoManager, AllowedFormats allowedFormats) {
this.repoManager = repoManager;
this.allowedFormats = allowedFormats;
}
@Override
@@ -51,7 +98,7 @@ class GetArchive implements RestReadView<RevisionResource> {
if (Strings.isNullOrEmpty(format)) {
throw new BadRequestException("format is not specified");
}
final ArchiveFormat f = formats.get("." + format);
final ArchiveFormat f = allowedFormats.extensions.get("." + format);
if (f == null) {
throw new BadRequestException("unknown archive format");
}