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. This jar contains APIs for JDK 1.8 and up. The APIs can be used in conjunction with a JCE/JCA provider such as the one provided with the Bouncy Castle Cryptography APIs.

There is a newer version: 1.78.1
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;
    }

    /**
     * Create specifying content type header value and default content transfer encoding.
     *
     * @param contentType                    The content type value
     * @param defaultContentTransferEncoding default content transfer encoding.
     */
    public Headers(String contentType, String defaultContentTransferEncoding)
    {
        String header = "Content-Type: " + contentType;
        headersAsPresented = new ArrayList();
        headersAsPresented.add(header);


        this.put("Content-Type", contentType);

        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)    // JVM compatibility
        {
            multipart = true;
            String bound = (String)contentTypeParameters.get("boundary");
            if (bound.startsWith("\"") && bound.endsWith("\""))
            {
                boundary = bound.substring(1, bound.length() - 1); // quoted-string
            }
            else
            {
                boundary = bound;
            }
        }
        else
        {
            boundary = null;
            multipart = false;
        }
    }

    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 static 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