]> source.dussan.org Git - poi.git/commitdiff
Add correct detection for encrypted powerpoint files. An exception will be thrown...
authorNick Burch <nick@apache.org>
Mon, 3 Jul 2006 20:34:41 +0000 (20:34 +0000)
committerNick Burch <nick@apache.org>
Mon, 3 Jul 2006 20:34:41 +0000 (20:34 +0000)
git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@418842 13f79535-47bb-0310-9956-ffa450edef68

src/scratchpad/src/org/apache/poi/hslf/EncryptedSlideShow.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hslf/HSLFSlideShow.java
src/scratchpad/src/org/apache/poi/hslf/exceptions/EncryptedPowerPointFileException.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hslf/record/DocumentEncryptionAtom.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hslf/record/Record.java
src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java
src/scratchpad/testcases/org/apache/poi/hslf/TestEncryptedFile.java [new file with mode: 0644]
src/scratchpad/testcases/org/apache/poi/hslf/data/Password_Protected-56-hello.ppt [new file with mode: 0644]
src/scratchpad/testcases/org/apache/poi/hslf/data/Password_Protected-hello.ppt [new file with mode: 0644]
src/scratchpad/testcases/org/apache/poi/hslf/data/Password_Protected-np-hello.ppt [new file with mode: 0644]
src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocumentEncryptionAtom.java [new file with mode: 0644]

diff --git a/src/scratchpad/src/org/apache/poi/hslf/EncryptedSlideShow.java b/src/scratchpad/src/org/apache/poi/hslf/EncryptedSlideShow.java
new file mode 100644 (file)
index 0000000..0271abe
--- /dev/null
@@ -0,0 +1,127 @@
+
+/* ====================================================================
+   Copyright 2002-2004   Apache Software Foundation
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+        
+
+
+package org.apache.poi.hslf;
+
+import java.io.FileNotFoundException;
+
+import org.apache.poi.hslf.record.CurrentUserAtom;
+import org.apache.poi.hslf.record.DocumentEncryptionAtom;
+import org.apache.poi.hslf.record.PersistPtrHolder;
+import org.apache.poi.hslf.record.Record;
+import org.apache.poi.hslf.record.UserEditAtom;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+import org.apache.poi.poifs.filesystem.DocumentEntry;
+import org.apache.poi.poifs.filesystem.DocumentInputStream;
+import org.apache.poi.util.LittleEndian;
+
+/**
+ * This class provides helper functions for determining if a
+ *  PowerPoint document is Encrypted. 
+ * In future, it may also provide Encryption and Decryption
+ *  functions, but first we'd need to figure out how 
+ *  PowerPoint encryption is really done!
+ *
+ * @author Nick Burch
+ */
+
+public class EncryptedSlideShow
+{
+       /**
+        * Check to see if a HSLFSlideShow represents an encrypted
+        *  PowerPoint document, or not
+        * @param hss The HSLFSlideShow to check
+        * @return true if encrypted, otherwise false
+        */
+       public static boolean checkIfEncrypted(HSLFSlideShow hss) {
+               // Easy way to check - contains a stream
+               //  "EncryptedSummary"
+               POIFSFileSystem fs = hss.getPOIFSFileSystem();
+               try {
+                       fs.getRoot().getEntry("EncryptedSummary");
+                       return true;
+               } catch(FileNotFoundException fnfe) {
+                       // Doesn't have encrypted properties
+               }
+               
+               // If they encrypted the document but not the properties,
+               //  it's harder.
+               // We need to see what the last record pointed to by the
+               //  first PersistPrtHolder is - if it's a 
+               //  DocumentEncryptionAtom, then the file's Encrypted
+               DocumentEncryptionAtom dea = fetchDocumentEncryptionAtom(hss);
+               if(dea != null) {
+                       return true;
+               }
+               return false;
+       }
+       
+       /**
+        * Return the DocumentEncryptionAtom for a HSLFSlideShow, or
+        *  null if there isn't one.
+        * @return a DocumentEncryptionAtom, or null if there isn't one
+        */
+       public static DocumentEncryptionAtom fetchDocumentEncryptionAtom(HSLFSlideShow hss) {
+               // Will be the last Record pointed to by the 
+               //  first PersistPrtHolder, if there is one
+               
+               CurrentUserAtom cua = hss.getCurrentUserAtom();
+               if(cua.getCurrentEditOffset() != 0) {
+                       // Grab the details of the UserEditAtom there
+                       Record r = Record.buildRecordAtOffset(
+                                       hss.getUnderlyingBytes(),
+                                       (int)cua.getCurrentEditOffset()
+                       );
+                       if(! (r instanceof UserEditAtom)) { return null; }
+                       UserEditAtom uea = (UserEditAtom)r;
+                       
+                       // Now get the PersistPtrHolder
+                       Record r2 = Record.buildRecordAtOffset(
+                                       hss.getUnderlyingBytes(),
+                                       uea.getPersistPointersOffset()
+                       );
+                       if(! (r2 instanceof PersistPtrHolder)) { return null; }
+                       PersistPtrHolder pph = (PersistPtrHolder)r2;
+                       
+                       // Now get the last record
+                       int[] slideIds = pph.getKnownSlideIDs();
+                       int maxSlideId = -1;
+                       for(int i=0; i<slideIds.length; i++) {
+                               if(slideIds[i] > maxSlideId) { maxSlideId = slideIds[i]; }
+                       }
+                       if(maxSlideId == -1) { return null; }
+                       
+                       int offset = (
+                                       (Integer)pph.getSlideLocationsLookup().get(
+                                                       new Integer(maxSlideId)
+                                       ) ).intValue();
+                       Record r3 = Record.buildRecordAtOffset(
+                                       hss.getUnderlyingBytes(),
+                                       offset
+                       );
+                       
+                       // If we have a DocumentEncryptionAtom, it'll be this one
+                       if(r3 instanceof DocumentEncryptionAtom) {
+                               return (DocumentEncryptionAtom)r3;
+                       }
+               }
+               
+               return null;
+       }
+}
index ddf9c7520e1c33281a1c21e70ed6c39cbce77976..9aa5bd9d2ac95d4b8b9090a44837bcabfb5bde9a 100644 (file)
@@ -33,6 +33,7 @@ import org.apache.poi.hpsf.MutablePropertySet;
 import org.apache.poi.hpsf.SummaryInformation;
 import org.apache.poi.hpsf.DocumentSummaryInformation;
 
