From a74ddc24545ec45d0bb82ca2bb8f628ffdaa9da3 Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Fri, 10 Oct 2014 12:04:39 -0400
Subject: [PATCH] Improve relative path determination using Java 7 Paths

---
 src/main/java/com/gitblit/servlet/RawServlet.java |   83 +++++++++++++++++++++++------------------
 1 files changed, 47 insertions(+), 36 deletions(-)

diff --git a/src/main/java/com/gitblit/servlet/RawServlet.java b/src/main/java/com/gitblit/servlet/RawServlet.java
index ff3f735..ac77646 100644
--- a/src/main/java/com/gitblit/servlet/RawServlet.java
+++ b/src/main/java/com/gitblit/servlet/RawServlet.java
@@ -101,7 +101,7 @@
 			fsc = c;
 		}
 		if (branch != null) {
-			branch = branch.replace('/', fsc);
+			branch = Repository.shortenRefName(branch).replace('/', fsc);
 		}
 
 		String encodedPath = path == null ? "" : path.replace(' ', '-');
@@ -172,7 +172,7 @@
 			} else {
 				repository = path.substring(0, slash);
 			}
-			offset += slash;
+			offset = ( slash + 1 );
 			r = repositoryManager.getRepository(repository, false);
 			if (repository.equals(path)) {
 				// either only repository in url or no repository found
@@ -245,41 +245,29 @@
 						}
 					}
 
-					setContentType(response, contentType);
-
 					if (isTextType(contentType)) {
 
 						// load, interpret, and serve text content as UTF-8
 						String [] encodings = runtimeManager.getSettings().getStrings(Keys.web.blobEncodings).toArray(new String[0]);
 						String content = JGitUtils.getStringContent(r, commit.getTree(), requestedPath, encodings);
+						if (content == null) {
+							logger.error("RawServlet Failed to load {} {} {}", repository, commit.getName(), path);
+							notFound(response, requestedPath, branch);
+							return;
+						}
 
 						byte [] bytes = content.getBytes(Constants.ENCODING);
+						setContentType(response, contentType);
 						response.setContentLength(bytes.length);
 						ByteArrayInputStream is = new ByteArrayInputStream(bytes);
 						sendContent(response, JGitUtils.getCommitDate(commit), is);
 
 					} else {
-						// serve binary content
-						String filename = StringUtils.getLastPathElement(requestedPath);
-						try {
-					    	String userAgent = request.getHeader("User-Agent");
-							if (userAgent != null && userAgent.indexOf("MSIE 5.5") > -1) {
-							      response.setHeader("Content-Disposition", "filename=\""
-							    		  +  URLEncoder.encode(filename, Constants.ENCODING) + "\"");
-							} else if (userAgent != null && userAgent.indexOf("MSIE") > -1) {
-							      response.setHeader("Content-Disposition", "attachment; filename=\""
-							    		  +  URLEncoder.encode(filename, Constants.ENCODING) + "\"");
-							} else {
-									response.setHeader("Content-Disposition", "attachment; filename=\""
-									      + new String(filename.getBytes(Constants.ENCODING), "latin1") + "\"");
-							}
-						}
-						catch (UnsupportedEncodingException e) {
-							response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
-						}
-
 						// stream binary content directly from the repository
-						streamFromRepo(response, r, commit, requestedPath);
+						if (!streamFromRepo(request, response, r, commit, requestedPath)) {
+							logger.error("RawServlet Failed to load {} {} {}", repository, commit.getName(), path);
+							notFound(response, requestedPath, branch);
+						}
 					}
 					return;
 				} catch (Exception e) {
@@ -339,11 +327,7 @@
 			// no content, document list or 404 page
 			if (pathEntries.isEmpty()) {
 				// default 404 page
-				String str = MessageFormat.format(
-						"# Error\nSorry, the requested resource **{0}** was not found.",
-						requestedPath);
-				response.setStatus(HttpServletResponse.SC_NOT_FOUND);
-				error(response, str);
+				notFound(response, requestedPath, branch);
 				return;
 			} else {
 				//
@@ -409,12 +393,10 @@
 		}
 	}
 
-	private void streamFromRepo(HttpServletResponse response, Repository repository,
+	protected boolean streamFromRepo(HttpServletRequest request, HttpServletResponse response, Repository repository,
 			RevCommit commit, String requestedPath) throws IOException {
 
-		response.setDateHeader("Last-Modified", JGitUtils.getCommitDate(commit).getTime());
-		response.setHeader("Cache-Control", "public, max-age=3600, must-revalidate");
-
+		boolean served = false;
 		RevWalk rw = new RevWalk(repository);
 		TreeWalk tw = new TreeWalk(repository);
 		try {
@@ -432,10 +414,30 @@
 				}
 				tw.getObjectId(id, 0);
 
+				String filename = StringUtils.getLastPathElement(requestedPath);
+				try {
+			    	String userAgent = request.getHeader("User-Agent");
+					if (userAgent != null && userAgent.indexOf("MSIE 5.5") > -1) {
+					      response.setHeader("Content-Disposition", "filename=\""
+					    		  +  URLEncoder.encode(filename, Constants.ENCODING) + "\"");
+					} else if (userAgent != null && userAgent.indexOf("MSIE") > -1) {
+					      response.setHeader("Content-Disposition", "attachment; filename=\""
+					    		  +  URLEncoder.encode(filename, Constants.ENCODING) + "\"");
+					} else {
+							response.setHeader("Content-Disposition", "attachment; filename=\""
+							      + new String(filename.getBytes(Constants.ENCODING), "latin1") + "\"");
+					}
+				}
+				catch (UnsupportedEncodingException e) {
+					response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
+				}
+
 				long len = reader.getObjectSize(id, org.eclipse.jgit.lib.Constants.OBJ_BLOB);
+				setContentType(response, "application/octet-stream");
 				response.setIntHeader("Content-Length", (int) len);
 				ObjectLoader ldr = repository.open(id);
 				ldr.copyTo(response.getOutputStream());
+				served = true;
 			}
 		} finally {
 			tw.release();
@@ -443,11 +445,11 @@
 		}
 
 		response.flushBuffer();
+		return served;
 	}
 
-	private void sendContent(HttpServletResponse response, Date date, InputStream is) throws ServletException, IOException {
-		response.setDateHeader("Last-Modified", date.getTime());
-		response.setHeader("Cache-Control", "public, max-age=3600, must-revalidate");
+	protected void sendContent(HttpServletResponse response, Date date, InputStream is) throws ServletException, IOException {
+
 		try {
 			byte[] tmp = new byte[8192];
 			int len = 0;
@@ -460,6 +462,15 @@
 		response.flushBuffer();
 	}
 
+	protected void notFound(HttpServletResponse response, String requestedPath, String branch)
+			throws ParseException, ServletException, IOException {
+		String str = MessageFormat.format(
+				"# Error\nSorry, the requested resource **{0}** was not found in **{1}**.",
+				requestedPath, branch);
+		response.setStatus(HttpServletResponse.SC_NOT_FOUND);
+		error(response, str);
+	}
+
 	private void error(HttpServletResponse response, String mkd) throws ServletException,
 			IOException, ParseException {
 		String content = MarkdownUtils.transformMarkdown(mkd);

--
Gitblit v1.9.1