/* The contents of this file are subject to the license and copyright terms
* detailed in the license directory at the root of the source tree (also
* available online at http://fedora-commons.org/license/).
*/
package fedora.server.security.servletfilters;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Determines if the client is a flash player (based on a query string
* value of 'flash' being set to true) and wraps the response to
* guarantee only 2xx range response codes.
*
* Responses which would normally return with a status outside of the 2xx
* range are updated such that the response code is set to 200 and the
* response body ends with the string "::ERROR(code)" where code
* is replaced by the actual response code.
*
* @author Bill Branan
*/
public class FilterRestApiFlash implements Filter {
protected static Log log = LogFactory.getLog(FilterRestApiFlash.class);
/**
* Required Filter method
*/
public void init(FilterConfig arg0) throws ServletException {
}
/**
* Perform flash client response filtering
*/
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain filterChain)
throws IOException, ServletException {
if (log.isDebugEnabled()) {
log.debug("Entering FilterRestApiFlash.doThisSubclass()");
}
HttpServletRequest httpRequest = (HttpServletRequest)request;
HttpServletResponse httpResponse = (HttpServletResponse)response;
String queryString = httpRequest.getQueryString();
if(queryString != null &&
queryString.contains("flash=true")) {
StatusHttpServletResponseWrapper sHttpResponse =
new StatusHttpServletResponseWrapper(httpResponse);
filterChain.doFilter(request, sHttpResponse);
if(sHttpResponse.status != sHttpResponse.realStatus) {
// Append the error indicator with real status
try {
ServletOutputStream out = sHttpResponse.getOutputStream();
out.print("::ERROR("+sHttpResponse.realStatus+")");
} catch(IllegalStateException ise) {
PrintWriter out = sHttpResponse.getWriter();
out.print("::ERROR("+sHttpResponse.realStatus+")");
}
}
} else {
filterChain.doFilter(request, response);
}
}
/**
* Required Filter method
*/
public void destroy() {
}
/**
* Ensures that all returned HTTP status codes are in the 2xx range,
* this allows Flash-based client applications to have access to
* error responses.
*/
private static class StatusHttpServletResponseWrapper
extends HttpServletResponseWrapper {
private int realStatus;
private int status;
public StatusHttpServletResponseWrapper(HttpServletResponse response) {
super(response);
}
@Override
public void setStatus(final int statusCode) {
realStatus = statusCode;
if ((statusCode - 200) < 0 ||
(statusCode - 200) >= 100) {
// Set code to 200 for all responses
status = SC_OK;
super.setStatus(status);
} else {
status = statusCode;
}
}
}
}