org.kawanfw.file.servlet.ServerFileUploadAction.java Source code

Java tutorial

Introduction

Here is the source code for org.kawanfw.file.servlet.ServerFileUploadAction.java

Source

/*
 * 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);
        }
    }

}