This is an automated email from the ASF dual-hosted git repository.

mridulpathak pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git


The following commit(s) were added to refs/heads/trunk by this push:
     new ff421b9bc4 Improved: Replace commons-imaging with metadata-extractor + 
TwelveMonkeys ImageIO TIFF plugin (OFBIZ-13507)
ff421b9bc4 is described below

commit ff421b9bc4e68ab4a4ec32180be00b54110a5192
Author: Mridul Pathak <[email protected]>
AuthorDate: Sun Aug 30 18:37:39 2026 +0530

    Improved: Replace commons-imaging with metadata-extractor + TwelveMonkeys 
ImageIO TIFF plugin (OFBIZ-13507)
    
    commons-imaging has been pinned to 1.0-alpha3 since its API broke in 
1.0.0-alpha4, and the library itself has stayed alpha-only since 2019 with no 
GA in sight. Actual usage was concentrated in SecuredUpload.java for magic-byte 
format validation and a TIFF decode/encode fallback, since the JDK's built-in 
ImageIO already handles PNG/GIF/JPEG natively. Both needs are now covered 
without a new unproven dependency: metadata-extractor's FileTypeDetector 
(already a project dependency) replac [...]
---
 .github/dependabot.yml                             |  17 ++--
 .../ofbiz/content/ContentManagementServices.java   |   3 +-
 .../apache/ofbiz/content/data/DataServices.java    |  20 +---
 .../org/apache/ofbiz/product/image/ScaleImage.java |   5 +-
 .../ofbiz/product/imagemanagement/FrameImage.java  |   3 +-
 .../imagemanagement/ImageManagementServices.java   |   5 +-
 .../ofbiz/product/product/ProductServices.java     |   5 +-
 dependencies.gradle                                |   2 +-
 .../ofbiz/base/util/HttpRequestFileUpload.java     |   4 -
 .../org/apache/ofbiz/security/SecuredUpload.java   | 105 ++++++---------------
 gradle/libs.versions.toml                          |   7 +-
 11 files changed, 53 insertions(+), 123 deletions(-)

diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 4c2c74e22b..7b5d825509 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -33,14 +33,6 @@ updates:
       - dependency-name: "*"
         update-types:
           - "version-update:semver-major"
-      # commons-imaging has been alpha-only since 2019 (alpha1..1.0.0-alpha6,
-      # see the version catalog comment) with no stable release in sight;
-      # we've deliberately deferred adapting to its post-alpha3 API changes
-      # until it ships an actual 1.0.0. This keeps Dependabot from reopening
-      # an alpha-to-alpha bump PR forever, while still surfacing a real 1.0.0
-      # (or later) release when one finally happens.
-      - dependency-name: "org.apache.commons:commons-imaging"
-        versions: ["< 1.0.0"]
 
   - package-ecosystem: "gradle"
     directory: "/"
@@ -56,7 +48,14 @@ updates:
       - dependency-name: "*"
         update-types:
           - "version-update:semver-major"
-      # See the same rule in the trunk gradle block above.
+      # commons-imaging has been alpha-only since 2019 (alpha1..1.0.0-alpha6,
+      # see the version catalog comment) with no stable release in sight;
+      # we've deliberately deferred adapting to its post-alpha3 API changes
+      # until it ships an actual 1.0.0. This keeps Dependabot from reopening
+      # an alpha-to-alpha bump PR forever, while still surfacing a real 1.0.0
+      # (or later) release when one finally happens. Trunk no longer needs
+      # this rule (OFBIZ-13507 removed the dependency there); this branch
+      # still has commons-imaging until that fix is backported.
       - dependency-name: "org.apache.commons:commons-imaging"
         versions: ["< 1.0.0"]
 
diff --git 
a/applications/content/src/main/java/org/apache/ofbiz/content/ContentManagementServices.java
 
b/applications/content/src/main/java/org/apache/ofbiz/content/ContentManagementServices.java
index 5e7c1c401d..3c2d9da6f3 100644
--- 
a/applications/content/src/main/java/org/apache/ofbiz/content/ContentManagementServices.java
+++ 
b/applications/content/src/main/java/org/apache/ofbiz/content/ContentManagementServices.java
@@ -33,7 +33,6 @@ import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 
-import org.apache.commons.imaging.ImageReadException;
 import org.apache.ofbiz.base.util.Debug;
 import org.apache.ofbiz.base.util.StringUtil;
 import org.apache.ofbiz.base.util.UtilDateTime;
