This is an automated email from the ASF dual-hosted git repository.

tallison pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tika.git


The following commit(s) were added to refs/heads/main by this push:
     new 94c681223 TIKA-3852 -- extract signature info at the document level 
from PDFs
94c681223 is described below

commit 94c6812232a85c4a8dd24ba393055f58e7436fca
Author: tballison <[email protected]>
AuthorDate: Tue Sep 13 11:51:10 2022 -0400

    TIKA-3852 -- extract signature info at the document level from PDFs
---
 .../java/org/apache/tika/metadata/Metadata.java    | 19 ++++++++
 .../java/org/apache/tika/metadata/Property.java    |  4 ++
 .../apache/tika/metadata/TikaCoreProperties.java   |  6 +++
 .../tika-parser-pdf-module/pom.xml                 | 17 +++++++
 .../java/org/apache/tika/parser/pdf/PDFParser.java | 35 ++++++++++++++
 .../tika/parser/pdf/PDMetadataExtractor.java       |  6 +++
 .../org/apache/tika/parser/pdf/PDFParserTest.java  | 56 ++++++++++++----------
 .../src/test/resources/log4j2.xml                  | 42 ++++++++++++++++
 8 files changed, 159 insertions(+), 26 deletions(-)

diff --git a/tika-core/src/main/java/org/apache/tika/metadata/Metadata.java 
b/tika-core/src/main/java/org/apache/tika/metadata/Metadata.java
index 98de6d282..1614f8cca 100644
--- a/tika-core/src/main/java/org/apache/tika/metadata/Metadata.java
+++ b/tika-core/src/main/java/org/apache/tika/metadata/Metadata.java
@@ -590,6 +590,25 @@ public class Metadata
         set(property, dateString);
     }
 
