0
|
1 package nabble.view.web.forum;
|
|
2
|
|
3 import fschmidt.util.java.IoUtils;
|
|
4 import fschmidt.util.servlet.AuthorizingServlet;
|
|
5 import fschmidt.util.servlet.JtpContext;
|
|
6 import fschmidt.util.servlet.CanonicalUrl;
|
|
7 import nabble.model.MailMessageFormat;
|
|
8 import nabble.model.Message;
|
|
9 import nabble.model.ModelHome;
|
|
10 import nabble.model.Node;
|
|
11 import nabble.model.Site;
|
|
12 import nabble.view.lib.Cache;
|
|
13 import nabble.view.lib.Jtp;
|
|
14 import nabble.view.lib.UrlMappable;
|
|
15
|
|
16 import javax.servlet.ServletException;
|
|
17 import javax.servlet.http.HttpServlet;
|
|
18 import javax.servlet.http.HttpServletRequest;
|
|
19 import javax.servlet.http.HttpServletResponse;
|
|
20 import java.io.IOException;
|
|
21 import java.io.InputStream;
|
|
22 import java.io.OutputStream;
|
|
23 import java.util.HashMap;
|
|
24 import java.util.Map;
|
|
25 import java.util.regex.Matcher;
|
|
26 import java.util.regex.Pattern;
|
|
27
|
|
28
|
|
29 public final class AttachmentDownload extends HttpServlet implements UrlMappable, AuthorizingServlet, CanonicalUrl {
|
|
30 private static final Pattern urlPtn = Pattern.compile("/attachment/(\\d+)/(\\d+)/(.*)$");
|
|
31
|
|
32 private static String url(Site site,String postId,String attachmentId,String name) {
|
|
33 return site.getBaseUrl()
|
|
34 + path(postId,attachmentId,name);
|
|
35 }
|
|
36
|
|
37 private static String path(String postId,String attachmentId,String name) {
|
|
38 StringBuilder buf = new StringBuilder();
|
|
39 buf.append( "/attachment/" );
|
|
40 buf.append( postId );
|
|
41 buf.append( "/" );
|
|
42 buf.append( attachmentId );
|
|
43 buf.append( "/" );
|
|
44 buf.append( name );
|
|
45 return buf.toString();
|
|
46 }
|
|
47
|
|
48 public String getCanonicalUrl(HttpServletRequest request) {
|
|
49 Site site = Jtp.getSite(request);
|
|
50 if( site == null )
|
|
51 return null;
|
|
52 String postId = request.getParameter("post");
|
|
53 String attachmentId = request.getParameter("attachment");
|
|
54 String name = request.getParameter("name");
|
|
55 return url(site,postId,attachmentId,name);
|
|
56 }
|
|
57
|
|
58 public Map<String,String[]> getParameterMapFromUrl(HttpServletRequest request,String mappedUrl) {
|
|
59 Matcher m = urlPtn.matcher(mappedUrl);
|
|
60 if( !m.find() )
|
|
61 throw new RuntimeException();
|
|
62 Map<String,String[]> params = new HashMap<String,String[]>();
|
|
63 String postId = m.group(1);
|
|
64 params.put("post",new String[]{postId});
|
|
65 String attachmentId = m.group(2);
|
|
66 params.put("attachment",new String[]{attachmentId});
|
|
67 String name = m.group(3);
|
|
68 params.put("name",new String[]{name});
|
|
69 return params;
|
|
70 }
|
|
71
|
|
72 public Pattern getUrlPattern() {
|
|
73 return urlPtn;
|
|
74 }
|
|
75
|
|
76 public String getAuthorizationKey(HttpServletRequest request) throws ServletException {
|
|
77 return Jtp.getReadAuthorizationKey( Jtp.getSiteNotNull(request).getNode(Jtp.getLong(request,"post")) );
|
|
78 }
|
|
79
|
|
80 public boolean authorize(String key,HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
|
|
81 return Jtp.authorizeForRead(key,request,response);
|
|
82 }
|
|
83
|
|
84 protected void service(HttpServletRequest request,HttpServletResponse response)
|
|
85 throws ServletException, IOException
|
|
86 {
|
|
87 OutputStream out = response.getOutputStream();
|
|
88 long postId = Long.parseLong( request.getParameter("post") );
|
|
89 int attachmentId = Integer.parseInt( request.getParameter("attachment") );
|
|
90 String name = request.getParameter("name");
|
|
91 String contentType = FileDownload.getMimeByExtension(name);
|
|
92 if (contentType==null /*|| !contentType.startsWith("image")*/) {
|
|
93 contentType = "application/x-download";
|
|
94 response.setHeader("content-disposition", "attachment; filename=\""+name+"\"");
|
|
95 }
|
|
96 response.setContentType(contentType);
|
|
97 Node post = Jtp.getSiteNotNull(request).getNode(postId);
|
|
98 if( post==null ) {
|
|
99 response.sendError(HttpServletResponse.SC_GONE,"This post has been deleted.");
|
|
100 return;
|
|
101 }
|
|
102 JtpContext jtpContext = (JtpContext)getServletContext().getAttribute(JtpContext.attrName);
|
|
103 jtpContext.setEtag(request,response, Cache.nodeChangeEvent(post) );
|
|
104 // If the user edits a mail message, we convert it into a HTML/TEXT format.
|
|
105 // After this change all attachments are lost because we lose the RAW email where
|
|
106 // the file was encoded. So we should return "404 Not Found" in such cases.
|
|
107 Message.Format fmt = post.getMessage().getFormat();
|
|
108 if (fmt instanceof MailMessageFormat) {
|
|
109 InputStream in = ((MailMessageFormat) fmt).getAttachment(post,attachmentId);
|
|
110 try {
|
|
111 IoUtils.copyAll(in,out);
|
|
112 } finally {
|
|
113 in.close();
|
|
114 }
|
|
115 } else {
|
|
116 response.sendError(HttpServletResponse.SC_NOT_FOUND, "File not found");
|
|
117 }
|
|
118 }
|
|
119
|
|
120 }
|