@@ -1592,7 +1591,7 @@ public class ContentManagementServices {
                     if 
(!org.apache.ofbiz.security.SecuredUpload.isValidFile(objectInfo, "All", 
delegator)) {
                         errorMessage = 
UtilProperties.getMessage("SecurityUiLabels", 
"SupportedFileFormatsIncludingSvg", locale);
                     }
-                } catch (ImageReadException | IOException e) {
+                } catch (IOException e) {
                     errorMessage = UtilProperties.getMessage(RESOURCE, 
"ContentUnableToOpenFileForWriting", UtilMisc.toMap("fileName",
                             objectInfo), locale);
                 }
diff --git 
a/applications/content/src/main/java/org/apache/ofbiz/content/data/DataServices.java
 
b/applications/content/src/main/java/org/apache/ofbiz/content/data/DataServices.java
index e59c89fad5..5b22a67b43 100644
--- 
a/applications/content/src/main/java/org/apache/ofbiz/content/data/DataServices.java
+++ 
b/applications/content/src/main/java/org/apache/ofbiz/content/data/DataServices.java
@@ -37,7 +37,6 @@ import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
 
-import org.apache.commons.imaging.ImageReadException;
 import org.apache.ofbiz.base.util.Debug;
 import org.apache.ofbiz.base.util.GeneralException;
 import org.apache.ofbiz.base.util.UtilDateTime;
@@ -197,8 +196,7 @@ public class DataServices {
         return createFileMethod(dctx, context);
     }
 
-    public static Map<String, Object> createFileNoPerm(DispatchContext dctx, 
Map<String, ? extends Object> rcontext) throws IOException,
-            ImageReadException {
+    public static Map<String, Object> createFileNoPerm(DispatchContext dctx, 
Map<String, ? extends Object> rcontext) throws IOException {
         String originalFileName = (String) rcontext.get("dataResourceName");
         String fileNameAndPath = (String) rcontext.get("objectInfo");
         Delegator delegator = dctx.getDelegator();
@@ -300,7 +298,7 @@ public class DataServices {
                     String errorMessage = 
UtilProperties.getMessage("SecurityUiLabels", "SupportedTextFileFormats", 
locale);
                     return ServiceUtil.returnError(errorMessage);
                 }
-            } catch (IOException | ImageReadException e) {
+            } catch (IOException e) {
                 Debug.logWarning(e, MODULE);
                 return 
ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, 
"ContentUnableWriteCharacterDataToFile",
                         UtilMisc.toMap("fileName", file.getAbsolutePath()), 
locale));
@@ -320,10 +318,6 @@ public class DataServices {
                 Files.copy(tempFile, file.toPath(), 
StandardCopyOption.REPLACE_EXISTING);
                 new File(tempFile.toString()).deleteOnExit();
 
-            } catch (ImageReadException e) {
-                Debug.logError(e, MODULE);
-                return 
ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, 
"ContentUnableToOpenFileForWriting",
-                        UtilMisc.toMap("fileName", file.getAbsolutePath()), 
locale));
             } catch (IOException e) {
                 Debug.logError(e, MODULE);
                 return 
ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, 
"ContentUnableWriteBinaryDataToFile",
@@ -524,7 +518,7 @@ public class DataServices {
                         String errorMessage = 
UtilProperties.getMessage("SecurityUiLabels", "SupportedTextFileFormats", 
locale);
                         return ServiceUtil.returnError(errorMessage);
                     }
-                } catch (IOException | ImageReadException e) {
+                } catch (IOException e) {
                     Debug.logWarning(e, MODULE);
                     return 
ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, 
"ContentUnableWriteCharacterDataToFile",
                             UtilMisc.toMap("fileName", 
file.getAbsolutePath()), locale));
@@ -543,10 +537,6 @@ public class DataServices {
                     }
                     Files.copy(tempFile, file.toPath(), 
StandardCopyOption.REPLACE_EXISTING);
                     new File(tempFile.toString()).deleteOnExit();
