File: System\Windows\Documents\FixedSchema.cs
Web Access
Project: src\src\Microsoft.DotNet.Wpf\src\PresentationFramework\PresentationFramework.csproj (PresentationFramework)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
#region Using directives
 
using System.Collections;
using System.Text;
using System.Windows.Markup;
using System.Xml;
using System.IO;
using System.IO.Packaging;
using System.Resources;
using System.Reflection;
using MS.Internal;
 
#endregion
 
 
namespace System.Windows.Documents
{
    internal class XpsSchemaValidator
    {
        private class XmlEncodingEnforcingTextReader : XmlTextReader
        {
            public XmlEncodingEnforcingTextReader(Stream objectStream)
                : base(objectStream)
            {
            }
 
            public override bool Read()
            {
                bool result = base.Read();
 
                if (result && !_encodingChecked)
                {
                    if (base.NodeType == XmlNodeType.XmlDeclaration)
                    {
                        string encoding = base["encoding"];
 
                        if (encoding != null)
                        {
                            if (!encoding.Equals(Encoding.Unicode.WebName, StringComparison.OrdinalIgnoreCase) &&
                                        !encoding.Equals(Encoding.UTF8.WebName, StringComparison.OrdinalIgnoreCase))
                            {
                                throw new FileFormatException(SR.XpsValidatingLoaderUnsupportedEncoding);
                            }
                        }
                    }
 
                    if (!(base.Encoding is UTF8Encoding) && !(base.Encoding is UnicodeEncoding))
                    {
                        throw new FileFormatException(SR.XpsValidatingLoaderUnsupportedEncoding);
                    }
 
                    _encodingChecked = true;
                }
 
                return result;
            }
 
            private bool _encodingChecked;
        }
 
        public
        XpsSchemaValidator(
            XpsValidatingLoader loader,
            XpsSchema schema, 
            ContentType mimeType,
            Stream  objectStream,
            Uri packageUri,
            Uri baseUri
            )
        {
            XmlTextReader xmlTextReader = new XmlEncodingEnforcingTextReader(objectStream);
 
            xmlTextReader.ProhibitDtd = true;
            xmlTextReader.Normalization = true;
 
            XmlReader xmlReader = xmlTextReader;
 
            string [] predefinedNamespaces = _predefinedNamespaces;
            if ( !string.IsNullOrEmpty(schema.RootNamespaceUri) )
            {
                predefinedNamespaces = new string[_predefinedNamespaces.Length + 1];
                predefinedNamespaces[0] = schema.RootNamespaceUri;
                _predefinedNamespaces.CopyTo(predefinedNamespaces, 1);
            }
 
            xmlReader = new XmlCompatibilityReader(xmlReader, predefinedNamespaces);
            xmlReader = XmlReader.Create(xmlReader, schema.GetXmlReaderSettings());
 
            if (schema.HasUriAttributes(mimeType) && packageUri != null && baseUri != null)
            {
                xmlReader = new RootXMLNSAndUriValidatingXmlReader(loader, schema, 
                                                        xmlReader, packageUri, baseUri);
            }
            else
            {
                xmlReader = new RootXMLNSAndUriValidatingXmlReader(loader, schema, xmlReader);
            }
 
            _compatReader = xmlReader;
        }
 
        public
        XmlReader
        XmlReader
        {
            get
            {
                return _compatReader;
            }
        }
 
        private
        XmlReader               _compatReader;
        static private string [] _predefinedNamespaces = new string [1] { 
            XamlReaderHelper.DefinitionMetroNamespaceURI
        };
 
        private class RootXMLNSAndUriValidatingXmlReader : XmlWrappingReader
        {
            public RootXMLNSAndUriValidatingXmlReader(
                        XpsValidatingLoader loader,
                        XpsSchema schema,
                        XmlReader xmlReader,
                        Uri packageUri,
                        Uri baseUri)
                        : base(xmlReader)
            {
                _loader = loader;
                _schema = schema;
                _packageUri = packageUri;
                _baseUri = baseUri;
            }
 
            public RootXMLNSAndUriValidatingXmlReader(
                        XpsValidatingLoader loader,
                        XpsSchema schema,
                        XmlReader xmlReader )
                : base(xmlReader)
            {
                _loader = loader;
                _schema = schema;
            }
 
