File: OverrideMode.cs

package info (click to toggle)
mono 6.12.0.199%2Bdfsg-6
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 1,296,836 kB
  • sloc: cs: 11,181,803; xml: 2,850,076; ansic: 699,709; cpp: 123,344; perl: 59,361; javascript: 30,841; asm: 21,853; makefile: 20,405; sh: 15,009; python: 4,839; pascal: 925; sql: 859; sed: 16; php: 1
file content (375 lines) | stat: -rw-r--r-- 17,058 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
//------------------------------------------------------------------------------
// <copyright file="ConfigDefinitionUpdates.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//------------------------------------------------------------------------------

namespace System.Configuration {
    using System.Configuration.Internal;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Configuration;
    using System.Globalization;
    using System.IO;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using System.Security.Permissions;
    using System.Security;
    using System.Text;
    using System.Xml;


    // This is the public type of the override mode enum visible to the API users
    // The override mode is an attribute of a <location> tag and controls if the sections inside this tag
    // can be defined in child web.config files
    public enum OverrideMode {
        // Default ( aka Indiferent ) - When specified on a location tag means the location tag will not alter
        // the locking mode ( locked or unlocked ). Rather, the locking mode should be picked
        // from the <location> tag with the closest parent path in the current file, or the parent file if no such location in the current one,
        // or the default for the specific section ( section.OverrideModeDefault )
        Inherit     = 0,
        // Allow overriding in child config files. I.e. unlock the settings for overridiing
        Allow       = 1,
        // Deny overriding of the settings defined in the <location> tag. It is an error for the sections in the <location> tag
        // to appear in a child config file. It is not an error for them to appear in another <lcoation> tag in the current file
        Deny        = 2,
    }

    

    // This is a class that abstracts the usage of the override mode setting
    internal struct OverrideModeSetting {

        private const byte  ApiDefinedLegacy    = 0x10;    // allowOverride was set thourhg the API  
        private const byte  ApiDefinedNewMode   = 0x20;    // overrideMode was set thourhg the API  
        private const byte  ApiDefinedAny       = ApiDefinedLegacy | ApiDefinedNewMode;    // allowOverride or overrideMode was set through the API  
        
        private const byte  XmlDefinedLegacy    = 0x40;    // allowOverride was defined in the XML
        private const byte  XmlDefinedNewMode   = 0x80;    // overrideMode was defined in the XML
        private const byte  XmlDefinedAny       = XmlDefinedLegacy | XmlDefinedNewMode;    // overrideMode or allowOverride was defined in the XML
        
        private const byte  ModeMask            = 0x0f;    // logical AND this with the current value to get the mode part only       


        private byte                _mode;


        internal static OverrideModeSetting  SectionDefault;
        internal static OverrideModeSetting  LocationDefault;

        static OverrideModeSetting() {
            
            SectionDefault = new OverrideModeSetting();
            // Default for section is ALLOW ( to be consistent with Whidbey )
            SectionDefault._mode = (byte)OverrideMode.Allow;


            LocationDefault = new OverrideModeSetting();
            // Default for location tags is INHERIT. Note that we do not make the value as existant in the XML or specified by the API
            LocationDefault._mode = (byte)OverrideMode.Inherit;
        }

        static internal OverrideModeSetting CreateFromXmlReadValue(bool allowOverride) {
            // Create a mode from the old "allowOverride" attribute in the xml

            // The conversion is true -> OverrideMode.Inherit
            // The conversion is false -> OverrideMode.Deny
            // This is consistent with Whidbey where true means true unless there is a false somewhere above
            OverrideModeSetting result = new OverrideModeSetting();

            result.SetMode(allowOverride ? OverrideMode.Inherit : OverrideMode.Deny);
            result._mode |= XmlDefinedLegacy;

            return result;
        }

        static internal OverrideModeSetting CreateFromXmlReadValue(OverrideMode mode) {
            OverrideModeSetting result = new OverrideModeSetting();
            
            result.SetMode(mode);        
            result._mode |= XmlDefinedNewMode;

            return result;
        }

         internal static OverrideMode ParseOverrideModeXmlValue(string value, XmlUtil xmlUtil) {
            // 'value' is the string representation of OverrideMode enum
            // Try to parse the string to the enum and generate errors if not possible

            switch (value) {
                case BaseConfigurationRecord.KEYWORD_OVERRIDEMODE_INHERIT:
                    return OverrideMode.Inherit;

                case BaseConfigurationRecord.KEYWORD_OVERRIDEMODE_ALLOW:
                    return OverrideMode.Allow;

                case BaseConfigurationRecord.KEYWORD_OVERRIDEMODE_DENY:
                    return OverrideMode.Deny;

                default:
                    throw new ConfigurationErrorsException(
                            SR.GetString(SR.Config_section_override_mode_attribute_invalid), 
                            xmlUtil);
            }
        }

