package com.greenautomation.pkeytool;

import java.io.*;
import java.security.*;
import java.security.cert.*;
import java.security.cert.Certificate;
import java.util.Map;

/**
 * Private Key Tool Utilities.<p>
 *
 * Copyright 2003 Green Automation, Inc.<p>
 *
 * This file is part of pkeytool.<p>
 *
 * pkeytool is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.<p>
 *
 * pkeytool is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.<p>
 *
 * You should have received a copy of the GNU General Public License
 * along with pkeytool; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * @author David Green &lt;green@couchpotato.net&gt;
 * @version $Id: Utils.java,v 1.2 2004/08/04 19:09:12 green Exp $
 */
public final class Utils {

    private static final char[] HEX_DIGITS = new char[] {
        '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
    };

    public static String promptFor(String prompt) throws IOException {
        System.err.print(prompt);
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String line = in.readLine();
        if (line == null) {
            return "";
        }
        return line;
    }

    public static String promptFor(String prompt, int count)
            throws IOException, PKeyToolException {
        int i = 0;
        while (true) {
            String s = Utils.promptFor(prompt);
            if (s.length() > 0) {
                return s;
            }
            if (++i >= 3) {
                throw new PKeyToolException("Too many failures - try later");
            }
        }
    }

    public static void saveKeyStore(KeyStore keystore, Map args)
            throws Exception {
        String filename = (String) args.get("-keystore");
        char[] pass = ((String) args.get("-storepass")).toCharArray();
        FileOutputStream out = new FileOutputStream(filename);
        keystore.store(out, pass);
        out.flush();
        out.close();
    }

    public static KeyStore openKeyStore(Map args, boolean passReqd, boolean create)
            throws Exception {
        String filename = (String) args.get("-keystore");
        char[] pass;
        if (passReqd) {
            String storepass = (String) args.get("-storepass");
            if (storepass == null) {
                storepass = Utils.promptFor("Enter keystore password:  ", 3);
                args.put("-storepass", storepass);
            }
            if (storepass.length() == 0) {
                    throw new PKeyToolException("No password was entered.");
            }
            pass = storepass.toCharArray();
        }
        else {
            pass = null;
        }
        if (filename == null) {
            filename = System.getProperty("user.home") + "/.keystore";
            args.put("-keystore", filename);
        }
        // ok we now check for the storetype and pass it into the KeyStore factory method
        String storetype = (String) args.get("-storetype");
        if(storetype == null) {
            storetype = KeyStore.getDefaultType();
        }
        KeyStore keystore = KeyStore.getInstance(storetype);
        try {
            FileInputStream in = new FileInputStream(filename);
            keystore.load(in, pass);
            in.close();
            return keystore;
        }
        catch (FileNotFoundException ex) {
            if (!create) {
                throw ex;
            }
            keystore.load(null, pass);
            return keystore;
        }
    }

    public static String getFingerprint(Certificate cert, String alg)
            throws NoSuchAlgorithmException, CertificateEncodingException {
        MessageDigest md5 = MessageDigest.getInstance(alg);
        byte[] digestBytes = md5.digest(cert.getEncoded());
        char[] digest = new char[digestBytes.length * 3 - 1];
        int j = 0;
        for (int i=0; i < digestBytes.length; i++) {
            if (i > 0) {
                digest[j++] = ':';
            }
            digest[j++] = HEX_DIGITS[digestBytes[i] >>> 4 & 0xF];
            digest[j++] = HEX_DIGITS[digestBytes[i] & 0xF];
        }
        return new String(digest);
    }

    public static void writeArmored(
            PrintStream out, byte[] data, String name, int lineLength) {
        out.println("-----BEGIN " + name + "-----");
        String s = new String(Base64.encode(data));
        for (int j = 0; j < s.length(); j += lineLength) {
            out.println(s.substring(
                    j, Math.min(j + lineLength, s.length())));
        }
        out.println("-----END " + name + "-----");
    }

    /**
     * Reads possibly armored data from the InputStream.
     *
     * @param in the input stream.
     * @param name the name of the data type.
     * @return the data
     */
    public static byte[] readArmored(InputStream in, String name)
            throws PKeyToolException, IOException {
        String header = "-----BEGIN " + name + "-----";
        byte[] headerBytes = header.getBytes();
        String footer = "-----END " + name + "-----";
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        while (true) {
            int b = in.read();
            if (b < 0) {
                break;
            }
            baos.write(b);
        }
        boolean isArmored = true;
        byte[] b = baos.toByteArray();
        for (int i=0; i < headerBytes.length; i++) {
            if (i >= b.length || b[i] != headerBytes[i]) {
                isArmored = false;
                break;
            }
        }
        if (!isArmored) {
            return b;
        }
        String b64data = new String(b);
        int start = header.length();
        int end = b64data.indexOf(footer, start);
        if (end < 0) {
            throw new PKeyToolException("Was expecting: " + footer);
        }
        b64data = b64data.substring(start, end);
        b = Base64.decode(Base64.strip(b64data.toCharArray()));
        return b;
    }

}