The Labs \ Source Viewer \ SSCLI \ System.Configuration \ ConfigurationErrorsException

  1. //------------------------------------------------------------------------------
  2. // <copyright file="ConfigurationErrorsException.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. namespace System.Configuration
  16. {
  17.     using System.Configuration.Internal;
  18.     using System;
  19.     using System.Collections;
  20.     using System.Collections.Generic;
  21.     using System.Globalization;
  22.     using System.IO;
  23.     using System.Runtime.Serialization;
  24.     using System.Security;
  25.     using System.Security.Permissions;
  26.     using System.Xml;
  27.     using System.Runtime.Versioning;
  28.    
  29.     [Serializable()]
  30.     public class ConfigurationErrorsException : ConfigurationException
  31.     {
  32.        
  33.         // Constants
  34.         private const string HTTP_PREFIX = "http:";
  35.         private const string SERIALIZATION_PARAM_FILENAME = "firstFilename";
  36.         private const string SERIALIZATION_PARAM_LINE = "firstLine";
  37.         private const string SERIALIZATION_PARAM_ERROR_COUNT = "count";
  38.         private const string SERIALIZATION_PARAM_ERROR_DATA = "_errors";
  39.         private const string SERIALIZATION_PARAM_ERROR_TYPE = "_errors_type";
  40.        
  41.         private string _firstFilename;
  42.         private int _firstLine;
  43.         private ConfigurationException[] _errors;
  44.        
  45.         void Init(string filename, int line)
  46.         {
  47.             HResult = HResults.Configuration;
  48.            
  49.             // BaseConfigurationRecord.cs uses -1 as uninitialized line number.
  50.             if (line == -1) {
  51.                 line = 0;
  52.             }
  53.            
  54.             _firstFilename = filename;
  55.             _firstLine = line;
  56.         }
  57.        
  58.         public ConfigurationErrorsException(string message, Exception inner, string filename, int line) : base(message, inner)
  59.         {
  60.             Init(filename, line);
  61.         }
  62.        
  63.         public ConfigurationErrorsException() : this(null, null, null, 0)
  64.         {
  65.         }
  66.        
  67.         public ConfigurationErrorsException(string message) : this(message, null, null, 0)
  68.         {
  69.         }
  70.        
  71.         public ConfigurationErrorsException(string message, Exception inner) : this(message, inner, null, 0)
  72.         {
  73.         }
  74.        
  75.         public ConfigurationErrorsException(string message, string filename, int line) : this(message, null, filename, line)
  76.         {
  77.         }
  78.        
  79.         public ConfigurationErrorsException(string message, XmlNode node) : this(message, null, GetUnsafeFilename(node), GetLineNumber(node))
  80.         {
  81.         }
  82.        
  83.         public ConfigurationErrorsException(string message, Exception inner, XmlNode node) : this(message, inner, GetUnsafeFilename(node), GetLineNumber(node))
  84.         {
  85.         }
  86.        
  87.         public ConfigurationErrorsException(string message, XmlReader reader) : this(message, null, GetUnsafeFilename(reader), GetLineNumber(reader))
  88.         {
  89.         }
  90.        
  91.         public ConfigurationErrorsException(string message, Exception inner, XmlReader reader) : this(message, inner, GetUnsafeFilename(reader), GetLineNumber(reader))
  92.         {
  93.         }
  94.        
  95.        
  96.         internal ConfigurationErrorsException(string message, IConfigErrorInfo errorInfo) : this(message, null, GetUnsafeConfigErrorInfoFilename(errorInfo), GetConfigErrorInfoLineNumber(errorInfo))
  97.         {
  98.         }
  99.        
  100.         internal ConfigurationErrorsException(string message, Exception inner, IConfigErrorInfo errorInfo) : this(message, inner, GetUnsafeConfigErrorInfoFilename(errorInfo), GetConfigErrorInfoLineNumber(errorInfo))
  101.         {
  102.         }
  103.        
  104.         internal ConfigurationErrorsException(ConfigurationException e) : this(GetBareMessage(e), GetInnerException(e), GetUnsafeFilename(e), GetLineNumber(e))
  105.         {
  106.         }
  107.        
  108.        
  109.         [ResourceExposure(ResourceScope.None)]
  110.         internal ConfigurationErrorsException(ICollection<ConfigurationException> coll) : this(GetFirstException(coll))
  111.         {
  112.            
  113.             if (coll.Count > 1) {
  114.                 _errors = new ConfigurationException[coll.Count];
  115.                 coll.CopyTo(_errors, 0);
  116.             }
  117.         }
  118.        
  119.         internal ConfigurationErrorsException(ArrayList coll) : this((ConfigurationException)(coll.Count > 0 ? coll[0] : null))
  120.         {
  121.            
  122.             if (coll.Count > 1) {
  123.                 _errors = new ConfigurationException[coll.Count];
  124.                 coll.CopyTo(_errors, 0);
  125.                
  126.                 foreach (object error in _errors) {
  127.                     // force an illegal typecast exception if the object is not
  128.                     // of the right type
  129.                     ConfigurationException exception = (ConfigurationException)error;
  130.                 }
  131.             }
  132.         }
  133.        
  134.         private static ConfigurationException GetFirstException(ICollection<ConfigurationException> coll)
  135.         {
  136.             foreach (ConfigurationException e in coll) {
  137.                 return e;
  138.             }
  139.            
  140.             return null;
  141.         }
  142.        
  143.        
  144.         private static string GetBareMessage(ConfigurationException e)
  145.         {
  146.             if (e != null) {
  147.                 return e.BareMessage;
  148.             }
  149.            
  150.             return null;
  151.         }
  152.        
  153.         private static Exception GetInnerException(ConfigurationException e)
  154.         {
  155.             if (e != null) {
  156.                 return e.InnerException;
  157.             }
  158.            
  159.             return null;
  160.         }
  161.        
  162.         //
  163.         // We assert PathDiscovery so that we get the full filename when calling ConfigurationException.Filename
  164.         //
  165.         [FileIOPermission(SecurityAction.Assert, AllFiles = FileIOPermissionAccess.PathDiscovery)]
  166.         private static string GetUnsafeFilename(ConfigurationException e)
  167.         {
  168.             if (e != null) {
  169.                 return e.Filename;
  170.             }
  171.            
  172.             return null;
  173.         }
  174.        
  175.         private static int GetLineNumber(ConfigurationException e)
  176.         {
  177.             if (e != null) {
  178.                 return e.Line;
  179.             }
  180.            
  181.             return 0;
  182.         }
  183.        
  184.        
  185.         // Serialization methods
  186.         protected ConfigurationErrorsException(SerializationInfo info, StreamingContext context) : base(info, context)
  187.         {
  188.            
  189.             string firstFilename;
  190.             int firstLine;
  191.             int count;
  192.             string numPrefix;
  193.             string currentType;
  194.             Type currentExceptionType;
  195.            
  196.             // Retrieve out members
  197.             firstFilename = info.GetString(SERIALIZATION_PARAM_FILENAME);
  198.             firstLine = info.GetInt32(SERIALIZATION_PARAM_LINE);
  199.            
  200.             Init(firstFilename, firstLine);
  201.            
  202.             // Retrieve errors for _errors object
  203.             count = info.GetInt32(SERIALIZATION_PARAM_ERROR_COUNT);
  204.            
  205.             if (count != 0) {
  206.                 _errors = new ConfigurationException[count];
  207.                
  208.                 for (int i = 0; i < count; i++) {
  209.                     numPrefix = i.ToString(CultureInfo.InvariantCulture);
  210.                    
  211.                     currentType = info.GetString(numPrefix + SERIALIZATION_PARAM_ERROR_TYPE);
  212.                     currentExceptionType = Type.GetType(currentType, true);
  213.                    
  214.                     // Only allow our exception types
  215.                     if ((currentExceptionType != typeof(ConfigurationException)) && (currentExceptionType != typeof(ConfigurationErrorsException))) {
  216.                         throw ExceptionUtil.UnexpectedError("ConfigurationErrorsException");
  217.                     }
  218.                    
  219.                     _errors[i] = (ConfigurationException)info.GetValue(numPrefix + SERIALIZATION_PARAM_ERROR_DATA, currentExceptionType);
  220.                 }
  221.             }
  222.         }
  223.        
  224.         [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
  225.         public override void GetObjectData(SerializationInfo info, StreamingContext context)
  226.         {
  227.             int subErrors = 0;
  228.             string numPrefix;
  229.            
  230.             // call base implementation
  231.             base.GetObjectData(info, context);
  232.            
  233.             // Serialize our members
  234.             info.AddValue(SERIALIZATION_PARAM_FILENAME, Filename);
  235.             info.AddValue(SERIALIZATION_PARAM_LINE, Line);
  236.            
  237.             // Serialize rest of errors, along with count
  238.             // (since first error duplicates this error, only worry if
  239.             // there is more than one)
  240.             if ((_errors != null) && (_errors.Length > 1)) {
  241.                 subErrors = _errors.Length;
  242.                
  243.                 for (int i = 0; i < _errors.Length; i++) {
  244.                     numPrefix = i.ToString(CultureInfo.InvariantCulture);
  245.                    
  246.                     info.AddValue(numPrefix + SERIALIZATION_PARAM_ERROR_DATA, _errors[i]);
  247.                     info.AddValue(numPrefix + SERIALIZATION_PARAM_ERROR_TYPE, _errors[i].GetType());
  248.                 }
  249.             }
  250.            
  251.             info.AddValue(SERIALIZATION_PARAM_ERROR_COUNT, subErrors);
  252.         }
  253.        
  254.         // The message includes the file/line number information.
  255.         // To get the message without the extra information, use BareMessage.
  256.         public override string Message {
  257.             get {
  258.                 string file = Filename;
  259.                 if (!string.IsNullOrEmpty(file)) {
  260.                     if (Line != 0) {
  261.                         return BareMessage + " (" + file + " line " + Line.ToString(CultureInfo.CurrentCulture) + ")";
  262.                     }
  263.                     else {
  264.                         return BareMessage + " (" + file + ")";
  265.                     }
  266.                 }
  267.                 else if (Line != 0) {
  268.                     return BareMessage + " (line " + Line.ToString("G", CultureInfo.CurrentCulture) + ")";
  269.                 }
  270.                 else {
  271.                     return BareMessage;
  272.                 }
  273.             }
  274.         }
  275.        
  276.         public override string BareMessage {
  277.             get { return base.BareMessage; }
  278.         }
  279.        
  280.         public override string Filename {
  281.             get { return SafeFilename(_firstFilename); }
  282.         }
  283.        
  284.         public override int Line {
  285.             get { return _firstLine; }
  286.         }
  287.        
  288.         public ICollection Errors {
  289.             get {
  290.                 if (_errors != null) {
  291.                     return _errors;
  292.                 }
  293.                 else {
  294.                     ConfigurationErrorsException e = new ConfigurationErrorsException(BareMessage, base.InnerException, _firstFilename, _firstLine);
  295.                     ConfigurationException[] a = new ConfigurationException[] {e};
  296.                     return a;
  297.                 }
  298.             }
  299.         }
  300.        
  301.         internal ICollection<ConfigurationException> ErrorsGeneric {
  302.             get { return (ICollection<ConfigurationException>)this.Errors; }
  303.         }
  304.        
  305.         //
  306.         // Get file and linenumber from an XML Node in a DOM
  307.         //
  308.         public static int GetLineNumber(XmlNode node)
  309.         {
  310.             return GetConfigErrorInfoLineNumber(node as IConfigErrorInfo);
  311.         }
  312.        
  313.         public static string GetFilename(XmlNode node)
  314.         {
  315.             return SafeFilename(GetUnsafeFilename(node));
  316.         }
  317.        
  318.         private static string GetUnsafeFilename(XmlNode node)
  319.         {
  320.             return GetUnsafeConfigErrorInfoFilename(node as IConfigErrorInfo);
  321.         }
  322.        
  323.         //
  324.         // Get file and linenumber from an XML Reader
  325.         //
  326.         public static int GetLineNumber(XmlReader reader)
  327.         {
  328.             return GetConfigErrorInfoLineNumber(reader as IConfigErrorInfo);
  329.         }
  330.        
  331.         public static string GetFilename(XmlReader reader)
  332.         {
  333.             return SafeFilename(GetUnsafeFilename(reader));
  334.         }
  335.        
  336.         private static string GetUnsafeFilename(XmlReader reader)
  337.         {
  338.             return GetUnsafeConfigErrorInfoFilename(reader as IConfigErrorInfo);
  339.         }
  340.        
  341.         //
  342.         // Get file and linenumber from an IConfigErrorInfo
  343.         //
  344.         private static int GetConfigErrorInfoLineNumber(IConfigErrorInfo errorInfo)
  345.         {
  346.             if (errorInfo != null) {
  347.                 return errorInfo.LineNumber;
  348.             }
  349.             else {
  350.                 return 0;
  351.             }
  352.         }
  353.        
  354.         private static string GetUnsafeConfigErrorInfoFilename(IConfigErrorInfo errorInfo)
  355.         {
  356.             if (errorInfo != null) {
  357.                 return errorInfo.Filename;
  358.             }
  359.             else {
  360.                 return null;
  361.             }
  362.         }
  363.        
  364.         [FileIOPermission(SecurityAction.Assert, AllFiles = FileIOPermissionAccess.PathDiscovery)]
  365.         private static string FullPathWithAssert(string filename)
  366.         {
  367.             string fullPath = null;
  368.            
  369.             try {
  370.                 fullPath = Path.GetFullPath(filename);
  371.             }
  372.             catch {
  373.             }
  374.            
  375.             return fullPath;
  376.         }
  377.        
  378.         //
  379.         // Internal Helper to strip a full path to just filename.ext when caller
  380.         // does not have path discovery to the path (used for sane error handling).
  381.         //
  382.         static internal string SafeFilename(string filename)
  383.         {
  384.             if (string.IsNullOrEmpty(filename)) {
  385.                 return filename;
  386.             }
  387.            
  388.             // configuration file can be an http URL in IE
  389.             if (StringUtil.StartsWithIgnoreCase(filename, HTTP_PREFIX)) {
  390.                 return filename;
  391.             }
  392.            
  393.             //
  394.             // If it is a relative path, return it as is.
  395.             // This could happen if the exception was constructed from the serialization constructor,
  396.             // and the caller did not have PathDiscoveryPermission for the file.
  397.             //
  398.             try {
  399.                 if (!Path.IsPathRooted(filename)) {
  400.                     return filename;
  401.                 }
  402.             }
  403.             catch {
  404.                 return null;
  405.             }
  406.            
  407.             try {
  408.                 // Confirm that it is a full path.
  409.                 // GetFullPath will also Demand PathDiscovery for the resulting path
  410.                 string fullPath = Path.GetFullPath(filename);
  411.             }
  412.             catch (SecurityException) {
  413.                 // Get just the name of the file without the directory part.
  414.                 try {
  415.                     string fullPath = FullPathWithAssert(filename);
  416.                     filename = Path.GetFileName(fullPath);
  417.                 }
  418.                 catch {
  419.                     filename = null;
  420.                 }
  421.             }
  422.             catch {
  423.                 filename = null;
  424.             }
  425.            
  426.             return filename;
  427.         }
  428.        
  429.         //
  430.         // Internal Helper to always strip a full path to just filename.ext.
  431.         //
  432.         static internal string AlwaysSafeFilename(string filename)
  433.         {
  434.             if (string.IsNullOrEmpty(filename)) {
  435.                 return filename;
  436.             }
  437.            
  438.             // configuration file can be an http URL in IE
  439.             if (StringUtil.StartsWithIgnoreCase(filename, HTTP_PREFIX)) {
  440.                 return filename;
  441.             }
  442.            
  443.             //
  444.             // If it is a relative path, return it as is.
  445.             // This could happen if the exception was constructed from the serialization constructor,
  446.             // and the caller did not have PathDiscoveryPermission for the file.
  447.             //
  448.             try {
  449.                 if (!Path.IsPathRooted(filename)) {
  450.                     return filename;
  451.                 }
  452.             }
  453.             catch {
  454.                 return null;
  455.             }
  456.            
  457.             // Get just the name of the file without the directory part.
  458.             try {
  459.                 string fullPath = FullPathWithAssert(filename);
  460.                 filename = Path.GetFileName(fullPath);
  461.             }
  462.             catch {
  463.                 filename = null;
  464.             }
  465.            
  466.             return filename;
  467.         }
  468.        
  469.     }
  470. }

Developer Fusion