Copilot commented on code in PR #3096:
URL: https://github.com/apache/tika/pull/3096#discussion_r3887616177
##########
tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/UnpackerResource.java:
##########
@@ -215,15 +272,162 @@ public Response unpackAll(InputStream is, @Context
HttpHeaders httpHeaders, @Con
@POST
@Consumes("multipart/form-data")
@Produces("application/zip")
- public Response unpackAllWithConfig(List<Attachment> attachments, @Context
HttpHeaders httpHeaders, @Context UriInfo info) throws Exception {
+ public Response unpackAllWithConfig(List<Attachment> attachments, @Context
HttpHeaders httpHeaders, @Context UriInfo info,
+ @QueryParam("renderThumbnails") boolean
renderThumbnails) throws Exception {
ParseContext pc = tikaResource.createRequestContext();
Metadata metadata = tikaResource.newRequestMetadata();
try (TikaInputStream tis =
tikaResource.setupMultipartConfig(attachments, metadata, pc)) {
TikaResource.logRequest(LOG, "/unpack/all", metadata);
+ if (renderThumbnails) {
+ //under the request's config, which setupMultipartConfig has
already merged
+ tikaResource.getThumbnailDefaults().applyTo(pc);
+ }
return doUnpack(tis, metadata, pc, true);
}
}
+ /**
+ * Returns the document thumbnail with its metadata (simple PUT).
+ */
+ @jakarta.ws.rs.Path("/thumbnail")
+ @PUT
+ @Produces("application/json")
+ public Response unpackThumbnail(InputStream is, @Context HttpHeaders
httpHeaders) throws Exception {
+ ParseContext pc = tikaResource.createRequestContext();
+ Metadata metadata = tikaResource.newRequestMetadata();
+ try (TikaInputStream tis = TikaInputStream.get(is)) {
+ fillMetadata(null, metadata, httpHeaders.getRequestHeaders());
+ TikaResource.logRequest(LOG, "/unpack/thumbnail", metadata);
+ return doUnpackThumbnail(tis, metadata, pc);
+ }
+ }
+
+ /**
+ * Returns the document thumbnail with its metadata (multipart POST,
"file" part).
+ */
+ @jakarta.ws.rs.Path("/thumbnail")
+ @POST
+ @Consumes("multipart/form-data")
+ @Produces("application/json")
+ public Response unpackThumbnailMultipart(List<Attachment> attachments,
@Context HttpHeaders httpHeaders)
+ throws Exception {
+ ParseContext pc = tikaResource.createRequestContext();
+ Metadata metadata = tikaResource.newRequestMetadata();
+ try (TikaInputStream tis =
tikaResource.setupMultipartConfig(attachments, metadata, pc)) {
+ TikaResource.logRequest(LOG, "/unpack/thumbnail", metadata);
+ return doUnpackThumbnail(tis, metadata, pc);
+ }
+ }
+
+ private static final ObjectMapper MAPPER = new ObjectMapper();
+ private static final String METADATA_SUFFIX = ".metadata.json";
+
+ /**
+ * Parses in unpack mode with the thumbnail configuration, then selects
+ * the thumbnail among the extracted embedded documents.
+ */
+ private Response doUnpackThumbnail(TikaInputStream tis, Metadata metadata,
ParseContext pc)
+ throws Exception {
+ PipesParsingHelper helper = tikaResource.getPipesParsingHelper();
+ if (helper == null) {
+ throw new WebApplicationException("Pipes-based parsing is not
enabled", Response.Status.SERVICE_UNAVAILABLE);
+ }
+ configureThumbnailParse(pc);
+
+ PipesParsingHelper.UnpackResult result = helper.parseUnpack(tis,
metadata, pc, false);
+ if (result.zipFile() == null) {
+ throw new WebApplicationException(Response.Status.NO_CONTENT);
+ }
+ try (ZipFile zip = new ZipFile(result.zipFile().toFile())) {
+ Map<String, Metadata> extracted = readExtractedMetadata(zip);
+ Metadata thumbnail = ThumbnailSelector.select(new
ArrayList<>(extracted.values()));
+ if (thumbnail == null) {
+ throw new WebApplicationException(Response.Status.NO_CONTENT);
+ }
+ String entryName = null;
+ for (Map.Entry<String, Metadata> e : extracted.entrySet()) {
+ if (e.getValue() == thumbnail) {
+ entryName = e.getKey();
+ }
+ }
+ ZipEntry imageEntry = entryName == null ? null :
zip.getEntry(entryName);
+ if (imageEntry == null) {
+ throw new WebApplicationException(Response.Status.NO_CONTENT);
+ }
+ byte[] image;
+ try (InputStream is = zip.getInputStream(imageEntry)) {
+ image = is.readAllBytes();
+ }
Review Comment:
`/unpack/thumbnail` reads the selected image entry with `readAllBytes()`,
which can allocate arbitrarily large arrays and produce extremely large base64
JSON responses. With `UnpackConfig`'s default `maxUnpackBytes` being 10GB, this
can lead to OOM or very large responses if a document contains a huge embedded
THUMBNAIL/RENDERING.
Consider enforcing a hard upper bound for this endpoint (or at least for
base64-in-JSON responses) by checking `ZipEntry#getSize()` when available and
reading with a bounded `readNBytes`, returning 413 when the limit is exceeded.
--
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]