        internal static bool CanUseSameLocationTag(OverrideModeSetting x, OverrideModeSetting y) {
            // This function tells if the two OverrideModeSettings are compatible enough to be used in only one location tag
            // or each of them should go to a separate one

            // The rules here are ( in order of importance )
            // 1. The effective mode is the same ( we will use only the new OverrideMode to compare )
            // 2. When the mode was changed( i.e. API change ) - both must be changed the same way ( i.e. using either allowOverride or OverrideMode )
            // 3. When mode was not changed the XML - they must've been the same in the xml ( i.e. allowOverride specified on both, or overrideMode or neither of them )

            bool result = false;

            result = (x.OverrideMode == y.OverrideMode);

            if (result == true) {
                
                result = false;
                
                // Check for an API change for each setting first
                // If one mode was set through the API - the other mode has to be set in the same way through the API or has to be using the same type in the xml

                // Handle case where "x" was API modified
                if ((x._mode & ApiDefinedAny) != 0) {

                    result = IsMatchingApiChangedLocationTag(x, y);
                }
                // Handle case where "y" was API modified
                else if ((y._mode & ApiDefinedAny) != 0) {
                    
                    result = IsMatchingApiChangedLocationTag(y, x);
                }
                // Handle case where neither "x" nor "y" was API modified
                else {

                    // If one of the settings was XML defined - they are a match only if both were XML defined in the same way
                    if (    ((x._mode & XmlDefinedAny) != 0) || 
                            ((y._mode & XmlDefinedAny) != 0)) {

                        result = (x._mode & XmlDefinedAny) == (y._mode & XmlDefinedAny);
                    }
                    // Neither "x" nor "y" was XML defined - they are a match since they can both go 
                    // to a default <location> with no explicit mode setting written out
                    else {
                        result = true;
                    }
                }
            }

            return result;
        }

        private static bool IsMatchingApiChangedLocationTag(OverrideModeSetting x, OverrideModeSetting y) {
            // x must be a changed through the API setting
            // Returns true if x and y can share the same location tag

            Debug.Assert((x._mode & ApiDefinedAny) != 0);

            bool result = false;

            // If "y" was modified through the API as well - the modified setting must be the same ( i.e. allowOvverride or overrideMode must be modified in both settings )
            if ((y._mode & ApiDefinedAny) != 0) {
                
                result = (x._mode & ApiDefinedAny) == (y._mode & ApiDefinedAny);
            }
            // "y" was not API modified  - they are still a match if "y" was a XML setting from the same mode
            else if ((y._mode & XmlDefinedAny) != 0) {
                
                result = (  (((x._mode & ApiDefinedLegacy) != 0) && ((y._mode & XmlDefinedLegacy) != 0)) || // "x" was API changed in Legacy and "y" was XML defined in Legacy
                            (((x._mode & ApiDefinedNewMode) != 0) && ((y._mode & XmlDefinedNewMode) != 0)));         // "x" was API changed in New and "y" was XML defined in New
                            
            }
            // "y" was not API or XML modified - since "x" was API modified - they are not a match ( i.e. "y" should go to an <location> with no explicit mode written out )
            else {
            }                    

            return result;
        }

        internal bool IsDefaultForSection {
            get {
                // Returns true if the current value of the overrideMode setting is the default one on a section declaration

                // The current default value for a section's overrideMode ( i.e. overrideModeDefault ) is Allow ( see CreateDefaultForSection )
                // It would've been nice not to repeat that rule here but since OverrideMode.Inherited means the same in this specific context we have to
                // I.e. the default for a section is both Allow and Inherited. In this case they mean the same
                
                OverrideMode mode = OverrideMode;

                // Return  true if mode is Allow or Inherit
                return ((mode == OverrideMode.Allow) || (mode == OverrideMode.Inherit));
            }
        }

        internal bool IsDefaultForLocationTag {
            get {
                // Returns true if the current setting is the same as the default value for a location tag
                // Note that if the setting was an API modified or XmlDefined  it is not a default since it
                // cannot go to the default <location> tag which does not explicitlly specify a mode

                OverrideModeSetting defaultSetting = LocationDefault;

                return  (defaultSetting.OverrideMode == this.OverrideMode) &&
                        ((_mode & ApiDefinedAny) == 0) &&
                        ((_mode & XmlDefinedAny) == 0);
            }
        }

        internal bool IsLocked {
            get { return OverrideMode == OverrideMode.Deny;}
        }

