| File: MS\Internal\Documents\Application\RestrictedTransactionalPackage.cs | Web Access |
| Project: src\wpf\src\Microsoft.DotNet.Wpf\src\PresentationUI\PresentationUI.csproj (PresentationUI) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // This class wraps TransactionalPackage, ensuring that only parts with // approved content types can be written. using System; using System.IO; using System.IO.Packaging; using System.Windows.TrustUI; namespace MS.Internal.Documents.Application { /// <summary> /// This class wraps TransactionalPackage, ensuring that only approved /// part content types can be written. /// </summary> internal sealed class RestrictedTransactionalPackage : TransactionalPackage { #region Constructors //-------------------------------------------------------------------------- // Constructors //------------------------------------------------------------------------- /// <summary> /// Requires an existing open Package; and returns a package which will /// capture changes with out applying them to the original. /// See the class description for details. /// </summary> /// <exception cref="System.ArgumentNullException" /> /// <example> /// Package package = new RestrictedTransactionalPackage( /// Package.Open(source, FileMode.Open, FileAccess.Read)); /// </example> /// <param name="originalPackage">An open package.</param> internal RestrictedTransactionalPackage(Stream original) : base(original) { } #endregion Constructors /// <exception cref="System.ArgumentNullException" /> /// <exception cref="System.ArgumentException" /> internal override void MergeChanges(Stream target) { ArgumentNullException.ThrowIfNull(target); if (TempPackage != null) { foreach (PackagePart part in TempPackage.GetParts()) { // Ensure that all parts being modified are permitted. if ((part != null) && (!IsValidContentType(part.ContentType))) { throw new NotSupportedException(SR.PackagePartTypeNotWritable); } } base.MergeChanges(target); } } /// <summary> /// Creates a new PackagePart. /// </summary> /// <remarks> /// When creating a new PackagePart we must: /// a) ensure the part does not exist in package /// b) ensure there is a writable package /// c) create a temp part /// d) update active part reference to the temp part /// /// What if a PackagePart with the same Uri already exists? /// Package.CreatePart checks for this. /// /// Do we need to worry about updating relationships and other parts? /// Relationships are a part and are thus intrinsically handled. /// </remarks> /// <param name="partUri">Uri for the part to create.</param> /// <param name="contentType">Content type string.</param> /// <param name="compressionOption">Compression options.</param> /// <returns>A new PackagePart.</returns> protected override PackagePart CreatePartCore( Uri partUri, string contentType, CompressionOption compressionOption) { // Ensure that modifying this contentType is permitted. if (!IsValidContentType(contentType)) { throw new ArgumentException(SR.PackagePartTypeNotWritable, nameof(contentType)); } return base.CreatePartCore(partUri, contentType, compressionOption); } /// <summary> /// Verifies that parts of the the given contentType are allowed to be modified. /// </summary> /// <param name="contentType">The content type of the part being modified.</param> /// <returns>True if modification is allowed, false otherwise.</returns> /// Critical: /// 1) This code makes the actual security decision as to whether a specific /// content type can be written. /// TreatAsSafe: /// 1) The list of content types is a hardcoded constant list of strings that /// is only maintained here. The only data being used is the string content /// type to check. private bool IsValidContentType(string contentType) { // Check that the contentType is a valid string, and of one of the approved // contentTypes. // // The approved content types come from the Package-wide content types list // in the XPS Specification and Reference Guide. // Internally available at http://metroportal/ // Externally available at http://www.microsoft.com/xps/ return ((!string.IsNullOrEmpty(contentType)) && ((contentType.Equals( @"application/xml", StringComparison.OrdinalIgnoreCase)) || // Core Properties Part (contentType.Equals( @"application/vnd.openxmlformats-package.core-properties+xml", StringComparison.OrdinalIgnoreCase)) || // Digital Signature Certificate Part (contentType.Equals( @"application/vnd.openxmlformats-package.digital-signature-certificate", StringComparison.OrdinalIgnoreCase)) || // Digital Signature Origin Part (contentType.Equals( @"application/vnd.openxmlformats-package.digital-signature-origin", StringComparison.OrdinalIgnoreCase)) || // Digital Signature XML Signature Part (contentType.Equals( @"application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml", StringComparison.OrdinalIgnoreCase)) || // Relationships Part (contentType.Equals( @"application/vnd.openxmlformats-package.relationships+xml", StringComparison.OrdinalIgnoreCase)) )); } } }