From cb285cbfddfc0b633d6b8cdb4dc0d2bd2b8b51ef Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Thu, 05 Jan 2012 17:34:05 -0500
Subject: [PATCH] Fixed bug in receive hook for repositories in subfolders

---
 src/com/gitblit/FederationServlet.java |  208 +++++++++++++++++++++++----------------------------
 1 files changed, 95 insertions(+), 113 deletions(-)

diff --git a/src/com/gitblit/FederationServlet.java b/src/com/gitblit/FederationServlet.java
index 784ec33..e772050 100644
--- a/src/com/gitblit/FederationServlet.java
+++ b/src/com/gitblit/FederationServlet.java
@@ -15,31 +15,28 @@
  */
 package com.gitblit;
 
-import java.io.BufferedReader;
+import java.io.File;
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
-import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletResponse;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import com.gitblit.Constants.FederationRequest;
-import com.gitblit.Constants.FederationToken;
 import com.gitblit.models.FederationModel;
 import com.gitblit.models.FederationProposal;
-import com.gitblit.models.RepositoryModel;
+import com.gitblit.models.TeamModel;
 import com.gitblit.models.UserModel;
+import com.gitblit.utils.FederationUtils;
+import com.gitblit.utils.FileUtils;
 import com.gitblit.utils.HttpUtils;
 import com.gitblit.utils.StringUtils;
 import com.gitblit.utils.TimeUtils;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
 
 /**
  * Handles federation requests.
@@ -47,69 +44,37 @@
  * @author James Moger
  * 
  */
