]> source.dussan.org Git - poi.git/commitdiff
#63955 - HMEFContentsExtractor fails to extract content from winmail.dat
authorAndreas Beeker <kiwiwings@apache.org>
Sun, 1 Dec 2019 21:06:54 +0000 (21:06 +0000)
committerAndreas Beeker <kiwiwings@apache.org>
Sun, 1 Dec 2019 21:06:54 +0000 (21:06 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1870692 13f79535-47bb-0310-9956-ffa450edef68

src/scratchpad/src/org/apache/poi/hsmf/datatypes/Types.java
src/scratchpad/testcases/org/apache/poi/hmef/HMEFTest.java [deleted file]
src/scratchpad/testcases/org/apache/poi/hmef/TestAttachments.java
src/scratchpad/testcases/org/apache/poi/hmef/TestCompressedRTF.java
src/scratchpad/testcases/org/apache/poi/hmef/TestHMEFMessage.java
src/scratchpad/testcases/org/apache/poi/hmef/attribute/TestMAPIAttributes.java
src/scratchpad/testcases/org/apache/poi/hmef/attribute/TestTNEFAttributes.java
src/scratchpad/testcases/org/apache/poi/hmef/dev/TestHMEFDumper.java

index f92c97c220960fc8603fa141da823ff01c121f31..4c92da4f0f2d71e1f4fb1077a82c6c99c74492b6 100644 (file)
@@ -26,8 +26,8 @@ import java.util.Map;
  * http://msdn.microsoft.com/en-us/library/microsoft.exchange.data.contenttypes.tnef.tnefpropertytype%28v=EXCHG.140%29.aspx
  */
 public final class Types {
-    private static Map<Integer, MAPIType> builtInTypes = new HashMap<>();
-    private static Map<Integer, MAPIType> customTypes = new HashMap<>();
+    private static final Map<Integer, MAPIType> builtInTypes = new HashMap<>();
+    private static final Map<Integer, MAPIType> customTypes = new HashMap<>();
 
     /** Unspecified */
     public static final MAPIType UNSPECIFIED = new MAPIType(0x0000,
@@ -119,7 +119,7 @@ public final class Types {
          * Is this type a fixed-length type, or a variable-length one?
          */
         public boolean isFixedLength() {
-            return (length != -1) && (length <= 8);
+            return ((length != -1) && (length <= 8)) || (id == Types.CLS_ID.id);
         }
 
         public int getId() {
@@ -132,8 +132,7 @@ public final class Types {
 
         @Override
         public String toString() {
-            return id + " / 0x" + asFileEnding() + " - " + name + " @ "
-                    + length;
+            return id + " / 0x" + asFileEnding() + " - " + name + " @ " + length;
         }
 
         /**
diff --git a/src/scratchpad/testcases/org/apache/poi/hmef/HMEFTest.java b/src/scratchpad/testcases/org/apache/poi/hmef/HMEFTest.java
deleted file mode 100644 (file)
index a43bc30..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/* ====================================================================
-   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.hmef;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import junit.framework.TestCase;
-
-import org.apache.poi.POIDataSamples;
-import org.apache.poi.util.IOUtils;
-
-public abstract class HMEFTest extends TestCase {
-   protected static final POIDataSamples _samples = POIDataSamples.getHMEFInstance();
-   
-   protected void assertContents(String filename, Attachment attachment) 
-         throws IOException {
-      assertEquals(filename, attachment.getLongFilename());
-      assertContents(filename, attachment.getContents());
-   }
-
-   protected void assertContents(String filename, byte[] actual) 
-         throws IOException {
-       try (InputStream stream = _samples.openResourceAsStream("quick-contents/" + filename)) {
-           byte[] expected = IOUtils.toByteArray(stream);
-
-           assertEquals(expected.length, actual.length);
-           for (int i = 0; i < expected.length; i++) {
-               assertEquals("Byte " + i + " wrong", expected[i], actual[i]);
-           }
-       }
-   }
-}
index 87655cb3aef5350772046e653d0b4ca4162431fd..1220c23f32b183f0c6e5967fb60d0be50f5781d8 100644 (file)
 
 package org.apache.poi.hmef;
 
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.List;
 import java.util.Locale;
 
+import org.apache.poi.POIDataSamples;
 import org.apache.poi.util.LocaleUtil;
+import org.junit.Before;
+import org.junit.Test;
+
+public final class TestAttachments {
+    protected static final POIDataSamples _samples = POIDataSamples.getHMEFInstance();
+
+
+    private HMEFMessage quick;
+
+    @Before
+    public void setUp() throws Exception {
+        quick = new HMEFMessage(
+                _samples.openResourceAsStream("quick-winmail.dat")
+        );
+    }
+
+    /**
+     * Check the file is as we expect
+     */
+    @Test
+    public void testCounts() throws Exception {
+        // Should have 5 attachments
+        assertEquals(5, quick.getAttachments().size());
+    }
+
+    /**
+     * Check some basic bits about the attachments
+     */
+    @Test
+    public void testBasicAttachments() throws Exception {
+        List<Attachment> attachments = quick.getAttachments();
+
+        // Word first
+        assertEquals("quick.doc", attachments.get(0).getFilename());
+        assertEquals("quick.doc", attachments.get(0).getLongFilename());
+        assertEquals(".doc", attachments.get(0).getExtension());
+
+        // Then HTML
+        assertEquals("QUICK~1.HTM", attachments.get(1).getFilename());
+        assertEquals("quick.html", attachments.get(1).getLongFilename());
+        assertEquals(".html", attachments.get(1).getExtension());
+
+        // Then PDF
+        assertEquals("quick.pdf", attachments.get(2).getFilename());
+        assertEquals("quick.pdf", attachments.get(2).getLongFilename());
+        assertEquals(".pdf", attachments.get(2).getExtension());
+
+        // Then Text
+        assertEquals("quick.txt", attachments.get(3).getFilename());
+        assertEquals("quick.txt", attachments.get(3).getLongFilename());
+        assertEquals(".txt", attachments.get(3).getExtension());
+
+        // And finally XML
+        assertEquals("quick.xml", attachments.get(4).getFilename());
+        assertEquals("quick.xml", attachments.get(4).getLongFilename());
+        assertEquals(".xml", attachments.get(4).getExtension());
+    }
+
+    /**
+     * Query the attachments in detail, and check we see
+     * the right values for key things
+     */
+    @Test
+    public void testAttachmentDetails() throws Exception {
+        List<Attachment> attachments = quick.getAttachments();
+
+        // Pick a predictable date format + timezone
+        DateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy hh:mm:ss", Locale.UK);
+        fmt.setTimeZone(LocaleUtil.TIMEZONE_UTC);
+
+        // They should all have the same date on them
+        assertEquals("28-Apr-2010 12:40:56", fmt.format(attachments.get(0).getModifiedDate()));
+        assertEquals("28-Apr-2010 12:40:56", fmt.format(attachments.get(1).getModifiedDate()));
+        assertEquals("28-Apr-2010 12:40:56", fmt.format(attachments.get(2).getModifiedDate()));
+        assertEquals("28-Apr-2010 12:40:56", fmt.format(attachments.get(3).getModifiedDate()));
+        assertEquals("28-Apr-2010 12:40:56", fmt.format(attachments.get(4).getModifiedDate()));
+
+        // They should all have a 3512 byte metafile rendered version
+        assertEquals(3512, attachments.get(0).getRenderedMetaFile().length);
+        assertEquals(3512, attachments.get(1).getRenderedMetaFile().length);
+        assertEquals(3512, attachments.get(2).getRenderedMetaFile().length);
+        assertEquals(3512, attachments.get(3).getRenderedMetaFile().length);
+        assertEquals(3512, attachments.get(4).getRenderedMetaFile().length);
+    }
+
+    /**
+     * Ensure the attachment contents come back as they should do
+     */
+    @Test
+    public void testAttachmentContents() throws Exception {
+        List<Attachment> attachments = quick.getAttachments();
+
+        assertContents("quick.doc", attachments.get(0));
+        assertContents("quick.html", attachments.get(1));
+        assertContents("quick.pdf", attachments.get(2));
+        assertContents("quick.txt", attachments.get(3));
+        assertContents("quick.xml", attachments.get(4));
+    }
 
-public final class TestAttachments extends HMEFTest {
-   private HMEFMessage quick;
-   
-   @Override
-   protected void setUp() throws Exception {
-      super.setUp();
-      
-      quick = new HMEFMessage(
-            _samples.openResourceAsStream("quick-winmail.dat")
-      );
-   }
-
-   /**
-    * Check the file is as we expect
-    */
-       public void testCounts() throws Exception {
-      // Should have 5 attachments
-      assertEquals(5, quick.getAttachments().size());
-       }
-   
-       /**
-        * Check some basic bits about the attachments 
-        */
-   public void testBasicAttachments() throws Exception {
-      List<Attachment> attachments = quick.getAttachments();
-      
-      // Word first
-      assertEquals("quick.doc", attachments.get(0).getFilename());
-      assertEquals("quick.doc", attachments.get(0).getLongFilename());
-      assertEquals(".doc", attachments.get(0).getExtension());
-      
-      // Then HTML
-      assertEquals("QUICK~1.HTM", attachments.get(1).getFilename());
-      assertEquals("quick.html", attachments.get(1).getLongFilename());
-      assertEquals(".html", attachments.get(1).getExtension());
-      
-      // Then PDF
-      assertEquals("quick.pdf", attachments.get(2).getFilename());
-      assertEquals("quick.pdf", attachments.get(2).getLongFilename());
-      assertEquals(".pdf", attachments.get(2).getExtension());
-      
-      // Then Text
-      assertEquals("quick.txt", attachments.get(3).getFilename());
-      assertEquals("quick.txt", attachments.get(3).getLongFilename());
-      assertEquals(".txt", attachments.get(3).getExtension());
-      
-      // And finally XML
-      assertEquals("quick.xml", attachments.get(4).getFilename());
-      assertEquals("quick.xml", attachments.get(4).getLongFilename());
-      assertEquals(".xml", attachments.get(4).getExtension());
-   }
-   
-   /**
-    * Query the attachments in detail, and check we see
-    *  the right values for key things
-    */
-   public void testAttachmentDetails() throws Exception {
-      List<Attachment> attachments = quick.getAttachments();
-      
-      // Pick a predictable date format + timezone
-      DateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy hh:mm:ss", Locale.UK);
-      fmt.setTimeZone(LocaleUtil.TIMEZONE_UTC);
-      
-      // They should all have the same date on them
-      assertEquals("28-Apr-2010 12:40:56", fmt.format( attachments.get(0).getModifiedDate()));
-      assertEquals("28-Apr-2010 12:40:56", fmt.format( attachments.get(1).getModifiedDate()));
-      assertEquals("28-Apr-2010 12:40:56", fmt.format( attachments.get(2).getModifiedDate()));
-      assertEquals("28-Apr-2010 12:40:56", fmt.format( attachments.get(3).getModifiedDate()));
-      assertEquals("28-Apr-2010 12:40:56", fmt.format( attachments.get(4).getModifiedDate()));
-      
-      // They should all have a 3512 byte metafile rendered version
-      assertEquals(3512, attachments.get(0).getRenderedMetaFile().length);
-      assertEquals(3512, attachments.get(1).getRenderedMetaFile().length);
-      assertEquals(3512, attachments.get(2).getRenderedMetaFile().length);
-      assertEquals(3512, attachments.get(3).getRenderedMetaFile().length);
-      assertEquals(3512, attachments.get(4).getRenderedMetaFile().length);
-   }
-
-   /**
-    * Ensure the attachment contents come back as they should do 
-    */
-   public void testAttachmentContents() throws Exception {
-      List<Attachment> attachments = quick.getAttachments();
-      
-      assertContents("quick.doc", attachments.get(0));
-      assertContents("quick.html", attachments.get(1));
-      assertContents("quick.pdf", attachments.get(2));
-      assertContents("quick.txt", attachments.get(3));
-      assertContents("quick.xml", attachments.get(4));
-   }
+    static void assertContents(String filename, Attachment attachment) throws IOException {
+        assertEquals(filename, attachment.getLongFilename());
+        TestHMEFMessage.assertContents(filename, attachment.getContents());
+    }
 }
index c010a6bf28153afe5f90b09415b4277556beab2c..d8781c22c1c2c286e693fac547a240775c1cddde 100644 (file)
 
 package org.apache.poi.hmef;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 
-import junit.framework.TestCase;
-
 import org.apache.poi.POIDataSamples;
 import org.apache.poi.hmef.attribute.MAPIAttribute;
 import org.apache.poi.hmef.attribute.MAPIRtfAttribute;
@@ -29,166 +31,173 @@ import org.apache.poi.hsmf.datatypes.MAPIProperty;
 import org.apache.poi.util.IOUtils;
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.StringUtil;
+import org.junit.Test;
 
-public final class TestCompressedRTF extends TestCase {
+public final class TestCompressedRTF {
     private static final POIDataSamples _samples = POIDataSamples.getHMEFInstance();
 
     private static final String block1 = "{\\rtf1\\adeflang102";
     private static final String block2 = block1 + "5\\ansi\\ansicpg1252";
-    
+
     /**
      * Check that things are as we expected. If this fails,
-     *  then decoding has no hope...  
+     * then decoding has no hope...
      */
+    @Test
     public void testQuickBasics() throws Exception {
-       HMEFMessage msg = new HMEFMessage(
-             _samples.openResourceAsStream("quick-winmail.dat")
-       );
-       
-       MAPIAttribute rtfAttr = msg.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
-       assertNotNull(rtfAttr);
-       assertTrue(rtfAttr instanceof MAPIRtfAttribute);
-       
-       // Check the start of the compressed version
-       byte[] data = ((MAPIRtfAttribute)rtfAttr).getRawData();
-       assertEquals(5907, data.length);
-       
-       // First 16 bytes is header stuff
-       // Check it has the length + compressed marker
-       assertEquals(5907-4, LittleEndian.getShort(data));
-       assertEquals(
-             "LZFu", 
-             StringUtil.getFromCompressedUnicode(data, 8, 4)
-       );
-             
-       
-       // Now Look at the code
-       assertEquals((byte)0x07, data[16+0]);  // Flag: cccUUUUU
-       assertEquals((byte)0x00, data[16+1]);  //  c1a: offset 0 / 0x000
-       assertEquals((byte)0x06, data[16+2]);  //  c1b: length 6+2  -> {\rtf1\a
-       assertEquals((byte)0x01, data[16+3]);  //  c2a: offset 16 / 0x010
-       assertEquals((byte)0x01, data[16+4]);  //  c2b: length 1+2  ->  def
-       assertEquals((byte)0x0b, data[16+5]);  //  c3a: offset 182 / 0xb6
-       assertEquals((byte)0x60, data[16+6]);  //  c3b: length 0+2  -> la 
-       assertEquals((byte)0x6e, data[16+7]);  // n
-       assertEquals((byte)0x67, data[16+8]);  // g
-       assertEquals((byte)0x31, data[16+9]);  // 1
-       assertEquals((byte)0x30, data[16+10]); // 0
-       assertEquals((byte)0x32, data[16+11]); // 2
-       
-       assertEquals((byte)0x66, data[16+12]); // Flag:  UccUUccU
-       assertEquals((byte)0x35, data[16+13]); // 5 
-       assertEquals((byte)0x00, data[16+14]); //  c2a: offset 6 / 0x006
-       assertEquals((byte)0x64, data[16+15]); //  c2b: length 4+2  -> \ansi\a
-       assertEquals((byte)0x00, data[16+16]); //  c3a: offset 7 / 0x007
-       assertEquals((byte)0x72, data[16+17]); //  c3b: length 2+2  -> nsi
-       assertEquals((byte)0x63, data[16+18]); // c 
-       assertEquals((byte)0x70, data[16+19]); // p
-       assertEquals((byte)0x0d, data[16+20]); //  c6a: offset 221 / 0x0dd
-       assertEquals((byte)0xd0, data[16+21]); //  c6b: length 0+2  -> g1
-       assertEquals((byte)0x0e, data[16+22]); //  c7a: offset 224 / 0x0e0
-       assertEquals((byte)0x00, data[16+23]); //  c7b: length 0+2  -> 25
-       assertEquals((byte)0x32, data[16+24]); // 2
+        HMEFMessage msg;
+        try (InputStream is = _samples.openResourceAsStream("quick-winmail.dat")) {
+            msg = new HMEFMessage(is);
+        }
+
+        MAPIAttribute rtfAttr = msg.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
+        assertNotNull(rtfAttr);
+        assertTrue(rtfAttr instanceof MAPIRtfAttribute);
+
+        // Check the start of the compressed version
+        byte[] data = ((MAPIRtfAttribute) rtfAttr).getRawData();
+        assertEquals(5907, data.length);
+
+        // First 16 bytes is header stuff
+        // Check it has the length + compressed marker
+        assertEquals(5907 - 4, LittleEndian.getShort(data));
+        assertEquals(
+                "LZFu",
+                StringUtil.getFromCompressedUnicode(data, 8, 4)
+        );
+
+
+        // Now Look at the code
+        assertEquals((byte) 0x07, data[16 + 0]);  // Flag: cccUUUUU
+        assertEquals((byte) 0x00, data[16 + 1]);  //  c1a: offset 0 / 0x000
+        assertEquals((byte) 0x06, data[16 + 2]);  //  c1b: length 6+2  -> {\rtf1\a
+        assertEquals((byte) 0x01, data[16 + 3]);  //  c2a: offset 16 / 0x010
+        assertEquals((byte) 0x01, data[16 + 4]);  //  c2b: length 1+2  ->  def
+        assertEquals((byte) 0x0b, data[16 + 5]);  //  c3a: offset 182 / 0xb6
+        assertEquals((byte) 0x60, data[16 + 6]);  //  c3b: length 0+2  -> la
+        assertEquals((byte) 0x6e, data[16 + 7]);  // n
+        assertEquals((byte) 0x67, data[16 + 8]);  // g
+        assertEquals((byte) 0x31, data[16 + 9]);  // 1
+        assertEquals((byte) 0x30, data[16 + 10]); // 0
+        assertEquals((byte) 0x32, data[16 + 11]); // 2
+
+        assertEquals((byte) 0x66, data[16 + 12]); // Flag:  UccUUccU
+        assertEquals((byte) 0x35, data[16 + 13]); // 5
+        assertEquals((byte) 0x00, data[16 + 14]); //  c2a: offset 6 / 0x006
+        assertEquals((byte) 0x64, data[16 + 15]); //  c2b: length 4+2  -> \ansi\a
+        assertEquals((byte) 0x00, data[16 + 16]); //  c3a: offset 7 / 0x007
+        assertEquals((byte) 0x72, data[16 + 17]); //  c3b: length 2+2  -> nsi
+        assertEquals((byte) 0x63, data[16 + 18]); // c
+        assertEquals((byte) 0x70, data[16 + 19]); // p
+        assertEquals((byte) 0x0d, data[16 + 20]); //  c6a: offset 221 / 0x0dd
+        assertEquals((byte) 0xd0, data[16 + 21]); //  c6b: length 0+2  -> g1
+        assertEquals((byte) 0x0e, data[16 + 22]); //  c7a: offset 224 / 0x0e0
+        assertEquals((byte) 0x00, data[16 + 23]); //  c7b: length 0+2  -> 25
+        assertEquals((byte) 0x32, data[16 + 24]); // 2
     }
 
     /**
      * Check that we can decode the first 8 codes
-     * (1 flag byte + 8 codes)  
+     * (1 flag byte + 8 codes)
      */
+    @Test
     public void testFirstBlock() throws Exception {
-       HMEFMessage msg = new HMEFMessage(
-             _samples.openResourceAsStream("quick-winmail.dat")
-       );
-       
-       MAPIAttribute attr = msg.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
-       assertNotNull(attr);
-       MAPIRtfAttribute rtfAttr = (MAPIRtfAttribute)attr;
-
-       // Truncate to header + flag + data for flag
-       byte[] data = new byte[16+12];
-       System.arraycopy(rtfAttr.getRawData(), 0, data, 0, data.length);
-       
-       // Decompress it
-       CompressedRTF comp = new CompressedRTF();
-       byte[] decomp = comp.decompress(new ByteArrayInputStream(data));
-       String decompStr = new String(decomp, "ASCII");
-       
-       // Test
-       assertEquals(block1.length(), decomp.length);
-       assertEquals(block1, decompStr);
+        HMEFMessage msg;
+        try (InputStream is = _samples.openResourceAsStream("quick-winmail.dat")) {
+            msg = new HMEFMessage(is);
+        }
+
+        MAPIAttribute attr = msg.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
+        assertNotNull(attr);
+        MAPIRtfAttribute rtfAttr = (MAPIRtfAttribute) attr;
+
+        // Truncate to header + flag + data for flag
+        byte[] data = new byte[16 + 12];
+        System.arraycopy(rtfAttr.getRawData(), 0, data, 0, data.length);
+
+        // Decompress it
+        CompressedRTF comp = new CompressedRTF();
+        byte[] decomp = comp.decompress(new ByteArrayInputStream(data));
+        String decompStr = new String(decomp, "ASCII");
+
+        // Test
+        assertEquals(block1.length(), decomp.length);
+        assertEquals(block1, decompStr);
     }
 
     /**
      * Check that we can decode the first 16 codes
-     * (flag + 8 codes, flag + 8 codes)  
+     * (flag + 8 codes, flag + 8 codes)
      */
+    @Test
     public void testFirstTwoBlocks() throws Exception {
-       HMEFMessage msg = new HMEFMessage(
-             _samples.openResourceAsStream("quick-winmail.dat")
-       );
-
-       MAPIAttribute attr = msg.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
-       assertNotNull(attr);
-       MAPIRtfAttribute rtfAttr = (MAPIRtfAttribute)attr;
-
-       // Truncate to header + flag + data for flag + flag + data
-       byte[] data = new byte[16+12+13];
-       System.arraycopy(rtfAttr.getRawData(), 0, data, 0, data.length);
-       
-       // Decompress it
-       CompressedRTF comp = new CompressedRTF();
-       byte[] decomp = comp.decompress(new ByteArrayInputStream(data));
-       String decompStr = new String(decomp, "ASCII");
-       
-       // Test
-       assertEquals(block2.length(), decomp.length);
-       assertEquals(block2, decompStr);
+        HMEFMessage msg;
+        try (InputStream is = _samples.openResourceAsStream("quick-winmail.dat")) {
+            msg = new HMEFMessage(is);
+        }
+
+        MAPIAttribute attr = msg.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
+        assertNotNull(attr);
+        MAPIRtfAttribute rtfAttr = (MAPIRtfAttribute) attr;
+
+        // Truncate to header + flag + data for flag + flag + data
+        byte[] data = new byte[16 + 12 + 13];
+        System.arraycopy(rtfAttr.getRawData(), 0, data, 0, data.length);
+
+        // Decompress it
+        CompressedRTF comp = new CompressedRTF();
+        byte[] decomp = comp.decompress(new ByteArrayInputStream(data));
+        String decompStr = new String(decomp, "ASCII");
+
+        // Test
+        assertEquals(block2.length(), decomp.length);
+        assertEquals(block2, decompStr);
     }
 
     /**
      * Check that we can correctly decode the whole file
      * TODO Fix what looks like a padding issue
      */
+    @Test
     public void testFull() throws Exception {
-       HMEFMessage msg = new HMEFMessage(
-             _samples.openResourceAsStream("quick-winmail.dat")
-       );
-       
-       MAPIAttribute attr = msg.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
-       assertNotNull(attr);
-       MAPIRtfAttribute rtfAttr = (MAPIRtfAttribute)attr;
-       
-       InputStream stream = _samples.openResourceAsStream("quick-contents/message.rtf");
-       try {
-           byte[] expected = IOUtils.toByteArray(stream);
-           
-           CompressedRTF comp = new CompressedRTF();
-           byte[] data = rtfAttr.getRawData();
-           byte[] decomp = comp.decompress(new ByteArrayInputStream(data));
-           
-           // Check the length was as expected
-           assertEquals(data.length, comp.getCompressedSize() + 16);
-           assertEquals(expected.length, comp.getDeCompressedSize()); 
-           
-           // Will have been padded though
-           assertEquals(expected.length+2, decomp.length);
-           byte[] tmp = new byte[expected.length];
-           System.arraycopy(decomp, 0, tmp, 0, tmp.length);
-           decomp = tmp;
-           
-           // By byte
-           assertEquals(expected.length, decomp.length);
-           for(int i=0; i<expected.length; i++) {
-               assertEquals(expected[i], decomp[i]);
-           }
-           
-           // By String
-           String expString = new String(expected, "ASCII");
-           String decompStr = rtfAttr.getDataString();
-           assertEquals(expString.length(), decompStr.length());
-           assertEquals(expString, decompStr);
-       } finally {
-           stream.close();
-       }
+        final HMEFMessage msg;
+        try (InputStream is = _samples.openResourceAsStream("quick-winmail.dat")) {
+            msg = new HMEFMessage(is);
+        }
+
+        MAPIAttribute attr = msg.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
+        assertNotNull(attr);
+        MAPIRtfAttribute rtfAttr = (MAPIRtfAttribute) attr;
+
+        final byte[] expected;
+        try (InputStream stream = _samples.openResourceAsStream("quick-contents/message.rtf")) {
+            expected = IOUtils.toByteArray(stream);
+        }
+
+        CompressedRTF comp = new CompressedRTF();
+        byte[] data = rtfAttr.getRawData();
+        byte[] decomp = comp.decompress(new ByteArrayInputStream(data));
+
+        // Check the length was as expected
+        assertEquals(data.length, comp.getCompressedSize() + 16);
+        assertEquals(expected.length, comp.getDeCompressedSize());
+
+        // Will have been padded though
+        assertEquals(expected.length + 2, decomp.length);
+        byte[] tmp = new byte[expected.length];
+        System.arraycopy(decomp, 0, tmp, 0, tmp.length);
+        decomp = tmp;
+
+        // By byte
+        assertEquals(expected.length, decomp.length);
+        for (int i = 0; i < expected.length; i++) {
+            assertEquals(expected[i], decomp[i]);
+        }
+
+        // By String
+        String expString = new String(expected, "ASCII");
+        String decompStr = rtfAttr.getDataString();
+        assertEquals(expString.length(), decompStr.length());
+        assertEquals(expString, decompStr);
     }
 }
index 25f0d07be3d8e4edffe1e58dafc0800bf46852f3..73a4b1b74e996c6c903d060302467418f5a39cfb 100644 (file)
 
 package org.apache.poi.hmef;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.io.InputStream;
 
+import org.apache.poi.POIDataSamples;
 import org.apache.poi.hmef.attribute.MAPIAttribute;
 import org.apache.poi.hmef.attribute.MAPIRtfAttribute;
 import org.apache.poi.hmef.attribute.MAPIStringAttribute;
 import org.apache.poi.hmef.attribute.TNEFProperty;
 import org.apache.poi.hsmf.datatypes.MAPIProperty;
 import org.apache.poi.hsmf.datatypes.Types;
+import org.apache.poi.util.IOUtils;
 import org.apache.poi.util.LittleEndian;
+import org.junit.Test;
+
+public final class TestHMEFMessage {
+    protected static final POIDataSamples _samples = POIDataSamples.getHMEFInstance();
+
+    @Test
+    public void testOpen() throws Exception {
+        HMEFMessage msg = new HMEFMessage(
+                _samples.openResourceAsStream("quick-winmail.dat")
+        );
+
+        assertNotNull(msg);
+    }
+
+    @Test
+    public void testCounts() throws Exception {
+        HMEFMessage msg = new HMEFMessage(
+                _samples.openResourceAsStream("quick-winmail.dat")
+        );
+
+        // Should have 4 attributes on the message
+        assertEquals(4, msg.getMessageAttributes().size());
+
+        // And should have 54 MAPI attributes on it
+        assertEquals(54, msg.getMessageMAPIAttributes().size());
+
+
+        // Should have 5 attachments
+        assertEquals(5, msg.getAttachments().size());
+
+        // Each attachment should have 6 normal attributes, and
+        //  20 or so MAPI ones
+        for (Attachment attach : msg.getAttachments()) {
+            int attrCount = attach.getAttributes().size();
+            int mapiAttrCount = attach.getMAPIAttributes().size();
 
-public final class TestHMEFMessage extends HMEFTest {
-       public void testOpen() throws Exception {
-               HMEFMessage msg = new HMEFMessage(
+            assertEquals(6, attrCount);
+            assertTrue("Should be 20-25 mapi attributes, found " + mapiAttrCount, mapiAttrCount >= 20);
+            assertTrue("Should be 20-25 mapi attributes, found " + mapiAttrCount, mapiAttrCount <= 25);
+        }
+    }
+
+    @Test
+    public void testBasicMessageAttributes() throws Exception {
+        HMEFMessage msg = new HMEFMessage(
+                _samples.openResourceAsStream("quick-winmail.dat")
+        );
+
+        // Should have version, codepage, class and MAPI
+        assertEquals(4, msg.getMessageAttributes().size());
+        assertNotNull(msg.getMessageAttribute(TNEFProperty.ID_TNEFVERSION));
+        assertNotNull(msg.getMessageAttribute(TNEFProperty.ID_OEMCODEPAGE));
+        assertNotNull(msg.getMessageAttribute(TNEFProperty.ID_MESSAGECLASS));
+        assertNotNull(msg.getMessageAttribute(TNEFProperty.ID_MAPIPROPERTIES));
+
+        // Check the order
+        assertEquals(TNEFProperty.ID_TNEFVERSION, msg.getMessageAttributes().get(0).getProperty());
+        assertEquals(TNEFProperty.ID_OEMCODEPAGE, msg.getMessageAttributes().get(1).getProperty());
+        assertEquals(TNEFProperty.ID_MESSAGECLASS, msg.getMessageAttributes().get(2).getProperty());
+        assertEquals(TNEFProperty.ID_MAPIPROPERTIES, msg.getMessageAttributes().get(3).getProperty());
+
+        // Check some that aren't there
+        assertNull(msg.getMessageAttribute(TNEFProperty.ID_AIDOWNER));
+        assertNull(msg.getMessageAttribute(TNEFProperty.ID_ATTACHDATA));
+
+        // Now check the details of one or two
+        assertEquals(
+                0x010000,
+                LittleEndian.getInt(msg.getMessageAttribute(TNEFProperty.ID_TNEFVERSION).getData())
+        );
+        assertEquals(
+                "IPM.Microsoft Mail.Note\0",
+                new String(msg.getMessageAttribute(TNEFProperty.ID_MESSAGECLASS).getData(), "ASCII")
+        );
+    }
+
+    @Test
+    public void testBasicMessageMAPIAttributes() throws Exception {
+        HMEFMessage msg = new HMEFMessage(
+                _samples.openResourceAsStream("quick-winmail.dat")
+        );
+
+        assertEquals("This is a test message", msg.getSubject());
+        assertEquals("{\\rtf1", msg.getBody().substring(0, 6));
+    }
+
+    /**
+     * Checks that the compressed RTF message contents
+     * can be correctly extracted
+     */
+    @Test
+    public void testMessageContents() throws Exception {
+        HMEFMessage msg = new HMEFMessage(
                 _samples.openResourceAsStream("quick-winmail.dat")
-               );
-
-               assertNotNull(msg);
-       }
-
-       public void testCounts() throws Exception {
-      HMEFMessage msg = new HMEFMessage(
-            _samples.openResourceAsStream("quick-winmail.dat")
-      );
-      
-      // Should have 4 attributes on the message
-      assertEquals(4, msg.getMessageAttributes().size());
-      
-      // And should have 54 MAPI attributes on it
-      assertEquals(54, msg.getMessageMAPIAttributes().size());
-      
-      
-      // Should have 5 attachments
-      assertEquals(5, msg.getAttachments().size());
-      
-      // Each attachment should have 6 normal attributes, and 
-      //  20 or so MAPI ones
-      for(Attachment attach : msg.getAttachments()) {
-         int attrCount = attach.getAttributes().size();
-         int mapiAttrCount = attach.getMAPIAttributes().size();
-         
-         assertEquals(6, attrCount);
-         assertTrue("Should be 20-25 mapi attributes, found " + mapiAttrCount, mapiAttrCount >= 20);
-         assertTrue("Should be 20-25 mapi attributes, found " + mapiAttrCount, mapiAttrCount <= 25);
-      }
-       }
-       
-       public void testBasicMessageAttributes() throws Exception {
-      HMEFMessage msg = new HMEFMessage(
-            _samples.openResourceAsStream("quick-winmail.dat")
-      );
-      
-      // Should have version, codepage, class and MAPI
-      assertEquals(4, msg.getMessageAttributes().size());
-      assertNotNull(msg.getMessageAttribute(TNEFProperty.ID_TNEFVERSION));
-      assertNotNull(msg.getMessageAttribute(TNEFProperty.ID_OEMCODEPAGE));
-      assertNotNull(msg.getMessageAttribute(TNEFProperty.ID_MESSAGECLASS));
-      assertNotNull(msg.getMessageAttribute(TNEFProperty.ID_MAPIPROPERTIES));
-      
-      // Check the order
-      assertEquals(TNEFProperty.ID_TNEFVERSION, msg.getMessageAttributes().get(0).getProperty());
-      assertEquals(TNEFProperty.ID_OEMCODEPAGE, msg.getMessageAttributes().get(1).getProperty());
-      assertEquals(TNEFProperty.ID_MESSAGECLASS, msg.getMessageAttributes().get(2).getProperty());
-      assertEquals(TNEFProperty.ID_MAPIPROPERTIES, msg.getMessageAttributes().get(3).getProperty());
-      
-      // Check some that aren't there
-      assertNull(msg.getMessageAttribute(TNEFProperty.ID_AIDOWNER));
-      assertNull(msg.getMessageAttribute(TNEFProperty.ID_ATTACHDATA));
-      
-      // Now check the details of one or two
-      assertEquals(
-            0x010000, 
-            LittleEndian.getInt( msg.getMessageAttribute(TNEFProperty.ID_TNEFVERSION).getData() )
-      );
-      assertEquals(
-            "IPM.Microsoft Mail.Note\0", 
-            new String(msg.getMessageAttribute(TNEFProperty.ID_MESSAGECLASS).getData(), "ASCII")
-      );
-       }
-   
-   public void testBasicMessageMAPIAttributes() throws Exception {
-      HMEFMessage msg = new HMEFMessage(
-            _samples.openResourceAsStream("quick-winmail.dat")
-      );
-      
-      assertEquals("This is a test message", msg.getSubject());
-      assertEquals("{\\rtf1", msg.getBody().substring(0, 6));
-   }
-
-   /**
-    * Checks that the compressed RTF message contents
-    *  can be correctly extracted
-    */
-   public void testMessageContents() throws Exception {
-      HMEFMessage msg = new HMEFMessage(
-            _samples.openResourceAsStream("quick-winmail.dat")
-      );
-      
-      // Firstly by byte
-      MAPIRtfAttribute rtf = (MAPIRtfAttribute)
-         msg.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
-      assertContents("message.rtf", rtf.getData());
-      
-      // Then by String
-      String contents = msg.getBody();
-      // It's all low bytes
-      byte[] contentsBytes = contents.getBytes("ASCII");
-      assertContents("message.rtf", contentsBytes);
-      
-      // try to get a message id that does not exist
-      assertNull(msg.getMessageMAPIAttribute(MAPIProperty.AB_DEFAULT_DIR));
-   }
-   
-   public void testMessageSample1() throws Exception {
-               HMEFMessage msg = new HMEFMessage(
-                               _samples.openResourceAsStream("winmail-sample1.dat"));
-
-               // Firstly by byte
-               MAPIRtfAttribute rtf = (MAPIRtfAttribute) msg
-                               .getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
-               // assertContents("message.rtf", rtf.getData());
-               assertNotNull(rtf);
-
-               // Then by String
-               String contents = msg.getBody();
-               //System.out.println(contents);
-               // It's all low bytes
-               byte[] contentsBytes = contents.getBytes("ASCII");
-               // assertContents("message.rtf", contentsBytes);
-               assertNotNull(contentsBytes);
-               
-               assertNotNull(msg.getSubject());
-               assertNotNull(msg.getBody());
-   }
-   
-   public void testInvalidMessage() throws Exception {
-          InputStream str = new ByteArrayInputStream(new byte[] {0, 0, 0, 0});
-          try {
-                  assertNotNull(new HMEFMessage(str));
-                  fail("Should catch an exception here");
-          } catch (IllegalArgumentException e) {
-                  assertTrue(e.getMessage().contains("TNEF signature not detected in file, expected 574529400 but got 0"));
-          }
-   }
-   
-   
-   public void testNoData() throws Exception {
-          ByteArrayOutputStream out = new ByteArrayOutputStream();
-          
-          // Header
-          LittleEndian.putInt(HMEFMessage.HEADER_SIGNATURE, out);
-          
-          // field
-          LittleEndian.putUShort(0, out);
-          
-          byte[] bytes = out.toByteArray();
-          InputStream str = new ByteArrayInputStream(bytes);
-          HMEFMessage msg = new HMEFMessage(str);
-          assertNull(msg.getSubject());
-          assertNull(msg.getBody());
-   }
-   
-   public void testInvalidLevel() throws Exception {
-          ByteArrayOutputStream out = new ByteArrayOutputStream();
-          
-          // Header
-          LittleEndian.putInt(HMEFMessage.HEADER_SIGNATURE, out);
-          
-          // field
-          LittleEndian.putUShort(0, out);
-          
-          // invalid level
-          LittleEndian.putUShort(90, out);
-          
-          byte[] bytes = out.toByteArray();
-          InputStream str = new ByteArrayInputStream(bytes);
-          try {
-                  assertNotNull(new HMEFMessage(str));
-                  fail("Should catch an exception here");
-          } catch (IllegalStateException e) {
-                  assertTrue(e.getMessage().contains("Unhandled level 90"));
-          }
-   }
-   
-   public void testCustomProperty() throws Exception {
-       HMEFMessage msg = new HMEFMessage(
-               _samples.openResourceAsStream("quick-winmail.dat")
-       );
-       
-       // Should have non-standard properties with IDs 0xE28 and 0xE29
-       boolean hasE28 = false;
-       boolean hasE29 = false;
-       for (MAPIAttribute attr : msg.getMessageMAPIAttributes()) {
-           if (attr.getProperty().id == 0xe28) hasE28 = true;
-           if (attr.getProperty().id == 0xe29) hasE29 = true;
-       }
-       assertEquals(true, hasE28);
-       assertEquals(true, hasE29);
-       
-       // Ensure we can fetch those as custom ones
-       MAPIProperty propE28 = MAPIProperty.createCustom(0xe28, Types.ASCII_STRING, "Custom E28");
-       MAPIProperty propE29 = MAPIProperty.createCustom(0xe29, Types.ASCII_STRING, "Custom E29");
-       assertNotNull(msg.getMessageMAPIAttribute(propE28));
-       assertNotNull(msg.getMessageMAPIAttribute(propE29));
-       
-       assertEquals(MAPIStringAttribute.class, msg.getMessageMAPIAttribute(propE28).getClass());
-       assertEquals(
-            "Zimbra - Mark Rogers", 
-            ((MAPIStringAttribute)msg.getMessageMAPIAttribute(propE28)).getDataString().substring(10)
-       );
-   }
+        );
+
+        // Firstly by byte
+        MAPIRtfAttribute rtf = (MAPIRtfAttribute)
+                msg.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
+        assertContents("message.rtf", rtf.getData());
+
+        // Then by String
+        String contents = msg.getBody();
+        // It's all low bytes
+        byte[] contentsBytes = contents.getBytes("ASCII");
+        assertContents("message.rtf", contentsBytes);
+
+        // try to get a message id that does not exist
+        assertNull(msg.getMessageMAPIAttribute(MAPIProperty.AB_DEFAULT_DIR));
+    }
+
+    @Test
+    public void testMessageSample1() throws Exception {
+        HMEFMessage msg = new HMEFMessage(
+                _samples.openResourceAsStream("winmail-sample1.dat"));
+
+        // Firstly by byte
+        MAPIRtfAttribute rtf = (MAPIRtfAttribute) msg
+                .getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
+        // assertContents("message.rtf", rtf.getData());
+        assertNotNull(rtf);
+
+        // Then by String
+        String contents = msg.getBody();
+        //System.out.println(contents);
+        // It's all low bytes
+        byte[] contentsBytes = contents.getBytes("ASCII");
+        // assertContents("message.rtf", contentsBytes);
+        assertNotNull(contentsBytes);
+
+        assertNotNull(msg.getSubject());
+        assertNotNull(msg.getBody());
+    }
+
+    @Test
+    public void testInvalidMessage() throws Exception {
+        InputStream str = new ByteArrayInputStream(new byte[]{0, 0, 0, 0});
+        try {
+            assertNotNull(new HMEFMessage(str));
+            fail("Should catch an exception here");
+        } catch (IllegalArgumentException e) {
+            assertTrue(e.getMessage().contains("TNEF signature not detected in file, expected 574529400 but got 0"));
+        }
+    }
+
+    @Test
+    public void testNoData() throws Exception {
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+        // Header
+        LittleEndian.putInt(HMEFMessage.HEADER_SIGNATURE, out);
+
+        // field
+        LittleEndian.putUShort(0, out);
+
+        byte[] bytes = out.toByteArray();
+        InputStream str = new ByteArrayInputStream(bytes);
+        HMEFMessage msg = new HMEFMessage(str);
+        assertNull(msg.getSubject());
+        assertNull(msg.getBody());
+    }
+
+    @Test
+    public void testInvalidLevel() throws Exception {
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+        // Header
+        LittleEndian.putInt(HMEFMessage.HEADER_SIGNATURE, out);
+
+        // field
+        LittleEndian.putUShort(0, out);
+
+        // invalid level
+        LittleEndian.putUShort(90, out);
+
+        byte[] bytes = out.toByteArray();
+        InputStream str = new ByteArrayInputStream(bytes);
+        try {
+            assertNotNull(new HMEFMessage(str));
+            fail("Should catch an exception here");
+        } catch (IllegalStateException e) {
+            assertTrue(e.getMessage().contains("Unhandled level 90"));
+        }
+    }
+
+    @Test
+    public void testCustomProperty() throws Exception {
+        HMEFMessage msg = new HMEFMessage(
+                _samples.openResourceAsStream("quick-winmail.dat")
+        );
+
+        // Should have non-standard properties with IDs 0xE28 and 0xE29
+        boolean hasE28 = false;
+        boolean hasE29 = false;
+        for (MAPIAttribute attr : msg.getMessageMAPIAttributes()) {
+            if (attr.getProperty().id == 0xe28) hasE28 = true;
+            if (attr.getProperty().id == 0xe29) hasE29 = true;
+        }
+        assertEquals(true, hasE28);
+        assertEquals(true, hasE29);
+
+        // Ensure we can fetch those as custom ones
+        MAPIProperty propE28 = MAPIProperty.createCustom(0xe28, Types.ASCII_STRING, "Custom E28");
+        MAPIProperty propE29 = MAPIProperty.createCustom(0xe29, Types.ASCII_STRING, "Custom E29");
+        assertNotNull(msg.getMessageMAPIAttribute(propE28));
+        assertNotNull(msg.getMessageMAPIAttribute(propE29));
+
+        assertEquals(MAPIStringAttribute.class, msg.getMessageMAPIAttribute(propE28).getClass());
+        assertEquals(
+                "Zimbra - Mark Rogers",
+                ((MAPIStringAttribute) msg.getMessageMAPIAttribute(propE28)).getDataString().substring(10)
+        );
+    }
+
+    static void assertContents(String filename, byte[] actual)
+            throws IOException {
+        try (InputStream stream = _samples.openResourceAsStream("quick-contents/" + filename)) {
+            byte[] expected = IOUtils.toByteArray(stream);
+
+            assertEquals(expected.length, actual.length);
+            for (int i = 0; i < expected.length; i++) {
+                assertEquals("Byte " + i + " wrong", expected[i], actual[i]);
+            }
+        }
+    }
+
 }
 
index 7fcad02042d743acd61b5455e8b7b4cfff2945b2..675a455cc6b1d6a911fb9a69dfdf1242671185e3 100644 (file)
@@ -17,6 +17,9 @@
 
 package org.apache.poi.hmef.attribute;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.text.DateFormat;
@@ -28,159 +31,159 @@ import org.apache.poi.hmef.HMEFMessage;
 import org.apache.poi.hsmf.datatypes.MAPIProperty;
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.LocaleUtil;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public final class TestMAPIAttributes {
+    private static final POIDataSamples _samples = POIDataSamples.getHMEFInstance();
+    private HMEFMessage quick;
+    private InputStream stream;
+
+    @Before
+    public void setUp() throws Exception {
+        stream = _samples.openResourceAsStream("quick-winmail.dat");
+        quick = new HMEFMessage(stream);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        stream.close();
+    }
+
+
+    /**
+     * Test counts
+     */
+    @Test
+    public void testCounts() throws Exception {
+        // Message should have 54
+        assertEquals(54, quick.getMessageMAPIAttributes().size());
+
+        // First attachment should have 22
+        assertEquals(22, quick.getAttachments().get(0).getMAPIAttributes().size());
+    }
+
+    /**
+     * Test various general ones
+     */
+    @Test
+    public void testBasics() throws Exception {
+        // Try constructing two attributes
+        byte[] data = new byte[]{
+                // Level one, id 36867, type 6
+                0x01, 0x03, (byte) 0x90, 0x06, 0x00,
+                // Length 24
+                0x24, 0x00, 0x00, 0x00,
+
+                // Three attributes
+                0x03, 0x00, 0x00, 0x00,
+                // AlternateRecipientAllowed = 01 00
+                0x0B, 0x00, 0x02, 0x00,
+                0x01, 0x00, 0x00, 0x00,
+                // Priority = 00 00 00 00
+                0x03, 0x00, 0x26, 0x00,
+                0x00, 0x00, 0x00, 0x00,
+                // ConversationTopic = Test
+                0x1E, 0x00, 0x70, 0x00,
+                0x01, 0x00, 0x00, 0x00,
+                0x04, 0x00, 0x00, 0x00,
+                (byte) 'T', (byte) 'e',
+                (byte) 's', (byte) 't',
+                // Checksum (may be wrong...)
+                0x01, 0x00
+        };
+        ByteArrayInputStream bais = new ByteArrayInputStream(data);
+
+        // Create it
+        int level = bais.read();
+        assertEquals(1, level);
+        TNEFAttribute attr = TNEFAttribute.create(bais);
+
+        // Check it
+        assertNotNull(attr);
+        assertEquals(TNEFMAPIAttribute.class, attr.getClass());
+
+        TNEFMAPIAttribute mapi = (TNEFMAPIAttribute) attr;
+        assertEquals(3, mapi.getMAPIAttributes().size());
+
+        assertEquals(
+                MAPIProperty.ALTERNATE_RECIPIENT_ALLOWED,
+                mapi.getMAPIAttributes().get(0).getProperty()
+        );
+        assertEquals(1, LittleEndian.getUShort(
+                mapi.getMAPIAttributes().get(0).getData()
+        ));
+
+        assertEquals(
+                MAPIProperty.PRIORITY,
+                mapi.getMAPIAttributes().get(1).getProperty()
+        );
+        assertEquals(0, LittleEndian.getUShort(
+                mapi.getMAPIAttributes().get(1).getData()
+        ));
+
+        assertEquals(
+                MAPIProperty.CONVERSATION_TOPIC,
+                mapi.getMAPIAttributes().get(2).getProperty()
+        );
+        assertEquals(
+                "Test",
+                ((MAPIStringAttribute) mapi.getMAPIAttributes().get(2)).getDataString()
+        );
+    }
+
+    /**
+     * Test String, Date and RTF ones
+     */
+    @Test
+    public void testTyped() throws Exception {
+        MAPIAttribute attr;
+
+        // String
+        //  ConversationTopic -> This is a test message
+        attr = quick.getMessageMAPIAttribute(MAPIProperty.CONVERSATION_TOPIC);
+        assertNotNull(attr);
+        assertEquals(MAPIStringAttribute.class, attr.getClass());
+
+        MAPIStringAttribute str = (MAPIStringAttribute) attr;
+        assertEquals("This is a test message", str.getDataString());
+
+        // Date
+        //  (Unknown/Custom) 32955 -> Wed Dec 15 2010 @ 14:46:31 UTC
+        attr = null;
+        for (MAPIAttribute a : quick.getMessageMAPIAttributes()) {
+            if (a.getProperty().id == 32955) {
+                attr = a;
+                break;
+            }
+        }
+        assertNotNull(attr);
+        assertEquals(MAPIDateAttribute.class, attr.getClass());
+
+        MAPIDateAttribute date = (MAPIDateAttribute) attr;
+        DateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss", Locale.UK);
+        fmt.setTimeZone(LocaleUtil.TIMEZONE_UTC);
+        assertEquals("15-Dec-2010 14:46:31", fmt.format(date.getDate()));
+
+        // RTF
+        //   RtfCompressed -> {\rtf1...
+        attr = quick.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
+        assertNotNull(attr);
+        assertEquals(MAPIRtfAttribute.class, attr.getClass());
+
+        MAPIRtfAttribute rtf = (MAPIRtfAttribute) attr;
+        assertEquals("{\\rtf1", rtf.getDataString().substring(0, 6));
+    }
+
+    /**
+     * Check common ones via helper accessors
+     */
+    @Test
+    public void testCommon() throws Exception {
+        assertEquals("This is a test message", quick.getSubject());
 
-import junit.framework.TestCase;
-
-public final class TestMAPIAttributes extends TestCase {
-   private static final POIDataSamples _samples = POIDataSamples.getHMEFInstance();
-   private HMEFMessage quick;
-   private InputStream stream;
-   
-   @Override
-   protected void setUp() throws Exception {
-      super.setUp();
-      
-      stream = _samples.openResourceAsStream("quick-winmail.dat");
-      quick = new HMEFMessage(stream);
-   }
-
-
-   @Override
-protected void tearDown() throws Exception {
-       stream.close();
-
-       super.tearDown();
-   }
-
-
-/** 
-    * Test counts
-    */
-   public void testCounts() throws Exception {
-      // Message should have 54
-      assertEquals(54, quick.getMessageMAPIAttributes().size());
-      
-      // First attachment should have 22
-      assertEquals(22, quick.getAttachments().get(0).getMAPIAttributes().size());
-   }
-       
-   /**
-    * Test various general ones
-    */
-   public void testBasics() throws Exception {
-      // Try constructing two attributes
-      byte[] data = new byte[] {
-            // Level one, id 36867, type 6
-            0x01,    0x03, (byte)0x90,   0x06, 0x00,
-            // Length 24
-            0x24, 0x00, 0x00, 0x00,
-            
-            // Three attributes
-            0x03, 0x00, 0x00, 0x00,
-            // AlternateRecipientAllowed = 01 00
-            0x0B, 0x00, 0x02, 0x00,
-            0x01, 0x00, 0x00, 0x00,
-            // Priority = 00 00 00 00
-            0x03, 0x00, 0x26, 0x00,
-            0x00, 0x00, 0x00, 0x00,
-            // ConversationTopic = Test
-            0x1E, 0x00, 0x70, 0x00,
-            0x01, 0x00, 0x00, 0x00,
-            0x04, 0x00, 0x00, 0x00,
-            (byte)'T', (byte)'e',
-            (byte)'s', (byte)'t',
-            // Checksum (may be wrong...)
-            0x01, 0x00
-      };
-      ByteArrayInputStream bais = new ByteArrayInputStream(data);
-      
-      // Create it
-      int level = bais.read();
-      assertEquals(1, level);
-      TNEFAttribute attr = TNEFAttribute.create(bais);
-      
-      // Check it
-      assertNotNull(attr);
-      assertEquals(TNEFMAPIAttribute.class, attr.getClass());
-      
-      TNEFMAPIAttribute mapi = (TNEFMAPIAttribute)attr;
-      assertEquals(3, mapi.getMAPIAttributes().size());
-      
-      assertEquals(
-            MAPIProperty.ALTERNATE_RECIPIENT_ALLOWED, 
-            mapi.getMAPIAttributes().get(0).getProperty()
-      );
-      assertEquals(1, LittleEndian.getUShort(
-               mapi.getMAPIAttributes().get(0).getData()
-      ));
-      
-      assertEquals(
-            MAPIProperty.PRIORITY, 
-            mapi.getMAPIAttributes().get(1).getProperty()
-      );
-      assertEquals(0, LittleEndian.getUShort(
-               mapi.getMAPIAttributes().get(1).getData()
-      ));
-      
-      assertEquals(
-            MAPIProperty.CONVERSATION_TOPIC, 
-            mapi.getMAPIAttributes().get(2).getProperty()
-      );
-      assertEquals(
-            "Test",
-            ((MAPIStringAttribute)mapi.getMAPIAttributes().get(2)).getDataString()
-      );
-   }
-
-   /**
-    * Test String, Date and RTF ones
-    */
-   public void testTyped() throws Exception {
-      MAPIAttribute attr;
-      
-      // String
-      //  ConversationTopic -> This is a test message
-      attr = quick.getMessageMAPIAttribute(MAPIProperty.CONVERSATION_TOPIC);
-      assertNotNull(attr);
-      assertEquals(MAPIStringAttribute.class, attr.getClass());
-      
-      MAPIStringAttribute str = (MAPIStringAttribute)attr;
-      assertEquals("This is a test message", str.getDataString());
-      
-      // Date
-      //  (Unknown/Custom) 32955 -> Wed Dec 15 2010 @ 14:46:31 UTC
-      attr = null;
-      for(MAPIAttribute a : quick.getMessageMAPIAttributes()) {
-         if(a.getProperty().id == 32955) {
-            attr = a;
-            break;
-         }
-      }
-      assertNotNull(attr);
-      assertEquals(MAPIDateAttribute.class, attr.getClass());
-      
-      MAPIDateAttribute date = (MAPIDateAttribute)attr;
-      DateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss", Locale.UK);
-      fmt.setTimeZone(LocaleUtil.TIMEZONE_UTC);
-      assertEquals("15-Dec-2010 14:46:31", fmt.format(date.getDate()));
-      
-      // RTF
-      //   RtfCompressed -> {\rtf1...
-      attr = quick.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
-      assertNotNull(attr);
-      assertEquals(MAPIRtfAttribute.class, attr.getClass());
-      
-      MAPIRtfAttribute rtf = (MAPIRtfAttribute)attr;
-      assertEquals("{\\rtf1", rtf.getDataString().substring(0, 6));
-   }
-
-   /**
-    * Check common ones via helper accessors
-    */
-   public void testCommon() throws Exception {
-      assertEquals("This is a test message", quick.getSubject());
-      
-      assertEquals("quick.doc", quick.getAttachments().get(0).getLongFilename());
-      assertEquals(".doc", quick.getAttachments().get(0).getExtension());
-   }
+        assertEquals("quick.doc", quick.getAttachments().get(0).getLongFilename());
+        assertEquals(".doc", quick.getAttachments().get(0).getExtension());
+    }
 }
index 04004fae23c82c4659bdb2db97c830e9d95627bb..4f274aa54e128e86930a9aa4f42ef6e922fb6290 100644 (file)
 
 package org.apache.poi.hmef.attribute;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
 import java.io.ByteArrayInputStream;
+import java.io.InputStream;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.Locale;
@@ -28,182 +32,186 @@ import org.apache.poi.hmef.HMEFMessage;
 import org.apache.poi.hsmf.datatypes.MAPIProperty;
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.LocaleUtil;
+import org.junit.Before;
+import org.junit.Test;
+
+public final class TestTNEFAttributes {
+    private static final POIDataSamples _samples = POIDataSamples.getHMEFInstance();
+    private HMEFMessage quick;
+
+    @Before
+    public void setUp() throws Exception {
+        try (InputStream is = _samples.openResourceAsStream("quick-winmail.dat")) {
+            quick = new HMEFMessage(is);
+        }
+    }
+
+    /**
+     * Test counts
+     */
+    @Test
+    public void testCounts() throws Exception {
+        // The message should have 4 attributes
+        assertEquals(4, quick.getMessageAttributes().size());
+
+        // Each attachment should have 6 attributes
+        for (Attachment attach : quick.getAttachments()) {
+            assertEquals(6, attach.getAttributes().size());
+        }
+    }
+
+    /**
+     * Test the basics
+     */
+    @Test
+    public void testBasics() throws Exception {
+        // An int one
+        assertEquals(
+                0x010000,
+                LittleEndian.getInt(quick.getMessageAttribute(TNEFProperty.ID_TNEFVERSION).getData())
+        );
+
+        // Claims not to be text, but really is
+        assertEquals(
+                "IPM.Microsoft Mail.Note\0",
+                new String(quick.getMessageAttribute(TNEFProperty.ID_MESSAGECLASS).getData(), "ASCII")
+        );
+
+        // Try constructing two attributes
+        byte[] data = new byte[]{
+                // Level one, id 36870, type 8
+                0x01, 0x06, (byte) 0x90, 0x08, 0x00,
+                // Length 4
+                0x04, 0x00, 0x00, 0x00,
+                // Data
+                0x00, 0x00, 0x01, 0x00,
+                // Checksum
+                0x01, 0x00,
+
+                // level one, id 36871, type 6
+                0x01, 0x07, (byte) 0x90, 0x06, 0x00,
+                // Length 8
+                0x08, 0x00, 0x00, 0x00,
+                // Data
+                (byte) 0xe4, 0x04, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00,
+                // Checksum
+                (byte) 0xe8, 0x00
+        };
+        ByteArrayInputStream bais = new ByteArrayInputStream(data);
+
+        // Create them
+        int level = bais.read();
+        assertEquals(1, level);
+        TNEFAttribute attr1 = TNEFAttribute.create(bais);
+
+        level = bais.read();
+        assertEquals(1, level);
+        TNEFAttribute attr2 = TNEFAttribute.create(bais);
+
+        assertEquals(-1, bais.read());
+
+        // Check them
+        assertEquals(TNEFProperty.ID_TNEFVERSION, attr1.getProperty());
+        assertEquals(8, attr1.getType());
+        assertEquals(4, attr1.getData().length);
+        assertEquals(0x010000, LittleEndian.getInt(attr1.getData()));
+
+        assertEquals(TNEFProperty.ID_OEMCODEPAGE, attr2.getProperty());
+        assertEquals(6, attr2.getType());
+        assertEquals(8, attr2.getData().length);
+        assertEquals(0x04e4, LittleEndian.getInt(attr2.getData()));
+    }
+
+    /**
+     * Test string based ones
+     */
+    @Test
+    public void testString() throws Exception {
+        TNEFAttribute attr = quick.getAttachments().get(0).getAttribute(
+                TNEFProperty.ID_ATTACHTITLE
+        );
+        assertNotNull(attr);
+        assertEquals(TNEFStringAttribute.class, attr.getClass());
+
+        // It is a null terminated string
+        assertEquals("quick.doc\u0000", new String(attr.getData(), "ASCII"));
+
+        // But when we ask for the string, that is sorted for us
+        TNEFStringAttribute str = (TNEFStringAttribute) attr;
+        assertEquals("quick.doc", str.getString());
+    }
+
+    /**
+     * Test date based ones
+     */
+    @Test
+    public void testDate() throws Exception {
+        TNEFAttribute attr = quick.getAttachments().get(0).getAttribute(
+                TNEFProperty.ID_ATTACHMODIFYDATE
+        );
+        assertNotNull(attr);
+        assertEquals(TNEFDateAttribute.class, attr.getClass());
+
+        // It is a series of date parts
+        // Weds 28th April 2010 @ 12:40:56 UTC
+        assertEquals(2010, LittleEndian.getUShort(attr.getData(), 0));
+        assertEquals(04, LittleEndian.getUShort(attr.getData(), 2));
+        assertEquals(28, LittleEndian.getUShort(attr.getData(), 4));
+        assertEquals(12, LittleEndian.getUShort(attr.getData(), 6));
+        assertEquals(40, LittleEndian.getUShort(attr.getData(), 8));
+        assertEquals(56, LittleEndian.getUShort(attr.getData(), 10));
+        assertEquals(3, LittleEndian.getUShort(attr.getData(), 12)); // Weds
+
+        // Ask for it as a Java date, and have it converted
+        // Pick a predictable format + location + timezone
+        TNEFDateAttribute date = (TNEFDateAttribute) attr;
+        DateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss", Locale.UK);
+        fmt.setTimeZone(LocaleUtil.TIMEZONE_UTC);
+        assertEquals("28-Apr-2010 12:40:56", fmt.format(date.getDate()));
+    }
+
+    /**
+     * Test a bit of mapi
+     */
+    @Test
+    public void testMAPI() throws Exception {
+        // Message MAPI
+        TNEFAttribute attr = quick.getMessageAttribute(
+                TNEFProperty.ID_MAPIPROPERTIES
+        );
+        assertNotNull(attr);
+        assertEquals(TNEFMAPIAttribute.class, attr.getClass());
+
+        TNEFMAPIAttribute mapi = (TNEFMAPIAttribute) attr;
+        assertEquals(54, mapi.getMAPIAttributes().size());
+        assertEquals(
+                MAPIProperty.ALTERNATE_RECIPIENT_ALLOWED,
+                mapi.getMAPIAttributes().get(0).getProperty()
+        );
+
+
+        // Attribute MAPI
+        attr = quick.getAttachments().get(0).getAttribute(
+                TNEFProperty.ID_ATTACHMENT
+        );
+        assertNotNull(attr);
+        assertEquals(TNEFMAPIAttribute.class, attr.getClass());
+
+        mapi = (TNEFMAPIAttribute) attr;
+        assertEquals(22, mapi.getMAPIAttributes().size());
+        assertEquals(
+                MAPIProperty.ATTACH_SIZE,
+                mapi.getMAPIAttributes().get(0).getProperty()
+        );
+    }
 
-import junit.framework.TestCase;
-
-public final class TestTNEFAttributes extends TestCase {
-   private static final POIDataSamples _samples = POIDataSamples.getHMEFInstance();
-   private HMEFMessage quick;
-   
-   @Override
-   protected void setUp() throws Exception {
-      super.setUp();
-      
-      quick = new HMEFMessage(
-            _samples.openResourceAsStream("quick-winmail.dat")
-      );
-   }
-       
-       /** 
-        * Test counts
-        */
-       public void testCounts() throws Exception {
-          // The message should have 4 attributes 
-      assertEquals(4, quick.getMessageAttributes().size());
-      
-      // Each attachment should have 6 attributes
-      for(Attachment attach : quick.getAttachments()) {
-         assertEquals(6, attach.getAttributes().size());
-      }
-       }
-       
-       /** 
-        * Test the basics
-        */
-       public void testBasics() throws Exception {
-          // An int one
-      assertEquals(
-            0x010000, 
-            LittleEndian.getInt( quick.getMessageAttribute(TNEFProperty.ID_TNEFVERSION).getData() )
-      );
-      
-      // Claims not to be text, but really is
-      assertEquals(
-            "IPM.Microsoft Mail.Note\0", 
-            new String(quick.getMessageAttribute(TNEFProperty.ID_MESSAGECLASS).getData(), "ASCII")
-      );
-          
-          // Try constructing two attributes
-      byte[] data = new byte[] {
-            // Level one, id 36870, type 8
-            0x01,    0x06, (byte)0x90,   0x08, 0x00,
-            // Length 4
-            0x04, 0x00, 0x00, 0x00,
-            // Data
-            0x00, 0x00, 0x01, 0x00,
-            // Checksum
-            0x01, 0x00, 
-            
-            // level one, id 36871, type 6
-            0x01,    0x07, (byte)0x90,   0x06, 0x00,
-            // Length 8
-            0x08, 0x00, 0x00, 0x00,
-            // Data
-            (byte)0xe4, 0x04, 0x00, 0x00,
-            0x00, 0x00, 0x00, 0x00,
-            // Checksum
-            (byte)0xe8, 0x00
-      };
-      ByteArrayInputStream bais = new ByteArrayInputStream(data);
-      
-      // Create them
-      int level = bais.read();
-      assertEquals(1, level);
-      TNEFAttribute attr1 = TNEFAttribute.create(bais);
-      
-      level = bais.read();
-      assertEquals(1, level);
-      TNEFAttribute attr2 = TNEFAttribute.create(bais);
-      
-      assertEquals(-1, bais.read());
-      
-      // Check them
-      assertEquals(TNEFProperty.ID_TNEFVERSION, attr1.getProperty());
-      assertEquals(8, attr1.getType());
-      assertEquals(4, attr1.getData().length);
-      assertEquals(0x010000, LittleEndian.getInt( attr1.getData() ));
-      
-      assertEquals(TNEFProperty.ID_OEMCODEPAGE, attr2.getProperty());
-      assertEquals(6, attr2.getType());
-      assertEquals(8, attr2.getData().length);
-      assertEquals(0x04e4, LittleEndian.getInt( attr2.getData() ));
-       }
-       
-       /**
-        * Test string based ones
-        */
-       public void testString() throws Exception {
-          TNEFAttribute attr = quick.getAttachments().get(0).getAttribute(
-                TNEFProperty.ID_ATTACHTITLE
-          );
-          assertNotNull(attr);
-          assertEquals(TNEFStringAttribute.class, attr.getClass());
-          
-          // It is a null terminated string
-          assertEquals("quick.doc\u0000", new String(attr.getData(), "ASCII"));
-          
-          // But when we ask for the string, that is sorted for us
-          TNEFStringAttribute str = (TNEFStringAttribute)attr;
-          assertEquals("quick.doc", str.getString());
-       }
-
-       /**
-        * Test date based ones
-        */
-       public void testDate() throws Exception {
-      TNEFAttribute attr = quick.getAttachments().get(0).getAttribute(
-            TNEFProperty.ID_ATTACHMODIFYDATE
-      );
-      assertNotNull(attr);
-      assertEquals(TNEFDateAttribute.class, attr.getClass());
-      
-      // It is a series of date parts
-      // Weds 28th April 2010 @ 12:40:56 UTC
-      assertEquals(2010, LittleEndian.getUShort(attr.getData(), 0));
-      assertEquals(04, LittleEndian.getUShort(attr.getData(), 2));
-      assertEquals(28, LittleEndian.getUShort(attr.getData(), 4));
-      assertEquals(12, LittleEndian.getUShort(attr.getData(), 6));
-      assertEquals(40, LittleEndian.getUShort(attr.getData(), 8));
-      assertEquals(56, LittleEndian.getUShort(attr.getData(), 10));
-      assertEquals(3, LittleEndian.getUShort(attr.getData(), 12)); // Weds
-      
-      // Ask for it as a Java date, and have it converted
-      // Pick a predictable format + location + timezone
-      TNEFDateAttribute date = (TNEFDateAttribute)attr;
-      DateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss", Locale.UK);
-      fmt.setTimeZone(LocaleUtil.TIMEZONE_UTC);
-      assertEquals("28-Apr-2010 12:40:56", fmt.format(date.getDate()));
-       }
-       
-       /** 
-        * Test a bit of mapi
-        */
-       public void testMAPI() throws Exception {
-          // Message MAPI
-      TNEFAttribute attr = quick.getMessageAttribute(
-            TNEFProperty.ID_MAPIPROPERTIES
-      );
-      assertNotNull(attr);
-      assertEquals(TNEFMAPIAttribute.class, attr.getClass());
-          
-      TNEFMAPIAttribute mapi = (TNEFMAPIAttribute)attr;
-      assertEquals(54, mapi.getMAPIAttributes().size());
-      assertEquals(
-            MAPIProperty.ALTERNATE_RECIPIENT_ALLOWED, 
-            mapi.getMAPIAttributes().get(0).getProperty()
-      );
-      
-      
-          // Attribute MAPI
-      attr = quick.getAttachments().get(0).getAttribute(
-            TNEFProperty.ID_ATTACHMENT
-      );
-      assertNotNull(attr);
-      assertEquals(TNEFMAPIAttribute.class, attr.getClass());
-      
-      mapi = (TNEFMAPIAttribute)attr;
-      assertEquals(22, mapi.getMAPIAttributes().size());
-      assertEquals(
-            MAPIProperty.ATTACH_SIZE, 
-            mapi.getMAPIAttributes().get(0).getProperty()
-      );
-       }
-       
-       /**
-        * Test common ones via helpers
-        */
-       public void testCommon() throws Exception {
-          assertEquals("This is a test message", quick.getSubject());
-          assertEquals("quick.doc", quick.getAttachments().get(0).getFilename());
-       }
+    /**
+     * Test common ones via helpers
+     */
+    @Test
+    public void testCommon() throws Exception {
+        assertEquals("This is a test message", quick.getSubject());
+        assertEquals("quick.doc", quick.getAttachments().get(0).getFilename());
+    }
 }
index 5d956b0cb85caa0e1bc1fc68309b5ced0797ca68..95a7d91460f035ac44a4d49a5f59c8102bef90e9 100644 (file)
 ==================================================================== */
 package org.apache.poi.hmef.dev;
 
+import java.io.File;
+import java.io.PrintStream;
+
 import org.apache.poi.POIDataSamples;
+import org.apache.poi.util.NullOutputStream;
 import org.junit.Test;
 
-import java.io.File;
-
 public class TestHMEFDumper {
     @Test(expected = IllegalArgumentException.class)
     public void noArguments() throws Exception {
-        HMEFDumper.main(new String[] {});
+        doMain();
     }
 
     @Test
     public void main() throws Exception {
         File file = POIDataSamples.getHMEFInstance().getFile("quick-winmail.dat");
-        HMEFDumper.main(new String[] {
-                file.getAbsolutePath()
-        });
+        doMain(file.getAbsolutePath());
     }
 
     @Test
     public void mainFull() throws Exception {
         File file = POIDataSamples.getHMEFInstance().getFile("quick-winmail.dat");
-        HMEFDumper.main(new String[] {
-                "--full",
-                file.getAbsolutePath()
-        });
+        doMain("--full", file.getAbsolutePath());
+    }
+
+    private static void doMain(String... args) throws Exception {
+        PrintStream ps = System.out;
+        try {
+            System.setOut(new PrintStream(new NullOutputStream(), true, "UTF-8"));
+            HMEFDumper.main(args);
+        } finally {
+            System.setOut(ps);
+        }
     }
 }
\ No newline at end of file