+    /**
+     * Adds the date value of the identified metadata property.
+     *
+     * @param property simple calendar property definition
+     * @param date     property value
+     * @since Apache Tika 2.5.0
+     */
+    public void add(Property property, Calendar date) {
+        if (property.getPrimaryProperty().getValueType() != 
Property.ValueType.DATE) {
+            throw new PropertyTypeException(Property.ValueType.DATE,
+                    property.getPrimaryProperty().getValueType());
+        }
+        String dateString = null;
+        if (date != null) {
+            dateString = formatDate(date);
+        }
+        add(property, dateString);
+    }
+
     /**
      * Remove a metadata and all its associated values.
      *
diff --git a/tika-core/src/main/java/org/apache/tika/metadata/Property.java 
b/tika-core/src/main/java/org/apache/tika/metadata/Property.java
index 93614b72b..3d6714141 100644
--- a/tika-core/src/main/java/org/apache/tika/metadata/Property.java
+++ b/tika-core/src/main/java/org/apache/tika/metadata/Property.java
@@ -144,6 +144,10 @@ public final class Property implements 
Comparable<Property> {
         return new Property(name, true, ValueType.DATE);
     }
 
+    public static Property internalDateBag(String name) {
+        return new Property(name, true, PropertyType.BAG, ValueType.DATE);
+    }
+
     public static Property internalInteger(String name) {
         return new Property(name, true, ValueType.INTEGER);
     }
diff --git 
a/tika-core/src/main/java/org/apache/tika/metadata/TikaCoreProperties.java 
b/tika-core/src/main/java/org/apache/tika/metadata/TikaCoreProperties.java
index 79d80d658..03a0e2cd2 100644
--- a/tika-core/src/main/java/org/apache/tika/metadata/TikaCoreProperties.java
+++ b/tika-core/src/main/java/org/apache/tika/metadata/TikaCoreProperties.java
@@ -284,6 +284,12 @@ public interface TikaCoreProperties {
             EmbeddedResourceType.THUMBNAIL.toString(), 
EmbeddedResourceType.RENDERING.toString());
     Property HAS_SIGNATURE = Property.internalBoolean("hasSignature");
 
+    Property SIGNATURE_NAME = Property.internalTextBag("signature:name");
+    Property SIGNATURE_DATE = Property.internalDateBag("signature:date");
+    Property SIGNATURE_LOCATION = 
Property.internalTextBag("signature:location");
+    Property SIGNATURE_REASON = Property.internalTextBag("signature:reason");
+    Property SIGNATURE_FILTER = Property.internalTextBag("signature:filter");
+    Property SIGNATURE_CONTACT_INFO = 
Property.internalTextBag("signature:contact-info");
 
     /**
      * A file might contain different types of embedded documents.
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/pom.xml
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/pom.xml
index fc655e0b9..4d8470026 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/pom.xml
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/pom.xml
@@ -80,6 +80,23 @@
       <artifactId>jaxb-runtime</artifactId>
       <version>${jaxb.version}</version>
     </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-core</artifactId>
+      <version>${log4j2.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-slf4j-impl</artifactId>
+      <version>${log4j2.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>jcl-over-slf4j</artifactId>
+      <scope>test</scope>
+    </dependency>
     <!-- incompatible with Apache license, only use in testing -->
     <dependency>
       <groupId>com.github.jai-imageio</groupId>
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/PDFParser.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/PDFParser.java
index e790378ae..94afd30db 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/PDFParser.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/PDFParser.java
@@ -42,7 +42,9 @@ import 
org.apache.pdfbox.pdmodel.encryption.InvalidPasswordException;
 import org.apache.pdfbox.pdmodel.fixup.AbstractFixup;
 import org.apache.pdfbox.pdmodel.fixup.PDDocumentFixup;
 import org.apache.pdfbox.pdmodel.fixup.processor.AcroFormDefaultsProcessor;
+import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
 import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
+import org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 
@@ -178,6 +180,7 @@ public class PDFParser extends AbstractParser implements 
RenderingParser, Initia
             boolean hasXFA = hasXFA(pdfDocument, metadata);
             boolean hasMarkedContent = hasMarkedContent(pdfDocument, metadata);
             extractMetadata(pdfDocument, metadata, context);
+            extractSignatures(pdfDocument, metadata);
             AccessChecker checker = localConfig.getAccessChecker();
             checker.check(metadata);
             renderPagesBeforeParse(tstream, handler, metadata, context, 
localConfig);
@@ -218,6 +221,38 @@ public class PDFParser extends AbstractParser implements 
RenderingParser, Initia
             }
         }
     }
+    private void extractSignatures(PDDocument pdfDocument, Metadata metadata) {
+        boolean hasSignature = false;
+        try {
+            for (PDSignatureField signatureField : 
pdfDocument.getSignatureFields()) {
+                PDSignature signature = signatureField.getSignature();
+                if (signature == null) {
+                    continue;
+                }
+                
PDMetadataExtractor.addNotNull(TikaCoreProperties.SIGNATURE_NAME,
+                        signature.getName(), metadata);
+
+                Calendar date = signature.getSignDate();
+                if (date != null) {
+                    metadata.add(TikaCoreProperties.SIGNATURE_DATE, date);
+                }
+                
PDMetadataExtractor.addNotNull(TikaCoreProperties.SIGNATURE_CONTACT_INFO,
+                        signature.getContactInfo(), metadata);
+                
PDMetadataExtractor.addNotNull(TikaCoreProperties.SIGNATURE_FILTER,
+                        signature.getFilter(), metadata);
+                
PDMetadataExtractor.addNotNull(TikaCoreProperties.SIGNATURE_LOCATION,
+                        signature.getLocation(), metadata);
+                
PDMetadataExtractor.addNotNull(TikaCoreProperties.SIGNATURE_REASON,
+                        signature.getReason(), metadata);
+                hasSignature = true;
+            }
+        } catch (IOException e) {
+            //swallow
+        }
+        if (hasSignature) {
+            metadata.set(TikaCoreProperties.HAS_SIGNATURE, hasSignature);
+        }
+    }
 
     private boolean shouldSpool(PDFParserConfig localConfig) {
         if (localConfig.getImageStrategy() == 
PDFParserConfig.IMAGE_STRATEGY.RENDER_PAGES_BEFORE_PARSE
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/PDMetadataExtractor.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/PDMetadataExtractor.java
index 34beb3f77..cb36de0a9 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/PDMetadataExtractor.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/PDMetadataExtractor.java
@@ -309,6 +309,12 @@ public class PDMetadataExtractor {
         }
     }
 
+    static void addNotNull(Property property, String value, Metadata metadata) 
{
+        if (! StringUtils.isBlank(value)) {
+            metadata.add(property, value);
+        }
+    }
+
     /**
      * As of this writing, XMPSchema can contain bags or sequence lists
      * for some attributes...despite standards documentation.
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/test/java/org/apache/tika/parser/pdf/PDFParserTest.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/test/java/org/apache/tika/parser/pdf/PDFParserTest.java
index e554a784a..585feb02c 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/test/java/org/apache/tika/parser/pdf/PDFParserTest.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/test/java/org/apache/tika/parser/pdf/PDFParserTest.java
@@ -1390,32 +1390,36 @@ public class PDFParserTest extends TikaTest {
         }
     }
 
-            /**
-            @Test
-            public void testWriteLimit() throws Exception {
-                for (int i = 0; i < 10000; i += 13) {
-                    Metadata metadata = 
testWriteLimit("testPDF_childAttachments.pdf", i);
-                    assertEquals("true", 
metadata.get(TikaCoreProperties.WRITE_LIMIT_REACHED));
-                    int len = 
metadata.get(TikaCoreProperties.TIKA_CONTENT).length();
-                    System.out.println(len + " : " + i);
-                    assertTrue(len <= i);
-                }
-            }
+    /**
+     * TODO -- need to test signature extraction
+     */
 