            private void CheckUri(string attr)
            {
                CheckUri(Reader.LocalName, attr);
            }
 
            private void CheckUri(string localName, string attr)
            {
                if (!object.ReferenceEquals(attr, _lastAttr))      // Check for same string object, not for equality!
                {
                    _lastAttr = attr;
                    string [] uris = _schema.ExtractUriFromAttr(localName, attr);
                    if (uris != null)
                    {
                        foreach (string uriAttr in uris)
                        {
                            if (uriAttr.Length > 0)
                            {
                                Uri targetUri = PackUriHelper.ResolvePartUri(_baseUri, new Uri(uriAttr, UriKind.Relative));
                                Uri absTargetUri = PackUriHelper.Create(_packageUri, targetUri);
                                _loader.UriHitHandler(_node,absTargetUri);
                            }
                        }
                    }
                }
            }
 
            public override string Value                
            { 
                get 
                {
                    CheckUri(Reader.Value);
                    return Reader.Value;
                }
            }
 
            public override string GetAttribute( string name ) 
            {
                string attr= Reader.GetAttribute( name );
                CheckUri(name,attr);
                return attr;
            }
 
            public override string GetAttribute( string name, string namespaceURI ) 
            {
                string attr = Reader.GetAttribute(name, namespaceURI);
                CheckUri(attr);
                return attr;
            }
 
            public override string GetAttribute( int i ) 
            {
                string attr = Reader.GetAttribute( i );
                CheckUri(attr);
                return attr;
            }
 
            public override bool Read() 
            {
                bool result;
                _node++;
                result = Reader.Read();
 
                if ( (Reader.NodeType == XmlNodeType.Element) && !_rootXMLNSChecked )
                {
                    if (!_schema.IsValidRootNamespaceUri(Reader.NamespaceURI))
                    {
                        throw new FileFormatException(SR.XpsValidatingLoaderUnsupportedRootNamespaceUri);
                    }
                    _rootXMLNSChecked = true;
                }
 
                return result;
            }
 
            private XpsValidatingLoader _loader;
            private XpsSchema _schema;
            private Uri _packageUri;
            private Uri _baseUri;
            private string _lastAttr;
            private int _node;
            private bool _rootXMLNSChecked;
        }
    }
 
 
    internal class XpsSchema
    {
        protected XpsSchema()
        {
        }
 
        static protected void RegisterSchema(XpsSchema schema, ContentType[] handledMimeTypes)
        {
            foreach (ContentType mime in handledMimeTypes)
            {
                _schemas.Add(mime, schema);
            }
        }
 
        protected void RegisterRequiredResourceMimeTypes(ContentType[] requiredResourceMimeTypes)
        {
            if (requiredResourceMimeTypes != null)
            {
                foreach (ContentType type in requiredResourceMimeTypes)
                {
                    _requiredResourceMimeTypes.Add(type, true);
                }
            }
        }
 
        public virtual XmlReaderSettings GetXmlReaderSettings()
        {
            XmlReaderSettings xmlReaderSettings = new XmlReaderSettings();
 
            xmlReaderSettings.ValidationFlags = System.Xml.Schema.XmlSchemaValidationFlags.ProcessIdentityConstraints | System.Xml.Schema.XmlSchemaValidationFlags.ReportValidationWarnings;
 
            return xmlReaderSettings;
        }
 
 
        public virtual void ValidateRelationships(Package package, Uri packageUri, Uri partUri, ContentType mimeType)
        {
        }
 
        public virtual bool HasRequiredResources(ContentType mimeType)
        {
            return false;
        }
 
        public virtual bool HasUriAttributes(ContentType mimeType)
        {
            return false;
        }
 
        public virtual bool AllowsMultipleReferencesToSameUri(ContentType mimeType)
        {
            return true;
        }
 
        public virtual bool IsValidRootNamespaceUri(string namespaceUri)
        {
            return false;
        }
 
        public virtual string RootNamespaceUri
        {
            get
            {
                return "";
            }
        }
 
        public bool IsValidRequiredResourceMimeType(ContentType mimeType)
        {
            foreach (ContentType ct in _requiredResourceMimeTypes.Keys)
            {
                if (ct.AreTypeAndSubTypeEqual(mimeType))
                {
                    return true;
                }
            }
            return false;
        }
 
