bug 22195 ClassID support, by Michael Zalewski, sync from branch, pls verify
git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@353429 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
e16e9b24e1
commit
f52aea647a
@ -55,6 +55,10 @@
|
||||
*/
|
||||
package org.apache.poi.hpsf;
|
||||
|
||||
import java.io.*;
|
||||
import org.apache.poi.util.HexDump;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
* <p>Represents a class ID (16 bytes). Unlike other little-endian
|
||||
* type the {@link ClassID} is not just 16 bytes stored in the wrong
|
||||
@ -229,7 +233,25 @@ public class ClassID
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a human readable representation of the Class ID
|
||||
* in standard format <code>"{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"</code>
|
||||
* @return String representation of the Class ID represented
|
||||
* by this object.
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer sbClassId = new StringBuffer( 38);
|
||||
sbClassId.append( '{');
|
||||
for( int i=0; i < 16; i++) {
|
||||
sbClassId.append( HexDump.toHex( bytes[ i]));
|
||||
if( i == 3 || i == 5 || i == 7 || i == 9) {
|
||||
sbClassId.append( '-');
|
||||
}
|
||||
}
|
||||
sbClassId.append( '}');
|
||||
return sbClassId.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Object#hashCode()
|
||||
|
@ -59,6 +59,8 @@ import java.io.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.apache.poi.hpsf.ClassID;
|
||||
|
||||
import org.apache.poi.poifs.common.POIFSConstants;
|
||||
import org.apache.poi.poifs.dev.POIFSViewable;
|
||||
import org.apache.poi.util.ByteField;
|
||||
@ -87,6 +89,8 @@ public abstract class Property
|
||||
static final private int _previous_property_offset = 0x44;
|
||||
static final private int _next_property_offset = 0x48;
|
||||
static final private int _child_property_offset = 0x4C;
|
||||
static final private int _storage_clsid_offset = 0x50;
|
||||
static final private int _user_flags_offset = 0x60;
|
||||
static final private int _seconds_1_offset = 0x64;
|
||||
static final private int _days_1_offset = 0x68;
|
||||
static final private int _seconds_2_offset = 0x6C;
|
||||
@ -107,6 +111,8 @@ public abstract class Property
|
||||
private IntegerField _previous_property;
|
||||
private IntegerField _next_property;
|
||||
private IntegerField _child_property;
|
||||
private ClassID _storage_clsid;
|
||||
private IntegerField _user_flags;
|
||||
private IntegerField _seconds_1;
|
||||
private IntegerField _days_1;
|
||||
private IntegerField _seconds_2;
|
||||
@ -136,6 +142,8 @@ public abstract class Property
|
||||
_NO_INDEX, _raw_data);
|
||||
_child_property = new IntegerField(_child_property_offset,
|
||||
_NO_INDEX, _raw_data);
|
||||
_storage_clsid = new ClassID(_raw_data,_storage_clsid_offset);
|
||||
_user_flags = new IntegerField(_user_flags_offset, 0, _raw_data);
|
||||
_seconds_1 = new IntegerField(_seconds_1_offset, 0,
|
||||
_raw_data);
|
||||
_days_1 = new IntegerField(_days_1_offset, 0, _raw_data);
|
||||
@ -173,6 +181,8 @@ public abstract class Property
|
||||
_raw_data);
|
||||
_child_property = new IntegerField(_child_property_offset,
|
||||
_raw_data);
|
||||
_storage_clsid = new ClassID(_raw_data,_storage_clsid_offset);
|
||||
_user_flags = new IntegerField(_user_flags_offset, 0, _raw_data);
|
||||
_seconds_1 = new IntegerField(_seconds_1_offset, _raw_data);
|
||||
_days_1 = new IntegerField(_days_1_offset, _raw_data);
|
||||
_seconds_2 = new IntegerField(_seconds_2_offset, _raw_data);
|
||||
@ -295,12 +305,21 @@ public abstract class Property
|
||||
|
||||
abstract public boolean isDirectory();
|
||||
|
||||
/**
|
||||
* Sets the storage clsid, which is the Class ID of a COM object which
|
||||
* reads and writes this stream
|
||||
* @return storage Class ID for this property stream
|
||||
*/
|
||||
public ClassID getStorageClsid()
|
||||
{
|
||||
return _storage_clsid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name; silently truncates the name if it's too long.
|
||||
*
|
||||
* @param name the new name
|
||||
*/
|
||||
|
||||
protected final void setName(final String name)
|
||||
{
|
||||
char[] char_array = name.toCharArray();
|
||||
@ -327,6 +346,20 @@ public abstract class Property
|
||||
* LittleEndianConsts.SHORT_SIZE), _raw_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the storage class ID for this property stream. This is the Class ID
|
||||
* of the COM object which can read and write this property stream
|
||||
* @param clsidStorage Storage Class ID
|
||||
*/
|
||||
public void setStorageClsid( ClassID clsidStorage)
|
||||
{
|
||||
_storage_clsid = clsidStorage;
|
||||
if( clsidStorage == null) {
|
||||
Arrays.fill( _raw_data, _storage_clsid_offset, _storage_clsid_offset + ClassID.LENGTH, (byte) 0);
|
||||
} else {
|
||||
clsidStorage.write( _raw_data, _storage_clsid_offset);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Set the property type. Makes no attempt to validate the value.
|
||||
*
|
||||
|
171
src/testcases/org/apache/poi/hpsf/basic/TestClassID.java
Normal file
171
src/testcases/org/apache/poi/hpsf/basic/TestClassID.java
Normal file
@ -0,0 +1,171 @@
|
||||
/* ====================================================================
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
* Copyright (c) 2003 The Apache Software Foundation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The end-user documentation included with the redistribution,
|
||||
* if any, must include the following acknowledgment:
|
||||
* "This product includes software developed by the
|
||||
* Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowledgment may appear in the software itself,
|
||||
* if and wherever such third-party acknowledgments normally appear.
|
||||
*
|
||||
* 4. The names "Apache" and "Apache Software Foundation" and
|
||||
* "Apache POI" must not be used to endorse or promote products
|
||||
* derived from this software without prior written permission. For
|
||||
* written permission, please contact apache@apache.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Apache",
|
||||
* "Apache POI", nor may "Apache" appear in their name, without
|
||||
* prior written permission of the Apache Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*/
|
||||
|
||||
package org.apache.poi.hpsf.basic;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hpsf.ClassID;
|
||||
|
||||
/**
|
||||
* <p>Tests ClassID structure.</p>
|
||||
*
|
||||
* @author Michael Zalewski (zalewski@optonline.net)
|
||||
*/
|
||||
public class TestClassID extends TestCase
|
||||
{
|
||||
/**
|
||||
* <p>Constructor</p>
|
||||
*
|
||||
* @param name the test case's name
|
||||
*/
|
||||
public TestClassID(final String name)
|
||||
{
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Various tests of overridden .equals()
|
||||
*/
|
||||
public void testEquals()
|
||||
{
|
||||
ClassID clsidTest1 = new ClassID(
|
||||
new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
|
||||
, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 }
|
||||
, 0
|
||||
);
|
||||
ClassID clsidTest2 = new ClassID(
|
||||
new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
|
||||
, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 }
|
||||
, 0
|
||||
);
|
||||
ClassID clsidTest3 = new ClassID(
|
||||
new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
|
||||
, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x11 }
|
||||
, 0
|
||||
);
|
||||
Assert.assertEquals( clsidTest1, clsidTest1);
|
||||
Assert.assertEquals( clsidTest1, clsidTest2);
|
||||
Assert.assertFalse( clsidTest1.equals( clsidTest3));
|
||||
Assert.assertFalse( clsidTest1.equals( null));
|
||||
}
|
||||
/**
|
||||
* Try to write to a buffer that is too small. This should
|
||||
* throw an Exception
|
||||
*/
|
||||
public void testWriteArrayStoreException()
|
||||
{
|
||||
ClassID clsidTest = new ClassID(
|
||||
new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
|
||||
, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 }
|
||||
, 0
|
||||
);
|
||||
boolean bExceptionOccurred = false;
|
||||
try {
|
||||
clsidTest.write( new byte[ 15], 0);
|
||||
} catch( Exception e) {
|
||||
bExceptionOccurred = true;
|
||||
}
|
||||
Assert.assertTrue( bExceptionOccurred);
|
||||
|
||||
bExceptionOccurred = false;
|
||||
try {
|
||||
clsidTest.write( new byte[ 16], 1);
|
||||
} catch( Exception e) {
|
||||
bExceptionOccurred = true;
|
||||
}
|
||||
Assert.assertTrue( bExceptionOccurred);
|
||||
|
||||
// These should work without throwing an Exception
|
||||
bExceptionOccurred = false;
|
||||
try {
|
||||
clsidTest.write( new byte[ 16], 0);
|
||||
clsidTest.write( new byte[ 17], 1);
|
||||
} catch( Exception e) {
|
||||
bExceptionOccurred = true;
|
||||
}
|
||||
Assert.assertFalse( bExceptionOccurred);
|
||||
}
|
||||
/**
|
||||
* <p>Tests the {@link PropertySet} methods. The test file has two
|
||||
* property set: the first one is a {@link SummaryInformation},
|
||||
* the second one is a {@link DocumentSummaryInformation}.</p>
|
||||
*/
|
||||
public void testClassID()
|
||||
{
|
||||
ClassID clsidTest = new ClassID(
|
||||
new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
|
||||
, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 }
|
||||
, 0
|
||||
);
|
||||
Assert.assertEquals(
|
||||
clsidTest.toString().toUpperCase()
|
||||
, "{04030201-0605-0807-090A-0B0C0D0E0F10}"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Runs the test cases stand-alone.</p>
|
||||
*/
|
||||
public static void main(final String[] args)
|
||||
{
|
||||
System.setProperty("HPSF.testdata.path",
|
||||
"./src/testcases/org/apache/poi/hpsf/data");
|
||||
junit.textui.TestRunner.run(TestClassID.class);
|
||||
}
|
||||
|
||||
}
|
@ -150,6 +150,7 @@ public class TestDocumentProperty
|
||||
( byte ) 0xFE, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF,
|
||||
( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00,
|
||||
( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00,
|
||||
|
||||
( byte ) 0x57, ( byte ) 0x00, ( byte ) 0x6F, ( byte ) 0x00,
|
||||
( byte ) 0x72, ( byte ) 0x00, ( byte ) 0x6B, ( byte ) 0x00,
|
||||
( byte ) 0x62, ( byte ) 0x00, ( byte ) 0x6F, ( byte ) 0x00,
|
||||
@ -182,6 +183,7 @@ public class TestDocumentProperty
|
||||
( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00,
|
||||
( byte ) 0x00, ( byte ) 0x10, ( byte ) 0x00, ( byte ) 0x00,
|
||||
( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00,
|
||||
|
||||
( byte ) 0x05, ( byte ) 0x00, ( byte ) 0x53, ( byte ) 0x00,
|
||||
( byte ) 0x75, ( byte ) 0x00, ( byte ) 0x6D, ( byte ) 0x00,
|
||||
( byte ) 0x6D, ( byte ) 0x00, ( byte ) 0x61, ( byte ) 0x00,
|
||||
@ -214,6 +216,7 @@ public class TestDocumentProperty
|
||||
( byte ) 0x08, ( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00,
|
||||
( byte ) 0x00, ( byte ) 0x10, ( byte ) 0x00, ( byte ) 0x00,
|
||||
( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00,
|
||||
|
||||
( byte ) 0x05, ( byte ) 0x00, ( byte ) 0x44, ( byte ) 0x00,
|
||||
( byte ) 0x6F, ( byte ) 0x00, ( byte ) 0x63, ( byte ) 0x00,
|
||||
( byte ) 0x75, ( byte ) 0x00, ( byte ) 0x6D, ( byte ) 0x00,
|
||||
|
@ -217,11 +217,11 @@ public class TestRootProperty
|
||||
( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00, ( byte ) 0x00
|
||||
};
|
||||
|
||||
verifyReadingProperty(0, input, 0, "Root Entry");
|
||||
verifyReadingProperty(0, input, 0, "Root Entry", "{00020820-0000-0000-C000-000000000046}");
|
||||
}
|
||||
|
||||
private void verifyReadingProperty(int index, byte [] input, int offset,
|
||||
String name)
|
||||
String name, String sClsId)
|
||||
throws IOException
|
||||
{
|
||||
RootProperty property = new RootProperty(index, input,
|
||||
@ -242,6 +242,7 @@ public class TestRootProperty
|
||||
assertEquals(index, property.getIndex());
|
||||
assertEquals(name, property.getName());
|
||||
assertTrue(!property.getChildren().hasNext());
|
||||
assertEquals(property.getStorageClsid().toString(), sClsId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user