-            private Metadata testWriteLimit(String fileName, int limit) throws 
Exception {
-                BasicContentHandlerFactory factory = new 
BasicContentHandlerFactory(
-                        BasicContentHandlerFactory.HANDLER_TYPE.TEXT, limit
-                );
-                ContentHandler contentHandler = factory.getNewContentHandler();
-                Metadata metadata = new Metadata();
-                ParseContext parseContext = new ParseContext();
-                try (InputStream is = getResourceAsStream("/test-documents/" + 
fileName)) {
-                    AUTO_DETECT_PARSER.parse(is, contentHandler, metadata, 
parseContext);
-                } catch (WriteLimitReachedException e) {
-                    //e.printStackTrace();
-                }
-                metadata.set(TikaCoreProperties.TIKA_CONTENT, 
contentHandler.toString());
-                return metadata;
-            }*/
+    /**
+    @Test
+    public void testWriteLimit() throws Exception {
+        for (int i = 0; i < 10000; i += 13) {
+            Metadata metadata = testWriteLimit("testPDF_childAttachments.pdf", 
i);
+            assertEquals("true", 
metadata.get(TikaCoreProperties.WRITE_LIMIT_REACHED));
+            int len = metadata.get(TikaCoreProperties.TIKA_CONTENT).length();
+            System.out.println(len + " : " + i);
+            assertTrue(len <= i);
+        }
+    }
+
+    private Metadata testWriteLimit(String fileName, int limit) throws 
Exception {
+        BasicContentHandlerFactory factory = new BasicContentHandlerFactory(
+                BasicContentHandlerFactory.HANDLER_TYPE.TEXT, limit
+        );
+        ContentHandler contentHandler = factory.getNewContentHandler();
+        Metadata metadata = new Metadata();
+        ParseContext parseContext = new ParseContext();
+        try (InputStream is = getResourceAsStream("/test-documents/" + 
fileName)) {
+            AUTO_DETECT_PARSER.parse(is, contentHandler, metadata, 
parseContext);
+        } catch (WriteLimitReachedException e) {
+            //e.printStackTrace();
+        }
+        metadata.set(TikaCoreProperties.TIKA_CONTENT, 
contentHandler.toString());
+        return metadata;
+    }*/
 
 }
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/test/resources/log4j2.xml
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/test/resources/log4j2.xml
new file mode 100644
index 000000000..6f4371a49
--- /dev/null
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/test/resources/log4j2.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<Configuration status="WARN">
+  <Appenders>
+    <Console name="Console" target="SYSTEM_ERR">
+      <PatternLayout pattern="%-5p [%t] %d{HH:mm:ss,SSS} %c %m%n"/>
+    </Console>
+
+    <File name="pdfbox-appender" 
fileName="logs/pdfbox-${sys:pipesClientId}.log">
+      <PatternLayout pattern="%-5p [%t] %d{HH:mm:ss,SSS} %c %m%n"/>
+    </File>
+  </Appenders>
+  <Loggers>
+    <Root level="info">
+      <AppenderRef ref="Console"/>
+    </Root>
+    <Logger name="org.apache.fontbox" level="ERROR" additivity="false">
+      <AppenderRef ref="pdfbox-appender"/>
+    </Logger>
+    <Logger name="org.apache.pdfbox" level="ERROR" additivity="false">
+      <AppenderRef ref="pdfbox-appender"/>
+    </Logger>
+  </Loggers>
+</Configuration>
\ No newline at end of file

Reply via email to