You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ki...@apache.org on 2016/08/03 23:54:02 UTC

svn commit: r1755127 [3/3] - in /poi/branches/hssf_cryptoapi/src: java/org/apache/poi/ java/org/apache/poi/hssf/record/ java/org/apache/poi/poifs/crypt/ java/org/apache/poi/poifs/crypt/binaryrc4/ java/org/apache/poi/poifs/crypt/cryptoapi/ java/org/apac...

Modified: poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowEncrypted.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowEncrypted.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowEncrypted.java (original)
+++ poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowEncrypted.java Wed Aug  3 23:54:01 2016
@@ -17,6 +17,8 @@
 
 package org.apache.poi.hslf.usermodel;
 
+import java.io.Closeable;
+import java.io.IOException;
 import java.io.OutputStream;
 import java.security.GeneralSecurityException;
 import java.util.ArrayList;
@@ -25,9 +27,6 @@ import java.util.Map;
 import java.util.NavigableMap;
 import java.util.TreeMap;
 
-import javax.crypto.Cipher;
-import javax.crypto.CipherOutputStream;
-
 import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException;
 import org.apache.poi.hslf.exceptions.EncryptedPowerPointFileException;
 import org.apache.poi.hslf.record.DocumentEncryptionAtom;
@@ -36,26 +35,45 @@ import org.apache.poi.hslf.record.Positi
 import org.apache.poi.hslf.record.Record;
 import org.apache.poi.hslf.record.UserEditAtom;
 import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
+import org.apache.poi.poifs.crypt.ChunkedCipherInputStream;
+import org.apache.poi.poifs.crypt.ChunkedCipherOutputStream;
 import org.apache.poi.poifs.crypt.Decryptor;
 import org.apache.poi.poifs.crypt.EncryptionInfo;
 import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIDecryptor;
 import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIEncryptor;
 import org.apache.poi.util.BitField;
+import org.apache.poi.util.IOUtils;
 import org.apache.poi.util.Internal;
 import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianByteArrayInputStream;
+import org.apache.poi.util.LittleEndianByteArrayOutputStream;
 
 /**
  * This class provides helper functions for encrypted PowerPoint documents.
  */
 @Internal
