| /* ==================================================================== |
| 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.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; |
| 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; |
| |
| public final class TestCompressedRTF extends TestCase { |
| 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... |
| */ |
| 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 |
| } |
| |
| /** |
| * Check that we can decode the first 8 codes |
| * (1 flag byte + 8 codes) |
| */ |
| 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); |
| } |
| |
| /** |
| * Check that we can decode the first 16 codes |
| * (flag + 8 codes, flag + 8 codes) |
| */ |
| 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); |
| } |
| |
| /** |
| * Check that we can correctly decode the whole file |
| * TODO Fix what looks like a padding issue |
| */ |
| 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(); |
| } |
| } |
| } |