-                } catch (ImageReadException e) {
-                    Debug.logError(e, MODULE);
-                    return 
ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, 
"ContentUnableToOpenFileForWriting",
-                            UtilMisc.toMap("fileName", 
file.getAbsolutePath()), locale));
                 } catch (IOException e) {
                     Debug.logError(e, MODULE);
                     return 
ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE, 
"ContentUnableWriteBinaryDataToFile",
@@ -715,7 +705,7 @@ public class DataServices {
                 if (Debug.infoOn()) {
                     Debug.logInfo("in createBinaryFileMethod, length:" + 
file.length(), MODULE);
                 }
-            } catch (IOException | ImageReadException e) {
+            } catch (IOException e) {
                 Debug.logWarning(e, MODULE);
                 throw new GenericServiceException(e.getMessage());
             }
@@ -776,7 +766,7 @@ public class DataServices {
                 if (Debug.infoOn()) {
                     Debug.logInfo("in updateBinaryFileMethod, length:" + 
file.length(), MODULE);
                 }
-            } catch (IOException | ImageReadException e) {
+            } catch (IOException e) {
                 Debug.logWarning(e, MODULE);
                 throw new GenericServiceException(e.getMessage());
             }
diff --git 
a/applications/product/src/main/java/org/apache/ofbiz/product/image/ScaleImage.java
 
b/applications/product/src/main/java/org/apache/ofbiz/product/image/ScaleImage.java
index c7c9ac49bd..19cf3fcb37 100644
--- 
a/applications/product/src/main/java/org/apache/ofbiz/product/image/ScaleImage.java
+++ 
b/applications/product/src/main/java/org/apache/ofbiz/product/image/ScaleImage.java
@@ -29,7 +29,6 @@ import java.util.Map;
 
 import javax.imageio.ImageIO;
 
-import org.apache.commons.imaging.ImageReadException;
 import org.apache.ofbiz.base.location.FlexibleLocation;
 import org.apache.ofbiz.base.util.Debug;
 import org.apache.ofbiz.base.util.UtilGenerics;
@@ -234,7 +233,7 @@ public class ScaleImage {
                         Debug.logError(errMsg, MODULE);
                         result.put(ModelService.ERROR_MESSAGE, errMsg);
                         return result;
-                    } catch (IOException | ImageReadException e) {
+                    } catch (IOException e) {
                         String errMsg = UtilProperties.getMessage(RESOURCE, 
"ScaleImage.error_occurs_during_writing", locale) + e.toString();
                         Debug.logError(errMsg, MODULE);
                         result.put(ModelService.ERROR_MESSAGE, errMsg);
@@ -413,7 +412,7 @@ public class ScaleImage {
                         Debug.logError(errMsg, MODULE);
                         result.put(ModelService.ERROR_MESSAGE, errMsg);
                         return result;
-                    } catch (IOException | ImageReadException e) {
+                    } catch (IOException e) {
                         String errMsg = UtilProperties.getMessage(RESOURCE, 
"ScaleImage.error_occurs_during_writing", locale) + e.toString();
                         Debug.logError(errMsg, MODULE);
                         result.put(ModelService.ERROR_MESSAGE, errMsg);
diff --git 
a/applications/product/src/main/java/org/apache/ofbiz/product/imagemanagement/FrameImage.java
 
b/applications/product/src/main/java/org/apache/ofbiz/product/imagemanagement/FrameImage.java
index 3b0883bcd3..71b63f0be5 100644
--- 
a/applications/product/src/main/java/org/apache/ofbiz/product/imagemanagement/FrameImage.java
+++ 
b/applications/product/src/main/java/org/apache/ofbiz/product/imagemanagement/FrameImage.java
@@ -44,7 +44,6 @@ import jakarta.servlet.http.HttpServletResponse;
 import jakarta.servlet.http.HttpSession;
 import javax.swing.ImageIcon;
 
-import org.apache.commons.imaging.ImageReadException;
 import org.apache.ofbiz.base.util.Debug;
 import org.apache.ofbiz.base.util.FileUtil;
 import org.apache.ofbiz.base.util.UtilDateTime;
@@ -364,7 +363,7 @@ public class FrameImage {
                 return "error";
             }
             contentId = contentResult.get("contentId").toString();
-        } catch (GenericServiceException | IOException | ImageReadException 
gse) {
+        } catch (GenericServiceException | IOException gse) {
             request.setAttribute("_ERROR_MESSAGE_", gse.getMessage());
             return "error";
         }
diff --git 
a/applications/product/src/main/java/org/apache/ofbiz/product/imagemanagement/ImageManagementServices.java
 
b/applications/product/src/main/java/org/apache/ofbiz/product/imagemanagement/ImageManagementServices.java
index 47bbd4b180..741bb8c934 100644
--- 
a/applications/product/src/main/java/org/apache/ofbiz/product/imagemanagement/ImageManagementServices.java
+++ 
b/applications/product/src/main/java/org/apache/ofbiz/product/imagemanagement/ImageManagementServices.java
@@ -39,7 +39,6 @@ import java.util.Map;
 
 import javax.imageio.ImageIO;
 
-import org.apache.commons.imaging.ImageReadException;
 import org.apache.ofbiz.base.location.FlexibleLocation;
 import org.apache.ofbiz.base.util.Debug;
 import org.apache.ofbiz.base.util.UtilDateTime;
@@ -101,7 +100,7 @@ public class ImageManagementServices {
     }
 
     public static Map<String, Object> 
addMultipleuploadForProduct(DispatchContext dctx,
-            Map<String, ? extends Object> context) throws ImageReadException {
+            Map<String, ? extends Object> context) {
 
         Map<String, Object> result = new HashMap<>();
         LocalDispatcher dispatcher = dctx.getDispatcher();
@@ -602,7 +601,7 @@ public class ImageManagementServices {
     }
 
     public static Map<String, Object> createContentThumbnail(DispatchContext 
dctx, Map<String, ? extends Object> context,
-            GenericValue userLogin, ByteBuffer imageData, String productId, 
String imageName) throws ImageReadException {
+            GenericValue userLogin, ByteBuffer imageData, String productId, 
String imageName) {
         Map<String, Object> result = new HashMap<>();
         LocalDispatcher dispatcher = dctx.getDispatcher();
         Delegator delegator = dctx.getDelegator();
diff --git 
a/applications/product/src/main/java/org/apache/ofbiz/product/product/ProductServices.java
 
b/applications/product/src/main/java/org/apache/ofbiz/product/product/ProductServices.java
index 73f3e04b6e..d08b2ce3ce 100644
--- 
a/applications/product/src/main/java/org/apache/ofbiz/product/product/ProductServices.java
+++ 
b/applications/product/src/main/java/org/apache/ofbiz/product/product/ProductServices.java
@@ -41,7 +41,6 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 
-import org.apache.commons.imaging.ImageReadException;
 import org.apache.ofbiz.base.util.Debug;
 import org.apache.ofbiz.base.util.UtilDateTime;
 import org.apache.ofbiz.base.util.UtilGenerics;
@@ -971,7 +970,7 @@ public class ProductServices {
     }
 
     public static Map<String, Object> 
addAdditionalViewForProduct(DispatchContext dctx,
-            Map<String, ? extends Object> context) throws ImageReadException {
+            Map<String, ? extends Object> context) {
 
         LocalDispatcher dispatcher = dctx.getDispatcher();
         Delegator delegator = dctx.getDelegator();
@@ -1438,7 +1437,7 @@ public class ProductServices {
                 Debug.logError(e, MODULE);
                 return 
ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE,
                         "ProductImageViewUnableWriteFile", 
UtilMisc.toMap("fileName", file.getAbsolutePath()), locale));
-            } catch (IOException | ImageReadException e) {
+            } catch (IOException e) {
                 Debug.logError(e, MODULE);
                 return 
ServiceUtil.returnError(UtilProperties.getMessage(RESOURCE,
                         "ProductImageViewUnableWriteBinaryData", 
UtilMisc.toMap("fileName", file.getAbsolutePath()), locale));
diff --git a/dependencies.gradle b/dependencies.gradle
index 1bd025ae68..20a7f9f510 100644
--- a/dependencies.gradle
+++ b/dependencies.gradle
@@ -32,6 +32,7 @@ dependencies {
     implementation libs.utils.mail.dkim
     implementation libs.rome
     implementation libs.xstream
+    implementation libs.twelvemonkeys.imageio.tiff
     implementation libs.commons.cli
     implementation libs.commons.net
     implementation libs.commons.validator
@@ -44,7 +45,6 @@ dependencies {
     implementation libs.commons.csv
     implementation libs.commons.dbcp2
     implementation libs.commons.fileupload2.jakarta
-    implementation libs.commons.imaging
     implementation libs.commons.text
     implementation libs.geronimo.transaction
     implementation libs.geronimo.jms.spec
diff --git 
a/framework/base/src/main/java/org/apache/ofbiz/base/util/HttpRequestFileUpload.java
 
b/framework/base/src/main/java/org/apache/ofbiz/base/util/HttpRequestFileUpload.java
index 0c72894e06..fcc06e328c 100644
--- 
a/framework/base/src/main/java/org/apache/ofbiz/base/util/HttpRequestFileUpload.java
+++ 
b/framework/base/src/main/java/org/apache/ofbiz/base/util/HttpRequestFileUpload.java
@@ -31,7 +31,6 @@ import java.util.Map;
 import jakarta.servlet.ServletInputStream;
 import jakarta.servlet.http.HttpServletRequest;
 
-import org.apache.commons.imaging.ImageReadException;
 import org.apache.ofbiz.entity.Delegator;
 
 /**
@@ -291,9 +290,6 @@ public class HttpRequestFileUpload {
                         if (!fileToValidate.equals(fileTocheck)) {
                             new File(fileToValidate).renameTo(new 
File(fileTocheck));
                         }
-                    } catch (ImageReadException e) {
-                        Debug.logError(e, MODULE);
-                        return false;
                     }
                 } else {
                     // this is a field
diff --git 
a/framework/security/src/main/java/org/apache/ofbiz/security/SecuredUpload.java 
b/framework/security/src/main/java/org/apache/ofbiz/security/SecuredUpload.java
index 363a658be0..c860af85c8 100644
--- 
a/framework/security/src/main/java/org/apache/ofbiz/security/SecuredUpload.java
+++ 
b/framework/security/src/main/java/org/apache/ofbiz/security/SecuredUpload.java
@@ -23,6 +23,7 @@ import java.awt.Graphics;
 import java.awt.Image;
 import java.awt.Transparency;
 import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.DataInputStream;
 import java.io.File;
@@ -71,16 +72,6 @@ import org.apache.batik.anim.dom.SAXSVGDocumentFactory;
 import org.apache.batik.util.XMLResourceDescriptor;
 import org.apache.commons.csv.CSVFormat;
 import org.apache.commons.csv.CSVParser;
-import org.apache.commons.imaging.ImageFormat;
-import org.apache.commons.imaging.ImageFormats;
-import org.apache.commons.imaging.ImageInfo;
-import org.apache.commons.imaging.ImageParser;
-import org.apache.commons.imaging.ImageReadException;
-import org.apache.commons.imaging.ImageWriteException;
-import org.apache.commons.imaging.Imaging;
-import org.apache.commons.imaging.formats.gif.GifImageParser;
-import org.apache.commons.imaging.formats.png.PngImageParser;
-import org.apache.commons.imaging.formats.tiff.TiffImageParser;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.lang.StringUtils;
@@ -118,6 +109,8 @@ import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 import org.xml.sax.SAXException;
 
+import com.drew.imaging.FileType;
+import com.drew.imaging.FileTypeDetector;
 import com.drew.imaging.ImageMetadataReader;
 import com.drew.imaging.ImageProcessingException;
 import com.drew.metadata.Directory;
@@ -403,9 +396,8 @@ public class SecuredUpload {
      * @param delegator
      * @return true if the file is valid
      * @throws IOException
-     * @throws ImageReadException
      */
-    public static boolean isValidAllFile(String fileToCheck, Delegator 
delegator) throws IOException, ImageReadException {
+    public static boolean isValidAllFile(String fileToCheck, Delegator 
delegator) throws IOException {
         return isValidFile(fileToCheck, "All", delegator);
     }
 
@@ -414,9 +406,8 @@ public class SecuredUpload {
      * @param fileType
      * @return true if the file is valid
      * @throws IOException
-     * @throws ImageReadException
      */
-    public static boolean isValidFile(String fileToCheck, String fileType, 
Delegator delegator) throws IOException, ImageReadException {
+    public static boolean isValidFile(String fileToCheck, String fileType, 
Delegator delegator) throws IOException {
         // Allow all uploads w/o check
         if 
(("true".equalsIgnoreCase(EntityUtilProperties.getPropertyValue("security", 
"allowAllUploads", delegator)))) {
             return true;
@@ -546,16 +537,16 @@ public class SecuredUpload {
      * Is it a supported image format?
      * @param fileName
      * @return true if it's a valid image file
-     * @throws IOException ImageReadException
+     * @throws IOException
      */
-    private static boolean isValidImageFile(String fileName) throws 
ImageReadException, IOException {
+    private static boolean isValidImageFile(String fileName) throws 
IOException {
         Path filePath = Paths.get(fileName);
         byte[] bytesFromFile = Files.readAllBytes(filePath);
-        ImageFormat imageFormat = Imaging.guessFormat(bytesFromFile);
-        boolean knownRasterFormat = imageFormat.equals(ImageFormats.PNG)
-                || imageFormat.equals(ImageFormats.GIF)
-                || imageFormat.equals(ImageFormats.TIFF)
-                || imageFormat.equals(ImageFormats.JPEG);
+        FileType fileType = FileTypeDetector.detectFileType(new 
ByteArrayInputStream(bytesFromFile));
+        boolean knownRasterFormat = fileType == FileType.Png
+                || fileType == FileType.Gif
+                || fileType == FileType.Tiff
+                || fileType == FileType.Jpeg;
         if (!knownRasterFormat) {
             return false;
         }
@@ -569,12 +560,12 @@ public class SecuredUpload {
     /**
      * Implementation based on 
https://github.com/righettod/document-upload-protection sanitizer for Image 
file. See
      * 
https://github.com/righettod/document-upload-protection/blob/master/src/main/java/eu/righettod/poc/sanitizer/ImageDocumentSanitizerImpl.java
-     * Uses Java built-in API in complement of Apache Commons Imaging for 
format not supported by the built-in API. See
-     * http://commons.apache.org/proper/commons-imaging/ and 
http://commons.apache.org/proper/commons-imaging/formatsupport.html
+     * PNG, GIF and JPEG are supported by the JDK's built-in ImageIO; TIFF 
support comes from the TwelveMonkeys
+     * ImageIO plugin (com.twelvemonkeys.imageio:imageio-tiff), registered 
transparently as an ImageIO service
+     * provider, so no format-specific fallback code is needed here.
      */
     private static boolean imageMadeSafe(String fileName) {
         File file = new File(fileName);
-        boolean fallbackOnApacheCommonsImaging;
 
         if (!noWebshellInMetadata(file)) {
             return false;
@@ -595,31 +586,17 @@ public class SecuredUpload {
             try {
                 // Get the image format
                 String formatName;
-                ImageInputStream iis = ImageIO.createImageInputStream(file);
-                Iterator<ImageReader> imageReaderIterator = 
ImageIO.getImageReaders(iis);
-                // If there not ImageReader instance found so it's means that 
the current format is not supported by the Java built-in API
-                if (!imageReaderIterator.hasNext()) {
-                    ImageInfo imageInfo = Imaging.getImageInfo(file);
-                    if (imageInfo != null && imageInfo.getFormat() != null && 
imageInfo.getFormat().getName() != null) {
-                        formatName = imageInfo.getFormat().getName();
-                        fallbackOnApacheCommonsImaging = true;
-                    } else {
+                try (ImageInputStream iis = 
ImageIO.createImageInputStream(file)) {
+                    Iterator<ImageReader> imageReaderIterator = 
ImageIO.getImageReaders(iis);
+                    if (!imageReaderIterator.hasNext()) {
                         throw new IOException("Format of the original image " 
+ fileName + " is not supported for read operation !");
                     }
-                } else {
                     ImageReader reader = imageReaderIterator.next();
                     formatName = reader.getFormatName();
-                    fallbackOnApacheCommonsImaging = false;
-                    iis.close(); // This was not correctly handled in the 
document-upload-protection example, and I did not spot it :/
                 }
 
                 // Load the image
-                BufferedImage originalImage;
-                if (!fallbackOnApacheCommonsImaging) {
-                    originalImage = ImageIO.read(file);
-                } else {
-                    originalImage = Imaging.getBufferedImage(file);
-                }
+                BufferedImage originalImage = ImageIO.read(file);
 
                 // Check that image has been successfully loaded
                 if (originalImage == null) {
@@ -646,34 +623,11 @@ public class SecuredUpload {
                 // Open the output stream only after the sanitized image is 
ready, so that
                 // TRUNCATE_EXISTING does not wipe the file before it has been 
read.
                 try (OutputStream fos = Files.newOutputStream(file.toPath(), 
StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING)) {
-                    if (!fallbackOnApacheCommonsImaging) {
-                        ImageIO.write(sanitizedImage, formatName, fos);
-                    } else {
-                        ImageParser<?> imageParser;
-                        // Handle only formats for which Apache Commons 
Imaging can successfully write (YES in Write column of the reference link)
-                        // the image format. See reference link in the class 
header
-                        switch (formatName) {
-                        case "TIFF":
-                            imageParser = new TiffImageParser();
-                            break;
-                        case "GIF":
-                            imageParser = new GifImageParser();
-                            break;
-                        case "PNG":
-                            imageParser = new PngImageParser();
-                            break;
-                        // case "JPEG":
-                        // imageParser = new JpegImageParser(); // Does not 
provide imageParser.writeImage used below
-                        // break;
-                        default:
-                            throw new IOException("Format of the original 
image " + fileName + " is not supported for write operation !");
-                        }
-                        imageParser.writeImage(sanitizedImage, fos, null);
-                    }
+                    ImageIO.write(sanitizedImage, formatName, fos);
                 }
                 // Set state flag
                 safeState = true;
-            } catch (IOException | ImageReadException | ImageWriteException e) 
{
+            } catch (IOException e) {
                 Debug.logWarning(e, "Error during Image file " + fileName + " 
processing !", MODULE);
             }
         }
@@ -762,7 +716,7 @@ public class SecuredUpload {
     private static boolean noWebshellInJPEG(File file) {
         try {
             byte[] bytes = Files.readAllBytes(file.toPath());
-            if (!Imaging.guessFormat(bytes).equals(ImageFormats.JPEG)) {
+            if (FileTypeDetector.detectFileType(new 
ByteArrayInputStream(bytes)) != FileType.Jpeg) {
                 return true; // Not a JPEG file, it's OK so far
             }
             // SOI marker check
@@ -833,7 +787,7 @@ public class SecuredUpload {
     private static boolean noWebshellInGIF(File file) {
         try {
             byte[] bytes = Files.readAllBytes(file.toPath());
-            if (!Imaging.guessFormat(bytes).equals(ImageFormats.GIF)) {
+            if (FileTypeDetector.detectFileType(new 
ByteArrayInputStream(bytes)) != FileType.Gif) {
                 return true; // Not a GIF file, it's OK so far
             }
             // Header: "GIF87a" or "GIF89a"
@@ -914,8 +868,7 @@ public class SecuredUpload {
     private static boolean isPNG(File file) throws IOException {
         Path filePath = Paths.get(file.getPath());
         byte[] bytesFromFile = Files.readAllBytes(filePath);
-        ImageFormat imageFormat = Imaging.guessFormat(bytesFromFile);
-        return (imageFormat.equals(ImageFormats.PNG));
+        return FileTypeDetector.detectFileType(new 
ByteArrayInputStream(bytesFromFile)) == FileType.Png;
     }
 
     private static boolean inflate(byte[] data) {
@@ -960,9 +913,9 @@ public class SecuredUpload {
      * Is it a supported image format, including SVG?
      * @param fileName
      * @return true if it's a valid image file
-     * @throws IOException ImageReadException
+     * @throws IOException
      */
-    private static boolean isValidImageIncludingSvgFile(String fileName) 
throws ImageReadException, IOException {
+    private static boolean isValidImageIncludingSvgFile(String fileName) 
throws IOException {
         return isValidImageFile(fileName) || isValidSvgFile(fileName);
     }
 
@@ -1156,9 +1109,9 @@ public class SecuredUpload {
      * http://commons.apache.org/proper/commons-compress/examples.html
      * @param fileName
      * @return true if it's a valid compressed file
-     * @throws IOException ImageReadException
+     * @throws IOException
      */
-    private static boolean isValidCompressedFile(String fileName, Delegator 
delegator) throws IOException, ImageReadException {
+    private static boolean isValidCompressedFile(String fileName, Delegator 
delegator) throws IOException {
         String mimeType = getMimeTypeFromFileName(fileName);
         // I planned to handle more formats but did only ZIP
         // The code can be extended based on that
@@ -1214,7 +1167,7 @@ public class SecuredUpload {
         return null;
     }
 
-    private static boolean isValidDirectoryInCompressedFile(String folderName, 
Delegator delegator) throws IOException, ImageReadException {
+    private static boolean isValidDirectoryInCompressedFile(String folderName, 
Delegator delegator) throws IOException {
         File folder = new File(folderName);
         Collection<File> files = FileUtils.listFiles(folder, null, true);
         for (File f : files) {
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 0e308ddd06..5a55c6bd3a 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -32,6 +32,7 @@ angus-mail = "2.0.5"
 utils-mail-dkim = "3.3.0"
 rome = "2.1.0"
 xstream = "1.4.21"
+twelvemonkeys-imageio-tiff = "3.14.0"
 commons-cli = "1.11.0"
 commons-net = "3.13.0"
 commons-validator = "1.11.0"
@@ -44,10 +45,6 @@ commons-collections4 = "4.6.0"
 commons-csv = "1.14.1"
 commons-dbcp2 = "2.14.0"
 commons-fileupload2-jakarta = "2.0.0-M1"
-# Alpha but OK, "Imaging was working and was used by a number of projects in 
production even before
-# reaching its initial release as an Apache Commons component." Since 
1.0.0-alpha4 (note the use of
-# semver) the API has changed. Better wait an "official release" to rewrite 
OFBiz code...
-commons-imaging = "1.0-alpha3"
 commons-text = "1.15.0"
 # 4.0.0 does not compile
 geronimo-transaction = "3.1.5"
@@ -130,6 +127,7 @@ angus-mail = { module = "org.eclipse.angus:angus-mail", 
version.ref = "angus-mai
 utils-mail-dkim = { module = "org.simplejavamail:utils-mail-dkim", version.ref 
= "utils-mail-dkim" }
 rome = { module = "com.rometools:rome", version.ref = "rome" }
 xstream = { module = "com.thoughtworks.xstream:xstream", version.ref = 
"xstream" }
+twelvemonkeys-imageio-tiff = { module = 
"com.twelvemonkeys.imageio:imageio-tiff", version.ref = 
"twelvemonkeys-imageio-tiff" }
 commons-cli = { module = "commons-cli:commons-cli", version.ref = 
"commons-cli" }
 commons-net = { module = "commons-net:commons-net", version.ref = 
"commons-net" }
 commons-validator = { module = "commons-validator:commons-validator", 
version.ref = "commons-validator" }
@@ -142,7 +140,6 @@ commons-collections4 = { module = 
"org.apache.commons:commons-collections4", ver
 commons-csv = { module = "org.apache.commons:commons-csv", version.ref = 
"commons-csv" }
 commons-dbcp2 = { module = "org.apache.commons:commons-dbcp2", version.ref = 
"commons-dbcp2" }
 commons-fileupload2-jakarta = { module = 
"org.apache.commons:commons-fileupload2-jakarta", version.ref = 
"commons-fileupload2-jakarta" }
-commons-imaging = { module = "org.apache.commons:commons-imaging", version.ref 
= "commons-imaging" }
 commons-text = { module = "org.apache.commons:commons-text", version.ref = 
"commons-text" }
 geronimo-transaction = { module = 
"org.apache.geronimo.components:geronimo-transaction", version.ref = 
"geronimo-transaction" }
 geronimo-jms-spec = { module = 
"org.apache.geronimo.specs:geronimo-jms_1.1_spec", version.ref = 
"geronimo-jms-spec" }

Reply via email to