/*
 * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*-
 *      news stream opener
 */

package sun.net.www;

import java.io.*;
import java.util.Collections;
import java.util.*;

/** An RFC 844 or MIME message header.  Includes methods
    for parsing headers from incoming streams, fetching
    values, setting values, and printing headers.
    Key values of null are legal: they indicate lines in
    the header that don't have a valid key, but do have
    a value (this isn't legal according to the standard,
    but lines like this are everywhere). */
public
class MessageHeader {
    private String keys[];
    private String values[];
    private int nkeys;

    public MessageHeader () {
        grow();
    }

    public MessageHeader (InputStream is) throws java.io.IOException {
        parseHeader(is);
    }

    /**
     * Returns list of header names in a comma separated list
     */
    public synchronized String getHeaderNamesInList() {
        StringJoiner joiner = new StringJoiner(",");
        for (int i=0; i<nkeys; i++) {
            joiner.add(keys[i]);
        }
        return joiner.toString();
    }

    /**
     * Reset a message header (all key/values removed)
     */
    public synchronized void reset() {
        keys = null;
        values = null;
        nkeys = 0;
        grow();
    }

    /**
     * Find the value that corresponds to this key.
     * It finds only the first occurrence of the key.
     * @param k the key to find.
     * @return null if not found.
     */
    public synchronized String findValue(String k) {
        if (k == null) {
            for (int i = nkeys; --i >= 0;)
                if (keys[i] == null)
                    return values[i];
        } else
            for (int i = nkeys; --i >= 0;) {
                if (k.equalsIgnoreCase(keys[i]))
                    return values[i];
            }
        return null;
    }

    // return the location of the key
    public synchronized int getKey(String k) {
        for (int i = nkeys; --i >= 0;)
            if ((keys[i] == k) ||
                (k != null && k.equalsIgnoreCase(keys[i])))
                return i;
        return -1;
    }

    public synchronized String getKey(int n) {
        if (n < 0 || n >= nkeys) return null;
        return keys[n];
    }

    public synchronized String getValue(int n) {
        if (n < 0 || n >= nkeys) return null;
        return values[n];
    }

    /** Deprecated: Use multiValueIterator() instead.
     *
     *  Find the next value that corresponds to this key.
     *  It finds the first value that follows v. To iterate
     *  over all the values of a key use:
     *  <pre>
     *          for(String v=h.findValue(k); v!=null; v=h.findNextValue(k, v)) {
     *              ...
     *          }
     *  </pre>
     */
    public synchronized String findNextValue(String k, String v) {
        boolean foundV = false;
        if (k == null) {
            for (int i = nkeys; --i >= 0;)
                if (keys[i] == null)
                    if (foundV)
                        return values[i];
                    else if (values[i] == v)
                        foundV = true;
        } else
            for (int i = nkeys; --i >= 0;)
                if (k.equalsIgnoreCase(keys[i]))
                    if (foundV)
                        return values[i];
                    else if (values[i] == v)
                        foundV = true;
        return null;
    }

    /**
     * Removes bare Negotiate and Kerberos headers when an "NTLM ..."
     * appears. All Performed on headers with key being k.
     * @return true if there is a change
     */
    public boolean filterNTLMResponses(String k) {
        boolean found = false;
        for (int i=0; i<nkeys; i++) {
            if (k.equalsIgnoreCase(keys[i])
                    && values[i] != null && values[i].length() > 5
                    && values[i].substring(0, 5).equalsIgnoreCase("NTLM ")) {
                found = true;
                break;
            }
        }
        if (found) {
            int j = 0;
            for (int i=0; i<nkeys; i++) {
                if (k.equalsIgnoreCase(keys[i]) && (
                        "Negotiate".equalsIgnoreCase(values[i]) ||
                        "Kerberos".equalsIgnoreCase(values[i]))) {
                    continue;
                }
                if (i != j) {
                    keys[j] = keys[i];
                    values[j] = values[i];
                }
                j++;
            }
            if (j != nkeys) {
                nkeys = j;
                return true;
            }
        }
        return false;
    }

    class HeaderIterator implements Iterator<String> {
        int index = 0;
        int next = -1;
        String key;
        boolean haveNext = false;
        Object lock;

