Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
ironfede committed Aug 12, 2024
2 parents f823209 + b1aa6ef commit 73c5a2f
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,41 @@ public void RemoveProperty(uint propertyIdentifier)
properties.Remove(toRemove);
}

/// <summary>
/// Create a new UserDefinedProperties container within this container.
/// </summary>
/// <remarks>
/// Only containers of type DocumentSummaryInfo can contain user defined properties.
/// </remarks>
/// <param name="codePage">The code page to use for the user defined properties.</param>
/// <returns>The UserDefinedProperties container.</returns>
/// <exception cref="CFInvalidOperation">If this container is a type that doesn't suppose user defined properties.</exception>
public OLEPropertiesContainer CreateUserDefinedProperties(int codePage)
{
// Only the DocumentSummaryInfo stream can contain a UserDefinedProperties
if (this.ContainerType != ContainerType.DocumentSummaryInfo)
{
throw new CFInvalidOperation($"Only a DocumentSummaryInfo can contain user defined properties. Current container type is {this.ContainerType}");
}

// Create the container, and add the codepage to the initial set of properties
UserDefinedProperties = new OLEPropertiesContainer(codePage, ContainerType.UserDefinedProperties)
{
PropertyNames = new Dictionary<uint, string>()
};

var op = new OLEProperty(UserDefinedProperties)
{
VTType = VTPropertyType.VT_I2,
PropertyIdentifier = 1,
Value = (short)codePage
};

UserDefinedProperties.properties.Add(op);
this.HasUserDefinedProperties = true;

return UserDefinedProperties;
}

public void Save(CFStream cfStream)
{
Expand Down
12 changes: 6 additions & 6 deletions sources/OpenMcdf/CompoundFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public int Compare(CFItem x, CFItem y)
}

/// <summary>
/// Configuration parameters for the compund files.
/// Configuration parameters for the compound files.
/// They can be OR-combined to configure
/// <see cref="T:OpenMcdf.CompoundFile">Compound file</see> behaviour.
/// All flags are NOT set by Default.
Expand Down Expand Up @@ -112,7 +112,7 @@ public enum CFSUpdateMode
/// Standard Microsoft&#169; Compound File implementation.
/// It is also known as OLE/COM structured storage
/// and contains a hierarchy of storage and stream objects providing
/// efficent storage of multiple kinds of documents in a single file.
/// efficient storage of multiple kinds of documents in a single file.
/// Version 3 and 4 of specifications are supported.
/// </summary>
public class CompoundFile : IDisposable
Expand Down Expand Up @@ -1146,7 +1146,7 @@ private void AllocateDIFATSectorChain(List<Sector> FATsectorChain)
nCurrentSectors++;

//... so, adding a FAT sector may induce DIFAT sectors to increase by one
// and consequently this may induce ANOTHER FAT sector (TO-THINK: May this condition occure ?)
// and consequently this may induce ANOTHER FAT sector (TO-THINK: May this condition occur ?)
if (nDIFATSectors * DIFAT_SECTOR_FAT_ENTRIES_COUNT <
(header.FATSectorsNumber > HEADER_DIFAT_ENTRIES_COUNT ?
header.FATSectorsNumber - HEADER_DIFAT_ENTRIES_COUNT :
Expand Down Expand Up @@ -1569,7 +1569,7 @@ internal List<Sector> GetSectorChain(int secID, SectorType chainType)
return GetMiniSectorChain(secID);

default:
throw new CFException("Unsupproted chain type");
throw new CFException("Unsupported chain type");
}
}

Expand Down Expand Up @@ -2668,7 +2668,7 @@ void IDisposable.Dispose()

/// <summary>
/// When called from user code, release all resources, otherwise, in the case runtime called it,
/// only unmanagd resources are released.
/// only unmanaged resources are released.
/// </summary>
/// <param name="disposing">If true, method has been called from User code, if false it's been called from .net runtime</param>
protected virtual void Dispose(bool disposing)
Expand Down Expand Up @@ -2760,7 +2760,7 @@ private IList<IDirectoryEntry> FindDirectoryEntries(String entryName)
/// <summary>
/// Get a list of all entries with a given name contained in the document.
/// </summary>
/// <param name="entryName">Name of entries to retrive</param>
/// <param name="entryName">Name of entries to retrieve</param>
/// <returns>A list of name-matching entries</returns>
/// <remarks>This function is aimed to speed up entity lookup in
/// flat-structure files (only one or little more known entries)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -486,5 +486,58 @@ public void Test_CLSID_PROPERTY()

}
}

// The test file 'report.xls' contains a DocumentSummaryInfo section, but no user defined properties.
// This tests adding a new user defined properties section to the existing DocumentSummaryInfo.
[TestMethod]
public void Test_ADD_USER_DEFINED_PROPERTIES_SECTION()
{
if (File.Exists("test_add_user_defined_properties.xls"))
File.Delete("test_add_user_defined_properties.xls");

using (CompoundFile cf = new CompoundFile("report.xls"))
{
var dsiStream = cf.RootStorage.GetStream("\u0005DocumentSummaryInformation");
var co = dsiStream.AsOLEPropertiesContainer();

Assert.IsFalse(co.HasUserDefinedProperties);
Assert.IsNull(co.UserDefinedProperties);

var newUserDefinedProperties = co.CreateUserDefinedProperties(65001); // 65001 - UTF-8

newUserDefinedProperties.PropertyNames[2] = "MyCustomProperty";

var newProperty = co.NewProperty(VTPropertyType.VT_LPSTR, 2);
newProperty.Value = "Testing";
newUserDefinedProperties.AddProperty(newProperty);

co.Save(dsiStream);
cf.SaveAs("test_add_user_defined_properties.xls");
}

using (CompoundFile cf = new CompoundFile("test_add_user_defined_properties.xls"))
{
var co = cf.RootStorage.GetStream("\u0005DocumentSummaryInformation").AsOLEPropertiesContainer();

// User defined properties should be present now
Assert.IsTrue(co.HasUserDefinedProperties);
Assert.IsNotNull(co.UserDefinedProperties);
Assert.AreEqual(65001, co.UserDefinedProperties.Context.CodePage);

// And the expected properties should the there
var propArray = co.UserDefinedProperties.Properties.ToArray();
Assert.AreEqual(propArray.Length, 2);

// CodePage prop
Assert.AreEqual(1u, propArray[0].PropertyIdentifier);
Assert.AreEqual("0x00000001", propArray[0].PropertyName);
Assert.AreEqual((short)-535, propArray[0].Value);

// User properties
Assert.AreEqual("MyCustomProperty", propArray[1].PropertyName);
Assert.AreEqual("Testing", propArray[1].Value);
Assert.AreEqual(VTPropertyType.VT_LPSTR, propArray[1].VTType);
}
}
}
}

0 comments on commit 73c5a2f

Please sign in to comment.