All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bouncycastle.mime.Headers Maven / Gradle / Ivy

Go to download

The Bouncy Castle Java APIs for CMS, PKCS, EAC, TSP, CMP, CRMF, OCSP, and certificate generation. The APIs are designed primarily to be used in conjunction with the BC FIPS provider. The APIs may also be used with other providers although if being used in a FIPS context it is the responsibility of the user to ensure that any other providers used are FIPS certified.

There is a newer version: 2.0.7
Show newest version
package org.bouncycastle.mime;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.bouncycastle.util.Iterable;
import org.bouncycastle.util.Strings;

public class Headers
    implements Iterable
{
    private final Map headers = new TreeMap(String.CASE_INSENSITIVE_ORDER);
    private final List headersAsPresented;
    private final String contentTransferEncoding;

    private String boundary;
    private boolean multipart;
    private String contentType;
    private Map contentTypeParameters;

    private static List parseHeaders(InputStream src)
        throws IOException
    {
        String s;
        List headerLines = new ArrayList();
        LineReader   rd = new LineReader(src);

        while ((s = rd.readLine()) != null)
        {
            if (s.length() == 0)
            {
                break;
            }
            headerLines.add(s);
        }

        return headerLines;
    }

    public Headers(InputStream source, String defaultContentTransferEncoding)
        throws IOException
    {
        this(parseHeaders(source), defaultContentTransferEncoding);
    }

    public Headers(List headerLines, String defaultContentTransferEncoding)
    {
        this.headersAsPresented = headerLines;

        String header = "";
        for (Iterator it = headerLines.iterator(); it.hasNext();)
        {
            String line = (String)it.next();
            if (line.startsWith(" ") || line.startsWith("\t"))
            {
                header = header + line.trim();
            }
            else
            {
                if (header.length() != 0)
                {
                    this.put(header.substring(0, header.indexOf(':')).trim(), header.substring(header.indexOf(':') + 1).trim());
                }
                header = line;
            }
        }

        // pick up last header line
        if (header.trim().length() != 0)
        {
            this.put(header.substring(0, header.indexOf(':')).trim(), header.substring(header.indexOf(':') + 1).trim());
        }

        String contentTypeHeader = (this.getValues("Content-Type") == null) ? "text/plain" : this.getValues("Content-Type")[0];

        int parameterIndex = contentTypeHeader.indexOf(';');
        if (parameterIndex < 0)
        {
            contentType = contentTypeHeader;
            contentTypeParameters = Collections.EMPTY_MAP;
        }
        else
        {
            contentType = contentTypeHeader.substring(0, parameterIndex);
            contentTypeParameters = createContentTypeParameters(contentTypeHeader.substring(parameterIndex + 1).trim());
        }

        contentTransferEncoding = this.getValues("Content-Transfer-Encoding") == null ? defaultContentTransferEncoding : this.getValues("Content-Transfer-Encoding")[0];

        if (contentType.indexOf("multipart") >= 0)
        {
            multipart = true;
            String bound = (String)contentTypeParameters.get("boundary");
            boundary = bound.substring(1, bound.length() - 1); // quoted-string
        }
        else
        {
            boundary = null;
            multipart = false;
        }
    }

    /**
     * Return the a Map of the ContentType attributes and their values.
     *
     * @return a Map of ContentType parameters - empty if none present.
     */
    public Map getContentTypeAttributes()
    {
        return contentTypeParameters;
    }

    /**
     * Return the a list of the ContentType parameters.
     *
     * @return a list of ContentType parameters - empty if none present.
     */
    private Map createContentTypeParameters(String contentTypeParameters)
    {
        String[] parameterSplit = contentTypeParameters.split(";");
        Map rv = new LinkedHashMap();

        for (int i = 0; i != parameterSplit.length; i++)
        {
            String parameter = parameterSplit[i];

            int eqIndex = parameter.indexOf('=');
            if (eqIndex < 0)
            {
                throw new IllegalArgumentException("malformed Content-Type header");
            }

            rv.put(parameter.substring(0, eqIndex).trim(), parameter.substring(eqIndex + 1).trim());
        }

        return Collections.unmodifiableMap(rv);
    }

    public boolean isMultipart()
    {
        return multipart;
    }

    public String getBoundary()
    {
        return boundary;
    }

    public String getContentType()
    {
        return contentType;
    }

    public String getContentTransferEncoding()
    {
        return contentTransferEncoding;
    }

    private void put(String field, String value)
    {
        synchronized (this)
        {
            KV kv = new KV(field, value);
            List list = (List)headers.get(field);
            if (list == null)
            {
                list = new ArrayList();
                headers.put(field, list);
            }
            list.add(kv);
        }
    }

    public Iterator getNames()
    {
        return headers.keySet().iterator();
    }

    public String[] getValues(String header)
    {

        synchronized (this)
        {
            List kvList = (List)headers.get(header);
            if (kvList == null)
            {
                return null;
            }
            String[] out = new String[kvList.size()];

            for (int t = 0; t < kvList.size(); t++)
            {
                out[t] = ((KV)kvList.get(t)).value;
            }

            return out;
        }
    }

    public boolean isEmpty()
    {
        synchronized (this)
        {
            return headers.isEmpty();
        }
    }

    public boolean containsKey(String s)
    {
        return headers.containsKey(s);
    }

    public Iterator iterator()
    {
        return headers.keySet().iterator();
    }

    public void dumpHeaders(OutputStream outputStream)
        throws IOException
    {
        for (Iterator it = headersAsPresented.iterator(); it.hasNext();)
        {
            outputStream.write(Strings.toUTF8ByteArray(it.next().toString()));
            outputStream.write('\r');
            outputStream.write('\n');
        }
    }

    private class KV
    {
        public final String key;
        public final String value;

        public KV(String key, String value)
        {
            this.key = key;
            this.value = value;
        }

        public KV(KV kv)
        {
            this.key = kv.key;
            this.value = kv.value;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy