From f76fee63ed9cb3a30d3c0c092d860b1cb93a481b Mon Sep 17 00:00:00 2001
From: Gerard Smyth <gerard.smyth@gmail.com>
Date: Thu, 08 May 2014 13:09:30 -0400
Subject: [PATCH] Updated the SyndicationServlet to provide an additional option to return details of the tags in the repository instead of the commits. This uses a new 'ot' request parameter to indicate the object type of the content to return, which can be ither TAG or COMMIT. If this is not provided, then COMMIT is assumed to maintain backwards compatability. If tags are returned, then the paging parameters, 'l' and 'pg' are still supported, but searching options are currently ignored.

---
 src/main/java/com/gitblit/wicket/pages/BasePage.java |  309 ++++++++++++++++++++++++++++----------------------
 1 files changed, 172 insertions(+), 137 deletions(-)

diff --git a/src/main/java/com/gitblit/wicket/pages/BasePage.java b/src/main/java/com/gitblit/wicket/pages/BasePage.java
index 5c73df3..4971039 100644
--- a/src/main/java/com/gitblit/wicket/pages/BasePage.java
+++ b/src/main/java/com/gitblit/wicket/pages/BasePage.java
@@ -15,6 +15,8 @@
  */
 package com.gitblit.wicket.pages;
 
+import java.io.IOException;
+import java.io.InputStream;
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Calendar;
@@ -31,23 +33,20 @@
 
 import javax.servlet.http.HttpServletRequest;
 
+import org.apache.commons.io.IOUtils;
 import org.apache.wicket.Application;
-import org.apache.wicket.MarkupContainer;
+import org.apache.wicket.Page;
 import org.apache.wicket.PageParameters;
 import org.apache.wicket.RedirectToUrlException;
-import org.apache.wicket.RequestCycle;
-import org.apache.wicket.RestartResponseException;
 import org.apache.wicket.markup.html.CSSPackageResource;
-import org.apache.wicket.markup.html.WebPage;
 import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.link.BookmarkablePageLink;
 import org.apache.wicket.markup.html.link.ExternalLink;
 import org.apache.wicket.markup.html.panel.FeedbackPanel;
-import org.apache.wicket.markup.html.panel.Fragment;
 import org.apache.wicket.protocol.http.RequestUtils;
-import org.apache.wicket.protocol.http.WebRequest;
 import org.apache.wicket.protocol.http.WebResponse;
 import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
+import org.apache.wicket.util.time.Duration;
+import org.apache.wicket.util.time.Time;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -56,68 +55,87 @@
 import com.gitblit.Constants.AccessRestrictionType;
 import com.gitblit.Constants.AuthorizationControl;
 import com.gitblit.Constants.FederationStrategy;
-import com.gitblit.GitBlit;
 import com.gitblit.Keys;
 import com.gitblit.models.ProjectModel;
-import com.gitblit.models.RepositoryModel;
 import com.gitblit.models.TeamModel;
 import com.gitblit.models.UserModel;
 import com.gitblit.utils.StringUtils;
 import com.gitblit.utils.TimeUtils;
+import com.gitblit.wicket.CacheControl;
+import com.gitblit.wicket.GitBlitWebApp;
 import com.gitblit.wicket.GitBlitWebSession;
 import com.gitblit.wicket.WicketUtils;
-import com.gitblit.wicket.panels.LinkPanel;
 
