package org.limewire.http.handler; import java.io.File; import java.io.IOException; import java.util.StringTokenizer; import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpException; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.ProtocolException; import org.apache.http.nio.entity.ConsumingNHttpEntity; import org.apache.http.nio.protocol.SimpleNHttpRequestHandler; import org.apache.http.protocol.HttpContext; import org.limewire.http.entity.BasicFileTransferMonitor; import org.limewire.http.entity.FileNIOEntity; import org.limewire.http.entity.NotFoundEntity; /** * Generic request handler that serves files from the local file system. A root * directory must be specified and only files below that directory will be * served. Requests that contain relative path names are rejected. Browsing of * directories is not supported. */ public class FileRequestHandler extends SimpleNHttpRequestHandler { private String indexFilename = "index.html"; private final File rootDirectory; private final MimeTypeProvider mimeTypeProvider; private int timeout = -1; /** * Constructs a request handler. The <code>rootDirectory</code> specifies * the root directory of the web server, i.e. a request for <code>/</code> * will be mapped to this directory. * * @param rootDirectory only files below this directory are served * @param mimeTypeProvider used to determine the mime type of a file */ public FileRequestHandler(File rootDirectory, MimeTypeProvider mimeTypeProvider) { this.rootDirectory = rootDirectory; this.mimeTypeProvider = mimeTypeProvider; } /** * If a directory is requested it is searched for a file named * <code>indexFilename</code>. The default is <code>index.html</code>. * * @param indexFilename the name of the index file */ public void setIndexFilename(String indexFilename) { this.indexFilename = indexFilename; } public String getIndexFilename() { return indexFilename; } public void setTimeout(int timeout) { this.timeout = timeout; } public int getTimeout() { return timeout; } public ConsumingNHttpEntity entityRequest(HttpEntityEnclosingRequest request, HttpContext context) throws HttpException, IOException { return null; } @Override public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException { File file = getFile(request); if (file.exists() && file.isFile()) { String mimeType = mimeTypeProvider.getMimeType(file); FileNIOEntity entity = new FileNIOEntity(file, mimeType , new BasicFileTransferMonitor(context)); if (timeout != -1) { entity.setTimeout(timeout); } response.setEntity(entity); } else { response.setEntity(new NotFoundEntity(request)); response.setStatusCode(HttpStatus.SC_NOT_FOUND); } } private File getFile(HttpRequest request) throws HttpException { if (!request.getRequestLine().getUri().startsWith("/")) { throw new ProtocolException("Invalid request"); } File file = rootDirectory; StringTokenizer t = new StringTokenizer(request.getRequestLine().getUri(), "/"); while (t.hasMoreTokens()) { String next = t.nextToken(); if (next.indexOf(File.pathSeparator) != -1) { throw new ProtocolException("Invalid request"); } if (next.indexOf("..") != -1) { throw new ProtocolException("Invalid request"); } file = new File(file, next); } if (file.isDirectory()) { file = new File(file, indexFilename); } return file; } }