+import org.apache.poi.hslf.exceptions.EncryptedPowerPointFileException;
 import org.apache.poi.hslf.record.*;
 import org.apache.poi.hslf.usermodel.PictureData;
 
@@ -58,6 +59,14 @@ public class HSLFSlideShow extends POIDocument
 
        // Raw Pictures contained in the pictures stream
        private PictureData[] _pictures;
+       
+       /**
+        * Returns the underlying POIFSFileSystem for the document
+        *  that is open.
+        */
+       protected POIFSFileSystem getPOIFSFileSystem() {
+               return filesystem;
+       }
 
        /**
         * Constructs a Powerpoint document from fileName. Parses the document 
@@ -95,15 +104,29 @@ public class HSLFSlideShow extends POIDocument
        public HSLFSlideShow(POIFSFileSystem filesystem) throws IOException
        {
                this.filesystem = filesystem;
+               
+               // First up, grab the "Current User" stream
+               // We need this before we can detect Encrypted Documents
+               readCurrentUserStream();
+               
+               // Next up, grab the data that makes up the 
+               //  PowerPoint stream
+               readPowerPointStream();
+               
+               // Check to see if we have an encrypted document,
+               //  bailing out if we do
+               boolean encrypted = EncryptedSlideShow.checkIfEncrypted(this);
+               if(encrypted) {
+                       throw new EncryptedPowerPointFileException("Encrypted PowerPoint files are not supported");
+               }
 
-               // Go find a PowerPoint document in the stream
-               // Save anything useful we come across
-               readFIB();
+               // Now, build records based on the PowerPoint stream
+               buildRecords();
 
                // Look for Property Streams:
                readProperties();
                
-               // Look for other streams
+               // Look for any other streams
                readOtherStreams();
 
                // Look for Picture Streams:
@@ -132,66 +155,70 @@ public class HSLFSlideShow extends POIDocument
        }
 
 
-  /**
-   * Extracts the main document stream from the POI file then hands off 
-   * to other functions that parse other areas.
-   *
-   * @throws IOException
-   */
-  private void readFIB() throws IOException
-  {
-       // Get the main document stream
-       DocumentEntry docProps =
-               (DocumentEntry)filesystem.getRoot().getEntry("PowerPoint Document");
-
-       // Grab the document stream
-       _docstream = new byte[docProps.getSize()];
-       filesystem.createDocumentInputStream("PowerPoint Document").read(_docstream);
-
-       // The format of records in a powerpoint file are:
-       //   <little endian 2 byte "info">
-       //   <little endian 2 byte "type">
-       //   <little endian 4 byte "length">
-       // If it has a zero length, following it will be another record
-       //              <xx xx yy yy 00 00 00 00> <xx xx yy yy zz zz zz zz>
-       // If it has a length, depending on its type it may have children or data
-       // If it has children, these will follow straight away
-       //              <xx xx yy yy zz zz zz zz <xx xx yy yy zz zz zz zz>>
-       // If it has data, this will come straigh after, and run for the length
-       //      <xx xx yy yy zz zz zz zz dd dd dd dd dd dd dd>
-       // All lengths given exclude the 8 byte record header
-       // (Data records are known as Atoms)
-
-       // Document should start with:
-       //   0F 00 E8 03 ## ## ## ##
-    //     (type 1000 = document, info 00 0f is normal, rest is document length)
-       //   01 00 E9 03 28 00 00 00
-       //     (type 1001 = document atom, info 00 01 normal, 28 bytes long)
-       //   80 16 00 00 E0 10 00 00 xx xx xx xx xx xx xx xx
-       //   05 00 00 00 0A 00 00 00 xx xx xx
-       //     (the contents of the document atom, not sure what it means yet)
-       //   (records then follow)
-
-       // When parsing a document, look to see if you know about that type
-       //  of the current record. If you know it's a type that has children, 
-       //  process the record's data area looking for more records
-       // If you know about the type and it doesn't have children, either do
-       //  something with the data (eg TextRun) or skip over it
-       // If you don't know about the type, play safe and skip over it (using
-       //  its length to know where the next record will start)
-       //
-       // For now, this work is handled by Record.findChildRecords
-
-       _records = Record.findChildRecords(_docstream,0,_docstream.length);
-  }
+       /**
+        * Extracts the main PowerPoint document stream from the 
+        *  POI file, ready to be passed 
+        *
+        * @throws IOException
+        */
+       private void readPowerPointStream() throws IOException
+       {
+               // Get the main document stream
+               DocumentEntry docProps =
+                       (DocumentEntry)filesystem.getRoot().getEntry("PowerPoint Document");
 
+               // Grab the document stream
+               _docstream = new byte[docProps.getSize()];
+               filesystem.createDocumentInputStream("PowerPoint Document").read(_docstream);
+       }
+       
+       /**
+        * Builds the list of records, based on the contents  
+        *  of the PowerPoint stream
+        */
+       private void buildRecords()
+       {
+               // The format of records in a powerpoint file are:
+               //   <little endian 2 byte "info">
+               //   <little endian 2 byte "type">
+               //   <little endian 4 byte "length">
+               // If it has a zero length, following it will be another record
+               //              <xx xx yy yy 00 00 00 00> <xx xx yy yy zz zz zz zz>
+               // If it has a length, depending on its type it may have children or data
+               // If it has children, these will follow straight away
+               //              <xx xx yy yy zz zz zz zz <xx xx yy yy zz zz zz zz>>
+               // If it has data, this will come straigh after, and run for the length
+               //      <xx xx yy yy zz zz zz zz dd dd dd dd dd dd dd>
+               // All lengths given exclude the 8 byte record header
+               // (Data records are known as Atoms)
+       
+               // Document should start with:
+               //   0F 00 E8 03 ## ## ## ##
+           //     (type 1000 = document, info 00 0f is normal, rest is document length)
+               //   01 00 E9 03 28 00 00 00
+               //     (type 1001 = document atom, info 00 01 normal, 28 bytes long)
+               //   80 16 00 00 E0 10 00 00 xx xx xx xx xx xx xx xx
+               //   05 00 00 00 0A 00 00 00 xx xx xx
+               //     (the contents of the document atom, not sure what it means yet)
+               //   (records then follow)
+       
+               // When parsing a document, look to see if you know about that type
+               //  of the current record. If you know it's a type that has children, 
+               //  process the record's data area looking for more records
+               // If you know about the type and it doesn't have children, either do
+               //  something with the data (eg TextRun) or skip over it
+               // If you don't know about the type, play safe and skip over it (using
+               //  its length to know where the next record will start)
+               //
+               // For now, this work is handled by Record.findChildRecords
+       
+               _records = Record.findChildRecords(_docstream,0,_docstream.length);
+       }
 
        /**
-        * Find the other from the filesystem (currently just CurrentUserAtom), 
-        *  and load them
+        * Find the "Current User" stream, and load it 
         */
