All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src-main.org.kawanfw.file.servlet.ServerFileUploadAction Maven / Gradle / Ivy

Go to download

Awake FILE is a secure Open Source framework that allows to program very easily file uploads/downloads and RPC through http. File transfers include powerful features like file chunking and automatic recovery mechanism. Security has been taken into account from the design: server side allows to specify strong security rules in order to protect the files and to secure the RPC calls.

The newest version!
/*
 * This file is part of Awake FILE. 
 * Awake file: Easy file upload & download over HTTP with Java.                                    
 * Copyright (C) 2015,  KawanSoft SAS
 * (http://www.kawansoft.com). All rights reserved.                                
 *                                                                               
 * Awake FILE is free software; you can redistribute it and/or                 
 * modify it under the terms of the GNU Lesser General Public                    
 * License as published by the Free Software Foundation; either                  
 * version 2.1 of the License, or (at your option) any later version.            
 *                                                                               
 * Awake FILE is distributed in the hope that it will be useful,               
 * but WITHOUT ANY WARRANTY; without even the implied warranty of                
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU             
 * Lesser General Public License for more details.                               
 *                                                                               
 * You should have received a copy of the GNU Lesser General Public              
 * License along with this library; if not, write to the Free Software           
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  
 * 02110-1301  USA
 *
 * Any modifications to this file must keep this entire header
 * intact.
 */
package org.kawanfw.file.servlet;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.logging.Level;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.kawanfw.commons.api.server.CommonsConfigurator;
import org.kawanfw.commons.server.util.ServerLogger;
import org.kawanfw.commons.util.FrameworkDebug;
import org.kawanfw.commons.util.HtmlConverter;
import org.kawanfw.commons.util.Tag;
import org.kawanfw.commons.util.TransferStatus;
import org.kawanfw.file.api.server.FileConfigurator;
import org.kawanfw.file.servlet.convert.StreamsEncrypted;
import org.kawanfw.file.servlet.util.FileTransferManager;
import org.kawanfw.file.util.parms.Parameter;
import org.kawanfw.file.util.parms.ReturnCode;

/**
 * 
 * @author Nicolas de Pomereu
 * 
 *         Upload file name See Word Documentation for help
 */

public class ServerFileUploadAction {
    private static boolean DEBUG = FrameworkDebug
	    .isSet(ServerFileUploadAction.class);

    // Max file size
    @SuppressWarnings("unused")
    private static final int MAX_FILE_SIZE = 1024 * 1024 * 20;

    // A space
    public static final String SPACE = " ";

    /**
     * 
     * Execute the dispatched request
     * 
     * @param request
     *            the http request
     * @param response
     *            the http response
     * @param servletContextTempDir
     *            The temp dir used by Servlets
     * @param commonsConfigurator
     *            the client login specific class
     * @throws IOException
     */