        public virtual string [] ExtractUriFromAttr(string attrName, string attrValue)
        {
            return null;
        }
 
        static public XpsSchema GetSchema(ContentType mimeType)
        {
            XpsSchema schema = null;
 
            if (!_schemas.TryGetValue(mimeType, out schema))
            {
                throw new FileFormatException(SR.XpsValidatingLoaderUnsupportedMimeType);
            }
 
            return schema;
        }
 
        static private readonly Dictionary<ContentType, XpsSchema> _schemas = new Dictionary<ContentType, XpsSchema>(new ContentType.StrongComparer());
        private Hashtable _requiredResourceMimeTypes = new Hashtable(11);
    }
 
    internal class XpsS0Schema:XpsSchema
    {
        // When creating a new schema, add a static member to XpsSchemaValidator to register it.
        protected
        XpsS0Schema()
        {
        }
 
        public override XmlReaderSettings GetXmlReaderSettings()
        {
            if (_xmlReaderSettings == null)
            {
                _xmlReaderSettings = new XmlReaderSettings();
 
                _xmlReaderSettings.ValidationFlags = System.Xml.Schema.XmlSchemaValidationFlags.ProcessIdentityConstraints | System.Xml.Schema.XmlSchemaValidationFlags.ReportValidationWarnings;
 
                MemoryStream xpsSchemaStream = new MemoryStream(XpsS0Schema.S0SchemaBytes);
                MemoryStream dictionarySchemaStream = new MemoryStream(XpsS0Schema.DictionarySchemaBytes);
 
                XmlResolver resolver = new XmlUrlResolver();
 
                _xmlReaderSettings.ValidationType = ValidationType.Schema;
                _xmlReaderSettings.Schemas.XmlResolver = resolver;
 
                _xmlReaderSettings.Schemas.Add(_xpsS0SchemaNamespace,
                                            new XmlTextReader(xpsSchemaStream));
                _xmlReaderSettings.Schemas.Add(null,
                                            new XmlTextReader(dictionarySchemaStream));
            }
 
            return _xmlReaderSettings;
        }
 
        public override bool HasRequiredResources(ContentType mimeType)
        {
            if (_fixedPageContentType.AreTypeAndSubTypeEqual(mimeType))
            {
                return true;
            }
 
            return false;
        }
 
        public override bool HasUriAttributes(ContentType mimeType)
        {
            // All of the root elements for content types supported by this schema have Uri attributes that need to be checked
            return true;
        }
 
        public override bool AllowsMultipleReferencesToSameUri(ContentType mimeType)
        {
            if (_fixedDocumentSequenceContentType.AreTypeAndSubTypeEqual(mimeType) ||
                _fixedDocumentContentType.AreTypeAndSubTypeEqual(mimeType))
            {
                // FixedDocumentSequence - FixedDocument - FixedPage must form a tree. Cannot share elements
                return false;
            }
            else
            {
                return true;
            }
        }
 
        public override bool IsValidRootNamespaceUri(string namespaceUri)
        {
            return namespaceUri.Equals(_xpsS0SchemaNamespace, StringComparison.Ordinal);
        }
 
        public override string RootNamespaceUri
        {
            get
            {
                return _xpsS0SchemaNamespace;
            }
        }
 
        public override string[] ExtractUriFromAttr(string attrName, string attrValue)
        {
            // Note: Do not check for "FixedPage.NavigateUri", because external references are allowed.
            if (attrName.Equals("Source", StringComparison.Ordinal) ||
                attrName.Equals("FontUri", StringComparison.Ordinal))
            {
                return new string[] { attrValue };
            }
            else if (attrName.Equals("ImageSource", StringComparison.Ordinal))
            {
                if (attrValue.StartsWith(_colorConvertedBitmap, StringComparison.Ordinal))
                {
                    attrValue = attrValue.Substring(_colorConvertedBitmap.Length);
                    string[] pieces = attrValue.Split(new char[] { ' ', '}' });
 
                    return pieces;
                }
                else
                {
                    return new string[] { attrValue };
                }
            }
            else if (attrName.Equals("Color", StringComparison.Ordinal) ||
                attrName.Equals("Fill", StringComparison.Ordinal) ||
                attrName.Equals("Stroke", StringComparison.Ordinal))
            {
                ReadOnlySpan<char> attrValueSpan = attrValue.AsSpan().Trim();
                if (attrValueSpan.StartsWith(_contextColor, StringComparison.Ordinal))
                {
                    attrValueSpan = attrValueSpan.Slice(_contextColor.Length).Trim();
                    int spacePos = attrValueSpan.IndexOf(' ');
                    if (spacePos >= 0)
                    {
                        return new string[] { attrValueSpan.Slice(0, spacePos).ToString() };
                    }
                }
            }
 
            return null;
        }
 
