1 //------------------------------------------------------------------------------
2 // <copyright file="HandlerBase.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //------------------------------------------------------------------------------
6 
7 /*
8  * HandlerBase contains static helper functions for consistent XML parsing
9  * behavior and error messages.
10  *
11  * Copyright (c) 1998 Microsoft Corporation
12  */
13 
14 namespace System.Web.Configuration {
15 
16     using System.Collections;
17     using System.Collections.Specialized;
18     using System.Configuration;
19     using System.Globalization;
20     using System.Text;
21     using System.Web.Hosting;
22     using System.Web.Util;
23     using System.Xml;
24     using System.Web.Compilation;
25 
26     static internal class HandlerBase {
27 
28 
29         //
30         // XML Attribute Helpers
31         //
32 
GetAndRemoveAttribute(XmlNode node, string attrib, bool fRequired)33         private static XmlNode GetAndRemoveAttribute(XmlNode node, string attrib, bool fRequired) {
34             XmlNode a = node.Attributes.RemoveNamedItem(attrib);
35 
36             // If the attribute is required and was not present, throw
37             if (fRequired && a == null) {
38                 throw new ConfigurationErrorsException(
39                     SR.GetString(SR.Missing_required_attribute, attrib, node.Name),
40                     node);
41             }
42 
43             return a;
44         }
45 
GetAndRemoveStringAttributeInternal(XmlNode node, string attrib, bool fRequired, ref string val)46         private static XmlNode GetAndRemoveStringAttributeInternal(XmlNode node, string attrib, bool fRequired, ref string val) {
47             XmlNode a = GetAndRemoveAttribute(node, attrib, fRequired);
48             if (a != null) {
49                 val = a.Value;
50             }
51 
52             return a;
53         }
54 
GetAndRemoveStringAttribute(XmlNode node, string attrib, ref string val)55         internal static XmlNode GetAndRemoveStringAttribute(XmlNode node, string attrib, ref string val) {
56             return GetAndRemoveStringAttributeInternal(node, attrib, false /*fRequired*/, ref val);
57         }
58 
GetAndRemoveRequiredStringAttribute(XmlNode node, string attrib, ref string val)59         internal static XmlNode GetAndRemoveRequiredStringAttribute(XmlNode node, string attrib, ref string val) {
60             return GetAndRemoveStringAttributeInternal(node, attrib, true /*fRequired*/, ref val);
61         }
62 
GetAndRemoveNonEmptyStringAttribute(XmlNode node, string attrib, ref string val)63         internal static XmlNode GetAndRemoveNonEmptyStringAttribute(XmlNode node, string attrib, ref string val) {
64             return GetAndRemoveNonEmptyStringAttributeInternal(node, attrib, false /*fRequired*/, ref val);
65         }
66 
GetAndRemoveRequiredNonEmptyStringAttribute(XmlNode node, string attrib, ref string val)67         internal static XmlNode GetAndRemoveRequiredNonEmptyStringAttribute(XmlNode node, string attrib, ref string val) {
68             return GetAndRemoveNonEmptyStringAttributeInternal(node, attrib, true /*fRequired*/, ref val);
69         }
70 
GetAndRemoveNonEmptyStringAttributeInternal(XmlNode node, string attrib, bool fRequired, ref string val)71         private static XmlNode GetAndRemoveNonEmptyStringAttributeInternal(XmlNode node, string attrib, bool fRequired, ref string val) {
72             XmlNode a = GetAndRemoveStringAttributeInternal(node, attrib, fRequired, ref val);
73             if (a != null && val.Length == 0) {
74                 throw new ConfigurationErrorsException(
75                     SR.GetString(SR.Empty_attribute, attrib),
76                     a);
77             }
78 
79             return a;
80         }
81 
82         // input.Xml cursor must be at a true/false XML attribute
GetAndRemoveBooleanAttributeInternal(XmlNode node, string attrib, bool fRequired, ref bool val)83         private static XmlNode GetAndRemoveBooleanAttributeInternal(XmlNode node, string attrib, bool fRequired, ref bool val) {
84             XmlNode a = GetAndRemoveAttribute(node, attrib, fRequired);
85             if (a != null) {
86                 if (a.Value == "true") {
87                     val = true;
88                 }
89                 else if (a.Value == "false") {
90                     val = false;
91                 }
92                 else {
93                     throw new ConfigurationErrorsException(
94                                     SR.GetString(SR.Invalid_boolean_attribute, a.Name),
95                                     a);
96                 }
97             }
98 
99             return a;
100         }
101 
GetAndRemoveBooleanAttribute(XmlNode node, string attrib, ref bool val)102         internal static XmlNode GetAndRemoveBooleanAttribute(XmlNode node, string attrib, ref bool val) {
103             return GetAndRemoveBooleanAttributeInternal(node, attrib, false /*fRequired*/, ref val);
104         }
105 
GetAndRemoveIntegerAttributeInternal(XmlNode node, string attrib, bool fRequired, ref int val)106         private static XmlNode GetAndRemoveIntegerAttributeInternal(XmlNode node, string attrib, bool fRequired, ref int val) {
107             XmlNode a = GetAndRemoveAttribute(node, attrib, fRequired);
108             if (a != null) {
109                 if (a.Value.Trim() != a.Value) {
110                     throw new ConfigurationErrorsException(
111                         SR.GetString(SR.Invalid_integer_attribute, a.Name),
112                         a);
113                 }
114 
115                 try {
116                     val = int.Parse(a.Value, CultureInfo.InvariantCulture);
117                 }
118                 catch (Exception e) {
119                     throw new ConfigurationErrorsException(
120                         SR.GetString(SR.Invalid_integer_attribute, a.Name),
121                         e, a);
122                 }
123             }
124 
125             return a;
126         }
127 
GetAndRemovePositiveAttributeInternal(XmlNode node, string attrib, bool fRequired, ref int val)128         private static XmlNode GetAndRemovePositiveAttributeInternal(XmlNode node, string attrib, bool fRequired, ref int val) {
129             XmlNode a = GetAndRemoveIntegerAttributeInternal(node, attrib, fRequired, ref val);
130 
131             if (a != null && val <= 0) {
132                 throw new ConfigurationErrorsException(
133                     SR.GetString(SR.Invalid_positive_integer_attribute, attrib),
134                     a);
135             }
136 
137             return a;
138         }
139 
140 
GetAndRemovePositiveIntegerAttribute(XmlNode node, string attrib, ref int val)141         internal static XmlNode GetAndRemovePositiveIntegerAttribute(XmlNode node, string attrib, ref int val) {
142             return GetAndRemovePositiveAttributeInternal(node, attrib, false /*fRequired*/, ref val);
143         }
144 
145 
GetAndRemoveTypeAttributeInternal(XmlNode node, string attrib, bool fRequired, ref Type val)146         private static XmlNode GetAndRemoveTypeAttributeInternal(XmlNode node, string attrib, bool fRequired, ref Type val) {
147             XmlNode a = GetAndRemoveAttribute(node, attrib, fRequired);
148 
149             if (a != null) {
150                 val = ConfigUtil.GetType(a.Value, a);
151             }
152 
153             return a;
154         }
155 
GetAndRemoveTypeAttribute(XmlNode node, string attrib, ref Type val)156         internal static XmlNode GetAndRemoveTypeAttribute(XmlNode node, string attrib, ref Type val) {
157             return GetAndRemoveTypeAttributeInternal(node, attrib, false /*fRequired*/, ref val);
158         }
159 
CheckForbiddenAttribute(XmlNode node, string attrib)160         internal static void CheckForbiddenAttribute(XmlNode node, string attrib) {
161             XmlAttribute attr = node.Attributes[attrib];
162             if (attr != null) {
163                 throw new ConfigurationErrorsException(
164                                 SR.GetString(SR.Config_base_unrecognized_attribute, attrib),
165                                 attr);
166             }
167         }
168 
CheckForUnrecognizedAttributes(XmlNode node)169         internal static void CheckForUnrecognizedAttributes(XmlNode node) {
170             if (node.Attributes.Count != 0) {
171                 throw new ConfigurationErrorsException(
172                                 SR.GetString(SR.Config_base_unrecognized_attribute, node.Attributes[0].Name),
173                                 node.Attributes[0]);
174             }
175         }
176 
177 
178         //
179         // Obsolete XML Attribute Helpers
180         //
181 
182         // if attribute not found return null
RemoveAttribute(XmlNode node, string name)183         internal static string RemoveAttribute(XmlNode node, string name) {
184 
185             XmlNode attribute = node.Attributes.RemoveNamedItem(name);
186 
187             if (attribute != null) {
188                 return attribute.Value;
189             }
190 
191             return null;
192         }
193 
194         // if attr not found throw standard message - "attribute x required"
RemoveRequiredAttribute(XmlNode node, string name)195         internal static string RemoveRequiredAttribute(XmlNode node, string name) {
196             return RemoveRequiredAttribute(node, name, false);
197         }
198 
RemoveRequiredAttribute(XmlNode node, string name, bool allowEmpty)199         internal static string RemoveRequiredAttribute(XmlNode node, string name, bool allowEmpty) {
200             XmlNode attribute = node.Attributes.RemoveNamedItem(name);
201 
202             if (attribute == null) {
203                 throw new ConfigurationErrorsException(
204                                 SR.GetString(SR.Config_base_required_attribute_missing, name),
205                                 node);
206             }
207 
208             if (attribute.Value.Length == 0 && !allowEmpty) {
209                 throw new ConfigurationErrorsException(
210                                 SR.GetString(SR.Config_base_required_attribute_empty, name),
211                                 node);
212             }
213 
214             return attribute.Value;
215         }
216 
217 
218 
219         //
220         // XML Element Helpers
221         //
222 
223 
CheckForNonCommentChildNodes(XmlNode node)224         internal static void CheckForNonCommentChildNodes(XmlNode node) {
225             foreach (XmlNode childNode in node.ChildNodes) {
226                 if (childNode.NodeType != XmlNodeType.Comment) {
227                     throw new ConfigurationErrorsException(
228                                     SR.GetString(SR.Config_base_no_child_nodes),
229                                     childNode);
230                 }
231             }
232         }
233 
ThrowUnrecognizedElement(XmlNode node)234         internal static void ThrowUnrecognizedElement(XmlNode node) {
235             throw new ConfigurationErrorsException(
236                             SR.GetString(SR.Config_base_unrecognized_element),
237                             node);
238         }
239 
240 
CheckAssignableType(XmlNode node, Type baseType, Type type)241         internal static void CheckAssignableType(XmlNode node, Type baseType, Type type) {
242             if (!baseType.IsAssignableFrom(type)) {
243                 throw new ConfigurationErrorsException(
244                                 SR.GetString(SR.Type_doesnt_inherit_from_type, type.FullName, baseType.FullName),
245                                 node);
246             }
247         }
248 
CheckAssignableType(string filename, int lineNumber, Type baseType, Type type)249         internal static void CheckAssignableType(string filename, int lineNumber, Type baseType, Type type) {
250             if (!baseType.IsAssignableFrom(type)) {
251                 throw new ConfigurationErrorsException(
252                                 SR.GetString(SR.Type_doesnt_inherit_from_type, type.FullName, baseType.FullName),
253                                 filename, lineNumber);
254             }
255         }
256 
257         // Section handlers can run in client mode through:
258         //      ConfigurationManager.GetSection("sectionName")
259         // See ASURT 123738
IsServerConfiguration(object context)260         internal static bool IsServerConfiguration(object context) {
261             return context is HttpConfigurationContext;
262         }
263 
CheckAndReadRegistryValue(ref string value, bool throwIfError)264         internal static bool CheckAndReadRegistryValue(ref string value, bool throwIfError) {
265             if (value == null) {
266                 return true;
267             }
268 
269             if (!StringUtil.StringStartsWithIgnoreCase(value, "registry:")) {
270                 // Not a registry value.  It's not an error.
271                 return true;
272             }
273 
274             const int size = 1024;
275             StringBuilder str = new StringBuilder(size);
276             int iRet = UnsafeNativeMethods.GetCredentialFromRegistry(value, str, size);
277             if (iRet == 0) {
278                 value = str.ToString();
279                 return true;
280             }
281             else {
282                 if (throwIfError) {
283                     throw new ConfigurationErrorsException(
284                             SR.GetString(SR.Invalid_registry_config));
285                 }
286                 else {
287                     return false;
288                 }
289             }
290         }
291 
CheckAndReadConnectionString(ref string connectionString, bool throwIfError)292         internal static bool CheckAndReadConnectionString(ref string connectionString, bool throwIfError) {
293             ConnectionStringSettings connObj = RuntimeConfig.GetConfig().ConnectionStrings.ConnectionStrings[connectionString];
294             if (connObj != null && connObj.ConnectionString != null && connObj.ConnectionString.Length > 0)
295                 connectionString = connObj.ConnectionString;
296 
297             return CheckAndReadRegistryValue(ref connectionString, throwIfError);
298         }
299     }
300 }
301