Listing of Source cgi/FileDownloadCGI.java
package se.entra.phantom.server.http; 

import se.entra.phantom.server.ClientSessionManager;
import se.entra.phantom.server.http.HttpSession;
import se.entra.phantom.server.http.HttpResource;
import se.entra.phantom.server.http.CgiHttpResourceInterface;

import java.io.File;
import java.io.IOException;

/**
 * The <code>FileDownloadCGI</code> class causes a file to be downloaded
 * in the browser when called. The URI parameter after the resource should
 * be an URLEncoded file name.
 * 
 * @see se.entra.phantom.server.http.DirectoryListingCGI
 */
public class FileDownloadCGI implements CgiHttpResourceInterface
{
  /**
   * <p>The root directory in "server.ini" in the [FileDownloadCGI] section
   * is located from the resource name "/download.cgi". The resource name must be
   * specified as e.g. "/download.cgi=htdocs/info".
   * 
   * @throws  IOException  for IO errors.
   */
  @Override
  public HttpResource performAction(HttpSession session) throws IOException
    {
    // Locate the root directory.
    String dir=ClientSessionManager.getServerIni().getData("FileDownloadCGI",session.resourceName);
    if ( dir==null )
      throw new IOException("Root directory for "+session.resourceName+" not found in 'server.ini' section [FileDownloadCGI].");
  
    return downloadFile(session,dir);
    }
  
  /**
   * Loads a resource from a root directory for browser download.
   * 
   * @throws  IOException  for IO errors.
   */
  public static HttpResource downloadFile(HttpSession session,String dir) throws IOException
    {
    // Make sure directory is OK.
    File f=new File(dir);
    if ( !f.exists() )
      throw new IOException("Root directory for "+session.resourceName+" in "+dir+" does not exist.");
  
    if ( !f.isDirectory() )
      throw new IOException("Root directory for "+session.resourceName+" in "+dir+" is not a directory.");
  
    // Get the file name relative the root directory.
    String params=session.uriParams;
    if ( params==null || params.length()==0 )
      throw new IOException("File name parameter is invalid.");
  
    // Convert to string and make sure it's not trying to
    // access something above the root directory.
    String fn=InternetCharacterConversion.urlDecode(params).replace('\\','/');
    if ( params.indexOf("/..")>=0 )
      throw new IOException("Invalid file name specification '"+fn+"'.");
    
    if ( !fn.startsWith("/") )
      fn="/"+fn;
    
    f=new File(dir+fn);
    if ( !f.exists() )
      throw new IOException("File '"+fn+"' does not exist.");
    
    if ( !f.isFile() )
      throw new IOException("File '"+fn+"' is not a file.");
    
    try
      {
      fn=dir+fn;
      HttpResource res=session.webServer.loadResource(fn,fn,true);

      if ( res instanceof HtmlResource )
        ((HtmlResource)res).setParse(false);

      // Set HTTP reply content type to Application.
      session.replyContentType="Application/octet-stream";
    
      // Get pure filename.
      String filename=f.getName();
      int ls=filename.lastIndexOf("/");
      if (ls != -1 && ls<filename.length()-1)
        filename = filename.substring(ls+1);
      
      // Set content-disposition HTTP header, so that browser suggest correct filename.
      session.addReplyExtraHeader("Content-Disposition: attachment; filename="+filename+";");
      
      session.resourceName="n.exe";
      return res;
      }
    catch(IOException e)
      {
      throw new IOException("Cannot load resource "+fn+": "+e.getMessage());
      }
    }
}