Copilot commented on code in PR #3179:
URL: https://github.com/apache/tika/pull/3179#discussion_r4019739715


##########
tika-pipes/tika-pipes-core/src/main/java/org/apache/tika/pipes/core/extractor/ThumbnailUnpackSelector.java:
##########
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tika.pipes.core.extractor;
+
+import java.util.Locale;
+import java.util.Set;
+
+import org.apache.tika.annotation.TikaComponent;
+import org.apache.tika.config.TransientParseState;
+import org.apache.tika.extractor.UnpackSelector;
+import org.apache.tika.metadata.HttpHeaders;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.metadata.Rendering;
+import org.apache.tika.metadata.TikaCoreProperties;
+import org.apache.tika.mime.MediaType;
+import org.apache.tika.parser.ParseContext;
+
+/**
+ * Unpacks the one embedded document a client would show as the document's 
thumbnail and
+ * nothing else. A candidate is a raster image that is a {@code THUMBNAIL} at 
depth 1 (stored
+ * thumbnail), a rendered {@code THUMBNAIL} at depth 2 (the rasterized vector 
thumbnail of an
+ * Office document; {@code tk:rendering:rendered-by} marks it), or a {@code 
RENDERING} at
+ * depth 1 (the first page of a PDF); the first candidate of a parse wins. The 
thumbnail of a
+ * document inside an archive is that document's, not the archive's, and is 
not a candidate.
+ * Pair it with parser config that renders only those, as the catalog preset 
{@code thumbnails}
+ * does; clients reading {@code /rmeta} apply the same rule.
+ *
+ * @since Apache Tika 4.1.0
+ */
+@TikaComponent
+public class ThumbnailUnpackSelector implements UnpackSelector {
+
+    private static final Set<String> VECTOR_TYPES = Set.of("image/emf", 
"image/x-emf",
+            "image/wmf", "image/x-wmf", "image/svg+xml");
+
+    /** Marks a parse whose thumbnail is taken; the selector itself may be 
shared. */
+    private static final class Taken implements TransientParseState {
+    }
+
+    @Override
+    public boolean select(Metadata metadata) {
+        return isCandidate(metadata);
+    }
+
+    /** The stateless rule; {@code /rmeta} clients pick the first embedded 
document it accepts. */
+    public static boolean isCandidate(Metadata metadata) {
+        String type = metadata.get(TikaCoreProperties.EMBEDDED_RESOURCE_TYPE);
+        Integer depth = metadata.getInt(TikaCoreProperties.EMBEDDED_DEPTH);
+        if (type == null || depth == null || !isRaster(metadata)) {
+            return false;
+        }
+        if 
(TikaCoreProperties.EmbeddedResourceType.THUMBNAIL.name().equals(type)) {
+            return depth == 1
+                    || (depth == 2 && metadata.get(Rendering.RENDERED_BY) != 
null);
+        }
+        return 
TikaCoreProperties.EmbeddedResourceType.RENDERING.name().equals(type)
+                && depth == 1;
+    }
+
+    @Override
+    public boolean select(Metadata metadata, ParseContext context) {
+        if (context.get(Taken.class) != null || !isCandidate(metadata)) {
+            return false;
+        }
+        context.set(Taken.class, new Taken());

Review Comment:
   Because `Taken` is stored in the `ParseContext` and is never cleared, 
reusing one context for a second top-level parse permanently rejects every 
later candidate. `ParseContext` is allowed to survive later parses (for 
example, `CompositeParser` explicitly caches state on reused contexts), so this 
per-parse overload does not actually reset at a parse boundary; bind the marker 
to the current parse lifecycle or clear it when the top-level parse starts, and 
add a reuse test.



##########
tika-pipes/tika-pipes-core/src/main/resources/org/apache/tika/pipes/core/presets/thumbnails.json:
##########
@@ -0,0 +1,17 @@
+{
+  // one raster thumbnail per document, nothing else; the rule is in 
ThumbnailUnpackSelector
+  "thumbnail-unpack-selector": {},

Review Comment:
   This selector only filters bytes when `UnpackExtractor` stores an 
already-parsed child; it does not stop the embedded parser from traversing 
later siblings or descendants. Because this preset leaves `EmbeddedLimits` at 
its unlimited defaults, a large/deep archive can still parse and render its 
entire tree (including every PDF's first page) before discarding all but one 
image, which conflicts with the documented bounded/cheap preset behavior. Add 
explicit embedded depth/count limits that still allow the direct depth-2 
vector-thumbnail render, or add an equivalent traversal short-circuit.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to