-       public void readOtherStreams() {
-               // Current User
+       private void readCurrentUserStream() {
                try {
                        currentUser = new CurrentUserAtom(filesystem);
                } catch(IOException ie) {
@@ -199,6 +226,13 @@ public class HSLFSlideShow extends POIDocument
                        currentUser = new CurrentUserAtom();
                }
        }
+       
+       /**
+        * Find any other streams from the filesystem, and load them 
+        */
+       private void readOtherStreams() {
+               // Currently, there aren't any
+       }
 
        /**
         * Find and read in pictures contained in this presentation
diff --git a/src/scratchpad/src/org/apache/poi/hslf/exceptions/EncryptedPowerPointFileException.java b/src/scratchpad/src/org/apache/poi/hslf/exceptions/EncryptedPowerPointFileException.java
new file mode 100644 (file)
index 0000000..e509d8e
--- /dev/null
@@ -0,0 +1,34 @@
+
+/* ====================================================================
+   Copyright 2002-2004   Apache Software Foundation
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+        
+
+
+package org.apache.poi.hslf.exceptions;
+
+/**
+ * This exception is thrown when we try to open a PowerPoint file, and
+ *  discover that it is encrypted
+ *
+ * @author Nick Burch
+ */
+
+public class EncryptedPowerPointFileException extends IllegalStateException
+{
+       public EncryptedPowerPointFileException(String s) {
+               super(s);
+       }
+}
diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/DocumentEncryptionAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/DocumentEncryptionAtom.java
new file mode 100644 (file)
index 0000000..84d2319
--- /dev/null
@@ -0,0 +1,101 @@
+
+/* ====================================================================
+   Copyright 2002-2004   Apache Software Foundation
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+        
+
+package org.apache.poi.hslf.record;
+
+import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.StringUtil;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * A Document Encryption Atom (type 12052). Holds information
+ *  on the Encryption of a Document
+ *
+ * @author Nick Burch
+ */
+
+public class DocumentEncryptionAtom extends RecordAtom
+{
+       private byte[] _header;
+       private static long _type = 12052l;
+
+       private byte[] data;
+       private String encryptionProviderName;
+
+       /** 
+        * For the Document Encryption Atom
+        */
+       protected DocumentEncryptionAtom(byte[] source, int start, int len) {
+               // Get the header
+               _header = new byte[8];
+               System.arraycopy(source,start,_header,0,8);
+
+               // Grab everything else, for now
+               data = new byte[len-8];
+               System.arraycopy(source, start+8, data, 0, len-8);
+
+               // Grab the provider, from byte 8+44 onwards
+               // It's a null terminated Little Endian String
+               int endPos = -1;
+               int pos = start + 8+44;
+               while(pos < (start+len) && endPos < 0) {
+                       if(source[pos] == 0 && source[pos+1] == 0) {
+                               // Hit the end
+                               endPos = pos;
+                       }
+                       pos += 2;
+               }
+               pos = start + 8+44;
+               int stringLen = (endPos-pos) / 2;
+               encryptionProviderName = StringUtil.getFromUnicodeLE(source, pos, stringLen);
+       }
+       
+       /**
+        * Return the length of the encryption key, in bits
+        */
+       public int getKeyLength() {
+               return data[28];
+       }
+       
+       /**
+        * Return the name of the encryption provider used
+        */
+       public String getEncryptionProviderName() {
+               return encryptionProviderName;
+       }
+       
+
+       /**
+        * We are of type 12052
+        */
+       public long getRecordType() { return _type; }
+
+       /**
+        * Write the contents of the record back, so it can be written
+        *  to disk
+        */
+       public void writeOut(OutputStream out) throws IOException {
+               // Header
+               out.write(_header);
+
+               // Data
+               out.write(data);
+       }
+}
index 0a8906d8b905a2b8fc120cdd25e37714c7273c74..1a8470fda6235d5abab4fb9b89e60f23837711bd 100644 (file)
@@ -82,6 +82,23 @@ public abstract class Record
                LittleEndian.putShort(bs,s);
                o.write(bs);
        }
