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

fanningpj 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 87c4c38792 HSLF: support passing password as a param (#1023)
87c4c38792 is described below

commit 87c4c38792e55c90d892152c5147a4f0c8094b15
Author: PJ Fanning <[email protected]>
AuthorDate: Thu Mar 5 09:51:18 2026 +0100

    HSLF: support passing password as a param (#1023)
    
    * HSLF: support passing password as a param
    
    * Update TestDocumentEncryption.java
---
 .../apache/poi/hslf/usermodel/HSLFSlideShow.java   | 42 ++++++++++++-
 .../poi/hslf/usermodel/HSLFSlideShowEncrypted.java | 22 ++++++-
 .../poi/hslf/usermodel/HSLFSlideShowImpl.java      | 68 +++++++++++++++++++---
 .../poi/hslf/record/TestDocumentEncryption.java    | 23 +++++---
 4 files changed, 133 insertions(+), 22 deletions(-)

diff --git 
a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShow.java 
b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShow.java
index 9e020cfd4b..1d8a1f3e18 100644
--- 
a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShow.java
+++ 
b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShow.java
@@ -175,33 +175,69 @@ public final class HSLFSlideShow extends POIDocument 
implements SlideShow<HSLFSh
      * @throws IllegalStateException a number of runtime exceptions can be 
thrown, especially if there are problems with the
      * input format
      */
-    @SuppressWarnings("resource")
     public HSLFSlideShow(InputStream inputStream) throws IOException {
         this(new HSLFSlideShowImpl(inputStream));
     }
 
+    /**
+     * Constructs a Powerpoint document from an input stream.
+     * @param inputStream stream containing ppt data
+     * @param password in char array format (can be null)
+     * @throws IOException If reading data from the stream fails
+     * @throws IllegalStateException a number of runtime exceptions can be 
thrown, especially if there are problems with the
+     * input format
+     * @since 6.0.0
+     */
+    public HSLFSlideShow(InputStream inputStream, char[] password) throws 
IOException {
+        this(new HSLFSlideShowImpl(inputStream, password));
+    }
+
     /**
      * Constructs a Powerpoint document from an POIFSFileSystem.
      * @throws IOException If reading data from the file-system fails
      * @throws IllegalStateException a number of runtime exceptions can be 
thrown, especially if there are problems with the
      * input format
      */
-    @SuppressWarnings("resource")
     public HSLFSlideShow(POIFSFileSystem poifs) throws IOException {
         this(new HSLFSlideShowImpl(poifs));
     }
 
+    /**
+     * Constructs a Powerpoint document from an POIFSFileSystem.
+     * @param poifs POIFSFileSystem containing ppt data
+     * @param password in char array format (can be null)
+     * @throws IOException If reading data from the file-system fails
+     * @throws IllegalStateException a number of runtime exceptions can be 
thrown, especially if there are problems with the
+     * input format
+     * @since 6.0.0
+     */
+    public HSLFSlideShow(POIFSFileSystem poifs, char[] password) throws 
IOException {
+        this(new HSLFSlideShowImpl(poifs, password));
+    }
+
     /**
      * Constructs a Powerpoint document from an DirectoryNode.
      * @throws IOException If reading data from the DirectoryNode fails
      * @throws IllegalStateException a number of runtime exceptions can be 
thrown, especially if there are problems with the
      * input format
      */
-    @SuppressWarnings("resource")
     public HSLFSlideShow(DirectoryNode root) throws IOException {
         this(new HSLFSlideShowImpl(root));
     }
 
+    /**
+     * Constructs a Powerpoint document from an DirectoryNode.
+     * @param root DirectoryNode containing ppt data
+     * @param password in char array format (can be null)
+     * @throws IOException If reading data from the DirectoryNode fails
+     * @throws IllegalStateException a number of runtime exceptions can be 
thrown, especially if there are problems with the
+     * input format
+     * @since 6.0.0
+     */
+    public HSLFSlideShow(DirectoryNode root, char[] password) throws 
IOException {
+        this(new HSLFSlideShowImpl(root, password));
+    }
+
     /**
      * @return the current loading/saving phase
      */
diff --git 
a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShowEncrypted.java
 
b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShowEncrypted.java
index f98c05fec1..62853c7bc9 100644
--- 
a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShowEncrypted.java
+++ 
b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShowEncrypted.java
@@ -79,7 +79,23 @@ public class HSLFSlideShowEncrypted implements Closeable {
         this.dea = dea;
     }
 
-    protected HSLFSlideShowEncrypted(byte[] docstream, 
NavigableMap<Integer,Record> recordMap) {
+    protected HSLFSlideShowEncrypted(byte[] docstream, NavigableMap<Integer, 
Record> recordMap) {
+        this(docstream, recordMap, (String) null);
+    }
+
+    /**
+     * @param docstream
+     * @param recordMap
+     * @param password in char array format (can be null)
+     * @since 6.0.0
+     */
+    protected HSLFSlideShowEncrypted(byte[] docstream, NavigableMap<Integer, 
Record> recordMap,
+                                     char[] password) {
+        this(docstream, recordMap, password == null ? null : new 
String(password));
+    }
+
+    private HSLFSlideShowEncrypted(byte[] docstream, NavigableMap<Integer, 
Record> recordMap,
+                                   String password) {
         // check for DocumentEncryptionAtom, which would be at the last offset
         // need to ignore already set UserEdit and PersistAtoms
         UserEditAtom userEditAtomWithEncryption = null;
@@ -125,7 +141,7 @@ public class HSLFSlideShowEncrypted implements Closeable {
         }
         this.dea = (DocumentEncryptionAtom)r;
 
-        String pass = Biff8EncryptionKey.getCurrentUserPassword();
+        final String pass = password == null ? 
Biff8EncryptionKey.getCurrentUserPassword() : password;
         EncryptionInfo ei = getEncryptionInfo();
         try {
             if (ei == null || ei.getDecryptor() == null) {
@@ -137,7 +153,7 @@ public class HSLFSlideShowEncrypted implements Closeable {
         } catch (GeneralSecurityException e) {
             throw new EncryptedPowerPointFileException(e);
         }
-     }
+    }
 
     public DocumentEncryptionAtom getDocumentEncryptionAtom() {
         return dea;
diff --git 
a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java
 
b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java
index 51eaf30f01..2983369062 100644
--- 
a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java
+++ 
b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java
@@ -132,11 +132,23 @@ public final class HSLFSlideShowImpl extends POIDocument 
implements Closeable {
      * @param fileName The name of the file to read.
      * @throws IOException if there is a problem while parsing the document.
      */
-    @SuppressWarnings("resource")
     public HSLFSlideShowImpl(String fileName) throws IOException {
         this(new POIFSFileSystem(new File(fileName)));
     }
 
+    /**
+     * Constructs a Powerpoint document from fileName. Parses the document
+     * and places all the important stuff into data structures.
+     *
+     * @param fileName The name of the file to read.
+     * @param password in char array format (can be null)
+     * @throws IOException if there is a problem while parsing the document.
+     * @since 6.0.0
+     */
+    public HSLFSlideShowImpl(String fileName, char[] password) throws 
IOException {
+        this(new POIFSFileSystem(new File(fileName)), password);
+    }
+
     /**
      * Constructs a Powerpoint document from an input stream. Parses the
      * document and places all the important stuff into data structures.
@@ -144,12 +156,25 @@ public final class HSLFSlideShowImpl extends POIDocument 
implements Closeable {
      * @param inputStream the source of the data
      * @throws IOException if there is a problem while parsing the document.
      */
-    @SuppressWarnings("resource")
     public HSLFSlideShowImpl(InputStream inputStream) throws IOException {
         //do Ole stuff
         this(new POIFSFileSystem(inputStream));
     }
 
+    /**
+     * Constructs a Powerpoint document from an input stream. Parses the
+     * document and places all the important stuff into data structures.
+     *
+     * @param inputStream the source of the data
+     * @param password in char array format (can be null)
+     * @throws IOException if there is a problem while parsing the document.
+     * @since 6.0.0
+     */
+    public HSLFSlideShowImpl(InputStream inputStream, char[] password) throws 
IOException {
+        //do Ole stuff
+        this(new POIFSFileSystem(inputStream), password);
+    }
+
     /**
      * Constructs a Powerpoint document from a POIFS Filesystem. Parses the
      * document and places all the important stuff into data structures.
@@ -161,6 +186,19 @@ public final class HSLFSlideShowImpl extends POIDocument 
implements Closeable {
         this(filesystem.getRoot());
     }
 
+    /**
+     * Constructs a Powerpoint document from a POIFS Filesystem. Parses the
+     * document and places all the important stuff into data structures.
+     *
+     * @param filesystem the POIFS FileSystem to read from
+     * @param password in char array format (can be null)
+     * @throws IOException if there is a problem while parsing the document.
+     * @since 6.0.0
+     */
+    public HSLFSlideShowImpl(POIFSFileSystem filesystem, char[] password) 
throws IOException {
+        this(filesystem.getRoot(), password);
+    }
+
     /**
      * Constructs a Powerpoint document from a specific point in a
      * POIFS Filesystem. Parses the document and places all the
@@ -170,6 +208,20 @@ public final class HSLFSlideShowImpl extends POIDocument 
implements Closeable {
      * @throws IOException if there is a problem while parsing the document.
      */
     public HSLFSlideShowImpl(DirectoryNode dir) throws IOException {
+        this(dir, null);
+    }
+
+    /**
+     * Constructs a Powerpoint document from a specific point in a
+     * POIFS Filesystem. Parses the document and places all the
+     * important stuff into data structures.
+     *
+     * @param dir the POIFS directory to read from
+     * @param password in char array format (can be null)
+     * @throws IOException if there is a problem while parsing the document.
+     * @since 6.0.0
+     */
+    public HSLFSlideShowImpl(DirectoryNode dir, char[] password) throws 
IOException {
         super(handleDualStorage(dir));
 
         try {
@@ -182,7 +234,7 @@ public final class HSLFSlideShowImpl extends POIDocument 
implements Closeable {
             readPowerPointStream();
 
             // Now, build records based on the PowerPoint stream
-            buildRecords();
+            buildRecords(password);
 
             // Look for any other streams
             readOtherStreams();
@@ -248,7 +300,7 @@ public final class HSLFSlideShowImpl extends POIDocument 
implements Closeable {
      * Builds the list of records, based on the contents
      * of the PowerPoint stream
      */
-    private void buildRecords() throws IOException {
+    private void buildRecords(char[] password) throws IOException {
         // The format of records in a powerpoint file are:
         //   <little endian 2 byte "info">
         //   <little endian 2 byte "type">
@@ -282,16 +334,16 @@ public final class HSLFSlideShowImpl extends POIDocument 
implements Closeable {
         //  its length to know where the next record will start)
         //
 
-        _records = read(_docstream, (int) currentUser.getCurrentEditOffset());
+        _records = read(_docstream, (int) currentUser.getCurrentEditOffset(), 
password);
     }
 
-    private Record[] read(byte[] docstream, int usrOffset) throws IOException {
+    private Record[] read(byte[] docstream, int usrOffset, char[] password) 
throws IOException {
         //sort found records by offset.
         //(it is not necessary but SlideShow.findMostRecentCoreRecords() 
expects them sorted)
         NavigableMap<Integer, Record> records = new TreeMap<>(); // offset -> 
record
         Map<Integer, Integer> persistIds = new HashMap<>(); // offset -> 
persistId
         initRecordOffsets(docstream, usrOffset, records, persistIds);
-        HSLFSlideShowEncrypted decryptData = new 
HSLFSlideShowEncrypted(docstream, records);
+        HSLFSlideShowEncrypted decryptData = new 
HSLFSlideShowEncrypted(docstream, records, password);
 
         for (Map.Entry<Integer, Record> entry : records.entrySet()) {
             Integer offset = entry.getKey();
@@ -999,7 +1051,7 @@ public final class HSLFSlideShowImpl extends POIDocument 
implements Closeable {
         Document documentRecord = null;
         for (Record record : _records) {
             if (record == null) {
-                throw new CorruptPowerPointFileException("Did not have a valid 
record: " + record);
+                throw new CorruptPowerPointFileException("Did not have a valid 
record: null");
             }
             if (record.getRecordType() == RecordTypes.Document.typeID) {
                 if (!(record instanceof Document)) {
diff --git 
a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestDocumentEncryption.java
 
b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestDocumentEncryption.java
index d1ec21733f..65cbad9ef8 100644
--- 
a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestDocumentEncryption.java
+++ 
b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestDocumentEncryption.java
@@ -58,6 +58,19 @@ public class TestDocumentEncryption {
         "Password_Protected-np-hello.ppt"
     })
     void cryptoAPIDecryptionOther(String pptFile) throws Exception {
+        try (POIFSFileSystem fs = new 
POIFSFileSystem(slTests.getFile(pptFile), true);
+             HSLFSlideShow ppt = new HSLFSlideShow(fs, "hello".toCharArray())) 
{
+            assertFalse(ppt.getSlides().isEmpty());
+        }
+    }
+
+    @ParameterizedTest
+    @ValueSource(strings = {
+            "Password_Protected-56-hello.ppt",
+            "Password_Protected-hello.ppt",
+            "Password_Protected-np-hello.ppt"
+    })
+    void cryptoAPIDecryptionOtherBiff8EncryptionKey(String pptFile) throws 
Exception {
         Biff8EncryptionKey.setCurrentUserPassword("hello");
         try {
             try (POIFSFileSystem fs = new 
POIFSFileSystem(slTests.getFile(pptFile), true);
@@ -72,9 +85,8 @@ public class TestDocumentEncryption {
     @Test
     void cryptoAPIChangeKeySize() throws Exception {
         String pptFile = "cryptoapi-proc2356.ppt";
-        Biff8EncryptionKey.setCurrentUserPassword("crypto");
         try (POIFSFileSystem fs = new 
POIFSFileSystem(slTests.getFile(pptFile), true);
-             HSLFSlideShowImpl hss = new HSLFSlideShowImpl(fs)) {
+             HSLFSlideShowImpl hss = new HSLFSlideShowImpl(fs, 
"crypto".toCharArray())) {
             // need to cache data (i.e. read all data) before changing the key 
size
             List<HSLFPictureData> picsExpected = hss.getPictureData();
             hss.getDocumentSummaryInformation();
@@ -95,8 +107,6 @@ public class TestDocumentEncryption {
                     assertArrayEquals(picsExpected.get(i).getRawData(), 
picsActual.get(i).getRawData());
                 }
             }
-        } finally {
-            Biff8EncryptionKey.setCurrentUserPassword(null);
         }
     }
 
@@ -139,9 +149,8 @@ public class TestDocumentEncryption {
     void cryptoAPIDecryption() throws Exception {
         // taken from a msdn blog:
         // 
http://blogs.msdn.com/b/openspecification/archive/2009/05/08/dominic-salemno.aspx
-        Biff8EncryptionKey.setCurrentUserPassword("crypto");
         try (POIFSFileSystem fs = new 
POIFSFileSystem(slTests.getFile("cryptoapi-proc2356.ppt"));
-             HSLFSlideShow ss = new HSLFSlideShow(fs)) {
+             HSLFSlideShow ss = new HSLFSlideShow(fs, "crypto".toCharArray())) 
{
 
             HSLFSlide slide = ss.getSlides().get(0);
             String rawText = 
HSLFTextParagraph.getRawText(slide.getTextParagraphs().get(0));
@@ -181,8 +190,6 @@ public class TestDocumentEncryption {
                 assertTrue(ps.isDocumentSummaryInformation());
                 assertEquals("On-screen Show (4:3)", 
ps.getProperties()[1].getValue());
             }
-        } finally {
-            Biff8EncryptionKey.setCurrentUserPassword(null);
         }
     }
 }


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

Reply via email to