//
//  ========================================================================
//  Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;

import javax.servlet.MultipartConfigElement;
import javax.servlet.http.Part;

import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;



/**
 * MultiPartInputStream
 *
 * Handle a MultiPart Mime input stream, breaking it up on the boundary into files and strings.
 */
public class MultiPartInputStreamParser
{
    private static final Logger LOG = Log.getLogger(MultiPartInputStreamParser.class);
    public static final MultipartConfigElement  __DEFAULT_MULTIPART_CONFIG = new MultipartConfigElement(System.getProperty("java.io.tmpdir"));
    protected InputStream _in;
    protected MultipartConfigElement _config;
    protected String _contentType;
    protected MultiMap<Part> _parts;
    protected File _tmpDir;
    protected File _contextTmpDir;
    protected boolean _deleteOnExit;



    public class MultiPart implements Part
    {
        protected String _name;
        protected String _filename;
        protected File _file;
        protected OutputStream _out;
        protected ByteArrayOutputStream2 _bout;
        protected String _contentType;
        protected MultiMap<String> _headers;
        protected long _size = 0;
        protected boolean _temporary = true;

        public MultiPart (String name, String filename)
        throws IOException
        {
            _name = name;
            _filename = filename;
        }

        protected void setContentType (String contentType)
        {
            _contentType = contentType;
        }


        protected void open()
        throws IOException
        {
            //Write to a buffer in memory until we discover we've exceed the
            //MultipartConfig fileSizeThreshold
            _out = _bout= new ByteArrayOutputStream2();
        }

        protected void close()
        throws IOException
        {
            _out.close();
        }


        protected void write (int b)
        throws IOException
        {
            if (MultiPartInputStreamParser.this._config.getMaxFileSize() > 0 && _size + 1 > MultiPartInputStreamParser.this._config.getMaxFileSize())
                throw new IllegalStateException ("Multipart Mime part "+_name+" exceeds max filesize");

            if (MultiPartInputStreamParser.this._config.getFileSizeThreshold() > 0 && _size + 1 > MultiPartInputStreamParser.this._config.getFileSizeThreshold() && _file==null)
                createFile();

            _out.write(b);
            _size ++;
        }

        protected void write (byte[] bytes, int offset, int length)
        throws IOException
        {
            if (MultiPartInputStreamParser.this._config.getMaxFileSize() > 0 && _size + length > MultiPartInputStreamParser.this._config.getMaxFileSize())
                throw new IllegalStateException ("Multipart Mime part "+_name+" exceeds max filesize");

            if (MultiPartInputStreamParser.this._config.getFileSizeThreshold() > 0 && _size + length > MultiPartInputStreamParser.this._config.getFileSizeThreshold() && _file==null)
                createFile();

            _out.write(bytes, offset, length);
            _size += length;
        }

        protected void createFile ()
        throws IOException
        {
            /* Some statics just to make the code below easier to understand
             * This get optimized away during the compile anyway */
            final boolean USER = true;
            final boolean WORLD = false;
            
            _file = File.createTempFile("MultiPart", "", MultiPartInputStreamParser.this._tmpDir);
            _file.setReadable(false,WORLD); // (reset) disable it for everyone first
            _file.setReadable(true,USER); // enable for user only

            if (_deleteOnExit)
                _file.deleteOnExit();
            FileOutputStream fos = new FileOutputStream(_file);
            BufferedOutputStream bos = new BufferedOutputStream(fos);

            if (_size > 0 && _out != null)
            {
                //already written some bytes, so need to copy them into the file
                _out.flush();
                _bout.writeTo(bos);
                _out.close();
                _bout = null;
            }
            _out = bos;
        }



        protected void setHeaders(MultiMap<String> headers)
        {
            _headers = headers;
        }

        /**
         * @see javax.servlet.http.Part#getContentType()
         */
        public String getContentType()
        {
            return _contentType;
        }

        /**
         * @see javax.servlet.http.Part#getHeader(java.lang.String)
         */
        public String getHeader(String name)
        {
            if (name == null)
                return null;
            return _headers.getValue(name.toLowerCase(Locale.ENGLISH), 0);
        }

