/*
    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements.  See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership.  The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.
 */
package org.apache.wiki.attachment;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.log4j.Logger;
import org.apache.wiki.WikiContext;
import org.apache.wiki.WikiEngine;
import org.apache.wiki.WikiSession;
import org.apache.wiki.api.core.Attachment;
import org.apache.wiki.api.core.Engine;
import org.apache.wiki.api.core.Page;
import org.apache.wiki.api.core.Session;
import org.apache.wiki.api.exceptions.ProviderException;
import org.apache.wiki.api.exceptions.RedirectException;
import org.apache.wiki.api.exceptions.WikiException;
import org.apache.wiki.api.providers.WikiProvider;
import org.apache.wiki.auth.AuthorizationManager;
import org.apache.wiki.auth.permissions.PermissionFactory;
import org.apache.wiki.i18n.InternationalizationManager;
import org.apache.wiki.preferences.Preferences;
import org.apache.wiki.ui.progress.ProgressItem;
import org.apache.wiki.ui.progress.ProgressManager;
import org.apache.wiki.util.HttpUtil;
import org.apache.wiki.util.TextUtil;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketException;
import java.security.Permission;
import java.security.Principal;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;


/**
 *  This is the chief JSPWiki attachment management servlet.  It is used for
 *  both uploading new content and downloading old content.  It can handle
 *  most common cases, e.g. check for modifications and return 304's as necessary.
 *  <p>
 *  Authentication is done using JSPWiki's normal AAA framework.
 *  <p>
 *  This servlet is also capable of managing dynamically created attachments.
 *
 *
 *  @since 1.9.45.
 */
public class AttachmentServlet extends HttpServlet {

    private static final int BUFFER_SIZE = 8192;

    private static final long serialVersionUID = 3257282552187531320L;

    private Engine m_engine;
    private static final Logger log = Logger.getLogger( AttachmentServlet.class );

    private static final String HDR_VERSION     = "version";
    // private static final String HDR_NAME        = "page";

    /** Default expiry period is 1 day */
    protected static final long DEFAULT_EXPIRY = 1 * 24 * 60 * 60 * 1000;

    /**
     *  The maximum size that an attachment can be.
     */
    private int   m_maxSize = Integer.MAX_VALUE;

    /**
     *  List of attachment types which are allowed
     */

    private String[] m_allowedPatterns;

    private String[] m_forbiddenPatterns;

    //
    // Not static as DateFormat objects are not thread safe.
    // Used to handle the RFC date format = Sat, 13 Apr 2002 13:23:01 GMT
    //
    //private final DateFormat rfcDateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z");

    /**
     *  Initializes the servlet from Engine properties.
     */
    @Override
    public void init( final ServletConfig config ) throws ServletException {
        m_engine = WikiEngine.getInstance( config );
        final Properties props = m_engine.getWikiProperties();
        final String tmpDir = m_engine.getWorkDir() + File.separator + "attach-tmp";
        final String allowed = TextUtil.getStringProperty( props, AttachmentManager.PROP_ALLOWEDEXTENSIONS, null );
        m_maxSize = TextUtil.getIntegerProperty( props, AttachmentManager.PROP_MAXSIZE, Integer.MAX_VALUE );

        if( allowed != null && allowed.length() > 0 ) {
            m_allowedPatterns = allowed.toLowerCase().split( "\\s" );
        } else {
            m_allowedPatterns = new String[ 0 ];
        }

        final String forbidden = TextUtil.getStringProperty( props, AttachmentManager.PROP_FORBIDDENEXTENSIONS,null );
        if( forbidden != null && forbidden.length() > 0 ) {
            m_forbiddenPatterns = forbidden.toLowerCase().split("\\s");
        } else {
            m_forbiddenPatterns = new String[0];
        }

        final File f = new File( tmpDir );
        if( !f.exists() ) {
            f.mkdirs();
        } else if( !f.isDirectory() ) {
            log.fatal( "A file already exists where the temporary dir is supposed to be: " + tmpDir + ".  Please remove it." );
        }

        log.debug( "UploadServlet initialized. Using " + tmpDir + " for temporary storage." );
    }

