it.lufraproini.cms.servlet.Upload.java Source code

Java tutorial

Introduction

Here is the source code for it.lufraproini.cms.servlet.Upload.java

Source

/*   SimpleCMS - un semplice content management system di pagine statiche
 *    Copyright (C) 2013  Francesco Proietti, Luca Traini
 *
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU Affero General Public License as
 *    published by the Free Software Foundation, either version 3 of the
 *    License, or (at your option) any later version.
 *
 *    This program 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 Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>
 */
package it.lufraproini.cms.servlet;

import it.lufraproini.cms.framework.result.FailureResult;
import it.lufraproini.cms.framework.result.TemplateResult;
import it.lufraproini.cms.model.Css;
import it.lufraproini.cms.model.Immagine;
import it.lufraproini.cms.model.Slide;
import it.lufraproini.cms.model.Utente;
import it.lufraproini.cms.model.impl.CMSDataLayerImpl;
import it.lufraproini.cms.utility.ErroreGrave;
import it.lufraproini.cms.utility.SecurityLayer;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.sql.DataSource;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;

/**
 *
 * @author fsfskittu
 */
public class Upload extends HttpServlet {

    private String estensione;
    private String nomefile;
    private final String caratteri_non_ammessi = "['\"/\\\\]";//slash, apici singoli e apici doppi

    /*si poteva utilizzare un filtro per le form multipart gi creato dal prof. Della Penna,
    la tecnica  stata appresa successivamente allo sviluppo della seguente servlet, e
    poich non introduceva alcun miglioramento all'applicazione si  deciso di non adottarla
    */
    /*FUNZIONE GENERICA PER PRENDERE TUTTI I CAMPI E IL FILE NELLE FORM DI UPLOAD*/
    /*IL CAMPO DEL FILE DEVE INIZIARE PER file_to_upload*/
    private Map prendiInfo(HttpServletRequest request) throws FileUploadException {
        Map info = new HashMap();
        Map files = new HashMap();

        //riutilizzo codice prof. Della Penna per l'upload
        if (ServletFileUpload.isMultipartContent(request)) {
            // Funzioni delle librerie Apache per l'upload
            FileItemFactory factory = new DiskFileItemFactory();
            ServletFileUpload upload = new ServletFileUpload(factory);
            List<FileItem> items;
            items = upload.parseRequest(request);
            //
            for (FileItem item : items) {
                String name = item.getFieldName();
                //le form che prevedono l'upload di un file devono avere il campo del file chiamato in questo modo
                if (name.startsWith("file_to_upload")) {
                    files.put(name, item);
                } else {
                    info.put(name, item.getString());
                }
            }
            info.put("files", files);
            return info;
        }
        return null;
    }

    /*questa funzione*/
    private String action_upload(HttpServletRequest request, Map data)
            throws ErroreGrave, SQLException, IOException, NamingException, NoSuchAlgorithmException {

        FileItem fi = null;
        String sdigest = "";
        String cartella = "";
        String tipo_file = data.get("submit").toString();
        String estensione = "";
        String campi_errati = "";
        Map files = new HashMap();
        files = (HashMap) data.get("files");
        campi_errati = checkfields(data);
        if (!campi_errati.equals("")) {
            throw new ErroreGrave("I seguenti campi contengono valori non ammessi: " + campi_errati);
            //return null;
        }

        if (tipo_file.equals("immagine")) {
            cartella = getServletContext().getInitParameter("system.image_directory");
        } else if (tipo_file.equals("css")) {
            cartella = getServletContext().getInitParameter("system.css_directory");
        } else if (tipo_file.equals("slide")) {
            cartella = getServletContext().getInitParameter("system.slide_directory");
        } else {
            throw new ErroreGrave("i tipi di file che si vogliono inviare al server non sono ancora supportati");
        }

        fi = (FileItem) files.get("file_to_upload");
        String nome = fi.getName();
        if (nome != null) {
            estensione = FilenameUtils.getExtension(FilenameUtils.getName(nome));
        }
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        File temp_file = File.createTempFile("upload_", "_temp",
                new File(getServletContext().getRealPath(cartella)));
        InputStream is = fi.getInputStream();
        OutputStream os = new FileOutputStream(temp_file);
        byte[] buffer = new byte[1024];
        int read;
        while ((read = is.read(buffer)) > 0) {
            //durante la copia, aggreghiamo i byte del file nel digest sha-1
            os.write(buffer, 0, read);
            md.update(buffer, 0, read);
        }
        is.close();
        os.close();

        //covertiamo il digest in una stringa
        byte[] digest = md.digest();
        for (byte b : digest) {
            sdigest += String.valueOf(b);
        }

        if (sdigest.equals("")) {
            throw new ErroreGrave();
        }

        this.estensione = estensione;
        if (estensione.equals("css")) {
            this.nomefile = data.get("nome").toString();
        } else {
            this.nomefile = sdigest;
        }
        //L'immagine sar salvata con il digest + l'estensione del file mentre il css sar salvato con il nome inserito nella form
        File uploaded_file = new File(
                getServletContext().getRealPath(cartella) + File.separatorChar + this.nomefile + "." + estensione);
        if (!uploaded_file.exists()) {
            temp_file.renameTo(uploaded_file);
        } else {
            temp_file.delete();
        }
        return sdigest;
    }

    private Immagine memorizzaImmagine(Map data, CMSDataLayerImpl datalayer, String digest, long id_user)
            throws SQLException, ErroreGrave {
        String error_message;
        Map files = new HashMap();
        FileItem fi = null;
        files = (HashMap) data.get("files");
        fi = (FileItem) files.get("file_to_upload");
        /*costruzione current timestamp*/
        Calendar calendar = Calendar.getInstance();
        Date now = calendar.getTime();
        Timestamp current_timestamp = new Timestamp(now.getTime());
        /**/
        Utente U = datalayer.getUtente(id_user);
        Immagine img_upload = datalayer.createImmagine();
        Immagine img_result;
        //se l'utente non ha spazio a sufficienza per fare l'upload questo viene rifiutato
        long spazio_risultante = U.getSpazio_disp_img() - fi.getSize();
        if (spazio_risultante < 0) {
            //viene eliminato il file appena memorizzato in action_upload
            File uploaded_file = new File(
                    getServletContext().getRealPath(getServletContext().getInitParameter("system.image_directory"))
                            + File.separatorChar + this.nomefile + "." + this.estensione);
            if (uploaded_file.exists()) {
                uploaded_file.delete();
            }
            error_message = "L'utente non ha spazio disponibile sufficiente per caricare l'immagine!";
            error_message += " Byte disponibili: " + U.getSpazio_disp_img();
            error_message += " - Byte immagine: " + fi.getSize();
            throw new ErroreGrave(error_message);
        }
        img_upload.setNome(SecurityLayer.addSlashes(data.get("nome").toString()));
        img_upload.setDimensione(fi.getSize());
        img_upload.setTipo(fi.getContentType());
        img_upload.setFile(getServletContext().getInitParameter("system.image_directory") + File.separatorChar
                + digest + "." + estensione);
        img_upload.setDigest(digest);
        img_upload.setData_upload(current_timestamp);
        img_upload.setUtente(U);
        img_result = datalayer.addImmagine(img_upload);
        // aggiornamento spazio immagini utente
        if (img_result != null) {
            U.setSpazio_disp_img(spazio_risultante);
            U = datalayer.updateUtente(U);
            if (U != null) {
                return img_result;
            } else {
                datalayer.deleteImmagine(img_result);
                throw new ErroreGrave("Non  stato possibile aggiornare lo spazio immagine dell'utente!");
            }
        }
        throw new ErroreGrave("Impossibile inserire i dati dell'immagine nel DB!");
    }

