You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ti...@apache.org on 2019/07/27 09:19:34 UTC

svn commit: r1863845 - in /pdfbox/branches/issue4569/preflight/src/main/java/org/apache/pdfbox/preflight: graphic/StandardColorSpaceHelper.java process/CatalogValidationProcess.java

Author: tilman
Date: Sat Jul 27 09:19:33 2019
New Revision: 1863845

URL: http://svn.apache.org/viewvc?rev=1863845&view=rev
Log:
PDFBOX-4611: combine ICC checking code from two classes so that both gets the deepest check

Modified:
    pdfbox/branches/issue4569/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/StandardColorSpaceHelper.java
    pdfbox/branches/issue4569/preflight/src/main/java/org/apache/pdfbox/preflight/process/CatalogValidationProcess.java

Modified: pdfbox/branches/issue4569/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/StandardColorSpaceHelper.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/issue4569/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/StandardColorSpaceHelper.java?rev=1863845&r1=1863844&r2=1863845&view=diff
==============================================================================
--- pdfbox/branches/issue4569/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/StandardColorSpaceHelper.java (original)
+++ pdfbox/branches/issue4569/preflight/src/main/java/org/apache/pdfbox/preflight/graphic/StandardColorSpaceHelper.java Sat Jul 27 09:19:33 2019
@@ -28,7 +28,10 @@ import java.util.Map;
 
 import org.apache.pdfbox.cos.COSArray;
 import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSNumber;
+import org.apache.pdfbox.cos.COSStream;
 import org.apache.pdfbox.pdmodel.PDResources;
 import org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace;
 import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceN;
@@ -37,6 +40,7 @@ import org.apache.pdfbox.pdmodel.graphic
 import org.apache.pdfbox.pdmodel.graphics.color.PDICCBased;
 import org.apache.pdfbox.pdmodel.graphics.color.PDIndexed;
 import org.apache.pdfbox.pdmodel.graphics.color.PDSeparation;
+import org.apache.pdfbox.preflight.PreflightConfiguration;
 import org.apache.pdfbox.preflight.PreflightContext;
 import org.apache.pdfbox.preflight.PreflightPath;
 import org.apache.pdfbox.preflight.ValidationResult.ValidationError;
@@ -52,6 +56,8 @@ import static org.apache.pdfbox.prefligh
 import static org.apache.pdfbox.preflight.PreflightConstants.ERROR_GRAPHIC_INVALID_COLOR_SPACE_TOO_MANY_COMPONENTS_DEVICEN;
 import static org.apache.pdfbox.preflight.PreflightConstants.ERROR_GRAPHIC_INVALID_PATTERN_COLOR_SPACE_FORBIDDEN;
 import static org.apache.pdfbox.preflight.PreflightConstants.ERROR_GRAPHIC_INVALID_UNKNOWN_COLOR_SPACE;
+import static org.apache.pdfbox.preflight.PreflightConstants.ERROR_GRAPHIC_OUTPUT_INTENT_ICC_PROFILE_TOO_RECENT;
+import static org.apache.pdfbox.preflight.PreflightConstants.ERROR_GRAPHIC_OUTPUT_INTENT_INVALID_ENTRY;
 import static org.apache.pdfbox.preflight.PreflightConstants.MAX_DEVICE_N_LIMIT;
 
 /**
@@ -237,11 +243,12 @@ public class StandardColorSpaceHelper im
         PDICCBased iccBased = (PDICCBased) colorSpace;
         try
         {
+            ICC_Profile iccp;
             try (InputStream is = iccBased.getPDStream().createInputStream())
             {
                 // check that ICC profile loads (PDICCBased also does this, but catches the exception)
                 // PDFBOX-2819: load ICC profile as a stream, not as a byte array because of java error
-                ICC_Profile.getInstance(is);
+                iccp = ICC_Profile.getInstance(is);
             }
             PDColorSpace altpdcs = iccBased.getAlternateColorSpace();
             if (altpdcs != null)
@@ -262,8 +269,19 @@ public class StandardColorSpaceHelper im
                  * 
                  * We don't check the alternate ColorSpaces
                  */
+                // PDFBOX-4611, PDFBOX-4607: Yes we do because Adobe Reader chokes on it
+                // and because VeraPDF and PDF-Tools do it.
+                if (!validateICCProfileNEntry(iccBased.getPDStream().getCOSObject(), iccp))
+                {
+                    return;
+                }
+                if (!validateICCProfileVersion(iccp))
+                {
+                    return;
+                }
+                validateICCProfileAlternateEntry(iccBased);
             }