    private boolean isTypeAllowed( String name )
    {
        if( name == null || name.length() == 0 ) return false;

        name = name.toLowerCase();

        for( int i = 0; i < m_forbiddenPatterns.length; i++ )
        {
            if( name.endsWith(m_forbiddenPatterns[i]) && m_forbiddenPatterns[i].length() > 0 )
                return false;
        }

        for( int i = 0; i < m_allowedPatterns.length; i++ )
        {
            if( name.endsWith(m_allowedPatterns[i]) && m_allowedPatterns[i].length() > 0 )
                return true;
        }

        return m_allowedPatterns.length == 0;
    }

    /**
     *  Implements the OPTIONS method.
     *
     *  @param req The servlet request
     *  @param res The servlet response
     */

    @Override
    protected void doOptions( final HttpServletRequest req, final HttpServletResponse res ) {
        res.setHeader( "Allow", "GET, PUT, POST, OPTIONS, PROPFIND, PROPPATCH, MOVE, COPY, DELETE");
        res.setStatus( HttpServletResponse.SC_OK );
    }

    /**
     *  Serves a GET with two parameters: 'wikiname' specifying the wikiname
     *  of the attachment, 'version' specifying the version indicator.
     *
     */
    // FIXME: Messages would need to be localized somehow.
    @Override
    public void doGet( final HttpServletRequest  req, final HttpServletResponse res ) throws IOException {
        final WikiContext context = new WikiContext( m_engine, req, WikiContext.ATTACH );
        final AttachmentManager mgr = m_engine.getManager( AttachmentManager.class );
        final AuthorizationManager authmgr = m_engine.getManager( AuthorizationManager.class );
        final String version = req.getParameter( HDR_VERSION );
        final String nextPage = req.getParameter( "nextpage" );
        final String page = context.getPage().getName();
        int ver = WikiProvider.LATEST_VERSION;

        if( page == null ) {
            log.info( "Invalid attachment name." );
            res.sendError( HttpServletResponse.SC_BAD_REQUEST );
            return;
        }

        try( final OutputStream out = res.getOutputStream() ) {
            log.debug("Attempting to download att "+page+", version "+version);
            if( version != null ) {
                ver = Integer.parseInt( version );
            }

            final Attachment att = mgr.getAttachmentInfo( page, ver );
            if( att != null ) {
                //
                //  Check if the user has permission for this attachment
                //

                final Permission permission = PermissionFactory.getPagePermission( att, "view" );
                if( !authmgr.checkPermission( context.getWikiSession(), permission ) ) {
                    log.debug("User does not have permission for this");
                    res.sendError( HttpServletResponse.SC_FORBIDDEN );
                    return;
                }

                //
                //  Check if the client already has a version of this attachment.
                //
                if( HttpUtil.checkFor304( req, att.getName(), att.getLastModified() ) ) {
                    log.debug( "Client has latest version already, sending 304..." );
                    res.sendError( HttpServletResponse.SC_NOT_MODIFIED );
                    return;
                }

                final String mimetype = getMimeType( context, att.getFileName() );
                res.setContentType( mimetype );

                //
                //  We use 'inline' instead of 'attachment' so that user agents
                //  can try to automatically open the file.
                //
                res.addHeader( "Content-Disposition", "inline; filename=\"" + att.getFileName() + "\";" );
                res.addDateHeader("Last-Modified",att.getLastModified().getTime());

                if( !att.isCacheable() ) {
                    res.addHeader( "Pragma", "no-cache" );
                    res.addHeader( "Cache-control", "no-cache" );
                }

                // If a size is provided by the provider, report it.
                if( att.getSize() >= 0 ) {
                    // log.info("size:"+att.getSize());
                    res.setContentLength( (int)att.getSize() );
                }

                try( final InputStream  in = mgr.getAttachmentStream( context, att ) ) {
                    int read;
                    final byte[] buffer = new byte[ BUFFER_SIZE ];

                    while( ( read = in.read( buffer ) ) > -1 ) {
                        out.write( buffer, 0, read );
                    }
                }

                if( log.isDebugEnabled() ) {
                    log.debug( "Attachment "+att.getFileName()+" sent to "+req.getRemoteUser()+" on "+HttpUtil.getRemoteAddress(req) );
                }
                if( nextPage != null ) {
                    res.sendRedirect(
                        validateNextPage(
                            TextUtil.urlEncodeUTF8(nextPage),
                            m_engine.getURL( WikiContext.ERROR, "", null )
                        )
                    );
                }

            } else {
                final String msg = "Attachment '" + page + "', version " + ver + " does not exist.";
                log.info( msg );
                res.sendError( HttpServletResponse.SC_NOT_FOUND, msg );
            }
        } catch( final ProviderException pe ) {
            log.debug("Provider failed while reading", pe);
            //
            //  This might fail, if the response is already committed.  So in that
            //  case we just log it.
            //
            sendError( res, "Provider error: "+ pe.getMessage() );
        } catch( final NumberFormatException nfe ) {
            log.warn( "Invalid version number: " + version );
            res.sendError( HttpServletResponse.SC_BAD_REQUEST, "Invalid version number" );
        } catch( final SocketException se ) {
            //
            //  These are very common in download situations due to aggressive
            //  clients.  No need to try and send an error.
            //
            log.debug( "I/O exception during download", se );
        } catch( final IOException ioe ) {
            //
            //  Client dropped the connection or something else happened.
            //  We don't know where the error came from, so we'll at least
            //  try to send an error and catch it quietly if it doesn't quite work.
            //
            log.debug( "I/O exception during download", ioe );
            sendError( res, "Error: " + ioe.getMessage() );
        }
    }