    private Boolean creaThumbnail(Immagine img, String username) {
        String cartella = getServletContext().getInitParameter("system.image_directory");
        String file_img = img.getFile().substring(img.getFile().indexOf("/"));
        String path = getServletContext().getRealPath(cartella);
        int altezza_thumb = 120;
        int larghezza_thumb = 120;
        BufferedImage thumb = new BufferedImage(larghezza_thumb, altezza_thumb, BufferedImage.TYPE_INT_RGB);
        try {
            if (ImageIO.read(new File(path + file_img)).getWidth() >= larghezza_thumb) {
                thumb.createGraphics().drawImage(ImageIO.read(new File(path + file_img)).getScaledInstance(-1,
                        altezza_thumb, Image.SCALE_SMOOTH), 0, 0, null);
            } else {
                thumb.createGraphics().drawImage(ImageIO.read(new File(path + file_img))
                        .getScaledInstance(larghezza_thumb, altezza_thumb, Image.SCALE_SMOOTH), 0, 0, null);
            }

            ImageIO.write(thumb, estensione,
                    new File(path + File.separatorChar + "thumbnail_" + username + "." + estensione));
        } catch (IOException ex) {
            return false;
        }
        return true;
    }

    private Css memorizzaCss(Map data, CMSDataLayerImpl datalayer) throws ErroreGrave {
        Map files = new HashMap();
        FileItem fi = null;
        files = (HashMap) data.get("files");
        fi = (FileItem) files.get("file_to_upload");
        Css css_upload = datalayer.createCSS();
        Css css_result;

        css_upload.setFile(getServletContext().getInitParameter("system.css_directory") + File.separatorChar
                + data.get("nome").toString() + "." + estensione);
        css_upload.setNome(SecurityLayer.addSlashes(data.get("nome").toString()));
        if (data.get("descrizione").toString() != null) {
            css_upload.setDescrizione(data.get("descrizione").toString());
        }
        css_result = datalayer.addCSS(css_upload);
        if (css_result == null) {
            throw new ErroreGrave("Impossibile aggiungere dati del file css al DB!");
        }
        return css_result;
    }

    private Slide memorizzaSlide(Map data, CMSDataLayerImpl datalayer, String digest) throws ErroreGrave {
        Map files = new HashMap();
        FileItem fi = null;
        files = (HashMap) data.get("files");
        fi = (FileItem) files.get("file_to_upload");
        Slide slide_upload = datalayer.createSlide();
        Slide slide_result;
        /*i controlli sulla validit dei campi sono gi stati effettuati dalla funzione checkfields, pertanto  necessario soltanto utilizzare le funzioni per l'SQL INJECTION*/
        slide_upload.setFile(getServletContext().getInitParameter("system.slide_directory") + File.separatorChar
                + digest + "." + estensione);
        slide_upload.setDescrizione(SecurityLayer.addSlashes(data.get("descrizione").toString()));
        slide_upload.setPosizione(Integer.parseInt(data.get("posizione").toString()));
        slide_upload.setNome(SecurityLayer.addSlashes(data.get("nome").toString()));

        slide_result = datalayer.addSlide(slide_upload);
        if (slide_result == null) {
            throw new ErroreGrave("Impossibile aggiungere dati del file css al DB!");
        }
        return slide_result;
    }

    /*funzione che ritorna una stringa contenente tutti i campi considerati errati nella form*/
    private String checkfields(Map fields) {
        String campi_errati = "";
        //immagini, css e slide
        if (fields.containsKey("nome") && (fields.get("nome") == null
                || fields.get("nome").toString().matches(".*" + caratteri_non_ammessi + ".*"))) {
            campi_errati += " nome ";
        }
        //slide e css
        if (fields.containsKey("descrizione")) {
            if (fields.get("descrizione").toString().equals("")) {
                campi_errati += " descrizione ";
            }
        }
        //necessario per slide
        if (fields.containsKey("posizione")) {
            if (!fields.get("posizione").toString().equals("")) {
                try {
                    SecurityLayer.checkNumeric(fields.get("posizione").toString());
                } catch (NumberFormatException ex) {
                    campi_errati += " posizione ";
                }
            } else {
                campi_errati += " posizione ";
            }
        }
        return campi_errati;
    }