    public void executeAction(HttpServletRequest request,
	    HttpServletResponse response, File servletContextTempDir,
	    CommonsConfigurator commonsConfigurator,
	    FileConfigurator fileConfigurator) throws IOException {
	PrintWriter out = response.getWriter();

	try {
	    String username = null;
	    String token = null;
	    String filename = null;
	    long chunkLength = 0;

	    response.setContentType("text/html");
	    // Prepare the response

	    // Check that we have a file upload request
	    boolean isMultipart = ServletFileUpload.isMultipartContent(request);
	    debug("isMultipart: " + isMultipart);

	    if (!isMultipart) {
		return;
	    }

	    // Create a factory for disk-based file items
	    DiskFileItemFactory factory = new DiskFileItemFactory();
	    factory.setRepository(servletContextTempDir);

	    debug("servletContextTempDir: " + servletContextTempDir);

	    // Create a new file upload handler using the factory
	    // that define the secure temp dir
	    ServletFileUpload upload = new ServletFileUpload(factory);

	    // Parse the request
	    FileItemIterator iter = upload.getItemIterator(request);

	    // Parse the request
	    // List /* FileItem */ items = upload.parseRequest(request);
	    while (iter.hasNext()) {
		FileItemStream item = iter.next();
		String name = item.getFieldName();
		debug("name: " + name);

		// The input Stream for the File
		InputStream stream = item.openStream();

		if (item.isFormField()) {
		    if (name.equals(Parameter.USERNAME)) {
			// username = Streams.asString(stream);
			username = StreamsEncrypted.asString(stream,
				commonsConfigurator);

			// Not sure it's necessary:
			username = HtmlConverter.fromHtml(username);

			debug("username: " + username);
		    } else if (name.equals(Parameter.TOKEN)) {
			// token = Streams.asString(stream);
			token = StreamsEncrypted.asString(stream,
				commonsConfigurator);
			debug("token: " + token);
		    } else if (name.equals(Parameter.FILENAME)) {
			// filename = Streams.asString(stream);
			filename = StreamsEncrypted.asString(stream,
				commonsConfigurator);
			debug("filename: " + filename);
		    } else if (name.equals(Parameter.CHUNKLENGTH)) {
			String chunklengthStr = StreamsEncrypted.asString(
				stream, commonsConfigurator);
			chunkLength = Long.parseLong(chunklengthStr);
			debug("chunklengthStr: " + chunklengthStr);
		    }
		} else {

		    if (!isTokenValid(out, username, token, commonsConfigurator)) // Security
										  // check
		    {
			return;
		    }

		    // Not sure it's necessary:
		    filename = HtmlConverter.fromHtml(filename);

		    debug("");
		    debug("File field " + name + " with file name "
			    + item.getName() + " detected.");
		    debug("filename: " + filename);

		    new FileTransferManager().upload(fileConfigurator, stream,
			    username, filename, chunkLength);

		    out.println(TransferStatus.SEND_OK);
		    out.println("OK");

		    return;
		}
	    }
	} catch (Throwable throwable) {

	    Throwable finalThrowable = ServerFileDispatch.getFinalThrowable(throwable);
	    
	    out.println(TransferStatus.SEND_FAILED);
	    out.println(finalThrowable.getClass().getName());
	    out.println(ServerUserThrowable.getMessage(finalThrowable));
	    out.println(ExceptionUtils.getStackTrace(finalThrowable)); // stack trace

	    try {
		ServerLogger.getLogger().log(
			Level.WARNING,
			Tag.PRODUCT_EXCEPTION_RAISED + " "
				+ ServerUserThrowable.getMessage(finalThrowable));
		ServerLogger.getLogger().log(
			Level.WARNING,
			Tag.PRODUCT_EXCEPTION_RAISED + " "
				+ ExceptionUtils.getStackTrace(finalThrowable));
	    } catch (Exception e1) {
		e1.printStackTrace();
		e1.printStackTrace(System.out);
	    }

	}

    }

    /**
     * Check the validity of the (username, token) pair
     * 
     * @param out
     *            the out stream
     * @param username
     *            the username to check
     * @param token
     *            the associated token with the login
     * @param commonsConfigurator
     *            the client commons configurator
     * 
     * @return true if the pair (login, token) is verified and ok.
     * @throws Exception
     */
    private boolean isTokenValid(PrintWriter out, String username,
	    String token, CommonsConfigurator commonsConfigurator)
	    throws Exception {

	// OK! Now build a token with SHA-1(username + secretValue)
	String tokenRecomputed = CommonsConfiguratorCall.computeAuthToken(
		commonsConfigurator, username);

	if (token == null || !token.equals(tokenRecomputed)) {
	    debug("username       : " + username + ":");
	    debug("token          : " + token + ":");
	    debug("tokenRecomputed: " + tokenRecomputed + ":");

	    out.println(TransferStatus.SEND_OK + SPACE
		    + ReturnCode.INVALID_LOGIN_OR_PASSWORD);
	    return false;
	}

	return true;
    }

    /**
     * return the filename without the trailing / or \\
     * 
     * @param filename
     *            the filename to remove the trailing file separator
     * @return
     */
    public static String removeTrailingFileSep(String filename) {
	if (filename == null) {
	    return null;
	}

	if (filename.startsWith("" + File.separatorChar)) {
	    filename = filename.substring(1);
	}

	return filename;
    }

    private void debug(String s) {
	if (DEBUG) {
	    ServerLogger.getLogger().log(Level.WARNING, s);
	}
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy