This is an automated email from the ASF dual-hosted git repository.
tballison pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tika.git
The following commit(s) were added to refs/heads/main by this push:
new ddff151c27 bump bookmarks limit (#3212)
ddff151c27 is described below
commit ddff151c274c7d3df3405c59fdd00a877aee8873
Author: Tim Allison <[email protected]>
AuthorDate: Sun Sep 20 08:53:28 2026 -0400
bump bookmarks limit (#3212)
---
CHANGES.txt | 13 +++----
.../apache/tika/parser/pdf/AbstractPDF2XHTML.java | 14 ++++++--
.../org/apache/tika/parser/pdf/PDFParserTest.java | 40 ++++++++++++++++++++++
3 files changed, 57 insertions(+), 10 deletions(-)
diff --git a/CHANGES.txt b/CHANGES.txt
index 41a40a0203..225d306e66 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -2,14 +2,11 @@ Release 4.1.0 - unreleased
* A file name no longer turns plain text into a message type (emlx, mbox,
rfc822, news, HTTP capture) when the type's magic has already rejected
- the bytes: prose named .emlx is text/plain. An HTTP response captured
- without its version line ("200 OK", then headers) is detected as
- application/x-httpresponse (TIKA-4890).
-
- * Apple Mail emlx files are detected as message/x-emlx (real files pad the
- byte-count line to 10 columns and were falling through to text/html or
- message/rfc822), and RFC822Parser now parses them, dropping the byte-count
- line and, when the count is intact, the trailing plist (TIKA-4890).
+ the bytes (TIKA-4890).
+
+ * Apple Mail emlx files are detected as message/x-emlx and RFC822Parser
+ now parses them, dropping the byte-count line and,
+ when the count is intact, the trailing plist (TIKA-4890).
* The tika-server UAT gains an inference pass (TIKA-4913).
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/AbstractPDF2XHTML.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/AbstractPDF2XHTML.java
index cb73cdc034..eff1fbb3e5 100644
---
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/AbstractPDF2XHTML.java
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/AbstractPDF2XHTML.java
@@ -148,7 +148,8 @@ class AbstractPDF2XHTML extends PDFTextStripper {
* the embedded document tree.
*/
private final static int MAX_RECURSION_DEPTH = 100;
- private final static int MAX_BOOKMARK_ITEMS = 10000;
+ // a transcript's word index is ~12k items; the budget bounds a hostile
file, not a real one
+ private final static int MAX_BOOKMARK_ITEMS = 100000;
/** Deeper bookmarks are written as items of the deepest list, within the
XML nesting limit. */
private final static int MAX_BOOKMARK_DEPTH = 50;
@@ -1466,8 +1467,13 @@ class AbstractPDF2XHTML extends PDFTextStripper {
xhtml.startElement("ul");
int lists = 1;
int items = 0;
+ boolean truncated = false;
while (true) {
- if (current == null || seen.contains(current) || items >
MAX_BOOKMARK_ITEMS) {
+ if (items >= MAX_BOOKMARK_ITEMS && current != null &&
!seen.contains(current)) {
+ truncated = true;
+ current = null;
+ }
+ if (current == null || seen.contains(current)) {
if (parents.isEmpty()) {
break;
}
@@ -1499,6 +1505,10 @@ class AbstractPDF2XHTML extends PDFTextStripper {
}
}
xhtml.endElement("ul");
+ if (truncated) {
+ metadata.add(TikaCoreProperties.TIKA_META_EXCEPTION_WARNING,
+ "bookmark outline truncated at " + MAX_BOOKMARK_ITEMS + "
items");
+ }
}
void extractAcroForm(PDDocument pdf) throws IOException, SAXException,
TikaException {
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/test/java/org/apache/tika/parser/pdf/PDFParserTest.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/test/java/org/apache/tika/parser/pdf/PDFParserTest.java
index e48e93a0ae..63d9ccc407 100644
---
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/test/java/org/apache/tika/parser/pdf/PDFParserTest.java
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/test/java/org/apache/tika/parser/pdf/PDFParserTest.java
@@ -613,6 +613,46 @@ public class PDFParserTest extends TikaTest {
assertTrue(i < j);
}
+ /** A wide outline (a transcript's word index) is written whole; past the
budget the cut is recorded. */
+ @Test
+ public void testWideBookmarksAndTheBudget() throws Exception {
+ for (int n : new int[]{12000, 100500}) {
+ try (PDDocument doc = new PDDocument()) {
+ doc.addPage(new PDPage(PDRectangle.LETTER));
+ PDDocumentOutline outline = new PDDocumentOutline();
+ doc.getDocumentCatalog().setDocumentOutline(outline);
+ for (int i = 0; i < n / 4; i++) {
+ PDOutlineItem word = new PDOutlineItem();
+ word.setTitle("word" + i);
+ outline.addLast(word);
+ for (int j = 0; j < 3; j++) {
+ PDOutlineItem ref = new PDOutlineItem();
+ ref.setTitle("ref" + i + "-" + j);
+ word.addLast(ref);
+ }
+ }
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ doc.save(bos);
+ Metadata metadata = new Metadata();
+ String xml;
+ try (TikaInputStream tis =
TikaInputStream.get(bos.toByteArray())) {
+ ToXMLContentHandler handler = new ToXMLContentHandler();
+ new PDFParser().parse(tis, handler, metadata, new
ParseContext());
+ xml = handler.toString();
+ }
+ int items = xml.split("<li>").length - 1;
+ String warn = String.join(" ",
metadata.getValues(TikaCoreProperties.TIKA_META_EXCEPTION_WARNING));
+ if (n <= 100000) {
+ assertEquals(n, items, "every item written");
+ assertFalse(warn.contains("bookmark outline truncated"),
warn);
+ } else {
+ assertEquals(100000, items, "cut at the budget");
+ assertContains("bookmark outline truncated at 100000
items", warn);
+ }
+ }
+ }
+ }
+
/**
* An outline as deep as the item budget allows, each item the only child
of the last,
* on a thread with a stack a quarter of the default: every title is
written, lists nest