You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by le...@apache.org on 2020/01/03 14:17:14 UTC
svn commit: r1872289 - in
/pdfbox/branches/issue4569/pdfbox/src/main/java/org/apache/pdfbox/pdfparser:
COSParser.java PDFObjectStreamParser.java
Author: lehmi
Date: Fri Jan 3 14:17:13 2020
New Revision: 1872289
URL: http://svn.apache.org/viewvc?rev=1872289&view=rev
Log:
PDFBOX-4569: refactor brute force parser, use ondemand parser and remove redundant code
Modified:
pdfbox/branches/issue4569/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/COSParser.java
pdfbox/branches/issue4569/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/PDFObjectStreamParser.java
Modified: pdfbox/branches/issue4569/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/COSParser.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/issue4569/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/COSParser.java?rev=1872289&r1=1872288&r2=1872289&view=diff
==============================================================================
--- pdfbox/branches/issue4569/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/COSParser.java (original)
+++ pdfbox/branches/issue4569/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/COSParser.java Fri Jan 3 14:17:13 2020
@@ -38,7 +38,6 @@ import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSDocument;
-import org.apache.pdfbox.cos.COSInputStream;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.cos.COSNull;
import org.apache.pdfbox.cos.COSNumber;
@@ -568,7 +567,8 @@ public class COSParser extends BaseParse
public boolean dereferenceCOSObject(COSObject obj) throws IOException
{
long currentPos = source.getPosition();
- COSBase parsedObj = parseObjectDynamically(obj, false);
+ COSBase parsedObj = parseObjectDynamically(obj.getObjectNumber(), obj.getGenerationNumber(),
+ false);
if (currentPos > 0)
{
source.seek(currentPos);
@@ -577,25 +577,7 @@ public class COSParser extends BaseParse
}
/**
- * This will parse the next object from the stream and add it to the local state.
- *
- * @param obj object to be parsed (we only take object number and generation number for lookup start offset)
- * @param requireExistingNotCompressedObj if <code>true</code> object to be parsed must not be contained within
- * compressed stream
- * @return the parsed object (which is also added to document object)
- *
- * @throws IOException If an IO error occurs.
- */
- protected final COSBase parseObjectDynamically(COSObject obj,
- boolean requireExistingNotCompressedObj) throws IOException
- {
- return parseObjectDynamically(obj.getObjectNumber(),
- obj.getGenerationNumber(), requireExistingNotCompressedObj);
- }
-
- /**
* Parse the object for the given object number.
- * It's reduced to parsing an indirect object.
*
* @param objNr object number of object to be parsed
* @param objGenNr object generation number of object to be parsed
@@ -1652,31 +1634,32 @@ public class COSParser extends BaseParse
long stmObjNumber = readObjectNumber();
int stmGenNumber = readGenerationNumber();
readExpectedString(OBJ_MARKER, true);
- int nrOfObjects = 0;
- byte[] numbersBytes = null;
COSStream stream = null;
- COSInputStream is = null;
try
{
COSDictionary dict = parseCOSDictionary();
- int offsetFirstStream = dict.getInt(COSName.FIRST);
- nrOfObjects = dict.getInt(COSName.N);
- // skip the stream if required values are missing
- if (offsetFirstStream != -1 && nrOfObjects != -1)
+ stream = parseCOSStream(dict);
+ if (securityHandler != null)
{
- stream = parseCOSStream(dict);
- if (securityHandler != null)
- {
- securityHandler.decryptStream(stream, stmObjNumber, stmGenNumber);
+ securityHandler.decryptStream(stream, stmObjNumber, stmGenNumber);
+ }
+ PDFObjectStreamParser objStreamParser = new PDFObjectStreamParser(stream, document);
+ Map<Long, Integer> objectNumbers = objStreamParser.readObjectNumbers();
+ Map<COSObjectKey, Long> xrefOffset = xrefTrailerResolver.getXrefTable();
+ for (Long objNumber : objectNumbers.keySet())
+ {
+ COSObjectKey objKey = new COSObjectKey(objNumber, 0);
+ Long existingOffset = bfSearchCOSObjectKeyOffsets.get(objKey);
+ if (existingOffset != null && existingOffset < 0)
+ {
+ // translate stream object key to its offset
+ COSObjectKey objStmKey = new COSObjectKey(Math.abs(existingOffset), 0);
+ existingOffset = bfSearchCOSObjectKeyOffsets.get(objStmKey);
}
- is = stream.createInputStream();
- numbersBytes = new byte[offsetFirstStream];
- long isResult = is.read(numbersBytes);
-
- if (Long.compare(isResult, numbersBytes.length) != 0)
+ if (existingOffset == null || offset > existingOffset)
{
- LOG.debug("Tried reading " + numbersBytes.length + " bytes but only "
- + isResult + " bytes read");
+ bfSearchCOSObjectKeyOffsets.put(objKey, -stmObjNumber);
+ xrefOffset.put(objKey, -stmObjNumber);
}
}
}
@@ -1687,55 +1670,11 @@ public class COSParser extends BaseParse
}
finally
{
- if (is != null)
- {
- is.close();
- }
if (stream != null)
{
stream.close();
}
}
- if (numbersBytes != null)
- {
- // convert byte array to string, skip leading/trailing spaces, replace LF\double spaces
- String[] numbers = new String(numbersBytes, StandardCharsets.ISO_8859_1) //
- .trim() //
- .replaceAll("\n", " ") //
- .replace(" ", " ") //
- .split(" ");
- if (numbers.length < nrOfObjects * 2)
- {
- LOG.debug(
- "Skipped corrupt stream: (" + stmObjNumber + " 0 at offset " + offset);
- continue;
- }
- Map<COSObjectKey, Long> xrefOffset = xrefTrailerResolver.getXrefTable();
- for (int i = 0; i < nrOfObjects; i++)
- {
- try
- {
- long objNumber = Long.parseLong(numbers[i * 2]);
- COSObjectKey objKey = new COSObjectKey(objNumber, 0);
- Long existingOffset = bfSearchCOSObjectKeyOffsets.get(objKey);
- if (existingOffset != null && existingOffset < 0)
- {
- // translate stream object key to its offset
- COSObjectKey objStmKey = new COSObjectKey(Math.abs(existingOffset), 0);
- existingOffset = bfSearchCOSObjectKeyOffsets.get(objStmKey);
- }
- if (existingOffset == null || offset > existingOffset)
- {
- bfSearchCOSObjectKeyOffsets.put(objKey, -stmObjNumber);
- xrefOffset.put(objKey, -stmObjNumber);
- }
- }
- catch (NumberFormatException exception)
- {
- LOG.debug("Skipped corrupt object key in stream: " + stmObjNumber);
- }
- }
- }
}
// restore origin offset
source.seek(originOffset);
Modified: pdfbox/branches/issue4569/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/PDFObjectStreamParser.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/issue4569/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/PDFObjectStreamParser.java?rev=1872289&r1=1872288&r2=1872289&view=diff
==============================================================================
--- pdfbox/branches/issue4569/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/PDFObjectStreamParser.java (original)
+++ pdfbox/branches/issue4569/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/PDFObjectStreamParser.java Fri Jan 3 14:17:13 2020
@@ -63,6 +63,7 @@ public class PDFObjectStreamParser exten
/**
* Search for/parse the object with the given object number. This will close the stream when it is finished parsing.
+ * The stream is closed after parsing the object with the given number.
*
* @param objectNumber the number of the object to b e parsed
* @return the parsed object or null if the object with the given number can't be found
@@ -94,7 +95,14 @@ public class PDFObjectStreamParser exten
return streamObject;
}
- private Map<Long, Integer> readObjectNumbers() throws IOException
+ /**
+ * Read all object numbers from the compressed object stream. The stream is not closed after reading the object
+ * numbers.
+ *
+ * @return a map off all object numbers and the corresponding offset within the object stream.
+ * @throws IOException if there is an error while parsing the stream
+ */
+ public Map<Long, Integer> readObjectNumbers() throws IOException
{
Map<Long, Integer> objectNumbers = new HashMap<>(numberOfObjects);
for (int i = 0; i < numberOfObjects; i++)
@@ -105,5 +113,4 @@ public class PDFObjectStreamParser exten
}
return objectNumbers;
}
-
}