1 // Copyright 2006, 2007, 2008 The Apache Software Foundation
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 package org.apache.tapestry5.internal.services;
16
17 import org.apache.tapestry5.internal.InternalConstants;
18 import org.apache.tapestry5.services;
19
20 import javax.servlet.http.HttpServletResponse;
21 import java.io.IOException;
22 import java.net.URL;
23
24 /**
25 * Identifies requests that are for actual resource files in the context. For those, Tapestry allows the servlet
26 * container to process the request.
27 */
28 public class StaticFilesFilter implements RequestFilter
29 {
30 private final Context context;
31
32 public StaticFilesFilter(Context context)
33 {
34 this.context = context;
35 }
36
37 public boolean service(Request request, Response response, RequestHandler handler)
38 throws IOException
39 {
40 String path = request.getPath();
41
42 // TAPESTRY-1322: Treat requests from the browser for a favorites icon via the normal
43 // servlet even if the file doesn't exist, to keep the request from looking like a
44 // component action request.
45
46 if (path.equals("/favicon.ico")) return false;
47
48 // TAPESTRY-2606: A colon in the path is frequently the case for Tapestry event URLs,
49 // but gives Windows fits.
50
51 if (!path.contains(":"))
52 {
53 // We are making the questionable assumption that all files to be vended out will contain
54 // an extension (with a dot separator). Without this, the filter tends to match against
55 // folder names when we don't want it to (especially for the root context path).
56
57 int dotx = path.lastIndexOf(".");
58
59 if (dotx > 0)
60 {
61 URL url = context.getResource(path);
62
63 if (url != null)
64 {
65 String suffix = path.substring(dotx + 1);
66
67 // We never allow access to Tapestry component templates, even if they exist.
68 // It is considered a security risk, like seeing a raw JSP. Earlier alpha versions
69 // of Tapestry required that the templates be stored in WEB-INF.
70
71 if (suffix.equalsIgnoreCase(InternalConstants.TEMPLATE_EXTENSION))
72 {
73
74 response.sendError(HttpServletResponse.SC_FORBIDDEN, ServicesMessages
75 .resourcesAccessForbidden(path));
76
77 return true;
78 }
79
80 return false;
81 }
82 }
83 }
84
85 return handler.service(request, response);
86 }
87 }