        /**
         * @see javax.servlet.http.Part#getHeaderNames()
         */
        public Collection<String> getHeaderNames()
        {
            return _headers.keySet();
        }

        /**
         * @see javax.servlet.http.Part#getHeaders(java.lang.String)
         */
        public Collection<String> getHeaders(String name)
        {
           return _headers.getValues(name);
        }

        /**
         * @see javax.servlet.http.Part#getInputStream()
         */
        public InputStream getInputStream() throws IOException
        {
           if (_file != null)
           {
               //written to a file, whether temporary or not
               return new BufferedInputStream (new FileInputStream(_file));
           }
           else
           {
               //part content is in memory
               return new ByteArrayInputStream(_bout.getBuf(),0,_bout.size());
           }
        }


        /**
         * @see javax.servlet.http.Part#getSubmittedFileName()
         */
        @Override
        public String getSubmittedFileName()
        {
            return getContentDispositionFilename();
        }

        public byte[] getBytes()
        {
            if (_bout!=null)
                return _bout.toByteArray();
            return null;
        }

        /**
         * @see javax.servlet.http.Part#getName()
         */
        public String getName()
        {
           return _name;
        }

        /**
         * @see javax.servlet.http.Part#getSize()
         */
        public long getSize()
        {
            return _size;
        }

        /**
         * @see javax.servlet.http.Part#write(java.lang.String)
         */
        public void write(String fileName) throws IOException
        {
            if (_file == null)
            {
                _temporary = false;

                //part data is only in the ByteArrayOutputStream and never been written to disk
                _file = new File (_tmpDir, fileName);

                BufferedOutputStream bos = null;
                try
                {
                    bos = new BufferedOutputStream(new FileOutputStream(_file));
                    _bout.writeTo(bos);
                    bos.flush();
                }
                finally
                {
                    if (bos != null)
                        bos.close();
                    _bout = null;
                }
            }
            else
            {
                //the part data is already written to a temporary file, just rename it
                _temporary = false;

                Path src = _file.toPath();
                Path target = src.resolveSibling(fileName);
                Files.move(src, target, StandardCopyOption.REPLACE_EXISTING);
                _file = target.toFile();
            }
        }

        /**
         * Remove the file, whether or not Part.write() was called on it
         * (ie no longer temporary)
         * @see javax.servlet.http.Part#delete()
         */
        public void delete() throws IOException
        {
            if (_file != null && _file.exists())
                _file.delete();
        }

        /**
         * Only remove tmp files.
         *
         * @throws IOException if unable to delete the file
         */
        public void cleanUp() throws IOException
        {
            if (_temporary && _file != null && _file.exists())
                _file.delete();
        }


        /**
         * Get the file
         * @return the file, if any, the data has been written to.
         */
        public File getFile ()
        {
            return _file;
        }


        /**
         * Get the filename from the content-disposition.
         * @return null or the filename
         */
        public String getContentDispositionFilename ()
        {
            return _filename;
        }
    }




    /**
     * @param in Request input stream
     * @param contentType Content-Type header
     * @param config MultipartConfigElement
     * @param contextTmpDir javax.servlet.context.tempdir
     */
    public MultiPartInputStreamParser (InputStream in, String contentType, MultipartConfigElement config, File contextTmpDir)
    {
        _in = new ReadLineInputStream(in);
       _contentType = contentType;
       _config = config;
       _contextTmpDir = contextTmpDir;
       if (_contextTmpDir == null)
           _contextTmpDir = new File (System.getProperty("java.io.tmpdir"));

       if (_config == null)
           _config = new MultipartConfigElement(_contextTmpDir.getAbsolutePath());
    }

    /**
     * Get the already parsed parts.
     * @return the parts that were parsed
     */
    public Collection<Part> getParsedParts()
    {
        if (_parts == null)
            return Collections.emptyList();

        Collection<List<Part>> values = _parts.values();
        List<Part> parts = new ArrayList<>();
        for (List<Part> o: values)
        {
            List<Part> asList = LazyList.getList(o, false);
            parts.addAll(asList);
        }
        return parts;
    }

