151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
2545619b8f363fbf58881e08f6a0a1008361eabf3Tobias Thierer * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it
651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as
751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation.  Oracle designates this
851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided
951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code.
1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT
1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that
1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code).
1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version
1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation,
1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any
2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions.
2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*-
2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *      news stream opener
2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage sun.net.www;
3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.*;
3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Collections;
34545619b8f363fbf58881e08f6a0a1008361eabf3Tobias Thiererimport java.util.*;
3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/** An RFC 844 or MIME message header.  Includes methods
3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    for parsing headers from incoming streams, fetching
3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    values, setting values, and printing headers.
3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    Key values of null are legal: they indicate lines in
4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    the header that don't have a valid key, but do have
4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    a value (this isn't legal according to the standard,
4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    but lines like this are everywhere). */
4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic
4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiclass MessageHeader {
4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private String keys[];
4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private String values[];
4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private int nkeys;
4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public MessageHeader () {
5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        grow();
5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public MessageHeader (InputStream is) throws java.io.IOException {
5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        parseHeader(is);
5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
58545619b8f363fbf58881e08f6a0a1008361eabf3Tobias Thierer     * Returns list of header names in a comma separated list
59545619b8f363fbf58881e08f6a0a1008361eabf3Tobias Thierer     */
60545619b8f363fbf58881e08f6a0a1008361eabf3Tobias Thierer    public synchronized String getHeaderNamesInList() {
61545619b8f363fbf58881e08f6a0a1008361eabf3Tobias Thierer        StringJoiner joiner = new StringJoiner(",");
62545619b8f363fbf58881e08f6a0a1008361eabf3Tobias Thierer        for (int i=0; i<nkeys; i++) {
63545619b8f363fbf58881e08f6a0a1008361eabf3Tobias Thierer            joiner.add(keys[i]);
64545619b8f363fbf58881e08f6a0a1008361eabf3Tobias Thierer        }
65545619b8f363fbf58881e08f6a0a1008361eabf3Tobias Thierer        return joiner.toString();
66545619b8f363fbf58881e08f6a0a1008361eabf3Tobias Thierer    }
67545619b8f363fbf58881e08f6a0a1008361eabf3Tobias Thierer
68545619b8f363fbf58881e08f6a0a1008361eabf3Tobias Thierer    /**
6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reset a message header (all key/values removed)
7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public synchronized void reset() {
7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        keys = null;
7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        values = null;
7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        nkeys = 0;
7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        grow();
7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Find the value that corresponds to this key.
8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * It finds only the first occurrence of the key.
8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param k the key to find.
8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return null if not found.
8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public synchronized String findValue(String k) {
8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (k == null) {
8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (int i = nkeys; --i >= 0;)
8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (keys[i] == null)
8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return values[i];
8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else
9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (int i = nkeys; --i >= 0;) {
9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (k.equalsIgnoreCase(keys[i]))
9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return values[i];
9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return null;
9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // return the location of the key
9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public synchronized int getKey(String k) {
9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = nkeys; --i >= 0;)
10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if ((keys[i] == k) ||
10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                (k != null && k.equalsIgnoreCase(keys[i])))
10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return i;
10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return -1;
10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public synchronized String getKey(int n) {
10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (n < 0 || n >= nkeys) return null;
10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return keys[n];
10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public synchronized String getValue(int n) {
11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (n < 0 || n >= nkeys) return null;
11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return values[n];
11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** Deprecated: Use multiValueIterator() instead.
11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *  Find the next value that corresponds to this key.
11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *  It finds the first value that follows v. To iterate
12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *  over all the values of a key use:
12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *  <pre>
12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          for(String v=h.findValue(k); v!=null; v=h.findNextValue(k, v)) {
12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *              ...
12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          }
12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *  </pre>
12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public synchronized String findNextValue(String k, String v) {
12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean foundV = false;
12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (k == null) {
13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (int i = nkeys; --i >= 0;)
13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (keys[i] == null)
13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (foundV)
13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return values[i];
13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    else if (values[i] == v)
13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        foundV = true;
13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else
13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (int i = nkeys; --i >= 0;)
13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (k.equalsIgnoreCase(keys[i]))
13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (foundV)
14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return values[i];
14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    else if (values[i] == v)
14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        foundV = true;
14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return null;
14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Removes bare Negotiate and Kerberos headers when an "NTLM ..."
14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * appears. All Performed on headers with key being k.
14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return true if there is a change
15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean filterNTLMResponses(String k) {
15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean found = false;
15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i=0; i<nkeys; i++) {
15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (k.equalsIgnoreCase(keys[i])
15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    && values[i] != null && values[i].length() > 5
156545619b8f363fbf58881e08f6a0a1008361eabf3Tobias Thierer                    && values[i].substring(0, 5).equalsIgnoreCase("NTLM ")) {
15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                found = true;
15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break;
15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (found) {
16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int j = 0;
16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (int i=0; i<nkeys; i++) {
16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (k.equalsIgnoreCase(keys[i]) && (
16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        "Negotiate".equalsIgnoreCase(values[i]) ||
16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        "Kerberos".equalsIgnoreCase(values[i]))) {
16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    continue;
16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (i != j) {
17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    keys[j] = keys[i];
17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    values[j] = values[i];
17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                j++;
17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (j != nkeys) {
17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                nkeys = j;
17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return true;
17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return false;
18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    class HeaderIterator implements Iterator<String> {
18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int index = 0;
18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int next = -1;
18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String key;
18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean haveNext = false;
18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Object lock;
18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public HeaderIterator (String k, Object lock) {
19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            key = k;
19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            this.lock = lock;
19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public boolean hasNext () {
19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            synchronized (lock) {
19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (haveNext) {
19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return true;
19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                while (index < nkeys) {
20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (key.equalsIgnoreCase (keys[index])) {
20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        haveNext = true;
20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        next = index++;
20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return true;
20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    index ++;
20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return false;
20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public String next() {
21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            synchronized (lock) {
21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (haveNext) {
21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    haveNext = false;
21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return values [next];
21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (hasNext()) {
21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return next();
21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    throw new NoSuchElementException ("No more elements");
22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public void remove () {
22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new UnsupportedOperationException ("remove not allowed");
22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * return an Iterator that returns all values of a particular
23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * key in sequence
23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public Iterator<String> multiValueIterator (String k) {
23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return new HeaderIterator (k, this);
23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public synchronized Map<String, List<String>> getHeaders() {
23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return getHeaders(null);
23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public synchronized Map<String, List<String>> getHeaders(String[] excludeList) {
24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return filterAndAddHeaders(excludeList, null);
24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
244545619b8f363fbf58881e08f6a0a1008361eabf3Tobias Thierer    public synchronized Map<String, List<String>> filterAndAddHeaders(
245545619b8f363fbf58881e08f6a0a1008361eabf3Tobias Thierer            String[] excludeList, Map<String, List<String>>  include) {
24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean skipIt = false;
24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Map<String, List<String>> m = new HashMap<String, List<String>>();
24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = nkeys; --i >= 0;) {
24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (excludeList != null) {
25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // check if the key is in the excludeList.
25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // if so, don't include it in the Map.
25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                for (int j = 0; j < excludeList.length; j++) {
25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if ((excludeList[j] != null) &&
25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        (excludeList[j].equalsIgnoreCase(keys[i]))) {
25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        skipIt = true;
25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        break;
25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!skipIt) {
26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                List<String> l = m.get(keys[i]);
26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (l == null) {
26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    l = new ArrayList<String>();
26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    m.put(keys[i], l);
26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                l.add(values[i]);
26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // reset the flag
26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                skipIt = false;
27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (include != null) {
274545619b8f363fbf58881e08f6a0a1008361eabf3Tobias Thierer                for (Map.Entry<String,List<String>> entry: include.entrySet()) {
275545619b8f363fbf58881e08f6a0a1008361eabf3Tobias Thierer                List<String> l = m.get(entry.getKey());
27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (l == null) {
277545619b8f363fbf58881e08f6a0a1008361eabf3Tobias Thierer                    l = new ArrayList<String>();
278545619b8f363fbf58881e08f6a0a1008361eabf3Tobias Thierer                    m.put(entry.getKey(), l);
27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
280545619b8f363fbf58881e08f6a0a1008361eabf3Tobias Thierer                l.addAll(entry.getValue());
28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (String key : m.keySet()) {
28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            m.put(key, Collections.unmodifiableList(m.get(key)));
28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return Collections.unmodifiableMap(m);
28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** Prints the key-value pairs represented by this
29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        header.  Also prints the RFC required blank line
29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        at the end. Omits pairs with a null key. */
29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public synchronized void print(PrintStream p) {
29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = 0; i < nkeys; i++)
29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (keys[i] != null) {
29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                p.print(keys[i] +
29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    (values[i] != null ? ": "+values[i]: "") + "\r\n");
29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        p.print("\r\n");
30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        p.flush();
30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** Adds a key value pair to the end of the
30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        header.  Duplicates are allowed */
30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public synchronized void add(String k, String v) {
30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        grow();
30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        keys[nkeys] = k;
30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        values[nkeys] = v;
31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        nkeys++;
31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** Prepends a key value pair to the beginning of the
31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        header.  Duplicates are allowed */
31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public synchronized void prepend(String k, String v) {
31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        grow();
31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = nkeys; i > 0; i--) {
31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            keys[i] = keys[i-1];
31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            values[i] = values[i-1];
32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        keys[0] = k;
32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        values[0] = v;
32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        nkeys++;
32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** Overwrite the previous key/val pair at location 'i'
32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * with the new k/v.  If the index didn't exist before
32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the key/val is simply tacked onto the end.
32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public synchronized void set(int i, String k, String v) {
33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        grow();
33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (i < 0) {
33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return;
33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (i >= nkeys) {
33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            add(k, v);
33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            keys[i] = k;
33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            values[i] = v;
34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** grow the key/value arrays as needed */
34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void grow() {
34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (keys == null || nkeys >= keys.length) {
34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            String[] nk = new String[nkeys + 4];
34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            String[] nv = new String[nkeys + 4];
35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (keys != null)
35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                System.arraycopy(keys, 0, nk, 0, nkeys);
35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (values != null)
35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                System.arraycopy(values, 0, nv, 0, nkeys);
35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            keys = nk;
35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            values = nv;
35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Remove the key from the header. If there are multiple values under
36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the same key, they are all removed.
36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Nothing is done if the key doesn't exist.
36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * After a remove, the other pairs' order are not changed.
36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param k the key to remove
36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public synchronized void remove(String k) {
36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if(k == null) {
36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (int i = 0; i < nkeys; i++) {
36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                while (keys[i] == null && i < nkeys) {
37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    for(int j=i; j<nkeys-1; j++) {
37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        keys[j] = keys[j+1];
37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        values[j] = values[j+1];
37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    nkeys--;
37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (int i = 0; i < nkeys; i++) {
37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                while (k.equalsIgnoreCase(keys[i]) && i < nkeys) {
38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    for(int j=i; j<nkeys-1; j++) {
38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        keys[j] = keys[j+1];
38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        values[j] = values[j+1];
38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    nkeys--;
38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** Sets the value of a key.  If the key already
39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        exists in the header, it's value will be
39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        changed.  Otherwise a new key/value pair will
39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        be added to the end of the header. */
39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public synchronized void set(String k, String v) {
39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = nkeys; --i >= 0;)
39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (k.equalsIgnoreCase(keys[i])) {
39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                values[i] = v;
39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return;
39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
40051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        add(k, v);
40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** Set's the value of a key only if there is no
40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *  key with that value already.
40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
40651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public synchronized void setIfNotSet(String k, String v) {
40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (findValue(k) == null) {
40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            add(k, v);
41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
41251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
41351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** Convert a message-id string to canonical form (strips off
41451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        leading and trailing <>s) */
41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static String canonicalID(String id) {
41651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (id == null)
41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return "";
41851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int st = 0;
41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int len = id.length();
42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean substr = false;
42151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int c;
42251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        while (st < len && ((c = id.charAt(st)) == '<' ||
42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            c <= ' ')) {
42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            st++;
42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            substr = true;
42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        while (st < len && ((c = id.charAt(len - 1)) == '>' ||
42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            c <= ' ')) {
42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            len--;
43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            substr = true;
43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return substr ? id.substring(st, len) : id;
43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
43451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
43551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** Parse a MIME header from an input stream. */
43651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void parseHeader(InputStream is) throws java.io.IOException {
43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        synchronized (this) {
43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            nkeys = 0;
43951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
44051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        mergeHeader(is);
44151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
44251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
44351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /** Parse and merge a MIME header from an input stream. */
444545619b8f363fbf58881e08f6a0a1008361eabf3Tobias Thierer    @SuppressWarnings("fallthrough")
44551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void mergeHeader(InputStream is) throws java.io.IOException {
44651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (is == null)
44751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return;
44851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        char s[] = new char[10];
44951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int firstc = is.read();
45051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        while (firstc != '\n' && firstc != '\r' && firstc >= 0) {
45151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int len = 0;
45251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int keyend = -1;
45351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int c;
45451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            boolean inKey = firstc > ' ';
45551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            s[len++] = (char) firstc;
45651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    parseloop:{
45751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                while ((c = is.read()) >= 0) {
45851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    switch (c) {
45951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                      case ':':
46051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (inKey && len > 0)
46151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            keyend = len;
46251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        inKey = false;
46351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        break;
46451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                      case '\t':
46551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        c = ' ';
466545619b8f363fbf58881e08f6a0a1008361eabf3Tobias Thierer                      /*fall through*/
46751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                      case ' ':
46851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        inKey = false;
46951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        break;
47051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                      case '\r':
47151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                      case '\n':
47251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        firstc = is.read();
47351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (c == '\r' && firstc == '\n') {
47451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            firstc = is.read();
47551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            if (firstc == '\r')
47651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                firstc = is.read();
47751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
47851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (firstc == '\n' || firstc == '\r' || firstc > ' ')
47951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            break parseloop;
48051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        /* continuation */
48151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        c = ' ';
48251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        break;
48351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
48451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (len >= s.length) {
48551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        char ns[] = new char[s.length * 2];
48651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        System.arraycopy(s, 0, ns, 0, len);
48751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        s = ns;
48851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
48951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    s[len++] = (char) c;
49051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
49151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                firstc = -1;
49251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
49351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while (len > 0 && s[len - 1] <= ' ')
49451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                len--;
49551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            String k;
49651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (keyend <= 0) {
49751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                k = null;
49851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                keyend = 0;
49951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
50051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                k = String.copyValueOf(s, 0, keyend);
50151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (keyend < len && s[keyend] == ':')
50251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    keyend++;
50351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                while (keyend < len && s[keyend] <= ' ')
50451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    keyend++;
50551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
50651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            String v;
50751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (keyend >= len)
50851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                v = new String();
50951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            else
51051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                v = String.copyValueOf(s, keyend, len - keyend);
51151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            add(k, v);
51251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
51351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
51451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
51551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public synchronized String toString() {
51651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String result = super.toString() + nkeys + " pairs: ";
51751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = 0; i < keys.length && i < nkeys; i++) {
51851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            result += "{"+keys[i]+": "+values[i]+"}";
51951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
52051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return result;
52151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
52251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
523