    void sendError( final HttpServletResponse res, final String message ) throws IOException {
        try {
            res.sendError( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message );
        } catch( final IllegalStateException e ) {
            // ignore
        }
    }

    /**
     *  Returns the mime type for this particular file.  Case does not matter.
     *
     * @param ctx WikiContext; required to access the ServletContext of the request.
     * @param fileName The name to check for.
     * @return A valid mime type, or application/binary, if not recognized
     */
    private static String getMimeType( final WikiContext ctx, final String fileName ) {
        String mimetype = null;

        final HttpServletRequest req = ctx.getHttpRequest();
        if( req != null ) {
            final ServletContext s = req.getSession().getServletContext();

            if( s != null ) {
                mimetype = s.getMimeType( fileName.toLowerCase() );
            }
        }

        if( mimetype == null ) {
            mimetype = "application/binary";
        }

        return mimetype;
    }


    /**
     * Grabs mime/multipart data and stores it into the temporary area.
     * Uses other parameters to determine which name to store as.
     *
     * <p>The input to this servlet is generated by an HTML FORM with
     * two parts. The first, named 'page', is the WikiName identifier
     * for the parent file. The second, named 'content', is the binary
     * content of the file.
     *
     */
    @Override
    public void doPost( final HttpServletRequest req, final HttpServletResponse res ) throws IOException {
        try {
            final String nextPage = upload( req );
            req.getSession().removeAttribute("msg");
            res.sendRedirect( nextPage );
        } catch( final RedirectException e ) {
            final Session session = WikiSession.getWikiSession( m_engine, req );
            session.addMessage( e.getMessage() );

            req.getSession().setAttribute("msg", e.getMessage());
            res.sendRedirect( e.getRedirect() );
        }
    }

    /**
     *  Validates the next page to be on the same server as this webapp.
     *  Fixes [JSPWIKI-46].
     */
    private String validateNextPage( String nextPage, final String errorPage ) {
        if( nextPage.contains( "://" ) ) {
            // It's an absolute link, so unless it starts with our address, we'll log an error.
            if( !nextPage.startsWith( m_engine.getBaseURL() ) ) {
                log.warn("Detected phishing attempt by redirecting to an unsecure location: "+nextPage);
                nextPage = errorPage;
            }
        }

        return nextPage;
    }