    /**
     * Delete any tmp storage for parts, and clear out the parts list.
     *
     * @throws MultiException if unable to delete the parts
     */
    public void deleteParts ()
    throws MultiException
    {
        Collection<Part> parts = getParsedParts();
        MultiException err = new MultiException();
        for (Part p:parts)
        {
            try
            {
                ((MultiPartInputStreamParser.MultiPart)p).cleanUp();
            }
            catch(Exception e)
            {
                err.add(e);
            }
        }
        _parts.clear();

        err.ifExceptionThrowMulti();
    }


    /**
     * Parse, if necessary, the multipart data and return the list of Parts.
     *
     * @return the parts
     * @throws IOException if unable to get the parts
     */
    public Collection<Part> getParts()
    throws IOException
    {
        parse();
        Collection<List<Part>> values = _parts.values();
        List<Part> parts = new ArrayList<>();
        for (List<Part> o: values)
        {
            List<Part> asList = LazyList.getList(o, false);
            parts.addAll(asList);
        }
        return parts;
    }


    /**
     * Get the named Part.
     *
     * @param name the part name
     * @return the parts
     * @throws IOException if unable to get the part
     */
    public Part getPart(String name)
    throws IOException
    {
        parse();
        return _parts.getValue(name, 0);
    }


    /**
     * Parse, if necessary, the multipart stream.
     *
     * @throws IOException if unable to parse
     */
    protected void parse ()
    throws IOException
    {
        //have we already parsed the input?
        if (_parts != null)
            return;

        //initialize
        long total = 0; //keep running total of size of bytes read from input and throw an exception if exceeds MultipartConfigElement._maxRequestSize
        _parts = new MultiMap<>();

        //if its not a multipart request, don't parse it
        if (_contentType == null || !_contentType.startsWith("multipart/form-data"))
            return;

        //sort out the location to which to write the files

        if (_config.getLocation() == null)
            _tmpDir = _contextTmpDir;
        else if ("".equals(_config.getLocation()))
            _tmpDir = _contextTmpDir;
        else
        {
            File f = new File (_config.getLocation());
            if (f.isAbsolute())
                _tmpDir = f;
            else
                _tmpDir = new File (_contextTmpDir, _config.getLocation());
        }

        if (!_tmpDir.exists())
            _tmpDir.mkdirs();

        String contentTypeBoundary = "";
        int bstart = _contentType.indexOf("boundary=");
        if (bstart >= 0)
        {
            int bend = _contentType.indexOf(";", bstart);
            bend = (bend < 0? _contentType.length(): bend);
            contentTypeBoundary = QuotedStringTokenizer.unquote(value(_contentType.substring(bstart,bend)).trim());
        }

        String boundary="--"+contentTypeBoundary;
        String lastBoundary=boundary+"--";
        byte[] byteBoundary=lastBoundary.getBytes(StandardCharsets.ISO_8859_1);

        // Get first boundary
        String line = null;
        try
        {
            line=((ReadLineInputStream)_in).readLine();
        }
        catch (IOException e)
        {
            LOG.warn("Badly formatted multipart request");
            throw e;
        }

        if (line == null)
            throw new IOException("Missing content for multipart request");

        boolean badFormatLogged = false;
        line=line.trim();
        while (line != null && !line.equals(boundary) && !line.equals(lastBoundary))
        {
            if (!badFormatLogged)
            {
                LOG.warn("Badly formatted multipart request");
                badFormatLogged = true;
            }
            line=((ReadLineInputStream)_in).readLine();
            line=(line==null?line:line.trim());
        }

        if (line == null || line.length() == 0)
            throw new IOException("Missing initial multi part boundary");

        // Empty multipart.
        if (line.equals(lastBoundary))
            return;

        // Read each part
        boolean lastPart=false;

        outer:while(!lastPart)
        {
            String contentDisposition=null;
            String contentType=null;
            String contentTransferEncoding=null;

            MultiMap<String> headers = new MultiMap<>();
            while(true)
            {
                line=((ReadLineInputStream)_in).readLine();

                //No more input
                if(line==null)
                    break outer;

                //end of headers:
                if("".equals(line))
                    break;

                total += line.length();
                if (_config.getMaxRequestSize() > 0 && total > _config.getMaxRequestSize())
                    throw new IllegalStateException ("Request exceeds maxRequestSize ("+_config.getMaxRequestSize()+")");

                //get content-disposition and content-type
                int c=line.indexOf(':',0);
                if(c>0)
                {
                    String key=line.substring(0,c).trim().toLowerCase(Locale.ENGLISH);
                    String value=line.substring(c+1,line.length()).trim();
                    headers.put(key, value);
                    if (key.equalsIgnoreCase("content-disposition"))
                        contentDisposition=value;
                    if (key.equalsIgnoreCase("content-type"))
                        contentType = value;
                    if(key.equals("content-transfer-encoding"))
                        contentTransferEncoding=value;
                }
            }

            // Extract content-disposition
            boolean form_data=false;
            if(contentDisposition==null)
            {
                throw new IOException("Missing content-disposition");
            }

            QuotedStringTokenizer tok=new QuotedStringTokenizer(contentDisposition,";", false, true);
            String name=null;
            String filename=null;
            while(tok.hasMoreTokens())
            {
                String t=tok.nextToken().trim();
                String tl=t.toLowerCase(Locale.ENGLISH);
                if(t.startsWith("form-data"))
                    form_data=true;
                else if(tl.startsWith("name="))
                    name=value(t);
                else if(tl.startsWith("filename="))
                    filename=filenameValue(t);
            }

            // Check disposition
            if(!form_data)
            {
                continue;
            }
            //It is valid for reset and submit buttons to have an empty name.
            //If no name is supplied, the browser skips sending the info for that field.
            //However, if you supply the empty string as the name, the browser sends the
            //field, with name as the empty string. So, only continue this loop if we
            //have not yet seen a name field.
            if(name==null)
            {
                continue;
            }

            //Have a new Part
            MultiPart part = new MultiPart(name, filename);
            part.setHeaders(headers);
            part.setContentType(contentType);
            _parts.add(name, part);
            part.open();

            InputStream partInput = null;
            if ("base64".equalsIgnoreCase(contentTransferEncoding))
            {
                partInput = new Base64InputStream((ReadLineInputStream)_in);
            }
            else if ("quoted-printable".equalsIgnoreCase(contentTransferEncoding))
            {
                partInput = new FilterInputStream(_in)
                {
                    @Override
                    public int read() throws IOException
                    {
                        int c = in.read();
                        if (c >= 0 && c == '=')
                        {
                            int hi = in.read();
                            int lo = in.read();
                            if (hi < 0 || lo < 0)
                            {
                                throw new IOException("Unexpected end to quoted-printable byte");
                            }
                            char[] chars = new char[] { (char)hi, (char)lo };
                            c = Integer.parseInt(new String(chars),16);
                        }
                        return c;
                    }
                };
            }
            else
                partInput = _in;


            try
            {
                int state=-2;
                int c;
                boolean cr=false;
                boolean lf=false;

                // loop for all lines
                while(true)
                {
                    int b=0;
                    while((c=(state!=-2)?state:partInput.read())!=-1)
                    {
                        total ++;
                        if (_config.getMaxRequestSize() > 0 && total > _config.getMaxRequestSize())
                            throw new IllegalStateException("Request exceeds maxRequestSize ("+_config.getMaxRequestSize()+")");

                        state=-2;

                        // look for CR and/or LF
                        if(c==13||c==10)
                        {
                            if(c==13)
                            {
                                partInput.mark(1);
                                int tmp=partInput.read();
                                if (tmp!=10)
                                    partInput.reset();
                                else
                                    state=tmp;
                            }
                            break;
                        }

                        // Look for boundary
                        if(b>=0&&b<byteBoundary.length&&c==byteBoundary[b])
                        {
                            b++;
                        }
                        else
                        {
                            // Got a character not part of the boundary, so we don't have the boundary marker.
                            // Write out as many chars as we matched, then the char we're looking at.
                            if(cr)
                                part.write(13);

                            if(lf)
                                part.write(10);

                            cr=lf=false;
                            if(b>0)
                                part.write(byteBoundary,0,b);

                            b=-1;
                            part.write(c);
                        }
                    }

                    // Check for incomplete boundary match, writing out the chars we matched along the way
                    if((b>0&&b<byteBoundary.length-2)||(b==byteBoundary.length-1))
                    {
                        if(cr)
                            part.write(13);

                        if(lf)
                            part.write(10);

                        cr=lf=false;
                        part.write(byteBoundary,0,b);
                        b=-1;
                    }

                    // Boundary match. If we've run out of input or we matched the entire final boundary marker, then this is the last part.
                    if(b>0||c==-1)
                    {

                        if(b==byteBoundary.length)
                            lastPart=true;
                        if(state==10)
                            state=-2;
                        break;
                    }

                    // handle CR LF
                    if(cr)
                        part.write(13);

                    if(lf)
                        part.write(10);

                    cr=(c==13);
                    lf=(c==10||state==10);
                    if(state==10)
                        state=-2;
                }
            }
            finally
            {

                part.close();
            }
        }
        if (!lastPart)
            throw new IOException("Incomplete parts");
    }

