]> source.dussan.org Git - poi.git/commitdiff
- Fixed bug 44375 - HPSF now copes with a broken dictionary in Document Summary Infor...
authorRainer Klute <klute@apache.org>
Fri, 8 Feb 2008 11:55:43 +0000 (11:55 +0000)
committerRainer Klute <klute@apache.org>
Fri, 8 Feb 2008 11:55:43 +0000 (11:55 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@619848 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/hpsf/Property.java
src/java/org/apache/poi/hpsf/Section.java
src/java/org/apache/poi/hpsf/VariantSupport.java
src/testcases/org/apache/poi/hpsf/basic/TestBasic.java
src/testcases/org/apache/poi/hpsf/basic/TestBugs.java [deleted file]
src/testcases/org/apache/poi/hpsf/basic/TestReadAllFiles.java [new file with mode: 0644]
src/testcases/org/apache/poi/hpsf/data/Bug44375.xls [deleted file]
src/testcases/org/apache/poi/hpsf/data/TestBug44375.xls [new file with mode: 0644]

index 3cfb58e6d12b21564afda618427acc484eadb9e2..16b4f7e41bd587f2641834f26a85ab62a15fc4af 100644 (file)
@@ -23,6 +23,8 @@ import java.util.Map;
 
 import org.apache.poi.util.HexDump;
 import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
 
 /**
  * <p>A property in a {@link Section} of a {@link PropertySet}.</p>
@@ -113,7 +115,8 @@ public class Property
      * 
      * @param id the property's ID.
      * @param type the property's type, see {@link Variant}.
-     * @param value the property's value. Only certain types are allowed, see {@link Variant}. 
+     * @param value the property's value. Only certain types are allowed, see
+     *        {@link Variant}.
      */
     public Property(final long id, final long type, final Object value)
     {
@@ -210,68 +213,80 @@ public class Property
         o += LittleEndian.INT_SIZE;
 
         final Map m = new HashMap((int) nrEntries, (float) 1.0);
-        for (int i = 0; i < nrEntries; i++)
+
+        try
         {
-            /* The key. */
-            final Long id = new Long(LittleEndian.getUInt(src, o));
-            o += LittleEndian.INT_SIZE;
-
-            /* The value (a string). The length is the either the
-             * number of (two-byte) characters if the character set is Unicode
-             * or the number of bytes if the character set is not Unicode.
-             * The length includes terminating 0x00 bytes which we have to strip
-             * off to create a Java string. */
-            long sLength = LittleEndian.getUInt(src, o);
-            o += LittleEndian.INT_SIZE;
-
-            /* Read the string. */
-            final StringBuffer b = new StringBuffer();
-            switch (codepage)
+            for (int i = 0; i < nrEntries; i++)
             {
-                case -1:
-                {
-                    /* Without a codepage the length is equal to the number of
-                     * bytes. */
-                    b.append(new String(src, o, (int) sLength));
-                    break;
-                }
-                case Constants.CP_UNICODE:
+                /* The key. */
+                final Long id = new Long(LittleEndian.getUInt(src, o));
+                o += LittleEndian.INT_SIZE;
+
+                /* The value (a string). The length is the either the
+                 * number of (two-byte) characters if the character set is Unicode
+                 * or the number of bytes if the character set is not Unicode.
+                 * The length includes terminating 0x00 bytes which we have to strip
+                 * off to create a Java string. */
+                long sLength = LittleEndian.getUInt(src, o);
+                o += LittleEndian.INT_SIZE;
+
+                /* Read the string. */
+                final StringBuffer b = new StringBuffer();
+                switch (codepage)
                 {
-                    /* The length is the number of characters, i.e. the number
-                     * of bytes is twice the number of the characters. */
-                    final int nrBytes = (int) (sLength * 2);
-                    final byte[] h = new byte[nrBytes];
-                    for (int i2 = 0; i2 < nrBytes; i2 += 2)
+                    case -1:
+                    {
+                        /* Without a codepage the length is equal to the number of
+                         * bytes. */
+                        b.append(new String(src, o, (int) sLength));
+                        break;
+                    }
+                    case Constants.CP_UNICODE:
+                    {
+                        /* The length is the number of characters, i.e. the number
+                         * of bytes is twice the number of the characters. */
+                        final int nrBytes = (int) (sLength * 2);
+                        final byte[] h = new byte[nrBytes];
+                        for (int i2 = 0; i2 < nrBytes; i2 += 2)
+                        {
+                            h[i2] = src[o + i2 + 1];
+                            h[i2 + 1] = src[o + i2];
+                        }
+                        b.append(new String(h, 0, nrBytes,
+                                VariantSupport.codepageToEncoding(codepage)));
+                        break;
+                    }
+                    default:
                     {
-                        h[i2] = src[o + i2 + 1];
-                        h[i2 + 1] = src[o + i2];
+                        /* For encodings other than Unicode the length is the number
+                         * of bytes. */
+                        b.append(new String(src, o, (int) sLength,
+                                 VariantSupport.codepageToEncoding(codepage)));
+                        break;
                     }
-                    b.append(new String(h, 0, nrBytes,
-                            VariantSupport.codepageToEncoding(codepage)));
-                    break;
                 }
-                default:
+
+                /* Strip 0x00 characters from the end of the string: */
+                while (b.length() > 0 && b.charAt(b.length() - 1) == 0x00)
+                    b.setLength(b.length() - 1);
+                if (codepage == Constants.CP_UNICODE)
                 {
-                    /* For encodings other than Unicode the length is the number
-                     * of bytes. */
-                    b.append(new String(src, o, (int) sLength,
-                             VariantSupport.codepageToEncoding(codepage)));
-                    break;
+                    if (sLength % 2 == 1)
+                        sLength++;
+                    o += (sLength + sLength);
                 }
+                else
+                    o += sLength;
+                m.put(id, b.toString());
             }
-
-            /* Strip 0x00 characters from the end of the string: */
-            while (b.length() > 0 && b.charAt(b.length() - 1) == 0x00)
-                b.setLength(b.length() - 1);
-            if (codepage == Constants.CP_UNICODE)
-            {
-                if (sLength % 2 == 1)
-                    sLength++;
-                o += (sLength + sLength);
-            }
-            else
-                o += sLength;
-            m.put(id, b.toString());
+        }
+        catch (RuntimeException ex)
+        {
+            final POILogger l = POILogFactory.getLogger(getClass());
+            l.log(POILogger.WARN,
+                    "The property set's dictionary contains bogus data. "
+                    + "All dictionary entries starting with the one with ID "
+                    + id + " will be ignored.", ex);
         }
         return m;
     }
@@ -320,11 +335,10 @@ public class Property
 
 
     /**
-     * <p>Compares two properties.</p>
-     * 
-     * <p>Please beware that a property with ID == 0 is a special case: It does not have a type, and its value is the section's
-     * dictionary. Another special case are strings: Two properties may have
-     * the different types Variant.VT_LPSTR and Variant.VT_LPWSTR;</p>
+     * <p>Compares two properties.</p> <p>Please beware that a property with
+     * ID == 0 is a special case: It does not have a type, and its value is the
+     * section's dictionary. Another special case are strings: Two properties
+     * may have the different types Variant.VT_LPSTR and Variant.VT_LPWSTR;</p>
      * 
      * @see Object#equals(java.lang.Object)
      */
index 3b041ed9c20a599feb6244a417a0dec8e2d38a7a..76824e7b7eb0ad9cb191da7737df1dea11e530da 100644 (file)
@@ -210,7 +210,7 @@ public class Section
         
         /* Pass 1: Read the property list. */
         int pass1Offset = o1;
-        List propertyList = new ArrayList(propertyCount);
+        final List propertyList = new ArrayList(propertyCount);
         PropertyListEntry ple;
         for (int i = 0; i < properties.length; i++)
         {
index 1986cac30cce3d0c3823adcbfa15efbdf26876ec..703e8abe8d707c139968019c7cf395d414ac4bf9 100644 (file)
@@ -109,25 +109,51 @@ public class VariantSupport extends Variant
     }
 
 
+    /**
+     * <p>HPSF is able to read these {@link Variant} types.</p>
+     */
+    final static public int[] SUPPORTED_TYPES = { Variant.VT_EMPTY,
+            Variant.VT_I2, Variant.VT_I4, Variant.VT_I8, Variant.VT_R8,
+            Variant.VT_FILETIME, Variant.VT_LPSTR, Variant.VT_LPWSTR,
+            Variant.VT_CF, Variant.VT_BOOL };
+
+
+
+    /**
+     * <p>Checks whether HPSF supports the specified variant type. Unsupported
+     * types should be implemented included in the {@link #SUPPORTED_TYPES}
+     * array.</p>
+     * 
+     * @see Variant
+     * @param variantType the variant type to check
+     * @return <code>true</code> if HPFS supports this type, else
+     *         <code>false</code>
+     */
+    public boolean isSupportedType(final int variantType)
+    {
+        for (int i = 0; i < SUPPORTED_TYPES.length; i++)
+            if (variantType == SUPPORTED_TYPES[i])
+                return true;
+        return false;
+    }
+
+
 
     /**
      * <p>Reads a variant type from a byte array.</p>
-     *
+     * 
      * @param src The byte array
-     * @param offset The offset in the byte array where the variant
-     * starts
-     * @param length The length of the variant including the variant
-     * type field
+     * @param offset The offset in the byte array where the variant starts
+     * @param length The length of the variant including the variant type field
      * @param type The variant type to read
-     * @param codepage The codepage to use to write non-wide strings
-     * @return A Java object that corresponds best to the variant
-     * field. For example, a VT_I4 is returned as a {@link Long}, a
-     * VT_LPSTR as a {@link String}.
+     * @param codepage The codepage to use for non-wide strings
+     * @return A Java object that corresponds best to the variant field. For
+     *         example, a VT_I4 is returned as a {@link Long}, a VT_LPSTR as a
+     *         {@link String}.
      * @exception ReadingNotSupportedException if a property is to be written
-     * who's variant type HPSF does not yet support
+     *            who's variant type HPSF does not yet support
      * @exception UnsupportedEncodingException if the specified codepage is not
-     * supported.
-     *
+     *            supported.
      * @see Variant
      */
     public static Object read(final byte[] src, final int offset,
index 521ce819e80fc697b5b67f229282ca5b23f83855..1932f0f11b9f78a4b7c767ed5aab6223050d3e61 100644 (file)
@@ -20,7 +20,6 @@ package org.apache.poi.hpsf.basic;
 
 import java.io.ByteArrayInputStream;
 import java.io.File;
-import java.io.FileFilter;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
@@ -227,46 +226,6 @@ public class TestBasic extends TestCase
 
 
 
-    /**
-     * <p>This test methods reads all property set streams from all POI
-     * filesystems in the "data" directory.</p>
-     */
-    public void testReadAllFiles()
-    {
-        final File dataDir =
-            new File(System.getProperty("HPSF.testdata.path"));
-        final File[] fileList = dataDir.listFiles(new FileFilter()
-            {
-                public boolean accept(final File f)
-                {
-                    return f.isFile();
-                }
-            });
-        try
-        {
-            for (int i = 0; i < fileList.length; i++)
-            {
-                File f = fileList[i];
-                /* Read the POI filesystem's property set streams: */
-                final POIFile[] psf1 = Util.readPropertySets(f);
-
-                for (int j = 0; j < psf1.length; j++)
-                {
-                    final InputStream in =
-                        new ByteArrayInputStream(psf1[j].getBytes());
-                    PropertySetFactory.create(in);
-                }
-            }
-        }
-        catch (Throwable t)
-        {
-            final String s = org.apache.poi.hpsf.Util.toString(t);
-            fail(s);
-        }
-    }
-
-
-
     /**
      * <p>Runs the test cases stand-alone.</p>
      * 
diff --git a/src/testcases/org/apache/poi/hpsf/basic/TestBugs.java b/src/testcases/org/apache/poi/hpsf/basic/TestBugs.java
deleted file mode 100644 (file)
index 0d2b55d..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.apache.poi.hpsf.basic;
-
-import java.io.File;
-import java.io.FileInputStream;
-
-import org.apache.poi.hpsf.DocumentSummaryInformation;
-import org.apache.poi.hpsf.PropertySet;
-import org.apache.poi.hpsf.PropertySetFactory;
-import org.apache.poi.hpsf.SummaryInformation;
-import org.apache.poi.poifs.filesystem.DocumentInputStream;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-
-import junit.framework.TestCase;
-
-public class TestBugs extends TestCase {
-       private String dirname;
-
-       protected void setUp() throws Exception {
-               dirname = System.getProperty("HPSF.testdata.path");
-       }
-       
-       public void BROKENtestBug44375() throws Exception {
-               POIFSFileSystem fs = new POIFSFileSystem(
-                               new FileInputStream(new File(dirname,"Bug44375.xls"))
-               );
-               
-               DocumentInputStream dis;
-               PropertySet set;
-
-               dis = fs.createDocumentInputStream(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
-               set = PropertySetFactory.create(dis);
-               
-               dis = fs.createDocumentInputStream(SummaryInformation.DEFAULT_STREAM_NAME);
-               // This currently fails
-               set = PropertySetFactory.create(dis);
-       }
-
-}
diff --git a/src/testcases/org/apache/poi/hpsf/basic/TestReadAllFiles.java b/src/testcases/org/apache/poi/hpsf/basic/TestReadAllFiles.java
new file mode 100644 (file)
index 0000000..f68b4c3
--- /dev/null
@@ -0,0 +1,110 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.hpsf.basic;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.InputStream;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.hpsf.PropertySetFactory;
+
+
+
+/**
+ * <p>Tests some HPSF functionality by reading all property sets from all files
+ * in the "data" directory. If you want to ensure HPSF can deal with a certain
+ * OLE2 file, just add it to the "data" directory and run this test case.</p>
+ * 
+ * @author Rainer Klute (klute@rainer-klute.de)
+ * @since 2008-02-08
+ * @version $Id: TestBasic.java 489730 2006-12-22 19:18:16Z bayard $
+ */
+public class TestReadAllFiles extends TestCase
+{
+
+    /**
+     * <p>Test case constructor.</p>
+     * 
+     * @param name The test case's name.
+     */
+    public TestReadAllFiles(final String name)
+    {
+        super(name);
+    }
+
+
+
+    /**
+     * <p>This test methods reads all property set streams from all POI
+     * filesystems in the "data" directory.</p>
+     */
+    public void testReadAllFiles()
+    {
+        final File dataDir =
+            new File(System.getProperty("HPSF.testdata.path"));
+        final File[] fileList = dataDir.listFiles(new FileFilter()
+            {
+                public boolean accept(final File f)
+                {
+                    return f.isFile();
+                }
+            });
+        try
+        {
+            for (int i = 0; i < fileList.length; i++)
+            {
+                final File f = fileList[i];
+                /* Read the POI filesystem's property set streams: */
+                final POIFile[] psf1 = Util.readPropertySets(f);
+
+                for (int j = 0; j < psf1.length; j++)
+                {
+                    final InputStream in =
+                        new ByteArrayInputStream(psf1[j].getBytes());
+                    PropertySetFactory.create(in);
+                }
+            }
+        }
+        catch (Throwable t)
+        {
+            final String s = org.apache.poi.hpsf.Util.toString(t);
+            fail(s);
+        }
+    }
+
+
+
+    /**
+     * <p>Runs the test cases stand-alone.</p>
+     * 
+     * @param args Command-line arguments (ignored)
+     * 
+     * @exception Throwable if any sort of exception or error occurs
+     */
+    public static void main(final String[] args) throws Throwable
+    {
+        System.setProperty("HPSF.testdata.path",
+                           "./src/testcases/org/apache/poi/hpsf/data");
+        junit.textui.TestRunner.run(TestReadAllFiles.class);
+    }
+
+}
diff --git a/src/testcases/org/apache/poi/hpsf/data/Bug44375.xls b/src/testcases/org/apache/poi/hpsf/data/Bug44375.xls
deleted file mode 100644 (file)
index 1e253d1..0000000
Binary files a/src/testcases/org/apache/poi/hpsf/data/Bug44375.xls and /dev/null differ
diff --git a/src/testcases/org/apache/poi/hpsf/data/TestBug44375.xls b/src/testcases/org/apache/poi/hpsf/data/TestBug44375.xls
new file mode 100644 (file)
index 0000000..0ebd762
Binary files /dev/null and b/src/testcases/org/apache/poi/hpsf/data/TestBug44375.xls differ