-        }        
+        }
         catch (IllegalArgumentException e)
         {
             // this is not a ICC_Profile
@@ -460,4 +478,85 @@ public class StandardColorSpaceHelper im
 
         return result;
     }
+
+    private boolean validateICCProfileVersion(ICC_Profile iccp)
+    {
+        PreflightConfiguration config = context.getConfig();
+
+        // check the ICC Profile version (6.2.2)
+        if (iccp.getMajorVersion() == 2)
+        {
+            if (iccp.getMinorVersion() > 0x40)
+            {
+                // in PDF 1.4, max version is 02h.40h (meaning V 3.5)
+                // see the ICCProfile specification (ICC.1:1998-09)page 13 - §6.1.3 :
+                // The current profile version number is "2.4.0" (encoded as 02400000h")
+                ValidationError error = new ValidationError(ERROR_GRAPHIC_OUTPUT_INTENT_ICC_PROFILE_TOO_RECENT,
+                        "Invalid version of the ICCProfile");
+                error.setWarning(config.isLazyValidation());
+                context.addValidationError(error);
+                return false;
+            }
+            // else OK
+        }
+        else if (iccp.getMajorVersion() > 2)
+        {
+            // in PDF 1.4, max version is 02h.40h (meaning V 3.5)
+            // see the ICCProfile specification (ICC.1:1998-09)page 13 - §6.1.3 :
+            // The current profile version number is "2.4.0" (encoded as 02400000h"
+            ValidationError error = new ValidationError(ERROR_GRAPHIC_OUTPUT_INTENT_ICC_PROFILE_TOO_RECENT,
+                    "Invalid version of the ICCProfile");
+            error.setWarning(config.isLazyValidation());
+            context.addValidationError(error);
+            return false;
+        }
+        // else seems less than 2, so correct
+        return true;
+    }
+
+    private boolean validateICCProfileNEntry(COSStream stream, ICC_Profile iccp)
+            throws IOException
+    {
+        COSDictionary streamDict = (COSDictionary) stream.getCOSObject();
+        if (!streamDict.containsKey(COSName.N))
+        {
+            context.addValidationError(new ValidationError(ERROR_GRAPHIC_OUTPUT_INTENT_INVALID_ENTRY,
+                    "/N entry of ICC profile is mandatory"));
+            return false;
+        }
+        COSBase nValue = streamDict.getItem(COSName.N);
+        if (!(nValue instanceof COSNumber))
+        {
+            context.addValidationError(new ValidationError(ERROR_GRAPHIC_OUTPUT_INTENT_INVALID_ENTRY,
+                    "/N entry of ICC profile must be a number, but is " + nValue));
+            return false;
+        }
+        int nNumberValue = ((COSNumber) nValue).intValue();
+        if (nNumberValue != 1 && nNumberValue != 3 && nNumberValue != 4)
+        {
+            context.addValidationError(new ValidationError(ERROR_GRAPHIC_OUTPUT_INTENT_INVALID_ENTRY,
+                    "/N entry of ICC profile must be 1, 3 or 4, but is " + nNumberValue));
+            return false;
+        }
+        if (iccp.getNumComponents() != nNumberValue)
+        {
+            context.addValidationError(new ValidationError(ERROR_GRAPHIC_OUTPUT_INTENT_INVALID_ENTRY,
+                    "/N entry of ICC profile is " + nNumberValue + " but the ICC profile has " + iccp.getNumComponents() + " components"));
+            return false;
+        }
+        return true;
+    }
+
+    private void validateICCProfileAlternateEntry(PDICCBased iccBased) throws IOException
+    {
+        PDColorSpace altCS = iccBased.getAlternateColorSpace();
+        if (altCS != null && altCS.getNumberOfComponents() != iccBased.getNumberOfComponents())
+        {
+            // https://github.com/veraPDF/veraPDF-library/issues/773
+            context.addValidationError(new ValidationError(ERROR_GRAPHIC_OUTPUT_INTENT_INVALID_ENTRY,
+                    "/N entry of ICC profile is different (" + iccBased.getNumberOfComponents()
+                    + ") than alternate entry colorspace component count ("
+                    + altCS.getNumberOfComponents() + ")"));
+        }
+    }
 }

