public void TestClassID1() { ClassID clsidTest = new ClassID( new byte[] {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10} , 0 ); Assert.AreEqual(clsidTest.ToString().ToUpper(), "{04030201-0605-0807-090A-0B0C0D0E0F10}" ); }
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 ); bool bExceptionOccurred = false; try { clsidTest.Write(new byte[15], 0); } catch (Exception) { bExceptionOccurred = true; } Assert.IsTrue(bExceptionOccurred); bExceptionOccurred = false; try { clsidTest.Write(new byte[16], 1); } catch (Exception) { bExceptionOccurred = true; } Assert.IsTrue(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) { bExceptionOccurred = true; } Assert.IsFalse(bExceptionOccurred); }
/// <summary> /// Initializes a new instance of the <see cref="MutablePropertySet"/> class. /// Its primary task is To initialize the immutable field with their proper /// values. It also Sets fields that might Change To reasonable defaults. /// </summary> public MutablePropertySet() { /* Initialize the "byteOrder" field. */ byteOrder = LittleEndian.GetUShort(BYTE_ORDER_ASSERTION); /* Initialize the "format" field. */ format = LittleEndian.GetUShort(FORMAT_ASSERTION); /* Initialize "osVersion" field as if the property has been Created on * a Win32 platform, whether this is the case or not. */ osVersion = (OS_WIN32 << 16) | 0x0A04; /* Initailize the "classID" field. */ classID = new ClassID(); /* Initialize the sections. Since property Set must have at least * one section it is Added right here. */ sections = new List<Section>(); sections.Add(new MutableSection()); }
/// <summary> /// Checks whether this ClassID is equal to another /// object. /// </summary> /// <param name="o">the object to compare this PropertySet with</param> /// <returns>true if the objects are equal, else /// false</returns> public override bool Equals(Object o) { if (o == null || !(o is ClassID)) { return(false); } ClassID cid = (ClassID)o; if (bytes.Length != cid.bytes.Length) { return(false); } for (int i = 0; i < bytes.Length; i++) { if (bytes[i] != cid.bytes[i]) { return(false); } } return(true); }
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.AreEqual(clsidTest1, clsidTest1); Assert.AreEqual(clsidTest1, clsidTest2); Assert.IsFalse(clsidTest1.Equals(clsidTest3)); Assert.IsFalse(clsidTest1.Equals(null)); }
/// <summary> /// Constructor from byte data /// </summary> /// <param name="index">index number</param> /// <param name="array">byte data</param> /// <param name="offset">offset into byte data</param> protected Property(int index, byte [] array, int offset) { _raw_data = new byte[ POIFSConstants.PROPERTY_SIZE ]; System.Array.Copy(array, offset, _raw_data, 0, POIFSConstants.PROPERTY_SIZE); _name_size = new ShortField(_name_size_offset, _raw_data); _property_type = new ByteField(PropertyConstants.PROPERTY_TYPE_OFFSET, _raw_data); _node_color = new ByteField(_node_color_offset, _raw_data); _previous_property = new IntegerField(_previous_property_offset, _raw_data); _next_property = new IntegerField(_next_property_offset, _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); _days_2 = new IntegerField(_days_2_offset, _raw_data); _start_block = new IntegerField(_start_block_offset, _raw_data); _size = new IntegerField(_size_offset, _raw_data); _index = index; int name_length = (_name_size.Value / LittleEndianConstants.SHORT_SIZE) - 1; if (name_length < 1) { _name = ""; } else { char[] char_array = new char[ name_length ]; int name_offset = 0; for (int j = 0; j < name_length; j++) { char_array[ j ] = ( char ) new ShortField(name_offset, _raw_data).Value; name_offset += LittleEndianConstants.SHORT_SIZE; } _name = new String(char_array, 0, name_length); } _next_child = null; _previous_child = null; }
/// <summary> /// Initializes a new instance of the <see cref="Property"/> class. /// </summary> protected Property() { _raw_data = new byte[POIFSConstants.PROPERTY_SIZE]; for (int i = 0; i < this._raw_data.Length; i++) { this._raw_data[i] = _default_fill; } _name_size = new ShortField(_name_size_offset); _property_type = new ByteField(PropertyConstants.PROPERTY_TYPE_OFFSET); _node_color = new ByteField(_node_color_offset); _previous_property = new IntegerField(_previous_property_offset, _NO_INDEX, _raw_data); _next_property = new IntegerField(_next_property_offset, _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); _seconds_2 = new IntegerField(_seconds_2_offset, 0, _raw_data); _days_2 = new IntegerField(_days_2_offset, 0, _raw_data); _start_block = new IntegerField(_start_block_offset); _size = new IntegerField(_size_offset, 0, _raw_data); _index = _NO_INDEX; this.Name=""; this.NextChild=null; this.PreviousChild=null; }
/// <summary> /// Creates a {@link Section} instance from a byte array. /// </summary> /// <param name="src">Contains the complete property Set stream.</param> /// <param name="offset">The position in the stream that points To the /// section's format ID.</param> public Section(byte[] src, int offset) { int o1 = offset; /* * Read the format ID. */ formatID = new ClassID(src, o1); o1 += ClassID.LENGTH; /* * Read the offset from the stream's start and positions To * the section header. */ this.offset = LittleEndian.GetUInt(src, o1); o1 = (int)this.offset; /* * Read the section Length. */ size = (int)LittleEndian.GetUInt(src, o1); o1 += LittleEndianConsts.INT_SIZE; /* * Read the number of properties. */ int propertyCount = (int)LittleEndian.GetUInt(src, o1); o1 += LittleEndianConsts.INT_SIZE; /* * Read the properties. The offset is positioned at the first * entry of the property list. There are two problems: * * 1. For each property we have To Find out its Length. In the * property list we Find each property's ID and its offset relative * To the section's beginning. Unfortunately the properties in the * property list need not To be in ascending order, so it is not * possible To calculate the Length as * (offset of property(i+1) - offset of property(i)). Before we can * that we first have To sort the property list by ascending offsets. * * 2. We have To Read the property with ID 1 before we Read other * properties, at least before other properties containing strings. * The reason is that property 1 specifies the codepage. If it Is * 1200, all strings are in Unicode. In other words: Before we can * Read any strings we have To know whether they are in Unicode or * not. Unfortunately property 1 is not guaranteed To be the first in * a section. * * The algorithm below Reads the properties in two passes: The first * one looks for property ID 1 and extracts the codepage number. The * seconds pass Reads the other properties. */ properties = new Property[propertyCount]; /* Pass 1: Read the property list. */ int pass1OffSet = o1; ArrayList propertyList = new ArrayList(propertyCount); PropertyListEntry ple; for (int i = 0; i < properties.Length; i++) { ple = new PropertyListEntry(); /* Read the property ID. */ ple.id = (int)LittleEndian.GetUInt(src, pass1OffSet); pass1OffSet += LittleEndianConsts.INT_SIZE; /* OffSet from the section's start. */ ple.offset = (int)LittleEndian.GetUInt(src, pass1OffSet); pass1OffSet += LittleEndianConsts.INT_SIZE; /* Add the entry To the property list. */ propertyList.Add(ple); } /* Sort the property list by ascending offsets: */ propertyList.Sort(); /* Calculate the properties' Lengths. */ for (int i = 0; i < propertyCount - 1; i++) { PropertyListEntry ple1 = (PropertyListEntry)propertyList[i]; PropertyListEntry ple2 = (PropertyListEntry)propertyList[i + 1]; ple1.Length = ple2.offset - ple1.offset; } if (propertyCount > 0) { ple = (PropertyListEntry)propertyList[propertyCount - 1]; ple.Length = size - ple.offset; //if (ple.Length <= 0) //{ // StringBuilder b = new StringBuilder(); // b.Append("The property Set claims To have a size of "); // b.Append(size); // b.Append(" bytes. However, it exceeds "); // b.Append(ple.offset); // b.Append(" bytes."); // throw new IllegalPropertySetDataException(b.ToString()); //} } /* Look for the codepage. */ int codepage = -1; for (IEnumerator i = propertyList.GetEnumerator(); codepage == -1 && i.MoveNext(); ) { ple = (PropertyListEntry)i.Current; /* Read the codepage if the property ID is 1. */ if (ple.id == PropertyIDMap.PID_CODEPAGE) { /* Read the property's value type. It must be * VT_I2. */ int o = (int)(this.offset + ple.offset); long type = LittleEndian.GetUInt(src, o); o += LittleEndianConsts.INT_SIZE; if (type != Variant.VT_I2) throw new HPSFRuntimeException ("Value type of property ID 1 is not VT_I2 but " + type + "."); /* Read the codepage number. */ codepage = LittleEndian.GetUShort(src, o); } } /* Pass 2: Read all properties - including the codepage property, * if available. */ int i1 = 0; for (IEnumerator i = propertyList.GetEnumerator(); i.MoveNext(); ) { ple = (PropertyListEntry)i.Current; Property p = new Property(ple.id, src, this.offset + ple.offset, ple.Length, codepage); if (p.ID == PropertyIDMap.PID_CODEPAGE) p = new Property(p.ID, p.Type, codepage); properties[i1++] = p; } /* * Extract the dictionary (if available). * Tony changed the logic */ this.dictionary = (IDictionary)GetProperty(0); }
public void TestWriteTwoSections() { String STREAM_NAME = "PropertySetStream"; String SECTION1 = "Section 1"; String SECTION2 = "Section 2"; FileInfo fi = TempFile.CreateTempFile(POI_FS, ".doc"); FileStream file = new FileStream(fi.FullName, FileMode.Open, FileAccess.ReadWrite); //filename.deleteOnExit(); FileStream out1 = file; POIFSFileSystem poiFs = new POIFSFileSystem(); MutablePropertySet ps = new MutablePropertySet(); ps.ClearSections(); ClassID formatID = new ClassID(); formatID.Bytes = new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; MutableSection s1 = new MutableSection(); s1.SetFormatID(formatID); s1.SetProperty(2, SECTION1); ps.AddSection(s1); MutableSection s2 = new MutableSection(); s2.SetFormatID(formatID); s2.SetProperty(2, SECTION2); ps.AddSection(s2); poiFs.CreateDocument(ps.GetStream(), STREAM_NAME); poiFs.WriteFileSystem(out1); //out1.Close(); /* Read the POIFS: */ psa = new PropertySet[1]; POIFSReader reader2 = new POIFSReader(); //reader2.StreamReaded += new POIFSReaderEventHandler(reader2_StreamReaded); POIFSReaderListener2 prl = new POIFSReaderListener2(); reader2.RegisterListener(prl); reader2.Read(file); Assert.IsNotNull(psa[0]); Section s = (Section)(psa[0].Sections[0]); Assert.AreEqual(s.FormatID, formatID); Object p = s.GetProperty(2); Assert.AreEqual(SECTION1, p); s = (Section)(psa[0].Sections[1]); p = s.GetProperty(2); Assert.AreEqual(SECTION2, p); file.Close(); //File.Delete(dataDir + POI_FS); try { File.Delete(fi.FullName); } catch { } }
/// <summary> /// Sets the section's format ID. /// </summary> /// <param name="formatID">The section's format ID as a byte array. It components /// are in big-endian format.</param> public void SetFormatID(byte[] formatID) { ClassID fid = this.FormatID; if (fid == null) { fid = new ClassID(); SetFormatID(fid); } fid.Bytes=formatID; }
/// <summary> /// Sets the section's format ID. /// </summary> /// <param name="formatID">The section's format ID</param> public void SetFormatID(ClassID formatID) { this.formatID = formatID; }
/// <summary> /// Initializes this {@link PropertySet} instance from a byte /// array. The method assumes that it has been checked alReady that /// the byte array indeed represents a property Set stream. It does /// no more checks on its own. /// </summary> /// <param name="src">Byte array containing the property Set stream</param> /// <param name="offset">The property Set stream starts at this offset</param> /// <param name="Length">Length of the property Set stream.</param> private void init(byte[] src, int offset, int Length) { /* FIXME (3): Ensure that at most "Length" bytes are Read. */ /* * Read the stream's header fields. */ int o = offset; byteOrder = LittleEndian.GetUShort(src, o); o += LittleEndianConsts.SHORT_SIZE; format = LittleEndian.GetUShort(src, o); o += LittleEndianConsts.SHORT_SIZE; osVersion = (int)LittleEndian.GetUInt(src, o); o += LittleEndianConsts.INT_SIZE; classID = new ClassID(src, o); o += ClassID.LENGTH; int sectionCount = LittleEndian.GetInt(src, o); o += LittleEndianConsts.INT_SIZE; if (sectionCount < 0) throw new HPSFRuntimeException("Section count " + sectionCount + " is negative."); /* * Read the sections, which are following the header. They * start with an array of section descriptions. Each one * consists of a format ID telling what the section Contains * and an offset telling how many bytes from the start of the * stream the section begins. */ /* * Most property Sets have only one section. The Document * Summary Information stream has 2. Everything else is a rare * exception and is no longer fostered by Microsoft. */ sections = new List<Section>(sectionCount); /* * Loop over the section descriptor array. Each descriptor * consists of a ClassID and a DWord, and we have To increment * "offset" accordingly. */ for (int i = 0; i < sectionCount; i++) { Section s = new Section(src, o); o += ClassID.Length + LittleEndianConsts.INT_SIZE; sections.Add(s); } }
/// <summary> /// Checks whether a byte array is in the Horrible Property Set /// Format. /// </summary> /// <param name="src">The byte array To check.</param> /// <param name="offset">The offset in the byte array.</param> /// <param name="Length">The significant number of bytes in the byte /// array. Only this number of bytes will be checked.</param> /// <returns> /// <c>true</c> if the byte array is a property Set /// stream; otherwise, <c>false</c>. /// </returns> public static bool IsPropertySetStream(byte[] src, int offset, int Length) { /* FIXME (3): Ensure that at most "Length" bytes are Read. */ /* * Read the header fields of the stream. They must always be * there. */ int o = offset; int byteOrder = LittleEndian.GetUShort(src, o); o += LittleEndianConsts.SHORT_SIZE; byte[] temp = new byte[LittleEndianConsts.SHORT_SIZE]; LittleEndian.PutShort(temp, 0, (short)byteOrder); if (!Arrays.Equals(temp, BYTE_ORDER_ASSERTION)) return false; int format = LittleEndian.GetUShort(src, o); o += LittleEndianConsts.SHORT_SIZE; temp = new byte[LittleEndianConsts.SHORT_SIZE]; LittleEndian.PutShort(temp,0, (short)format); if (!Arrays.Equals(temp, FORMAT_ASSERTION)) return false; long osVersion = LittleEndian.GetUInt(src, offset); o += LittleEndianConsts.INT_SIZE; ClassID classID = new ClassID(src, offset); o += ClassID.LENGTH; long sectionCount = LittleEndian.GetUInt(src, o); o += LittleEndianConsts.INT_SIZE; if (sectionCount < 0) return false; return true; }
/** * Writes a 16-byte {@link ClassID} To an output stream. * * @param out The stream To Write To * @param n The value To Write * @return The number of bytes written * @exception IOException if an I/O error occurs */ public static int WriteToStream(Stream out1, ClassID n) { byte[] b = new byte[16]; n.Write(b, 0); out1.Write(b, 0, b.Length); return b.Length; }