    /**
     *  Uploads a specific mime multipart input set, intercepts exceptions.
     *
     *  @param req The servlet request
     *  @return The page to which we should go next.
     *  @throws RedirectException If there's an error and a redirection is needed
     *  @throws IOException If upload fails
     */
    protected String upload( final HttpServletRequest req ) throws RedirectException, IOException {
        final String msg;
        final String attName = "(unknown)";
        final String errorPage = m_engine.getURL( WikiContext.ERROR, "", null ); // If something bad happened, Upload should be able to take care of most stuff
        String nextPage = errorPage;
        final String progressId = req.getParameter( "progressid" );

        // Check that we have a file upload request
        if( !ServletFileUpload.isMultipartContent(req) ) {
            throw new RedirectException( "Not a file upload", errorPage );
        }

        try {
            final FileItemFactory factory = new DiskFileItemFactory();

            // Create the context _before_ Multipart operations, otherwise strict servlet containers may fail when setting encoding.
            final WikiContext context = new WikiContext( m_engine, req, WikiContext.ATTACH );
            final UploadListener pl = new UploadListener();

            m_engine.getManager( ProgressManager.class ).startProgress( pl, progressId );

            final ServletFileUpload upload = new ServletFileUpload( factory );
            upload.setHeaderEncoding( "UTF-8" );
            if( !context.hasAdminPermissions() ) {
                upload.setFileSizeMax( m_maxSize );
            }
            upload.setProgressListener( pl );
            final List<FileItem> items = upload.parseRequest( req );

            String   wikipage   = null;
            String   changeNote = null;
            //FileItem actualFile = null;
            final List<FileItem> fileItems = new ArrayList<>();

            for( final FileItem item : items ) {
                if( item.isFormField() ) {
                    switch( item.getFieldName() ) {
                    case "page":
                        // FIXME: Kludge alert.  We must end up with the parent page name, if this is an upload of a new revision
                        wikipage = item.getString( "UTF-8" );
                        final int x = wikipage.indexOf( "/" );
                        if( x != -1 ) {
                            wikipage = wikipage.substring( 0, x );
                        }
                        break;
                    case "changenote":
                        changeNote = item.getString( "UTF-8" );
                        if( changeNote != null ) {
                            changeNote = TextUtil.replaceEntities( changeNote );
                        }
                        break;
                    case "nextpage":
                        nextPage = validateNextPage( item.getString( "UTF-8" ), errorPage );
                        break;
                    }
                } else {
                    fileItems.add( item );
                }
            }

            if( fileItems.size() == 0 ) {
                throw new RedirectException( "Broken file upload", errorPage );

            } else {
                for( final FileItem actualFile : fileItems ) {
                    final String filename = actualFile.getName();
                    final long   fileSize = actualFile.getSize();
                    try( final InputStream in  = actualFile.getInputStream() ) {
                        executeUpload( context, in, filename, nextPage, wikipage, changeNote, fileSize );
                    }
                }
            }

        } catch( final ProviderException e ) {
            msg = "Upload failed because the provider failed: "+e.getMessage();
            log.warn( msg + " (attachment: " + attName + ")", e );

            throw new IOException( msg );
        } catch( final IOException e ) {
            // Show the submit page again, but with a bit more intimidating output.
            msg = "Upload failure: " + e.getMessage();
            log.warn( msg + " (attachment: " + attName + ")", e );

            throw e;
        } catch( final FileUploadException e ) {
            // Show the submit page again, but with a bit more intimidating output.
            msg = "Upload failure: " + e.getMessage();
            log.warn( msg + " (attachment: " + attName + ")", e );

            throw new IOException( msg, e );
        } finally {
            m_engine.getManager( ProgressManager.class ).stopProgress( progressId );
            // FIXME: In case of exceptions should absolutely remove the uploaded file.
        }

        return nextPage;
    }

