e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
885 lines
41 KiB
C#
885 lines
41 KiB
C#
//------------------------------------------------------------------------------
|
|
// <copyright file="HttpRuntimeSection.cs" company="Microsoft">
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// </copyright>
|
|
//------------------------------------------------------------------------------
|
|
|
|
namespace System.Web.Configuration {
|
|
using System;
|
|
using System.ComponentModel;
|
|
using System.Configuration;
|
|
using System.Runtime.Versioning;
|
|
using System.Text;
|
|
using System.Web.Security.AntiXss;
|
|
using System.Web.Util;
|
|
|
|
public sealed class HttpRuntimeSection : ConfigurationSection {
|
|
#if !FEATURE_PAL // FEATURE_PAL-specific timeout values
|
|
internal const int DefaultExecutionTimeout = 110;
|
|
#else // !FEATURE_PAL
|
|
// The timeout needs to be extended, since Coriolis/Rotor is much slower
|
|
// especially platforms like Solaris wan't be able to process complicated
|
|
// requests if in debug mode.
|
|
// Remove or change this once the real timeout is known
|
|
#if DEBUG
|
|
internal const int DefaultExecutionTimeout = 110 * 10;
|
|
#else // DEBUG
|
|
internal const int DefaultExecutionTimeout = 110 * 5;
|
|
#endif // DEBUG
|
|
|
|
#endif // !FEATURE_PAL
|
|
internal const int DefaultMaxRequestLength = 4096 * 1024; // 4MB
|
|
internal const int DefaultRequestLengthDiskThreshold = 80 * 1024; // 80KB
|
|
internal const int DefaultMinFreeThreads = 8;
|
|
internal const int DefaultMinLocalRequestFreeThreads = 4;
|
|
internal const int DefaultAppRequestQueueLimit = 100;
|
|
internal const int DefaultShutdownTimeout = 90;
|
|
internal const int DefaultDelayNotificationTimeout = 0;
|
|
internal const int DefaultWaitChangeNotification = 0;
|
|
internal const int DefaultMaxWaitChangeNotification = 0;
|
|
internal const bool DefaultAllowDynamicModuleRegistration = true;
|
|
internal const bool DefaultEnableKernelOutputCache = true;
|
|
internal const bool DefaultRequireRootedSaveAsPath = true;
|
|
internal const bool DefaultSendCacheControlHeader = true;
|
|
internal const string DefaultEncoderType = "System.Web.Util.HttpEncoder";
|
|
internal static readonly Version DefaultRequestValidationMode = VersionUtil.FrameworkDefault;
|
|
internal const string DefaultRequestValidationModeString = VersionUtil.FrameworkDefaultString;
|
|
internal const string DefaultRequestValidationType = "System.Web.Util.RequestValidator";
|
|
internal const string DefaultRequestPathInvalidCharacters = "<,>,*,%,&,:,\\,?";
|
|
internal const int DefaultMaxUrlLength = 260;
|
|
internal const int DefaultMaxQueryStringLength = 2048;
|
|
internal const bool DefaultRelaxedUrlToFileSystemMapping = false;
|
|
internal const string DefaultTargetFramework = null;
|
|
|
|
private AsyncPreloadModeFlags asyncPreloadModeCache;
|
|
private bool asyncPreloadModeCached = false;
|
|
|
|
private bool enableVersionHeaderCache = true;
|
|
private bool enableVersionHeaderCached = false;
|
|
private TimeSpan executionTimeoutCache;
|
|
private bool executionTimeoutCached = false;
|
|
|
|
private bool sendCacheControlHeaderCached = false;
|
|
private bool sendCacheControlHeaderCache;
|
|
|
|
private FcnMode fcnModeCache;
|
|
private bool fcnModeCached = false;
|
|
|
|
private static ConfigurationPropertyCollection _properties;
|
|
private static readonly ConfigurationProperty _propAsyncPreloadMode =
|
|
new ConfigurationProperty("asyncPreloadMode",
|
|
typeof(AsyncPreloadModeFlags),
|
|
AsyncPreloadModeFlags.None,
|
|
ConfigurationPropertyOptions.None);
|
|
|
|
private static readonly ConfigurationProperty _propExecutionTimeout =
|
|
new ConfigurationProperty("executionTimeout",
|
|
typeof(TimeSpan),
|
|
TimeSpan.FromSeconds((double)DefaultExecutionTimeout),
|
|
StdValidatorsAndConverters.TimeSpanSecondsConverter,
|
|
StdValidatorsAndConverters.PositiveTimeSpanValidator,
|
|
ConfigurationPropertyOptions.None);
|
|
private static readonly ConfigurationProperty _propMaxRequestLength =
|
|
new ConfigurationProperty("maxRequestLength",
|
|
typeof(int),
|
|
4096,
|
|
null,
|
|
StdValidatorsAndConverters.NonZeroPositiveIntegerValidator,
|
|
ConfigurationPropertyOptions.None);
|
|
private static readonly ConfigurationProperty _propRequestLengthDiskThreshold =
|
|
new ConfigurationProperty("requestLengthDiskThreshold",
|
|
typeof(int),
|
|
80,
|
|
null,
|
|
StdValidatorsAndConverters.NonZeroPositiveIntegerValidator,
|
|
ConfigurationPropertyOptions.None);
|
|
private static readonly ConfigurationProperty _propUseFullyQualifiedRedirectUrl =
|
|
new ConfigurationProperty("useFullyQualifiedRedirectUrl",
|
|
typeof(bool),
|
|
false,
|
|
ConfigurationPropertyOptions.None);
|
|
private static readonly ConfigurationProperty _propMinFreeThreads =
|
|
new ConfigurationProperty("minFreeThreads",
|
|
typeof(int),
|
|
8,
|
|
null,
|
|
StdValidatorsAndConverters.PositiveIntegerValidator,
|
|
ConfigurationPropertyOptions.None);
|
|
private static readonly ConfigurationProperty _propMinLocalRequestFreeThreads =
|
|
new ConfigurationProperty("minLocalRequestFreeThreads",
|
|
typeof(int),
|
|
4,
|
|
null,
|
|
StdValidatorsAndConverters.PositiveIntegerValidator,
|
|
ConfigurationPropertyOptions.None);
|
|
private static readonly ConfigurationProperty _propAppRequestQueueLimit =
|
|
new ConfigurationProperty("appRequestQueueLimit",
|
|
typeof(int),
|
|
5000,
|
|
null,
|
|
StdValidatorsAndConverters.NonZeroPositiveIntegerValidator,
|
|
ConfigurationPropertyOptions.None);
|
|
private static readonly ConfigurationProperty _propEnableKernelOutputCache =
|
|
new ConfigurationProperty("enableKernelOutputCache",
|
|
typeof(bool),
|
|
true,
|
|
ConfigurationPropertyOptions.None);
|
|
private static readonly ConfigurationProperty _propEnableVersionHeader =
|
|
new ConfigurationProperty("enableVersionHeader",
|
|
typeof(bool),
|
|
true,
|
|
ConfigurationPropertyOptions.None);
|
|
private static readonly ConfigurationProperty _propRequireRootedSaveAsPath =
|
|
new ConfigurationProperty("requireRootedSaveAsPath",
|
|
typeof(bool),
|
|
true,
|
|
ConfigurationPropertyOptions.None);
|
|
private static readonly ConfigurationProperty _propEnable =
|
|
new ConfigurationProperty("enable",
|
|
typeof(bool),
|
|
true,
|
|
ConfigurationPropertyOptions.None);
|
|
private static readonly ConfigurationProperty _propDefaultRegexMatchTimeout =
|
|
new ConfigurationProperty("defaultRegexMatchTimeout",
|
|
typeof(TimeSpan),
|
|
TimeSpan.Zero,
|
|
null,
|
|
StdValidatorsAndConverters.RegexMatchTimeoutValidator,
|
|
ConfigurationPropertyOptions.None);
|
|
private static readonly ConfigurationProperty _propShutdownTimeout =
|
|
new ConfigurationProperty("shutdownTimeout",
|
|
typeof(TimeSpan),
|
|
TimeSpan.FromSeconds((double)DefaultShutdownTimeout),
|
|
StdValidatorsAndConverters.TimeSpanSecondsConverter,
|
|
null,
|
|
ConfigurationPropertyOptions.None);
|
|
private static readonly ConfigurationProperty _propDelayNotificationTimeout =
|
|
new ConfigurationProperty("delayNotificationTimeout",
|
|
typeof(TimeSpan),
|
|
TimeSpan.FromSeconds((double)DefaultDelayNotificationTimeout),
|
|
StdValidatorsAndConverters.TimeSpanSecondsConverter,
|
|
null,
|
|
ConfigurationPropertyOptions.None);
|
|
private static readonly ConfigurationProperty _propWaitChangeNotification =
|
|
new ConfigurationProperty("waitChangeNotification",
|
|
typeof(int),
|
|
0,
|
|
null,
|
|
StdValidatorsAndConverters.PositiveIntegerValidator,
|
|
ConfigurationPropertyOptions.None);
|
|
private static readonly ConfigurationProperty _propMaxWaitChangeNotification =
|
|
new ConfigurationProperty("maxWaitChangeNotification",
|
|
typeof(int),
|
|
0,
|
|
null,
|
|
StdValidatorsAndConverters.PositiveIntegerValidator,
|
|
ConfigurationPropertyOptions.None);
|
|
private static readonly ConfigurationProperty _propEnableHeaderChecking =
|
|
new ConfigurationProperty("enableHeaderChecking",
|
|
typeof(bool),
|
|
true,
|
|
ConfigurationPropertyOptions.None);
|
|
private static readonly ConfigurationProperty _propSendCacheControlHeader =
|
|
new ConfigurationProperty("sendCacheControlHeader",
|
|
typeof(bool),
|
|
DefaultSendCacheControlHeader,
|
|
ConfigurationPropertyOptions.None);
|
|
private static readonly ConfigurationProperty _propApartmentThreading =
|
|
new ConfigurationProperty("apartmentThreading",
|
|
typeof(bool),
|
|
false,
|
|
ConfigurationPropertyOptions.None);
|
|
private static readonly ConfigurationProperty _propEncoderType =
|
|
new ConfigurationProperty("encoderType",
|
|
typeof(string),
|
|
DefaultEncoderType,
|
|
null,
|
|
StdValidatorsAndConverters.NonEmptyStringValidator,
|
|
ConfigurationPropertyOptions.None);
|
|
private static readonly ConfigurationProperty _propRequestValidationMode =
|
|
new ConfigurationProperty("requestValidationMode",
|
|
typeof(Version),
|
|
DefaultRequestValidationMode,
|
|
StdValidatorsAndConverters.VersionConverter,
|
|
null,
|
|
ConfigurationPropertyOptions.None);
|
|
private static readonly ConfigurationProperty _propRequestValidationType =
|
|
new ConfigurationProperty("requestValidationType",
|
|
typeof(string),
|
|
DefaultRequestValidationType,
|
|
null,
|
|
StdValidatorsAndConverters.NonEmptyStringValidator,
|
|
ConfigurationPropertyOptions.None);
|
|
|
|
private static readonly ConfigurationProperty _propRequestPathInvalidCharacters =
|
|
new ConfigurationProperty("requestPathInvalidCharacters",
|
|
typeof(string),
|
|
DefaultRequestPathInvalidCharacters,
|
|
StdValidatorsAndConverters.WhiteSpaceTrimStringConverter,
|
|
null,
|
|
ConfigurationPropertyOptions.None);
|
|
|
|
private static readonly ConfigurationProperty _propMaxUrlLength =
|
|
new ConfigurationProperty("maxUrlLength",
|
|
typeof(int),
|
|
DefaultMaxUrlLength,
|
|
null,
|
|
new IntegerValidator(0, 2097151), // Max from VS 330766
|
|
ConfigurationPropertyOptions.None);
|
|
|
|
private static readonly ConfigurationProperty _propMaxQueryStringLength =
|
|
new ConfigurationProperty("maxQueryStringLength",
|
|
typeof(int),
|
|
DefaultMaxQueryStringLength,
|
|
null,
|
|
new IntegerValidator(0, 2097151), // Max from VS 330766
|
|
ConfigurationPropertyOptions.None);
|
|
|
|
private static readonly ConfigurationProperty _propRelaxedUrlToFileSystemMapping =
|
|
new ConfigurationProperty("relaxedUrlToFileSystemMapping",
|
|
typeof(bool),
|
|
DefaultRelaxedUrlToFileSystemMapping,
|
|
ConfigurationPropertyOptions.None);
|
|
|
|
private static readonly ConfigurationProperty _propAllowDynamicModuleRegistration =
|
|
new ConfigurationProperty("allowDynamicModuleRegistration",
|
|
typeof(bool),
|
|
DefaultAllowDynamicModuleRegistration,
|
|
ConfigurationPropertyOptions.None);
|
|
|
|
private static readonly ConfigurationProperty _propFcnMode =
|
|
new ConfigurationProperty("fcnMode",
|
|
typeof(FcnMode),
|
|
FcnMode.NotSet,
|
|
ConfigurationPropertyOptions.None);
|
|
|
|
private static readonly ConfigurationProperty _propTargetFramework =
|
|
new ConfigurationProperty("targetFramework",
|
|
typeof(string),
|
|
DefaultTargetFramework,
|
|
ConfigurationPropertyOptions.None);
|
|
|
|
|
|
private int _MaxRequestLengthBytes;
|
|
private int _RequestLengthDiskThresholdBytes;
|
|
private static String s_versionHeader = null;
|
|
private Version _requestValidationMode;
|
|
|
|
/* <!--
|
|
httpRuntime Attributes:
|
|
asyncPreloadMode="None" [None | Form | FormMultiPart | AllFormTypes | NonForm | All]
|
|
executionTimeout="[seconds]" - time in seconds before request is automatically timed out
|
|
maxRequestLength="[KBytes]" - KBytes size of maximum request length to accept
|
|
requestLengthDiskThreshold="[KBytes]" - KBytes threshold to use disk for posted content temporary storage
|
|
useFullyQualifiedRedirectUrl="[true|false]" - Fully qualifiy the URL for client redirects
|
|
minFreeThreads="[count]" - minimum number of free thread to allow execution of new requests
|
|
minLocalRequestFreeThreads="[count]" - minimum number of free thread to allow execution of new local requests
|
|
appRequestQueueLimit="[count]" - maximum number of requests queued for the application; the sum of requests in all application queues is bounded from above by the global requestQueueLimit in the processModel section
|
|
enableKernelOutputCache="[true|false]" - enable the http.sys cache on IIS6 and higher - default is true
|
|
enableVersionHeader="[true|false]" - outputs X-AspNet-Version header with each request
|
|
requireRootedSaveAsPath="[true|false]" - the filename argument to SaveAs methods must be a rooted path
|
|
enable="[true|false]" - enable processing requests for this application
|
|
waitChangeNotification="[seconds]" - time in seconds to wait for another file change notification before restarting the AppDomain
|
|
maxWaitChangeNotification="[seconds]" - maximum time in seconds to wait from the first file change notification before restarting the AppDomain
|
|
enableHeaderChecking="[true|false]" - when true, CRLF pairs in response headers are encoded
|
|
encoderType="[typename]" - type used for custom HTTP encoding (HTML encoding, URL encoding, etc.)
|
|
requestValidationMode="[version]" - "2.0" to turn request validation on only for pages, "4.0" for the entire pipeline, "4.5" to enable granular request validation
|
|
requestValidationType="[typename]" - type used for custom request validation
|
|
RequestPathInvalidCharacters="[string]" - comma seperated list of chars in the URL to reject
|
|
maxUrlLength="[int]" - Max length of Request.Path
|
|
maxQueryStringLength="[int]" - Max length of QueryString
|
|
relaxedUrlToFileSystemMapping = "false"
|
|
allowDynamicModuleRegistration="[true|flase]" - used to block RegisterModule method calls
|
|
targetFramework="[string]" - framework version behavior to trigger CLR "quirks mode" settings
|
|
-->
|
|
<httpRuntime
|
|
asyncPreloadMode="None"
|
|
executionTimeout="110"
|
|
maxRequestLength="4096"
|
|
requestLengthDiskThreshold="80"
|
|
useFullyQualifiedRedirectUrl="false"
|
|
minFreeThreads="8"
|
|
minLocalRequestFreeThreads="4"
|
|
appRequestQueueLimit="5000"
|
|
enableVersionHeader="true"
|
|
requireRootedSaveAsPath="true"
|
|
enable="true"
|
|
encoderType="System.Web.Util.HttpEncoder"
|
|
requestValidationMode="4.0"
|
|
requestValidationType="System.Web.Util.RequestValidator"
|
|
RequestPathInvalidCharacters="<,>,*,%,&,:,\,?"
|
|
maxUrlLength="260"
|
|
maxQueryStringLength="4096"
|
|
relaxedUrlToFileSystemMapping = "false"
|
|
allowDynamicModuleRegistration = "true"
|
|
/>
|
|
*/
|
|
|
|
static HttpRuntimeSection() {
|
|
// Property initialization
|
|
_properties = new ConfigurationPropertyCollection();
|
|
_properties.Add(_propAsyncPreloadMode);
|
|
_properties.Add(_propExecutionTimeout);
|
|
_properties.Add(_propMaxRequestLength);
|
|
_properties.Add(_propRequestLengthDiskThreshold);
|
|
_properties.Add(_propUseFullyQualifiedRedirectUrl);
|
|
_properties.Add(_propMinFreeThreads);
|
|
_properties.Add(_propMinLocalRequestFreeThreads);
|
|
_properties.Add(_propAppRequestQueueLimit);
|
|
_properties.Add(_propEnableKernelOutputCache);
|
|
_properties.Add(_propEnableVersionHeader);
|
|
_properties.Add(_propRequireRootedSaveAsPath);
|
|
_properties.Add(_propEnable);
|
|
|
|
_properties.Add(_propDefaultRegexMatchTimeout);
|
|
_properties.Add(_propShutdownTimeout);
|
|
_properties.Add(_propDelayNotificationTimeout);
|
|
_properties.Add(_propWaitChangeNotification);
|
|
_properties.Add(_propMaxWaitChangeNotification);
|
|
|
|
_properties.Add(_propEnableHeaderChecking);
|
|
_properties.Add(_propSendCacheControlHeader);
|
|
_properties.Add(_propApartmentThreading);
|
|
|
|
_properties.Add(_propEncoderType);
|
|
_properties.Add(_propRequestValidationMode);
|
|
_properties.Add(_propRequestValidationType);
|
|
_properties.Add(_propRequestPathInvalidCharacters);
|
|
_properties.Add(_propMaxUrlLength);
|
|
_properties.Add(_propMaxQueryStringLength);
|
|
_properties.Add(_propRelaxedUrlToFileSystemMapping);
|
|
_properties.Add(_propAllowDynamicModuleRegistration);
|
|
_properties.Add(_propFcnMode);
|
|
_properties.Add(_propTargetFramework);
|
|
}
|
|
|
|
public HttpRuntimeSection() {
|
|
_MaxRequestLengthBytes = -1;
|
|
_RequestLengthDiskThresholdBytes = -1;
|
|
}
|
|
|
|
protected override ConfigurationPropertyCollection Properties {
|
|
get {
|
|
return _properties;
|
|
}
|
|
}
|
|
|
|
[ConfigurationProperty("asyncPreloadMode", DefaultValue = AsyncPreloadModeFlags.None)]
|
|
public AsyncPreloadModeFlags AsyncPreloadMode {
|
|
get {
|
|
if (asyncPreloadModeCached == false) {
|
|
asyncPreloadModeCache = (AsyncPreloadModeFlags)base[_propAsyncPreloadMode];
|
|
asyncPreloadModeCached = true;
|
|
}
|
|
return asyncPreloadModeCache;
|
|
}
|
|
set {
|
|
base[_propAsyncPreloadMode] = value;
|
|
asyncPreloadModeCache = value;
|
|
}
|
|
}
|
|
|
|
[ConfigurationProperty("fcnMode", DefaultValue = FcnMode.NotSet)]
|
|
public FcnMode FcnMode {
|
|
get {
|
|
if (!fcnModeCached) {
|
|
fcnModeCache = (FcnMode)base[_propFcnMode];
|
|
fcnModeCached = true;
|
|
}
|
|
return fcnModeCache;
|
|
}
|
|
set {
|
|
base[_propFcnMode] = value;
|
|
fcnModeCache = value;
|
|
}
|
|
}
|
|
|
|
[ConfigurationProperty("executionTimeout", DefaultValue = "00:01:50")]
|
|
[TypeConverter(typeof(TimeSpanSecondsConverter))]
|
|
[TimeSpanValidator(MinValueString = "00:00:00", MaxValueString = TimeSpanValidatorAttribute.TimeSpanMaxValue)]
|
|
public TimeSpan ExecutionTimeout {
|
|
get {
|
|
if (executionTimeoutCached == false) {
|
|
executionTimeoutCache = (TimeSpan)base[_propExecutionTimeout];
|
|
executionTimeoutCached = true;
|
|
}
|
|
return executionTimeoutCache;
|
|
}
|
|
set {
|
|
base[_propExecutionTimeout] = value;
|
|
executionTimeoutCache = value;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
[ConfigurationProperty("maxRequestLength", DefaultValue = 4096)]
|
|
[IntegerValidator(MinValue = 0)]
|
|
public int MaxRequestLength {
|
|
get {
|
|
return (int)base[_propMaxRequestLength];
|
|
}
|
|
set {
|
|
if (value < RequestLengthDiskThreshold) {
|
|
throw new ConfigurationErrorsException(SR.GetString(SR.Config_max_request_length_smaller_than_max_request_length_disk_threshold),
|
|
ElementInformation.Properties[_propMaxRequestLength.Name].Source,
|
|
ElementInformation.Properties[_propMaxRequestLength.Name].LineNumber);
|
|
}
|
|
base[_propMaxRequestLength] = value;
|
|
} //
|
|
}
|
|
|
|
[ConfigurationProperty("requestLengthDiskThreshold", DefaultValue = 80)]
|
|
[IntegerValidator(MinValue = 1)]
|
|
public int RequestLengthDiskThreshold {
|
|
get {
|
|
return (int)base[_propRequestLengthDiskThreshold];
|
|
}
|
|
set {
|
|
if (value > MaxRequestLength) {
|
|
throw new ConfigurationErrorsException(SR.GetString(SR.Config_max_request_length_disk_threshold_exceeds_max_request_length),
|
|
ElementInformation.Properties[_propRequestLengthDiskThreshold.Name].Source,
|
|
ElementInformation.Properties[_propRequestLengthDiskThreshold.Name].LineNumber);
|
|
}
|
|
base[_propRequestLengthDiskThreshold] = value;
|
|
}
|
|
}
|
|
|
|
[ConfigurationProperty("useFullyQualifiedRedirectUrl", DefaultValue = false)]
|
|
public bool UseFullyQualifiedRedirectUrl {
|
|
get {
|
|
return (bool)base[_propUseFullyQualifiedRedirectUrl];
|
|
}
|
|
set {
|
|
base[_propUseFullyQualifiedRedirectUrl] = value;
|
|
}
|
|
}
|
|
|
|
[ConfigurationProperty("minFreeThreads", DefaultValue = 8)]
|
|
[IntegerValidator(MinValue = 0)]
|
|
public int MinFreeThreads {
|
|
get {
|
|
return (int)base[_propMinFreeThreads];
|
|
}
|
|
set {
|
|
base[_propMinFreeThreads] = value;
|
|
}
|
|
}
|
|
|
|
[ConfigurationProperty("minLocalRequestFreeThreads", DefaultValue = 4)]
|
|
[IntegerValidator(MinValue = 0)]
|
|
public int MinLocalRequestFreeThreads {
|
|
get {
|
|
return (int)base[_propMinLocalRequestFreeThreads];
|
|
}
|
|
set {
|
|
base[_propMinLocalRequestFreeThreads] = value;
|
|
}
|
|
}
|
|
|
|
[ConfigurationProperty("appRequestQueueLimit", DefaultValue = 5000)]
|
|
[IntegerValidator(MinValue = 1)]
|
|
public int AppRequestQueueLimit {
|
|
get {
|
|
return (int)base[_propAppRequestQueueLimit];
|
|
}
|
|
set {
|
|
base[_propAppRequestQueueLimit] = value;
|
|
}
|
|
}
|
|
|
|
[ConfigurationProperty("enableKernelOutputCache", DefaultValue = true)]
|
|
public bool EnableKernelOutputCache {
|
|
get {
|
|
return (bool)base[_propEnableKernelOutputCache];
|
|
}
|
|
set {
|
|
base[_propEnableKernelOutputCache] = value;
|
|
}
|
|
}
|
|
|
|
[ConfigurationProperty("enableVersionHeader", DefaultValue = true)]
|
|
public bool EnableVersionHeader {
|
|
get {
|
|
if (enableVersionHeaderCached == false) {
|
|
enableVersionHeaderCache = (bool)base[_propEnableVersionHeader];
|
|
enableVersionHeaderCached = true;
|
|
}
|
|
return enableVersionHeaderCache;
|
|
}
|
|
set {
|
|
base[_propEnableVersionHeader] = value;
|
|
enableVersionHeaderCache = value;
|
|
}
|
|
}
|
|
|
|
[ConfigurationProperty("apartmentThreading", DefaultValue = false)]
|
|
public bool ApartmentThreading {
|
|
get {
|
|
return (bool)base[_propApartmentThreading];
|
|
}
|
|
set {
|
|
base[_propApartmentThreading] = value;
|
|
}
|
|
}
|
|
|
|
[ConfigurationProperty("requireRootedSaveAsPath", DefaultValue = true)]
|
|
public bool RequireRootedSaveAsPath {
|
|
get {
|
|
return (bool)base[_propRequireRootedSaveAsPath];
|
|
}
|
|
set {
|
|
base[_propRequireRootedSaveAsPath] = value;
|
|
}
|
|
}
|
|
|
|
[ConfigurationProperty("enable", DefaultValue = true)]
|
|
public bool Enable {
|
|
get {
|
|
return (bool)base[_propEnable];
|
|
}
|
|
set {
|
|
base[_propEnable] = value;
|
|
}
|
|
}
|
|
|
|
[ConfigurationProperty("targetFramework", DefaultValue = DefaultTargetFramework)]
|
|
public string TargetFramework {
|
|
get {
|
|
return (string)base[_propTargetFramework];
|
|
}
|
|
set {
|
|
base[_propTargetFramework] = value;
|
|
}
|
|
}
|
|
|
|
// method is used to provide a FrameworkName to be used for the AppDomainSetup.TargetFrameworkName property
|
|
internal FrameworkName GetTargetFrameworkName() {
|
|
string targetFramework = TargetFramework; // only read from property once so the value can't change in the middle of processing
|
|
if (String.IsNullOrEmpty(targetFramework)) {
|
|
// no target framework; let caller perform default behavior
|
|
return null;
|
|
}
|
|
else {
|
|
Version version;
|
|
if (!Version.TryParse(targetFramework, out version)) {
|
|
// if this doesn't parse as a valid Version object, throw an exception containing the erroneous line in config
|
|
PropertyInformation targetFrameworkPropInfo = ElementInformation.Properties["targetFramework"];
|
|
throw new ConfigurationErrorsException(SR.GetString(SR.HttpRuntimeSection_TargetFramework_Invalid),
|
|
filename: targetFrameworkPropInfo.Source,
|
|
line: targetFrameworkPropInfo.LineNumber);
|
|
}
|
|
|
|
// check succeeded
|
|
return new FrameworkName(".NETFramework", version);
|
|
}
|
|
}
|
|
|
|
[ConfigurationProperty("sendCacheControlHeader", DefaultValue = DefaultSendCacheControlHeader)]
|
|
public bool SendCacheControlHeader {
|
|
get {
|
|
if (sendCacheControlHeaderCached == false) {
|
|
sendCacheControlHeaderCache = (bool)base[_propSendCacheControlHeader];
|
|
sendCacheControlHeaderCached = true;
|
|
}
|
|
return sendCacheControlHeaderCache;
|
|
}
|
|
set {
|
|
base[_propSendCacheControlHeader] = value;
|
|
sendCacheControlHeaderCache = value;
|
|
}
|
|
}
|
|
|
|
[ConfigurationProperty("defaultRegexMatchTimeout", DefaultValue = "00:00:00")]
|
|
[RegexMatchTimeoutValidator]
|
|
public TimeSpan DefaultRegexMatchTimeout {
|
|
get {
|
|
return (TimeSpan)base[_propDefaultRegexMatchTimeout];
|
|
}
|
|
set {
|
|
base[_propDefaultRegexMatchTimeout] = value;
|
|
}
|
|
}
|
|
|
|
[ConfigurationProperty("shutdownTimeout", DefaultValue = "00:01:30")]
|
|
[TypeConverter(typeof(TimeSpanSecondsConverter))]
|
|
public TimeSpan ShutdownTimeout {
|
|
get {
|
|
return (TimeSpan)base[_propShutdownTimeout];
|
|
}
|
|
set {
|
|
base[_propShutdownTimeout] = value;
|
|
}
|
|
}
|
|
|
|
[ConfigurationProperty("delayNotificationTimeout", DefaultValue = "00:00:00")]
|
|
[TypeConverter(typeof(TimeSpanSecondsConverter))]
|
|
public TimeSpan DelayNotificationTimeout {
|
|
get {
|
|
return (TimeSpan)base[_propDelayNotificationTimeout];
|
|
}
|
|
set {
|
|
base[_propDelayNotificationTimeout] = value;
|
|
}
|
|
}
|
|
|
|
[ConfigurationProperty("waitChangeNotification", DefaultValue = 0)]
|
|
[IntegerValidator(MinValue = 0)]
|
|
public int WaitChangeNotification {
|
|
get {
|
|
return (int)base[_propWaitChangeNotification];
|
|
}
|
|
set {
|
|
base[_propWaitChangeNotification] = value;
|
|
}
|
|
}
|
|
|
|
[ConfigurationProperty("maxWaitChangeNotification", DefaultValue = 0)]
|
|
[IntegerValidator(MinValue = 0)]
|
|
public int MaxWaitChangeNotification {
|
|
get {
|
|
return (int)base[_propMaxWaitChangeNotification];
|
|
}
|
|
set {
|
|
base[_propMaxWaitChangeNotification] = value;
|
|
}
|
|
}
|
|
|
|
[ConfigurationProperty("enableHeaderChecking", DefaultValue = true)]
|
|
public bool EnableHeaderChecking {
|
|
get {
|
|
return (bool)base[_propEnableHeaderChecking];
|
|
}
|
|
set {
|
|
base[_propEnableHeaderChecking] = value;
|
|
}
|
|
}
|
|
|
|
[ConfigurationProperty("encoderType", DefaultValue = DefaultEncoderType)]
|
|
[StringValidator(MinLength = 1)]
|
|
public string EncoderType {
|
|
get {
|
|
return (string)base[_propEncoderType];
|
|
}
|
|
set {
|
|
base[_propEncoderType] = value;
|
|
}
|
|
}
|
|
|
|
[ConfigurationProperty("requestValidationMode", DefaultValue = DefaultRequestValidationModeString)]
|
|
[TypeConverter(typeof(VersionConverter))]
|
|
public Version RequestValidationMode {
|
|
get {
|
|
if (_requestValidationMode == null) {
|
|
_requestValidationMode = (Version)base[_propRequestValidationMode];
|
|
}
|
|
return _requestValidationMode;
|
|
}
|
|
set {
|
|
_requestValidationMode = value;
|
|
base[_propRequestValidationMode] = value;
|
|
}
|
|
}
|
|
|
|
[ConfigurationProperty("requestValidationType", DefaultValue = DefaultRequestValidationType)]
|
|
[StringValidator(MinLength = 1)]
|
|
public string RequestValidationType {
|
|
get {
|
|
return (string)base[_propRequestValidationType];
|
|
}
|
|
set {
|
|
base[_propRequestValidationType] = value;
|
|
}
|
|
}
|
|
|
|
[ConfigurationProperty("requestPathInvalidCharacters", DefaultValue = DefaultRequestPathInvalidCharacters)]
|
|
public string RequestPathInvalidCharacters {
|
|
get {
|
|
return (string)base[_propRequestPathInvalidCharacters];
|
|
}
|
|
set {
|
|
base[_propRequestPathInvalidCharacters] = value;
|
|
_RequestPathInvalidCharactersArray = null;
|
|
}
|
|
}
|
|
|
|
private int _MaxUrlLength = 0;
|
|
[ConfigurationProperty("maxUrlLength", DefaultValue = DefaultMaxUrlLength)]
|
|
[IntegerValidator(MinValue = 0)]
|
|
public int MaxUrlLength {
|
|
get {
|
|
if (_MaxUrlLength == 0)
|
|
_MaxUrlLength = (int)base[_propMaxUrlLength];
|
|
return _MaxUrlLength;
|
|
}
|
|
set {
|
|
_MaxUrlLength = value;
|
|
base[_propMaxUrlLength] = value;
|
|
}
|
|
}
|
|
|
|
|
|
private int _MaxQueryStringLength = 0;
|
|
[ConfigurationProperty("maxQueryStringLength", DefaultValue = DefaultMaxQueryStringLength)]
|
|
[IntegerValidator(MinValue = 0)]
|
|
public int MaxQueryStringLength {
|
|
get {
|
|
if (_MaxQueryStringLength == 0)
|
|
_MaxQueryStringLength = (int)base[_propMaxQueryStringLength];
|
|
return _MaxQueryStringLength;
|
|
}
|
|
set {
|
|
_MaxQueryStringLength = value;
|
|
base[_propMaxQueryStringLength] = value;
|
|
}
|
|
}
|
|
|
|
[ConfigurationProperty("relaxedUrlToFileSystemMapping", DefaultValue = DefaultRelaxedUrlToFileSystemMapping)]
|
|
public bool RelaxedUrlToFileSystemMapping {
|
|
get {
|
|
return (bool)base[_propRelaxedUrlToFileSystemMapping];
|
|
}
|
|
set {
|
|
base[_propRelaxedUrlToFileSystemMapping] = value;
|
|
}
|
|
}
|
|
|
|
[ConfigurationProperty("allowDynamicModuleRegistration", DefaultValue = DefaultAllowDynamicModuleRegistration)]
|
|
public bool AllowDynamicModuleRegistration {
|
|
get {
|
|
return (bool)base[_propAllowDynamicModuleRegistration];
|
|
}
|
|
set {
|
|
base[_propAllowDynamicModuleRegistration] = value;
|
|
}
|
|
}
|
|
|
|
private int BytesFromKilobytes(int kilobytes) {
|
|
long maxLength = kilobytes * 1024L;
|
|
return ((maxLength < Int32.MaxValue) ? (int)maxLength : Int32.MaxValue);
|
|
}
|
|
|
|
internal int MaxRequestLengthBytes {
|
|
get {
|
|
if (_MaxRequestLengthBytes < 0) {
|
|
_MaxRequestLengthBytes = BytesFromKilobytes(MaxRequestLength);
|
|
}
|
|
return _MaxRequestLengthBytes;
|
|
}
|
|
}
|
|
|
|
internal int RequestLengthDiskThresholdBytes {
|
|
get {
|
|
if (_RequestLengthDiskThresholdBytes < 0) {
|
|
_RequestLengthDiskThresholdBytes = BytesFromKilobytes(RequestLengthDiskThreshold);
|
|
}
|
|
return _RequestLengthDiskThresholdBytes;
|
|
}
|
|
}
|
|
|
|
internal String VersionHeader {
|
|
get {
|
|
if (!EnableVersionHeader) {
|
|
return null;
|
|
}
|
|
|
|
if (s_versionHeader == null) {
|
|
String header = null;
|
|
// construct once (race condition here doesn't matter)
|
|
try {
|
|
String version = VersionInfo.SystemWebVersion;
|
|
int i = version.LastIndexOf('.');
|
|
if (i > 0) {
|
|
header = version.Substring(0, i);
|
|
}
|
|
}
|
|
catch {
|
|
}
|
|
|
|
if (header == null) {
|
|
header = String.Empty;
|
|
}
|
|
|
|
s_versionHeader = header;
|
|
}
|
|
|
|
return s_versionHeader;
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
private char[] _RequestPathInvalidCharactersArray = null;
|
|
internal char[] RequestPathInvalidCharactersArray {
|
|
get {
|
|
if (_RequestPathInvalidCharactersArray != null)
|
|
return _RequestPathInvalidCharactersArray;
|
|
|
|
_RequestPathInvalidCharactersArray = DecodeAndThenSplitString(RequestPathInvalidCharacters);
|
|
if (_RequestPathInvalidCharactersArray == null) {
|
|
// Maybe comma was one of the invalid chars, which can cause DecodeAndThenSplitString to fail
|
|
// Split using the comma and then decode each part
|
|
_RequestPathInvalidCharactersArray = SplitStringAndThenDecode(RequestPathInvalidCharacters);
|
|
}
|
|
|
|
if (_RequestPathInvalidCharactersArray == null) { // failed to construct invalid chars
|
|
throw new ConfigurationErrorsException(SR.GetString(SR.Config_property_generic),
|
|
ElementInformation.Properties[_propRequestPathInvalidCharacters.Name].Source,
|
|
ElementInformation.Properties[_propRequestPathInvalidCharacters.Name].LineNumber);
|
|
}
|
|
return _RequestPathInvalidCharactersArray;
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
private static char[] DecodeAndThenSplitString(string invalidCharString) {
|
|
if (string.IsNullOrEmpty(invalidCharString)) {
|
|
return new char[0];
|
|
}
|
|
|
|
string[] stringsDecoded = HttpUtility.UrlDecode(invalidCharString, Encoding.UTF8).Split(',');
|
|
char[] charsDecoded = new char[stringsDecoded.Length];
|
|
|
|
for (int iter = 0; iter < stringsDecoded.Length; iter++) {
|
|
string decodedString = stringsDecoded[iter].Trim();
|
|
if (decodedString.Length == 1)
|
|
charsDecoded[iter] = decodedString[0];
|
|
else
|
|
return null; // failed
|
|
}
|
|
return charsDecoded;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
private static char[] SplitStringAndThenDecode(string invalidCharString) {
|
|
if (string.IsNullOrEmpty(invalidCharString)) {
|
|
return new char[0];
|
|
}
|
|
|
|
string[] stringsToDecode = invalidCharString.Split(',');
|
|
char[] charsDecoded = new char[stringsToDecode.Length];
|
|
|
|
for (int iter = 0; iter < stringsToDecode.Length; iter++) {
|
|
string decodedString = HttpUtility.UrlDecode(stringsToDecode[iter], Encoding.UTF8).Trim();
|
|
if (decodedString.Length == 1)
|
|
charsDecoded[iter] = decodedString[0];
|
|
else
|
|
return null; // failed
|
|
}
|
|
return charsDecoded;
|
|
}
|
|
|
|
// This is called as the last step of the deserialization process before the newly created section is seen by the consumer.
|
|
// We can use it to change defaults on-the-fly.
|
|
protected override void SetReadOnly() {
|
|
// Unless overridden, set <httpRuntime requestValidationMode="4.5" />
|
|
ConfigUtil.SetFX45DefaultValue(this, _propRequestValidationMode, VersionUtil.Framework45);
|
|
|
|
base.SetReadOnly();
|
|
}
|
|
}
|
|
}
|