1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.apache.struts2.interceptor;
23
24 import java.io.File;
25 import java.io.IOException;
26 import java.net.URI;
27 import java.net.URL;
28 import java.util.HashMap;
29 import java.util.List;
30 import java.util.Locale;
31 import java.util.Map;
32
33 import javax.servlet.http.HttpServletRequest;
34
35 import org.apache.struts2.ServletActionContext;
36 import org.apache.struts2.StrutsTestCase;
37 import org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest;
38 import org.apache.struts2.dispatcher.multipart.MultiPartRequest;
39 import org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper;
40 import org.apache.commons.fileupload.servlet.ServletFileUpload;
41 import org.springframework.mock.web.MockHttpServletRequest;
42
43 import com.opensymphony.xwork2.util.ClassLoaderUtil;
44 import com.opensymphony.xwork2.ActionContext;
45 import com.opensymphony.xwork2.ActionSupport;
46 import com.opensymphony.xwork2.ValidationAwareSupport;
47 import com.opensymphony.xwork2.mock.MockActionInvocation;
48
49
50 /***
51 * Test case for FileUploadInterceptor.
52 */
53 public class FileUploadInterceptorTest extends StrutsTestCase {
54
55 private FileUploadInterceptor interceptor;
56 private File tempDir;
57
58 public void testAcceptFileWithEmptyAllowedTypesAndExtensions() throws Exception {
59
60 ValidationAwareSupport validation = new ValidationAwareSupport();
61 boolean ok = interceptor.acceptFile(null, new File(""), "filename", "text/plain", "inputName", validation, Locale.getDefault());
62
63 assertTrue(ok);
64 assertTrue(validation.getFieldErrors().isEmpty());
65 assertFalse(validation.hasErrors());
66 }
67
68 public void testAcceptFileWithoutEmptyTypes() throws Exception {
69 interceptor.setAllowedTypes("text/plain");
70
71
72 ValidationAwareSupport validation = new ValidationAwareSupport();
73 boolean ok = interceptor.acceptFile(null, new File(""), "filename.txt", "text/plain", "inputName", validation, Locale.getDefault());
74
75 assertTrue(ok);
76 assertTrue(validation.getFieldErrors().isEmpty());
77 assertFalse(validation.hasErrors());
78
79
80 validation = new ValidationAwareSupport();
81 boolean notOk = interceptor.acceptFile(null, new File(""), "filename.html", "text/html", "inputName", validation, Locale.getDefault());
82
83 assertFalse(notOk);
84 assertFalse(validation.getFieldErrors().isEmpty());
85 assertTrue(validation.hasErrors());
86 }
87
88 public void testAcceptFileWithoutEmptyExtensions() throws Exception {
89 interceptor.setAllowedExtensions(".txt");
90
91
92 ValidationAwareSupport validation = new ValidationAwareSupport();
93 boolean ok = interceptor.acceptFile(null, new File(""), "filename.txt", "text/plain", "inputName", validation, Locale.getDefault());
94
95 assertTrue(ok);
96 assertTrue(validation.getFieldErrors().isEmpty());
97 assertFalse(validation.hasErrors());
98
99
100 validation = new ValidationAwareSupport();
101 boolean notOk = interceptor.acceptFile(null, new File(""), "filename.html", "text/html", "inputName", validation, Locale.getDefault());
102
103 assertFalse(notOk);
104 assertFalse(validation.getFieldErrors().isEmpty());
105 assertTrue(validation.hasErrors());
106
107
108 interceptor.setAllowedExtensions(".txt,.lol");
109 validation = new ValidationAwareSupport();
110 ok = interceptor.acceptFile(null, new File(""), "filename.lol", "text/plain", "inputName", validation, Locale.getDefault());
111
112 assertTrue(ok);
113 assertTrue(validation.getFieldErrors().isEmpty());
114 assertFalse(validation.hasErrors());
115 }
116
117 public void testAcceptFileWithNoFile() throws Exception {
118 FileUploadInterceptor interceptor = new FileUploadInterceptor();
119 interceptor.setAllowedTypes("text/plain");
120
121
122 ValidationAwareSupport validation = new ValidationAwareSupport();
123 boolean notOk = interceptor.acceptFile(null, null, "filename.html", "text/html", "inputName", validation, Locale.getDefault());
124
125 assertFalse(notOk);
126 assertFalse(validation.getFieldErrors().isEmpty());
127 assertTrue(validation.hasErrors());
128 List errors = (List) validation.getFieldErrors().get("inputName");
129 assertEquals(1, errors.size());
130 String msg = (String) errors.get(0);
131 assertTrue(msg.startsWith("Error uploading:"));
132 assertTrue(msg.indexOf("inputName") > 0);
133 }
134
135 public void testAcceptFileWithMaxSize() throws Exception {
136 interceptor.setAllowedTypes("text/plain");
137 interceptor.setMaximumSize(new Long(10));
138
139
140 ValidationAwareSupport validation = new ValidationAwareSupport();
141
142 URL url = ClassLoaderUtil.getResource("log4j.properties", FileUploadInterceptorTest.class);
143 File file = new File(new URI(url.toString()));
144 assertTrue("log4j.properties should be in src/test folder", file.exists());
145 boolean notOk = interceptor.acceptFile(null, file, "filename", "text/html", "inputName", validation, Locale.getDefault());
146
147 assertFalse(notOk);
148 assertFalse(validation.getFieldErrors().isEmpty());
149 assertTrue(validation.hasErrors());
150 List errors = (List) validation.getFieldErrors().get("inputName");
151 assertEquals(1, errors.size());
152 String msg = (String) errors.get(0);
153
154 assertTrue(msg.startsWith("The file is to large to be uploaded"));
155 assertTrue(msg.indexOf("inputName") > 0);
156 assertTrue(msg.indexOf("log4j.properties") > 0);
157 }
158
159 public void testNoMultipartRequest() throws Exception {
160 MyFileupAction action = new MyFileupAction();
161
162 MockActionInvocation mai = new MockActionInvocation();
163 mai.setAction(action);
164 mai.setResultCode("NoMultipart");
165 mai.setInvocationContext(ActionContext.getContext());
166
167
168 assertEquals("NoMultipart", interceptor.intercept(mai));
169 }
170
171 public void testInvalidContentTypeMultipartRequest() throws Exception {
172 MockHttpServletRequest req = new MockHttpServletRequest();
173
174 req.setCharacterEncoding("text/html");
175 req.setContentType("text/xml");
176 req.addHeader("Content-type", "multipart/form-data");
177
178 MyFileupAction action = new MyFileupAction();
179 MockActionInvocation mai = new MockActionInvocation();
180 mai.setAction(action);
181 mai.setResultCode("success");
182 mai.setInvocationContext(ActionContext.getContext());
183
184 Map param = new HashMap();
185 ActionContext.getContext().setParameters(param);
186 ActionContext.getContext().put(ServletActionContext.HTTP_REQUEST, createMultipartRequest((HttpServletRequest) req, 2000));
187
188 interceptor.intercept(mai);
189
190 assertTrue(action.hasErrors());
191 }
192
193 public void testNoContentMultipartRequest() throws Exception {
194 MockHttpServletRequest req = new MockHttpServletRequest();
195
196 req.setCharacterEncoding("text/html");
197 req.setContentType("multipart/form-data; boundary=---1234");
198 req.setContent(null);
199
200 MyFileupAction action = new MyFileupAction();
201 MockActionInvocation mai = new MockActionInvocation();
202 mai.setAction(action);
203 mai.setResultCode("success");
204 mai.setInvocationContext(ActionContext.getContext());
205
206 Map param = new HashMap();
207 ActionContext.getContext().setParameters(param);
208 ActionContext.getContext().put(ServletActionContext.HTTP_REQUEST, createMultipartRequest((HttpServletRequest) req, 2000));
209
210 interceptor.intercept(mai);
211
212 assertTrue(action.hasErrors());
213 }
214
215 public void testSuccessUploadOfATextFileMultipartRequest() throws Exception {
216 MockHttpServletRequest req = new MockHttpServletRequest();
217 req.setCharacterEncoding("text/html");
218 req.setContentType("multipart/form-data; boundary=---1234");
219 req.addHeader("Content-type", "multipart/form-data");
220
221
222 String content = ("-----1234\r\n" +
223 "Content-Disposition: form-data; name=\"file\"; filename=\"deleteme.txt\"\r\n" +
224 "Content-Type: text/html\r\n" +
225 "\r\n" +
226 "Unit test of FileUploadInterceptor" +
227 "\r\n" +
228 "-----1234--\r\n");
229 req.setContent(content.getBytes("US-ASCII"));
230
231 MyFileupAction action = new MyFileupAction();
232
233 MockActionInvocation mai = new MockActionInvocation();
234 mai.setAction(action);
235 mai.setResultCode("success");
236 mai.setInvocationContext(ActionContext.getContext());
237 Map<String, Object> param = new HashMap<String, Object>();
238 ActionContext.getContext().setParameters(param);
239 ActionContext.getContext().put(ServletActionContext.HTTP_REQUEST, createMultipartRequest((HttpServletRequest) req, 2000));
240
241 interceptor.intercept(mai);
242
243 assertTrue(!action.hasErrors());
244
245 assertTrue(param.size() == 3);
246 File[] files = (File[]) param.get("file");
247 String[] fileContentTypes = (String[]) param.get("fileContentType");
248 String[] fileRealFilenames = (String[]) param.get("fileFileName");
249
250 assertNotNull(files);
251 assertNotNull(fileContentTypes);
252 assertNotNull(fileRealFilenames);
253 assertTrue(files.length == 1);
254 assertTrue(fileContentTypes.length == 1);
255 assertTrue(fileRealFilenames.length == 1);
256 assertEquals("text/html", fileContentTypes[0]);
257 assertNotNull("deleteme.txt", fileRealFilenames[0]);
258 }
259
260 /***
261 * tests whether with multiple files sent with the same name, the ones with forbiddenTypes (see
262 * FileUploadInterceptor.setAllowedTypes(...) ) are sorted out.
263 *
264 * @throws Exception
265 */
266 public void testMultipleAccept() throws Exception {
267 final String htmlContent = "<html><head></head><body>html content</body></html>";
268 final String plainContent = "plain content";
269 final String bondary = "simple boundary";
270 final String endline = "\r\n";
271
272 MockHttpServletRequest req = new MockHttpServletRequest();
273 req.setCharacterEncoding("text/html");
274 req.setMethod("POST");
275 req.setContentType("multipart/form-data; boundary=" + bondary);
276 req.addHeader("Content-type", "multipart/form-data");
277 StringBuilder content = new StringBuilder(128);
278 content.append(encodeTextFile(bondary, endline, "file", "test.html", "text/plain", plainContent));
279 content.append(encodeTextFile(bondary, endline, "file", "test1.html", "text/html", htmlContent));
280 content.append(encodeTextFile(bondary, endline, "file", "test2.html", "text/html", htmlContent));
281 content.append(endline);
282 content.append(endline);
283 content.append(endline);
284 content.append("--");
285 content.append(bondary);
286 content.append("--");
287 content.append(endline);
288 req.setContent(content.toString().getBytes());
289
290 assertTrue(ServletFileUpload.isMultipartContent(req));
291
292 MyFileupAction action = new MyFileupAction();
293 MockActionInvocation mai = new MockActionInvocation();
294 mai.setAction(action);
295 mai.setResultCode("success");
296 mai.setInvocationContext(ActionContext.getContext());
297 Map<String, Object> param = new HashMap<String, Object>();
298 ActionContext.getContext().setParameters(param);
299 ActionContext.getContext().put(ServletActionContext.HTTP_REQUEST, createMultipartRequest(req, 2000));
300
301 interceptor.setAllowedTypes("text/html");
302 interceptor.intercept(mai);
303
304 assertEquals(3, param.size());
305 File[] files = (File[]) param.get("file");
306 String[] fileContentTypes = (String[]) param.get("fileContentType");
307 String[] fileRealFilenames = (String[]) param.get("fileFileName");
308
309 assertNotNull(files);
310 assertNotNull(fileContentTypes);
311 assertNotNull(fileRealFilenames);
312 assertEquals("files accepted ", 2, files.length);
313 assertEquals(2, fileContentTypes.length);
314 assertEquals(2, fileRealFilenames.length);
315 assertEquals("text/html", fileContentTypes[0]);
316 assertNotNull("test1.html", fileRealFilenames[0]);
317 }
318
319 private String encodeTextFile(String bondary, String endline, String name, String filename, String contentType, String content) {
320 final StringBuilder sb = new StringBuilder(64);
321 sb.append(endline);
322 sb.append("--");
323 sb.append(bondary);
324 sb.append(endline);
325 sb.append("Content-Disposition: form-data; name=\"");
326 sb.append(name);
327 sb.append("\"; filename=\"");
328 sb.append(filename);
329 sb.append(endline);
330 sb.append("Content-Type: ");
331 sb.append(contentType);
332 sb.append(endline);
333 sb.append(endline);
334 sb.append(content);
335
336 return sb.toString();
337 }
338
339 private MultiPartRequestWrapper createMultipartRequest(HttpServletRequest req, int maxsize) throws IOException {
340 JakartaMultiPartRequest jak = new JakartaMultiPartRequest();
341 jak.setMaxSize(String.valueOf(maxsize));
342 return new MultiPartRequestWrapper(jak, req, tempDir.getAbsolutePath());
343 }
344
345 protected void setUp() throws Exception {
346 super.setUp();
347 interceptor = new FileUploadInterceptor();
348 tempDir = File.createTempFile("struts", "fileupload");
349 tempDir.delete();
350 tempDir.mkdirs();
351 }
352
353 protected void tearDown() throws Exception {
354 tempDir.delete();
355 interceptor.destroy();
356 super.tearDown();
357 }
358
359 private class MyFileupAction extends ActionSupport {
360
361 private static final long serialVersionUID = 6255238895447968889L;
362
363
364 }
365
366
367 }