/*
 * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package com.sun.ejte.ccl.webrunner.webtest;

import java.util.*;

/**
 *
* MIME is an internet standard for communicating multimedia content over e-mail systems.MimeHeader extends HashTable so that it can store key value pairs.
 *
* @author       Deepa Singh(deepa.singh@sun.com)
 *Company: Sun Microsystems Inc
 *@see com.sun.ejte.ccl.webrunner.proxy.MimeHeader
*
*/

public class MimeHeader extends Hashtable
{
    private String RequestHeader=new String();
    private  boolean requestGET=false;
    private boolean requestPOST=false;
    private boolean cookieSet=false;
    private String postdata=new String();


    /**
     * Takes a String as a parameter and parses it.Takes a raw MIME-formatted String and enter its key/value pairs into a given instance of MimeHeader.Uses
     *StringTokenizer to split the input data into individual lines marked by CRLF(\r\n) sequence.
     *It differs in it's implementation of parse() from com.sun.ejte.ccl.webrunner.proxy.MimeHeader.parse() in that it checks the request type.
     *If it is POST then stores the post data to be sent to external web server.
     * @author       Deepa Singh(deepa.singh@sun.com)
     * @return       void
     * @param                data        The string to be parsed
     **@see com.sun.ejte.ccl.webrunner.proxy.MimeHeader
    */
    void parse(String data)
    {
        StringTokenizer st=new StringTokenizer(data,"\r\n");
        while(st.hasMoreTokens())
        {
            String s=st.nextToken();

            //first check for Cookie as they are contained in script file.This needs to be stripped from the new request string sent to server
            if(s.startsWith("Cookie"))
            {
                cookieSet=true;
            }
            else
                cookieSet=false;

            //These lines are HTTP headers.Do not contain request.
            if(!s.startsWith("GET") && (!s.startsWith("POST")))
            {
                //System.out.println("_from_mime_header"+s);
                if((s.indexOf(':'))!=-1)
                {
                    int colon=s.indexOf(':');
                    String key=s.substring(0,colon);
                    String val=s.substring(colon+2);
                    put(key,val);
                }
                //This is POST data after request and headers.Header has ended and after CRLF Content starts.
                //\r\n\r\n is CRLF.Header lines are separated by \r\n
                else
                {
                    //System.out.println("\n%%%%%%POST DATA%%%%%%");
                    postdata=s;
                    postdata.trim();
                    System.out.println(postdata);
                }
            }
            //This is the first line of HTTP request
            else
            {
                RequestHeader=s;
                if((RequestHeader.indexOf("GET"))!=-1)
                    requestGET=true;
                else if((RequestHeader.indexOf("POST"))!=-1)
                    requestPOST=true;
            }
        }
    }

        MimeHeader(){}
        public boolean ifGETRequest()
        {
            return this.requestGET;
        }
        public boolean ifPOSTRequest()
        {
            return this.requestPOST;
        }
        public String getRequestHeader()
        {
            return this.RequestHeader;
        }
        MimeHeader(String d)
        {
                parse(d);
        }

        public String toString()
        {
                String ret="";
                Enumeration e=keys();
                while(e.hasMoreElements())
                {
                String key=(String)e.nextElement();
                String val=(String)get(key);
                ret+=key + ": " + val + "\r\n";
                }
        return ret;
        }

        public String getPostData()
        {
                return postdata.trim();

        }



        /**
        *To remove the discrepancy in MIME specification for "Content-Type" and "content-type" and "Content-Length" to "content-length"
         *To avoid problems, all incoming and outgoing MimeHeader keys are converted to canonical form.
        * @author       Deepa Singh(deepa.singh@sun.com)
        * @return       String
        * @param                ms        String to be operated upon
        */
        private String fix(String ms)
        {
        char chars[]=ms.toLowerCase().toCharArray();
        boolean upcaseNext=true;
        for(int i=0;i<chars.length-1;i++)
        {
                char ch=chars[i];
                if(upcaseNext && 'a' <=ch && ch <='z')
                {
                        chars[i]=(char)(ch-('a'-'A'));
                }
                upcaseNext=ch=='-';
        }
        return new String(chars);
        }


        /*
        * @author       Deepa Singh(deepa.singh@sun.com)
       * @return        String
       * @param                String key MIME header e.g Content-Type

       **@see com.sun.ejte.ccl.webrunner.proxy.MimeHeader
       */
        public String get(String key)
        {
        return (String)super.get(fix(key));
        }


       /*
        * @author       Deepa Singh(deepa.singh@sun.com)
       * @return       void
       * @param                String key MIME header e.g Content-Type
        *@param         String value value of MIME header
       **@see com.sun.ejte.ccl.webrunner.proxy.MimeHeader
       */
        public void put(String key,String val)
        {
        super.put(fix(key),val);
        }
}
