/** * This file is part of git-as-svn. It is subject to the license terms * in the LICENSE file found in the top-level directory of this distribution * and at http://www.gnu.org/licenses/gpl-2.0.html. No part of git-as-svn, * including this file, may be copied, modified, propagated, or distributed * except according to the terms contained in the LICENSE file. */ package svnserver.server; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.tmatesoft.svn.core.SVNErrorCode; import org.tmatesoft.svn.core.SVNErrorMessage; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; import svnserver.StringHelper; import svnserver.auth.User; import svnserver.parser.SvnServerParser; import svnserver.parser.SvnServerWriter; import svnserver.repository.RepositoryInfo; import svnserver.repository.VcsAccess; import svnserver.repository.VcsFile; import svnserver.repository.VcsRepository; import svnserver.server.msg.ClientInfo; import svnserver.server.step.Step; import java.io.IOException; import java.util.*; /** * SVN client session context. * * @author Artem V. Navrotskiy <bozaro@users.noreply.github.com> */ public final class SessionContext { @NotNull private final SvnServerParser parser; @NotNull private final SvnServerWriter writer; @NotNull private final Deque<Step> stepStack = new ArrayDeque<>(); @NotNull private final SvnServer server; @NotNull private final RepositoryInfo repositoryInfo; @NotNull private final Set<String> capabilities; @NotNull private final VcsAccess acl; @NotNull private User user; @NotNull private String parent; public SessionContext(@NotNull SvnServerParser parser, @NotNull SvnServerWriter writer, @NotNull SvnServer server, @NotNull RepositoryInfo repositoryInfo, @NotNull ClientInfo clientInfo) throws SVNException { this.parser = parser; this.writer = writer; this.server = server; this.user = User.getAnonymous(); this.repositoryInfo = repositoryInfo; this.acl = getRepository().getContext().sure(VcsAccess.class); setParent(clientInfo.getUrl()); this.capabilities = new HashSet<>(Arrays.asList(clientInfo.getCapabilities())); } public boolean isCompressionEnabled() { return server.isCompressionEnabled() && hasCapability("svndiff1"); } public void authenticate(boolean allowAnonymous) throws IOException, SVNException { if (!user.isAnonymous()) { throw new IllegalStateException(); } this.user = server.authenticate(parser, writer, repositoryInfo, allowAnonymous); } public boolean hasCapability(@NotNull String capability) { return capabilities.contains(capability); } public void setParent(@NotNull SVNURL url) throws SVNException { this.parent = getRepositoryPath(url); } @NotNull public String getRepositoryPath(@NotNull String localPath) throws SVNException { return StringHelper.joinPath(parent, localPath); } @NotNull private String getRepositoryPath(@NotNull SVNURL url) throws SVNException { final String root = repositoryInfo.getBaseUrl().getPath(); final String path = url.getPath(); if (!path.startsWith(root)) { throw new SVNException(SVNErrorMessage.create(SVNErrorCode.BAD_URL, "Invalid relative path: " + path + " (base: " + root + ")")); } if (root.length() == path.length()) { return ""; } final boolean hasSlash = root.endsWith("/"); if ((!hasSlash) && (path.charAt(root.length()) != '/')) { throw new SVNException(SVNErrorMessage.create(SVNErrorCode.BAD_URL, "Invalid relative path: " + path + " (base: " + root + ")")); } return StringHelper.normalize(path.substring(root.length())); } @NotNull public User getUser() { return user; } @NotNull public VcsRepository getRepository() { return repositoryInfo.getRepository(); } @NotNull public SvnServerParser getParser() { return parser; } @NotNull public SvnServerWriter getWriter() { return writer; } public void push(@NotNull Step step) { stepStack.push(step); } @Nullable public Step poll() { return stepStack.poll(); } /** * Get repository file. * * @param rev Target revision. * @param path Target path or url. * @return Return file object. * @throws SVNException * @throws IOException */ @Nullable public VcsFile getFile(int rev, @NotNull String path) throws SVNException, IOException { return getRepository().getRevisionInfo(rev).getFile(getRepositoryPath(path)); } @Nullable public VcsFile getFile(int rev, @NotNull SVNURL url) throws SVNException, IOException { final String path = getRepositoryPath(url); checkRead(path); return getRepository().getRevisionInfo(rev).getFile(path); } public void checkRead(@Nullable String path) throws SVNException, IOException { acl.checkRead(user, path); } public void checkWrite(@Nullable String path) throws SVNException, IOException { acl.checkWrite(user, path); } }