+       
+       /**
+        * Build and return the Record at the given offset.
+        * Note - does less error checking and handling than findChildRecords
+        * @param b The byte array to build from
+        * @param offset The offset to build at
+        */
+       public static Record buildRecordAtOffset(byte[] b, int offset) {
+               long type = LittleEndian.getUShort(b,offset+2);
+               long rlen = LittleEndian.getUInt(b,offset+4);
+
+               // Sanity check the length
+               int rleni = (int)rlen;
+               if(rleni < 0) { rleni = 0; }
+
+               return createRecordForType(type,b,offset,8+rleni);
+       }
 
        /**
         * Default method for finding child records of a container record
index e9b7062d72128bffd8195bb2e8161b9520a65717..5117d5f1fdcfca746e34e6ba7f900a097eb6a31b 100644 (file)
@@ -156,6 +156,9 @@ public class RecordTypes {
     public static final Type Comment2000Atom = new Type(12001,Comment2000Atom.class);
     public static final Type Comment2000Summary = new Type(12004,null);
     public static final Type Comment2000SummaryAtom = new Type(12005,null);
+    
+    // Records ~12050 seem to be related to Document Encryption
+    public static final Type DocumentEncryptionAtom = new Type(12052,DocumentEncryptionAtom.class);
 
     //records greater then 0xF000 belong to with Microsoft Office Drawing format also known as Escher
     public static final int EscherDggContainer = 0xf000;
diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/TestEncryptedFile.java b/src/scratchpad/testcases/org/apache/poi/hslf/TestEncryptedFile.java
new file mode 100644 (file)
index 0000000..d7d17ae
--- /dev/null
@@ -0,0 +1,81 @@
+
+/* ====================================================================
+   Copyright 2002-2004   Apache Software Foundation
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+        
+
+
+package org.apache.poi.hslf;
+
+
+import junit.framework.TestCase;
+
+import org.apache.poi.hslf.exceptions.EncryptedPowerPointFileException;
+import org.apache.poi.hslf.record.*;
+
+/**
+ * Tests that HSLFSlideShow does the right thing with an encrypted file
+ *
+ * @author Nick Burch (nick at torchbox dot com)
+ */
+public class TestEncryptedFile extends TestCase {
+       // A non encrypted file
+       private String ss_ne;
+       // An encrypted file, with encrypted properties
+       private String ss_e;
+       // An encrypted file, without encrypted properties
+       private String ss_np_e;
+       // An encrypted file, with a 56 bit key
+       private String ss_56_e;
+       
+
+    public TestEncryptedFile() throws Exception {
+               String dirname = System.getProperty("HSLF.testdata.path");
+               
+               ss_ne = dirname + "/basic_test_ppt_file.ppt";
+               ss_e = dirname + "/Password_Protected-hello.ppt";
+               ss_np_e = dirname + "/Password_Protected-np-hello.ppt";
+               ss_56_e = dirname + "/Password_Protected-56-hello.ppt";
+    }
+    
+    public void testLoadNonEncrypted() throws Exception {
+       HSLFSlideShow hss = new HSLFSlideShow(ss_ne);
+       
+       assertNotNull(hss);
+    }
+    
+    public void testLoadEncrypted() throws Exception {
+       try {
+               new HSLFSlideShow(ss_e);
+               fail();
+       } catch(EncryptedPowerPointFileException e) {
+               // Good
+       }
+       
+       try {
+               new HSLFSlideShow(ss_np_e);
+               fail();
+       } catch(EncryptedPowerPointFileException e) {
+               // Good
+       }
+       
+       try {
+               new HSLFSlideShow(ss_56_e);
+               fail();
+       } catch(EncryptedPowerPointFileException e) {
+               // Good
+       }
+    }
+}
diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/data/Password_Protected-56-hello.ppt b/src/scratchpad/testcases/org/apache/poi/hslf/data/Password_Protected-56-hello.ppt
new file mode 100644 (file)
index 0000000..d1e5d66
Binary files /dev/null and b/src/scratchpad/testcases/org/apache/poi/hslf/data/Password_Protected-56-hello.ppt differ
diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/data/Password_Protected-hello.ppt b/src/scratchpad/testcases/org/apache/poi/hslf/data/Password_Protected-hello.ppt
new file mode 100644 (file)
index 0000000..3bbab4d
Binary files /dev/null and b/src/scratchpad/testcases/org/apache/poi/hslf/data/Password_Protected-hello.ppt differ
diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/data/Password_Protected-np-hello.ppt b/src/scratchpad/testcases/org/apache/poi/hslf/data/Password_Protected-np-hello.ppt
new file mode 100644 (file)
index 0000000..8634183
Binary files /dev/null and b/src/scratchpad/testcases/org/apache/poi/hslf/data/Password_Protected-np-hello.ppt differ
diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocumentEncryptionAtom.java b/src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocumentEncryptionAtom.java
new file mode 100644 (file)
index 0000000..0e13d7e
--- /dev/null
@@ -0,0 +1,107 @@
+
+/* ====================================================================
+   Copyright 2002-2004   Apache Software Foundation
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+        
+
+
+package org.apache.poi.hslf.record;
+
+
+import junit.framework.TestCase;
+
+/**
+ * Tests that DocumentEncryptionAtom works properly.
+ *
+ * @author Nick Burch (nick at torchbox dot com)
+ */
+public class TestDocumentEncryptionAtom extends TestCase {
+       // From a real file
+       private byte[] data_a = new byte[] { 
+               0x0F, 00, 0x14, 0x2F, 0xBE-256, 00, 00, 00,
+               02, 00, 02, 00, 0x0C, 00, 00, 00, 
+               0x76, 00, 00, 00, 0x0C, 00, 00, 00,
+               00, 00, 00, 00, 01, 0x68, 00, 00, 
+               04, 0x80-256, 00, 00, 0x28, 00, 00, 00,
+               01, 00, 00, 00, 0x30, 00, 0x26, 01, 
+               00, 00, 00, 00,
+               
+               0x4D, 00, 0x69, 00,
+               0x63, 00, 0x72, 00, 0x6F, 00, 0x73, 00, 
+               0x6F, 00, 0x66, 00, 0x74, 00, 0x20, 00,
+               0x42, 00, 0x61, 00, 0x73, 00, 0x65, 00, 
+               0x20, 00, 0x43, 00, 0x72, 00, 0x79, 00,
+               0x70, 00, 0x74, 00, 0x6F, 00, 0x67, 00, 
+               0x72, 00, 0x61, 00, 0x70, 00, 0x68, 00,
+               0x69, 00, 0x63, 00, 0x20, 00, 0x50, 00, 
+               0x72, 00, 0x6F, 00, 0x76, 00, 0x69, 00,
+               0x64, 00, 0x65, 00, 0x72, 00, 0x20, 00, 
+               0x76, 00, 0x31, 00, 0x2E, 00, 0x30, 00,
+               0x00, 0x00,
+               
+               0x10, 00, 0x00, 00, 
+               0x62, 0xA6-256, 
+               0xDF-256, 0xEA-256, 0x96-256, 0x84-256, 
+               0xFB-256, 0x89-256, 0x93-256, 0xCA-256,
+               0xBA-256, 0xEE-256, 0x8E-256, 0x43, 
+               0xC8-256, 0x71, 0xD1-256, 0x89-256, 
+               0xF6-256, 0x4B, 0x2B, 0xD9-256, 
+               0x7E, 0x0B, 0x52, 0xFB-256,
+               0x68, 0xD7-256, 0x5A, 0x4E, 0x45, 0xDF-256, 0x14, 0x00, 
+               0x00, 0x00, 0x93-256, 0x15, 0x27, 0xEB-256, 0x21, 0x54,
+               0x7F, 0x0B, 0x56, 0x07, 0xEE-256, 0x66, 0xEB-256, 0x6F, 
+               0xB2-256, 0x8E-256, 0x67, 0x54, 0x07, 0x04, 0x00
+       };
+       
+       private byte[] data_b = new byte[] {
+                       15, 0, 20, 47, -66, 0, 0, 0,
+                       2, 0, 2, 0, 4, 
+                       0, 0, 0, 118, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 
+                       0, 1, 104, 0, 0, 4, -128, 0, 0, 56, 0, 0, 0, 
+                       1, 0, 0, 0, 48, 0, 38, 1, 0, 0, 0, 0, 77, 0, 
+                       105, 0, 99, 0, 114, 0, 111, 0, 115, 0, 111, 
+                       0, 102, 0, 116, 0, 32, 0, 66, 0, 97, 0, 115, 
+                       0, 101, 0, 32, 0, 67, 0, 114, 0, 121, 0, 112, 
+                       0, 116, 0, 111, 0, 103, 0, 114, 0, 97, 0, 
+                       112, 0, 104, 0, 105, 0, 99, 0, 32, 0, 80, 0, 
+                       114, 0, 111, 0, 118, 0, 105, 0, 100, 0, 101, 
+                       0, 114, 0, 32, 0, 118, 0, 49, 0, 46, 0, 48, 
+                       0, 0, 0, 16, 0, 0, 0, -80, -66, 112, -40, 57, 
+                       110, 54, 80, 64, 61, -73, -29, 48, -35, -20, 
+                       17, -40, 84, 54, 6, -103, 125, -22, -72, 53, 
+                       103, -114, 13, -48, 111, 29, 78, 20, 0, 0, 
+                       0, -97, -67, 55, -62, -94, 14, 15, -21, 37, 
+                       3, -104, 22, 6, 102, -61, -98, 62, 40, 61, 21
+       };
+
+    public void testRecordType() throws Exception {
+               DocumentEncryptionAtom dea1 = new DocumentEncryptionAtom(data_a, 0, data_a.length);
+               assertEquals(12052l, dea1.getRecordType());
+               
+               DocumentEncryptionAtom dea2 = new DocumentEncryptionAtom(data_b, 0, data_b.length);
+               assertEquals(12052l, dea2.getRecordType());
+               
+               System.out.println(data_a.length);
+               System.out.println(data_b.length);
+       }
+    
+    public void testEncryptionTypeName() throws Exception {
+               DocumentEncryptionAtom dea1 = new DocumentEncryptionAtom(data_a, 0, data_a.length);
+               assertEquals("Microsoft Base Cryptographic Provider v1.0", dea1.getEncryptionProviderName());
+               
+               DocumentEncryptionAtom dea2 = new DocumentEncryptionAtom(data_b, 0, data_b.length);
+               assertEquals("Microsoft Base Cryptographic Provider v1.0", dea2.getEncryptionProviderName());
+    }
+}