/** * Checks whether this section is equal To another object. The result Is * <c>false</c> if one of the the following conditions holds: * * <ul> * * <li>The other object is not a {@link Section}.</li> * * <li>The format IDs of the two sections are not equal.</li> * * <li>The sections have a different number of properties. However, * properties with ID 1 (codepage) are not counted.</li> * * <li>The other object is not a {@link Section}.</li> * * <li>The properties have different values. The order of the properties * is irrelevant.</li> * * </ul> * * @param o The object To Compare this section with * @return <c>true</c> if the objects are equal, <c>false</c> if * not */ public override bool Equals(Object o) { if (o == null || !(o is Section)) { return(false); } Section s = (Section)o; if (!s.FormatID.Equals(FormatID)) { return(false); } /* Compare all properties except 0 and 1 as they must be handled * specially. */ Property[] pa1 = new Property[Properties.Length]; Property[] pa2 = new Property[s.Properties.Length]; System.Array.Copy(Properties, 0, pa1, 0, pa1.Length); System.Array.Copy(s.Properties, 0, pa2, 0, pa2.Length); /* Extract properties 0 and 1 and Remove them from the copy of the * arrays. */ Property p10 = null; Property p20 = null; for (int i = 0; i < pa1.Length; i++) { long id = pa1[i].ID; if (id == 0) { p10 = pa1[i]; pa1 = Remove(pa1, i); i--; } if (id == 1) { // p11 = pa1[i]; pa1 = Remove(pa1, i); i--; } } for (int i = 0; i < pa2.Length; i++) { long id = pa2[i].ID; if (id == 0) { p20 = pa2[i]; pa2 = Remove(pa2, i); i--; } if (id == 1) { // p21 = pa2[i]; pa2 = Remove(pa2, i); i--; } } /* If the number of properties (not counting property 1) is unequal the * sections are unequal. */ if (pa1.Length != pa2.Length) { return(false); } /* If the dictionaries are unequal the sections are unequal. */ bool dictionaryEqual = true; if (p10 != null && p20 != null) { //tony qu fixed this issue Hashtable a = (Hashtable)p10.Value; Hashtable b = (Hashtable)p20.Value; dictionaryEqual = a.Count == b.Count; } else if (p10 != null || p20 != null) { dictionaryEqual = false; } if (!dictionaryEqual) { return(false); } else { return(Util.AreEqual(pa1, pa2)); } }
/// <summary> /// Initializes a new instance of the <see cref="MutableProperty"/> class. /// </summary> /// <param name="p">The property To copy.</param> public MutableProperty(Property p) { this.ID=p.ID; this.Type=p.Type; this.Value=p.Value; }
/// <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); }