/*
 * 09/12/97 97/09/12
 * 
 * Copyright (c) 1995-1997 Sun Microsystems, Inc. All Rights Reserved.
 * 
 * This software is the confidential and proprietary information of Sun
 * Microsystems, Inc. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Sun.
 * 
 * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
 * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
 * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
 * THIS SOFTWARE OR ITS DERIVATIVES.  
 * 
 * CopyrightVersion 1.0
 */

import java.io.IOException;
import java.io.File;
import java.io.PrintStream;
import java.io.FileOutputStream;
import java.io.BufferedOutputStream;

import java.util.Hashtable;
import java.util.Enumeration;

import javax.servlet.*;
import javax.servlet.http.*;

/**
 * This is a basic file upload and storage servlet.  It will allow gifs to be
 * uploaded to a precreated directory, as defined by the tempDirectory init parameter.
 *
 * WARNING:  File upload opens up the potential for huge security holes.
             Please be very careful in all your implementations of this
             technology.  As in all matters related to security, it is
             best to have your work reveiwed for security implications
             by a qualified security expert.
             
             This example is believed safe, however it is still recommended
             that this example not be enabled on a production webserver.
             At the least, no real attempt has been made to stop a denial
             of service attack on your diskspace.  An unscrupulous programmer
             could use this servlet to quickly fill even the largest harddrive.
 *
 * This servlet is intended to be called via a special form page.  See
 * public_html/gifup.html for more information on configuring this servlet to run.
 *
 */
public class GifUploadServlet extends FileUploadServlet { 

    /** 
     *  Specifies temporary storage directory, where the file will be stored.
     *  If null, the servlet is considered unavailable, and an error will be
     *  returned to the client.
     *  Example:  public_html/temp/
     */
    //protected File tempDirectory = new File("public_html"+File.separator+"temp"+File.separator);
    protected File tempDirectory = null;

    /** 
     *  Specifies the URL/directory where the file will be available for viewing.
     *  If null, the file is assumed to not be viewable.
     *  Note, in JWS, this will only work if listdirectories is permitted - you
     *  can set this to be true from the admintool.
     *  Example:  /temp
     */
    //protected String urlAvail = "/temp/";
    protected String urlAvail = null;

    /** 
     *  Specifies maximum size of uploadable file.
     *  By default, this value is 1MB.  
     */
    protected int maxSize = 1024*1024*1; // 1MB 
    
    /** 
     *  Provide a default webpage for information on uploading servlets - including a form to do so.
     */
    public void init(ServletConfig sc) {
        String temp = sc.getInitParameter("tempDirectory");
        this.urlAvail = sc.getInitParameter("urlAvail");
        String max = sc.getInitParameter("maxSize");
        try {
            maxSize = Integer.parseInt(max);
        } catch (Exception e) {
            // Do nothing, leave at default value
        }
	try {
	    if (!temp.endsWith(File.separator)) {
		temp += File.separator;
	    }
	    temp.replace('/',File.separatorChar);
            tempDirectory = new File(temp);
        } catch (Exception e) {
	    // Leave set at null, will disable servlet.
        }
	try {
	    if (this.urlAvail.endsWith("/")) {
		this.urlAvail += "/";
	    }
        } catch (Exception e) {
	}
	if (tempDirectory != null && !tempDirectory.exists()
            && !tempDirectory.mkdirs() ) {
	    // Since we couldn't create the temporary directory,
	    // even though it doesn't exist, disable the servlet.
	    tempDirectory = null;
	}
    }

    /** 
    /**
     * Since fileupload requires POST, we only override this method.
     */
    protected void doPost(HttpServletRequest req, HttpServletResponse res) 
                   throws ServletException, IOException {

        Hashtable table;


	if (tempDirectory == null) {sendFailureStandard(res,"tempDirectory is unset"); return;}

        if (!req.getContentType().toLowerCase().startsWith("multipart/form-data")) {
            // Since this servlet only handles File Upload, bail out
            sendFailure(res,"Wrong content type set for file upload in the "+
			    "main page.  Something is seriously amiss.");
            return;
        }

        if (req.getContentLength() > maxSize) {
            sendFailure(res,
                       "Content too long - sent files are limited in size");
            return;
        }

        int ind = req.getContentType().indexOf("boundary=");
        if (ind == -1) {
            sendFailure(res,"boundary is not set");
            return;
        }

        String boundary = req.getContentType().substring(ind+9);

        if (boundary == null) {
            sendFailure(res,"boundary is not set");
            return;
        }

        try {
            table = parseMulti(boundary, req.getInputStream());
        } catch (Throwable t) {
            t.printStackTrace(new PrintStream(res.getOutputStream()));
            return;
        }

        ServletOutputStream out = res.getOutputStream();
        out.println("<HTML><HEAD><TITLE>FileUpload Output");
        out.println("</TITLE></HEAD><BODY>");

        Object obj = table.get("giffile");
        if (obj == null || !(obj instanceof Hashtable)) {
	    sendFailure(res, "Did not upload a file.  There may an error in the form.");
	    return;
	}
        Hashtable filehash = (Hashtable)obj;
	if (!((String)filehash.get("filename")).endsWith(".gif")) {
	    sendFailure(res, "The filename as reported by the browser "+
	                     "did not <BR> end in \".gif\".  "+
			     "Are you sure you sent a gif file?");
            return;
	}
	if (!((String)filehash.get("content-type"))
	     .toLowerCase().equals("image/gif")) {
	    sendFailure(res, "The filetype as reported by the browser"+
	                     " was not <BR> \"image/gif\".  It was "+
			     (String)filehash.get("content-type")+"<BR>"+
			     "Are you sure you sent a gif file?");
            return;
	}

        obj = table.get("filename");
        if (obj == null || !(obj instanceof String[]) || ((String[])obj)[0].equals("")) {
	    sendFailure(res,"You must specify a filename for the gif file.");
            return;
        }
	String filename = ((String[])obj)[0];
	if (filename.indexOf("..") != -1 || filename.indexOf(File.separator) != -1) {
	    sendFailure(res, "The filename you specified contained either<BR>"+
			     "\"..\" or \""+File.separator+"\".  Please do not use "+
			     "these characters.");
            return;
	}

	BufferedOutputStream fileout = new BufferedOutputStream(new FileOutputStream(tempDirectory+filename+".gif"));
        byte[] bytes = (byte[])filehash.get("content");
        fileout.write(bytes,0,bytes.length);
        fileout.flush();
	fileout.close();

        out.println("You just created a file named: " + filename+".gif<BR>");
	if (urlAvail != null) {
	    out.println("Here it is: <image src=\""+urlAvail+filename+".gif\" alt=\"Just uploaded\">");
        }

        out.println("</BODY></HTML>");
        return;
    }

/**
 * Obtain information on this servlet.
 * @return String describing this servlet.
 */
    public String getServletInfo() {
        return "gif upload servlet -- an example of fileupload";
    }

    private void sendFailureStandard(HttpServletResponse res, String addtl) throws IOException {
	sendFailure(res,"The administrator has either not set up the <BR>"+
			"servlet, or has configured it incorrectly.<BR>"+
			"The specific reason for failure is:<BR> "+addtl);
            return;
    }

    private void sendFailure(HttpServletResponse res, String reason) 
                throws IOException {

        ServletOutputStream out = res.getOutputStream();

        out.println("<HTML><HEAD>Upload Failure</HEAD><BODY>");
        out.println("<h2>The upload failed, due to:</h2>");
        out.println("<b>"+reason+"</b>");
        out.println("<P>You may wish to inform the system administrator.");
        out.println("</BODY></HTML>");
    }
}

