package cz.hobrasoft.pdfmu.sign;

import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfReader;
import cz.hobrasoft.pdfmu.Operation;
import cz.hobrasoft.pdfmu.OperationException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import net.sourceforge.argparse4j.impl.Arguments;
import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser;

/**
 * Displays signatures of a PDF document
 *
 * @author <a href="mailto:filip.bartek@hobrasoft.cz">Filip Bartek</a>
 */
public class OperationSignatureDisplay implements Operation {

    @Override
    public String getCommandName() {
        return "display";
    }

    @Override
    public Subparser configureSubparser(Subparser subparser) {
        String help = "Display signatures of a PDF document";

        String metavarIn = "IN.pdf";

        // Configure the subparser
        subparser.help(help)
                .description(help)
                .defaultHelp(true)
                .setDefault("command", this.getClass());

        // Add arguments to the subparser
        // Positional arguments are required by default
        subparser.addArgument("in")
                .help("input PDF document")
                .metavar(metavarIn)
                .type(Arguments.fileType().acceptSystemIn().verifyCanRead())
                .required(true);

        return subparser;
    }

    @Override
    public void execute(Namespace namespace) throws OperationException {
        // Input file
        File inFile = namespace.get("in");
        assert inFile != null; // Required argument
        System.err.println(String.format("Input PDF document: %s", inFile));

        display(inFile);
    }

    private static void display(File inFile) throws OperationException {
        assert inFile != null;

        System.err.println(String.format("Input PDF document: %s", inFile));

        // Open the input stream
        FileInputStream inStream;
        try {
            inStream = new FileInputStream(inFile);
        } catch (FileNotFoundException ex) {
            throw new OperationException("Input file not found.", ex);
        }

        display(inStream);

        // Close the input stream
        try {
            inStream.close();
        } catch (IOException ex) {
            throw new OperationException("Could not close the input file.", ex);
        }
    }

    private static void display(InputStream inStream) throws OperationException {
        // Open the PDF reader
        // PdfReader parses a PDF document.
        PdfReader pdfReader;
        try {
            pdfReader = new PdfReader(inStream);
        } catch (IOException ex) {
            throw new OperationException("Could not open the input PDF document.", ex);
        }

        display(pdfReader);

        // Close the PDF reader
        pdfReader.close();
    }

    private static void display(PdfReader pdfReader) {
        AcroFields fields = pdfReader.getAcroFields();
        ArrayList<String> names = fields.getSignatureNames();
        for (String name : names) {
            System.err.println(String.format("Signature name: %s", name));
        }
    }

}

@@ -108,16 +108,64 @@
 Reader;%0A
+import com.itextpdf.text.pdf.security.PdfPKCS7;%0A
 import c
@@ -378,32 +378,79 @@
 io.InputStream;%0A
+import java.security.GeneralSecurityException;%0A
 import java.util
@@ -3139,162 +3139,723 @@
 er) 
-%7B%0A        AcroFields fields = pdfReader.getAcroFields();%0A        ArrayList%3CString%3E names = fields.getSignatureNames();%0A        for (String name : names) %7B
+throws OperationException %7B%0A        // digitalsignatures20130304.pdf : Code sample 5.1%0A        AcroFields fields = pdfReader.getAcroFields();%0A        display(fields);%0A    %7D%0A%0A    private static void display(AcroFields fields) throws OperationException %7B%0A        // digitalsignatures20130304.pdf : Code sample 5.1%0A        ArrayList%3CString%3E names = fields.getSignatureNames();%0A%0A        // Print number of signatures%0A        System.err.println(String.format(%22Number of signatures: %25d%22, names.size()));%0A        System.err.println(String.format(%22Number of document revisions: %25d%22, fields.getTotalRevisions()));%0A%0A        for (String name : names) %7B%0A            System.err.println(); // Separate singatures by an empty line
 %0A   
@@ -3907,16 +3907,22 @@
 gnature 
+field 
 name: %25s
@@ -3932,27 +3932,843 @@
 name));%0A        
-%7D
+    verifySignature(fields, name);%0A        %7D%0A    %7D%0A%0A    private static PdfPKCS7 verifySignature(AcroFields fields, String name) throws OperationException %7B%0A        // digitalsignatures20130304.pdf : Code sample 5.2%0A        System.err.println(String.format(%22  Signature covers the whole document: %25b%22, fields.signatureCoversWholeDocument(name)));%0A        System.err.println(String.format(%22  Document revision: %25d of %25d%22, fields.getRevision(name), fields.getTotalRevisions()));%0A        PdfPKCS7 pkcs7 = fields.verifySignature(name);%0A        try %7B%0A            System.err.println(String.format(%22  Integrity check OK?: %25b%22, pkcs7.verify()));%0A        %7D catch (GeneralSecurityException ex) %7B%0A            throw new OperationException(String.format(%22Could not verify signature %25s.%22, name), ex);%0A        %7D%0A        return pkcs7;
 %0A    %7D%0A%0A%7D%0A

Verify signatures