-public class HSLFSlideShowEncrypted {
+public class HSLFSlideShowEncrypted implements Closeable {
     DocumentEncryptionAtom dea;
     CryptoAPIEncryptor enc = null;
     CryptoAPIDecryptor dec = null;
-    Cipher cipher = null;
-    CipherOutputStream cyos = null;
+//    Cipher cipher = null;
+    ChunkedCipherOutputStream cyos = null;
 
     private static final BitField fieldRecInst = new BitField(0xFFF0);
+
+    private static final int BLIB_STORE_ENTRY_PARTS[] = {
+        1,     // btWin32
+        1,     // btMacOS
+        16,    // rgbUid
+        2,     // tag
+        4,     // size
+        4,     // cRef
+        4,     // foDelay
+        1,     // unused1
+        1,     // cbName (@ index 33)
+        1,     // unused2
+        1,     // unused3
+    };
     
     protected HSLFSlideShowEncrypted(DocumentEncryptionAtom dea) {
         this.dea = dea;
@@ -67,7 +85,9 @@ public class HSLFSlideShowEncrypted {
         UserEditAtom userEditAtomWithEncryption = null;
         for (Map.Entry<Integer, Record> me : recordMap.descendingMap().entrySet()) {
             Record r = me.getValue();
-            if (!(r instanceof UserEditAtom)) continue;
+            if (!(r instanceof UserEditAtom)) {
+                continue;
+            }
             UserEditAtom uea = (UserEditAtom)r;
             if (uea.getEncryptSessionPersistIdRef() != -1) {
                 userEditAtomWithEncryption = uea;
@@ -83,7 +103,7 @@ public class HSLFSlideShowEncrypted {
         Record r = recordMap.get(userEditAtomWithEncryption.getPersistPointersOffset());
         assert(r instanceof PersistPtrHolder);
         PersistPtrHolder ptr = (PersistPtrHolder)r;
-        
+
         Integer encOffset = ptr.getSlideLocationsLookup().get(userEditAtomWithEncryption.getEncryptSessionPersistIdRef());
         if (encOffset == null) {
             // encryption info doesn't exist anymore
@@ -91,7 +111,7 @@ public class HSLFSlideShowEncrypted {
             dea = null;
             return;
         }
-        
+
         r = recordMap.get(encOffset);
         if (r == null) {
             r = Record.buildRecordAtOffset(docstream, encOffset);
@@ -100,7 +120,7 @@ public class HSLFSlideShowEncrypted {
         assert(r instanceof DocumentEncryptionAtom);
         this.dea = (DocumentEncryptionAtom)r;
         decryptInit();
-        
+
         String pass = Biff8EncryptionKey.getCurrentUserPassword();
         if(!dec.verifyPassword(pass != null ? pass : Decryptor.DEFAULT_PASSWORD)) {
             throw new EncryptedPowerPointFileException("PowerPoint file is encrypted. The correct password needs to be set via Biff8EncryptionKey.setCurrentUserPassword()");
@@ -110,119 +130,144 @@ public class HSLFSlideShowEncrypted {
     public DocumentEncryptionAtom getDocumentEncryptionAtom() {
         return dea;
     }
-    
-    protected void setPersistId(int persistId) {
-        if (enc != null && dec != null) {
-            throw new EncryptedPowerPointFileException("Use instance either for en- or decryption");
-        }
-        
-        try {
-            if (enc != null) cipher = enc.initCipherForBlock(cipher, persistId);
-            if (dec != null) cipher = dec.initCipherForBlock(cipher, persistId);
-        } catch (GeneralSecurityException e) {
-            throw new EncryptedPowerPointFileException(e);
-        }
-    }
-    
+
     protected void decryptInit() {
-        if (dec != null) return;
+        if (dec != null) {
+            return;
+        }
         EncryptionInfo ei = dea.getEncryptionInfo();
         dec = (CryptoAPIDecryptor)ei.getDecryptor();
     }
-    
+
     protected void encryptInit() {
-        if (enc != null) return;
+        if (enc != null) {
+            return;
+        }
         EncryptionInfo ei = dea.getEncryptionInfo();
         enc = (CryptoAPIEncryptor)ei.getEncryptor();
     }
-    
 
-    
+
+
     protected OutputStream encryptRecord(OutputStream plainStream, int persistId, Record record) {
-        boolean isPlain = (dea == null 
+        boolean isPlain = (dea == null
             || record instanceof UserEditAtom
             || record instanceof PersistPtrHolder
             || record instanceof DocumentEncryptionAtom
         );
-        if (isPlain) return plainStream;
 
-        encryptInit();
-        setPersistId(persistId);
-        
-        if (cyos == null) {
-            cyos = new CipherOutputStream(plainStream, cipher);
+        try {
+            if (isPlain) {
+                if (cyos != null) {
+                    // write cached data to stream
+                    cyos.flush();
+                }
+                return plainStream;
+            }
+
+            encryptInit();
+
+            if (cyos == null) {
+                enc.setChunkSize(-1);
+                cyos = enc.getDataStream(plainStream);
+            }
+            cyos.initCipherForBlock(persistId, false);
+        } catch (Exception e) {
+            throw new EncryptedPowerPointFileException(e);
         }
         return cyos;
     }
 
+    private static void readFully(ChunkedCipherInputStream ccis, byte[] docstream, int offset, int len) throws IOException {
+        if (IOUtils.readFully(ccis, docstream, offset, len) == -1) {
+            throw new EncryptedPowerPointFileException("unexpected EOF");
+        }
+    }
+
     protected void decryptRecord(byte[] docstream, int persistId, int offset) {
-        if (dea == null) return;
+        if (dea == null) {
+            return;
+        }
 
         decryptInit();
-        setPersistId(persistId);
-        
+        dec.setChunkSize(-1);
+        LittleEndianByteArrayInputStream lei = new LittleEndianByteArrayInputStream(docstream, offset);
+        ChunkedCipherInputStream ccis = null;
         try {
+            ccis = dec.getDataStream(lei, docstream.length-offset, 0);
+            ccis.initCipherForBlock(persistId);
+
             // decrypt header and read length to be decrypted
-            cipher.update(docstream, offset, 8, docstream, offset);
+            readFully(ccis, docstream, offset, 8);
             // decrypt the rest of the record
             int rlen = (int)LittleEndian.getUInt(docstream, offset+4);
-            cipher.update(docstream, offset+8, rlen, docstream, offset+8);
-        } catch (GeneralSecurityException e) {
-            throw new CorruptPowerPointFileException(e);
-        }       
-    }        
+            readFully(ccis, docstream, offset+8, rlen);
+
+        } catch (Exception e) {
+            throw new EncryptedPowerPointFileException(e);
+        } finally {
+            try {
+                if (ccis != null) {
+                    ccis.close();
+                }
+                lei.close();
+            } catch (IOException e) {
+                throw new EncryptedPowerPointFileException(e);
+            }
+        }
+    }
+
+    private void decryptPicBytes(byte[] pictstream, int offset, int len)
+    throws IOException, GeneralSecurityException {
+        // when reading the picture elements, each time a segment is read, the cipher needs
+        // to be reset (usually done when calling Cipher.doFinal)
+        LittleEndianByteArrayInputStream lei = new LittleEndianByteArrayInputStream(pictstream, offset);
+        ChunkedCipherInputStream ccis = dec.getDataStream(lei, len, 0);
+        readFully(ccis, pictstream, offset, len);
+        ccis.close();
+        lei.close();
+    }
     
     protected void decryptPicture(byte[] pictstream, int offset) {
-        if (dea == null) return;
-        
+        if (dea == null) {
+            return;
+        }
+
         decryptInit();
-        setPersistId(0);
-        
+
         try {
             // decrypt header and read length to be decrypted
-            cipher.doFinal(pictstream, offset, 8, pictstream, offset);
+            decryptPicBytes(pictstream, offset, 8);
             int recInst = fieldRecInst.getValue(LittleEndian.getUShort(pictstream, offset));
             int recType = LittleEndian.getUShort(pictstream, offset+2);
             int rlen = (int)LittleEndian.getUInt(pictstream, offset+4);
             offset += 8;
-            int endOffset = offset + rlen; 
+            int endOffset = offset + rlen;
 
             if (recType == 0xF007) {
                 // TOOD: get a real example file ... to actual test the FBSE entry
                 // not sure where the foDelay block is
-                
+
                 // File BLIP Store Entry (FBSE)
-                cipher.doFinal(pictstream, offset, 1, pictstream, offset); // btWin32
-                offset++;
-                cipher.doFinal(pictstream, offset, 1, pictstream, offset); // btMacOS
-                offset++;
-                cipher.doFinal(pictstream, offset, 16, pictstream, offset); // rgbUid
-                offset += 16;
-                cipher.doFinal(pictstream, offset, 2, pictstream, offset); // tag
-                offset += 2;
-                cipher.doFinal(pictstream, offset, 4, pictstream, offset); // size
-                offset += 4;
-                cipher.doFinal(pictstream, offset, 4, pictstream, offset); // cRef
-                offset += 4;
-                cipher.doFinal(pictstream, offset, 4, pictstream, offset); // foDelay
-                offset += 4;
-                cipher.doFinal(pictstream, offset+0, 1, pictstream, offset+0); // unused1
-                cipher.doFinal(pictstream, offset+1, 1, pictstream, offset+1); // cbName
-                cipher.doFinal(pictstream, offset+2, 1, pictstream, offset+2); // unused2
-                cipher.doFinal(pictstream, offset+3, 1, pictstream, offset+3); // unused3
-                int cbName = LittleEndian.getUShort(pictstream, offset+1);
-                offset += 4;
+                for (int part : BLIB_STORE_ENTRY_PARTS) {
+                    decryptPicBytes(pictstream, offset, part);
+                }
+                offset += 36;
+                
+                int cbName = LittleEndian.getUShort(pictstream, offset-3);
                 if (cbName > 0) {
-                    cipher.doFinal(pictstream, offset, cbName, pictstream, offset); // nameData
+                    // read nameData
+                    decryptPicBytes(pictstream, offset, cbName);
                     offset += cbName;
                 }
+                
                 if (offset == endOffset) {
                     return; // no embedded blip
                 }
                 // fall through, read embedded blip now
 
                 // update header data
-                cipher.doFinal(pictstream, offset, 8, pictstream, offset);
+                decryptPicBytes(pictstream, offset, 8);
                 recInst = fieldRecInst.getValue(LittleEndian.getUShort(pictstream, offset));
                 recType = LittleEndian.getUShort(pictstream, offset+2);
                 // rlen = (int)LittleEndian.getUInt(pictstream, offset+4);
@@ -231,70 +276,73 @@ public class HSLFSlideShowEncrypted {
 
             int rgbUidCnt = (recInst == 0x217 || recInst == 0x3D5 || recInst == 0x46B || recInst == 0x543 ||
                 recInst == 0x6E1 || recInst == 0x6E3 || recInst == 0x6E5 || recInst == 0x7A9) ? 2 : 1;
-            
+
+            // rgbUid 1/2
             for (int i=0; i<rgbUidCnt; i++) {
-                cipher.doFinal(pictstream, offset, 16, pictstream, offset); // rgbUid 1/2
+                decryptPicBytes(pictstream, offset, 16);
                 offset += 16;
             }
-            
+
+            int nextBytes;
             if (recType == 0xF01A || recType == 0XF01B || recType == 0XF01C) {
-                cipher.doFinal(pictstream, offset, 34, pictstream, offset); // metafileHeader
-                offset += 34;
+                // metafileHeader
+                nextBytes = 34;
             } else {
-                cipher.doFinal(pictstream, offset, 1, pictstream, offset); // tag
-                offset += 1;
+                // tag
+                nextBytes = 1;
             }
             
+            decryptPicBytes(pictstream, offset, nextBytes);
+            offset += nextBytes;
+
             int blipLen = endOffset - offset;
-            cipher.doFinal(pictstream, offset, blipLen, pictstream, offset);
-        } catch (GeneralSecurityException e) {
+            decryptPicBytes(pictstream, offset, blipLen);
+        } catch (Exception e) {
             throw new CorruptPowerPointFileException(e);
-        }       
+        }
     }
 
     protected void encryptPicture(byte[] pictstream, int offset) {
-        if (dea == null) return;
-        
+        if (dea == null) {
+            return;
+        }
+
         encryptInit();
-        setPersistId(0);
+
+        LittleEndianByteArrayOutputStream los = new LittleEndianByteArrayOutputStream(pictstream, offset);
+        ChunkedCipherOutputStream ccos = null;
 
         try {
+            enc.setChunkSize(-1);
+            ccos = enc.getDataStream(los);
             int recInst = fieldRecInst.getValue(LittleEndian.getUShort(pictstream, offset));
             int recType = LittleEndian.getUShort(pictstream, offset+2);
-            int rlen = (int)LittleEndian.getUInt(pictstream, offset+4);
-            cipher.doFinal(pictstream, offset, 8, pictstream, offset);
+            final int rlen = (int)LittleEndian.getUInt(pictstream, offset+4);
+
+            ccos.write(pictstream, offset, 8);
+            ccos.flush();
             offset += 8;
-            int endOffset = offset + rlen; 
+            int endOffset = offset + rlen;
 
             if (recType == 0xF007) {
                 // TOOD: get a real example file ... to actual test the FBSE entry
                 // not sure where the foDelay block is
-                
+
                 // File BLIP Store Entry (FBSE)
-                cipher.doFinal(pictstream, offset, 1, pictstream, offset); // btWin32
-                offset++;
-                cipher.doFinal(pictstream, offset, 1, pictstream, offset); // btMacOS
-                offset++;
-                cipher.doFinal(pictstream, offset, 16, pictstream, offset); // rgbUid
-                offset += 16;
-                cipher.doFinal(pictstream, offset, 2, pictstream, offset); // tag
-                offset += 2;
-                cipher.doFinal(pictstream, offset, 4, pictstream, offset); // size
-                offset += 4;
-                cipher.doFinal(pictstream, offset, 4, pictstream, offset); // cRef
-                offset += 4;
-                cipher.doFinal(pictstream, offset, 4, pictstream, offset); // foDelay
-                offset += 4;
-                int cbName = LittleEndian.getUShort(pictstream, offset+1);
-                cipher.doFinal(pictstream, offset+0, 1, pictstream, offset+0); // unused1
-                cipher.doFinal(pictstream, offset+1, 1, pictstream, offset+1); // cbName
-                cipher.doFinal(pictstream, offset+2, 1, pictstream, offset+2); // unused2
-                cipher.doFinal(pictstream, offset+3, 1, pictstream, offset+3); // unused3
-                offset += 4;
+                int cbName = LittleEndian.getUShort(pictstream, offset+33);
+                
+                for (int part : BLIB_STORE_ENTRY_PARTS) {
+                    ccos.write(pictstream, offset, part);
+                    ccos.flush();
+                    offset += part;
+                }
+                
                 if (cbName > 0) {
-                    cipher.doFinal(pictstream, offset, cbName, pictstream, offset); // nameData
+                    ccos.write(pictstream, offset, cbName);
+                    ccos.flush();
                     offset += cbName;
                 }
+                
                 if (offset == endOffset) {
                     return; // no embedded blip
                 }
@@ -303,32 +351,45 @@ public class HSLFSlideShowEncrypted {
                 // update header data
                 recInst = fieldRecInst.getValue(LittleEndian.getUShort(pictstream, offset));
                 recType = LittleEndian.getUShort(pictstream, offset+2);
-                // rlen = (int) LittleEndian.getUInt(pictstream, offset+4);
-                cipher.doFinal(pictstream, offset, 8, pictstream, offset);
+                ccos.write(pictstream, offset, 8);
+                ccos.flush();
                 offset += 8;
             }
-            
+
             int rgbUidCnt = (recInst == 0x217 || recInst == 0x3D5 || recInst == 0x46B || recInst == 0x543 ||
                 recInst == 0x6E1 || recInst == 0x6E3 || recInst == 0x6E5 || recInst == 0x7A9) ? 2 : 1;
-                
+
             for (int i=0; i<rgbUidCnt; i++) {
-                cipher.doFinal(pictstream, offset, 16, pictstream, offset); // rgbUid 1/2
+                ccos.write(pictstream, offset, 16); // rgbUid 1/2
+                ccos.flush();
                 offset += 16;
             }
-            
+
             if (recType == 0xF01A || recType == 0XF01B || recType == 0XF01C) {
-                cipher.doFinal(pictstream, offset, 34, pictstream, offset); // metafileHeader
+                ccos.write(pictstream, offset, 34); // metafileHeader
                 offset += 34;
+                ccos.flush();
             } else {
-                cipher.doFinal(pictstream, offset, 1, pictstream, offset); // tag
+                ccos.write(pictstream, offset, 1); // tag
                 offset += 1;
+                ccos.flush();
             }
-            
+
             int blipLen = endOffset - offset;
-            cipher.doFinal(pictstream, offset, blipLen, pictstream, offset);
-        } catch (GeneralSecurityException e) {
-            throw new CorruptPowerPointFileException(e);
-        }       
+            ccos.write(pictstream, offset, blipLen);
+            ccos.flush();
+        } catch (Exception e) {
+            throw new EncryptedPowerPointFileException(e);
+        } finally {
+            try {
+                if (ccos != null) {
+                    ccos.close();
+                }
+                los.close();
+            } catch (IOException e) {
+                throw new EncryptedPowerPointFileException(e);
+            }
+        }
     }
 
     protected Record[] updateEncryptionRecord(Record records[]) {
@@ -372,7 +433,7 @@ public class HSLFSlideShowEncrypted {
     protected static Record[] normalizeRecords(Record records[]) {
         // http://msdn.microsoft.com/en-us/library/office/gg615594(v=office.14).aspx
         // repeated slideIds can be overwritten, i.e. ignored
-        
+
         UserEditAtom uea = null;
         PersistPtrHolder pph = null;
         TreeMap<Integer,Integer> slideLocations = new TreeMap<Integer,Integer>();
@@ -386,7 +447,7 @@ public class HSLFSlideShowEncrypted {
                 uea = (UserEditAtom)pdr;
                 continue;
             }
-            
+
             if (pdr instanceof PersistPtrHolder) {
                 if (pph != null) {
                     duplicatedCount++;
@@ -394,16 +455,18 @@ public class HSLFSlideShowEncrypted {
                 pph = (PersistPtrHolder)pdr;
                 for (Map.Entry<Integer,Integer> me : pph.getSlideLocationsLookup().entrySet()) {
                     Integer oldOffset = slideLocations.put(me.getKey(), me.getValue());
-                    if (oldOffset != null) obsoleteOffsets.add(oldOffset);
+                    if (oldOffset != null) {
+                        obsoleteOffsets.add(oldOffset);
+                    }
                 }
                 continue;
             }
-            
+
             recordMap.put(pdr.getLastOnDiskOffset(), r);
         }
-        
+
         assert(uea != null && pph != null && uea.getPersistPointersOffset() == pph.getLastOnDiskOffset());
-        
+
         recordMap.put(pph.getLastOnDiskOffset(), pph);
         recordMap.put(uea.getLastOnDiskOffset(), uea);
 
@@ -416,15 +479,15 @@ public class HSLFSlideShowEncrypted {
         for (Map.Entry<Integer,Integer> me : slideLocations.entrySet()) {
             pph.addSlideLookup(me.getKey(), me.getValue());
         }
-        
+
         for (Integer oldOffset : obsoleteOffsets) {
             recordMap.remove(oldOffset);
         }
-        
+
         return recordMap.values().toArray(new Record[recordMap.size()]);
     }
-     
-    
+
+
     protected static Record[] removeEncryptionRecord(Record records[]) {
         int deaSlideId = -1;
         int deaOffset = -1;
@@ -444,23 +507,27 @@ public class HSLFSlideShowEncrypted {
             }
             recordList.add(r);
         }
-        
+
         assert(ptr != null);
-        if (deaSlideId == -1 && deaOffset == -1) return records;
-        
+        if (deaSlideId == -1 && deaOffset == -1) {
+            return records;
+        }
+
         TreeMap<Integer,Integer> tm = new TreeMap<Integer,Integer>(ptr.getSlideLocationsLookup());
         ptr.clear();
         int maxSlideId = -1;
         for (Map.Entry<Integer,Integer> me : tm.entrySet()) {
-            if (me.getKey() == deaSlideId || me.getValue() == deaOffset) continue;
+            if (me.getKey() == deaSlideId || me.getValue() == deaOffset) {
+                continue;
+            }
             ptr.addSlideLookup(me.getKey(), me.getValue());
             maxSlideId = Math.max(me.getKey(), maxSlideId);
         }
-        
+
         uea.setMaxPersistWritten(maxSlideId);
 
         records = recordList.toArray(new Record[recordList.size()]);
-        
+
         return records;
     }
 
@@ -470,9 +537,13 @@ public class HSLFSlideShowEncrypted {
         int ueaIdx = -1, ptrIdx = -1, deaIdx = -1, idx = -1;
         for (Record r : records) {
             idx++;
-            if (r instanceof UserEditAtom) ueaIdx = idx;
-            else if (r instanceof PersistPtrHolder) ptrIdx = idx;
-            else if (r instanceof DocumentEncryptionAtom) deaIdx = idx;
+            if (r instanceof UserEditAtom) {
+                ueaIdx = idx;
+            } else if (r instanceof PersistPtrHolder) {
+                ptrIdx = idx;
+            } else if (r instanceof DocumentEncryptionAtom) {
+                deaIdx = idx;
+            }
         }
         assert(ueaIdx != -1 && ptrIdx != -1 && ptrIdx < ueaIdx);
         if (deaIdx != -1) {
@@ -488,13 +559,22 @@ public class HSLFSlideShowEncrypted {
             ptr.addSlideLookup(nextSlideId, ptr.getLastOnDiskOffset()-1);
             uea.setEncryptSessionPersistIdRef(nextSlideId);
             uea.setMaxPersistWritten(nextSlideId);
-            
+
             Record newRecords[] = new Record[records.length+1];
-            if (ptrIdx > 0) System.arraycopy(records, 0, newRecords, 0, ptrIdx);
-            if (ptrIdx < records.length-1) System.arraycopy(records, ptrIdx, newRecords, ptrIdx+1, records.length-ptrIdx);
+            if (ptrIdx > 0) {
+                System.arraycopy(records, 0, newRecords, 0, ptrIdx);
+            }
+            if (ptrIdx < records.length-1) {
+                System.arraycopy(records, ptrIdx, newRecords, ptrIdx+1, records.length-ptrIdx);
+            }
             newRecords[ptrIdx] = dea;
             return newRecords;
         }
     }
 
+    public void close() throws IOException {
+        if (cyos != null) {
+            cyos.close();
+        }
+    }
 }

Modified: poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java (original)
+++ poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java Wed Aug  3 23:54:01 2016
@@ -54,6 +54,7 @@ import org.apache.poi.poifs.filesystem.E
 import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
 import org.apache.poi.poifs.filesystem.POIFSFileSystem;
 import org.apache.poi.sl.usermodel.PictureData.PictureType;
+import org.apache.poi.util.IOUtils;
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
@@ -205,14 +206,12 @@ public final class HSLFSlideShowImpl ext
 
 		// Grab the document stream
 		int len = docProps.getSize();
-		_docstream = new byte[len];
-		InputStream is = directory.createDocumentInputStream("PowerPoint Document");
-		int readLen = is.read(_docstream);
-		is.close();
-		
-		if (len != readLen) {
-		    throw new IOException("Document input stream ended prematurely - expected "+len+" bytes - received "+readLen+" bytes");
-		}
+        InputStream is = directory.createDocumentInputStream("PowerPoint Document");
+        try {
+            _docstream = IOUtils.toByteArray(is, len);
+        } finally {
+            is.close();
+        }
 	}
 
 	/**
@@ -364,17 +363,10 @@ public final class HSLFSlideShowImpl ext
         HSLFSlideShowEncrypted decryptData = new HSLFSlideShowEncrypted(getDocumentEncryptionAtom());
         
 		DocumentEntry entry = (DocumentEntry)directory.getEntry("Pictures");
-		int len = entry.getSize();
-		byte[] pictstream = new byte[len];
-		DocumentInputStream is = directory.createDocumentInputStream(entry);
-		int readLen = is.read(pictstream);
+        DocumentInputStream is = directory.createDocumentInputStream(entry);
+		byte[] pictstream = IOUtils.toByteArray(is, entry.getSize());
 		is.close();
 
-		if (len != readLen) {
-		    throw new IOException("Picture stream ended prematurely - expected "+len+" bytes - received "+readLen+" bytes");
-		}
-
-		
         int pos = 0;
 		// An empty picture record (length 0) will take up 8 bytes
         while (pos <= (pictstream.length-8)) {
@@ -512,7 +504,7 @@ public final class HSLFSlideShowImpl ext
         }
         
         HSLFSlideShowEncrypted encData = new HSLFSlideShowEncrypted(getDocumentEncryptionAtom());
-	    
+        
 	    for (Record record : _records) {
             assert(record instanceof PositionDependentRecord);
             // We've already figured out their new location, and
@@ -533,6 +525,8 @@ public final class HSLFSlideShowImpl ext
                 record.writeOut(encData.encryptRecord(os, persistId, record));
             }
         }
+	    
+	    encData.close();
 
         // Update and write out the Current User atom
         int oldLastUserEditAtomPos = (int)currentUser.getCurrentEditOffset();
@@ -733,7 +727,7 @@ public final class HSLFSlideShowImpl ext
         if (dea != null) {
             CryptoAPIEncryptor enc = (CryptoAPIEncryptor)dea.getEncryptionInfo().getEncryptor();
             try {
-                enc.getDataStream(outFS.getRoot()); // ignore OutputStream
+                enc.getSummaryEntries(outFS.getRoot()); // ignore OutputStream
             } catch (IOException e) {
                 throw e;
             } catch (GeneralSecurityException e) {

Modified: poi/branches/hssf_cryptoapi/src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocumentEncryption.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocumentEncryption.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocumentEncryption.java (original)
+++ poi/branches/hssf_cryptoapi/src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocumentEncryption.java Wed Aug  3 23:54:01 2016
@@ -25,6 +25,7 @@ import static org.junit.Assert.fail;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
+import java.io.FileOutputStream;
 import java.security.MessageDigest;
 import java.util.List;
 
@@ -44,6 +45,7 @@ import org.apache.poi.hssf.record.crypto
 import org.apache.poi.poifs.crypt.CryptoFunctions;
 import org.apache.poi.poifs.crypt.EncryptionInfo;
 import org.apache.poi.poifs.crypt.HashAlgorithm;
+import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIDecryptor;
 import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIEncryptionHeader;
 import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
 import org.apache.poi.poifs.filesystem.POIFSFileSystem;
@@ -176,7 +178,7 @@ public class TestDocumentEncryption {
         
         DocumentEncryptionAtom dea = hss.getDocumentEncryptionAtom();
         
-        POIFSFileSystem fs2 = new POIFSFileSystem(dea.getEncryptionInfo().getDecryptor().getDataStream(fs));
+        POIFSFileSystem fs2 = ((CryptoAPIDecryptor)dea.getEncryptionInfo().getDecryptor()).getSummaryEntries(fs.getRoot(), "EncryptedSummary");
         PropertySet ps = PropertySetFactory.create(fs2.getRoot(), SummaryInformation.DEFAULT_STREAM_NAME);
         assertTrue(ps.isSummaryInformation());
         assertEquals("RC4 CryptoAPI Encryption", ps.getProperties()[1].getValue());



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org