You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by gb...@apache.org on 2013/03/06 17:46:37 UTC
svn commit: r1453416 [5/16] - in /pdfbox/trunk/preflight: ./
src/main/java/org/apache/pdfbox/preflight/
src/main/java/org/apache/pdfbox/preflight/action/
src/main/java/org/apache/pdfbox/preflight/annotation/
src/main/java/org/apache/pdfbox/preflight/an...
Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamEngine.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamEngine.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamEngine.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamEngine.java Wed Mar 6 16:46:35 2013
@@ -92,471 +92,531 @@ import org.apache.pdfbox.util.operator.S
import org.apache.pdfbox.util.operator.SetTextRenderingMode;
import org.apache.pdfbox.util.operator.SetTextRise;
import org.apache.pdfbox.util.operator.SetWordSpacing;
+
/**
- * This class inherits from org.apache.pdfbox.util.PDFStreamEngine to allow the
- * validation of specific rules in ContentStream.
+ * This class inherits from org.apache.pdfbox.util.PDFStreamEngine to allow the validation of specific rules in
+ * ContentStream.
*/
-public abstract class ContentStreamEngine extends PDFStreamEngine {
+public abstract class ContentStreamEngine extends PDFStreamEngine
+{
- private enum ColorSpaceType {
- RGB,
- CMYK,
- ALL;
- }
-
- protected PreflightContext context = null;
-
- protected COSDocument cosDocument = null;
-
- protected PDPage processeedPage = null;
-
- protected Map<String,OperatorProcessor> contentStreamEngineOperators = new HashMap<String,OperatorProcessor>();
-
- public ContentStreamEngine(PreflightContext _context, PDPage _page) {
- super();
- this.context = _context;
- this.cosDocument = _context.getDocument().getDocument();
- this.processeedPage = _page;
-
- // Graphics operators
- registerOperatorProcessor("w", new SetLineWidth());
- registerOperatorProcessor("cm", new Concatenate());
-
- registerOperatorProcessor("CS", new SetStrokingColorSpace());
- registerOperatorProcessor("cs", new SetNonStrokingColorSpace());
- registerOperatorProcessor("d", new SetLineDashPattern());
- registerOperatorProcessor("Do", new Invoke());
-
- registerOperatorProcessor("j", new SetLineJoinStyle());
- registerOperatorProcessor("J", new SetLineCapStyle());
- registerOperatorProcessor("K", new SetStrokingCMYKColor());
- registerOperatorProcessor("k", new SetNonStrokingCMYKColor());
-
- registerOperatorProcessor("rg", new SetNonStrokingRGBColor());
- registerOperatorProcessor("RG", new SetStrokingRGBColor());
-
- registerOperatorProcessor("SC", new SetStrokingColor());
- registerOperatorProcessor("SCN", new SetStrokingColor());
- registerOperatorProcessor("sc", new SetNonStrokingColor());
- registerOperatorProcessor("scn", new SetNonStrokingColor());
-
- // Graphics state
- registerOperatorProcessor("Q", new GRestore());
- registerOperatorProcessor("q", new GSave());
-
- // Text operators
- registerOperatorProcessor("BT", new BeginText());
- registerOperatorProcessor("ET", new EndText());
- registerOperatorProcessor("Tf", new SetTextFont());
- registerOperatorProcessor("Tr", new SetTextRenderingMode());
- registerOperatorProcessor("Tm", new SetMatrix());
- registerOperatorProcessor("Td", new MoveText());
- registerOperatorProcessor("T*", new NextLine());
- registerOperatorProcessor("TD", new MoveTextSetLeading());
- registerOperatorProcessor("Tc", new SetCharSpacing());
- registerOperatorProcessor("TL", new SetTextLeading());
- registerOperatorProcessor("Ts", new SetTextRise());
- registerOperatorProcessor("Tw", new SetWordSpacing());
- registerOperatorProcessor("Tz", new SetHorizontalTextScaling());
-
- /* Do not use the PDFBox Operator, because of the PageDrawer class cast
- * Or because the Operator doesn't exist
- */
- StubOperator stubOp = new StubOperator();
- registerOperatorProcessor("l", stubOp);
- registerOperatorProcessor("re", stubOp);
- registerOperatorProcessor("c", stubOp);
- registerOperatorProcessor("y", stubOp);
- registerOperatorProcessor("v", stubOp);
- registerOperatorProcessor("n", stubOp);
- registerOperatorProcessor("BI", stubOp);
- registerOperatorProcessor("EI", stubOp);
- registerOperatorProcessor("m", stubOp);
- registerOperatorProcessor("W*", stubOp);
- registerOperatorProcessor("W", stubOp);
- registerOperatorProcessor("h", stubOp);
-
- registerOperatorProcessor("Tj", stubOp);
- registerOperatorProcessor("TJ", stubOp);
- registerOperatorProcessor("'", stubOp);
- registerOperatorProcessor("\"", stubOp);
-
- registerOperatorProcessor("b", stubOp);
- registerOperatorProcessor("B", stubOp);
- registerOperatorProcessor("b*", stubOp);
- registerOperatorProcessor("B*", stubOp);
-
- registerOperatorProcessor("BDC", stubOp);
- registerOperatorProcessor("BMC", stubOp);
- registerOperatorProcessor("DP", stubOp);
- registerOperatorProcessor("EMC", stubOp);
-
- registerOperatorProcessor("d0", stubOp);
- registerOperatorProcessor("d1", stubOp);
-
- registerOperatorProcessor("f", stubOp);
- registerOperatorProcessor("F", stubOp);
- registerOperatorProcessor("f*", stubOp);
-
- registerOperatorProcessor("g", stubOp);
- registerOperatorProcessor("G", stubOp);
-
- registerOperatorProcessor("M", stubOp);
- registerOperatorProcessor("MP", stubOp);
-
- registerOperatorProcessor("gs", stubOp);
- registerOperatorProcessor("h", stubOp);
- registerOperatorProcessor("i", stubOp);
-
- registerOperatorProcessor("ri", stubOp);
- registerOperatorProcessor("s", stubOp);
- registerOperatorProcessor("S", stubOp);
- registerOperatorProcessor("sh", stubOp);
- }
-
- public final void registerOperatorProcessor( String operator, OperatorProcessor op )
- {
- super.registerOperatorProcessor(operator, op);
- contentStreamEngineOperators.put( operator, op );
- }
-
-
- /**
- * Check operands of the "ri" operator. Operands must exist in the
- * RenderingIntent list. (net.awl.edoc.pdfa.validation.utils.RenderingIntents)
- *
- * @param operator
- * the "ri" operator
- * @param arguments
- * the "ri" operands
- * @throws ContentStreamException
- * ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY if the operand is invalid
- */
- protected void validRenderingIntent(PDFOperator operator, List arguments)
- throws ContentStreamException {
- if ("ri".equals(operator.getOperation())) {
- String riArgument0 = "";
- if (arguments.get(0) instanceof COSName) {
- riArgument0 = ((COSName)arguments.get(0)).getName();
- } else if (arguments.get(0) instanceof String) {
- riArgument0 = (String)arguments.get(0);
- }
-
- if (!RenderingIntents.contains(riArgument0)) {
- registerError("Unexpected value '" + arguments.get(0)
- + "' for ri operand. ", ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY);
- return;
- }
- }
- }
-
- /**
- * Valid the number of graphic states if the operator is the Save Graphic state operator ("q")
- * @param operator
- * @throws ContentStreamException
- */
- protected void validNumberOfGraphicStates(PDFOperator operator) throws ContentStreamException {
- if ("q".equals(operator.getOperation())) {
- int numberOfGraphicStates = this.getGraphicsStack().size();
- if (numberOfGraphicStates > MAX_GRAPHIC_STATES) {
- registerError("Too many graphic states", ERROR_GRAPHIC_TOO_MANY_GRAPHIC_STATES);
- return;
- }
- }
- }
-
- /**
- * Throw a ContentStreamException if the LZW filter is used in a InlinedImage.
- *
- * @param operator
- * the InlinedImage object (BI to EI)
- * @throws ContentStreamException
- */
- protected void validImageFilter(PDFOperator operator)throws ContentStreamException {
- COSDictionary dict = operator.getImageParameters().getDictionary();
- /*
- * Search a Filter declaration in the InlinedImage dictionary.
- * The LZWDecode Filter is forbidden.
- */
- COSBase filter = dict.getDictionaryObject(COSName.F, COSName.FILTER);
- FilterHelper.isAuthorizedFilter(context, COSUtils.getAsString(filter, this.context.getDocument().getDocument()));
- }
-
- /**
- * This method validates if the ColorSpace used by the InlinedImage is
- * consistent with the color space defined in OutputIntent dictionaries.
- *
- * @param operator
- * the InlinedImage object (BI to EI)
- * @throws ContentStreamException
- */
- protected void validImageColorSpace(PDFOperator operator) throws ContentStreamException, IOException {
- COSDictionary dict = operator.getImageParameters().getDictionary();
-
- COSBase csInlinedBase = dict.getItem(COSName.CS);
- ColorSpaceHelper csHelper = null;
- if (csInlinedBase != null) {
- if (COSUtils.isString(csInlinedBase, cosDocument)) {
- /*
- * In InlinedImage only DeviceGray/RGB/CMYK and
- * restricted Indexed color spaces are allowed.
- */
- String colorSpace = COSUtils.getAsString(csInlinedBase, cosDocument);
- ColorSpaces cs = null;
-
- try {
- cs = ColorSpaces.valueOf(colorSpace);
- } catch (IllegalArgumentException e) {
- /*
- * The color space is unknown.
- * Try to access the resources dictionary, the color space can be a reference.
- */
- PDColorSpace pdCS = (PDColorSpace) this.getColorSpaces().get(colorSpace);
- if (pdCS != null) {
- cs = ColorSpaces.valueOf(pdCS.getName());
- PreflightConfiguration cfg = context.getConfig();
- ColorSpaceHelperFactory csFact = cfg.getColorSpaceHelperFact();
- csHelper = csFact.getColorSpaceHelper(context, pdCS, ColorSpaceRestriction.ONLY_DEVICE);
- }
- }
-
- if (cs == null) {
- registerError("The ColorSpace is unknown", ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY);
- return;
- }
- }
-
- if (csHelper == null) {
- PDColorSpace pdCS = PDColorSpaceFactory.createColorSpace(csInlinedBase);
- PreflightConfiguration cfg = context.getConfig();
- ColorSpaceHelperFactory csFact = cfg.getColorSpaceHelperFact();
- csHelper = csFact.getColorSpaceHelper(context, pdCS, ColorSpaceRestriction.ONLY_DEVICE);
- }
-
- csHelper.validate();
- }
- }
-
- /**
- * This method validates if the ColorOperator can be used with the color space
- * defined in OutputIntent dictionaries.
- *
- * @param operator
- * the color operator
- * @throws ContentStreamException
- */
- protected void checkColorOperators(String operation)
- throws ContentStreamException {
- PDColorState cs = getColorState(operation);
-
- if ("rg".equals(operation) || "RG".equals(operation)) {
- if (!validColorSpace(cs, ColorSpaceType.RGB)) {
- registerError("The operator \"" + operation
- + "\" can't be used with CMYK Profile",
- ERROR_GRAPHIC_INVALID_COLOR_SPACE_RGB);
- return;
- }
- }
-
- if ("k".equals(operation) || "K".equals(operation)) {
- if (!validColorSpace(cs, ColorSpaceType.CMYK)) {
- registerError("The operator \"" + operation
- + "\" can't be used with RGB Profile",
- ERROR_GRAPHIC_INVALID_COLOR_SPACE_CMYK);
- return;
- }
- }
-
- if ("g".equals(operation) || "G".equals(operation)) {
- if (!validColorSpace(cs, ColorSpaceType.ALL)) {
- registerError("The operator \"" + operation
- + "\" can't be used without Color Profile",
- ERROR_GRAPHIC_INVALID_COLOR_SPACE_MISSING);
- return;
- }
- }
-
- if ("f".equals(operation) || "F".equals(operation)
- || "f*".equals(operation) || "B".equals(operation)
- || "B*".equals(operation) || "b".equals(operation)
- || "b*".equals(operation)) {
- if (!validColorSpace(cs, ColorSpaceType.ALL)) {
- // The default fill color needs an OutputIntent
- registerError("The operator \"" + operation
- + "\" can't be used without Color Profile",
- ERROR_GRAPHIC_INVALID_COLOR_SPACE_MISSING);
- return;
- }
- }
- }
-
- private boolean validColorSpace(PDColorState colorState, ColorSpaceType expectedType)
- throws ContentStreamException {
- boolean result = true;
- if (colorState == null) {
- result = validColorSpaceDestOutputProfile(expectedType);
- } else {
- PDColorSpace cs = colorState.getColorSpace();
- if (isDeviceIndependent(cs, expectedType)) {
- result = true;
- } else {
- result = validColorSpaceDestOutputProfile(expectedType);
- }
- }
- return result;
- }
-
- /**
- * Check if the ColorProfile provided by the DestOutputProfile entry isn't null and
- * if the ColorSpace represented by the Profile has the right type (RGB or CMYK)
- *
- * @param expectedType
- * @return
- */
- private boolean validColorSpaceDestOutputProfile(ColorSpaceType expectedType) throws ContentStreamException {
- boolean result = false;
- ICCProfileWrapper profileWrapper;
- try {
- profileWrapper = ICCProfileWrapper.getOrSearchICCProfile(context);
- if (profileWrapper != null) {
- switch (expectedType) {
- case RGB:
- result = profileWrapper.isRGBColorSpace();
- break;
- case CMYK:
- result = profileWrapper.isCMYKColorSpace();
- break;
- default:
- result = true;
- break;
- }
- }
- } catch (ValidationException e) {
- throw new ContentStreamException(e);
- }
- return result;
- }
-
- /**
- * Return true if the given ColorSpace is an independent device ColorSpace.
- * If the color space is an ICCBased, check the embedded profile color (RGB or CMYK)
- * @param cs
- * @return
- */
- private boolean isDeviceIndependent(PDColorSpace cs, ColorSpaceType expectedType) {
- boolean result = (cs instanceof PDCalGray || cs instanceof PDCalRGB || cs instanceof PDLab);
- if (cs instanceof PDICCBased) {
- PDICCBased iccBased = (PDICCBased)cs;
- try {
- ColorSpace iccColorSpace = iccBased.getJavaColorSpace();
- switch (expectedType) {
- case RGB:
- result = (iccColorSpace.getType() == ICC_ColorSpace.TYPE_RGB);
- break;
- case CMYK:
- result = (iccColorSpace.getType() == ICC_ColorSpace.TYPE_CMYK);
- break;
- default:
- result = true;
- break;
- }
- } catch (IOException e) {
- result = false;
- }
- }
- return result;
- }
-
- /**
- * Return the current color state used by the operation
- * @param operation
- * @return
- */
- private PDColorState getColorState(String operation) {
- if (getGraphicsState() == null) {
- return null;
- }
-
- PDColorState colorState;
- if (operation.equals("rg") || operation.equals("g") || operation.equals("k")
- || operation.equals("f") || operation.equals("F") || operation.equals("f*")) {
- // non stroking operator
- colorState = getGraphicsState().getNonStrokingColor();
- } else {
- // stroking operator
- colorState = getGraphicsState().getStrokingColor();
- }
- return colorState;
- }
-
- /**
- * This method validates if the ColorSpace used as operand is consistent with
- * the color space defined in OutputIntent dictionaries.
- *
- * @param operator
- * @param arguments
- * @throws IOException
- */
- protected void checkSetColorSpaceOperators(PDFOperator operator, List<?> arguments)
- throws IOException {
- if (!("CS".equals(operator.getOperation()) || "cs".equals(operator.getOperation()))) {
- return;
- }
-
- String colorSpaceName = null;
- if (arguments.get(0) instanceof String) {
- colorSpaceName = (String) arguments.get(0);
- } else if (arguments.get(0) instanceof COSString) {
- colorSpaceName = ((COSString) arguments.get(0)).toString();
- } else if (arguments.get(0) instanceof COSName) {
- colorSpaceName = ((COSName) arguments.get(0)).getName();
- } else {
- registerError("The operand doesn't have the expected type", ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY);
- return;
- }
-
- ColorSpaceHelper csHelper = null;
- ColorSpaces cs = null;
- try {
- cs = ColorSpaces.valueOf(colorSpaceName);
- } catch (IllegalArgumentException e) {
- /*
- * The color space is unknown.
- * Try to access the resources dictionary,
- * the color space can be a reference.
- */
- PDColorSpace pdCS = (PDColorSpace) this.getColorSpaces().get(colorSpaceName);
- if (pdCS != null) {
- cs = ColorSpaces.valueOf(pdCS.getName());
- PreflightConfiguration cfg = context.getConfig();
- ColorSpaceHelperFactory csFact = cfg.getColorSpaceHelperFact();
- csHelper = csFact.getColorSpaceHelper(context, pdCS, ColorSpaceRestriction.NO_RESTRICTION);
- }
- }
-
- if (cs == null) {
- registerError("The ColorSpace is unknown", ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY);
- return;
- }
-
- if (csHelper == null) {
- PDColorSpace pdCS = PDColorSpaceFactory.createColorSpace(COSName.getPDFName(colorSpaceName));
- PreflightConfiguration cfg = context.getConfig();
- ColorSpaceHelperFactory csFact = cfg.getColorSpaceHelperFact();
- csHelper = csFact.getColorSpaceHelper(context, pdCS, ColorSpaceRestriction.NO_RESTRICTION);
- }
-
- csHelper.validate();
- }
-
- /**
- * Add a validation error into the PreflightContext
- *
- * @param msg exception details
- * @param errorCode the error code.
- */
- protected void registerError(String msg, String errorCode) {
- ValidationError error = new ValidationError(errorCode, msg);
- this.context.addValidationError(error);
- }
+ private enum ColorSpaceType
+ {
+ RGB, CMYK, ALL;
+ }
+
+ protected PreflightContext context = null;
+
+ protected COSDocument cosDocument = null;
+
+ protected PDPage processeedPage = null;
+
+ protected Map<String, OperatorProcessor> contentStreamEngineOperators = new HashMap<String, OperatorProcessor>();
+
+ public ContentStreamEngine(PreflightContext _context, PDPage _page)
+ {
+ super();
+ this.context = _context;
+ this.cosDocument = _context.getDocument().getDocument();
+ this.processeedPage = _page;
+
+ // Graphics operators
+ registerOperatorProcessor("w", new SetLineWidth());
+ registerOperatorProcessor("cm", new Concatenate());
+
+ registerOperatorProcessor("CS", new SetStrokingColorSpace());
+ registerOperatorProcessor("cs", new SetNonStrokingColorSpace());
+ registerOperatorProcessor("d", new SetLineDashPattern());
+ registerOperatorProcessor("Do", new Invoke());
+
+ registerOperatorProcessor("j", new SetLineJoinStyle());
+ registerOperatorProcessor("J", new SetLineCapStyle());
+ registerOperatorProcessor("K", new SetStrokingCMYKColor());
+ registerOperatorProcessor("k", new SetNonStrokingCMYKColor());
+
+ registerOperatorProcessor("rg", new SetNonStrokingRGBColor());
+ registerOperatorProcessor("RG", new SetStrokingRGBColor());
+
+ registerOperatorProcessor("SC", new SetStrokingColor());
+ registerOperatorProcessor("SCN", new SetStrokingColor());
+ registerOperatorProcessor("sc", new SetNonStrokingColor());
+ registerOperatorProcessor("scn", new SetNonStrokingColor());
+
+ // Graphics state
+ registerOperatorProcessor("Q", new GRestore());
+ registerOperatorProcessor("q", new GSave());
+
+ // Text operators
+ registerOperatorProcessor("BT", new BeginText());
+ registerOperatorProcessor("ET", new EndText());
+ registerOperatorProcessor("Tf", new SetTextFont());
+ registerOperatorProcessor("Tr", new SetTextRenderingMode());
+ registerOperatorProcessor("Tm", new SetMatrix());
+ registerOperatorProcessor("Td", new MoveText());
+ registerOperatorProcessor("T*", new NextLine());
+ registerOperatorProcessor("TD", new MoveTextSetLeading());
+ registerOperatorProcessor("Tc", new SetCharSpacing());
+ registerOperatorProcessor("TL", new SetTextLeading());
+ registerOperatorProcessor("Ts", new SetTextRise());
+ registerOperatorProcessor("Tw", new SetWordSpacing());
+ registerOperatorProcessor("Tz", new SetHorizontalTextScaling());
+
+ /*
+ * Do not use the PDFBox Operator, because of the PageDrawer class cast Or because the Operator doesn't exist
+ */
+ StubOperator stubOp = new StubOperator();
+ registerOperatorProcessor("l", stubOp);
+ registerOperatorProcessor("re", stubOp);
+ registerOperatorProcessor("c", stubOp);
+ registerOperatorProcessor("y", stubOp);
+ registerOperatorProcessor("v", stubOp);
+ registerOperatorProcessor("n", stubOp);
+ registerOperatorProcessor("BI", stubOp);
+ registerOperatorProcessor("EI", stubOp);
+ registerOperatorProcessor("m", stubOp);
+ registerOperatorProcessor("W*", stubOp);
+ registerOperatorProcessor("W", stubOp);
+ registerOperatorProcessor("h", stubOp);
+
+ registerOperatorProcessor("Tj", stubOp);
+ registerOperatorProcessor("TJ", stubOp);
+ registerOperatorProcessor("'", stubOp);
+ registerOperatorProcessor("\"", stubOp);
+
+ registerOperatorProcessor("b", stubOp);
+ registerOperatorProcessor("B", stubOp);
+ registerOperatorProcessor("b*", stubOp);
+ registerOperatorProcessor("B*", stubOp);
+
+ registerOperatorProcessor("BDC", stubOp);
+ registerOperatorProcessor("BMC", stubOp);
+ registerOperatorProcessor("DP", stubOp);
+ registerOperatorProcessor("EMC", stubOp);
+
+ registerOperatorProcessor("d0", stubOp);
+ registerOperatorProcessor("d1", stubOp);
+
+ registerOperatorProcessor("f", stubOp);
+ registerOperatorProcessor("F", stubOp);
+ registerOperatorProcessor("f*", stubOp);
+
+ registerOperatorProcessor("g", stubOp);
+ registerOperatorProcessor("G", stubOp);
+
+ registerOperatorProcessor("M", stubOp);
+ registerOperatorProcessor("MP", stubOp);
+
+ registerOperatorProcessor("gs", stubOp);
+ registerOperatorProcessor("h", stubOp);
+ registerOperatorProcessor("i", stubOp);
+
+ registerOperatorProcessor("ri", stubOp);
+ registerOperatorProcessor("s", stubOp);
+ registerOperatorProcessor("S", stubOp);
+ registerOperatorProcessor("sh", stubOp);
+ }
+
+ public final void registerOperatorProcessor(String operator, OperatorProcessor op)
+ {
+ super.registerOperatorProcessor(operator, op);
+ contentStreamEngineOperators.put(operator, op);
+ }
+
+ /**
+ * Check operands of the "ri" operator. Operands must exist in the RenderingIntent list.
+ * (net.awl.edoc.pdfa.validation.utils.RenderingIntents)
+ *
+ * @param operator
+ * the "ri" operator
+ * @param arguments
+ * the "ri" operands
+ * @throws ContentStreamException
+ * ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY if the operand is invalid
+ */
+ protected void validRenderingIntent(PDFOperator operator, List arguments) throws ContentStreamException
+ {
+ if ("ri".equals(operator.getOperation()))
+ {
+ String riArgument0 = "";
+ if (arguments.get(0) instanceof COSName)
+ {
+ riArgument0 = ((COSName) arguments.get(0)).getName();
+ }
+ else if (arguments.get(0) instanceof String)
+ {
+ riArgument0 = (String) arguments.get(0);
+ }
+
+ if (!RenderingIntents.contains(riArgument0))
+ {
+ registerError("Unexpected value '" + arguments.get(0) + "' for ri operand. ",
+ ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY);
+ return;
+ }
+ }
+ }
+
+ /**
+ * Valid the number of graphic states if the operator is the Save Graphic state operator ("q")
+ *
+ * @param operator
+ * @throws ContentStreamException
+ */
+ protected void validNumberOfGraphicStates(PDFOperator operator) throws ContentStreamException
+ {
+ if ("q".equals(operator.getOperation()))
+ {
+ int numberOfGraphicStates = this.getGraphicsStack().size();
+ if (numberOfGraphicStates > MAX_GRAPHIC_STATES)
+ {
+ registerError("Too many graphic states", ERROR_GRAPHIC_TOO_MANY_GRAPHIC_STATES);
+ return;
+ }
+ }
+ }
+
+ /**
+ * Throw a ContentStreamException if the LZW filter is used in a InlinedImage.
+ *
+ * @param operator
+ * the InlinedImage object (BI to EI)
+ * @throws ContentStreamException
+ */
+ protected void validImageFilter(PDFOperator operator) throws ContentStreamException
+ {
+ COSDictionary dict = operator.getImageParameters().getDictionary();
+ /*
+ * Search a Filter declaration in the InlinedImage dictionary. The LZWDecode Filter is forbidden.
+ */
+ COSBase filter = dict.getDictionaryObject(COSName.F, COSName.FILTER);
+ FilterHelper
+ .isAuthorizedFilter(context, COSUtils.getAsString(filter, this.context.getDocument().getDocument()));
+ }
+
+ /**
+ * This method validates if the ColorSpace used by the InlinedImage is consistent with the color space defined in
+ * OutputIntent dictionaries.
+ *
+ * @param operator
+ * the InlinedImage object (BI to EI)
+ * @throws ContentStreamException
+ */
+ protected void validImageColorSpace(PDFOperator operator) throws ContentStreamException, IOException
+ {
+ COSDictionary dict = operator.getImageParameters().getDictionary();
+
+ COSBase csInlinedBase = dict.getItem(COSName.CS);
+ ColorSpaceHelper csHelper = null;
+ if (csInlinedBase != null)
+ {
+ if (COSUtils.isString(csInlinedBase, cosDocument))
+ {
+ /*
+ * In InlinedImage only DeviceGray/RGB/CMYK and restricted Indexed color spaces are allowed.
+ */
+ String colorSpace = COSUtils.getAsString(csInlinedBase, cosDocument);
+ ColorSpaces cs = null;
+
+ try
+ {
+ cs = ColorSpaces.valueOf(colorSpace);
+ }
+ catch (IllegalArgumentException e)
+ {
+ /*
+ * The color space is unknown. Try to access the resources dictionary, the color space can be a
+ * reference.
+ */
+ PDColorSpace pdCS = (PDColorSpace) this.getColorSpaces().get(colorSpace);
+ if (pdCS != null)
+ {
+ cs = ColorSpaces.valueOf(pdCS.getName());
+ PreflightConfiguration cfg = context.getConfig();
+ ColorSpaceHelperFactory csFact = cfg.getColorSpaceHelperFact();
+ csHelper = csFact.getColorSpaceHelper(context, pdCS, ColorSpaceRestriction.ONLY_DEVICE);
+ }
+ }
+
+ if (cs == null)
+ {
+ registerError("The ColorSpace is unknown", ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY);
+ return;
+ }
+ }
+
+ if (csHelper == null)
+ {
+ PDColorSpace pdCS = PDColorSpaceFactory.createColorSpace(csInlinedBase);
+ PreflightConfiguration cfg = context.getConfig();
+ ColorSpaceHelperFactory csFact = cfg.getColorSpaceHelperFact();
+ csHelper = csFact.getColorSpaceHelper(context, pdCS, ColorSpaceRestriction.ONLY_DEVICE);
+ }
+
+ csHelper.validate();
+ }
+ }
+
+ /**
+ * This method validates if the ColorOperator can be used with the color space defined in OutputIntent dictionaries.
+ *
+ * @param operator
+ * the color operator
+ * @throws ContentStreamException
+ */
+ protected void checkColorOperators(String operation) throws ContentStreamException
+ {
+ PDColorState cs = getColorState(operation);
+
+ if ("rg".equals(operation) || "RG".equals(operation))
+ {
+ if (!validColorSpace(cs, ColorSpaceType.RGB))
+ {
+ registerError("The operator \"" + operation + "\" can't be used with CMYK Profile",
+ ERROR_GRAPHIC_INVALID_COLOR_SPACE_RGB);
+ return;
+ }
+ }
+
+ if ("k".equals(operation) || "K".equals(operation))
+ {
+ if (!validColorSpace(cs, ColorSpaceType.CMYK))
+ {
+ registerError("The operator \"" + operation + "\" can't be used with RGB Profile",
+ ERROR_GRAPHIC_INVALID_COLOR_SPACE_CMYK);
+ return;
+ }
+ }
+
+ if ("g".equals(operation) || "G".equals(operation))
+ {
+ if (!validColorSpace(cs, ColorSpaceType.ALL))
+ {
+ registerError("The operator \"" + operation + "\" can't be used without Color Profile",
+ ERROR_GRAPHIC_INVALID_COLOR_SPACE_MISSING);
+ return;
+ }
+ }
+
+ if ("f".equals(operation) || "F".equals(operation) || "f*".equals(operation) || "B".equals(operation)
+ || "B*".equals(operation) || "b".equals(operation) || "b*".equals(operation))
+ {
+ if (!validColorSpace(cs, ColorSpaceType.ALL))
+ {
+ // The default fill color needs an OutputIntent
+ registerError("The operator \"" + operation + "\" can't be used without Color Profile",
+ ERROR_GRAPHIC_INVALID_COLOR_SPACE_MISSING);
+ return;
+ }
+ }
+ }
+
+ private boolean validColorSpace(PDColorState colorState, ColorSpaceType expectedType) throws ContentStreamException
+ {
+ boolean result = true;
+ if (colorState == null)
+ {
+ result = validColorSpaceDestOutputProfile(expectedType);
+ }
+ else
+ {
+ PDColorSpace cs = colorState.getColorSpace();
+ if (isDeviceIndependent(cs, expectedType))
+ {
+ result = true;
+ }
+ else
+ {
+ result = validColorSpaceDestOutputProfile(expectedType);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Check if the ColorProfile provided by the DestOutputProfile entry isn't null and if the ColorSpace represented by
+ * the Profile has the right type (RGB or CMYK)
+ *
+ * @param expectedType
+ * @return
+ */
+ private boolean validColorSpaceDestOutputProfile(ColorSpaceType expectedType) throws ContentStreamException
+ {
+ boolean result = false;
+ ICCProfileWrapper profileWrapper;
+ try
+ {
+ profileWrapper = ICCProfileWrapper.getOrSearchICCProfile(context);
+ if (profileWrapper != null)
+ {
+ switch (expectedType)
+ {
+ case RGB:
+ result = profileWrapper.isRGBColorSpace();
+ break;
+ case CMYK:
+ result = profileWrapper.isCMYKColorSpace();
+ break;
+ default:
+ result = true;
+ break;
+ }
+ }
+ }
+ catch (ValidationException e)
+ {
+ throw new ContentStreamException(e);
+ }
+ return result;
+ }
+
+ /**
+ * Return true if the given ColorSpace is an independent device ColorSpace. If the color space is an ICCBased, check
+ * the embedded profile color (RGB or CMYK)
+ *
+ * @param cs
+ * @return
+ */
+ private boolean isDeviceIndependent(PDColorSpace cs, ColorSpaceType expectedType)
+ {
+ boolean result = (cs instanceof PDCalGray || cs instanceof PDCalRGB || cs instanceof PDLab);
+ if (cs instanceof PDICCBased)
+ {
+ PDICCBased iccBased = (PDICCBased) cs;
+ try
+ {
+ ColorSpace iccColorSpace = iccBased.getJavaColorSpace();
+ switch (expectedType)
+ {
+ case RGB:
+ result = (iccColorSpace.getType() == ICC_ColorSpace.TYPE_RGB);
+ break;
+ case CMYK:
+ result = (iccColorSpace.getType() == ICC_ColorSpace.TYPE_CMYK);
+ break;
+ default:
+ result = true;
+ break;
+ }
+ }
+ catch (IOException e)
+ {
+ result = false;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Return the current color state used by the operation
+ *
+ * @param operation
+ * @return
+ */
+ private PDColorState getColorState(String operation)
+ {
+ if (getGraphicsState() == null)
+ {
+ return null;
+ }
+
+ PDColorState colorState;
+ if (operation.equals("rg") || operation.equals("g") || operation.equals("k") || operation.equals("f")
+ || operation.equals("F") || operation.equals("f*"))
+ {
+ // non stroking operator
+ colorState = getGraphicsState().getNonStrokingColor();
+ }
+ else
+ {
+ // stroking operator
+ colorState = getGraphicsState().getStrokingColor();
+ }
+ return colorState;
+ }
+
+ /**
+ * This method validates if the ColorSpace used as operand is consistent with the color space defined in
+ * OutputIntent dictionaries.
+ *
+ * @param operator
+ * @param arguments
+ * @throws IOException
+ */
+ protected void checkSetColorSpaceOperators(PDFOperator operator, List<?> arguments) throws IOException
+ {
+ if (!("CS".equals(operator.getOperation()) || "cs".equals(operator.getOperation())))
+ {
+ return;
+ }
+
+ String colorSpaceName = null;
+ if (arguments.get(0) instanceof String)
+ {
+ colorSpaceName = (String) arguments.get(0);
+ }
+ else if (arguments.get(0) instanceof COSString)
+ {
+ colorSpaceName = ((COSString) arguments.get(0)).toString();
+ }
+ else if (arguments.get(0) instanceof COSName)
+ {
+ colorSpaceName = ((COSName) arguments.get(0)).getName();
+ }
+ else
+ {
+ registerError("The operand doesn't have the expected type", ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY);
+ return;
+ }
+
+ ColorSpaceHelper csHelper = null;
+ ColorSpaces cs = null;
+ try
+ {
+ cs = ColorSpaces.valueOf(colorSpaceName);
+ }
+ catch (IllegalArgumentException e)
+ {
+ /*
+ * The color space is unknown. Try to access the resources dictionary, the color space can be a reference.
+ */
+ PDColorSpace pdCS = (PDColorSpace) this.getColorSpaces().get(colorSpaceName);
+ if (pdCS != null)
+ {
+ cs = ColorSpaces.valueOf(pdCS.getName());
+ PreflightConfiguration cfg = context.getConfig();
+ ColorSpaceHelperFactory csFact = cfg.getColorSpaceHelperFact();
+ csHelper = csFact.getColorSpaceHelper(context, pdCS, ColorSpaceRestriction.NO_RESTRICTION);
+ }
+ }
+
+ if (cs == null)
+ {
+ registerError("The ColorSpace is unknown", ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY);
+ return;
+ }
+
+ if (csHelper == null)
+ {
+ PDColorSpace pdCS = PDColorSpaceFactory.createColorSpace(COSName.getPDFName(colorSpaceName));
+ PreflightConfiguration cfg = context.getConfig();
+ ColorSpaceHelperFactory csFact = cfg.getColorSpaceHelperFact();
+ csHelper = csFact.getColorSpaceHelper(context, pdCS, ColorSpaceRestriction.NO_RESTRICTION);
+ }
+
+ csHelper.validate();
+ }
+
+ /**
+ * Add a validation error into the PreflightContext
+ *
+ * @param msg
+ * exception details
+ * @param errorCode
+ * the error code.
+ */
+ protected void registerError(String msg, String errorCode)
+ {
+ ValidationError error = new ValidationError(errorCode, msg);
+ this.context.addValidationError(error);
+ }
}
Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamException.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamException.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamException.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamException.java Wed Mar 6 16:46:35 2013
@@ -23,27 +23,33 @@ package org.apache.pdfbox.preflight.cont
import org.apache.pdfbox.preflight.exception.ValidationException;
-public class ContentStreamException extends ValidationException {
- private String errorCode="";
-
- public ContentStreamException(String arg0, Throwable arg1) {
- super(arg0);
- }
-
- public ContentStreamException(String arg0) {
- super(arg0);
- }
-
- public ContentStreamException(Throwable arg0) {
- super(arg0.getMessage());
- }
-
- public String getErrorCode() {
- return errorCode;
- }
-
- public void setErrorCode(String errorCode) {
- this.errorCode = errorCode;
- }
+public class ContentStreamException extends ValidationException
+{
+ private String errorCode = "";
+
+ public ContentStreamException(String arg0, Throwable arg1)
+ {
+ super(arg0);
+ }
+
+ public ContentStreamException(String arg0)
+ {
+ super(arg0);
+ }
+
+ public ContentStreamException(Throwable arg0)
+ {
+ super(arg0.getMessage());
+ }
+
+ public String getErrorCode()
+ {
+ return errorCode;
+ }
+
+ public void setErrorCode(String errorCode)
+ {
+ this.errorCode = errorCode;
+ }
}
Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamWrapper.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamWrapper.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamWrapper.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/ContentStreamWrapper.java Wed Mar 6 16:46:35 2013
@@ -51,286 +51,339 @@ import org.apache.pdfbox.preflight.font.
import org.apache.pdfbox.util.PDFOperator;
import org.apache.pdfbox.util.operator.OperatorProcessor;
-public class ContentStreamWrapper extends ContentStreamEngine {
+public class ContentStreamWrapper extends ContentStreamEngine
+{
- public ContentStreamWrapper(PreflightContext _context, PDPage _page) {
- super(_context, _page);
- }
-
- /**
- * Process the validation of a PageContent (The page is initialized by the
- * constructor)
- *
- * @return A list of validation error. This list is empty if the validation
- * succeed.
- * @throws ValidationException.
- */
- public void validPageContentStream() throws ValidationException {
- try {
- PDStream pstream = this.processeedPage.getContents();
- if (pstream != null) {
- processStream(processeedPage, processeedPage.findResources(), pstream.getStream());
- }
- } catch (ContentStreamException e) {
- context.addValidationError(new ValidationError(e.getErrorCode(), e.getMessage()));
- } catch (IOException e) {
- throw new ValidationException("Unable to check the ContentStream : " + e.getMessage(), e);
- }
- }
-
- /**
- * Process the validation of a XObject Form
- *
- * @param xobj
- * @return A list of validation error. This list is empty if the validation
- * succeed.
- * @throws ValidationException
- */
- public void validXObjContentStream(PDXObjectForm xobj) throws ValidationException {
- try {
- resetEnginContext();
- processSubStream(this.processeedPage, xobj.getResources(), xobj.getCOSStream());
- } catch (ContentStreamException e) {
- context.addValidationError(new ValidationError(e.getErrorCode(), e.getMessage()));
- } catch (IOException e) {
- throw new ValidationException("Unable to check the ContentStream : "
- + e.getMessage(), e);
- }
- }
-
- /**
- * Process the validation of a Tiling Pattern
- *
- * @param pattern
- * @return A list of validation error. This list is empty if the validation
- * succeed.
- * @throws ValidationException
- */
- public void validPatternContentStream(COSStream pattern) throws ValidationException {
- try {
- COSDictionary res = (COSDictionary) pattern.getDictionaryObject(COSName.RESOURCES);
- resetEnginContext();
- processSubStream(this.processeedPage, new PDResources(res), pattern);
- } catch (ContentStreamException e) {
- context.addValidationError(new ValidationError(e.getErrorCode(), e.getMessage()));
- } catch (IOException e) {
- throw new ValidationException("Unable to check the ContentStream : " + e.getMessage(), e);
- }
- }
-
- public final void resetEnginContext() {
- this.setGraphicsState(new PDGraphicsState());
- this.setTextMatrix(null);
- this.setTextLineMatrix(null);
- this.getGraphicsStack().clear();
- // this.streamResourcesStack.clear();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * org.apache.pdfbox.util.PDFStreamEngine#processOperator(org.apache.pdfbox
- * .util.PDFOperator, java.util.List)
- */
- protected void processOperator(PDFOperator operator, List arguments) throws IOException {
- /*
- * Here is a copy of the super method because the else block is different.
- * (If the operator is unknown, throw an exception)
- */
- String operation = operator.getOperation();
- OperatorProcessor processor = (OperatorProcessor) contentStreamEngineOperators.get(operation);
- if (processor != null) {
- processor.setContext(this);
- processor.process(operator, arguments);
- } else {
- registerError("The operator \"" + operation
- + "\" isn't supported.", ERROR_SYNTAX_CONTENT_STREAM_UNSUPPORTED_OP);
- return;
- }
-
- /*
- * Process Specific Validation.
- * The Generic Processing is useless for PDFA validation
- */
- if ("BI".equals(operation)) {
- validImageFilter(operator);
- validImageColorSpace(operator);
- }
-
- checkShowTextOperators(operator, arguments);
- checkColorOperators(operation);
- validRenderingIntent(operator, arguments);
- checkSetColorSpaceOperators(operator, arguments);
- validNumberOfGraphicStates(operator);
- }
-
- /**
- * Process Text Validation. According to the operator one of the both method
- * will be called. (validStringDefinition(PDFOperator operator, List<?>
- * arguments) / validStringArray(PDFOperator operator, List<?> arguments))
- *
- * @param operator
- * @param arguments
- * @throws ContentStreamException
- * @throws IOException
- */
- protected void checkShowTextOperators(PDFOperator operator, List<?> arguments)
- throws ContentStreamException, IOException {
- String op = operator.getOperation();
- if ("Tj".equals(op)
- || "'".equals(op)
- || "\"".equals(op)) {
- validStringDefinition(operator, arguments);
- }
-
- if ("TJ".equals(op)) {
- validStringArray(operator, arguments);
- }
- }
-
- /**
- * Process Text Validation for the Operands of a Tj, "'" and "\"" operator.
- *
- * If the validation fails for an unexpected reason, a IOException is thrown.
- * If the validation fails due to validation error, a ContentStreamException
- * is thrown. (Use the ValidationError attribute to know the cause)
- *
- * @param operator
- * @param arguments
- * @throws ContentStreamException
- * @throws IOException
- */
- private void validStringDefinition(PDFOperator operator, List<?> arguments)
- throws ContentStreamException, IOException {
- /* For a Text operator, the arguments list should contain only one
- * COSString object
- */
- if ("\"".equals(operator.getOperation())) {
- if (arguments.size() != 3) {
- registerError("Invalid argument for the operator : "
- + operator.getOperation(), ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
- return;
- }
- Object arg0 = arguments.get(0);
- Object arg1 = arguments.get(1);
- Object arg2 = arguments.get(2);
- if (!(arg0 instanceof COSInteger || arg0 instanceof COSFloat) ||
- !(arg1 instanceof COSInteger || arg1 instanceof COSFloat) ) {
- registerError("Invalid argument for the operator : "
- + operator.getOperation(), ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
- return;
- }
-
- if (arg2 instanceof COSString) {
- validText(((COSString) arg2).getBytes());
- } else {
- registerError("Invalid argument for the operator : "
- + operator.getOperation(), ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
- return;
- }
- } else {
- Object objStr = arguments.get(0);
- if (objStr instanceof COSString) {
- validText(((COSString) objStr).getBytes());
- } else if (!(objStr instanceof COSInteger)) {
- registerError("Invalid argument for the operator : "
- + operator.getOperation(), ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
- return;
- }
- }
- }
-
- /**
- * Process Text Validation for the Operands of a TJ operator.
- *
- * If the validation fails for an unexpected reason, a IOException is thrown.
- * If the validation fails due to validation error, a ContentStreamException
- * is thrown. (Use the ValidationError attribute to know the cause)
- *
- * @param operator
- * @param arguments
- * @throws ContentStreamException
- * @throws IOException
- */
- private void validStringArray(PDFOperator operator, List<?> arguments) throws ContentStreamException, IOException {
- for (Object object : arguments) {
- if (object instanceof COSArray) {
- validStringArray(operator, ((COSArray) object).toList());
- } else if (object instanceof COSString) {
- validText(((COSString) object).getBytes());
- } else if (!(object instanceof COSInteger || object instanceof COSFloat)) {
- registerError("Invalid argument for the operator : "
- + operator.getOperation(), ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
- return;
- }
- }
- }
-
- /**
- * Process the validation of a Text operand contains in a ContentStream This
- * validation checks that :
- * <UL>
- * <li>The font isn't missing if the Rendering Mode isn't 3
- * <li>The font metrics are consistent
- * <li>All character used in the text are defined in the font program.
- * </UL>
- *
- * @param string
- * @throws IOException
- */
- public void validText(byte[] string) throws IOException {
- // TextSize accessible through the TextState
- PDTextState textState = getGraphicsState().getTextState();
- final int renderingMode = textState.getRenderingMode();
- final PDFont font = textState.getFont();
- if (font == null) {
- // Unable to decode the Text without Font
- registerError("Text operator can't be process without Font", ERROR_FONTS_UNKNOWN_FONT_REF);
- return;
- }
-
- FontContainer fontContainer = context.getFontContainer(font.getCOSObject());
- if (renderingMode == 3 && (fontContainer == null || !fontContainer.isEmbeddedFont())) {
- // font not embedded and rendering mode is 3. Valid case and nothing to check
- return ;
- } else if (fontContainer == null) {
- // Font Must be embedded if the RenderingMode isn't 3
- registerError(font.getBaseFont() + " is unknown wasn't found by the FontHelperValdiator", ERROR_FONTS_UNKNOWN_FONT_REF);
- return;
- } else if (!fontContainer.isValid() && !fontContainer.errorsAleadyMerged()) {
- context.addValidationErrors(fontContainer.getAllErrors());
- fontContainer.setErrorsAleadyMerged(true);
- return;
- } if (!fontContainer.isValid() && fontContainer.errorsAleadyMerged()) {
- // font already computed
- return;
- }
-
-
- int codeLength = 1;
- for (int i = 0; i < string.length; i += codeLength) {
- // explore the string to detect character code (length can be 1 or 2 bytes)
- int cid = -1;
- codeLength = 1;
- try {
- // according to the encoding, extract the character identifier
- cid = font.encodeToCID(string, i, codeLength);
- if (cid == -1 && i + 1 < string.length) {
- // maybe a multibyte encoding
- codeLength++;
- cid = font.encodeToCID(string, i, codeLength);
- }
- fontContainer.checkGlyphWith(cid);
- } catch (IOException e) {
- registerError("Encoding can't interpret the character code", ERROR_FONTS_ENCODING_ERROR);
- return;
- } catch (GlyphException e) {
- if (renderingMode != 3) {
- registerError(e.getMessage(), e.getErrorCode());
- return;
- }
- }
- }
- }
+ public ContentStreamWrapper(PreflightContext _context, PDPage _page)
+ {
+ super(_context, _page);
+ }
+
+ /**
+ * Process the validation of a PageContent (The page is initialized by the constructor)
+ *
+ * @return A list of validation error. This list is empty if the validation succeed.
+ * @throws ValidationException.
+ */
+ public void validPageContentStream() throws ValidationException
+ {
+ try
+ {
+ PDStream pstream = this.processeedPage.getContents();
+ if (pstream != null)
+ {
+ processStream(processeedPage, processeedPage.findResources(), pstream.getStream());
+ }
+ }
+ catch (ContentStreamException e)
+ {
+ context.addValidationError(new ValidationError(e.getErrorCode(), e.getMessage()));
+ }
+ catch (IOException e)
+ {
+ throw new ValidationException("Unable to check the ContentStream : " + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Process the validation of a XObject Form
+ *
+ * @param xobj
+ * @return A list of validation error. This list is empty if the validation succeed.
+ * @throws ValidationException
+ */
+ public void validXObjContentStream(PDXObjectForm xobj) throws ValidationException
+ {
+ try
+ {
+ resetEnginContext();
+ processSubStream(this.processeedPage, xobj.getResources(), xobj.getCOSStream());
+ }
+ catch (ContentStreamException e)
+ {
+ context.addValidationError(new ValidationError(e.getErrorCode(), e.getMessage()));
+ }
+ catch (IOException e)
+ {
+ throw new ValidationException("Unable to check the ContentStream : " + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Process the validation of a Tiling Pattern
+ *
+ * @param pattern
+ * @return A list of validation error. This list is empty if the validation succeed.
+ * @throws ValidationException
+ */
+ public void validPatternContentStream(COSStream pattern) throws ValidationException
+ {
+ try
+ {
+ COSDictionary res = (COSDictionary) pattern.getDictionaryObject(COSName.RESOURCES);
+ resetEnginContext();
+ processSubStream(this.processeedPage, new PDResources(res), pattern);
+ }
+ catch (ContentStreamException e)
+ {
+ context.addValidationError(new ValidationError(e.getErrorCode(), e.getMessage()));
+ }
+ catch (IOException e)
+ {
+ throw new ValidationException("Unable to check the ContentStream : " + e.getMessage(), e);
+ }
+ }
+
+ public final void resetEnginContext()
+ {
+ this.setGraphicsState(new PDGraphicsState());
+ this.setTextMatrix(null);
+ this.setTextLineMatrix(null);
+ this.getGraphicsStack().clear();
+ // this.streamResourcesStack.clear();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.pdfbox.util.PDFStreamEngine#processOperator(org.apache.pdfbox .util.PDFOperator, java.util.List)
+ */
+ protected void processOperator(PDFOperator operator, List arguments) throws IOException
+ {
+ /*
+ * Here is a copy of the super method because the else block is different. (If the operator is unknown, throw an
+ * exception)
+ */
+ String operation = operator.getOperation();
+ OperatorProcessor processor = (OperatorProcessor) contentStreamEngineOperators.get(operation);
+ if (processor != null)
+ {
+ processor.setContext(this);
+ processor.process(operator, arguments);
+ }
+ else
+ {
+ registerError("The operator \"" + operation + "\" isn't supported.",
+ ERROR_SYNTAX_CONTENT_STREAM_UNSUPPORTED_OP);
+ return;
+ }
+
+ /*
+ * Process Specific Validation. The Generic Processing is useless for PDFA validation
+ */
+ if ("BI".equals(operation))
+ {
+ validImageFilter(operator);
+ validImageColorSpace(operator);
+ }
+
+ checkShowTextOperators(operator, arguments);
+ checkColorOperators(operation);
+ validRenderingIntent(operator, arguments);
+ checkSetColorSpaceOperators(operator, arguments);
+ validNumberOfGraphicStates(operator);
+ }
+
+ /**
+ * Process Text Validation. According to the operator one of the both method will be called.
+ * (validStringDefinition(PDFOperator operator, List<?> arguments) / validStringArray(PDFOperator operator, List<?>
+ * arguments))
+ *
+ * @param operator
+ * @param arguments
+ * @throws ContentStreamException
+ * @throws IOException
+ */
+ protected void checkShowTextOperators(PDFOperator operator, List<?> arguments) throws ContentStreamException,
+ IOException
+ {
+ String op = operator.getOperation();
+ if ("Tj".equals(op) || "'".equals(op) || "\"".equals(op))
+ {
+ validStringDefinition(operator, arguments);
+ }
+
+ if ("TJ".equals(op))
+ {
+ validStringArray(operator, arguments);
+ }
+ }
+
+ /**
+ * Process Text Validation for the Operands of a Tj, "'" and "\"" operator.
+ *
+ * If the validation fails for an unexpected reason, a IOException is thrown. If the validation fails due to
+ * validation error, a ContentStreamException is thrown. (Use the ValidationError attribute to know the cause)
+ *
+ * @param operator
+ * @param arguments
+ * @throws ContentStreamException
+ * @throws IOException
+ */
+ private void validStringDefinition(PDFOperator operator, List<?> arguments) throws ContentStreamException,
+ IOException
+ {
+ /*
+ * For a Text operator, the arguments list should contain only one COSString object
+ */
+ if ("\"".equals(operator.getOperation()))
+ {
+ if (arguments.size() != 3)
+ {
+ registerError("Invalid argument for the operator : " + operator.getOperation(),
+ ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
+ return;
+ }
+ Object arg0 = arguments.get(0);
+ Object arg1 = arguments.get(1);
+ Object arg2 = arguments.get(2);
+ if (!(arg0 instanceof COSInteger || arg0 instanceof COSFloat)
+ || !(arg1 instanceof COSInteger || arg1 instanceof COSFloat))
+ {
+ registerError("Invalid argument for the operator : " + operator.getOperation(),
+ ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
+ return;
+ }
+
+ if (arg2 instanceof COSString)
+ {
+ validText(((COSString) arg2).getBytes());
+ }
+ else
+ {
+ registerError("Invalid argument for the operator : " + operator.getOperation(),
+ ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
+ return;
+ }
+ }
+ else
+ {
+ Object objStr = arguments.get(0);
+ if (objStr instanceof COSString)
+ {
+ validText(((COSString) objStr).getBytes());
+ }
+ else if (!(objStr instanceof COSInteger))
+ {
+ registerError("Invalid argument for the operator : " + operator.getOperation(),
+ ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
+ return;
+ }
+ }
+ }
+
+ /**
+ * Process Text Validation for the Operands of a TJ operator.
+ *
+ * If the validation fails for an unexpected reason, a IOException is thrown. If the validation fails due to
+ * validation error, a ContentStreamException is thrown. (Use the ValidationError attribute to know the cause)
+ *
+ * @param operator
+ * @param arguments
+ * @throws ContentStreamException
+ * @throws IOException
+ */
+ private void validStringArray(PDFOperator operator, List<?> arguments) throws ContentStreamException, IOException
+ {
+ for (Object object : arguments)
+ {
+ if (object instanceof COSArray)
+ {
+ validStringArray(operator, ((COSArray) object).toList());
+ }
+ else if (object instanceof COSString)
+ {
+ validText(((COSString) object).getBytes());
+ }
+ else if (!(object instanceof COSInteger || object instanceof COSFloat))
+ {
+ registerError("Invalid argument for the operator : " + operator.getOperation(),
+ ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
+ return;
+ }
+ }
+ }
+
+ /**
+ * Process the validation of a Text operand contains in a ContentStream This validation checks that :
+ * <UL>
+ * <li>The font isn't missing if the Rendering Mode isn't 3
+ * <li>The font metrics are consistent
+ * <li>All character used in the text are defined in the font program.
+ * </UL>
+ *
+ * @param string
+ * @throws IOException
+ */
+ public void validText(byte[] string) throws IOException
+ {
+ // TextSize accessible through the TextState
+ PDTextState textState = getGraphicsState().getTextState();
+ final int renderingMode = textState.getRenderingMode();
+ final PDFont font = textState.getFont();
+ if (font == null)
+ {
+ // Unable to decode the Text without Font
+ registerError("Text operator can't be process without Font", ERROR_FONTS_UNKNOWN_FONT_REF);
+ return;
+ }
+
+ FontContainer fontContainer = context.getFontContainer(font.getCOSObject());
+ if (renderingMode == 3 && (fontContainer == null || !fontContainer.isEmbeddedFont()))
+ {
+ // font not embedded and rendering mode is 3. Valid case and nothing to check
+ return;
+ }
+ else if (fontContainer == null)
+ {
+ // Font Must be embedded if the RenderingMode isn't 3
+ registerError(font.getBaseFont() + " is unknown wasn't found by the FontHelperValdiator",
+ ERROR_FONTS_UNKNOWN_FONT_REF);
+ return;
+ }
+ else if (!fontContainer.isValid() && !fontContainer.errorsAleadyMerged())
+ {
+ context.addValidationErrors(fontContainer.getAllErrors());
+ fontContainer.setErrorsAleadyMerged(true);
+ return;
+ }
+ if (!fontContainer.isValid() && fontContainer.errorsAleadyMerged())
+ {
+ // font already computed
+ return;
+ }
+
+ int codeLength = 1;
+ for (int i = 0; i < string.length; i += codeLength)
+ {
+ // explore the string to detect character code (length can be 1 or 2 bytes)
+ int cid = -1;
+ codeLength = 1;
+ try
+ {
+ // according to the encoding, extract the character identifier
+ cid = font.encodeToCID(string, i, codeLength);
+ if (cid == -1 && i + 1 < string.length)
+ {
+ // maybe a multibyte encoding
+ codeLength++;
+ cid = font.encodeToCID(string, i, codeLength);
+ }
+ fontContainer.checkGlyphWith(cid);
+ }
+ catch (IOException e)
+ {
+ registerError("Encoding can't interpret the character code", ERROR_FONTS_ENCODING_ERROR);
+ return;
+ }
+ catch (GlyphException e)
+ {
+ if (renderingMode != 3)
+ {
+ registerError(e.getMessage(), e.getErrorCode());
+ return;
+ }
+ }
+ }
+ }
}
Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/StubOperator.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/StubOperator.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/StubOperator.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/content/StubOperator.java Wed Mar 6 16:46:35 2013
@@ -48,287 +48,376 @@ import org.apache.pdfbox.util.PDFOperato
import org.apache.pdfbox.util.operator.OperatorProcessor;
/**
- * This implementation of OperatorProcessor allow the operator validation
- * according PDF/A rules without compute the operator actions.
+ * This implementation of OperatorProcessor allow the operator validation according PDF/A rules without compute the
+ * operator actions.
*/
-public class StubOperator extends OperatorProcessor {
+public class StubOperator extends OperatorProcessor
+{
- /*
- * (non-Javadoc)
- *
- * @see
- * org.apache.pdfbox.util.operator.OperatorProcessor#process(org.apache.pdfbox
- * .util.PDFOperator, java.util.List)
- */
- @Override
- public void process(PDFOperator operator, List<COSBase> arguments)
- throws IOException {
- String op = operator.getOperation();
- if ("S".equals(op)) {
- checkNoOperands(arguments);
- } else if ("B".equals(op)) {
- checkNoOperands(arguments);
- } else if ("f".equals(op)) {
- checkNoOperands(arguments);
- } else if ("F".equals(op)) {
- checkNoOperands(arguments);
- } else if ("f*".equals(op)) {
- checkNoOperands(arguments);
- } else if ("b".equals(op)) {
- checkNoOperands(arguments);
- } else if ("B*".equals(op)) {
- checkNoOperands(arguments);
- } else if ("b*".equals(op)) {
- checkNoOperands(arguments);
- } else if ("s".equals(op)) {
- checkNoOperands(arguments);
- } else if ("EMC".equals(op)) {
- checkNoOperands(arguments);
- } else if ("BMC".equals(op)) {
- checkStringOperands(arguments, 1);
- } else if ("BDC".equals(op)) {
- checkTagAndPropertyOperands(arguments);
- } else if ("DP".equals(op)) {
- checkTagAndPropertyOperands(arguments);
- } else if ("c".equals(op)) {
- checkNumberOperands(arguments, 6);
- } else if ("v".equals(op)) {
- checkNumberOperands(arguments, 4);
- } else if ("y".equals(op)) {
- checkNumberOperands(arguments, 4);
- } else if ("d0".equals(op)) {
- checkNumberOperands(arguments, 2);
- } else if ("d1".equals(op)) {
- checkNumberOperands(arguments, 6);
- } else if ("g".equals(op)) {
- checkNumberOperands(arguments, 1);
- } else if ("G".equals(op)) {
- checkNumberOperands(arguments, 1);
- } else if ("gs".equals(op)) {
- checkStringOperands(arguments, 1);
- } else if ("h".equals(op)) {
- checkNoOperands(arguments);
- } else if ("i".equals(op)) {
- checkNumberOperands(arguments, 1);
- } else if ("l".equals(op)) {
- checkNumberOperands(arguments, 2);
- } else if ("m".equals(op)) {
- checkNumberOperands(arguments, 2);
- } else if ("M".equals(op)) {
- checkNumberOperands(arguments, 1);
- } else if ("MP".equals(op)) {
- checkStringOperands(arguments, 1);
- } else if ("n".equals(op)) {
- checkNoOperands(arguments);
- } else if ("re".equals(op)) {
- checkNumberOperands(arguments, 4);
- } else if ("ri".equals(op)) {
- checkStringOperands(arguments, 1);
- } else if ("s".equals(op)) {
- checkNoOperands(arguments);
- } else if ("S".equals(op)) {
- checkNoOperands(arguments);
- } else if ("sh".equals(op)) {
- checkStringOperands(arguments, 1);
- } else if ("'".equals(op)) {
- checkStringOperands(arguments, 1);
- } else if ("Tj".equals(op)) {
- checkStringOperands(arguments, 1);
- } else if ("TJ".equals(op)) {
- checkArrayOperands(arguments, 1);
- } else if ("W".equals(op)) {
- checkNoOperands(arguments);
- } else if ("W*".equals(op)) {
- checkNoOperands(arguments);
- } else if ("\"".equals(op)) {
- checkNumberOperands(arguments.subList(0, 2), 2);
- checkStringOperands(arguments.subList(2, arguments.size()), 1);
- }
- // else
- // ---- Some operators are processed by PDFBox Objects.
- // ---- Other operators are authorized but it isn't used.
-
- }
-
- /**
- * If the arguments list of Operator isn't empty, this method throws a
- * ContentStreamException.
- *
- * @param arguments
- * @throws ContentStreamException
- */
- private void checkNoOperands(List<COSBase> arguments)
- throws ContentStreamException {
- if (arguments != null && !arguments.isEmpty()) {
- throw createInvalidArgumentsError();
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.pdfbox.util.operator.OperatorProcessor#process(org.apache.pdfbox .util.PDFOperator,
+ * java.util.List)
+ */
+ @Override
+ public void process(PDFOperator operator, List<COSBase> arguments) throws IOException
+ {
+ String op = operator.getOperation();
+ if ("S".equals(op))
+ {
+ checkNoOperands(arguments);
+ }
+ else if ("B".equals(op))
+ {
+ checkNoOperands(arguments);
+ }
+ else if ("f".equals(op))
+ {
+ checkNoOperands(arguments);
+ }
+ else if ("F".equals(op))
+ {
+ checkNoOperands(arguments);
+ }
+ else if ("f*".equals(op))
+ {
+ checkNoOperands(arguments);
+ }
+ else if ("b".equals(op))
+ {
+ checkNoOperands(arguments);
+ }
+ else if ("B*".equals(op))
+ {
+ checkNoOperands(arguments);
+ }
+ else if ("b*".equals(op))
+ {
+ checkNoOperands(arguments);
+ }
+ else if ("s".equals(op))
+ {
+ checkNoOperands(arguments);
+ }
+ else if ("EMC".equals(op))
+ {
+ checkNoOperands(arguments);
+ }
+ else if ("BMC".equals(op))
+ {
+ checkStringOperands(arguments, 1);
+ }
+ else if ("BDC".equals(op))
+ {
+ checkTagAndPropertyOperands(arguments);
+ }
+ else if ("DP".equals(op))
+ {
+ checkTagAndPropertyOperands(arguments);
+ }
+ else if ("c".equals(op))
+ {
+ checkNumberOperands(arguments, 6);
+ }
+ else if ("v".equals(op))
+ {
+ checkNumberOperands(arguments, 4);
+ }
+ else if ("y".equals(op))
+ {
+ checkNumberOperands(arguments, 4);
+ }
+ else if ("d0".equals(op))
+ {
+ checkNumberOperands(arguments, 2);
+ }
+ else if ("d1".equals(op))
+ {
+ checkNumberOperands(arguments, 6);
+ }
+ else if ("g".equals(op))
+ {
+ checkNumberOperands(arguments, 1);
+ }
+ else if ("G".equals(op))
+ {
+ checkNumberOperands(arguments, 1);
+ }
+ else if ("gs".equals(op))
+ {
+ checkStringOperands(arguments, 1);
+ }
+ else if ("h".equals(op))
+ {
+ checkNoOperands(arguments);
+ }
+ else if ("i".equals(op))
+ {
+ checkNumberOperands(arguments, 1);
+ }
+ else if ("l".equals(op))
+ {
+ checkNumberOperands(arguments, 2);
+ }
+ else if ("m".equals(op))
+ {
+ checkNumberOperands(arguments, 2);
+ }
+ else if ("M".equals(op))
+ {
+ checkNumberOperands(arguments, 1);
+ }
+ else if ("MP".equals(op))
+ {
+ checkStringOperands(arguments, 1);
+ }
+ else if ("n".equals(op))
+ {
+ checkNoOperands(arguments);
+ }
+ else if ("re".equals(op))
+ {
+ checkNumberOperands(arguments, 4);
+ }
+ else if ("ri".equals(op))
+ {
+ checkStringOperands(arguments, 1);
+ }
+ else if ("s".equals(op))
+ {
+ checkNoOperands(arguments);
+ }
+ else if ("S".equals(op))
+ {
+ checkNoOperands(arguments);
+ }
+ else if ("sh".equals(op))
+ {
+ checkStringOperands(arguments, 1);
+ }
+ else if ("'".equals(op))
+ {
+ checkStringOperands(arguments, 1);
+ }
+ else if ("Tj".equals(op))
+ {
+ checkStringOperands(arguments, 1);
+ }
+ else if ("TJ".equals(op))
+ {
+ checkArrayOperands(arguments, 1);
+ }
+ else if ("W".equals(op))
+ {
+ checkNoOperands(arguments);
+ }
+ else if ("W*".equals(op))
+ {
+ checkNoOperands(arguments);
+ }
+ else if ("\"".equals(op))
+ {
+ checkNumberOperands(arguments.subList(0, 2), 2);
+ checkStringOperands(arguments.subList(2, arguments.size()), 1);
+ }
+ // else
+ // ---- Some operators are processed by PDFBox Objects.
+ // ---- Other operators are authorized but it isn't used.
+
+ }
+
+ /**
+ * If the arguments list of Operator isn't empty, this method throws a ContentStreamException.
+ *
+ * @param arguments
+ * @throws ContentStreamException
+ */
+ private void checkNoOperands(List<COSBase> arguments) throws ContentStreamException
+ {
+ if (arguments != null && !arguments.isEmpty())
+ {
+ throw createInvalidArgumentsError();
+ }
+ }
+
+ /**
+ * If the arguments list of Operator doesn't have String parameter, this method throws a ContentStreamException.
+ *
+ * @param arguments
+ * @param length
+ * @throws ContentStreamException
+ */
+ private void checkStringOperands(List<COSBase> arguments, int length) throws ContentStreamException
+ {
+ if (arguments == null || arguments.isEmpty() || arguments.size() != length)
+ {
+ throw createInvalidArgumentsError();
+ }
+
+ for (int i = 0; i < length; ++i)
+ {
+ COSBase arg = arguments.get(i);
+ if (!(arg instanceof COSName) && !(arg instanceof COSString))
+ {
+ throw createInvalidArgumentsError();
+ }
+
+ if (arg instanceof COSName && ((COSName) arg).getName().length() > MAX_NAME_SIZE)
+ {
+ throw createLimitError(ERROR_SYNTAX_NAME_TOO_LONG, "A Name operand is too long");
+ }
+
+ if (arg instanceof COSString && ((COSString) arg).getString().getBytes().length > MAX_STRING_LENGTH)
+ {
+ throw createLimitError(ERROR_SYNTAX_LITERAL_TOO_LONG, "A String operand is too long");
+ }
+ }
+ }
+
+ /**
+ * If the arguments list of Operator doesn't have Array parameter, this method throws a ContentStreamException.
+ *
+ * @param arguments
+ * @param length
+ * @throws ContentStreamException
+ */
+ private void checkArrayOperands(List<COSBase> arguments, int length) throws ContentStreamException
+ {
+ if (arguments == null || arguments.isEmpty() || arguments.size() != length)
+ {
+ throw createInvalidArgumentsError();
+ }
+
+ for (int i = 0; i < length; ++i)
+ {
+ COSBase arg = arguments.get(i);
+ if (!(arg instanceof COSArray))
+ {
+ throw createInvalidArgumentsError();
+ }
+
+ if (((COSArray) arg).size() > MAX_ARRAY_ELEMENTS)
+ {
+ throw createLimitError(ERROR_SYNTAX_ARRAY_TOO_LONG, "Array has " + ((COSArray) arg).size()
+ + " elements");
+ }
+ }
+ }
+
+ /**
+ * If the arguments list of Operator doesn't have Number parameters (Int, float...), this method throws a
+ * ContentStreamException.
+ *
+ * @param arguments
+ * the arguments list to check
+ * @param length
+ * the expected size of the list
+ * @throws ContentStreamException
+ */
+ private void checkNumberOperands(List<COSBase> arguments, int length) throws ContentStreamException
+ {
+ if (arguments == null || arguments.isEmpty() || arguments.size() != length)
+ {
+ throw createInvalidArgumentsError();
+ }
+
+ for (int i = 0; i < length; ++i)
+ {
+ COSBase arg = arguments.get(i);
+ if (!(arg instanceof COSFloat) && !(arg instanceof COSInteger))
+ {
+ throw createInvalidArgumentsError();
+ }
+
+ if (arg instanceof COSInteger
+ && (((COSInteger) arg).longValue() > Integer.MAX_VALUE || ((COSInteger) arg).longValue() < Integer.MIN_VALUE))
+ {
+ throw createLimitError(ERROR_SYNTAX_NUMERIC_RANGE, "Invalid integer range in a Number operands");
+ }
+
+ if (arg instanceof COSFloat
+ && (((COSFloat) arg).doubleValue() > MAX_POSITIVE_FLOAT || ((COSFloat) arg).doubleValue() < MAX_NEGATIVE_FLOAT))
+ {
+ throw createLimitError(ERROR_SYNTAX_NUMERIC_RANGE, "Invalid float range in a Number operands");
+ }
+ }
+ }
+
+ /**
+ * The given arguments list is valid only if the first argument is a Tag (A String) and if the second argument is a
+ * String or a Dictionary
+ *
+ * @param arguments
+ * @throws ContentStreamException
+ */
+ private void checkTagAndPropertyOperands(List<COSBase> arguments) throws ContentStreamException
+ {
+ if (arguments == null || arguments.isEmpty() || arguments.size() != 2)
+ {
+ throw createInvalidArgumentsError();
+ }
+
+ COSBase arg = arguments.get(0);
+ if (!(arg instanceof COSName) && !(arg instanceof COSString))
+ {
+ throw createInvalidArgumentsError();
+ }
+
+ if (arg instanceof COSName && ((COSName) arg).getName().length() > MAX_NAME_SIZE)
+ {
+ throw createLimitError(ERROR_SYNTAX_NAME_TOO_LONG, "A Name operand is too long");
+ }
+
+ if (arg instanceof COSString && ((COSString) arg).getString().getBytes().length > MAX_STRING_LENGTH)
+ {
+ throw createLimitError(ERROR_SYNTAX_LITERAL_TOO_LONG, "A String operand is too long");
+ }
+
+ COSBase arg2 = arguments.get(1);
+ if (!(arg2 instanceof COSName) && !(arg2 instanceof COSString) && !(arg2 instanceof COSDictionary))
+ {
+ throw createInvalidArgumentsError();
+ }
+
+ if (arg2 instanceof COSName && ((COSName) arg2).getName().length() > MAX_NAME_SIZE)
+ {
+ throw createLimitError(ERROR_SYNTAX_NAME_TOO_LONG, "A Name operand is too long");
+ }
+
+ if (arg2 instanceof COSString && ((COSString) arg2).getString().getBytes().length > MAX_STRING_LENGTH)
+ {
+ throw createLimitError(ERROR_SYNTAX_LITERAL_TOO_LONG, "A String operand is too long");
+ }
+
+ if (arg2 instanceof COSDictionary && ((COSDictionary) arg2).size() > MAX_DICT_ENTRIES)
+ {
+ throw createLimitError(ERROR_SYNTAX_TOO_MANY_ENTRIES, "Dictionary has " + ((COSDictionary) arg2).size()
+ + " entries");
+ }
+ }
+
+ /**
+ * Create a ContentStreamException with ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT.
+ *
+ * @return
+ */
+ private ContentStreamException createInvalidArgumentsError()
+ {
+ ContentStreamException ex = new ContentStreamException("Invalid arguments");
+ ex.setErrorCode(ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
+ return ex;
+ }
+
+ /**
+ * Create a ContentStreamException with ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT.
+ *
+ * @return
+ */
+ private ContentStreamException createLimitError(String errorCode, String details)
+ {
+ ContentStreamException ex = new ContentStreamException(details);
+ ex.setErrorCode(errorCode);
+ return ex;
}
- }
-
- /**
- * If the arguments list of Operator doesn't have String parameter, this
- * method throws a ContentStreamException.
- *
- * @param arguments
- * @param length
- * @throws ContentStreamException
- */
- private void checkStringOperands(List<COSBase> arguments, int length)
- throws ContentStreamException {
- if (arguments == null || arguments.isEmpty() || arguments.size() != length) {
- throw createInvalidArgumentsError();
- }
-
- for (int i = 0; i < length; ++i) {
- COSBase arg = arguments.get(i);
- if (!(arg instanceof COSName) && !(arg instanceof COSString)) {
- throw createInvalidArgumentsError();
- }
-
- if (arg instanceof COSName
- && ((COSName) arg).getName().length() > MAX_NAME_SIZE) {
- throw createLimitError(ERROR_SYNTAX_NAME_TOO_LONG, "A Name operand is too long");
- }
-
- if (arg instanceof COSString
- && ((COSString) arg).getString().getBytes().length > MAX_STRING_LENGTH) {
- throw createLimitError(ERROR_SYNTAX_LITERAL_TOO_LONG, "A String operand is too long");
- }
- }
- }
-
- /**
- * If the arguments list of Operator doesn't have Array parameter, this method
- * throws a ContentStreamException.
- *
- * @param arguments
- * @param length
- * @throws ContentStreamException
- */
- private void checkArrayOperands(List<COSBase> arguments, int length)
- throws ContentStreamException {
- if (arguments == null || arguments.isEmpty() || arguments.size() != length) {
- throw createInvalidArgumentsError();
- }
-
- for (int i = 0; i < length; ++i) {
- COSBase arg = arguments.get(i);
- if (!(arg instanceof COSArray)) {
- throw createInvalidArgumentsError();
- }
-
- if (((COSArray) arg).size() > MAX_ARRAY_ELEMENTS) {
- throw createLimitError(ERROR_SYNTAX_ARRAY_TOO_LONG, "Array has " + ((COSArray) arg).size() + " elements");
- }
- }
- }
-
- /**
- * If the arguments list of Operator doesn't have Number parameters (Int,
- * float...), this method throws a ContentStreamException.
- *
- * @param arguments
- * the arguments list to check
- * @param length
- * the expected size of the list
- * @throws ContentStreamException
- */
- private void checkNumberOperands(List<COSBase> arguments, int length)
- throws ContentStreamException {
- if (arguments == null || arguments.isEmpty() || arguments.size() != length) {
- throw createInvalidArgumentsError();
- }
-
- for (int i = 0; i < length; ++i) {
- COSBase arg = arguments.get(i);
- if (!(arg instanceof COSFloat) && !(arg instanceof COSInteger)) {
- throw createInvalidArgumentsError();
- }
-
- if (arg instanceof COSInteger
- && (((COSInteger) arg).longValue() > Integer.MAX_VALUE || ((COSInteger) arg)
- .longValue() < Integer.MIN_VALUE)) {
- throw createLimitError(ERROR_SYNTAX_NUMERIC_RANGE, "Invalid integer range in a Number operands");
- }
-
- if (arg instanceof COSFloat
- && (((COSFloat) arg).doubleValue() > MAX_POSITIVE_FLOAT || ((COSFloat) arg)
- .doubleValue() < MAX_NEGATIVE_FLOAT)) {
- throw createLimitError(ERROR_SYNTAX_NUMERIC_RANGE, "Invalid float range in a Number operands");
- }
- }
- }
-
- /**
- * The given arguments list is valid only if the first argument is a Tag (A
- * String) and if the second argument is a String or a Dictionary
- *
- * @param arguments
- * @throws ContentStreamException
- */
- private void checkTagAndPropertyOperands(List<COSBase> arguments)
- throws ContentStreamException {
- if (arguments == null || arguments.isEmpty() || arguments.size() != 2) {
- throw createInvalidArgumentsError();
- }
-
- COSBase arg = arguments.get(0);
- if (!(arg instanceof COSName) && !(arg instanceof COSString)) {
- throw createInvalidArgumentsError();
- }
-
- if (arg instanceof COSName
- && ((COSName) arg).getName().length() > MAX_NAME_SIZE) {
- throw createLimitError(ERROR_SYNTAX_NAME_TOO_LONG,"A Name operand is too long");
- }
-
- if (arg instanceof COSString
- && ((COSString) arg).getString().getBytes().length > MAX_STRING_LENGTH) {
- throw createLimitError(ERROR_SYNTAX_LITERAL_TOO_LONG,"A String operand is too long");
- }
-
- COSBase arg2 = arguments.get(1);
- if (!(arg2 instanceof COSName) && !(arg2 instanceof COSString)
- && !(arg2 instanceof COSDictionary)) {
- throw createInvalidArgumentsError();
- }
-
- if (arg2 instanceof COSName
- && ((COSName) arg2).getName().length() > MAX_NAME_SIZE) {
- throw createLimitError(ERROR_SYNTAX_NAME_TOO_LONG,"A Name operand is too long");
- }
-
- if (arg2 instanceof COSString
- && ((COSString) arg2).getString().getBytes().length > MAX_STRING_LENGTH) {
- throw createLimitError(ERROR_SYNTAX_LITERAL_TOO_LONG,"A String operand is too long");
- }
-
- if (arg2 instanceof COSDictionary
- && ((COSDictionary) arg2).size() > MAX_DICT_ENTRIES) {
- throw createLimitError(ERROR_SYNTAX_TOO_MANY_ENTRIES, "Dictionary has " + ((COSDictionary) arg2).size() + " entries");
- }
- }
-
- /**
- * Create a ContentStreamException with
- * ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT.
- *
- * @return
- */
- private ContentStreamException createInvalidArgumentsError() {
- ContentStreamException ex = new ContentStreamException("Invalid arguments");
- ex.setErrorCode(ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT);
- return ex;
- }
-
- /**
- * Create a ContentStreamException with
- * ERROR_SYNTAX_CONTENT_STREAM_INVALID_ARGUMENT.
- *
- * @return
- */
- private ContentStreamException createLimitError(String errorCode, String details) {
- ContentStreamException ex = new ContentStreamException(details);
- ex.setErrorCode(errorCode);
- return ex;
- }
}
Modified: pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/exception/BodyParseException.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/exception/BodyParseException.java?rev=1453416&r1=1453415&r2=1453416&view=diff
==============================================================================
--- pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/exception/BodyParseException.java (original)
+++ pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/exception/BodyParseException.java Wed Mar 6 16:46:35 2013
@@ -24,81 +24,86 @@ package org.apache.pdfbox.preflight.exce
import org.apache.pdfbox.preflight.PreflightConstants;
import org.apache.pdfbox.preflight.javacc.PDFParserConstants;
import org.apache.pdfbox.preflight.javacc.ParseException;
+
/**
- * This Exception is thrown if an validation error occurs during the javacc
- * validation in the PDF Body.
+ * This Exception is thrown if an validation error occurs during the javacc validation in the PDF Body.
*
* Error codes provided by this exception should start by 1.2 or 1.0.
*/
-public class BodyParseException extends PdfParseException {
+public class BodyParseException extends PdfParseException
+{
- /*
- * (non-Javadoc)
- *
- * @see
- * net.awl.edoc.pdfa.validation.PdfParseException#PdfParseException(net.awl
- * .edoc.pdfa.validation.ParseException)
- */
- public BodyParseException(ParseException e) {
- super(e);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * net.awl.edoc.pdfa.validation.PdfParseException#PdfParseException(java.lang
- * .String,java.lang.String)
- */
- public BodyParseException(String message, String code) {
- super(message, code);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * net.awl.edoc.pdfa.validation.PdfParseException#PdfParseException(java.lang
- * .String)
- */
- public BodyParseException(String message) {
- super(message);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see net.awl.edoc.pdfa.validation.PdfParseException#getErrorCode()
- */
- @Override
- public String getErrorCode() {
- if (this.errorCode != null) {
- return this.errorCode;
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.awl.edoc.pdfa.validation.PdfParseException#PdfParseException(net.awl
+ * .edoc.pdfa.validation.ParseException)
+ */
+ public BodyParseException(ParseException e)
+ {
+ super(e);
}
- // default error code
- this.errorCode = PreflightConstants.ERROR_SYNTAX_BODY;
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.awl.edoc.pdfa.validation.PdfParseException#PdfParseException(java.lang .String,java.lang.String)
+ */
+ public BodyParseException(String message, String code)
+ {
+ super(message, code);
+ }
- if (!isTokenMgrError) {
- // it is a parse error, according to the ExpectedTokens data
- // some error code can be returned
- if (this.expectedTokenSequences != null) {
- // check object delimiters error
- for (int i = 0; i < this.expectedTokenSequences.length; ++i) {
- // Check only the first Expected token on each array.
- // Others can be check if some choice can start by the same token
- // in this case, a factorization is possible
- switch (this.expectedTokenSequences[i][0]) {
- case PDFParserConstants.START_OBJECT:
- case PDFParserConstants.END_OBJECT:
- this.errorCode = PreflightConstants.ERROR_SYNTAX_OBJ_DELIMITER;
- break;
- }
- }
- // add here other error code
- }
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.awl.edoc.pdfa.validation.PdfParseException#PdfParseException(java.lang .String)
+ */
+ public BodyParseException(String message)
+ {
+ super(message);
}
- return errorCode;
- }
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.awl.edoc.pdfa.validation.PdfParseException#getErrorCode()
+ */
+ @Override
+ public String getErrorCode()
+ {
+ if (this.errorCode != null)
+ {
+ return this.errorCode;
+ }
+
+ // default error code
+ this.errorCode = PreflightConstants.ERROR_SYNTAX_BODY;
+
+ if (!isTokenMgrError)
+ {
+ // it is a parse error, according to the ExpectedTokens data
+ // some error code can be returned
+ if (this.expectedTokenSequences != null)
+ {
+ // check object delimiters error
+ for (int i = 0; i < this.expectedTokenSequences.length; ++i)
+ {
+ // Check only the first Expected token on each array.
+ // Others can be check if some choice can start by the same token
+ // in this case, a factorization is possible
+ switch (this.expectedTokenSequences[i][0])
+ {
+ case PDFParserConstants.START_OBJECT:
+ case PDFParserConstants.END_OBJECT:
+ this.errorCode = PreflightConstants.ERROR_SYNTAX_OBJ_DELIMITER;
+ break;
+ }
+ }
+ // add here other error code
+ }
+ }
+
+ return errorCode;
+ }
}