// 
// Decompiled by Procyon v0.6.0
// 

package io.netty.handler.ssl;

import java.io.ByteArrayOutputStream;
import java.security.KeyException;
import java.util.regex.Matcher;
import java.util.List;
import io.netty.handler.codec.base64.Base64;
import io.netty.buffer.Unpooled;
import io.netty.util.CharsetUtil;
import java.util.ArrayList;
import java.io.InputStream;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.io.FileInputStream;
import io.netty.buffer.ByteBuf;
import java.io.File;
import java.util.regex.Pattern;

final class PemReader
{
    private static final Pattern CERT_HEADER;
    private static final Pattern CERT_FOOTER;
    private static final Pattern KEY_HEADER;
    private static final Pattern KEY_FOOTER;
    private static final Pattern BODY;
    
    static ByteBuf[] readCertificates(final File file) throws CertificateException {
        try (final InputStream in = new FileInputStream(file)) {
            return readCertificates(in);
        }
        catch (final IOException e) {
            throw new CertificateException("could not find certificate file: " + file);
        }
    }
    
    static ByteBuf[] readCertificates(final InputStream in) throws CertificateException {
        String content;
        try {
            content = readContent(in);
        }
        catch (final IOException e) {
            throw new CertificateException("failed to read certificate input stream", e);
        }
        final List<ByteBuf> certs = new ArrayList<ByteBuf>();
        final Matcher m = PemReader.CERT_HEADER.matcher(content);
        int start = 0;
        while (true) {
            while (m.find(start)) {
                start = m.end();
                m.usePattern(PemReader.BODY);
                if (m.find(start)) {
                    final ByteBuf base64 = Unpooled.copiedBuffer(m.group(0), CharsetUtil.US_ASCII);
                    start = m.end();
                    m.usePattern(PemReader.CERT_FOOTER);
                    if (m.find(start)) {
                        final ByteBuf der = Base64.decode(base64);
                        base64.release();
                        certs.add(der);
                        start = m.end();
                        m.usePattern(PemReader.CERT_HEADER);
                        continue;
                    }
                }
                if (certs.isEmpty()) {
                    throw new CertificateException("found no certificates in input stream");
                }
                return certs.toArray(new ByteBuf[0]);
            }
            continue;
        }
    }
    
    static ByteBuf readPrivateKey(final File file) throws KeyException {
        try (final InputStream in = new FileInputStream(file)) {
            return readPrivateKey(in);
        }
        catch (final IOException e) {
            throw new KeyException("could not find key file: " + file);
        }
    }
    
    static ByteBuf readPrivateKey(final InputStream in) throws KeyException {
        String content;
        try {
            content = readContent(in);
        }
        catch (final IOException e) {
            throw new KeyException("failed to read key input stream", e);
        }
        int start = 0;
        final Matcher m = PemReader.KEY_HEADER.matcher(content);
        if (!m.find(start)) {
            throw keyNotFoundException();
        }
        start = m.end();
        m.usePattern(PemReader.BODY);
        if (!m.find(start)) {
            throw keyNotFoundException();
        }
        final ByteBuf base64 = Unpooled.copiedBuffer(m.group(0), CharsetUtil.US_ASCII);
        start = m.end();
        m.usePattern(PemReader.KEY_FOOTER);
        if (!m.find(start)) {
            throw keyNotFoundException();
        }
        final ByteBuf der = Base64.decode(base64);
        base64.release();
        return der;
    }
    
    private static KeyException keyNotFoundException() {
        return new KeyException("could not find a PKCS #8 private key in input stream (see https://netty.io/wiki/sslcontextbuilder-and-private-key.html for more information)");
    }
    
    private static String readContent(final InputStream in) throws IOException {
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        final byte[] buf = new byte[8192];
        while (true) {
            final int ret = in.read(buf);
            if (ret < 0) {
                break;
            }
            out.write(buf, 0, ret);
        }
        return out.toString(CharsetUtil.US_ASCII.name());
    }
    
    private PemReader() {
    }
    
    static {
        CERT_HEADER = Pattern.compile("-+BEGIN\\s[^-\\r\\n]*CERTIFICATE[^-\\r\\n]*-+(?:\\s|\\r|\\n)+");
        CERT_FOOTER = Pattern.compile("-+END\\s[^-\\r\\n]*CERTIFICATE[^-\\r\\n]*-+(?:\\s|\\r|\\n)*");
        KEY_HEADER = Pattern.compile("-+BEGIN\\s[^-\\r\\n]*PRIVATE\\s+KEY[^-\\r\\n]*-+(?:\\s|\\r|\\n)+");
        KEY_FOOTER = Pattern.compile("-+END\\s[^-\\r\\n]*PRIVATE\\s+KEY[^-\\r\\n]*-+(?:\\s|\\r|\\n)*");
        BODY = Pattern.compile("[a-z0-9+/=][a-z0-9+/=\\r\\n]*", 2);
    }
}