    /**
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code>
     * methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     * @throws org.apache.commons.fileupload.FileUploadException
     * @throws java.sql.SQLException
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException, FileUploadException, SQLException, Exception {
        /*verifica validit sessione*/
        HttpSession s = SecurityLayer.checkSession(request);
        if (s != null) {

            /*DBMS*/
            DataSource ds = (DataSource) getServletContext().getAttribute("datasource");
            Connection connection = ds.getConnection();
            /**/
            CMSDataLayerImpl datalayer = new CMSDataLayerImpl(connection);
            String digest = "";
            String html = "";
            String tipo = "";
            Map template_data = new HashMap();
            Map info = new HashMap();

            info = prendiInfo(request);
            //info = request.getParameterMap();

            /*per prevedere l'upload di un nuovo tipo di file basta dare un valore personalizzato al submit nella form
            e creare un if con il flusso relativo all'oggetto da caricare nel file system e nel database*/
            tipo = info.get("submit").toString();
            try {
                //flusso immagine
                if (tipo.equals("immagine")) {
                    Immagine img;
                    Boolean thumbnail = false;
                    html = "show_immagine.ftl.html";
                    digest = action_upload(request, info);
                    img = memorizzaImmagine(info, datalayer, digest, (Long) s.getAttribute("userid"));
                    img.setNome(SecurityLayer.stripSlashes(img.getNome()));//potrebbe causare eccezione su img  null
                    if (info.containsKey("thumbnail")) {
                        thumbnail = creaThumbnail(img, s.getAttribute("username").toString());
                    }
                    template_data.put("thumbnail", thumbnail.toString());
                    template_data.put("immagine", img);
                    template_data.put("id", img.getId());
                    template_data.put("id_utente", 2);
                } //flusso css
                else if (tipo.equals("css")) {
                    Css css = null;
                    html = "show_css.ftl.html";
                    action_upload(request, info);
                    css = memorizzaCss(info, datalayer);
                    css.setDescrizione(SecurityLayer.stripSlashes(css.getDescrizione()));//potrebbe generare una nullpointerexception
                    css.setNome(SecurityLayer.stripSlashes(css.getNome()));
                    template_data.put("css", css);
                    template_data.put("identifier", css.getId());
                } //flusso slide
                else if (tipo.equals("slide")) {
                    Slide img = null;
                    html = "show_slide.ftl.html";
                    digest = action_upload(request, info);
                    img = memorizzaSlide(info, datalayer, digest);
                    /*visualizzazione della slide appena inserita*/
                    img.setDescrizione(SecurityLayer.stripSlashes(img.getDescrizione()));
                    img.setNome(SecurityLayer.stripSlashes(img.getNome()));
                    template_data.put("slide", img);
                    template_data.put("id", img.getId());
                }
                template_data.put("outline_tpl", "");
                TemplateResult tr = new TemplateResult(getServletContext());
                tr.activate(html, template_data, response);
            } catch (ErroreGrave ex) {
                Logger.getLogger(Upload.class.getName()).log(Level.SEVERE, null, ex);
                FailureResult res = new FailureResult(getServletContext());
                res.activate(ex.getMessage(), request, response);
            }
        } else {
            response.sendRedirect("Homepage.html");
        }
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /**
     * Handles the HTTP <code>GET</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try {
            processRequest(request, response);

        } catch (SQLException ex) {
            Logger.getLogger(Upload.class.getName()).log(Level.SEVERE, null, ex);
        } catch (Exception ex) {
            Logger.getLogger(Upload.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Handles the HTTP <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try {
            processRequest(request, response);

        } catch (SQLException ex) {
            Logger.getLogger(Upload.class.getName()).log(Level.SEVERE, null, ex);
        } catch (Exception ex) {
            Logger.getLogger(Upload.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>

}