001: /**
002: * Copyright (C) 2006, 2007 David Bulmore, Software Sensation Inc.
003: * All Rights Reserved.
004: *
005: * This file is part of jWebApp.
006: *
007: * jWebApp is free software; you can redistribute it and/or modify it under
008: * the terms of the GNU General Public License (Version 2) as published by
009: * the Free Software Foundation.
010: *
011: * jWebApp is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with jWebApp; if not, write to the Free Software Foundation,
018: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
019: */package jwebapp.request;
020:
021: import java.io.File;
022: import java.io.InputStream;
023: import java.io.OutputStream;
024: import java.util.logging.Level;
025: import java.util.logging.Logger;
026: import javax.servlet.http.HttpServletResponse;
027: import jwebapp.controller.RequestHandler;
028: import jwebapp.controller.ServerInterface;
029:
030: /**
031: * Provides a secure method for downloads of any file, including files that can not be
032: * accessed via a normal web request.
033: *
034: * <p>DownloadHandler expects a jWebApp request parameter named 'filename' that contains the name
035: * of a file that will be returned to the client via the files expected content type. If the
036: * jWebApp request parameter is not defined then a normal request parameter should be defined.
037: *
038: * <p>DownloadHandler also looks for a jWebApp request parameter named 'directory'. If directory
039: * is defined then the file defined in the request parameter can only be retreived from the
040: * download directory. The filename defined in the request parameter should be relative to the
041: * directory. This should always be defined! If it is not defined, then the file parameter
042: * should not be accessable to the user, who could potentially download anything.
043: *
044: * <p>DownloadHandler can access files anywhere and uses ServletContext.getResource() to
045: * locate the file, so the file name can be relative to the web context. DownloadHandler allows
046: * you to protect downloads via security roles, and gives you the ability to narrow the download to a
047: * specific directory and/or file. Therefore, DownloadHandler provides a highly secure method for
048: * file downloads.
049: */
050: public class Download extends RequestHandler {
051: private static Logger logger = Logger.getLogger(Download.class
052: .getName());
053:
054: public String processRequest(ServerInterface serverInterface) {
055: String filename = serverInterface.getRequestData()
056: .getParameter("filename");
057: String directory = serverInterface.getRequestData()
058: .getParameter("directory");
059:
060: if (filename == null)
061: filename = serverInterface.getParameter("filename");
062:
063: if (directory != null)
064: filename = directory + File.separator + filename;
065:
066: try {
067: InputStream in = serverInterface.getServletContext()
068: .getResourceAsStream(filename);
069:
070: if (in == null) {
071: if (logger.isLoggable(Level.FINER))
072: logger.finer("filename resource '" + filename
073: + "' was not located");
074:
075: serverInterface.getServletResponse().sendError(
076: HttpServletResponse.SC_NOT_FOUND,
077: "filename resource '" + filename
078: + "' was not located");
079: } else {
080: serverInterface.getServletResponse().setContentType(
081: serverInterface.getServletContext()
082: .getMimeType(filename));
083: serverInterface.getServletResponse().addHeader(
084: "content-disposition",
085: "attachment; filename="
086: + new File(filename).getName());
087:
088: OutputStream out = serverInterface.getServletResponse()
089: .getOutputStream();
090: byte buf[] = new byte[2048];
091: int numberRead = 0;
092:
093: while ((numberRead = in.read(buf)) != -1)
094: out.write(buf, 0, numberRead);
095:
096: out.close();
097: in.close();
098: }
099: } catch (Exception e) {
100: logger.log(Level.SEVERE, e.toString(), e);
101:
102: serverInterface.setErrorMessage(e.toString());
103: }
104:
105: return NO_FORWARDING;
106: }
107: }
|