        public HeaderIterator (String k, Object lock) {
            key = k;
            this.lock = lock;
        }
        public boolean hasNext () {
            synchronized (lock) {
                if (haveNext) {
                    return true;
                }
                while (index < nkeys) {
                    if (key.equalsIgnoreCase (keys[index])) {
                        haveNext = true;
                        next = index++;
                        return true;
                    }
                    index ++;
                }
                return false;
            }
        }
        public String next() {
            synchronized (lock) {
                if (haveNext) {
                    haveNext = false;
                    return values [next];
                }
                if (hasNext()) {
                    return next();
                } else {
                    throw new NoSuchElementException ("No more elements");
                }
            }
        }
        public void remove () {
            throw new UnsupportedOperationException ("remove not allowed");
        }
    }

    /**
     * return an Iterator that returns all values of a particular
     * key in sequence
     */
    public Iterator<String> multiValueIterator (String k) {
        return new HeaderIterator (k, this);
    }

    public synchronized Map<String, List<String>> getHeaders() {
        return getHeaders(null);
    }

    public synchronized Map<String, List<String>> getHeaders(String[] excludeList) {
        return filterAndAddHeaders(excludeList, null);
    }

    public synchronized Map<String, List<String>> filterAndAddHeaders(
            String[] excludeList, Map<String, List<String>>  include) {
        boolean skipIt = false;
        Map<String, List<String>> m = new HashMap<String, List<String>>();
        for (int i = nkeys; --i >= 0;) {
            if (excludeList != null) {
                // check if the key is in the excludeList.
                // if so, don't include it in the Map.
                for (int j = 0; j < excludeList.length; j++) {
                    if ((excludeList[j] != null) &&
                        (excludeList[j].equalsIgnoreCase(keys[i]))) {
                        skipIt = true;
                        break;
                    }
                }
            }
            if (!skipIt) {
                List<String> l = m.get(keys[i]);
                if (l == null) {
                    l = new ArrayList<String>();
                    m.put(keys[i], l);
                }
                l.add(values[i]);
            } else {
                // reset the flag
                skipIt = false;
            }
        }

        if (include != null) {
                for (Map.Entry<String,List<String>> entry: include.entrySet()) {
                List<String> l = m.get(entry.getKey());
                if (l == null) {
                    l = new ArrayList<String>();
                    m.put(entry.getKey(), l);
                }
                l.addAll(entry.getValue());
            }
        }

        for (String key : m.keySet()) {
            m.put(key, Collections.unmodifiableList(m.get(key)));
        }

        return Collections.unmodifiableMap(m);
    }

    /** Prints the key-value pairs represented by this
        header.  Also prints the RFC required blank line
        at the end. Omits pairs with a null key. */
    public synchronized void print(PrintStream p) {
        for (int i = 0; i < nkeys; i++)
            if (keys[i] != null) {
                p.print(keys[i] +
                    (values[i] != null ? ": "+values[i]: "") + "\r\n");
            }
        p.print("\r\n");
        p.flush();
    }

    /** Adds a key value pair to the end of the
        header.  Duplicates are allowed */
    public synchronized void add(String k, String v) {
        grow();
        keys[nkeys] = k;
        values[nkeys] = v;
        nkeys++;
    }

    /** Prepends a key value pair to the beginning of the
        header.  Duplicates are allowed */
    public synchronized void prepend(String k, String v) {
        grow();
        for (int i = nkeys; i > 0; i--) {
            keys[i] = keys[i-1];
            values[i] = values[i-1];
        }
        keys[0] = k;
        values[0] = v;
        nkeys++;
    }

    /** Overwrite the previous key/val pair at location 'i'
     * with the new k/v.  If the index didn't exist before
     * the key/val is simply tacked onto the end.
     */

    public synchronized void set(int i, String k, String v) {
        grow();
        if (i < 0) {
            return;
        } else if (i >= nkeys) {
            add(k, v);
        } else {
            keys[i] = k;
            values[i] = v;
        }
    }


    /** grow the key/value arrays as needed */

    private void grow() {
        if (keys == null || nkeys >= keys.length) {
            String[] nk = new String[nkeys + 4];
            String[] nv = new String[nkeys + 4];
            if (keys != null)
                System.arraycopy(keys, 0, nk, 0, nkeys);
            if (values != null)
                System.arraycopy(values, 0, nv, 0, nkeys);
            keys = nk;
            values = nv;
        }
    }