    /**
     *
     * @param context the wiki context
     * @param data the input stream data
     * @param filename the name of the file to upload
     * @param errorPage the place to which you want to get a redirection
     * @param parentPage the page to which the file should be attached
     * @param changenote The change note
     * @param contentLength The content length
     * @return <code>true</code> if upload results in the creation of a new page;
     * <code>false</code> otherwise
     * @throws RedirectException If the content needs to be redirected
     * @throws IOException       If there is a problem in the upload.
     * @throws ProviderException If there is a problem in the backend.
     */
    protected boolean executeUpload( final WikiContext context, final InputStream data,
                                     String filename, final String errorPage,
                                     final String parentPage, final String changenote,
                                     final long contentLength )
            throws RedirectException, IOException, ProviderException {
        boolean created = false;

        try {
            filename = AttachmentManager.validateFileName( filename );
        } catch( final WikiException e ) {
            // this is a kludge, the exception that is caught here contains the i18n key
            // here we have the context available, so we can internationalize it properly :
            throw new RedirectException (Preferences.getBundle( context, InternationalizationManager.CORE_BUNDLE )
                    .getString( e.getMessage() ), errorPage );
        }

        //
        //  FIXME: This has the unfortunate side effect that it will receive the
        //  contents.  But we can't figure out the page to redirect to
        //  before we receive the file, due to the stupid constructor of MultipartRequest.
        //

        if( !context.hasAdminPermissions() ) {
            if( contentLength > m_maxSize ) {
                // FIXME: Does not delete the received files.
                throw new RedirectException( "File exceeds maximum size ("+m_maxSize+" bytes)", errorPage );
            }

            if( !isTypeAllowed(filename) ) {
                throw new RedirectException( "Files of this type may not be uploaded to this wiki", errorPage );
            }
        }

        final Principal user    = context.getCurrentUser();
        final AttachmentManager mgr = m_engine.getManager( AttachmentManager.class );

        log.debug("file="+filename);

        if( data == null ) {
            log.error("File could not be opened.");
            throw new RedirectException("File could not be opened.", errorPage);
        }

        //  Check whether we already have this kind of a page. If the "page" parameter already defines an attachment
        //  name for an update, then we just use that file. Otherwise we create a new attachment, and use the
        //  filename given.  Incidentally, this will also mean that if the user uploads a file with the exact
        //  same name than some other previous attachment, then that attachment gains a new version.
        Attachment att = mgr.getAttachmentInfo( context.getPage().getName() );
        if( att == null ) {
            att = new org.apache.wiki.attachment.Attachment( m_engine, parentPage, filename );
            created = true;
        }
        att.setSize( contentLength );

        //  Check if we're allowed to do this?
        final Permission permission = PermissionFactory.getPagePermission( att, "upload" );
        if( m_engine.getManager( AuthorizationManager.class ).checkPermission( context.getWikiSession(), permission ) ) {
            if( user != null ) {
                att.setAuthor( user.getName() );
            }

            if( changenote != null && changenote.length() > 0 ) {
                att.setAttribute( Page.CHANGENOTE, changenote );
            }

            try {
                m_engine.getManager( AttachmentManager.class ).storeAttachment( att, data );
            } catch( final ProviderException pe ) {
                // this is a kludge, the exception that is caught here contains the i18n key
                // here we have the context available, so we can internationalize it properly :
                throw new ProviderException( Preferences.getBundle( context, InternationalizationManager.CORE_BUNDLE ).getString( pe.getMessage() ) );
            }

            log.info( "User " + user + " uploaded attachment to " + parentPage + " called "+filename+", size " + att.getSize() );
        } else {
            throw new RedirectException( "No permission to upload a file", errorPage );
        }

        return created;
    }

    /**
     *  Provides tracking for upload progress.
     *
     */
    private static class UploadListener extends ProgressItem implements ProgressListener {
        public long m_currentBytes;
        public long m_totalBytes;

        @Override
        public void update( final long recvdBytes, final long totalBytes, final int item) {
            m_currentBytes = recvdBytes;
            m_totalBytes   = totalBytes;
        }

        @Override
        public int getProgress() {
            return ( int )( ( ( float )m_currentBytes / m_totalBytes ) * 100 + 0.5 );
        }
    }

}