        static
        private
        byte[] 
        S0SchemaBytes
        {
            get
            {
                ResourceManager resourceManager = new ResourceManager( "Schemas_S0", Assembly.GetAssembly(typeof(XpsS0Schema)));
                return (byte[])resourceManager.GetObject("s0schema.xsd");
            }
        }
 
        static
        private
        byte[] 
        DictionarySchemaBytes
        {
            get
            {
                ResourceManager resourceManager = new ResourceManager( "Schemas_S0", Assembly.GetAssembly(typeof(XpsS0Schema)));
                return (byte[])resourceManager.GetObject("rdkey.xsd");
            }
        }
 
        static
        protected
        ContentType _fontContentType = new ContentType("application/vnd.ms-opentype");
 
        static
        protected
        ContentType _colorContextContentType = new ContentType("application/vnd.ms-color.iccprofile");
 
        static
        protected
        ContentType _obfuscatedContentType = new ContentType("application/vnd.ms-package.obfuscated-opentype");
 
        static
        protected
        ContentType _jpgContentType = new ContentType("image/jpeg");
 
        static
        protected
        ContentType _pngContentType = new ContentType("image/png");
 
        static
        protected
        ContentType _tifContentType = new ContentType("image/tiff");
 
        static
        protected
        ContentType _wmpContentType = new ContentType("image/vnd.ms-photo");
 
        static
        protected
        ContentType _fixedDocumentSequenceContentType = new ContentType("application/vnd.ms-package.xps-fixeddocumentsequence+xml");
 
        static
        protected
        ContentType _fixedDocumentContentType = new ContentType("application/vnd.ms-package.xps-fixeddocument+xml");
 
        static
        protected
        ContentType _fixedPageContentType = new ContentType("application/vnd.ms-package.xps-fixedpage+xml");
 
        static
        protected
        ContentType _resourceDictionaryContentType = new ContentType("application/vnd.ms-package.xps-resourcedictionary+xml");
 
        static
        protected
        ContentType _printTicketContentType = new ContentType("application/vnd.ms-printing.printticket+xml");
 
        static
        protected
        ContentType _discardControlContentType = new ContentType("application/vnd.ms-package.xps-discard-control+xml");
 
        private
        const
        String _xpsS0SchemaNamespace = "http://schemas.microsoft.com/xps/2005/06";
 
        private
        const
        string _contextColor = "ContextColor ";
 
        private
        const
        string _colorConvertedBitmap = "{ColorConvertedBitmap ";
 
        static
        private
        XmlReaderSettings _xmlReaderSettings;
    }
 
    internal sealed class XpsS0FixedPageSchema : XpsS0Schema
    {
        public
        XpsS0FixedPageSchema()
        {
            RegisterSchema(this,
                new ContentType[] {  _fixedDocumentSequenceContentType, 
                                _fixedDocumentContentType,
                                _fixedPageContentType
                                }
                    );
            RegisterRequiredResourceMimeTypes(
                new ContentType[] {
                                _resourceDictionaryContentType,
                                _fontContentType, 
                                _colorContextContentType, 
                                _obfuscatedContentType,
                                _jpgContentType,
                                _pngContentType,
                                _tifContentType,
                                _wmpContentType
                                }
                    );
        }
 