    public void setDeleteOnExit(boolean deleteOnExit)
    {
        _deleteOnExit = deleteOnExit;
    }


    public boolean isDeleteOnExit()
    {
        return _deleteOnExit;
    }


    /* ------------------------------------------------------------ */
    private String value(String nameEqualsValue)
    {
        int idx = nameEqualsValue.indexOf('=');
        String value = nameEqualsValue.substring(idx+1).trim();
        return QuotedStringTokenizer.unquoteOnly(value);
    }


    /* ------------------------------------------------------------ */
    private String filenameValue(String nameEqualsValue)
    {
        int idx = nameEqualsValue.indexOf('=');
        String value = nameEqualsValue.substring(idx+1).trim();

        if (value.matches(".??[a-z,A-Z]\\:\\\\[^\\\\].*"))
        {
            //incorrectly escaped IE filenames that have the whole path
            //we just strip any leading & trailing quotes and leave it as is
            char first=value.charAt(0);
            if (first=='"' || first=='\'')
                value=value.substring(1);
            char last=value.charAt(value.length()-1);
            if (last=='"' || last=='\'')
                value = value.substring(0,value.length()-1);

            return value;
        }
        else
            //unquote the string, but allow any backslashes that don't
            //form a valid escape sequence to remain as many browsers
            //even on *nix systems will not escape a filename containing
            //backslashes
            return QuotedStringTokenizer.unquoteOnly(value, true);
    }



    private static class Base64InputStream extends InputStream
    {
        ReadLineInputStream _in;
        String _line;
        byte[] _buffer;
        int _pos;


        public Base64InputStream(ReadLineInputStream rlis)
        {
            _in = rlis;
        }

        @Override
        public int read() throws IOException
        {
            if (_buffer==null || _pos>= _buffer.length)
            {
                //Any CR and LF will be consumed by the readLine() call.
                //We need to put them back into the bytes returned from this
                //method because the parsing of the multipart content uses them
                //as markers to determine when we've reached the end of a part.
                _line = _in.readLine();
                if (_line==null)
                    return -1;  //nothing left
                if (_line.startsWith("--"))
                    _buffer=(_line+"\r\n").getBytes(); //boundary marking end of part
                else if (_line.length()==0)
                    _buffer="\r\n".getBytes(); //blank line
                else
                {
                    ByteArrayOutputStream baos = new ByteArrayOutputStream((4*_line.length()/3)+2);
                    B64Code.decode(_line, baos);
                    baos.write(13);
                    baos.write(10);
                    _buffer = baos.toByteArray();
                }

                _pos=0;
            }

            return _buffer[_pos++];
        }
    }
}
