Skip to content

Commit

Permalink
Rework the handling of FMTID0 in OlePropertiesContainer
Browse files Browse the repository at this point in the history
  • Loading branch information
Numpsy authored and jeremy-visionaid committed Nov 18, 2024
1 parent a23eecf commit a311f64
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 11 deletions.
6 changes: 6 additions & 0 deletions OpenMcdf.Ole.Tests/OlePropertiesExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -510,11 +510,15 @@ public void TestRetainDictionaryPropertyInAppSpecificStreams()
[4] = "Project Name"
};

Guid expectedFmtid0 = Guid.Parse("f0d6d0b1-a0d8-11ce-8aa2-08003601e988");

using (var cf = RootStorage.Open(modifiedStream, StorageModeFlags.LeaveOpen))
{
using CfbStream testStream = cf.OpenStream("Issue134");
OlePropertiesContainer co = new(testStream);

Assert.AreEqual(ContainerType.AppSpecific, co.ContainerType);
Assert.AreEqual(expectedFmtid0, co.FMTID0);
CollectionAssert.AreEqual(expectedPropertyNames, co.PropertyNames);

// Write test file
Expand All @@ -527,6 +531,8 @@ public void TestRetainDictionaryPropertyInAppSpecificStreams()
using CfbStream testStream = cf.OpenStream("Issue134");
OlePropertiesContainer co = new(testStream);

Assert.AreEqual(ContainerType.AppSpecific, co.ContainerType);
Assert.AreEqual(expectedFmtid0, co.FMTID0);
CollectionAssert.AreEqual(expectedPropertyNames, co.PropertyNames);
}
}
Expand Down
59 changes: 48 additions & 11 deletions OpenMcdf.Ole/OlePropertiesContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,26 @@ public class OlePropertiesContainer

public OlePropertiesContainer? UserDefinedProperties { get; private set; }

/// <summary>
/// Gets the type of the container.
/// </summary>
public ContainerType ContainerType { get; }
private Guid? FmtID0 { get; }

/// <summary>
/// Gets the FMTID of the properties container.
/// </summary>
public Guid FMTID0 { get; }

public PropertyContext Context { get; }

private readonly List<OleProperty> properties = new();
internal Stream? cfStream;

/// <summary>
/// Create a new instance of <see cref="OlePropertiesContainer"/> with the specified code page and container type.
/// </summary>
/// <param name="codePage">The code page to use for the new container.</param>
/// <param name="containerType">The type of the new container.</param>
public OlePropertiesContainer(int codePage, ContainerType containerType)
{
Context = new PropertyContext
Expand All @@ -36,6 +48,7 @@ public OlePropertiesContainer(int codePage, ContainerType containerType)
};

ContainerType = containerType;
FMTID0 = FmtIdFromContainerType(containerType);
}

public OlePropertiesContainer(CfbStream cfStream)
Expand All @@ -47,13 +60,8 @@ public OlePropertiesContainer(CfbStream cfStream)
using BinaryReader reader = new(cfStream, Encoding.Unicode, true);
pStream.Read(reader);

if (pStream.FMTID0 == FormatIdentifiers.SummaryInformation)
ContainerType = ContainerType.SummaryInfo;
else if (pStream.FMTID0 == FormatIdentifiers.DocSummaryInformation)
ContainerType = ContainerType.DocumentSummaryInfo;
else
ContainerType = ContainerType.AppSpecific;
FmtID0 = pStream.FMTID0;
FMTID0 = pStream.FMTID0;
ContainerType = ContainerTypeFromFmtId(pStream.FMTID0);

PropertyNames = (Dictionary<uint, string>?)pStream.PropertySet0!.Properties
.FirstOrDefault(p => p.PropertyType == PropertyType.DictionaryProperty)?.Value;
Expand Down Expand Up @@ -217,8 +225,6 @@ public void Save(Stream cfStream)
{
using BinaryWriter bw = new(cfStream);

Guid fmtId0 = FmtID0 ?? (ContainerType == ContainerType.SummaryInfo ? FormatIdentifiers.SummaryInformation : FormatIdentifiers.DocSummaryInformation);

PropertySetStream ps = new()
{
ByteOrder = 0xFFFE,
Expand All @@ -228,7 +234,7 @@ public void Save(Stream cfStream)

NumPropertySets = 1,

FMTID0 = fmtId0,
FMTID0 = this.FMTID0,
Offset0 = 0,

FMTID1 = Guid.Empty,
Expand Down Expand Up @@ -284,4 +290,35 @@ public void Save(Stream cfStream)

ps.Write(bw);
}

// Determine the type of the container from the FMTID0 property.
private static ContainerType ContainerTypeFromFmtId(Guid fmtId0)
{
if (fmtId0 == FormatIdentifiers.SummaryInformation)
return ContainerType.SummaryInfo;
else if (fmtId0 == FormatIdentifiers.DocSummaryInformation)
return ContainerType.DocumentSummaryInfo;
else if (fmtId0 == FormatIdentifiers.GlobalInfo)
return ContainerType.GlobalInfo;
else if (fmtId0 == FormatIdentifiers.ImageInfo)
return ContainerType.ImageInfo;
else if (fmtId0 == FormatIdentifiers.ImageContents)
return ContainerType.ImageContents;

return ContainerType.AppSpecific;
}

// Determine the FMTID property from the container type.
// Note: Uses FMTID_DocSummaryInformation by default to match the previous behavior.
private static Guid FmtIdFromContainerType(ContainerType containerType)
{
return containerType switch
{
ContainerType.SummaryInfo => FormatIdentifiers.SummaryInformation,
ContainerType.GlobalInfo => FormatIdentifiers.GlobalInfo,
ContainerType.ImageContents => FormatIdentifiers.ImageContents,
ContainerType.ImageInfo => FormatIdentifiers.ImageInfo,
_ => FormatIdentifiers.DocSummaryInformation,
};
}
}

0 comments on commit a311f64

Please sign in to comment.