-public class FederationServlet extends HttpServlet {
+public class FederationServlet extends JsonServlet {
 
 	private static final long serialVersionUID = 1L;
-
-	private transient Logger logger = LoggerFactory.getLogger(FederationServlet.class);
 
 	public FederationServlet() {
 		super();
 	}
 
 	/**
-	 * Returns an url to this servlet for the specified parameters.
-	 * 
-	 * @param sourceURL
-	 *            the url of the source gitblit instance
-	 * @param token
-	 *            the federation token of the source gitblit instance
-	 * @param req
-	 *            the pull type request
-	 */
-	public static String asFederationLink(String sourceURL, String token, FederationRequest req) {
-		return asFederationLink(sourceURL, null, token, req, null);
-	}
-
-	/**
-	 * 
-	 * @param remoteURL
-	 *            the url of the remote gitblit instance
-	 * @param tokenType
-	 *            the type of federation token of a gitblit instance
-	 * @param token
-	 *            the federation token of a gitblit instance
-	 * @param req
-	 *            the pull type request
-	 * @param myURL
-	 *            the url of this gitblit instance
-	 * @return
-	 */
-	public static String asFederationLink(String remoteURL, FederationToken tokenType,
-			String token, FederationRequest req, String myURL) {
-		if (remoteURL.length() > 0 && remoteURL.charAt(remoteURL.length() - 1) == '/') {
-			remoteURL = remoteURL.substring(0, remoteURL.length() - 1);
-		}
-		if (req == null) {
-			req = FederationRequest.PULL_REPOSITORIES;
-		}
-		return remoteURL + Constants.FEDERATION_PATH + "?req=" + req.name().toLowerCase()
-				+ (token == null ? "" : ("&token=" + token))
-				+ (tokenType == null ? "" : ("&tokenType=" + tokenType.name().toLowerCase()))
-				+ (myURL == null ? "" : ("&url=" + StringUtils.encodeURL(myURL)));
-	}
-
-	/**
-	 * Returns the list of repositories for federation requests.
+	 * Processes a federation request.
 	 * 
 	 * @param request
 	 * @param response
 	 * @throws javax.servlet.ServletException
 	 * @throws java.io.IOException
 	 */
-	private void processRequest(javax.servlet.http.HttpServletRequest request,
+
+	@Override
+	protected void processRequest(javax.servlet.http.HttpServletRequest request,
 			javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException,
 			java.io.IOException {
+		FederationRequest reqType = FederationRequest.fromName(request.getParameter("req"));
+		logger.info(MessageFormat.format("Federation {0} request from {1}", reqType,
+				request.getRemoteAddr()));
+
+		if (FederationRequest.POKE.equals(reqType)) {
+			// Gitblit always responds to POKE requests to verify a connection
+			logger.info("Received federation POKE from " + request.getRemoteAddr());
+			return;
+		}
+
 		if (!GitBlit.getBoolean(Keys.git.enableGitServlet, true)) {
 			logger.warn(Keys.git.enableGitServlet + " must be set TRUE for federation requests.");
 			response.sendError(HttpServletResponse.SC_FORBIDDEN);
@@ -124,38 +89,32 @@
 			return;
 		}
 
-		String token = request.getParameter("token");
-		FederationRequest reqType = FederationRequest.fromName(request.getParameter("req"));
-		logger.info(MessageFormat.format("Federation {0} request from {1}", reqType,
-				request.getRemoteAddr()));
-
 		if (FederationRequest.PROPOSAL.equals(reqType)) {
 			// Receive a gitblit federation proposal
-			BufferedReader reader = request.getReader();
-			StringBuilder json = new StringBuilder();
-			String line = null;
-			while ((line = reader.readLine()) != null) {
-				json.append(line);
-			}
-			reader.close();
-
-			// check to see if we have proposal data
-			if (json.length() == 0) {
-				logger.error(MessageFormat.format("Failed to receive proposal data from {0}",
-						request.getRemoteAddr()));
-				response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+			FederationProposal proposal = deserialize(request, response, FederationProposal.class);
+			if (proposal == null) {
 				return;
 			}
-
-			// deserialize the proposal
-			Gson gson = new Gson();
-			FederationProposal proposal = gson.fromJson(json.toString(), FederationProposal.class);
 
 			// reject proposal, if not receipt prohibited
 			if (!GitBlit.getBoolean(Keys.federation.allowProposals, false)) {
 				logger.error(MessageFormat.format("Rejected {0} federation proposal from {1}",
 						proposal.tokenType.name(), proposal.url));
 				response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
+				return;
+			}
+
+			// poke the origin Gitblit instance that is proposing federation
+			boolean poked = false;
+			try {
+				poked = FederationUtils.poke(proposal.url);
+			} catch (Exception e) {
+				logger.error("Failed to poke origin", e);
+			}
+			if (!poked) {
+				logger.error(MessageFormat.format("Failed to send federation poke to {0}",
+						proposal.url));
+				response.setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
 				return;
 			}
 
@@ -173,25 +132,13 @@
 			String remoteId = StringUtils.decodeFromHtml(request.getParameter("url"));
 			String identification = MessageFormat.format("{0} ({1})", remoteId,
 					request.getRemoteAddr());
-			BufferedReader reader = request.getReader();
-			StringBuilder json = new StringBuilder();
-			String line = null;
-			while ((line = reader.readLine()) != null) {
-				json.append(line);
-			}
-			reader.close();
 
-			// check to see if we have repository data
-			if (json.length() == 0) {
-				logger.error(MessageFormat.format(
-						"Failed to receive pulled repositories list from {0}", identification));
-				response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+			// deserialize the status data
+			FederationModel results = deserialize(request, response, FederationModel.class);
+			if (results == null) {
 				return;
 			}
 
-			// deserialize the status data
-			Gson gson = new Gson();
-			FederationModel results = gson.fromJson(json.toString(), FederationModel.class);
 			// setup the last and netx pull dates
 			results.lastPull = new Date();
 			int mins = TimeUtils.convertFrequencyToMinutes(results.frequency);
@@ -207,6 +154,7 @@
 		}
 
 		// Determine the federation tokens for this gitblit instance
+		String token = request.getParameter("token");
 		List<String> tokens = GitBlit.self().getFederationTokens();
 		if (!tokens.contains(token)) {
 			logger.warn(MessageFormat.format(
@@ -255,28 +203,62 @@
 					}
 				}
 				result = users;
+			} else if (FederationRequest.PULL_TEAMS.equals(reqType)) {
+				// pull teams
+				if (!GitBlit.self().validateFederationRequest(reqType, token)) {
+					// invalid token to pull teams
+					logger.warn(MessageFormat.format(
+							"Federation token from {0} not authorized to pull TEAMS",
+							request.getRemoteAddr()));
+					response.sendError(HttpServletResponse.SC_FORBIDDEN);
+					return;
+				}
+				List<String> teamnames = GitBlit.self().getAllTeamnames();
+				List<TeamModel> teams = new ArrayList<TeamModel>();
+				for (String teamname : teamnames) {
+					TeamModel user = GitBlit.self().getTeamModel(teamname);
+					teams.add(user);
+				}
+				result = teams;
+			} else if (FederationRequest.PULL_SCRIPTS.equals(reqType)) {
+				// pull scripts
+				if (!GitBlit.self().validateFederationRequest(reqType, token)) {
+					// invalid token to pull script
+					logger.warn(MessageFormat.format(
+							"Federation token from {0} not authorized to pull SCRIPTS",
+							request.getRemoteAddr()));
+					response.sendError(HttpServletResponse.SC_FORBIDDEN);
+					return;
+				}
+				Map<String, String> scripts = new HashMap<String, String>();
+				
+				Set<String> names = new HashSet<String>();
+				names.addAll(GitBlit.getStrings(Keys.groovy.preReceiveScripts));
+				names.addAll(GitBlit.getStrings(Keys.groovy.postReceiveScripts));
+				for (TeamModel team :  GitBlit.self().getAllTeams()) {
+					names.addAll(team.preReceiveScripts);
+					names.addAll(team.postReceiveScripts);
+				}
+				File scriptsFolder = GitBlit.getFileOrFolder(Keys.groovy.scriptsFolder, "groovy");
+				for (String name : names) {
+					File file = new File(scriptsFolder, name);
+					if (!file.exists() && !file.getName().endsWith(".groovy")) {
+						file = new File(scriptsFolder, name + ".groovy");
+					}
+					if (file.exists()) {
+						// read the script
+						String content = FileUtils.readContent(file, "\n");
+						scripts.put(name, content);
+					} else {
+						// missing script?!
+						logger.warn(MessageFormat.format("Failed to find push script \"{0}\"", name));
+					}
+				}
+				result = scripts;
 			}
 		}
 
-		if (result != null) {
-			// Send JSON response
-			Gson gson = new GsonBuilder().setPrettyPrinting().create();
-			String json = gson.toJson(result);
-			response.getWriter().append(json);
-		}
-	}
-
-	@Override
-	protected void doPost(javax.servlet.http.HttpServletRequest request,
-			javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException,
-			java.io.IOException {
-		processRequest(request, response);
-	}
-
-	@Override
-	protected void doGet(javax.servlet.http.HttpServletRequest request,
-			javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException,
-			java.io.IOException {
-		processRequest(request, response);
+		// send the result of the request
+		serialize(response, result);
 	}
 }

--
Gitblit v1.9.1