/*
    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.WikiPage;
import org.apache.wiki.WikiSession;
import org.apache.wiki.api.core.Engine;
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 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( WikiPage.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 );
        }
    }

}