        public override void ValidateRelationships(Package package, Uri packageUri, Uri partUri, ContentType mimeType)
        {
            PackagePart part = package.GetPart(partUri);
            PackageRelationshipCollection checkRels;
            int count;
 
            // Can only have 0 or 1 PrintTicket per FDS, FD or FP part
            checkRels = part.GetRelationshipsByType(_printTicketRel);
            count = 0;
            foreach (PackageRelationship rel in checkRels)
            {
                count++;
                if (count > 1)
                {
                    throw new FileFormatException(SR.XpsValidatingLoaderMoreThanOnePrintTicketPart);
                }
 
                // Also check for existence and type
                Uri targetUri = PackUriHelper.ResolvePartUri(partUri, rel.TargetUri);
                Uri absTargetUri = PackUriHelper.Create(packageUri, targetUri);
 
                PackagePart targetPart = package.GetPart(targetUri);
 
                if (!_printTicketContentType.AreTypeAndSubTypeEqual(new ContentType(targetPart.ContentType)))
                {
                    throw new FileFormatException(SR.XpsValidatingLoaderPrintTicketHasIncorrectType);
                }
            }
 
            checkRels = part.GetRelationshipsByType(_thumbnailRel);
            count = 0;
            foreach (PackageRelationship rel in checkRels)
            {
                count++;
                if (count > 1)
                {
                    throw new FileFormatException(SR.XpsValidatingLoaderMoreThanOneThumbnailPart);
                }
 
                // Also check for existence and type
                Uri targetUri = PackUriHelper.ResolvePartUri(partUri, rel.TargetUri);
                Uri absTargetUri = PackUriHelper.Create(packageUri, targetUri);
 
                PackagePart targetPart = package.GetPart(targetUri);
 
                if (!_jpgContentType.AreTypeAndSubTypeEqual(new ContentType(targetPart.ContentType)) &&
                    !_pngContentType.AreTypeAndSubTypeEqual(new ContentType(targetPart.ContentType)))
                {
                    throw new FileFormatException(SR.XpsValidatingLoaderThumbnailHasIncorrectType);
                }
            }
 
            // FixedDocument only has restricted font relationships
            if (_fixedDocumentContentType.AreTypeAndSubTypeEqual(mimeType))
            {
                // Check if target of restricted font relationship is present and is actually a font
                checkRels = part.GetRelationshipsByType(_restrictedFontRel);
                foreach (PackageRelationship rel in checkRels)
                {
                    // Check for existence and type
                    Uri targetUri = PackUriHelper.ResolvePartUri(partUri, rel.TargetUri);
                    Uri absTargetUri = PackUriHelper.Create(packageUri, targetUri);
 
                    PackagePart targetPart = package.GetPart(targetUri);
 
                    if (!_fontContentType.AreTypeAndSubTypeEqual(new ContentType(targetPart.ContentType)) &&
                            !_obfuscatedContentType.AreTypeAndSubTypeEqual(new ContentType(targetPart.ContentType)))
                    {
                        throw new FileFormatException(SR.XpsValidatingLoaderRestrictedFontHasIncorrectType);
                    }
                }
            }
 
            // check constraints for XPS fixed payload start part
            if (_fixedDocumentSequenceContentType.AreTypeAndSubTypeEqual(mimeType))
            {
                // This is the XPS payload root part. We also should check if the Package only has at most one discardcontrol...
                checkRels = package.GetRelationshipsByType(_discardControlRel);
                count = 0;
                foreach (PackageRelationship rel in checkRels)
                {
                    count++;
                    if (count > 1)
                    {
                        throw new FileFormatException(SR.XpsValidatingLoaderMoreThanOneDiscardControlInPackage);
                    }
 
                    // Also check for existence and type
                    Uri targetUri = PackUriHelper.ResolvePartUri(partUri, rel.TargetUri);
                    Uri absTargetUri = PackUriHelper.Create(packageUri, targetUri);
 
                    PackagePart targetPart = package.GetPart(targetUri);
 
                    if (!_discardControlContentType.AreTypeAndSubTypeEqual(new ContentType(targetPart.ContentType)))
                    {
                        throw new FileFormatException(SR.XpsValidatingLoaderDiscardControlHasIncorrectType);
                    }
                }
 
                // This is the XPS payload root part. We also should check if the Package only has at most one thumbnail...
                checkRels = package.GetRelationshipsByType(_thumbnailRel);
                count = 0;
                foreach (PackageRelationship rel in checkRels)
                {
                    count++;
                    if (count > 1)
                    {
                        throw new FileFormatException(SR.XpsValidatingLoaderMoreThanOneThumbnailInPackage);
                    }
 
                    // Also check for existence and type
                    Uri targetUri = PackUriHelper.ResolvePartUri(partUri, rel.TargetUri);
                    Uri absTargetUri = PackUriHelper.Create(packageUri, targetUri);
 
                    PackagePart targetPart = package.GetPart(targetUri);
 
                    if (!_jpgContentType.AreTypeAndSubTypeEqual(new ContentType(targetPart.ContentType)) &&
                        !_pngContentType.AreTypeAndSubTypeEqual(new ContentType(targetPart.ContentType)))
                    {
                        throw new FileFormatException(SR.XpsValidatingLoaderThumbnailHasIncorrectType);
                    }
                }
            }
        }
 
