001// Copyright 2006, 2007, 2008, 2010, 2011 The Apache Software Foundation 002// 003// Licensed under the Apache License, Version 2.0 (the "License"); 004// you may not use this file except in compliance with the License. 005// You may obtain a copy of the License at 006// 007// http://www.apache.org/licenses/LICENSE-2.0 008// 009// Unless required by applicable law or agreed to in writing, software 010// distributed under the License is distributed on an "AS IS" BASIS, 011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012// See the License for the specific language governing permissions and 013// limitations under the License. 014 015package org.apache.tapestry5.internal.services; 016 017import java.io.IOException; 018import java.net.URL; 019 020import javax.servlet.http.HttpServletResponse; 021 022import org.apache.tapestry5.TapestryConstants; 023import org.apache.tapestry5.http.services.Context; 024import org.apache.tapestry5.http.services.Request; 025import org.apache.tapestry5.http.services.RequestFilter; 026import org.apache.tapestry5.http.services.RequestHandler; 027import org.apache.tapestry5.http.services.Response; 028 029/** 030 * Identifies requests that are for actual resource files in the context. For those, Tapestry allows the servlet 031 * container to process the request. 032 */ 033public class StaticFilesFilter implements RequestFilter 034{ 035 private final Context context; 036 037 public StaticFilesFilter(Context context) 038 { 039 this.context = context; 040 } 041 042 public boolean service(Request request, Response response, RequestHandler handler) 043 throws IOException 044 { 045 String path = request.getPath(); 046 047 // TAPESTRY-1322: Treat requests from the browser for a favorites icon via the normal 048 // servlet even if the file doesn't exist, to keep the request from looking like a 049 // component action request. 050 051 if (path.equals("/favicon.ico")) return false; 052 053 // TAPESTRY-2606: A colon in the path is frequently the case for Tapestry event URLs, 054 // but gives Windows fits. 055 056 if (!path.contains(":")) 057 { 058 // We are making the questionable assumption that all files to be vended out will contain 059 // an extension (with a dot separator). Without this, the filter tends to match against 060 // folder names when we don't want it to (especially for the root context path). 061 062 int dotx = path.lastIndexOf("."); 063 064 if (dotx > 0) 065 { 066 URL url = context.getResource(path); 067 068 if (url != null) 069 { 070 String suffix = path.substring(dotx + 1); 071 072 // We never allow access to Tapestry component templates, even if they exist. 073 // It is considered a security risk, like seeing a raw JSP. Earlier alpha versions 074 // of Tapestry required that the templates be stored in WEB-INF. 075 076 if (suffix.equalsIgnoreCase(TapestryConstants.TEMPLATE_EXTENSION)) 077 { 078 079 response.sendError(HttpServletResponse.SC_FORBIDDEN, String.format("URI %s may not be accessed remotely.", path)); 080 081 return true; 082 } 083 084 return false; 085 } 086 } 087 } 088 089 return handler.service(request, response); 090 } 091}