Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue1069 check for model/gltf.binary content type and accept #1075

Merged
merged 13 commits into from
Nov 27, 2021
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [2.14.x] - 2021-11-23

### Added
- Added virtual method for content type checking in `OpenXmlPart` and fix issue for `model/gltf.binary` (#1069)

## [2.14.0] - 2021-10-28

### Added
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using DocumentFormat.OpenXml.Framework;
using System;
using System.Collections.Generic;
using System.IO.Packaging;

namespace DocumentFormat.OpenXml.Packaging
{
/// <summary>
/// Defines the Model3DReferenceRelationshipPart
/// </summary>
public partial class Model3DReferenceRelationshipPart
{
/// <inheritdoc/>
private protected override bool IsValidContentType(PackagePart part)
{
if (base.IsValidContentType(part))
{
return true;
}

// model/gltf.binary is an acceptable MIME for this part, PowerPoint writes this on save.
return part.ContentType == "model/gltf.binary";
}
}
}
22 changes: 16 additions & 6 deletions src/DocumentFormat.OpenXml/Packaging/OpenXmlPart.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,21 +74,21 @@ internal void Load(OpenXmlPackage? openXmlPackage, OpenXmlPart? parent, Uri uriT
_uri = uriTarget;

// TODO: should we delay load?
var metroPart = openXmlPackage.Package.GetPart(uriTarget);
var part = openXmlPackage.Package.GetPart(uriTarget);

if (IsContentTypeFixed && metroPart.ContentType != ContentType)
_packagePart = part;

if (IsContentTypeFixed && !IsValidContentType(part))
{
var errorMessage = SR.Format(
ExceptionMessages.InvalidPartContentType,
metroPart.Uri.OriginalString,
metroPart.ContentType,
part.Uri.OriginalString,
part.ContentType,
ContentType);

throw new OpenXmlPackageException(errorMessage);
}

_packagePart = metroPart;

// add the _uri to be reserved
openXmlPackage.ReserveUri(ContentType, Uri);

Expand Down Expand Up @@ -496,6 +496,16 @@ internal long MaxCharactersInPart
/// </summary>
internal bool IsContentTypeFixed => this is IFixedContentTypePart;

/// <summary>
/// Determines if the content type agrees with this part's constraints.
/// </summary>
/// <param name="part"></param>
/// <returns>True if the content type is valid for this part. False otherwise.</returns>
private protected virtual bool IsValidContentType(PackagePart part)
{
return part.ContentType == ContentType;
}

// find all reachable parts from the package root, the dictionary also used for cycle reference defense
internal sealed override void FindAllReachableParts(IDictionary<OpenXmlPart, bool> reachableParts)
{
Expand Down
40 changes: 40 additions & 0 deletions test/DocumentFormat.OpenXml.Packaging.Tests/OpenXmlPackageTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
using System.Xml.Linq;
using Xunit;

using static DocumentFormat.OpenXml.Tests.TestAssets;

using Text = DocumentFormat.OpenXml.Wordprocessing.Text;

namespace DocumentFormat.OpenXml.Packaging.Tests
Expand Down Expand Up @@ -261,5 +263,43 @@ public void TestDataReferenceRelationshipsAreClonedCorrectly()
MediaReferenceRelationship mrr = slidePart.AddMediaReferenceRelationship(mediaDataPart, "rId4");
Assert.Equal("rId4", mrr.Id);
}

// Regression test for issue #1069
// Opening a PowerPoint presentation with a 3d model graphic will fail if the Model3dReferenceRelationshipPart doesn't
// accept both model/gltf-binary *and* model/gltf.binary MIME types. PowerPoint writes the latter.
[Fact]
public void TestOpenModel3DWrittenByPowerPoint_DotMime()
{
using var testFile = GetStream(TestFiles._3DTestDot, false);

using var presDoc = PresentationDocument.Open(testFile, false);

Assert.NotNull(presDoc);

// Check to see that the Model3DReferenceRelationshippart has content type 'model/gltf-binary'
SlidePart slidePart = presDoc.PresentationPart.GetPartsOfType<SlidePart>().FirstOrDefault();
IEnumerable<Model3DReferenceRelationshipPart> model3DReferenceRelationshipParts = slidePart.Model3DReferenceRelationshipParts;
Model3DReferenceRelationshipPart model3DReferenceRelationshipPart = model3DReferenceRelationshipParts.FirstOrDefault();

Assert.Equal("model/gltf-binary", model3DReferenceRelationshipPart.ContentType);
}

// Also test the acceptance of model/gltf-binary that the SDK writes.
[Fact]
public void TestOpenModel3DWrittenByPowerPoint_DashMime()
{
using var testFile = GetStream(TestFiles._3DTestDash, false);

using var presDoc = PresentationDocument.Open(testFile, false);

Assert.NotNull(presDoc);

// Check to see that the Model3DReferenceRelationshippart has content type 'model/gltf-binary'
SlidePart slidePart = presDoc.PresentationPart.GetPartsOfType<SlidePart>().FirstOrDefault();
IEnumerable<Model3DReferenceRelationshipPart> model3DReferenceRelationshipParts = slidePart.Model3DReferenceRelationshipParts;
Model3DReferenceRelationshipPart model3DReferenceRelationshipPart = model3DReferenceRelationshipParts.FirstOrDefault();

Assert.Equal("model/gltf-binary", model3DReferenceRelationshipPart.ContentType);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ public static class Templates
public const string Spreadsheet = "TestFiles.Spreadsheet.xltx";
}

public const string _3DTestDot = "TestFiles.3dtestdot.pptx";

public const string _3DTestDash = "TestFiles.3dtestdash.pptx";

public const string _5Errors = "TestFiles.5Errors.docx";

public const string Algn_tab_TabAlignment = "TestFiles.Algn_tab_TabAlignment.pptx";
Expand Down
Binary file not shown.
Binary file not shown.