        private
        const
        string _printTicketRel = "http://schemas.microsoft.com/xps/2005/06/printticket";
 
        private
        const
        string _discardControlRel = "http://schemas.microsoft.com/xps/2005/06/discard-control";
 
        private
        const
        string _restrictedFontRel = "http://schemas.microsoft.com/xps/2005/06/restricted-font";
 
        private
        const
        string _thumbnailRel = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
    }
 
    internal sealed class XpsS0ResourceDictionarySchema : XpsS0Schema
    {
        // When creating a new schema, add a static member to XpsSchemaValidator to register it.
        public
        XpsS0ResourceDictionarySchema()
        {
            RegisterSchema(this,
                new ContentType[] {  _resourceDictionaryContentType
                                }
                    );
        }
 
        public override string [] ExtractUriFromAttr(string attrName, string attrValue)
        {
            if (attrName.Equals("Source", StringComparison.Ordinal))      // Cannot chain remote ResourceDictionary parts.
            {
                throw new FileFormatException(SR.XpsValidatingLoaderUnsupportedMimeType);
            }
 
            return base.ExtractUriFromAttr(attrName, attrValue);
        }
    }
 
    internal sealed class XpsDocStructSchema : XpsSchema
    {
        // When creating a new schema, add a static member to XpsSchemaValidator to register it.
        public
        XpsDocStructSchema()
        {
            RegisterSchema(this, new ContentType[] { _documentStructureContentType,
                                            _storyFragmentsContentType } );
        }
 
        public override XmlReaderSettings GetXmlReaderSettings()
        {
            if (_xmlReaderSettings == null)
            {
                _xmlReaderSettings = new XmlReaderSettings();
 
                _xmlReaderSettings.ValidationFlags = System.Xml.Schema.XmlSchemaValidationFlags.ProcessIdentityConstraints | System.Xml.Schema.XmlSchemaValidationFlags.ReportValidationWarnings;
 
                MemoryStream xpsSchemaStream = new MemoryStream(XpsDocStructSchema.SchemaBytes);
 
                XmlResolver resolver = new XmlUrlResolver();
 
                _xmlReaderSettings.ValidationType = ValidationType.Schema;
                _xmlReaderSettings.Schemas.XmlResolver = resolver;
 
                _xmlReaderSettings.Schemas.Add(_xpsDocStructureSchemaNamespace,
                                            new XmlTextReader(xpsSchemaStream));
            }
 
            return _xmlReaderSettings;
        }
 
        public override bool IsValidRootNamespaceUri(string namespaceUri)
        {
            return namespaceUri.Equals(_xpsDocStructureSchemaNamespace, StringComparison.Ordinal);
        }
 
        public override string RootNamespaceUri
        {
            get
            {
                return _xpsDocStructureSchemaNamespace;
            }
        }
 
        static
        private
        byte[]
        SchemaBytes
        {
            get
            {
                ResourceManager resourceManager = new ResourceManager("Schemas_DocStructure", Assembly.GetAssembly(typeof(XpsDocStructSchema)));
                return (byte[])resourceManager.GetObject("DocStructure.xsd");
            }
        }
 
        static
        private
        ContentType _documentStructureContentType = new ContentType("application/vnd.ms-package.xps-documentstructure+xml");
 
        static
        private
        ContentType _storyFragmentsContentType    = new ContentType("application/vnd.ms-package.xps-storyfragments+xml");
        
        private
        const
        String _xpsDocStructureSchemaNamespace = "http://schemas.microsoft.com/xps/2005/06/documentstructure";
 
        static
        private
        XmlReaderSettings _xmlReaderSettings;
    }
}