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

pjfanning pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/poi.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 8862c12fcb add util to normalize path (#1125)
8862c12fcb is described below

commit 8862c12fcb5a146cc27a270d6206a24f5819baac
Author: PJ Fanning <[email protected]>
AuthorDate: Tue Jun 9 10:26:49 2026 +0100

    add util to normalize path (#1125)
---
 .../src/test/java/org/apache/poi/stress/AbstractFileHandler.java | 3 ++-
 .../src/test/java/org/apache/poi/stress/HPSFFileHandler.java     | 3 ++-
 .../src/test/java/org/apache/poi/stress/StressMap.java           | 5 +++--
 .../src/test/java/org/apache/poi/stress/StressTestUtils.java     | 4 +++-
 .../src/test/java/org/apache/poi/stress/TestAllFiles.java        | 3 ++-
 .../java/org/apache/poi/openxml4j/opc/PackagingURIHelper.java    | 7 +++----
 .../org/apache/poi/openxml4j/util/ZipFileZipEntrySource.java     | 5 +++--
 .../apache/poi/openxml4j/util/ZipInputStreamZipEntrySource.java  | 7 ++++---
 .../main/java/org/apache/poi/openxml4j/util/ZipSecureFile.java   | 3 ++-
 .../apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java  | 3 ++-
 poi/src/main/java/org/apache/poi/util/IOUtils.java               | 9 +++++++++
 11 files changed, 35 insertions(+), 17 deletions(-)

diff --git 
a/poi-integration/src/test/java/org/apache/poi/stress/AbstractFileHandler.java 
b/poi-integration/src/test/java/org/apache/poi/stress/AbstractFileHandler.java
index c9c6165283..ec651afb13 100644
--- 
a/poi-integration/src/test/java/org/apache/poi/stress/AbstractFileHandler.java
+++ 
b/poi-integration/src/test/java/org/apache/poi/stress/AbstractFileHandler.java
@@ -37,6 +37,7 @@ import org.apache.poi.hpsf.extractor.HPSFPropertiesExtractor;
 import org.apache.poi.hssf.extractor.EventBasedExcelExtractor;
 import org.apache.poi.ooxml.POIXMLException;
 import org.apache.poi.ss.extractor.ExcelExtractor;
+import org.apache.poi.util.IOUtils;
 
 /**
  * Base class with things that can be run for any supported file handler
@@ -92,7 +93,7 @@ public abstract class AbstractFileHandler implements 
FileHandler {
             handleExtractingAsStream(file);
 
             // fix windows absolute paths for exception message tracking
-            String relPath = file.getPath().replaceAll(".*test-data", 
"test-data").replace('\\', '/');
+            String relPath = 
IOUtils.normalizePath(file.getPath().replaceAll(".*test-data", "test-data"));
             try (POITextExtractor extractor = 
ExtractorFactory.createExtractor(file)) {
                 assertNotNull(extractor, "Should get a POITextExtractor but 
had none for file " + relPath);
 
diff --git 
a/poi-integration/src/test/java/org/apache/poi/stress/HPSFFileHandler.java 
b/poi-integration/src/test/java/org/apache/poi/stress/HPSFFileHandler.java
index 9edd92306f..46c1af4cc0 100644
--- a/poi-integration/src/test/java/org/apache/poi/stress/HPSFFileHandler.java
+++ b/poi-integration/src/test/java/org/apache/poi/stress/HPSFFileHandler.java
@@ -39,6 +39,7 @@ import org.apache.poi.hpsf.extractor.HPSFPropertiesExtractor;
 import org.apache.poi.poifs.filesystem.DirectoryNode;
 import org.apache.poi.poifs.filesystem.DocumentInputStream;
 import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+import org.apache.poi.util.IOUtils;
 import org.apache.poi.util.TempFile;
 import org.junit.jupiter.api.Test;
 
@@ -69,7 +70,7 @@ public class HPSFFileHandler extends POIFSFileHandler {
              HPSFPropertiesExtractor extractor = new 
HPSFPropertiesExtractor(poifs)) {
 
             String fileAndParentName = file.getParentFile().getName() + "/" + 
file.getName();
-            String relPath = file.getPath().replaceAll(".*test-data", 
"test-data").replace('\\', '/');
+            String relPath = 
IOUtils.normalizePath(file.getPath().replaceAll(".*test-data", "test-data"));
 
             
assertFalse(EXPECTED_EXTRACTOR_FAILURES.contains(fileAndParentName),
                 "Expected Extraction to fail for file " + relPath + " and 
handler " + this + ", but did not fail!");
diff --git a/poi-integration/src/test/java/org/apache/poi/stress/StressMap.java 
b/poi-integration/src/test/java/org/apache/poi/stress/StressMap.java
index 234eb0f8c4..32f26e67f1 100644
--- a/poi-integration/src/test/java/org/apache/poi/stress/StressMap.java
+++ b/poi-integration/src/test/java/org/apache/poi/stress/StressMap.java
@@ -33,6 +33,7 @@ import 
org.apache.commons.collections4.multimap.ArrayListValuedHashMap;
 import org.apache.commons.csv.CSVFormat;
 import org.apache.commons.csv.CSVRecord;
 import org.apache.commons.io.input.BOMInputStream;
+import org.apache.poi.util.IOUtils;
 import org.opentest4j.AssertionFailedError;
 
 public class StressMap {
@@ -48,7 +49,7 @@ public class StressMap {
 
     public List<FileHandlerKnown> getHandler(String file) {
         // ... failures/handlers lookup doesn't work on windows otherwise
-        final String uniFile = file.replace('\\', '/');
+        final String uniFile = IOUtils.normalizePath(file);
 
         String firstHandler = handlerMap.entrySet().stream()
             .filter(me -> uniFile.endsWith(me.getKey()))
@@ -62,7 +63,7 @@ public class StressMap {
 
     public ExcInfo getExcInfo(String file, String testName, FileHandlerKnown 
handler) {
         // ... failures/handlers lookup doesn't work on windows otherwise
-        final String uniFile = file.replace('\\', '/');
+        final String uniFile = IOUtils.normalizePath(file);
 
         return exMap.get(uniFile).stream()
             .filter(e -> e.isMatch(testName, handler.name()))
diff --git 
a/poi-integration/src/test/java/org/apache/poi/stress/StressTestUtils.java 
b/poi-integration/src/test/java/org/apache/poi/stress/StressTestUtils.java
index 4d34326d23..8e10d7add5 100644
--- a/poi-integration/src/test/java/org/apache/poi/stress/StressTestUtils.java
+++ b/poi-integration/src/test/java/org/apache/poi/stress/StressTestUtils.java
@@ -16,6 +16,8 @@
 ==================================================================== */
 package org.apache.poi.stress;
 
+import org.apache.poi.util.IOUtils;
+
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
@@ -27,7 +29,7 @@ public class StressTestUtils {
     }
 
     static boolean excludeFile(String path, Set<String> excludeSet) {
-        String modifiedPath = path.replace('\\', '/');
+        String modifiedPath = IOUtils.normalizePath(path);
         return excludeSet.contains(modifiedPath);
     }
 }
diff --git 
a/poi-integration/src/test/java/org/apache/poi/stress/TestAllFiles.java 
b/poi-integration/src/test/java/org/apache/poi/stress/TestAllFiles.java
index a88ea32396..00589d5133 100644
--- a/poi-integration/src/test/java/org/apache/poi/stress/TestAllFiles.java
+++ b/poi-integration/src/test/java/org/apache/poi/stress/TestAllFiles.java
@@ -35,6 +35,7 @@ import java.util.stream.Stream;
 
 import org.apache.poi.POIDataSamples;
 import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
+import org.apache.poi.util.IOUtils;
 import org.apache.tools.ant.DirectoryScanner;
 import org.junit.jupiter.api.Assumptions;
 import org.junit.jupiter.api.function.Executable;
@@ -340,7 +341,7 @@ public class TestAllFiles {
         if (msg == null) return null;
 
         // Windows path replacement
-        msg = msg.replace('\\', '/');
+        msg = IOUtils.normalizePath(msg);
 
         // Adjust file paths to remove unwanted file path info.
         int filePathIndex = msg.indexOf(ROOT_DIR.toString());
diff --git 
a/poi-ooxml/src/main/java/org/apache/poi/openxml4j/opc/PackagingURIHelper.java 
b/poi-ooxml/src/main/java/org/apache/poi/openxml4j/opc/PackagingURIHelper.java
index 58718a6f32..c2e87ac5e1 100644
--- 
a/poi-ooxml/src/main/java/org/apache/poi/openxml4j/opc/PackagingURIHelper.java
+++ 
b/poi-ooxml/src/main/java/org/apache/poi/openxml4j/opc/PackagingURIHelper.java
@@ -27,6 +27,7 @@ import org.apache.logging.log4j.Logger;
 import org.apache.poi.logging.PoiLogManager;
 import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
 import org.apache.poi.openxml4j.exceptions.InvalidOperationException;
+import org.apache.poi.util.IOUtils;
 
 /**
  * Helper for part and pack URI.
@@ -686,9 +687,7 @@ public final class PackagingURIHelper {
      */
     public static URI toURI(String value) throws URISyntaxException  {
         //5. Convert all back slashes to forward slashes
-        if (value.contains("\\")) {
-             value = value.replace('\\', '/');
-        }
+        value = IOUtils.normalizePath(value);
 
         // URI fragments (those starting with '#') are not encoded
         // and may contain white spaces and raw unicode characters
@@ -704,7 +703,7 @@ public final class PackagingURIHelper {
         if(!value.isEmpty()){
             StringBuilder b = new StringBuilder();
             int idx = value.length() - 1;
-            for(; idx >= 0; idx--){
+            for(; idx >= 0; idx--) {
                 char c = value.charAt(idx);
                 if(Character.isWhitespace(c) || c == '\u00A0') {
                     b.append(c);
diff --git 
a/poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipFileZipEntrySource.java
 
b/poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipFileZipEntrySource.java
index 406e62f1ed..d1322fef30 100644
--- 
a/poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipFileZipEntrySource.java
+++ 
b/poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipFileZipEntrySource.java
@@ -22,6 +22,7 @@ import java.util.Enumeration;
 
 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
 import org.apache.commons.compress.archivers.zip.ZipFile;
+import org.apache.poi.util.IOUtils;
 
 /**
  * A ZipEntrySource wrapper around a ZipFile.
@@ -66,7 +67,7 @@ public class ZipFileZipEntrySource implements ZipEntrySource {
 
     @Override
     public ZipArchiveEntry getEntry(final String path) {
-        String normalizedPath = path.replace('\\', '/');
+        String normalizedPath = IOUtils.normalizePath(path);
 
         final ZipArchiveEntry entry = zipArchive.getEntry(normalizedPath);
         if (entry != null) {
@@ -77,7 +78,7 @@ public class ZipFileZipEntrySource implements ZipEntrySource {
         final Enumeration<ZipArchiveEntry> zipArchiveEntryEnumeration = 
zipArchive.getEntries();
         while (zipArchiveEntryEnumeration.hasMoreElements()) {
             ZipArchiveEntry ze = zipArchiveEntryEnumeration.nextElement();
-            if (normalizedPath.equalsIgnoreCase(ze.getName().replace('\\', 
'/'))) {
+            if 
(normalizedPath.equalsIgnoreCase(IOUtils.normalizePath(ze.getName()))) {
                 return ze;
             }
         }
diff --git 
a/poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipInputStreamZipEntrySource.java
 
b/poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipInputStreamZipEntrySource.java
index 37fa35e615..dfb9a1230f 100644
--- 
a/poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipInputStreamZipEntrySource.java
+++ 
b/poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipInputStreamZipEntrySource.java
@@ -28,6 +28,7 @@ import java.util.Set;
 
 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
 import org.apache.poi.openxml4j.opc.internal.InvalidZipException;
+import org.apache.poi.util.IOUtils;
 
 /**
  * Provides a way to get at all the ZipEntries
@@ -106,7 +107,7 @@ public class ZipInputStreamZipEntrySource implements 
ZipEntrySource {
             if (name == null || name.isEmpty()) {
                 throw new InvalidZipException("Input file contains an entry 
with an empty name");
             }
-            name = name.replace('\\', '/').toLowerCase(Locale.ROOT);
+            name = IOUtils.normalizePath(name).toLowerCase(Locale.ROOT);
             if (filenames.contains(name)) {
                 throw new InvalidZipException("Input file contains more than 1 
entry with the name " + zipEntry.getName());
             }
@@ -147,14 +148,14 @@ public class ZipInputStreamZipEntrySource implements 
ZipEntrySource {
 
     @Override
     public ZipArchiveEntry getEntry(final String path) {
-        final String normalizedPath = path.replace('\\', '/');
+        final String normalizedPath = IOUtils.normalizePath(path);
         final ZipArchiveEntry ze = zipEntries.get(normalizedPath);
         if (ze != null) {
             return ze;
         }
 
         for (final Map.Entry<String, ZipArchiveFakeEntry> fze : 
zipEntries.entrySet()) {
-            if (normalizedPath.equalsIgnoreCase(fze.getKey())) {
+            if 
(normalizedPath.equalsIgnoreCase(IOUtils.normalizePath(fze.getKey()))) {
                 return fze.getValue();
             }
         }
diff --git 
a/poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipSecureFile.java 
b/poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipSecureFile.java
index fbcc97ac2d..e303e8da97 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipSecureFile.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipSecureFile.java
@@ -29,6 +29,7 @@ import org.apache.commons.compress.archivers.zip.ZipFile;
 import org.apache.logging.log4j.Logger;
 import org.apache.poi.logging.PoiLogManager;
 import org.apache.poi.openxml4j.opc.internal.InvalidZipException;
+import org.apache.poi.util.IOUtils;
 import org.apache.poi.util.Internal;
 import org.apache.poi.util.Removal;
 
@@ -274,7 +275,7 @@ public class ZipSecureFile extends ZipFile {
             if (name == null || name.isEmpty()) {
                 throw new InvalidZipException("Input file contains an entry 
with an empty name");
             }
-            name = name.replace('\\', '/').toLowerCase(Locale.ROOT);
+            name = IOUtils.normalizePath(name).toLowerCase(Locale.ROOT);
             if (filenames.contains(name)) {
                 throw new InvalidZipException("Input file contains more than 1 
entry with the name " + entry.getName());
             }
diff --git 
a/poi-ooxml/src/main/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java
 
b/poi-ooxml/src/main/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java
index d7c6d070bd..a8092053dc 100644
--- 
a/poi-ooxml/src/main/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java
+++ 
b/poi-ooxml/src/main/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java
@@ -70,6 +70,7 @@ import org.apache.poi.poifs.crypt.dsig.SignatureConfig;
 import org.apache.poi.poifs.crypt.dsig.SignatureInfo;
 import org.apache.poi.poifs.crypt.dsig.services.RelationshipTransformService;
 import 
org.apache.poi.poifs.crypt.dsig.services.RelationshipTransformService.RelationshipTransformParameterSpec;
+import org.apache.poi.util.IOUtils;
 import 
org.openxmlformats.schemas.xpackage.x2006.digitalSignature.CTSignatureTime;
 import 
org.openxmlformats.schemas.xpackage.x2006.digitalSignature.SignatureTimeDocument;
 import org.w3c.dom.Document;
@@ -216,7 +217,7 @@ public class OOXMLSignatureFacet implements SignatureFacet {
             pn = baseUri + pn;
         }
         try {
-            pn = new URI(pn).normalize().getPath().replace('\\', '/');
+            pn = IOUtils.normalizePath(new URI(pn).normalize().getPath());
             LOG.atDebug().log("part name: {}", pn);
         } catch (URISyntaxException e) {
             throw new XMLSignatureException(e);
diff --git a/poi/src/main/java/org/apache/poi/util/IOUtils.java 
b/poi/src/main/java/org/apache/poi/util/IOUtils.java
index 97782e7ffe..652fcbd19c 100644
--- a/poi/src/main/java/org/apache/poi/util/IOUtils.java
+++ b/poi/src/main/java/org/apache/poi/util/IOUtils.java
@@ -747,6 +747,15 @@ public final class IOUtils {
         return file;
     }
 
+    /**
+     * Replaces Windows Style `\` chars with `/` to allow path comparisons.
+     *
+     * @since 6.0.0
+     */
+    public static String normalizePath(final String path) {
+        return path == null ? path : path.replace('\\', '/');
+    }
+
     private static void throwRFE(long length, int maxLength) {
         throwRFE(length, maxLength, "IOUtils.setByteArrayMaxOverride()");
     }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to