<servlet-name>GitServlet</servlet-name> \r
<url-pattern>/git/*</url-pattern>\r
</servlet-mapping>\r
+\r
\r
+ <!-- SparkleShare Invite Servlet\r
+ <url-pattern> MUST match: \r
+ * com.gitblit.Constants.SPARKLESHARE_INVITE_PATH\r
+ * Wicket Filter ignorePaths parameter -->\r
+ <servlet>\r
+ <servlet-name>SparkleShareInviteServlet</servlet-name>\r
+ <servlet-class>com.gitblit.SparkleShareInviteServlet</servlet-class>\r
+ </servlet>\r
+ <servlet-mapping>\r
+ <servlet-name>SparkleShareInviteServlet</servlet-name> \r
+ <url-pattern>/sparkleshare/*</url-pattern>\r
+ </servlet-mapping>\r
+\r
\r
<!-- Syndication Servlet\r
<url-pattern> MUST match: \r
* GitFilter <url-pattern>\r
* GitServlet <url-pattern>\r
* com.gitblit.Constants.GIT_PATH\r
+ * SparkleshareInviteServlet <url-pattern>\r
+ * com.gitblit.Constants.SPARKLESHARE_INVITE_PATH\r
* Zipfilter <url-pattern>\r
* ZipServlet <url-pattern>\r
* com.gitblit.Constants.ZIP_PATH\r
* PagesFilter <url-pattern>\r
* PagesServlet <url-pattern>\r
* com.gitblit.Constants.PAGES_PATH -->\r
- <param-value>git/,feed/,zip/,federation/,rpc/,pages/,robots.txt</param-value>\r
+ <param-value>git/,feed/,zip/,federation/,rpc/,pages/,robots.txt,sparkleshare/</param-value>\r
</init-param>\r
</filter>\r
<filter-mapping>\r
--- /dev/null
+/*\r
+ * Copyright 2013 gitblit.com.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package com.gitblit;\r
+\r
+import java.io.IOException;\r
+import java.text.MessageFormat;\r
+import java.util.List;\r
+\r
+import javax.servlet.ServletException;\r
+import javax.servlet.http.HttpServlet;\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.servlet.http.HttpServletResponse;\r
+\r
+import com.gitblit.Constants.AccessRestrictionType;\r
+import com.gitblit.models.RepositoryModel;\r
+import com.gitblit.models.UserModel;\r
+import com.gitblit.utils.StringUtils;\r
+\r
+/**\r
+ * Handles requests for Sparkleshare Invites\r
+ * \r
+ * @author James Moger\r
+ * \r
+ */\r
+public class SparkleShareInviteServlet extends HttpServlet {\r
+\r
+ private static final long serialVersionUID = 1L;\r
+\r
+ public SparkleShareInviteServlet() {\r
+ super();\r
+ }\r
+ \r
+ /**\r
+ * Returns an Sparkleshare invite url to this servlet for the repository.\r
+ * https://github.com/hbons/SparkleShare/wiki/Invites\r
+ * \r
+ * @param baseURL\r
+ * @param repository\r
+ * @param username\r
+ * @return an url\r
+ */\r
+ public static String asLink(String baseURL, String repository, String username) {\r
+ if (baseURL.length() > 0 && baseURL.charAt(baseURL.length() - 1) == '/') {\r
+ baseURL = baseURL.substring(0, baseURL.length() - 1);\r
+ }\r
+ String url = baseURL + Constants.SPARKLESHARE_INVITE_PATH\r
+ + ((StringUtils.isEmpty(username) ? "" : (username + "@")))\r
+ + repository + ".xml";\r
+ url = url.replace("https://", "sparkleshare://");\r
+ url = url.replace("http://", "sparkleshare-unsafe://");\r
+ return url;\r
+ }\r
+ \r
+ @Override\r
+ protected void doPost(HttpServletRequest request, HttpServletResponse response)\r
+ throws ServletException, java.io.IOException {\r
+ processRequest(request, response);\r
+ }\r
+\r
+ @Override\r
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)\r
+ throws ServletException, IOException {\r
+ processRequest(request, response);\r
+ }\r
+\r
+ protected void processRequest(javax.servlet.http.HttpServletRequest request,\r
+ javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException,\r
+ java.io.IOException { \r
+ \r
+ // extract repo name from request\r
+ String path = request.getPathInfo();\r
+ if (path != null && path.length() > 1) {\r
+ if (path.charAt(0) == '/') {\r
+ path = path.substring(1);\r
+ }\r
+ }\r
+ // trim trailing .xml\r
+ if (path.endsWith(".xml")) {\r
+ path = path.substring(0, path.length() - 4);\r
+ }\r
+ \r
+ String username = null;\r
+ int fetch = path.indexOf('@');\r
+ if (fetch > -1) {\r
+ username = path.substring(0, fetch);\r
+ path = path.substring(fetch + 1);\r
+ }\r
+ UserModel user;\r
+ if (StringUtils.isEmpty(username)) {\r
+ user = GitBlit.self().authenticate(request);\r
+ } else {\r
+ user = GitBlit.self().getUserModel(username);\r
+ }\r
+ if (user == null) {\r
+ user = UserModel.ANONYMOUS;\r
+ username = "";\r
+ }\r
+ \r
+ // ensure that the requested repository exists and is sparkleshared\r
+ RepositoryModel model = GitBlit.self().getRepositoryModel(path);\r
+ if (model == null) {\r
+ response.setStatus(HttpServletResponse.SC_NOT_FOUND);\r
+ response.getWriter().append(MessageFormat.format("Repository \"{0}\" not found!", path));\r
+ return;\r
+ } else if (!model.isSparkleshared()) {\r
+ response.setStatus(HttpServletResponse.SC_FORBIDDEN);\r
+ response.getWriter().append(MessageFormat.format("Repository \"{0}\" is not sparkleshared!", path));\r
+ return;\r
+ }\r
+ \r
+ if (GitBlit.getBoolean(Keys.git.enableGitServlet, true)\r
+ || GitBlit.getInteger(Keys.git.daemonPort, 0) > 0) {\r
+ // Gitblit as server\r
+ // determine username for repository url\r
+ if (model.accessRestriction.exceeds(AccessRestrictionType.NONE)) {\r
+ if (!user.canRewindRef(model)) {\r
+ response.setStatus(HttpServletResponse.SC_FORBIDDEN);\r
+ response.getWriter().append(MessageFormat.format("\"{0}\" does not have RW+ permissions for {1}!", user.username, path));\r
+ return;\r
+ }\r
+ }\r
+ \r
+ if (model.accessRestriction.exceeds(AccessRestrictionType.NONE)) {\r
+ username = user.username + "@";\r
+ } else {\r
+ username = "";\r
+ }\r
+\r
+ String serverPort = "";\r
+ if (request.getScheme().equals("https")) {\r
+ if (request.getServerPort() != 443) {\r
+ serverPort = ":" + request.getServerPort();\r
+ }\r
+ } else if (request.getScheme().equals("http")) {\r
+ if (request.getServerPort() != 80) {\r
+ serverPort = ":" + request.getServerPort();\r
+ }\r
+ }\r
+\r
+ // assume http/https serving\r
+ String scheme = request.getScheme();\r
+ String servletPath = Constants.GIT_PATH;\r
+\r
+ // try to switch to git://, if git servlet disabled and repo has no restrictions\r
+ if (!GitBlit.getBoolean(Keys.git.enableGitServlet, true)\r
+ && (GitBlit.getInteger(Keys.git.daemonPort, 0) > 0)\r
+ && AccessRestrictionType.NONE == model.accessRestriction) {\r
+ scheme = "git";\r
+ servletPath = "/";\r
+ serverPort = GitBlit.getString(Keys.git.daemonPort, "");\r
+ }\r
+\r
+ // construct Sparkleshare invite\r
+ StringBuilder sb = new StringBuilder(); \r
+ sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");\r
+ sb.append("<sparkleshare><invite>\n");\r
+ sb.append(MessageFormat.format("<address>{0}://{1}{2}{3}{4}</address>\n", scheme, username, request.getServerName(), serverPort, request.getContextPath()));\r
+ sb.append(MessageFormat.format("<remote_path>{0}{1}</remote_path>\n", servletPath, model.name));\r
+ if (GitBlit.getInteger(Keys.fanout.port, 0) > 0) {\r
+ // Gitblit is running it's own fanout service for pubsub notifications\r
+ sb.append(MessageFormat.format("<announcements_url>tcp://{0}:{1}</announcements_url>\n", request.getServerName(), GitBlit.getString(Keys.fanout.port, "")));\r
+ }\r
+ sb.append("</invite></sparkleshare>\n");\r
+\r
+ // write invite to client\r
+ response.setContentType("application/xml");\r
+ response.setContentLength(sb.length());\r
+ response.getWriter().append(sb.toString());\r
+ } else {\r
+ // Gitblit as viewer, repository access handled externally so\r
+ // assume RW+ permission\r
+ List<String> others = GitBlit.getStrings(Keys.web.otherUrls);\r
+ if (others.size() == 0) {\r
+ return;\r
+ }\r
+ \r
+ String address = MessageFormat.format(others.get(0), "", username);\r
+ \r
+ StringBuilder sb = new StringBuilder(); \r
+ sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");\r
+ sb.append("<sparkleshare><invite>\n");\r
+ \r
+ sb.append(MessageFormat.format("<address>{0}</address>\n", address));\r
+ sb.append(MessageFormat.format("<remote_path>{0}</remote_path>\n", model.name));\r
+ if (GitBlit.getInteger(Keys.fanout.port, 0) > 0) {\r
+ // Gitblit is running it's own fanout service for pubsub notifications\r
+ sb.append(MessageFormat.format("<announcements_url>tcp://{0}:{1}</announcements_url>\n", request.getServerName(), GitBlit.getString(Keys.fanout.port, "")));\r
+ }\r
+ sb.append("</invite></sparkleshare>\n");\r
+\r
+ // write invite to client\r
+ response.setContentType("application/xml");\r
+ response.setContentLength(sb.length());\r
+ response.getWriter().append(sb.toString());\r
+ }\r
+ }\r
+}\r
import com.gitblit.Constants.FederationStrategy;\r
import com.gitblit.GitBlit;\r
import com.gitblit.Keys;\r
+import com.gitblit.SparkleShareInviteServlet;\r
import com.gitblit.models.ProjectModel;\r
import com.gitblit.models.RepositoryModel;\r
import com.gitblit.models.TeamModel;\r
return new Label(wicketId).setVisible(false);\r
}\r
}\r
- \r
+\r
+ protected String getSparkleShareInviteUrl(RepositoryModel repository) {\r
+ if (repository.isBare && repository.isSparkleshared()) {\r
+ UserModel user = GitBlitWebSession.get().getUser();\r
+ if (user == null) {\r
+ user = UserModel.ANONYMOUS;\r
+ }\r
+ String username = null;\r
+ if (UserModel.ANONYMOUS != user) {\r
+ username = user.username;\r
+ }\r
+ if (GitBlit.getBoolean(Keys.git.enableGitServlet, true) || (GitBlit.getInteger(Keys.git.daemonPort, 0) > 0)) {\r
+ // Gitblit as server\r
+ // ensure user can rewind\r
+ if (user.canRewindRef(repository)) {\r
+ String baseURL = WicketUtils.getGitblitURL(RequestCycle.get().getRequest());\r
+ return SparkleShareInviteServlet.asLink(baseURL, repository.name, username);\r
+ }\r
+ } else {\r
+ // Gitblit as viewer, assume RW+ permission\r
+ String baseURL = WicketUtils.getGitblitURL(RequestCycle.get().getRequest());\r
+ return SparkleShareInviteServlet.asLink(baseURL, repository.name, username);\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+\r
protected List<ProjectModel> getProjectModels() {\r
final UserModel user = GitBlitWebSession.get().getUser();\r
List<ProjectModel> projects = GitBlit.self().getProjectModels(user, true);\r
--- /dev/null
+/*\r
+ * Copyright 2013 gitblit.com.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package com.gitblit.wicket.panels;\r
+\r
+import org.apache.wicket.Component;\r
+import org.apache.wicket.Localizer;\r
+import org.apache.wicket.markup.html.basic.Label;\r
+import org.apache.wicket.markup.html.image.ContextImage;\r
+import org.apache.wicket.markup.html.link.ExternalLink;\r
+\r
+import com.gitblit.Constants.AccessPermission;\r
+import com.gitblit.wicket.WicketUtils;\r
+\r
+public class SparkleShareInvitePanel extends BasePanel {\r
+\r
+ private static final long serialVersionUID = 1L;\r
+\r
+ public SparkleShareInvitePanel(String wicketId, Localizer localizer, Component parent, String url, AccessPermission ap) {\r
+ super(wicketId);\r
+ ContextImage star = WicketUtils.newImage("sparkleshareIcon", "star_16x16.png");\r
+ add(star);\r
+ add(new ExternalLink("inviteUrl", url));\r
+ String note = localizer.getString("gb.externalAccess", parent);\r
+ String permission = "";\r
+ if (ap != null) {\r
+ permission = ap.toString();\r
+ if (ap.atLeast(AccessPermission.PUSH)) {\r
+ note = localizer.getString("gb.readWriteAccess", parent);\r
+ } else if (ap.atLeast(AccessPermission.CLONE)) {\r
+ note = localizer.getString("gb.readOnlyAccess", parent);\r
+ } else {\r
+ note = localizer.getString("gb.viewAccess", parent);\r
+ }\r
+ }\r
+ Label label = new Label("accessPermission", permission);\r
+ WicketUtils.setHtmlTooltip(label, note);\r
+ add(label);\r
+ }\r
+}\r