X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FSystem%2FSystem.Configuration%2FConfigurationSettings.cs;h=199d83fe7bb383121660fd6e0dc5199d262e4321;hb=75883dc733e1e318c83ff2eab3c408d2926301f3;hp=ae1aa1584f8e2f5e42bb998141f8e43b1a95bcce;hpb=f442c04839034d8dd9852ee10eb71fe9b2db0c25;p=mono.git diff --git a/mcs/class/System/System.Configuration/ConfigurationSettings.cs b/mcs/class/System/System.Configuration/ConfigurationSettings.cs index ae1aa1584f8..199d83fe7bb 100644 --- a/mcs/class/System/System.Configuration/ConfigurationSettings.cs +++ b/mcs/class/System/System.Configuration/ConfigurationSettings.cs @@ -32,29 +32,62 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // +#if CONFIGURATION_DEP && !TARGET_JVM +extern alias PrebuiltSystem; +using NameValueCollection = PrebuiltSystem.System.Collections.Specialized.NameValueCollection; +#endif + using System; using System.Collections; using System.Collections.Specialized; using System.IO; using System.Runtime.CompilerServices; +using System.Security.Permissions; #if (XML_DEP) using System.Xml; using System.Xml.XPath; #endif +#if TARGET_JVM +using vmw.common; +using vmw.@internal.io; +#endif namespace System.Configuration { public sealed class ConfigurationSettings { - static IConfigurationSystem config = DefaultConfig.GetInstance (); +#if !TARGET_JVM + static IConfigurationSystem config = DefaultConfig.GetInstance (); +#else + static IConfigurationSystem config { + get { + IConfigurationSystem conf = (IConfigurationSystem) AppDomain.CurrentDomain.GetData ("ConfigurationSettings.Config"); + if (conf == null) { + conf = DefaultConfig.GetInstance (); + AppDomain.CurrentDomain.SetData ("ConfigurationSettings.Config", conf); + } + return conf; + } + set { + AppDomain.CurrentDomain.SetData ("ConfigurationSettings.Config", value); + } + } +#endif static object lockobj = new object (); private ConfigurationSettings () { } +#if NET_2_0 + [Obsolete ("This method is obsolete, it has been replaced by System.Configuration!System.Configuration.ConfigurationManager.GetSection")] +#endif public static object GetConfig (string sectionName) { +#if NET_2_0 && CONFIGURATION_DEP + return ConfigurationManager.GetSection (sectionName); +#else return config.GetConfig (sectionName); +#endif } #if NET_2_0 @@ -63,25 +96,19 @@ namespace System.Configuration public static NameValueCollection AppSettings { get { -#if NET_2_0 - /* XXX figure out the cyclic - * dependency foo between System and - * System.Configuration so this will - * work */ -// return ConfigurationManager.AppSettings; - return new NameValueCollection (); +#if NET_2_0 && CONFIGURATION_DEP + object appSettings = ConfigurationManager.GetSection ("appSettings"); #else object appSettings = GetConfig ("appSettings"); +#endif if (appSettings == null) appSettings = new NameValueCollection (); - return (NameValueCollection) appSettings; -#endif } } - // Invoked from System.Web - static IConfigurationSystem ChangeConfigurationSystem (IConfigurationSystem newSystem) + // Invoked from System.Web, disable warning + internal static IConfigurationSystem ChangeConfigurationSystem (IConfigurationSystem newSystem) { if (newSystem == null) throw new ArgumentNullException ("newSystem"); @@ -100,7 +127,23 @@ namespace System.Configuration // class DefaultConfig : IConfigurationSystem { - static readonly DefaultConfig instance = new DefaultConfig (); +#if !TARGET_JVM + static readonly DefaultConfig instance = new DefaultConfig (); +#else + static DefaultConfig instance { + get { + DefaultConfig conf = (DefaultConfig) AppDomain.CurrentDomain.GetData ("DefaultConfig.instance"); + if (conf == null) { + conf = new DefaultConfig (); + AppDomain.CurrentDomain.SetData ("DefaultConfig.instance", conf); + } + return conf; + } + set { + AppDomain.CurrentDomain.SetData ("DefaultConfig.instance", value); + } + } +#endif ConfigurationData config; private DefaultConfig () @@ -128,9 +171,13 @@ namespace System.Configuration return; ConfigurationData data = new ConfigurationData (); - if (!data.Load (GetMachineConfigPath ())) - throw new ConfigurationException ("Cannot find " + GetMachineConfigPath ()); + if (data.LoadString (GetBundledMachineConfig ())) { + // do nothing + } else { + if (!data.Load (GetMachineConfigPath ())) + throw new ConfigurationException ("Cannot find " + GetMachineConfigPath ()); + } string appfile = GetAppConfigPath (); if (appfile == null) { config = data; @@ -144,15 +191,29 @@ namespace System.Configuration config = data; } } - +#if TARGET_JVM + internal static string GetBundledMachineConfig () + { + return null; + } + internal static string GetMachineConfigPath () + { + return System.Runtime.InteropServices.RuntimeEnvironment.SystemConfigurationFile; + } +#else + [MethodImplAttribute(MethodImplOptions.InternalCall)] + extern private static string get_bundled_machine_config (); + internal static string GetBundledMachineConfig () + { + return get_bundled_machine_config (); + } [MethodImplAttribute(MethodImplOptions.InternalCall)] extern private static string get_machine_config_path (); - internal static string GetMachineConfigPath () { return get_machine_config_path (); } - +#endif private static string GetAppConfigPath () { AppDomainSetup currentInfo = AppDomain.CurrentDomain.SetupInformation; @@ -172,7 +233,7 @@ namespace System.Configuration MachineOnly, MachineToApplication } - + class SectionData { public readonly string SectionName; @@ -180,38 +241,42 @@ namespace System.Configuration public readonly bool AllowLocation; public readonly AllowDefinition AllowDefinition; public string FileName; + public readonly bool RequirePermission; public SectionData (string sectionName, string typeName, - bool allowLocation, AllowDefinition allowDefinition) + bool allowLocation, AllowDefinition allowDefinition, bool requirePermission) { SectionName = sectionName; TypeName = typeName; AllowLocation = allowLocation; AllowDefinition = allowDefinition; + RequirePermission = requirePermission; } } - + class ConfigurationData { ConfigurationData parent; Hashtable factories; + static object removedMark = new object (); + static object emptyMark = new object (); +#if (XML_DEP) Hashtable pending; string fileName; - static object removedMark = new object (); static object groupMark = new object (); - static object emptyMark = new object (); +#endif Hashtable cache; - Hashtable FileCache { - get { + Hashtable FileCache { + get { if (cache != null) return cache; cache = new Hashtable (); - return cache; - } - } + return cache; + } + } public ConfigurationData () : this (null) { @@ -223,19 +288,39 @@ namespace System.Configuration factories = new Hashtable (); } + // SECURITY-FIXME: limit this with an imperative assert for reading the specific file + [FileIOPermission (SecurityAction.Assert, Unrestricted = true)] public bool Load (string fileName) { +#if (XML_DEP) this.fileName = fileName; - if (fileName == null || !File.Exists (fileName)) + if (fileName == null +#if !TARGET_JVM + || !File.Exists (fileName) +#endif +) return false; -#if (XML_DEP) + XmlTextReader reader = null; try { +#if !TARGET_JVM FileStream fs = new FileStream (fileName, FileMode.Open, FileAccess.Read); +#else + Stream fs = (Stream) vmw.common.IOUtils.getStream (fileName); + + //patch for machine.config + if (fs == null && fileName.EndsWith ("machine.config")) { + fs = (Stream) IOUtils.getStreamForGHConfigs (fileName); + } + + if (fs == null) { + return false; + } +#endif reader = new XmlTextReader (fs); - InitRead (reader); - ReadConfigFile (reader); + if (InitRead (reader)) + ReadConfigFile (reader); } catch (ConfigurationException) { throw; } catch (Exception e) { @@ -247,7 +332,31 @@ namespace System.Configuration #endif return true; } + + public bool LoadString (string data) + { + if (data == null) + return false; +#if (XML_DEP) + XmlTextReader reader = null; + try { + TextReader tr = new StringReader (data); + reader = new XmlTextReader (tr); + if (InitRead (reader)) + ReadConfigFile (reader); + } catch (ConfigurationException) { + throw; + } catch (Exception e) { + throw new ConfigurationException ("Error reading " + fileName, e); + } finally { + if (reader != null) + reader.Close(); + } +#endif + return true; + } + object GetHandler (string sectionName) { lock (factories) { @@ -326,7 +435,7 @@ namespace System.Configuration return GetInnerDoc (doc, 0, sectionPath); } - + object GetConfigInternal (string sectionName) { object handler = GetHandler (sectionName); @@ -357,11 +466,11 @@ namespace System.Configuration config = this.FileCache [sectionName]; } - if (config == emptyMark) - return null; + if (config == emptyMark) + return null; - if (config != null) - return config; + if (config != null) + return config; lock (this) { config = GetConfigInternal (sectionName); @@ -369,7 +478,7 @@ namespace System.Configuration } return config; - } + } private object LookForFactory (string key) { @@ -383,7 +492,7 @@ namespace System.Configuration return null; } #if (XML_DEP) - private void InitRead (XmlTextReader reader) + private bool InitRead (XmlTextReader reader) { reader.MoveToContent (); if (reader.NodeType != XmlNodeType.Element || reader.Name != "configuration") @@ -391,10 +500,16 @@ namespace System.Configuration if (reader.HasAttributes) ThrowException ("Unrecognized attribute in root element", reader); - - MoveToNextElement (reader); + if (reader.IsEmptyElement) { + reader.Skip (); + return false; + } + reader.Read (); + reader.MoveToContent (); + return reader.NodeType != XmlNodeType.EndElement; } + // FIXME: this approach is not always safe and likely to cause bugs. private void MoveToNextElement (XmlTextReader reader) { while (reader.Read ()) { @@ -416,6 +531,8 @@ namespace System.Configuration string nameValue = null; string typeValue = null; string allowLoc = null, allowDef = null; + bool requirePermission = false; + string requirePer = null; bool allowLocation = true; AllowDefinition allowDefinition = AllowDefinition.Everywhere; @@ -436,6 +553,16 @@ namespace System.Configuration continue; } + if (attName == "requirePermission") { + if (requirePer != null) + ThrowException ("Duplicated requirePermission attribute.", reader); + requirePer = reader.Value; + requirePermission = (requirePer == "true"); + if (!requirePermission && requirePer != "false") + ThrowException ("Invalid attribute value", reader); + continue; + } + if (attName == "allowDefinition") { if (allowDef != null) ThrowException ("Duplicated allowDefinition attribute.", reader); @@ -480,11 +607,22 @@ namespace System.Configuration object o = LookForFactory (nameValue); if (o != null && o != removedMark) ThrowException ("Already have a factory for " + nameValue, reader); - SectionData section = new SectionData (nameValue, typeValue, allowLocation, allowDefinition); + SectionData section = new SectionData (nameValue, typeValue, allowLocation, + allowDefinition, requirePermission); section.FileName = fileName; factories [nameValue] = section; - MoveToNextElement (reader); + if (reader.IsEmptyElement) + reader.Skip (); + else { + reader.Read (); + reader.MoveToContent (); + if (reader.NodeType != XmlNodeType.EndElement) + // sub-section inside a section + ReadSections (reader, nameValue); + reader.ReadEndElement (); + } + reader.MoveToContent (); } private void ReadRemoveSection (XmlTextReader reader, string sectionName) @@ -514,16 +652,26 @@ namespace System.Configuration if (!reader.MoveToNextAttribute ()) ThrowException ("sectionGroup must have a 'name' attribute.", reader); - if (reader.Name != "name") - ThrowException ("Unrecognized attribute.", reader); - - if (reader.MoveToNextAttribute ()) - ThrowException ("Unrecognized attribute.", reader); + string value = null; + do { + if (reader.Name == "name") { + if (value != null) + ThrowException ("Duplicate 'name' attribute.", reader); + value = reader.Value; + } + else +#if NET_2_0 + if (reader.Name != "type") +#endif + ThrowException ("Unrecognized attribute.", reader); + } while (reader.MoveToNextAttribute ()); - string value = reader.Value; + if (value == null) + ThrowException ("No 'name' attribute.", reader); + if (value == "location") ThrowException ("location is a reserved section name", reader); - + if (configSection != null) value = configSection + '/' + value; @@ -532,14 +680,28 @@ namespace System.Configuration ThrowException ("Already have a factory for " + value, reader); factories [value] = groupMark; - MoveToNextElement (reader); - ReadSections (reader, value); + + if (reader.IsEmptyElement) { + reader.Skip (); + reader.MoveToContent (); + } else { + reader.Read (); + reader.MoveToContent (); + if (reader.NodeType != XmlNodeType.EndElement) + ReadSections (reader, value); + reader.ReadEndElement (); + reader.MoveToContent (); + } } + // It stops XmlReader consumption at where it found + // surrounding EndElement i.e. EndElement is not consumed here private void ReadSections (XmlTextReader reader, string configSection) { int depth = reader.Depth; - while (reader.Depth == depth) { + for (reader.MoveToContent (); + reader.Depth == depth; + reader.MoveToContent ()) { string name = reader.Name; if (name == "section") { ReadSection (reader, configSection); @@ -580,16 +742,23 @@ namespace System.Configuration private void ReadConfigFile (XmlTextReader reader) { - int depth = reader.Depth; - while (!reader.EOF && reader.Depth == depth) { + //int depth = reader.Depth; + for (reader.MoveToContent (); + !reader.EOF && reader.NodeType != XmlNodeType.EndElement; + reader.MoveToContent ()) { string name = reader.Name; if (name == "configSections") { if (reader.HasAttributes) ThrowException ("Unrecognized attribute in .", reader); - - MoveToNextElement (reader); - if (reader.Depth > depth) - ReadSections (reader, null); + if (reader.IsEmptyElement) + reader.Skip (); + else { + reader.Read (); + reader.MoveToContent (); + if (reader.NodeType != XmlNodeType.EndElement) + ReadSections (reader, null); + reader.ReadEndElement (); + } } else if (name != null && name != "") { StorePending (name, reader); MoveToNextElement (reader); @@ -598,7 +767,7 @@ namespace System.Configuration } } } - + private void ThrowException (string text, XmlTextReader reader) { throw new ConfigurationException (text, fileName, reader.LineNumber);