diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java b/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java index f8e5f25e..27262feb 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java @@ -8,6 +8,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; +import java.nio.file.Files; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; @@ -21,6 +22,7 @@ import java.security.cert.X509Certificate; import java.util.Calendar; import java.util.List; +import org.apache.commons.io.FileUtils; import org.apache.pdfbox.examples.signature.CreateSignatureBase; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; @@ -92,7 +94,7 @@ public class CertSignController { } class CreateSignature extends CreateSignatureBase { - File imageFile; + File logoFile; public CreateSignature(KeyStore keystore, char[] pin) throws KeyStoreException, @@ -102,11 +104,17 @@ public class CertSignController { CertificateException { super(keystore, pin); ClassPathResource resource = new ClassPathResource("static/images/signature.png"); - imageFile = resource.getFile(); + try (InputStream is = resource.getInputStream()) { + logoFile = Files.createTempFile("signature", ".png").toFile(); + FileUtils.copyInputStreamToFile(is, logoFile); + } catch (IOException e) { + logger.error("Failed to load image signature file"); + throw e; + } } public InputStream createVisibleSignature( - PDDocument srcDoc, PDSignature signature, Integer pageNumber, Boolean showImage) + PDDocument srcDoc, PDSignature signature, Integer pageNumber, Boolean showLogo) throws IOException { // modified from org.apache.pdfbox.examples.signature.CreateVisibleSignature2 try (PDDocument doc = new PDDocument()) { @@ -145,7 +153,7 @@ public class CertSignController { widget.setAppearance(appearance); try (PDPageContentStream cs = new PDPageContentStream(doc, appearanceStream)) { - if (showImage) { + if (showLogo) { cs.saveGraphicsState(); PDExtendedGraphicsState extState = new PDExtendedGraphicsState(); extState.setBlendMode(BlendMode.MULTIPLY); @@ -153,7 +161,7 @@ public class CertSignController { cs.setGraphicsStateParameters(extState); cs.transform(Matrix.getScaleInstance(0.08f, 0.08f)); PDImageXObject img = - PDImageXObject.createFromFileByExtension(imageFile, doc); + PDImageXObject.createFromFileByExtension(logoFile, doc); cs.drawImage(img, 100, 0); cs.restoreGraphicsState(); } @@ -219,6 +227,7 @@ public class CertSignController { String location = request.getLocation(); String name = request.getName(); Integer pageNumber = request.getPageNumber() - 1; + Boolean showLogo = request.isShowLogo(); if (certType == null) { throw new IllegalArgumentException("Cert type must be provided"); @@ -258,7 +267,8 @@ public class CertSignController { pageNumber, name, location, - reason); + reason, + showLogo); return WebResponseUtils.boasToWebResponse( baos, Filenames.toSimpleFileName(pdf.getOriginalFilename()).replaceFirst("[.][^.]+$", "") @@ -274,7 +284,8 @@ public class CertSignController { Integer pageNumber, String name, String location, - String reason) { + String reason, + Boolean showLogo) { try (PDDocument doc = pdfDocumentFactory.load(input)) { PDSignature signature = new PDSignature(); signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE); @@ -287,7 +298,7 @@ public class CertSignController { if (showSignature) { SignatureOptions signatureOptions = new SignatureOptions(); signatureOptions.setVisualSignature( - instance.createVisibleSignature(doc, signature, pageNumber, true)); + instance.createVisibleSignature(doc, signature, pageNumber, showLogo)); signatureOptions.setPage(pageNumber); doc.addSignature(signature, instance, signatureOptions); diff --git a/src/main/java/stirling/software/SPDF/model/api/security/SignPDFWithCertRequest.java b/src/main/java/stirling/software/SPDF/model/api/security/SignPDFWithCertRequest.java index d3399db9..6949a95e 100644 --- a/src/main/java/stirling/software/SPDF/model/api/security/SignPDFWithCertRequest.java +++ b/src/main/java/stirling/software/SPDF/model/api/security/SignPDFWithCertRequest.java @@ -50,4 +50,7 @@ public class SignPDFWithCertRequest extends PDFFile { description = "The page number where the signature should be visible. This is required if showSignature is set to true") private Integer pageNumber; + + @Schema(description = "Whether to visually show a signature logo along with the signature") + private boolean showLogo; } diff --git a/src/main/resources/messages_en_GB.properties b/src/main/resources/messages_en_GB.properties index 019930d8..f124bec8 100644 --- a/src/main/resources/messages_en_GB.properties +++ b/src/main/resources/messages_en_GB.properties @@ -750,6 +750,7 @@ certSign.showSig=Show Signature certSign.reason=Reason certSign.location=Location certSign.name=Name +certSign.showLogo=Show Logo certSign.submit=Sign PDF diff --git a/src/main/resources/messages_en_US.properties b/src/main/resources/messages_en_US.properties index bfb5d8e7..2da78640 100644 --- a/src/main/resources/messages_en_US.properties +++ b/src/main/resources/messages_en_US.properties @@ -750,6 +750,7 @@ certSign.showSig=Show Signature certSign.reason=Reason certSign.location=Location certSign.name=Name +certSign.showLogo=Show Logo certSign.submit=Sign PDF diff --git a/src/main/resources/templates/security/cert-sign.html b/src/main/resources/templates/security/cert-sign.html index ab9a755a..e69c4fa1 100644 --- a/src/main/resources/templates/security/cert-sign.html +++ b/src/main/resources/templates/security/cert-sign.html @@ -71,7 +71,11 @@