    /**
     * Remove the key from the header. If there are multiple values under
     * the same key, they are all removed.
     * Nothing is done if the key doesn't exist.
     * After a remove, the other pairs' order are not changed.
     * @param k the key to remove
     */
    public synchronized void remove(String k) {
        if(k == null) {
            for (int i = 0; i < nkeys; i++) {
                while (keys[i] == null && i < nkeys) {
                    for(int j=i; j<nkeys-1; j++) {
                        keys[j] = keys[j+1];
                        values[j] = values[j+1];
                    }
                    nkeys--;
                }
            }
        } else {
            for (int i = 0; i < nkeys; i++) {
                while (k.equalsIgnoreCase(keys[i]) && i < nkeys) {
                    for(int j=i; j<nkeys-1; j++) {
                        keys[j] = keys[j+1];
                        values[j] = values[j+1];
                    }
                    nkeys--;
                }
            }
        }
    }

    /** Sets the value of a key.  If the key already
        exists in the header, it's value will be
        changed.  Otherwise a new key/value pair will
        be added to the end of the header. */
    public synchronized void set(String k, String v) {
        for (int i = nkeys; --i >= 0;)
            if (k.equalsIgnoreCase(keys[i])) {
                values[i] = v;
                return;
            }
        add(k, v);
    }

    /** Set's the value of a key only if there is no
     *  key with that value already.
     */

    public synchronized void setIfNotSet(String k, String v) {
        if (findValue(k) == null) {
            add(k, v);
        }
    }

    /** Convert a message-id string to canonical form (strips off
        leading and trailing <>s) */
    public static String canonicalID(String id) {
        if (id == null)
            return "";
        int st = 0;
        int len = id.length();
        boolean substr = false;
        int c;
        while (st < len && ((c = id.charAt(st)) == '<' ||
                            c <= ' ')) {
            st++;
            substr = true;
        }
        while (st < len && ((c = id.charAt(len - 1)) == '>' ||
                            c <= ' ')) {
            len--;
            substr = true;
        }
        return substr ? id.substring(st, len) : id;
    }

    /** Parse a MIME header from an input stream. */
    public void parseHeader(InputStream is) throws java.io.IOException {
        synchronized (this) {
            nkeys = 0;
        }
        mergeHeader(is);
    }

    /** Parse and merge a MIME header from an input stream. */
    @SuppressWarnings("fallthrough")
    public void mergeHeader(InputStream is) throws java.io.IOException {
        if (is == null)
            return;
        char s[] = new char[10];
        int firstc = is.read();
        while (firstc != '\n' && firstc != '\r' && firstc >= 0) {
            int len = 0;
            int keyend = -1;
            int c;
            boolean inKey = firstc > ' ';
            s[len++] = (char) firstc;
    parseloop:{
                while ((c = is.read()) >= 0) {
                    switch (c) {
                      case ':':
                        if (inKey && len > 0)
                            keyend = len;
                        inKey = false;
                        break;
                      case '\t':
                        c = ' ';
                      /*fall through*/
                      case ' ':
                        inKey = false;
                        break;
                      case '\r':
                      case '\n':
                        firstc = is.read();
                        if (c == '\r' && firstc == '\n') {
                            firstc = is.read();
                            if (firstc == '\r')
                                firstc = is.read();
                        }
                        if (firstc == '\n' || firstc == '\r' || firstc > ' ')
                            break parseloop;
                        /* continuation */
                        c = ' ';
                        break;
                    }
                    if (len >= s.length) {
                        char ns[] = new char[s.length * 2];
                        System.arraycopy(s, 0, ns, 0, len);
                        s = ns;
                    }
                    s[len++] = (char) c;
                }
                firstc = -1;
            }
            while (len > 0 && s[len - 1] <= ' ')
                len--;
            String k;
            if (keyend <= 0) {
                k = null;
                keyend = 0;
            } else {
                k = String.copyValueOf(s, 0, keyend);
                if (keyend < len && s[keyend] == ':')
                    keyend++;
                while (keyend < len && s[keyend] <= ' ')
                    keyend++;
            }
            String v;
            if (keyend >= len)
                v = new String();
            else
                v = String.copyValueOf(s, keyend, len - keyend);
            add(k, v);
        }
    }

    public synchronized String toString() {
        String result = super.toString() + nkeys + " pairs: ";
        for (int i = 0; i < keys.length && i < nkeys; i++) {
            result += "{"+keys[i]+": "+values[i]+"}";
        }
        return result;
    }
}
