Updates referencesource to .NET 4.7
[mono-project.git] / mcs / class / referencesource / System.Web / UI / WebControls / xml.cs
blobfd57f86d647cd7046a9eca8661531a31e109d8e9
1 //------------------------------------------------------------------------------
2 // <copyright file="xml.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 // </copyright>
5 //------------------------------------------------------------------------------
7 namespace System.Web.UI.WebControls {
9 using System;
10 using System.IO;
11 using System.Collections;
12 using System.Collections.Specialized;
13 using System.ComponentModel;
14 using System.ComponentModel.Design;
15 using System.Diagnostics.CodeAnalysis;
16 using System.Drawing.Design;
17 using System.Globalization;
18 using System.Web;
19 using System.Web.Util;
20 using System.Web.UI;
21 using System.Web.Caching;
22 using System.Web.Hosting;
23 using System.Security.Policy;
24 using System.Xml;
25 using System.Xml.Xsl;
26 using System.Xml.XPath;
27 using System.Security.Permissions;
29 public class XmlBuilder : ControlBuilder {
32 public override void AppendLiteralString(string s) {}
35 public override Type GetChildControlType(string tagName, IDictionary attribs) {
36 return null;
40 public override bool NeedsTagInnerText() { return true; }
43 [SuppressMessage("Microsoft.Security", "MSEC1220:ReviewDtdProcessingAssignment", Justification = "Dtd processing is needed for back-compat, but is being done as safely as possible.")]
44 [SuppressMessage("Microsoft.Security.Xml", "CA3069:ReviewDtdProcessingAssignment", Justification = "Dtd processing is needed for back-compat, but is being done as safely as possible.")]
45 public override void SetTagInnerText(string text) {
46 if (!Util.IsWhiteSpaceString(text)) {
48 // Trim the initial whitespaces since XML is very picky (ASURT 58100)
49 int iFirstNonWhiteSpace = Util.FirstNonWhiteSpaceIndex(text);
50 string textNoWS = text.Substring(iFirstNonWhiteSpace);
52 // Update the line number to point to the correct line in the xml
53 // block (ASURT 58233).
54 Line += Util.LineCount(text, 0, iFirstNonWhiteSpace);
56 // Parse the XML here just to cause a parse error in case it is
57 // malformed. It will be parsed again at runtime.
58 XmlDocument document = new XmlDocument();
59 XmlReaderSettings readerSettings = XmlUtils.CreateXmlReaderSettings();
60 readerSettings.LineNumberOffset = Line - 1;
62 // VSWhidbey 546662: XmlReader has different default settings than XmlTextReader which was used in Everett
63 readerSettings.DtdProcessing = DtdProcessing.Parse;
64 readerSettings.CheckCharacters = false;
66 XmlReader dataReader = XmlUtils.CreateXmlReader(new StringReader(textNoWS), string.Empty, readerSettings);
68 try {
69 document.Load(dataReader);
71 catch (XmlException e) {
72 // Xml exception sometimes returns -1 for the line, in which case we ignore it.
73 if (e.LineNumber >= 0) {
74 Line = e.LineNumber;
77 throw;
80 base.AppendLiteralString(text);
86 /// <devdoc>
87 /// <para>[To be supplied.]</para>
88 /// </devdoc>
90 DefaultProperty("DocumentSource"),
91 PersistChildren(false, true),
92 ControlBuilderAttribute(typeof(XmlBuilder)),
93 Designer("System.Web.UI.Design.WebControls.XmlDesigner, " + AssemblyRef.SystemDesign)
95 public class Xml : Control {
97 private XPathNavigator _xpathNavigator;
98 private XmlDocument _document;
99 private XPathDocument _xpathDocument;
100 #pragma warning disable 0618 // To avoid deprecation warning
101 private XslTransform _transform;
102 #pragma warning restore 0618
103 private XslCompiledTransform _compiledTransform;
104 private XsltArgumentList _transformArgumentList;
105 private string _documentContent;
106 private string _documentSource;
107 private string _transformSource;
109 const string identityXslStr =
110 "<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>" +
111 "<xsl:template match=\"/\"> <xsl:copy-of select=\".\"/> </xsl:template> </xsl:stylesheet>";
113 #pragma warning disable 0618 // To avoid deprecation warning
114 static XslTransform _identityTransform;
115 #pragma warning restore 0618
117 [SuppressMessage("Microsoft.Security", "MSEC1201:DoNotUseXslTransform", Justification = "_identityTransform contents are trusted hard-coded string.")]
118 [SuppressMessage("Microsoft.Security.Xml", "CA3050:DoNotUseXslTransform", Justification = "_identityTransform contents are trusted hard-coded string.")]
119 [SuppressMessage("Microsoft.Security", "MSEC1205:DoNotAllowDtdOnXmlTextReader", Justification = "_identityTransform contents are trusted hard-coded string.")]
120 [SuppressMessage("Microsoft.Security.Xml", "CA3054:DoNotAllowDtdOnXmlTextReader", Justification = "_identityTransform contents are trusted hard-coded string.")]
121 [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
122 static Xml() {
124 // Instantiate an identity transform, to be used whenever we need to output XML
125 XmlTextReader reader = new XmlTextReader(new StringReader(identityXslStr));
126 #pragma warning disable 0618 // To avoid deprecation warning
127 _identityTransform = new XslTransform();
128 #pragma warning restore 0618
130 _identityTransform.Load(reader, null /*resolver*/, null /*evidence*/);
134 EditorBrowsable(EditorBrowsableState.Never),
136 public override string ClientID {
137 get {
138 return base.ClientID;
143 EditorBrowsable(EditorBrowsableState.Never),
145 public override ControlCollection Controls {
146 get {
147 return base.Controls;
152 /// <devdoc>
153 /// <para>[To be supplied.]</para>
154 /// </devdoc>
156 Browsable(false),
157 WebSysDescription(SR.Xml_Document),
158 DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
159 Obsolete("The recommended alternative is the XPathNavigator property. Create a System.Xml.XPath.XPathDocument and call CreateNavigator() to create an XPathNavigator. http://go.microsoft.com/fwlink/?linkid=14202"),
161 public XmlDocument Document {
162 get {
163 if (_document == null) {
164 LoadXmlDocument();
166 return _document;
168 set {
169 DocumentSource = null;
170 _xpathDocument = null;
171 _documentContent = null;
172 _document = value;
177 /// <devdoc>
178 /// <para>[To be supplied.]</para>
179 /// </devdoc>
181 Browsable(false),
182 DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
183 WebSysDescription(SR.Xml_DocumentContent)
185 public String DocumentContent {
186 get {
187 return _documentContent != null ? _documentContent : String.Empty;
189 set {
190 _document = null;
191 _xpathDocument = null;
192 _xpathNavigator = null;
193 _documentContent = value;
195 if (DesignMode) {
196 ViewState["OriginalContent"] = null;
202 /// <devdoc>
203 /// <para>[To be supplied.]</para>
204 /// </devdoc>
206 WebCategory("Behavior"),
207 DefaultValue(""),
208 Editor("System.Web.UI.Design.XmlUrlEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor)),
209 UrlProperty(),
210 WebSysDescription(SR.Xml_DocumentSource)
212 public String DocumentSource {
213 get {
214 return (_documentSource == null) ? String.Empty : _documentSource;
216 set {
217 _document = null;
218 _xpathDocument = null;
219 _documentContent = null;
220 _xpathNavigator = null;
221 _documentSource = value;
226 Browsable(false),
227 DefaultValue(false),
228 EditorBrowsable(EditorBrowsableState.Never),
230 public override bool EnableTheming {
231 get {
232 return false;
234 set {
235 throw new NotSupportedException(SR.GetString(SR.NoThemingSupport, this.GetType().Name));
240 Browsable(false),
241 DefaultValue(""),
242 EditorBrowsable(EditorBrowsableState.Never),
244 public override string SkinID {
245 get {
246 return String.Empty;
248 set {
249 throw new NotSupportedException(SR.GetString(SR.NoThemingSupport, this.GetType().Name));
254 /// <devdoc>
255 /// <para>[To be supplied.]</para>
256 /// </devdoc>
258 Browsable(false),
259 WebSysDescription(SR.Xml_Transform),
260 DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
262 #pragma warning disable 0618 // To avoid deprecation warning
263 public XslTransform Transform {
264 #pragma warning restore 0618
265 get {
266 return XmlUtils.GetXslTransform(_transform);
268 set {
269 if (XmlUtils.GetXslTransform(value) != null) {
270 // Setting this property will nullify _transform, so do it first.
271 TransformSource = null;
272 _transform = value;
278 /// <devdoc>
279 /// <para>[To be supplied.]</para>
280 /// </devdoc>
282 Browsable(false),
283 WebSysDescription(SR.Xml_TransformArgumentList),
284 DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
286 public XsltArgumentList TransformArgumentList {
287 get {
288 return _transformArgumentList;
290 set {
291 _transformArgumentList = value;
296 /// <devdoc>
297 /// <para>[To be supplied.]</para>
298 /// </devdoc>
300 WebCategory("Behavior"),
301 DefaultValue(""),
302 Editor("System.Web.UI.Design.XslUrlEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor)),
303 WebSysDescription(SR.Xml_TransformSource),
305 public String TransformSource {
306 get {
307 return (_transformSource == null) ? String.Empty : _transformSource;
309 set {
310 _transform = null;
311 _transformSource = value;
316 /// <devdoc>
317 /// </devdoc>
319 Browsable(false),
320 WebSysDescription(SR.Xml_XPathNavigator),
321 DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
323 public XPathNavigator XPathNavigator {
324 get {
325 return _xpathNavigator;
327 set {
328 DocumentSource = null;
329 _xpathDocument = null;
330 _documentContent = null;
331 _document = null;
332 _xpathNavigator = value;
337 [SuppressMessage("Microsoft.Security", "MSEC1218:ReviewWebControlForSet_DocumentContent", Justification = "Legacy code that trusts our developer input. Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
338 [SuppressMessage("Microsoft.Security.Xml", "CA3067:ReviewWebControlForSet_DocumentContent", Justification = "Legacy code that trusts our developer input. Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
339 protected override void AddParsedSubObject(object obj) {
340 if (obj is LiteralControl) {
341 // Trim the initial whitespaces since XML is very picky (related to ASURT 58100)
342 string text = ((LiteralControl)obj).Text;
344 int iFirstNonWhiteSpace = Util.FirstNonWhiteSpaceIndex(text);
345 DocumentContent = text.Substring(iFirstNonWhiteSpace);
347 if (DesignMode) {
348 ViewState["OriginalContent"] = text;
351 else {
352 throw new HttpException(SR.GetString(SR.Cannot_Have_Children_Of_Type, "Xml", obj.GetType().Name.ToString(CultureInfo.InvariantCulture)));
356 protected override ControlCollection CreateControlCollection() {
357 return new EmptyControlCollection(this);
361 EditorBrowsable(EditorBrowsableState.Never),
363 public override Control FindControl(string id) {
364 return base.FindControl(id);
368 /// <devdoc>
369 /// </devdoc>
371 EditorBrowsable(EditorBrowsableState.Never),
373 public override void Focus() {
374 throw new NotSupportedException(SR.GetString(SR.NoFocusSupport, this.GetType().Name));
377 [SecurityPermission(SecurityAction.Demand, Unrestricted = true)]
378 protected override IDictionary GetDesignModeState() {
379 IDictionary designModeState = new HybridDictionary();
380 designModeState["OriginalContent"] = ViewState["OriginalContent"];
382 return designModeState;
386 EditorBrowsable(EditorBrowsableState.Never),
388 public override bool HasControls() {
389 return base.HasControls();
392 private void LoadTransformFromSource() {
394 // We're done if we already have a transform
395 if (_transform != null)
396 return;
398 if (String.IsNullOrEmpty(_transformSource) || _transformSource.Trim().Length == 0)
399 return;
401 // First, figure out if it's a physical or virtual path
402 VirtualPath virtualPath;
403 string physicalPath;
404 ResolvePhysicalOrVirtualPath(_transformSource, out virtualPath, out physicalPath);
406 CacheStoreProvider cacheInternal = HttpRuntime.Cache.InternalCache;
407 string key = CacheInternal.PrefixLoadXPath + ((physicalPath != null) ?
408 physicalPath : virtualPath.VirtualPathString);
410 object xform = cacheInternal.Get(key);
412 if (xform == null) {
413 Debug.Trace("XmlControl", "Xsl Transform not found in cache (" + _transformSource + ")");
415 // Get the stream, and open the doc
416 CacheDependency dependency;
417 using (Stream stream = OpenFileAndGetDependency(virtualPath, physicalPath, out dependency)) {
419 // If we don't have a physical path, call MapPath to get one, in order to pass it as
420 // the baseUri to XmlTextReader. In pure VirtualPathProvider scenarios, it won't
421 // help much, but it allows the default case to have relative references (VSWhidbey 545322)
422 if (physicalPath == null)
423 physicalPath = virtualPath.MapPath();
425 // XslCompiledTransform for some reason wants to completely re-create an internal XmlReader
426 // from scratch. In doing so, it does not respect all the settings of XmlTextReader. So we want
427 // to be sure to specifically use XmlReader here so our settings on it will be respected by the
428 // XslCompiledTransform.
429 XmlReader xmlReader = XmlUtils.CreateXmlReader(stream, physicalPath);
430 _transform = XmlUtils.CreateXslTransform(xmlReader);
431 if (_transform == null) {
432 _compiledTransform = XmlUtils.CreateXslCompiledTransform(xmlReader);
436 // Cache it, but only if we got a dependency
437 if (dependency != null) {
438 using (dependency) {
439 cacheInternal.Insert(key, ((_compiledTransform == null) ? (object)_transform : (object)_compiledTransform),
440 new CacheInsertOptions() { Dependencies = dependency });
444 else {
445 Debug.Trace("XmlControl", "XslTransform found in cache (" + _transformSource + ")");
447 _compiledTransform = xform as XslCompiledTransform;
448 if (_compiledTransform == null) {
449 #pragma warning disable 0618 // To avoid deprecation warning
450 _transform = (XslTransform)xform;
451 #pragma warning restore 0618
456 private void LoadXmlDocument() {
458 Debug.Assert(_xpathDocument == null && _document == null && _xpathNavigator == null);
460 if (!String.IsNullOrEmpty(_documentContent)) {
461 _document = XmlUtils.CreateXmlDocumentFromContent(_documentContent);
462 return;
465 if (String.IsNullOrEmpty(_documentSource))
466 return;
468 // Make it absolute and check security
469 string physicalPath = MapPathSecure(_documentSource);
471 CacheStoreProvider cacheInternal = System.Web.HttpRuntime.Cache.InternalCache;
472 string key = CacheInternal.PrefixLoadXml + physicalPath;
474 _document = (XmlDocument) cacheInternal.Get(key);
476 if (_document == null) {
477 Debug.Trace("XmlControl", "XmlDocument not found in cache (" + _documentSource + ")");
479 CacheDependency dependency;
480 using (Stream stream = OpenFileAndGetDependency(null, physicalPath, out dependency)) {
482 _document = new XmlDocument();
483 _document.Load(XmlUtils.CreateXmlReader(stream, physicalPath));
484 cacheInternal.Insert(key, _document, new CacheInsertOptions() { Dependencies = dependency });
487 else {
488 Debug.Trace("XmlControl", "XmlDocument found in cache (" + _documentSource + ")");
492 lock (_document) {
493 // Always return a clone of the cached copy
494 _document = (XmlDocument)_document.CloneNode(true/*deep*/);
498 private void LoadXPathDocument() {
500 Debug.Assert(_xpathDocument == null && _document == null && _xpathNavigator == null);
502 if (!String.IsNullOrEmpty(_documentContent)) {
503 _xpathDocument = XmlUtils.CreateXPathDocumentFromContent(_documentContent);
504 return;
507 if (String.IsNullOrEmpty(_documentSource))
508 return;
510 // First, figure out if it's a physical or virtual path
511 VirtualPath virtualPath;
512 string physicalPath;
513 ResolvePhysicalOrVirtualPath(_documentSource, out virtualPath, out physicalPath);
515 CacheStoreProvider cacheInternal = HttpRuntime.Cache.InternalCache;
516 string key = CacheInternal.PrefixLoadXPath + ((physicalPath != null) ?
517 physicalPath : virtualPath.VirtualPathString);
519 _xpathDocument = (XPathDocument)cacheInternal.Get(key);
520 if (_xpathDocument == null) {
521 Debug.Trace("XmlControl", "XPathDocument not found in cache (" + _documentSource + ")");
523 // Get the stream, and open the doc
524 CacheDependency dependency;
525 using (Stream stream = OpenFileAndGetDependency(virtualPath, physicalPath, out dependency)) {
526 // The same comments as in LoadTransformFromSource() (VSWhidbey 545322, 546662)
527 if (physicalPath == null) {
528 physicalPath = virtualPath.MapPath();
531 _xpathDocument = new XPathDocument(XmlUtils.CreateXmlReader(stream, physicalPath));
534 // Cache it, but only if we got a dependency
535 if (dependency != null) {
536 using (dependency) {
537 cacheInternal.Insert(key, _xpathDocument, new CacheInsertOptions() { Dependencies = dependency });
541 else {
542 Debug.Trace("XmlControl", "XPathDocument found in cache (" + _documentSource + ")");
547 /// <devdoc>
548 /// <para>[To be supplied.]</para>
549 /// </devdoc>
550 [SuppressMessage("Microsoft.Security", "MSEC1204:UseSecureXmlResolver", Justification = "Legacy code that trusts our developer input. Optional safer codepath available via appSettings/aspnet:RestrictXmlControls configuration.")]
551 protected internal override void Render(HtmlTextWriter output)
554 // If we don't already have an XmlDocument or an XPathNavigator, load am XPathDocument (which is faster)
555 if ((_document == null) && (_xpathNavigator == null)) {
556 LoadXPathDocument();
559 LoadTransformFromSource();
561 // Abort if nothing has been loaded
562 if (_document == null && _xpathDocument == null && _xpathNavigator == null) {
563 return;
566 // If we don't have a transform, use the identity transform, which
567 // simply renders the XML.
568 if (_transform == null)
569 _transform = _identityTransform;
571 // Pass a resolver in full trust, to support certain XSL scenarios (ASURT 141427)
572 XmlUrlResolver xr = null;
573 if (HttpRuntime.HasUnmanagedPermission()) {
574 xr = new XmlUrlResolver();
577 IXPathNavigable doc = null;
578 if (_document != null) {
579 doc = _document;
580 } else if (_xpathNavigator != null) {
581 doc = _xpathNavigator;
582 } else {
583 doc = _xpathDocument;
586 if (_compiledTransform != null) {
587 XmlWriter writer = XmlWriter.Create(output);
588 _compiledTransform.Transform(doc, _transformArgumentList, writer, null);
589 } else {
590 _transform.Transform(doc, _transformArgumentList, output, xr);