package com.pugh.sockso.web.action; import java.io.DataInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.sql.SQLException; import org.apache.log4j.Logger; import com.pugh.sockso.Utils; import com.pugh.sockso.resources.Locale; import com.pugh.sockso.resources.Resources; import com.pugh.sockso.web.BadRequestException; import com.pugh.sockso.web.Request; import com.pugh.sockso.web.Response; import com.google.inject.Inject; public class FileServer extends BaseAction { private static final Logger log = Logger.getLogger( FileServer.class ); private final Resources r; @Inject public FileServer( final Resources r ) { this.r = r; } /** * handles the "file" command, which is a request for a resource from * the applications htdocs folder * * @throws IOException * @throws BadRequestException * @throws SQLException * */ public void handleRequest() throws IOException, BadRequestException, SQLException { final Request req = getRequest(); final Response res = getResponse(); final String type = req.getUrlParam( 1 ); res.setCookiesEnabled( false ); serveFile(); } /** * this action doesn't require a login as we still need to serve * images and css and stuff when the user isn't logged in * * @return false * */ @Override public boolean requiresLogin() { return false; } /** * no login required at all so no need to start a session * * @return * */ @Override public boolean requiresSession() { return false; } /** * serves a request file to the client * * @throws IOException * @throws BadRequestException * */ public void serveFile() throws IOException, BadRequestException { serveResource( getPathFromRequest() ); } /** * Returns the file path from the request * * @return * */ protected String getPathFromRequest() { final Request req = getRequest(); final StringBuffer path = new StringBuffer( "htdocs" ); for ( int i=1; i<req.getParamCount(); i++ ) { path.append( "/" ); path.append( req.getUrlParam(i) ); } return path.toString() .replaceAll( "\\.\\.", "" ) // remove double dots .replaceAll( "\\/{2,999}", "/" ); // remove groups of forward slashes } /** * serves the resource to the client * * @param path path to the resource * * @throws IOException * @throws BadRequestException * */ private void serveResource( final String path ) throws IOException, BadRequestException { DataInputStream in = null; final Locale locale = getLocale(); // only gzip for certain file types final String ext = Utils.getExt( path ).toLowerCase(); for ( final String gzipExt : new String[] { "css", "js" } ) if ( gzipExt.equals(ext) ) getResponse().enableGzip(); try { in = new DataInputStream( r.getResourceAsStream(path) ); sendHeaders( path ); getResponse().sendData( in ); } catch ( final FileNotFoundException e ) { throw new BadRequestException( locale.getString("www.error.fileNotFound"), 404 ); } finally { Utils.close( in ); } } /** * send the headers for serving a resource, just need to give the name of * the file we're serving to work out content types and stuff * * @param filename * */ protected void sendHeaders( final String filename ) { FileHeaders fh = new FileHeaders( getResponse(), getProperties() ); fh.sendHeaders( filename ); } }