/*
 * SamplePDFTimeStampValidator.java
 *
 * Copyright(C) 2005-2022 AMANO Corporation. All Rights Reserved.
 *
 * PDF Lib-J API - サンプルプログラム
 *
 * 指定されたタイムスタンプ付 PDF 文書を検証する
 * コンソールプログラムです。
 *
 * セキュリティ無しの文書の場合
 * Usage: java SamplePDFTimeStampValidator (TALL) FilePath CAFilePath CertificateFilePath
 *
 *    PDFFilePath          - PDF ファイルパス
 *    CAFilePath           - 中間CA証明書ファイルパス
 *    CertificateFilePath  - ルート証明書ファイルパス
 *
 * PDF 標準セキュリティ有りの文書の場合
 * Usage: java SamplePDFTimeStampValidator (TALL) FilePath UserPassword OwnerPassword CAFilePath CertificateFileaPath
 *
 *    PDFFilePath          - PDF ファイルパス
 *    UserPassword         - ユーザーパスワード
 *    OwnerPassword        - オーナーパスワード
 *    CAFilePath           - 中間CA証明書ファイルパス
 *    CertificateFilePath  - ルート証明書ファイルパス
 *
 * TALLを指定した場合、アマノタイムスタンプサービス 3161 によって発行されたタイムスタンプ及びアマノタイムスタンプサービス 3161 以外で
 * 発行されたタイムスタンプトークンのうち、時刻監査証明書を含まない タイムスタンプを検証します。
 */

import java.io.*;
import java.util.*;
import java.security.cert.*;

import jp.co.amano.etiming.apl3161.*;
import jp.co.amano.etiming.atss3161.*;

public class SamplePDFTimeStampValidator {

	public static void main(String[] args) throws Exception {

		String pdfFilePath = null;

		String[] certFilePath = new String[2];
		certFilePath[0] = null;
		certFilePath[1] = null;
		
		char[] userPassword = null;
		char[] ownerPassword = null;
		
		int verifyTarget = PDFTimeStampValidator.VERIFY_TARGET_AMANO;
		if (args.length == 2) {
			if (args[0].equals("TALL")) {
				showUsage();
			}
		}
		else if (args.length > 2) {
			if (args[0].equals("TALL")) {
				verifyTarget = PDFTimeStampValidator.VERIFY_TARGET_FULL;
			}
		}

		if (verifyTarget == PDFTimeStampValidator.VERIFY_TARGET_AMANO) {
			// 引数チェック
			if (args.length == 2 || args.length == 3) {
				pdfFilePath  = args[0];
				certFilePath[0] = args[1];
				if (args.length == 3) {
					certFilePath[1] = args[2];
				}
			} else if (args.length == 4 || args.length == 5) {
				pdfFilePath  = args[0];
				userPassword = args[1].toCharArray();
				ownerPassword = args[2].toCharArray();
				certFilePath[0] = args[3];
				if (args.length == 5) {
					certFilePath[1] = args[4];
				}
			} else {
				showUsage();
			}
		}
		else {
			// 引数チェック
			if (args.length == 3 || args.length == 4) {
				pdfFilePath  = args[1];
				certFilePath[0] = args[2];
				if (args.length == 4) {
					certFilePath[1] = args[3];
				}
			} else if (args.length == 5 || args.length == 6) {
				pdfFilePath  = args[1];
				userPassword = args[2].toCharArray();
				ownerPassword = args[3].toCharArray();
				certFilePath[0] = args[4];
				if (args.length == 6) {
					certFilePath[1] = args[5];
				}
			} else {
				showUsage();
			}
		}

		try {
			// PDF ファイルのオープン
			RandomAccessFile pdfDocument = new RandomAccessFile(pdfFilePath, "r");

			// PDF ファイル検証オブジェクトを生成する
			AmanoTSTValidator amanoValidator = makeAmanoTSTValidator(certFilePath);
			PDFTimeStampValidator pdfValidator = new PDFTimeStampValidator(amanoValidator);
			
			// タイムスタンプの検証対象を設定する
			pdfValidator.setVerifyTarget(verifyTarget);

			// 検証する
			if (userPassword == null && ownerPassword == null) {
				pdfValidator.validate(pdfDocument);
			} else {
				pdfValidator.validate(pdfDocument, userPassword, ownerPassword);
			}
			pdfDocument.close();

			// Exception が発生しなかった場合、検証処理は正常終了
			System.out.println("検証処理が成功しました。");

		} catch (Exception ex) {
			ex.printStackTrace();
			System.out.println("検証処理が失敗しました。");
		}
	}


	// タイムスタンプトークン検証オブジェクトを生成する
	//     CRL を自動取得する場合に使用する
	private static AmanoTSTValidator makeAmanoTSTValidator(String[] certPath) throws Exception {

		// CRL 取得時に使用するプロキシの設定
		ProxyHost proxy = null;

		// プロキシを使用して CRL を取得する場合は以下のように設定する
		//ProxyHost proxy = new ProxyHost("hostname", 80);

		// CRL 用ロケーターを作成する
		CRLDistributionPointsCRLLocator crlLocator = new CRLDistributionPointsCRLLocator();
		crlLocator.setConnectionTimeout(15000);
		crlLocator.setTimeout(15000);
		crlLocator.setProxyHost(proxy);
		crlLocator.setUpdateInterval(60);

		// 証明書用ロケーターを作成する
		CollectionCertificateLocator certLocator = makeCollectionCertificateLocator(certPath);

		// タイムスタンプトークンを検証するオブジェクトを生成する
		return new AmanoTSTValidator(certLocator, crlLocator);
	}

	// 証明書用ロケーターオブジェクトを生成する
	private static CollectionCertificateLocator makeCollectionCertificateLocator(String[] certPath) throws Exception {

		// 証明書ファクトリの作成
		CertificateFactory factory = CertificateFactory.getInstance("X.509");

		// 証明書ファイルを読み込んでリストに追加する
		ArrayList certList = new ArrayList();
		for (int i = 0; i < certPath.length; i++) {
			if (certPath[i] == null || certPath[i].isEmpty()) {
				continue;
			}
			
			X509Certificate cert = (X509Certificate)factory.generateCertificate(new FileInputStream(certPath[i]));
			certList.add((X509Certificate)cert);
		}

		// 証明書用ロケーターオブジェクトを生成する
		return new CollectionCertificateLocator(certList);
	}
	
	private static void showUsage() {
		System.out.println("usage : java SamplePDFTimeStampValidator (TALL) <PDFFilePath> <CertificateFilePath>");
		System.out.println("      : java SamplePDFTimeStampValidator (TALL) <PDFFilePath> <CAFilePath> <CertificateFilePath>");
		System.out.println("      : java SamplePDFTimeStampValidator (TALL) <PDFFilePath> <UserPassword> <OwnerPassword> <CertificateFilePath>");
		System.out.println("      : java SamplePDFTimeStampValidator (TALL) <PDFFilePath> <UserPassword> <OwnerPassword> <CAFilePath> <CertificateFilePath>");
		System.out.println();
		System.out.println("      PDFFilePath          - 検証する PDF ファイルパス");
		System.out.println("      UserPassword         - ユーザーパスワード");
		System.out.println("      OwnerPassword        - オーナーパスワード");
		System.out.println("      CAFilePath           - 中間CA証明書ファイルパス");
		System.out.println("      CertificateFilePath  - ルート証明書ファイルパス");
		System.exit(1);
	}
}