-public abstract class BasePage extends WebPage {
+public abstract class BasePage extends SessionPage {
 
-	private final Logger logger;
-	
+	private transient Logger logger;
+
 	private transient TimeUtils timeUtils;
 
 	public BasePage() {
 		super();
-		logger = LoggerFactory.getLogger(getClass());
 		customizeHeader();
-		login();
 	}
 
 	public BasePage(PageParameters params) {
 		super(params);
-		logger = LoggerFactory.getLogger(getClass());
 		customizeHeader();
-		login();
 	}
-	
+
+	protected Logger logger() {
+		if (logger == null) {
+			logger = LoggerFactory.getLogger(getClass());
+		}
+		return logger;
+	}
+
 	private void customizeHeader() {
-		if (GitBlit.getBoolean(Keys.web.useResponsiveLayout, true)) {
+		if (app().settings().getBoolean(Keys.web.useResponsiveLayout, true)) {
 			add(CSSPackageResource.getHeaderContribution("bootstrap/css/bootstrap-responsive.css"));
 		}
+		if (app().settings().getBoolean(Keys.web.hideHeader, false)) {
+			add(CSSPackageResource.getHeaderContribution("hideheader.css"));
+		}
 	}
-	
+
+	protected String getContextUrl() {
+		return getRequest().getRelativePathPrefixToContextRoot();
+	}
+
+	protected String getCanonicalUrl() {
+		return getCanonicalUrl(getClass(), getPageParameters());
+	}
+
+	protected String getCanonicalUrl(Class<? extends BasePage> clazz, PageParameters params) {
+		String relativeUrl = urlFor(clazz, params).toString();
+		String canonicalUrl = RequestUtils.toAbsolutePath(relativeUrl);
+		return canonicalUrl;
+	}
+
 	protected String getLanguageCode() {
 		return GitBlitWebSession.get().getLocale().getLanguage();
 	}
-	
+
 	protected String getCountryCode() {
 		return GitBlitWebSession.get().getLocale().getCountry().toLowerCase();
 	}
-	
+
 	protected TimeUtils getTimeUtils() {
 		if (timeUtils == null) {
-			ResourceBundle bundle;		
+			ResourceBundle bundle;
 			try {
 				bundle = ResourceBundle.getBundle("com.gitblit.wicket.GitBlitWebApp", GitBlitWebSession.get().getLocale());
 			} catch (Throwable t) {
 				bundle = ResourceBundle.getBundle("com.gitblit.wicket.GitBlitWebApp");
 			}
-			timeUtils = new TimeUtils(bundle);
+			timeUtils = new TimeUtils(bundle, getTimeZone());
 		}
 		return timeUtils;
 	}
-	
+
 	@Override
 	protected void onBeforeRender() {
-		if (GitBlit.isDebugMode()) {
+		if (app().isDebugMode()) {
 			// strip Wicket tags in debug mode for jQuery DOM traversal
 			Application.get().getMarkupSettings().setStripWicketTags(true);
 		}
@@ -126,66 +144,102 @@
 
 	@Override
 	protected void onAfterRender() {
-		if (GitBlit.isDebugMode()) {
+		if (app().isDebugMode()) {
 			// restore Wicket debug tags
 			Application.get().getMarkupSettings().setStripWicketTags(false);
 		}
 		super.onAfterRender();
-	}	
+	}
 
-	private void login() {
-		GitBlitWebSession session = GitBlitWebSession.get();
-		if (session.isLoggedIn() && !session.isSessionInvalidated()) {
-			// already have a session, refresh usermodel to pick up
-			// any changes to permissions or roles (issue-186)
-			UserModel user = GitBlit.self().getUserModel(session.getUser().username);
-			session.setUser(user);
+	@Override
+	protected void setHeaders(WebResponse response)	{
+		// set canonical link as http header for SEO (issue-304)
+		// https://support.google.com/webmasters/answer/139394?hl=en
+		response.setHeader("Link", MessageFormat.format("<{0}>; rel=\"canonical\"", getCanonicalUrl()));
+		int expires = app().settings().getInteger(Keys.web.pageCacheExpires, 0);
+		if (expires > 0) {
+			// pages are personalized for the authenticated user so they must be
+			// marked private to prohibit proxy servers from caching them
+			response.setHeader("Cache-Control", "private, must-revalidate");
+			setLastModified();
+		} else {
+			// use default Wicket caching behavior
+			super.setHeaders(response);
+		}
+	}
+
+	/**
+	 * Sets the last-modified header date, if appropriate, for this page.  The
+	 * date used is determined by the CacheControl annotation.
+	 *
+	 */
+	protected void setLastModified() {
+		if (getClass().isAnnotationPresent(CacheControl.class)) {
+			CacheControl cacheControl = getClass().getAnnotation(CacheControl.class);
+			switch (cacheControl.value()) {
+			case ACTIVITY:
+				setLastModified(app().getLastActivityDate());
+				break;
+			case BOOT:
+				setLastModified(app().getBootDate());
+				break;
+			case NONE:
+				break;
+			default:
+				logger().warn(getClass().getSimpleName() + ": unhandled LastModified type " + cacheControl.value());
+				break;
+			}
+		}
+	}
+
+	/**
+	 * Sets the last-modified header field and the expires field.
+	 *
+	 * @param when
+	 */
+	protected final void setLastModified(Date when) {
+		if (when == null) {
 			return;
 		}
-		
-		// try to authenticate by servlet request
-		HttpServletRequest httpRequest = ((WebRequest) getRequestCycle().getRequest()).getHttpServletRequest();
-		UserModel user = GitBlit.self().authenticate(httpRequest);
 
-		// Login the user
-		if (user != null) {
-			// issue 62: fix session fixation vulnerability
-			session.replaceSession();
-			session.setUser(user);
+		if (when.before(app().getBootDate())) {
+			// last-modified can not be before the Gitblit boot date
+			// this helps ensure that pages are properly refreshed after a
+			// server config change
+			when = app().getBootDate();
+		}
 
-			// Set Cookie
-			WebResponse response = (WebResponse) getRequestCycle().getResponse();
-			GitBlit.self().setCookie(response, user);
-			
-			session.continueRequest();
+		int expires = app().settings().getInteger(Keys.web.pageCacheExpires, 0);
+		WebResponse response = (WebResponse) getResponse();
+		response.setLastModifiedTime(Time.valueOf(when));
+		response.setDateHeader("Expires", System.currentTimeMillis() + Duration.minutes(expires).getMilliseconds());
+	}
+
+	protected String getPageTitle(String repositoryName) {
+		String siteName = app().settings().getString(Keys.web.siteName, Constants.NAME);
+		if (StringUtils.isEmpty(siteName)) {
+			siteName = Constants.NAME;
+		}
+		if (repositoryName != null && repositoryName.trim().length() > 0) {
+			return repositoryName + " - " + siteName;
+		} else {
+			return siteName;
 		}
 	}
 
 	protected void setupPage(String repositoryName, String pageName) {
-		if (repositoryName != null && repositoryName.trim().length() > 0) {
-			add(new Label("title", getServerName() + " - " + repositoryName));
-		} else {
-			add(new Label("title", getServerName()));
-		}
+		add(new Label("title", getPageTitle(repositoryName)));
 
-		ExternalLink rootLink = new ExternalLink("rootLink", urlFor(RepositoriesPage.class, null).toString());
-		WicketUtils.setHtmlTooltip(rootLink, GitBlit.getString(Keys.web.siteName, Constants.NAME));
+		String rootLinkUrl = app().settings().getString(Keys.web.rootLink, urlFor(GitBlitWebApp.get().getHomePage(), null).toString());
+		ExternalLink rootLink = new ExternalLink("rootLink", rootLinkUrl);
+		WicketUtils.setHtmlTooltip(rootLink, app().settings().getString(Keys.web.siteName, Constants.NAME));
 		add(rootLink);
 
 		// Feedback panel for info, warning, and non-fatal error messages
 		add(new FeedbackPanel("feedback"));
 
-		// footer
-		if (GitBlit.getBoolean(Keys.web.authenticateViewPages, true)
-				|| GitBlit.getBoolean(Keys.web.authenticateAdminPages, true)) {
-			UserFragment userFragment = new UserFragment("userPanel", "userFragment", BasePage.this);
-			add(userFragment);
-		} else {
-			add(new Label("userPanel", ""));
-		}
-
 		add(new Label("gbVersion", "v" + Constants.getVersion()));
-		if (GitBlit.getBoolean(Keys.web.aggressiveHeapManagement, false)) {
+		if (app().settings().getBoolean(Keys.web.aggressiveHeapManagement, false)) {
 			System.gc();
 		}
 	}
@@ -210,7 +264,7 @@
 		}
 		return map;
 	}
-	
+
 	protected Map<AccessPermission, String> getAccessPermissions() {
 		Map<AccessPermission, String> map = new LinkedHashMap<AccessPermission, String>();
 		for (AccessPermission type : AccessPermission.values()) {
@@ -243,7 +297,7 @@
 		}
 		return map;
 	}
-	
+
 	protected Map<FederationStrategy, String> getFederationTypes() {
 		Map<FederationStrategy, String> map = new LinkedHashMap<FederationStrategy, String>();
 		for (FederationStrategy type : FederationStrategy.values()) {
@@ -261,7 +315,7 @@
 		}
 		return map;
 	}
-	
+
 	protected Map<AuthorizationControl, String> getAuthorizationControls() {
 		Map<AuthorizationControl, String> map = new LinkedHashMap<AuthorizationControl, String>();
 		for (AuthorizationControl type : AuthorizationControl.values()) {
@@ -278,8 +332,8 @@
 	}
 
 	protected TimeZone getTimeZone() {
-		return GitBlit.getBoolean(Keys.web.useClientTimezone, false) ? GitBlitWebSession.get()
-				.getTimezone() : GitBlit.getTimezone();
+		return app().settings().getBoolean(Keys.web.useClientTimezone, false) ? GitBlitWebSession.get()
+				.getTimezone() : app().getTimezone();
 	}
 
 	protected String getServerName() {
@@ -287,28 +341,13 @@
 		HttpServletRequest req = servletWebRequest.getHttpServletRequest();
 		return req.getServerName();
 	}
-	
-	public static String getRepositoryUrl(RepositoryModel repository) {
-		StringBuilder sb = new StringBuilder();
-		sb.append(WicketUtils.getGitblitURL(RequestCycle.get().getRequest()));
-		sb.append(Constants.GIT_PATH);
-		sb.append(repository.name);
-		
-		// inject username into repository url if authentication is required
-		if (repository.accessRestriction.exceeds(AccessRestrictionType.NONE)
-				&& GitBlitWebSession.get().isLoggedIn()) {
-			String username = GitBlitWebSession.get().getUsername();
-			sb.insert(sb.indexOf("://") + 3, username + "@");
-		}
-		return sb.toString();
-	}
-	
+
 	protected List<ProjectModel> getProjectModels() {
 		final UserModel user = GitBlitWebSession.get().getUser();
-		List<ProjectModel> projects = GitBlit.self().getProjectModels(user, true);
+		List<ProjectModel> projects = app().projects().getProjectModels(user, true);
 		return projects;
 	}
-	
+
 	protected List<ProjectModel> getProjects(PageParameters params) {
 		if (params == null) {
 			return getProjectModels();
@@ -318,6 +357,7 @@
 		String regex = WicketUtils.getRegEx(params);
 		String team = WicketUtils.getTeam(params);
 		int daysBack = params.getInt("db", 0);
+		int maxDaysBack = app().settings().getInteger(Keys.web.activityDurationMaximum, 30);
 
 		List<ProjectModel> availableModels = getProjectModels();
 		Set<ProjectModel> models = new HashSet<ProjectModel>();
@@ -341,7 +381,7 @@
 			// need TeamModels first
 			List<TeamModel> teamModels = new ArrayList<TeamModel>();
 			for (String name : teams) {
-				TeamModel teamModel = GitBlit.self().getTeamModel(name);
+				TeamModel teamModel = app().users().getTeamModel(name);
 				if (teamModel != null) {
 					teamModels.add(teamModel);
 				}
@@ -365,6 +405,9 @@
 
 		// time-filter the list
 		if (daysBack > 0) {
+			if (maxDaysBack > 0 && daysBack > maxDaysBack) {
+				daysBack = maxDaysBack;
+			}
 			Calendar cal = Calendar.getInstance();
 			cal.set(Calendar.HOUR_OF_DAY, 0);
 			cal.set(Calendar.MINUTE, 0);
@@ -387,14 +430,30 @@
 	}
 
 	public void warn(String message, Throwable t) {
-		logger.warn(message, t);
+		logger().warn(message, t);
 	}
-	
+
 	public void error(String message, boolean redirect) {
-		logger.error(message  + " for " + GitBlitWebSession.get().getUsername());
-		if (redirect) {
+		error(message, null, redirect ? getApplication().getHomePage() : null);
+	}
+
+	public void error(String message, Throwable t, boolean redirect) {
+		error(message, t, getApplication().getHomePage());
+	}
+
+	public void error(String message, Throwable t, Class<? extends Page> toPage) {
+		error(message, t, toPage, null);
+	}
+
+	public void error(String message, Throwable t, Class<? extends Page> toPage, PageParameters params) {
+		if (t == null) {
+			logger().error(message  + " for " + GitBlitWebSession.get().getUsername());
+		} else {
+			logger().error(message  + " for " + GitBlitWebSession.get().getUsername(), t);
+		}
+		if (toPage != null) {
 			GitBlitWebSession.get().cacheErrorMessage(message);
-			String relativeUrl = urlFor(RepositoriesPage.class, null).toString();
+			String relativeUrl = urlFor(toPage, params).toString();
 			String absoluteUrl = RequestUtils.toAbsolutePath(relativeUrl);
 			throw new RedirectToUrlException(absoluteUrl);
 		} else {
@@ -402,18 +461,8 @@
 		}
 	}
 
-	public void error(String message, Throwable t, boolean redirect) {
-		logger.error(message, t);
-		if (redirect) {
-			GitBlitWebSession.get().cacheErrorMessage(message);
-			throw new RestartResponseException(getApplication().getHomePage());
-		} else {
-			super.error(message);
-		}
-	}
-
 	public void authenticationError(String message) {
-		logger.error(getRequest().getURL() + " for " + GitBlitWebSession.get().getUsername());
+		logger().error(getRequest().getURL() + " for " + GitBlitWebSession.get().getUsername());
 		if (!GitBlitWebSession.get().isLoggedIn()) {
 			// cache the request if we have not authenticated.
 			// the request will continue after authentication.
@@ -422,39 +471,25 @@
 		error(message, true);
 	}
 
-	/**
-	 * Panel fragment for displaying login or logout/change_password links.
-	 * 
-	 */
-	static class UserFragment extends Fragment {
+	protected String readResource(String resource) {
+		StringBuilder sb = new StringBuilder();
+		InputStream is = null;
+		try {
+			is = getClass().getResourceAsStream(resource);
+			List<String> lines = IOUtils.readLines(is);
+			for (String line : lines) {
+				sb.append(line).append('\n');
+			}
+		} catch (IOException e) {
 
-		private static final long serialVersionUID = 1L;
-
-		public UserFragment(String id, String markupId, MarkupContainer markupProvider) {
-			super(id, markupId, markupProvider);
-
-			GitBlitWebSession session = GitBlitWebSession.get();
-			if (session.isLoggedIn()) {				
-				UserModel user = session.getUser();
-				boolean editCredentials = GitBlit.self().supportsCredentialChanges(user);
-				boolean standardLogin = session.authenticationType.isStandard();
-
-				// username, logout, and change password
-				add(new Label("username", user.getDisplayName() + ":"));
-				add(new LinkPanel("loginLink", null, markupProvider.getString("gb.logout"),
-						LogoutPage.class).setVisible(standardLogin));
-				
-				// quick and dirty hack for showing a separator
-				add(new Label("separator", "|").setVisible(standardLogin && editCredentials));
-				add(new BookmarkablePageLink<Void>("changePasswordLink", 
-						ChangePasswordPage.class).setVisible(editCredentials));
-			} else {
-				// login
-				add(new Label("username").setVisible(false));
-				add(new Label("loginLink").setVisible(false));
-				add(new Label("separator").setVisible(false));
-				add(new Label("changePasswordLink").setVisible(false));
+		} finally {
+			if (is != null) {
+				try {
+					is.close();
+				} catch (IOException e) {
+				}
 			}
 		}
+		return sb.toString();
 	}
 }

--
Gitblit v1.9.1