| File: System\IO\Packaging\PackagingUtilities.cs | Web Access |
| Project: src\runtime\src\libraries\System.IO.Packaging\src\System.IO.Packaging.csproj (System.IO.Packaging) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Diagnostics; using System.IO; using System.Text; using System.Xml; namespace System.IO.Packaging { internal static class PackagingUtilities { internal const string RelationshipNamespaceUri = "http://schemas.openxmlformats.org/package/2006/relationships"; internal static readonly ContentType RelationshipPartContentType = new ContentType("application/vnd.openxmlformats-package.relationships+xml"); internal const string ContainerFileExtension = "xps"; internal const string XamlFileExtension = "xaml"; #region Internal Methods /// <summary> /// This method is used to determine if we support a given Encoding as per the /// OPC and XPS specs. Currently the only two encodings supported are UTF-8 and /// UTF-16 (Little Endian and Big Endian) /// </summary> /// <param name="reader">XmlReader</param> internal static void PerformInitialReadAndVerifyEncoding(XmlReader reader) { Debug.Assert(reader != null && reader.ReadState == ReadState.Initial); //If the first node is XmlDeclaration we check to see if the encoding attribute is present if (reader.Read() && reader.NodeType == XmlNodeType.XmlDeclaration && reader.Depth == 0) { string? encoding = reader.GetAttribute(EncodingAttribute); if (!string.IsNullOrEmpty(encoding)) { //If a non-empty encoding attribute is present [for example - <?xml version="1.0" encoding="utf-8" ?>] //we check to see if the value is either "utf-8" or "utf-16". Only these two values are supported //Note: For Byte order markings that require additional information to be specified in //the encoding attribute in XmlDeclaration have already been ruled out by this check as we allow for //only two valid values. if (string.Equals(encoding, WebNameUTF8, StringComparison.OrdinalIgnoreCase) || string.Equals(encoding, WebNameUnicode, StringComparison.OrdinalIgnoreCase)) { return; } else { //if the encoding attribute has any other value we throw an exception throw new FileFormatException(SR.EncodingNotSupported); } } } //Previously, the logic in System.IO.Packaging was that if the XmlDeclaration is not present, or encoding attribute //is not present, we base our decision on byte order marking. Previously, reader was an XmlTextReader, which would //take that into account and return the correct value. //However, we can't use XmlTextReader, as it is not in the libraries. Therefore, if there is no XmlDeclaration, or the encoding //attribute is not set, then we will throw now exception, and UTF-8 will be assumed. //TODO: in the future, we can do the work to detect the BOM, and throw an exception if the file is in an invalid encoding. // Eric White: IMO, this is not a serious problem. Office will never write with the wrong encoding, nor will any of the // other suites. The Open XML SDK will always write with the correct encoding. //The future logic would be: //- determine the encoding from the BOM //- if the encoding is not UTF-8 or UTF-16, then throw new FileFormatException(SR.EncodingNotSupported) } /// <summary> /// This method returns the count of xml attributes other than: /// 1. xmlns="namespace" /// 2. xmlns:someprefix="namespace" /// Reader should be positioned at the Element whose attributes /// are to be counted. /// </summary> /// <param name="reader"></param> /// <returns>An integer indicating the number of non-xmlns attributes</returns> internal static int GetNonXmlnsAttributeCount(XmlReader reader) { Debug.Assert(reader != null, "xmlReader should not be null"); Debug.Assert(reader.NodeType == XmlNodeType.Element, "XmlReader should be positioned at an Element"); int readerCount = 0; //If true, reader moves to the attribute //If false, there are no more attributes (or none) //and in that case the position of the reader is unchanged. //First time through, since the reader will be positioned at an Element, //MoveToNextAttribute is the same as MoveToFirstAttribute. while (reader.MoveToNextAttribute()) { if (!string.Equals(reader.Name, XmlNamespace, StringComparison.Ordinal) && !string.Equals(reader.Prefix, XmlNamespace, StringComparison.Ordinal)) { readerCount++; } } //re-position the reader to the element reader.MoveToElement(); return readerCount; } #endregion Internal Methods /// <summary> /// Synchronize access to IsolatedStorage methods that can step on each-other /// </summary> /// <remarks>See PS 1468964 for details.</remarks> private const string XmlNamespace = "xmlns"; private const string EncodingAttribute = "encoding"; private const string WebNameUTF8 = "utf-8"; private const string WebNameUnicode = "utf-16"; } }