Modified: pdfbox/branches/issue4569/preflight/src/main/java/org/apache/pdfbox/preflight/process/CatalogValidationProcess.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/issue4569/preflight/src/main/java/org/apache/pdfbox/preflight/process/CatalogValidationProcess.java?rev=1863845&r1=1863844&r2=1863845&view=diff
==============================================================================
--- pdfbox/branches/issue4569/preflight/src/main/java/org/apache/pdfbox/preflight/process/CatalogValidationProcess.java (original)
+++ pdfbox/branches/issue4569/preflight/src/main/java/org/apache/pdfbox/preflight/process/CatalogValidationProcess.java Sat Jul 27 09:19:33 2019
@@ -32,7 +32,6 @@ import org.apache.pdfbox.cos.COSArray;
 import org.apache.pdfbox.cos.COSBase;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.cos.COSName;
-import org.apache.pdfbox.cos.COSNumber;
 import org.apache.pdfbox.cos.COSObject;
 import org.apache.pdfbox.cos.COSObjectKey;
 import org.apache.pdfbox.cos.COSStream;
@@ -40,19 +39,19 @@ import org.apache.pdfbox.pdmodel.PDDocum
 import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
 import org.apache.pdfbox.pdmodel.PDDocumentNameDictionary;
 import org.apache.pdfbox.pdmodel.PDEmbeddedFilesNameTreeNode;
-import org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace;
 import org.apache.pdfbox.pdmodel.graphics.color.PDICCBased;
 import org.apache.pdfbox.preflight.PreflightConfiguration;
+import static org.apache.pdfbox.preflight.PreflightConfiguration.ACTIONS_PROCESS;
+import static org.apache.pdfbox.preflight.PreflightConstants.*;
 import org.apache.pdfbox.preflight.PreflightContext;
 import org.apache.pdfbox.preflight.ValidationResult.ValidationError;
 import org.apache.pdfbox.preflight.exception.ValidationException;
+import org.apache.pdfbox.preflight.graphic.ColorSpaceHelper;
+import org.apache.pdfbox.preflight.graphic.ColorSpaceHelperFactory;
+import org.apache.pdfbox.preflight.graphic.ColorSpaceHelperFactory.ColorSpaceRestriction;
 import org.apache.pdfbox.preflight.graphic.ICCProfileWrapper;
 import org.apache.pdfbox.preflight.utils.ContextHelper;
 
-
-import static org.apache.pdfbox.preflight.PreflightConfiguration.ACTIONS_PROCESS;
-import static org.apache.pdfbox.preflight.PreflightConstants.*;
-
 /**
  * This ValidationProcess check if the Catalog entries are confirming with the PDF/A-1b specification.
  */
@@ -338,7 +337,7 @@ public class CatalogValidationProcess ex
                 {
                     // A DestOutputProfile exits but it isn't the same, error
                     addValidationError(ctx, new ValidationError(ERROR_GRAPHIC_OUTPUT_INTENT_ICC_PROFILE_MULTIPLE,
-                            "More than one ICCProfile is defined"));
+                            "More than one ICCProfile is defined: " + destOutputProfile));
                     return;
                 }
                 // else the profile will be kept in the mapDestOutputProfile if it is valid
@@ -357,23 +356,22 @@ public class CatalogValidationProcess ex
             }
             COSStream stream = (COSStream) localDestOutputProfile;
 
-            ICC_Profile iccp;
-            try (InputStream is = stream.createInputStream())
-            {
-                iccp = ICC_Profile.getInstance(is);
-            }
+            COSArray array = new COSArray();
+            array.add(COSName.ICCBASED);
+            array.add(stream);
+            PDICCBased iccBased = PDICCBased.create(array, null);
+            PreflightConfiguration cfg = ctx.getConfig();
+            ColorSpaceHelperFactory csFact = cfg.getColorSpaceHelperFact();
+            ColorSpaceHelper csHelper =
+                    csFact.getColorSpaceHelper(ctx, iccBased, ColorSpaceRestriction.NO_RESTRICTION);
+            csHelper.validate();
 
-            if (!validateICCProfileNEntry(stream, ctx, iccp))
-            {
-                return;
-            }
-            if (!validateICCProfileVersion(iccp, ctx))
-            {
-                return;
-            }
             if (ctx.getIccProfileWrapper() == null)
             {
-                ctx.setIccProfileWrapper(new ICCProfileWrapper(iccp));
+                try (InputStream is = stream.createInputStream())
+                {
+                    ctx.setIccProfileWrapper(new ICCProfileWrapper(ICC_Profile.getInstance(is)));
+                }
             }
         }
         catch (IllegalArgumentException e)
