diff src/nabble/view/web/forum/FileDownload.java @ 0:7ecd1a4ef557

add content
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 21 Mar 2019 19:15:52 -0600
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/nabble/view/web/forum/FileDownload.java	Thu Mar 21 19:15:52 2019 -0600
@@ -0,0 +1,179 @@
+package nabble.view.web.forum;
+
+import fschmidt.util.java.HtmlUtils;
+import fschmidt.util.java.IoUtils;
+import fschmidt.util.servlet.AuthorizingServlet;
+import fschmidt.util.servlet.JtpContext;
+import nabble.model.FileUpload;
+import nabble.model.Message;
+import nabble.model.Node;
+import nabble.model.Site;
+import nabble.view.lib.Cache;
+import nabble.view.lib.Jtp;
+import nabble.view.lib.UrlMappable;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.ResourceBundle;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+public final class FileDownload extends HttpServlet implements UrlMappable, AuthorizingServlet {
+
+	private static final Pattern urlPtn = Pattern.compile("/file/(([a-z])(\\d+)/)?([^/]*)$");
+
+	public static String url(String filename,Message.Source src) {
+		return baseUrl(src) + path(filename,src);
+	}
+
+	public static String path(String filename,Message.Source src) {
+		StringBuilder buf = new StringBuilder();
+		buf.append( "/file/" );
+		if (!src.getMessageSourceType().equals(Message.SourceType.SITE)) {
+			buf.append( src.getMessageSourceType().getCode() );
+			buf.append( src.getSourceId() );
+			buf.append( "/" );
+		}
+		buf.append( HtmlUtils.urlEncode(filename) );
+		return buf.toString();
+	}
+
+	private static String baseUrl(Message.Source src) {
+		return src.getSite().getBaseUrl();
+	}
+
+	public Map<String,String[]> getParameterMapFromUrl(HttpServletRequest request,String mappedUrl) {
+		Matcher m = urlPtn.matcher(mappedUrl);
+		if( !m.find() )
+			throw new RuntimeException();
+		Map<String,String[]> params = new HashMap<String,String[]>();
+		if (m.group(1) == null)
+			params.put("type",new String[]{String.valueOf(Message.SourceType.SITE.getCode())});
+		else {
+			String type = m.group(2);
+			params.put("type",new String[]{type});
+			String fileId = m.group(3);
+			params.put("id",new String[]{fileId});
+		}
+		String name = m.group(4);
+		params.put("name",new String[]{name});
+		return params;
+	}
+
+	public Pattern getUrlPattern() {
+		return urlPtn;
+	}
+
+	public String getAuthorizationKey(HttpServletRequest request) throws ServletException {
+		Message.Source src = getSource(request);
+		return src instanceof Node ? Jtp.getReadAuthorizationKey((Node)src) : null;
+	}
+
+	public boolean authorize(String key,HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
+		return Jtp.authorizeForRead(key,request,response);
+	}
+
+	private static final Map<String,String> mimeMap = new HashMap<String,String>();
+	static {
+		ResourceBundle mime = ResourceBundle.getBundle("org/eclipse/jetty/http/mime");
+		Enumeration<String> i = mime.getKeys();
+		while( i.hasMoreElements() ) {
+			String ext = i.nextElement();
+			String type = mime.getString(ext);
+			mimeMap.put(ext.toLowerCase(),type);
+		}
+	}
+
+	static String getMimeByExtension(String fileName) {
+		return mimeMap.get( fileName.substring(fileName.lastIndexOf('.')+1).toLowerCase() );
+	}
+
+	protected void service(HttpServletRequest request,HttpServletResponse response)
+		throws ServletException, IOException
+	{
+		JtpContext jtpContext = (JtpContext)getServletContext().getAttribute(JtpContext.attrName);
+		char type = request.getParameter("type").charAt(0);
+		Message.Source src = getSource(request);
+		if (src == null) {
+			response.sendError(HttpServletResponse.SC_NOT_FOUND,"File not found");
+			return;
+		}
+
+		switch(type) {
+		case 't':
+			break;
+		case 's':
+			jtpContext.setEtag(request,response, Cache.siteChangeEvent(src.getSite()) );
+			break;
+		case 'n':
+			{
+				Set<String> events = new LinkedHashSet<String>();
+				if( src instanceof Node ) {
+					Node node = (Node)src;
+					events.add( Cache.nodeFileChangeEvent(node) );
+					Jtp.addBreadCrumbEvents(events, node);
+				}
+				jtpContext.setEtag(request,response, events.toArray(new String[events.size()]) );
+			}
+			break;
+		case 'a':
+			jtpContext.setEtag(request,response, Cache.userFileChangeEvent(((Message.AvatarSource)src).getUser()) );
+			break;
+		default:
+			if( Jtp.invalidReferer(request) ) {
+				throw new ServletException("type = '"+type+"'");
+			} else {
+				throw new RuntimeException("type = '"+type+"'");
+			}
+		}
+
+		response.setHeader("Cache-Control",null);
+		String name = request.getParameter("name");
+
+		InputStream in = FileUpload.getFileContent(src,name);
+		if (in == null) {
+			name = HtmlUtils.urlDecode(name);
+			in = FileUpload.getFileContent(src, name);
+			if (in == null) {
+				// We have to find a better way to track this down -- the log is too full of missing images [Hugo/Jun-2010]
+				response.sendError(HttpServletResponse.SC_NOT_FOUND,"File not found");
+				return;
+			}
+		}
+		OutputStream out = response.getOutputStream();
+		response.setContentType(getMimeByExtension(name));
+		try {
+			IoUtils.copyAll(in,out);
+		} finally {
+			in.close();
+		}
+	}
+
+	private static Message.Source getSource(HttpServletRequest request)
+		throws ServletException
+	{
+		char type = request.getParameter("type").charAt(0);
+		Message.SourceType sourceType = Message.SourceType.getType(type);
+		if( sourceType==null )
+			return null;
+		Site site = Jtp.getSite(request);
+		if (site == null)
+			return null;
+		if (sourceType.equals(Message.SourceType.SITE))
+			return site;
+		long fileId = Jtp.getLong(request,"id");
+		return sourceType.getSource(site,fileId);
+	}
+
+}