        internal string LocationTagXmlString {
            get {
                // Returns the string for this setting which is to be written in the xml <location> tag

                string  result      = String.Empty;
                string  value       = null;
                string  attrib      = null;

                bool    needToWrite = false;
                bool    useLegacy   = false;
                
                // If there was an API change - it has highest priority
                if ((_mode & ApiDefinedAny) != 0) {
                    // Whichever was changed by the API dictates what is to be written
                    useLegacy   = (_mode & ApiDefinedLegacy) != 0;
                    needToWrite = true;
                        
                    Debug.Assert(useLegacy || (_mode & ApiDefinedNewMode) != 0);
                }
                // It wasn't changed through the API - check if it was read originally from the XML
                else if ((_mode & XmlDefinedAny) != 0) {
                    // Whatever was defined in the XML is to be written out

                    useLegacy   = (_mode & XmlDefinedLegacy) != 0;
                    needToWrite = true;

                    Debug.Assert(useLegacy || (_mode & XmlDefinedNewMode) != 0);
                }

                if (needToWrite) {
                    // Legacy - allowOverride
                    if (useLegacy) {
                        attrib  = BaseConfigurationRecord.KEYWORD_LOCATION_ALLOWOVERRIDE;
                        value   = AllowOverride ? BaseConfigurationRecord.KEYWORD_TRUE : BaseConfigurationRecord.KEYWORD_FALSE;
                    }
                    else {
                        attrib  = BaseConfigurationRecord.KEYWORD_LOCATION_OVERRIDEMODE;
                        value   = OverrideModeXmlValue;
                    }

                    result = String.Format(CultureInfo.InvariantCulture, BaseConfigurationRecord.KEYWORD_LOCATION_OVERRIDEMODE_STRING, attrib, value);
                }

                return result;                    
            }
        }

        internal string OverrideModeXmlValue {
            get {
                // Returns the xml (string) value of the current setting for override mode

                switch(OverrideMode) {
                    case OverrideMode.Inherit:
                        return BaseConfigurationRecord.KEYWORD_OVERRIDEMODE_INHERIT;

                    case OverrideMode.Allow:
                        return BaseConfigurationRecord.KEYWORD_OVERRIDEMODE_ALLOW;

                    case OverrideMode.Deny:
                        return BaseConfigurationRecord.KEYWORD_OVERRIDEMODE_DENY;

                    default:
                        Debug.Assert(false, "Missing xml keyword for OverrideMode enum value");
                        break;
                }

                return null;
            }
        }

        // Use this method to change only the value of the setting when not done through the public API
        internal void ChangeModeInternal(OverrideMode mode) {
            SetMode(mode);
        }

        // Properties to enable external chnages to the mode.
        // Note that those changes will be tracked as made by the public API
        // There shouldn't be a reason for those to be used except in this specific case
        internal OverrideMode OverrideMode {
            get {
                return (OverrideMode)(_mode & ModeMask);
            }
            set {
                // Note that changing the mode through the API ( which is the purpose of this setter )
                // overrides the setting in the XML ( if any )
                // and hence we dont keep a track of it anymore

                // Error condition: We do not allow changes to the mode through both AllowOverride and OverrideMode
                // If one was changed first we require that API users stick with it
                VerifyConsistentChangeModel(ApiDefinedNewMode);

                SetMode(value);
                _mode |= ApiDefinedNewMode;
            }
        }

        internal bool AllowOverride {
            get {
                bool                    result  = true;

                switch(OverrideMode) {
                    case OverrideMode.Inherit:
                    case OverrideMode.Allow:
                        result = true;
                        break;

                    case OverrideMode.Deny:
                        result = false;
                        break;

                    default:
                        Debug.Assert(false, "Unrecognized OverrideMode");
                        break;
                }

                return result;
            }
            set {
                // Note that changing the mode through the API ( which is the purpose of this setter )
                // overrides the setting in the XML ( if any )
                // and hence we dont keep a track of it anymore

                // Error condition: We do not allow changes to the mode through both AllowOverride and OverrideMode
                // If one was changed first we require that API users stick with it
                VerifyConsistentChangeModel(ApiDefinedLegacy);

                SetMode(value ? OverrideMode.Inherit : OverrideMode.Deny);
                _mode |= ApiDefinedLegacy;
            }
        }


        private void SetMode(OverrideMode mode) {
            _mode = (byte)mode;
        }

        private void VerifyConsistentChangeModel(byte required) {
            // The required API change model ( i.e. was allowOverride used or OverrideMode ) should be consistent
            // I.e. its not possible to change both on the same OverrideModeSetting object
            
            byte current = (byte)(_mode & ApiDefinedAny);   // Shows whats the current setting: 0 ( none ), ApiDefinedLegacy or ApiDefinedNew

            if (current != 0 && current != required) {
                throw new ConfigurationErrorsException(SR.GetString(SR.Cannot_change_both_AllowOverride_and_OverrideMode));
            }
        }

    }
}