/**
 * BdkimUsageExample.java
 * Copyright (c) 2011, Casey Connor
 * All rights reserved.
 
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *    - Redistributions of source code must retain the above copyright notice, this
 *      list of conditions and the following disclaimer.
 *    - Redistributions in binary form must reproduce the above copyright notice,
 *      this list of conditions and the following disclaimer in the documentation
 *      and/or other materials provided with the distribution.
 *    - Neither the name of Lacinato nor the names of its contributors may be used to
 *      endorse or promote products derived from this software without specific prior
 *      written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
 * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 * http://lacinato.com/cm/software/emailrelated/bdkim
 
 * This is an example of how to use the BdkimAnalyzer. The main method takes a command-line argument for the path to a raw email message file
 * (containing all raw RFC-2822 headers and message content). It sends the message to the BDKIM perl server (which must be running and
 * configured) and prints the results returned from the server to stdout.
 
 @author Casey Connor -- lacinato.com
 @version 1.0
 */

package com.lacinato.tools.examples;

import com.lacinato.tools.bdkim.BdkimAnalyzer;
import com.lacinato.tools.bdkim.AuthVerificationException;
import com.lacinato.tools.bdkim.BdkimAnalyzer.SignatureResults;

import java.io.*;

/**
 * <a href="http://lacinato.com/cm/software/emailrelated/bdkim">http://lacinato.com/cm/software/emailrelated/bdkim</a>
 <p/>
 * This is a simple example of how to use the BdkimAnalyzer (and perhaps also useful for testing.) See the sourc code
 * for the details.
 <p/>
 * The main() method takes three command-line arguments:<br/>
 * - the path to a raw email message file (containing all raw headers and message content, etc)<br/>
 * - the hostname or IP address of the BDKIM perl server (e.g. "localhost")<br/>
 * - the port that the BDKIM perl server is using (e.g. 12300)
 <p/>
 * It sends the message over to the BDKIM perl server (which must be configured and running) and
 * prints the results returned from the server to stdout.
 <p/>
 * For information on the BdkimAnalyzer.SignatureResults object, which contains the results in a
 * structured form, see documentation for that class.
 
 @author Casey Connor -- <a href="http://lacinato.com">lacinato.com</a>
 @version 1.0
 */
public class BdkimUsageExample
{
    public static void main(String[] args)
    {
        // args[0] is filename
        // args[1] is hostname of BDKIM server (e.g. "localhost")
        // args[2] is the port of the BDKIM server (e.g. 12300)
        if (args.length < 3)
        {
            System.out.println("supply file name, host, and port!");
            System.exit(1);
        }

        // read in the source file:
        String message_txt = null;
        try message_txt = readMessageFile(args[0])}
        catch (Exception e) { System.out.println("Got exception opening message file: " + e); System.exit(1)}

        // The lines have to have proper \r\n email message line-endings. You can either ensure proper
        // line endings in the file itself before it is read in, here in Java (or your custom client), or on the
        // perl side. We don't need to clean line endings because the deafult config of BdkimAnalyzer and
        // BDKIM cleans them for us, but this is here in case you need it for testing, etc.
        // message_txt = cleanLineEndings(message_txt);

        // make a new analyzer instance and configure it (in your program keep this reference around for re-use):
        BdkimAnalyzer analyzer = new BdkimAnalyzer();
        analyzer.setHost(args[1]);
        try analyzer.setPort(Integer.parseInt(args[2]))}
        catch (NumberFormatException nfe) { System.out.println("bad port number specified!"); System.exit(1)}

        BdkimAnalyzer.SignatureResults results = null;

        // compute the results (this sends to the BDKIM server):
        try results = analyzer.determineDkimStatuses(message_txt)}
        catch (AuthVerificationException ave)
        {
            System.out.println("Got exception when attempting to determineDkimStatuses: " + ave);
            return;
        }

        // Use the results:

        System.out.println("Summary result (not recommended for precise use): " + SignatureResults.resultToString(results.getSummaryResult()));

        System.out.println("\ntoString() result is as follows: " + results);

        System.out.println("\nResults per signature:");

        int num_sigs;

        if ((num_sigs = results.getNumberOfSignatures()) == 0)
            System.out.println("NONE - there were no signatures found in the message.");
        else
        {
            for (int i = 0; i < num_sigs; i++)
            {
                System.out.println("-----------");
                System.out.println("Signature at index " + i + ":");
                System.out.println("Result: " + SignatureResults.resultToString(results.getResult(i)));
                System.out.println("Verbose result: " + results.getRawResult(i));
                System.out.println("Domain: " + results.getDomain(i));
                System.out.println("Headers signed by signature: " + results.getRawHeaderList(i));
                // could also fetch getHeaderList for an array form of the same
            }
        }
    }

    /**
     * Unused in default code above, but provided in case it's useful to you.
     */
    @SuppressWarnings("unused")
    private static String cleanLineEndings(String message_text)
    {
        BufferedReader my_bufr = new BufferedReader(new StringReader(message_text));
        
        String line;
        StringBuffer outp = new StringBuffer(message_text.length());

        try
        {
            while ((line = my_bufr.readLine()) != null)
            {
                outp.append(line + "\r\n");
            }
        }
        catch (IOException ioe)
        {
            System.out.println("Strange... couldn't fix line endings. Data is corrupt and will not work. IOException: " + ioe);
            return(outp.toString());
        }

        return(outp.toString());
    }

    /**
     * Read the file in.
     */
    private static String readMessageFile(String paththrows FileNotFoundException, IOException
    {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File(path)));

        boolean go = true;
        byte[] buf = new byte[4096];
        int read = -1;
        StringBuffer message_txt = new StringBuffer();

        while (go)
        {
            read = bis.read(buf, 04096);
            if (read > 0message_txt.append(new String(buf, 0, read));
            else go = false;
        }

        bis.close();
        return(message_txt.toString());
    }
}