/*
 * Copyright (c) 2011 ICM Uniwersytet Warszawski All rights reserved.
 * See LICENCE file for licensing information.
 */
package eu.emi.security.authn.x509.helpers;

import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.util.io.pem.PemHeader;
import org.bouncycastle.util.io.pem.PemObject;


/**
 * Extends BC's {@link PEMParser} class so it can read correctly also 
 * PEM files with a garbage at the beginning 
 * and minor syntax violations which occur more then often in the wild. 
 *
 * TODO - probably we can remove this class - BC seems to be fixed.
 *
 * @author K. Benedyczak
 */
public class FlexiblePEMReader extends PEMParser
{
	/**
	 * Creates a new {@link FlexiblePEMReader} object. 
	 * @param reader input source
	 */
	public FlexiblePEMReader(Reader reader)
	{
		super(reader);
	}

	/**
	 * Generate BC's PemObject
	 * @return the parsed PEM object
	 * @throws IOException IO exception
	 */
	@Override
	public PemObject readPemObject() throws IOException
	{
		Pattern starter = Pattern.compile("^---[-]+BEGIN [^-]+---[-]+$");
		Pattern end = Pattern.compile("^---[-]+END [^-]+---[-]+$");
		
		String line;
		boolean startFound = false;
		while ((line=readLine()) != null)
		{
			Matcher m = starter.matcher(line);
			if (m.find())
			{
				startFound = true;
				break;
			}
		}
		if (!startFound)
			return null;
		
		int pos = line.indexOf("BEGIN ") + 6;
	        int endPos = line.indexOf('-', pos);
	        String type = line.substring(pos, endPos);
		
		boolean endFound = false;
		StringBuilder sb = new StringBuilder();
		List<PemHeader> headers = new ArrayList<PemHeader>();
		while ((line=readLine()) != null)
		{
			Matcher m = end.matcher(line);
			if (m.find())
				throw new IOException("The supplied data is not in PEM format, end line found before getting any contents.");
			if (line.indexOf(":") >= 0)
			{
		                int index = line.indexOf(':');
		                String hdr = line.substring(0, index);
		                String value = line.substring(index + 1).trim();
		                headers.add(new PemHeader(hdr, value));
			} else 
			{
				sb.append(line.trim());
				break;
			}
		}
		
		while ((line=readLine()) != null)
		{
			Matcher m = end.matcher(line);
			if (m.find())
			{
				endFound = true;
				break;
			} else 
				sb.append(line.trim());
		}
		if (!endFound)
			throw new IOException("The supplied data is not in PEM format, no ending line found.");

		return new PemObject(type, headers, Base64.decode(sb.toString()));
	}

}