@@ -387,90 +385,4 @@ public class CatalogValidationProcess ex
             throw new ValidationException("Unable to parse the ICC Profile.", e);
         }
     }
-
-    private boolean validateICCProfileVersion(ICC_Profile iccp, PreflightContext ctx)
-    {
-        PreflightConfiguration config = ctx.getConfig();
-
-        // check the ICC Profile version (6.2.2)
-        if (iccp.getMajorVersion() == 2)
-        {
-            if (iccp.getMinorVersion() > 0x40)
-            {
-                // in PDF 1.4, max version is 02h.40h (meaning V 3.5)
-                // see the ICCProfile specification (ICC.1:1998-09)page 13 - §6.1.3 :
-                // The current profile version number is "2.4.0" (encoded as 02400000h")
-                ValidationError error = new ValidationError(ERROR_GRAPHIC_OUTPUT_INTENT_ICC_PROFILE_TOO_RECENT,
-                        "Invalid version of the ICCProfile");
-                error.setWarning(config.isLazyValidation());
-                addValidationError(ctx, error);
-                return false;
-            }
-            // else OK
-        }
-        else if (iccp.getMajorVersion() > 2)
-        {
-            // in PDF 1.4, max version is 02h.40h (meaning V 3.5)
-            // see the ICCProfile specification (ICC.1:1998-09)page 13 - §6.1.3 :
-            // The current profile version number is "2.4.0" (encoded as 02400000h"
-            ValidationError error = new ValidationError(ERROR_GRAPHIC_OUTPUT_INTENT_ICC_PROFILE_TOO_RECENT,
-                    "Invalid version of the ICCProfile");
-            error.setWarning(config.isLazyValidation());
-            addValidationError(ctx, error);
-            return false;
-        }
-        // else seems less than 2, so correct
-        return true;
-    }
-
-    private boolean validateICCProfileNEntry(COSStream stream, PreflightContext ctx, ICC_Profile iccp)
-            throws IOException
-    {
-        COSDictionary streamDict = (COSDictionary) stream.getCOSObject();
-        if (!streamDict.containsKey(COSName.N))
-        {
-            addValidationError(ctx, new ValidationError(ERROR_GRAPHIC_OUTPUT_INTENT_INVALID_ENTRY,
-                    "/N entry of ICC profile is mandatory"));
-            return false;
-        }
-        COSBase nValue = streamDict.getItem(COSName.N);
-        if (!(nValue instanceof COSNumber))
-        {
-            addValidationError(ctx, new ValidationError(ERROR_GRAPHIC_OUTPUT_INTENT_INVALID_ENTRY,
-                    "/N entry of ICC profile must be a number, but is " + nValue));
-            return false;
-        }
-        int nNumberValue = ((COSNumber) nValue).intValue();
-        if (nNumberValue != 1 && nNumberValue != 3 && nNumberValue != 4)
-        {
-            addValidationError(ctx, new ValidationError(ERROR_GRAPHIC_OUTPUT_INTENT_INVALID_ENTRY,
-                    "/N entry of ICC profile must be 1, 3 or 4, but is " + nNumberValue));
-            return false;
-        }
-        if (iccp.getNumComponents() != nNumberValue)
-        {
-            addValidationError(ctx, new ValidationError(ERROR_GRAPHIC_OUTPUT_INTENT_INVALID_ENTRY,
-                    "/N entry of ICC profile is " + nNumberValue + " but the ICC profile has " + iccp.getNumComponents() + " components"));
-            return false;
-        }
-        validateICCProfileAlternateEntry(stream, ctx);
-        return true;
-    }
-
-    private void validateICCProfileAlternateEntry(COSStream stream, PreflightContext ctx) throws IOException
-    {
-        COSArray array = new COSArray();
-        array.add(COSName.ICCBASED);
-        array.add(stream);
-        PDICCBased iccBased = PDICCBased.create(array, null);
-        PDColorSpace altCS = iccBased.getAlternateColorSpace();
-        if (altCS != null && altCS.getNumberOfComponents() != iccBased.getNumberOfComponents())
-        {
-            // https://github.com/veraPDF/veraPDF-library/issues/773
-            addValidationError(ctx, new ValidationError(ERROR_GRAPHIC_OUTPUT_INTENT_INVALID_ENTRY,
-                    "/N entry of ICC profile is different (" + iccBased.getNumberOfComponents()
-                    + ") than alternate entry colorspace component count ("
-                    + altCS.getNumberOfComponents() + ")"));
-        }
-    }
-}
\ No newline at end of file
+}