You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@@ -0,0 +1,95 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="ActivityIdHelper.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace System.Web.Util {
|
||||
using System;
|
||||
using System.Diagnostics.Tracing;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
|
||||
internal sealed class ActivityIdHelper {
|
||||
|
||||
private delegate Guid GetCurrentDelegate();
|
||||
private delegate void SetAndDestroyDelegate(Guid activityId);
|
||||
private delegate void SetAndPreserveDelegate(Guid activityId, out Guid oldActivityThatWillContinue);
|
||||
|
||||
// Note to callers: this field can be null.
|
||||
internal static readonly ActivityIdHelper Instance = GetSingleton();
|
||||
|
||||
private static readonly Guid _baseGuid = Guid.NewGuid();
|
||||
private static long _counter;
|
||||
|
||||
private readonly GetCurrentDelegate _getCurrentDel;
|
||||
private readonly SetAndDestroyDelegate _setAndDestroyDel;
|
||||
private readonly SetAndPreserveDelegate _setAndPreserveDel;
|
||||
|
||||
// use the factory to create an instance of this type
|
||||
private ActivityIdHelper(GetCurrentDelegate getCurrentDel, SetAndDestroyDelegate setAndDestroyDel, SetAndPreserveDelegate setAndPreserveDel) {
|
||||
_getCurrentDel = getCurrentDel;
|
||||
_setAndDestroyDel = setAndDestroyDel;
|
||||
_setAndPreserveDel = setAndPreserveDel;
|
||||
}
|
||||
|
||||
// Gets the current thread's activity ID.
|
||||
public Guid CurrentThreadActivityId {
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get { return _getCurrentDel(); }
|
||||
}
|
||||
|
||||
private static ActivityIdHelper GetSingleton() {
|
||||
try {
|
||||
// The mscorlib APIs we depend on weren't added until Blue, so we can't
|
||||
// take a direct dependency. Need to light up instead.
|
||||
|
||||
var getCurrentDel = (GetCurrentDelegate)Delegate.CreateDelegate(
|
||||
typeof(GetCurrentDelegate), typeof(EventSource), "get_CurrentThreadActivityId", ignoreCase: false, throwOnBindFailure: false);
|
||||
|
||||
var setAndDestroyDel = (SetAndDestroyDelegate)Delegate.CreateDelegate(
|
||||
typeof(SetAndDestroyDelegate), typeof(EventSource), "SetCurrentThreadActivityId", ignoreCase: false, throwOnBindFailure: false);
|
||||
|
||||
var setAndPreserveDel = (SetAndPreserveDelegate)Delegate.CreateDelegate(
|
||||
typeof(SetAndPreserveDelegate), typeof(EventSource), "SetCurrentThreadActivityId", ignoreCase: false, throwOnBindFailure: false);
|
||||
|
||||
if (getCurrentDel != null && setAndDestroyDel != null && setAndPreserveDel != null) {
|
||||
return new ActivityIdHelper(getCurrentDel, setAndDestroyDel, setAndPreserveDel);
|
||||
}
|
||||
}
|
||||
catch {
|
||||
// exceptions are not fatal; we just won't be able to call the new APIs
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Disposes of the thread's existing activity ID, then sets the new activity ID on this thread.
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void SetCurrentThreadActivityId(Guid activityId) {
|
||||
_setAndDestroyDel(activityId);
|
||||
}
|
||||
|
||||
// Suspends (but does not dispose of) the thread's existing activity ID, then sets a new activity ID on this thread.
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void SetCurrentThreadActivityId(Guid activityId, out Guid oldActivityThatWillContinue) {
|
||||
_setAndPreserveDel(activityId, out oldActivityThatWillContinue);
|
||||
}
|
||||
|
||||
// !! SECURITY WARNING !!
|
||||
// The GUIDs created by this method are predictable and should be used ONLY for tracing.
|
||||
// Any other use (such as leaking them to the user) constitutes information disclosure.
|
||||
//
|
||||
// This is a perf-sensitive method since it could potentially be called many times per
|
||||
// request. Guid.NewGuid() is slow since it eventually calls CAPI, and we did actually
|
||||
// see it show up as a bottleneck when developing MVC 2. The below implementation has
|
||||
// measurably better performance characteristics than calling the other Guid ctors.
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static unsafe Guid UnsafeCreateNewActivityId() {
|
||||
Guid guidCopy = _baseGuid;
|
||||
*(long*)(&guidCopy) ^= Interlocked.Increment(ref _counter); // operate on the copy, not the original
|
||||
return guidCopy;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
496
mcs/class/referencesource/System.Web/Util/AppSettings.cs
Normal file
496
mcs/class/referencesource/System.Web/Util/AppSettings.cs
Normal file
@@ -0,0 +1,496 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="AppSettings.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// AppSettings.cs
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.Configuration;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Security.Permissions;
|
||||
using System.Web.Configuration;
|
||||
using System.Web.Hosting;
|
||||
|
||||
namespace System.Web.Util {
|
||||
|
||||
internal static class AppSettings
|
||||
{
|
||||
private static volatile bool _settingsInitialized = false;
|
||||
private static object _appSettingsLock = new object();
|
||||
private static void EnsureSettingsLoaded() {
|
||||
|
||||
if (!_settingsInitialized) {
|
||||
lock (_appSettingsLock) {
|
||||
if (!_settingsInitialized) {
|
||||
|
||||
NameValueCollection settings = null;
|
||||
|
||||
try {
|
||||
settings = GetAppSettingsSection();
|
||||
} finally {
|
||||
|
||||
// GetApplicationPathData may throw. That's fine. Let the user see the exception
|
||||
// once, but just fall back on default settings for the future.
|
||||
if (settings == null || !Boolean.TryParse(settings["aspnet:UseHostHeaderForRequestUrl"], out _useHostHeaderForRequestUrl))
|
||||
_useHostHeaderForRequestUrl = false;
|
||||
|
||||
if (settings == null || !Boolean.TryParse(settings["aspnet:AllowAnonymousImpersonation"], out _allowAnonymousImpersonation))
|
||||
_allowAnonymousImpersonation = false;
|
||||
|
||||
if (settings == null || !Boolean.TryParse(settings["aspnet:ScriptResourceAllowNonJsFiles"], out _scriptResourceAllowNonJsFiles))
|
||||
_scriptResourceAllowNonJsFiles = false;
|
||||
|
||||
if (settings == null || !Boolean.TryParse(settings["aspnet:UseLegacyEncryption"], out _useLegacyEncryption))
|
||||
_useLegacyEncryption = false;
|
||||
|
||||
if (settings == null || !Boolean.TryParse(settings["aspnet:UseLegacyMachineKeyEncryption"], out _useLegacyMachineKeyEncryption))
|
||||
_useLegacyMachineKeyEncryption = false;
|
||||
|
||||
if (settings == null || !Boolean.TryParse(settings["aspnet:UseLegacyFormsAuthenticationTicketCompatibility"], out _useLegacyFormsAuthenticationTicketCompatibility))
|
||||
_useLegacyFormsAuthenticationTicketCompatibility = false;
|
||||
|
||||
if (settings == null || !Boolean.TryParse(settings["aspnet:UseLegacyEventValidationCompatibility"], out _useLegacyEventValidationCompatibility))
|
||||
_useLegacyEventValidationCompatibility = false;
|
||||
|
||||
_allowInsecureDeserialization = GetNullableBooleanValue(settings, "aspnet:AllowInsecureDeserialization");
|
||||
|
||||
if (settings == null || !Boolean.TryParse(settings["aspnet:AlwaysIgnoreViewStateValidationErrors"], out _alwaysIgnoreViewStateValidationErrors))
|
||||
_alwaysIgnoreViewStateValidationErrors = false;
|
||||
|
||||
if (settings == null || !Boolean.TryParse(settings["aspnet:AllowRelaxedHttpUserName"], out _allowRelaxedHttpUserName))
|
||||
_allowRelaxedHttpUserName = false;
|
||||
|
||||
if (settings == null || !Boolean.TryParse(settings["aspnet:JavaScriptDoNotEncodeAmpersand"], out _javaScriptDoNotEncodeAmpersand))
|
||||
_javaScriptDoNotEncodeAmpersand = false;
|
||||
|
||||
if (settings == null || !Boolean.TryParse(settings["aspnet:UseTaskFriendlySynchronizationContext"], out _useTaskFriendlySynchronizationContext))
|
||||
_useTaskFriendlySynchronizationContext = (BinaryCompatibility.Current.TargetsAtLeastFramework45) ? true : false;
|
||||
|
||||
if (settings == null || !Boolean.TryParse(settings["aspnet:AllowAsyncDuringSyncStages"], out _allowAsyncDuringSyncStages))
|
||||
_allowAsyncDuringSyncStages = false;
|
||||
|
||||
if (settings == null || !int.TryParse(settings["aspnet:MaxHttpCollectionKeys"], out _maxHttpCollectionKeys) || _maxHttpCollectionKeys < 0)
|
||||
_maxHttpCollectionKeys = DefaultMaxHttpCollectionKeys;
|
||||
|
||||
if (settings == null || !int.TryParse(settings["aspnet:MaxJsonDeserializerMembers"], out _maxJsonDeserializerMembers) || _maxJsonDeserializerMembers < 0)
|
||||
_maxJsonDeserializerMembers = DefaultMaxJsonDeserializerMembers;
|
||||
|
||||
if (settings == null || !Boolean.TryParse(settings["aspnet:DoNotDisposeSpecialHttpApplicationInstances"], out _doNotDisposeSpecialHttpApplicationInstances))
|
||||
_doNotDisposeSpecialHttpApplicationInstances = false;
|
||||
|
||||
if (settings != null)
|
||||
_formsAuthReturnUrlVar = settings["aspnet:FormsAuthReturnUrlVar"];
|
||||
|
||||
if (settings == null || !Boolean.TryParse(settings["aspnet:RestrictXmlControls"], out _restrictXmlControls))
|
||||
_restrictXmlControls = false;
|
||||
|
||||
if (settings == null || !Boolean.TryParse(settings["aspnet:AllowRelaxedRelativeUrl"], out _allowRelaxedRelativeUrl))
|
||||
_allowRelaxedRelativeUrl = false;
|
||||
|
||||
if (settings == null || !Boolean.TryParse(settings["aspnet:UseLegacyRequestUrlGeneration"], out _useLegacyRequestUrlGeneration))
|
||||
_useLegacyRequestUrlGeneration = false;
|
||||
|
||||
if (settings == null || !Boolean.TryParse(settings["aspnet:AllowUtf7RequestContentEncoding"], out _allowUtf7RequestContentEncoding))
|
||||
_allowUtf7RequestContentEncoding = false;
|
||||
|
||||
if (settings == null || !Boolean.TryParse(settings["aspnet:AllowRelaxedUnicodeDecoding"], out _allowRelaxedUnicodeDecoding))
|
||||
_allowRelaxedUnicodeDecoding = false;
|
||||
|
||||
if (settings == null || !Boolean.TryParse(settings["aspnet:DontUsePercentUUrlEncoding"], out _dontUsePercentUUrlEncoding))
|
||||
_dontUsePercentUUrlEncoding = BinaryCompatibility.Current.TargetsAtLeastFramework452; // default value is keyed off of <httpRuntime targetFramework="4.5.2" />
|
||||
|
||||
if (settings == null || !int.TryParse(settings["aspnet:UpdatePanelMaxScriptLength"], out _updatePanelMaxScriptLength) || _updatePanelMaxScriptLength < 0)
|
||||
_updatePanelMaxScriptLength = 0;
|
||||
|
||||
// AppSettings override allows users to build against 4.5 but run against 4.0 or 4.5
|
||||
_maxConcurrentCompilations = GetNullableIntegerValue(settings, "aspnet:MaxConcurrentCompilations");
|
||||
|
||||
if (settings == null || !int.TryParse(settings["aspnet:MaxAcceptLanguageFallbackCount"], out _maxAcceptLanguageFallbackCount) || _maxAcceptLanguageFallbackCount <= 0)
|
||||
_maxAcceptLanguageFallbackCount = DefaultMaxAcceptLanguageFallbackCount;
|
||||
|
||||
if (settings == null || !Boolean.TryParse(settings["aspnet:PortableCompilationOutput"], out _portableCompilationOutput))
|
||||
_portableCompilationOutput = false;
|
||||
|
||||
if (settings == null || string.IsNullOrWhiteSpace(_portableCompilationOutputSnapshotType = settings["aspnet:PortableCompilationOutputSnapshotType"]))
|
||||
_portableCompilationOutputSnapshotType = null;
|
||||
|
||||
if (settings == null || string.IsNullOrWhiteSpace(_portableCompilationOutputSnapshotTypeOptions = settings["aspnet:PortableCompilationOutputSnapshotTypeOptions"]))
|
||||
_portableCompilationOutputSnapshotTypeOptions = null;
|
||||
|
||||
if (settings == null || !Boolean.TryParse(settings["aspnet:EnsureSessionStateLockedOnFlush"], out _ensureSessionStateLockedOnFlush))
|
||||
_ensureSessionStateLockedOnFlush = false;
|
||||
|
||||
if (settings == null || !Boolean.TryParse(settings["aspnet:UseRandomizedStringHashAlgorithm"], out _useRandomizedStringHashAlgorithm))
|
||||
_useRandomizedStringHashAlgorithm = false;
|
||||
|
||||
if (settings == null || !Boolean.TryParse(settings["aspnet:EnableAsyncModelBinding"], out _enableAsyncModelBinding))
|
||||
_enableAsyncModelBinding = BinaryCompatibility.Current.TargetsAtLeastFramework46;
|
||||
|
||||
_settingsInitialized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationPermission(SecurityAction.Assert, Unrestricted = true)]
|
||||
[SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Justification = "This assert is safe since we control the callers; they're not leaking information.")]
|
||||
private static NameValueCollection GetAppSettingsSection() {
|
||||
// DevDiv #353926 - Fall back to reading App.config if System.Web types are being consumed outside an ASP.NET application
|
||||
if (!HostingEnvironment.IsHosted) {
|
||||
return ConfigurationManager.AppSettings;
|
||||
}
|
||||
|
||||
// Check the app-level config. Ignore configuration errors
|
||||
CachedPathData appPathData = CachedPathData.GetApplicationPathData();
|
||||
|
||||
if (appPathData != null && appPathData.ConfigRecord != null)
|
||||
return appPathData.ConfigRecord.GetSection("appSettings") as NameValueCollection;
|
||||
|
||||
// nothing found
|
||||
return null;
|
||||
}
|
||||
|
||||
// helper function to read a tri-state boolean from config
|
||||
private static bool? GetNullableBooleanValue(NameValueCollection settings, string key) {
|
||||
bool value;
|
||||
return (settings != null && Boolean.TryParse(settings[key], out value)) ? value : (bool?)null;
|
||||
}
|
||||
|
||||
// helper function to read a nullable int from config
|
||||
private static int? GetNullableIntegerValue(NameValueCollection settings, string key) {
|
||||
int value;
|
||||
return (settings != null && int.TryParse(settings[key], out value)) ? value : (int?)null;
|
||||
}
|
||||
|
||||
private static bool _useHostHeaderForRequestUrl;
|
||||
internal static bool UseHostHeaderForRequestUrl {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _useHostHeaderForRequestUrl;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool _allowAnonymousImpersonation;
|
||||
internal static bool AllowAnonymousImpersonation {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _allowAnonymousImpersonation;
|
||||
}
|
||||
}
|
||||
|
||||
// false [default] to allow ScriptResource.axd to serve static files only if they are *.js;
|
||||
// true to allow ScriptResource.axd to serve any static file (bad practice)
|
||||
private static bool _scriptResourceAllowNonJsFiles;
|
||||
internal static bool ScriptResourceAllowNonJsFiles {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _scriptResourceAllowNonJsFiles;
|
||||
}
|
||||
}
|
||||
|
||||
// false [default] to use encrypt+sign for all except Membership and MachineKey public API
|
||||
// true to use encrypt only (dangerous!)
|
||||
private static bool _useLegacyEncryption;
|
||||
internal static bool UseLegacyEncryption {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _useLegacyEncryption;
|
||||
}
|
||||
}
|
||||
|
||||
// false [default] to use encrypt+sign for MachineKey public API
|
||||
// true to use encrypt only for MachineKey public API (dangerous!)
|
||||
private static bool _useLegacyMachineKeyEncryption;
|
||||
internal static bool UseLegacyMachineKeyEncryption {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _useLegacyMachineKeyEncryption;
|
||||
}
|
||||
}
|
||||
|
||||
// false [default] to use secure semantics when generating FormsAuthentication tickets
|
||||
// true to allow ticketCompatibilityMode="Framework20" (dangerous!)
|
||||
private static bool _useLegacyFormsAuthenticationTicketCompatibility;
|
||||
internal static bool UseLegacyFormsAuthenticationTicketCompatibility {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _useLegacyFormsAuthenticationTicketCompatibility;
|
||||
}
|
||||
}
|
||||
|
||||
// false [default] to use a cryptographic hash algorithm when generating the __EVENTVALIDATION field
|
||||
// true to use String.GetHashCode() instead (dangerous!)
|
||||
// more info: DevDiv #233564 (http://vstfdevdiv:8080/DevDiv2/web/wi.aspx?id=233564)
|
||||
private static bool _useLegacyEventValidationCompatibility;
|
||||
internal static bool UseLegacyEventValidationCompatibility {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _useLegacyEventValidationCompatibility;
|
||||
}
|
||||
}
|
||||
|
||||
// false to always enforce EnableViewStateMac=false
|
||||
// true to allow the developer to specify EnableViewStateMac=false (dangerous, leads to RCE!)
|
||||
// null [default] to make the decision based on a registry key
|
||||
// more info: DevDiv #461378 (http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/461378)
|
||||
private static bool? _allowInsecureDeserialization;
|
||||
internal static bool? AllowInsecureDeserialization {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _allowInsecureDeserialization;
|
||||
}
|
||||
}
|
||||
|
||||
// false [default] to use the default heuristic for determining when to suppress __VIEWSTATE MAC validation errors and when to display a YSOD
|
||||
// true to always ---- errors and never show a YSOD
|
||||
private static bool _alwaysIgnoreViewStateValidationErrors;
|
||||
internal static bool AlwaysIgnoreViewStateValidationErrors {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _alwaysIgnoreViewStateValidationErrors;
|
||||
}
|
||||
}
|
||||
|
||||
// false [default] to restrict dangerous characters in any user name passed to native code
|
||||
// true to allow dangerous characters
|
||||
private static bool _allowRelaxedHttpUserName;
|
||||
internal static bool AllowRelaxedHttpUserName {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _allowRelaxedHttpUserName;
|
||||
}
|
||||
}
|
||||
|
||||
// false [default] to encode '&' characters in HttpUtility.JavaScriptStringEncode()
|
||||
// true to not encode '&' characters (bad practice)
|
||||
private static bool _javaScriptDoNotEncodeAmpersand;
|
||||
internal static bool JavaScriptDoNotEncodeAmpersand {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _javaScriptDoNotEncodeAmpersand;
|
||||
}
|
||||
}
|
||||
|
||||
// false [default] to use the updated AspNetSynchronizationContext type (needed for TAP methods)
|
||||
// true to use LegacyAspNetSynchronizationContext (needed for some back-compat scenarios)
|
||||
private static bool _useTaskFriendlySynchronizationContext ;
|
||||
internal static bool UseTaskFriendlySynchronizationContext {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _useTaskFriendlySynchronizationContext ;
|
||||
}
|
||||
}
|
||||
|
||||
// false [default] if the updated AspNetSynchronizationContext type should throw when it encounters invalid operations
|
||||
// true to allow some invalid operations through the system (needed for some back-compat scenarios)
|
||||
// more info: see doc on HttpContext.AllowAsyncDuringSyncStages
|
||||
private static bool _allowAsyncDuringSyncStages;
|
||||
internal static bool AllowAsyncDuringSyncStages {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _allowAsyncDuringSyncStages;
|
||||
}
|
||||
}
|
||||
|
||||
// maximum number of keys a HttpValueCollection, HttpFileCollection or HttpCookieCollection is allowed to have
|
||||
private const int DefaultMaxHttpCollectionKeys = Int32.MaxValue;
|
||||
private static int _maxHttpCollectionKeys = DefaultMaxHttpCollectionKeys;
|
||||
internal static int MaxHttpCollectionKeys {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _maxHttpCollectionKeys;
|
||||
}
|
||||
}
|
||||
|
||||
// maximum number of entries a Json deserialized dictionary is allowed to have
|
||||
private const int DefaultMaxJsonDeserializerMembers = Int32.MaxValue;
|
||||
private static int _maxJsonDeserializerMembers = DefaultMaxJsonDeserializerMembers;
|
||||
internal static int MaxJsonDeserializerMembers {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _maxJsonDeserializerMembers;
|
||||
}
|
||||
}
|
||||
|
||||
// false [default] to call HttpApplication.Dispose() on all HttpApplication instances instantiated by ASP.NET
|
||||
// true to suppress calling HttpApplication.Dispose() on "special" (i.e., associated with App_Start, App_End, etc.) HttpApplication instances
|
||||
// see DevDiv #109006 (http://vstfdevdiv:8080/DevDiv2/web/wi.aspx?id=109006): HttpModules attached to the "Special" HttpApplication instance are not disposed
|
||||
private static bool _doNotDisposeSpecialHttpApplicationInstances;
|
||||
internal static bool DoNotDisposeSpecialHttpApplicationInstances {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _doNotDisposeSpecialHttpApplicationInstances;
|
||||
}
|
||||
}
|
||||
|
||||
// none [default] to use the existing /loging.aspx?ReturnUrl=
|
||||
// <FormsAuthReturnUrlVar> to use /loging.aspx?<FormsAuthReturnUrlVar>=
|
||||
private static string _formsAuthReturnUrlVar;
|
||||
internal static string FormsAuthReturnUrlVar {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _formsAuthReturnUrlVar;
|
||||
}
|
||||
}
|
||||
|
||||
// false [default] to use potentially unsafe System.Xml API's that were in use for 1.0 through 4.0
|
||||
// true to avoid using vulnerable System.Xml API's.
|
||||
private static bool _restrictXmlControls;
|
||||
internal static bool RestrictXmlControls {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _restrictXmlControls;
|
||||
}
|
||||
}
|
||||
|
||||
// false [default] - requires relative url to be more strict
|
||||
// true - use less strict policy
|
||||
private static bool _allowRelaxedRelativeUrl;
|
||||
internal static bool AllowRelaxedRelativeUrl {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _allowRelaxedRelativeUrl;
|
||||
}
|
||||
}
|
||||
|
||||
// false [default] - attempts to re-encode HttpRequest.Url so that it is equivalent to the actual incoming URL
|
||||
// true - does not attempt to re-encode the Url, which could allow the Uri class to perform double-decoding (dangerous!)
|
||||
// See also DevDiv #703232 (http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/703232)
|
||||
private static bool _useLegacyRequestUrlGeneration;
|
||||
internal static bool UseLegacyRequestUrlGeneration {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _useLegacyRequestUrlGeneration;
|
||||
}
|
||||
}
|
||||
|
||||
// false [default] - disallow UTF-7 as an incoming ContentEncoding
|
||||
// true - allow UTF-7 as an incoming ContentEncoding (dangerous!)
|
||||
private static bool _allowUtf7RequestContentEncoding;
|
||||
internal static bool AllowUtf7RequestContentEncoding {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _allowUtf7RequestContentEncoding;
|
||||
}
|
||||
}
|
||||
|
||||
// false [default] - disallow invalid UTF-16 (like unpaired surrogates) when deserializing JSON strings and inside UrlDecode
|
||||
// true - allow malformed strings like "\ud800" and "%ud800" to be deserialized (dangerous!)
|
||||
private static bool _allowRelaxedUnicodeDecoding;
|
||||
internal static bool AllowRelaxedUnicodeDecoding {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _allowRelaxedUnicodeDecoding;
|
||||
}
|
||||
}
|
||||
|
||||
// false - use UrlEncodeUnicode for some URL generation within ASP.NET, which can produce non-compliant results
|
||||
// true - use UTF8 encoding for things like <form action>, which works with modern browsers
|
||||
// defaults to true when targeting >= 4.5.2, otherwise false
|
||||
// See DevDiv #762975 for more information.
|
||||
private static bool _dontUsePercentUUrlEncoding;
|
||||
internal static bool DontUsePercentUUrlEncoding {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _dontUsePercentUUrlEncoding;
|
||||
}
|
||||
}
|
||||
|
||||
// maximum length for UpdatePanel script block
|
||||
private static int _updatePanelMaxScriptLength;
|
||||
internal static int UpdatePanelMaxScriptLength {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _updatePanelMaxScriptLength;
|
||||
}
|
||||
}
|
||||
|
||||
// maximum number of concurrent compilations
|
||||
private static int? _maxConcurrentCompilations;
|
||||
internal static int? MaxConcurrentCompilations {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _maxConcurrentCompilations;
|
||||
}
|
||||
}
|
||||
|
||||
// Controls how deep we look when trying to get a CultureInfo from an Accept-Language header.
|
||||
// For example, a value of 3 with Accept-Language: en-us, en, fr-FR, zh-CN will cause us to
|
||||
// look for "en-us", "en", and "fr-FR" in order, taking the first hit, but we won't look
|
||||
// for "zh-CN" if the first three fail. Setting this value too high could result in DoS.
|
||||
private const int DefaultMaxAcceptLanguageFallbackCount = 3;
|
||||
private static int _maxAcceptLanguageFallbackCount;
|
||||
internal static int MaxAcceptLanguageFallbackCount {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _maxAcceptLanguageFallbackCount;
|
||||
}
|
||||
}
|
||||
|
||||
// false [default]
|
||||
// true to allow
|
||||
private static bool _portableCompilationOutput;
|
||||
internal static bool PortableCompilationOutput {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _portableCompilationOutput;
|
||||
}
|
||||
}
|
||||
|
||||
// null [default]
|
||||
// complete type name as string
|
||||
private static string _portableCompilationOutputSnapshotType;
|
||||
internal static string PortableCompilationOutputSnapshotType {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _portableCompilationOutputSnapshotType;
|
||||
}
|
||||
}
|
||||
|
||||
// null [default]
|
||||
// options
|
||||
private static string _portableCompilationOutputSnapshotTypeOptions;
|
||||
internal static string PortableCompilationOutputSnapshotTypeOptions {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _portableCompilationOutputSnapshotTypeOptions;
|
||||
}
|
||||
}
|
||||
|
||||
// false [default] - allow delayed store of session state item (possibly concurrent access on new session)
|
||||
// true - ensure the session state item is stored before another request is allowed to proceed with the same session
|
||||
private static bool _ensureSessionStateLockedOnFlush;
|
||||
internal static bool EnsureSessionStateLockedOnFlush {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _ensureSessionStateLockedOnFlush;
|
||||
}
|
||||
}
|
||||
|
||||
// false [default] - don't force randomized hash code algorithm. Exisiting behavior
|
||||
// true - use randomized hash code algorithm
|
||||
private static bool _useRandomizedStringHashAlgorithm;
|
||||
internal static bool UseRandomizedStringHashAlgorithm {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _useRandomizedStringHashAlgorithm;
|
||||
}
|
||||
}
|
||||
|
||||
// false - disable async model binding
|
||||
// true - enable async model binding
|
||||
// defaults to true when targeting >= 4.6, otherwise false
|
||||
private static bool _enableAsyncModelBinding;
|
||||
internal static bool EnableAsyncModelBinding {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _enableAsyncModelBinding;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
782
mcs/class/referencesource/System.Web/Util/AppVerifier.cs
Normal file
782
mcs/class/referencesource/System.Web/Util/AppVerifier.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,37 @@
|
||||
namespace System.Web.Util {
|
||||
using System;
|
||||
|
||||
// IMPORTANT: Each error code must be used in *exactly one place* in order to make
|
||||
// diagnosing the failure easier.
|
||||
|
||||
internal enum AppVerifierErrorCode {
|
||||
|
||||
Ok,
|
||||
|
||||
/* ASYNC OPERATIONS */
|
||||
HttpApplicationInstanceWasNull,
|
||||
BeginHandlerDelegateWasNull,
|
||||
AsyncCallbackInvokedMultipleTimes,
|
||||
AsyncCallbackInvokedWithNullParameter,
|
||||
AsyncCallbackGivenAsyncResultWhichWasNotCompleted,
|
||||
AsyncCallbackInvokedSynchronouslyButAsyncResultWasNotMarkedCompletedSynchronously,
|
||||
AsyncCallbackInvokedAsynchronouslyButAsyncResultWasMarkedCompletedSynchronously,
|
||||
AsyncCallbackInvokedWithUnexpectedAsyncResultInstance,
|
||||
AsyncCallbackInvokedAsynchronouslyThenBeginHandlerThrew,
|
||||
BeginHandlerThrewThenAsyncCallbackInvokedAsynchronously,
|
||||
AsyncCallbackInvokedSynchronouslyThenBeginHandlerThrew,
|
||||
AsyncCallbackInvokedWithUnexpectedAsyncResultAsyncState,
|
||||
AsyncCallbackCalledAfterHttpApplicationReassigned,
|
||||
BeginHandlerReturnedNull,
|
||||
BeginHandlerReturnedAsyncResultMarkedCompletedSynchronouslyButWhichWasNotCompleted,
|
||||
BeginHandlerReturnedAsyncResultMarkedCompletedSynchronouslyButAsyncCallbackNeverCalled,
|
||||
BeginHandlerReturnedUnexpectedAsyncResultInstance,
|
||||
BeginHandlerReturnedUnexpectedAsyncResultAsyncState,
|
||||
SyncContextSendOrPostCalledAfterRequestCompleted,
|
||||
SyncContextSendOrPostCalledBetweenNotifications,
|
||||
SyncContextPostCalledInNestedNotification,
|
||||
RequestNotificationCompletedSynchronouslyWithNotificationContextPending,
|
||||
NotificationContextHasChangedAfterSynchronouslyProcessingNotification,
|
||||
PendingProcessRequestNotificationStatusAfterCompletingNestedNotification
|
||||
}
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
namespace System.Web.Util {
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
// Thrown when the AppVerifier fails an assert.
|
||||
|
||||
// This type is used solely as a support / diagnostics tool and will never appear over the normal course of an application.
|
||||
// Specifically, it will never cross an AppDomain boundary, and we don't want to mark it as [Serializable] since that is
|
||||
// essentially a public contract, and the AppVerifier feature has no public API surface. We want to retain the ability to
|
||||
// change this feature on a whim without risk of breaking anybody.
|
||||
[SuppressMessage("Microsoft.Usage", "CA2237:MarkISerializableTypesWithSerializable", Justification = "Doesn't need to be serializable.")]
|
||||
internal sealed class AppVerifierException : Exception {
|
||||
|
||||
private readonly AppVerifierErrorCode _errorCode;
|
||||
|
||||
public AppVerifierException(AppVerifierErrorCode errorCode, string message)
|
||||
: base(message) {
|
||||
|
||||
_errorCode = errorCode;
|
||||
}
|
||||
|
||||
private AppVerifierException(SerializationInfo info, StreamingContext context) : base(info, context) { }
|
||||
|
||||
public AppVerifierErrorCode ErrorCode {
|
||||
get {
|
||||
return _errorCode;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,164 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="ArglessEventHandlerProxy.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace System.Web.Util {
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Security.Permissions;
|
||||
using System.Security;
|
||||
|
||||
/*
|
||||
* Proxy that provides EventHandler and redirects it to arg-less method on the given object
|
||||
*/
|
||||
internal class ArglessEventHandlerProxy {
|
||||
private Object _target;
|
||||
private MethodInfo _arglessMethod;
|
||||
|
||||
internal ArglessEventHandlerProxy(Object target, MethodInfo arglessMethod) {
|
||||
Debug.Assert(arglessMethod.GetParameters().Length == 0);
|
||||
|
||||
_target = target;
|
||||
_arglessMethod = arglessMethod;
|
||||
}
|
||||
|
||||
[ReflectionPermission(SecurityAction.Assert, Flags=ReflectionPermissionFlag.RestrictedMemberAccess)]
|
||||
internal void Callback(Object sender, EventArgs e) {
|
||||
_arglessMethod.Invoke(_target, new Object[0]);
|
||||
}
|
||||
|
||||
internal EventHandler Handler {
|
||||
get {
|
||||
return new EventHandler(Callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal delegate void VoidMethod();
|
||||
|
||||
internal class CalliEventHandlerDelegateProxy {
|
||||
private delegate void ParameterlessDelegate();
|
||||
private delegate void ParameterfulDelegate(object sender, EventArgs e);
|
||||
|
||||
private IntPtr _functionPointer;
|
||||
private Object _target;
|
||||
private bool _argless;
|
||||
|
||||
internal CalliEventHandlerDelegateProxy(Object target, IntPtr functionPointer, bool argless) {
|
||||
_argless = argless;
|
||||
_target = target;
|
||||
_functionPointer = functionPointer;
|
||||
}
|
||||
|
||||
internal void Callback(Object sender, EventArgs e) {
|
||||
if (_argless) {
|
||||
ParameterlessDelegate del = FastDelegateCreator<ParameterlessDelegate>.BindTo(_target, _functionPointer);
|
||||
del();
|
||||
}
|
||||
else {
|
||||
ParameterfulDelegate del = FastDelegateCreator<ParameterfulDelegate>.BindTo(_target, _functionPointer);
|
||||
del(sender, e);
|
||||
}
|
||||
}
|
||||
|
||||
internal EventHandler Handler {
|
||||
get {
|
||||
return new EventHandler(Callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if LCG_Implementation
|
||||
internal delegate void ArglessMethod(IntPtr methodPtr, Object target);
|
||||
internal delegate void EventArgMethod(IntPtr methodPtr, Object target, Object source, EventArgs e);
|
||||
|
||||
internal class CalliHelper {
|
||||
internal static ArglessMethod ArglessFunctionCaller;
|
||||
internal static EventArgMethod EventArgFunctionCaller;
|
||||
|
||||
// Make sure we have reflection permission to use ReflectionEmit and access method
|
||||
[ReflectionPermission(SecurityAction.Assert, Flags = ReflectionPermissionFlag.ReflectionEmit | ReflectionPermissionFlag.MemberAccess)]
|
||||
static CalliHelper() {
|
||||
// generate void(void) calli
|
||||
DynamicMethod dm = new DynamicMethod("void_calli",
|
||||
typeof(void),
|
||||
new Type[] { typeof(IntPtr) /* function ptr */, typeof(Object) /* target */},
|
||||
typeof(CalliHelper).Module);
|
||||
ILGenerator ilg = dm.GetILGenerator();
|
||||
|
||||
ilg.Emit(OpCodes.Ldarg_1);
|
||||
ilg.Emit(OpCodes.Ldarg_0);
|
||||
ilg.EmitCalli(OpCodes.Calli, CallingConventions.HasThis, typeof(void), new Type[0], null);
|
||||
ilg.Emit(OpCodes.Ret);
|
||||
ArglessFunctionCaller = (ArglessMethod)dm.CreateDelegate(typeof(ArglessMethod));
|
||||
|
||||
// generate void(Object, EventArgs) calli
|
||||
dm = new DynamicMethod("eventarg_calli",
|
||||
typeof(void),
|
||||
new Type[] { typeof(IntPtr) /* function ptr */, typeof(Object) /* target */, typeof(Object) /* sender */, typeof(EventArgs) },
|
||||
typeof(CalliHelper).Module);
|
||||
ilg = dm.GetILGenerator();
|
||||
|
||||
ilg.Emit(OpCodes.Ldarg_1);
|
||||
ilg.Emit(OpCodes.Ldarg_2);
|
||||
ilg.Emit(OpCodes.Ldarg_3);
|
||||
ilg.Emit(OpCodes.Ldarg_0);
|
||||
ilg.EmitCalli(OpCodes.Calli, CallingConventions.HasThis, typeof(void), new Type[] { typeof(object) /* sender */, typeof(EventArgs) }, null);
|
||||
ilg.Emit(OpCodes.Ret);
|
||||
EventArgFunctionCaller = (EventArgMethod)dm.CreateDelegate(typeof(EventArgMethod));
|
||||
}
|
||||
}
|
||||
#endif //LCG_Implementation
|
||||
|
||||
#if Reflection_Emit_Implementation
|
||||
internal delegate void ArglessMethod(IntPtr methodPtr, Object target);
|
||||
internal delegate void EventArgMethod(IntPtr methodPtr, Object target, Object source, EventArgs e);
|
||||
|
||||
internal class CalliHelper {
|
||||
|
||||
internal static ArglessMethod ArglessFunctionCaller;
|
||||
internal static EventArgMethod EventArgFunctionCaller;
|
||||
|
||||
// Make sure we have reflection permission to use ReflectionEmit and access method
|
||||
[ReflectionPermission(SecurityAction.Assert, Flags = ReflectionPermissionFlag.ReflectionEmit | ReflectionPermissionFlag.MemberAccess)]
|
||||
static CalliHelper() {
|
||||
|
||||
AssemblyName an = new AssemblyName("CalliHelper");
|
||||
AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
|
||||
ModuleBuilder mb = ab.DefineDynamicModule("CalliHelper.dll");
|
||||
|
||||
ConstructorInfo ci = typeof(CLSCompliantAttribute).GetConstructor(new Type[] { typeof(bool) });
|
||||
CustomAttributeBuilder cb = new CustomAttributeBuilder(ci, new object[] { true });
|
||||
mb.SetCustomAttribute(cb);
|
||||
|
||||
TypeBuilder tb = mb.DefineType("System.Web.Util.CalliHelper", TypeAttributes.NotPublic | TypeAttributes.Sealed);
|
||||
MethodBuilder methb = tb.DefineMethod("EventArgMethod", MethodAttributes.Assembly | MethodAttributes.Static, typeof(void), new Type[] { typeof(IntPtr), typeof(object), typeof(object), typeof(EventArgs) });
|
||||
ILGenerator ilg = methb.GetILGenerator();
|
||||
|
||||
ilg.Emit(OpCodes.Ldarg_1);
|
||||
ilg.Emit(OpCodes.Ldarg_2);
|
||||
ilg.Emit(OpCodes.Ldarg_3);
|
||||
ilg.Emit(OpCodes.Ldarg_0);
|
||||
ilg.EmitCalli(OpCodes.Calli, CallingConventions.HasThis, typeof(void), new Type[] { typeof(object), typeof(EventArgs) }, null);
|
||||
ilg.Emit(OpCodes.Ret);
|
||||
|
||||
methb = tb.DefineMethod("ArglessMethod", MethodAttributes.Assembly | MethodAttributes.Static, typeof(void), new Type[] { typeof (IntPtr), typeof(object) });
|
||||
ilg = methb.GetILGenerator();
|
||||
|
||||
ilg.Emit(OpCodes.Ldarg_1);
|
||||
ilg.Emit(OpCodes.Ldarg_0);
|
||||
ilg.EmitCalli(OpCodes.Calli, CallingConventions.HasThis, typeof(void), new Type[0], null);
|
||||
ilg.Emit(OpCodes.Ret);
|
||||
|
||||
Type t = tb.CreateType();
|
||||
ArglessFunctionCaller = (ArglessMethod)Delegate.CreateDelegate(typeof(ArglessMethod), t, "ArglessMethod", true);
|
||||
EventArgFunctionCaller = (EventArgMethod)Delegate.CreateDelegate(typeof(EventArgMethod), t, "EventArgMethod", true);
|
||||
|
||||
//ab.Save("CalliHelper.dll");
|
||||
}
|
||||
}
|
||||
#endif // Reflection_Emit_Implementation
|
||||
}
|
895
mcs/class/referencesource/System.Web/Util/AspCompat.cs
Normal file
895
mcs/class/referencesource/System.Web/Util/AspCompat.cs
Normal file
File diff suppressed because it is too large
Load Diff
31
mcs/class/referencesource/System.Web/Util/AssemblyUtil.cs
Normal file
31
mcs/class/referencesource/System.Web/Util/AssemblyUtil.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="AssemblyUtil.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace System.Web.Util {
|
||||
internal static class AssemblyUtil {
|
||||
private const string _emptyFileVersion = "0.0.0.0";
|
||||
|
||||
public static string GetAssemblyFileVersion(Assembly assembly) {
|
||||
AssemblyFileVersionAttribute[] attributes =
|
||||
(AssemblyFileVersionAttribute[])assembly.GetCustomAttributes(typeof(AssemblyFileVersionAttribute), false);
|
||||
|
||||
string version;
|
||||
if (attributes.Length > 0) {
|
||||
version = attributes[0].Version;
|
||||
if (String.IsNullOrEmpty(version)) {
|
||||
version = _emptyFileVersion;
|
||||
}
|
||||
}
|
||||
else {
|
||||
version = _emptyFileVersion;
|
||||
}
|
||||
return version;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="BinaryCompatibility.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace System.Web.Util {
|
||||
using System;
|
||||
using System.Runtime.Versioning;
|
||||
|
||||
// This class contains utility methods that mimic the mscorlib internal System.Runtime.Versioning.BinaryCompatibility type.
|
||||
|
||||
internal sealed class BinaryCompatibility {
|
||||
|
||||
// We need to use this AppDomain key instead of AppDomainSetup.TargetFrameworkName since we don't want applications
|
||||
// which happened to set TargetFrameworkName and are calling into ASP.NET APIs to suddenly start getting new behaviors.
|
||||
internal const string TargetFrameworkKey = "ASPNET_TARGETFRAMEWORK";
|
||||
|
||||
// quick accessor for the current AppDomain's instance
|
||||
public static readonly BinaryCompatibility Current = new BinaryCompatibility(AppDomain.CurrentDomain.GetData(TargetFrameworkKey) as FrameworkName);
|
||||
|
||||
public BinaryCompatibility(FrameworkName frameworkName) {
|
||||
// parse version from FrameworkName, otherwise use a default value
|
||||
Version version = VersionUtil.FrameworkDefault;
|
||||
if (frameworkName != null && frameworkName.Identifier == ".NETFramework") {
|
||||
version = frameworkName.Version;
|
||||
}
|
||||
|
||||
TargetFramework = version;
|
||||
TargetsAtLeastFramework45 = (version >= VersionUtil.Framework45);
|
||||
TargetsAtLeastFramework451 = (version >= VersionUtil.Framework451);
|
||||
TargetsAtLeastFramework452 = (version >= VersionUtil.Framework452);
|
||||
TargetsAtLeastFramework46 = (version >= VersionUtil.Framework46);
|
||||
TargetsAtLeastFramework461 = (version >= VersionUtil.Framework461);
|
||||
}
|
||||
|
||||
public bool TargetsAtLeastFramework45 { get; private set; }
|
||||
public bool TargetsAtLeastFramework451 { get; private set; }
|
||||
public bool TargetsAtLeastFramework452 { get; private set; }
|
||||
public bool TargetsAtLeastFramework46 { get; private set; }
|
||||
public bool TargetsAtLeastFramework461 { get; private set; }
|
||||
|
||||
public Version TargetFramework { get; private set; }
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,102 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="CancellationTokenHelper.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace System.Web.Util {
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
// Helper class for dealing with CancellationToken instances. Our Cancel and Dispose methods
|
||||
// are fully thread-safe and will never block or throw, while a normal CancellationTokenSource
|
||||
// doesn't make these guarantees.
|
||||
|
||||
internal sealed class CancellationTokenHelper : IDisposable {
|
||||
|
||||
private const int STATE_CREATED = 0;
|
||||
private const int STATE_CANCELING = 1;
|
||||
private const int STATE_CANCELED = 2;
|
||||
private const int STATE_DISPOSING = 3;
|
||||
private const int STATE_DISPOSED = 4; // terminal state
|
||||
|
||||
// A CancellationTokenHelper which is already marked as disposed; useful for avoiding
|
||||
// allocations of CancellationTokenHelper instances which are never observed.
|
||||
internal static readonly CancellationTokenHelper StaticDisposed = GetStaticDisposedHelper();
|
||||
|
||||
private readonly CancellationTokenSource _cts = new CancellationTokenSource();
|
||||
private int _state;
|
||||
|
||||
public CancellationTokenHelper(bool canceled) {
|
||||
if (canceled) {
|
||||
_cts.Cancel();
|
||||
}
|
||||
_state = (canceled) ? STATE_CANCELED : STATE_CREATED;
|
||||
}
|
||||
|
||||
internal bool IsCancellationRequested {
|
||||
get { return _cts.IsCancellationRequested; }
|
||||
}
|
||||
|
||||
internal CancellationToken Token {
|
||||
get { return _cts.Token; }
|
||||
}
|
||||
|
||||
// Cancels the token.
|
||||
public void Cancel() {
|
||||
if (Interlocked.CompareExchange(ref _state, STATE_CANCELING, STATE_CREATED) == STATE_CREATED) {
|
||||
// Only allow cancellation if the token hasn't yet been canceled or disposed.
|
||||
// Cancel on a ThreadPool thread so that we can release the original thread back to IIS.
|
||||
// We can use UnsafeQUWI to avoid an extra ExecutionContext capture since CancellationToken already captures it.
|
||||
ThreadPool.UnsafeQueueUserWorkItem(_ => {
|
||||
try {
|
||||
_cts.Cancel();
|
||||
}
|
||||
catch {
|
||||
// ---- all exceptions to avoid killing the worker process.
|
||||
}
|
||||
finally {
|
||||
if (Interlocked.CompareExchange(ref _state, STATE_CANCELED, STATE_CANCELING) == STATE_DISPOSING) {
|
||||
// A call to Dispose() came in on another thread while we were in the middle of a cancel
|
||||
// operation. That thread will no-op, so we'll dispose of it here.
|
||||
_cts.Dispose();
|
||||
Interlocked.Exchange(ref _state, STATE_DISPOSED);
|
||||
}
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
|
||||
// Disposes of the token.
|
||||
public void Dispose() {
|
||||
// Only allow a single call to Dispose.
|
||||
int originalState = Interlocked.Exchange(ref _state, STATE_DISPOSING);
|
||||
switch (originalState) {
|
||||
case STATE_CREATED:
|
||||
case STATE_CANCELED:
|
||||
// If Cancel() hasn't yet been called or has already run to completion,
|
||||
// the underlying CTS guarantees that the Dispose method won't block
|
||||
// or throw, so we can just call it directly.
|
||||
_cts.Dispose();
|
||||
Interlocked.Exchange(ref _state, STATE_DISPOSED);
|
||||
break;
|
||||
|
||||
case STATE_DISPOSED:
|
||||
// If the object was already disposed, we need to reset the flag here
|
||||
// since we accidentally blew it away with the original Exchange.
|
||||
Interlocked.Exchange(ref _state, STATE_DISPOSED);
|
||||
break;
|
||||
|
||||
// Otherwise, the object is already canceling or disposing, so the
|
||||
// other thread will handle the call to Dispose().
|
||||
}
|
||||
}
|
||||
|
||||
private static CancellationTokenHelper GetStaticDisposedHelper() {
|
||||
CancellationTokenHelper helper = new CancellationTokenHelper(false);
|
||||
helper.Dispose();
|
||||
return helper;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
97
mcs/class/referencesource/System.Web/Util/CodePageUtils.cs
Normal file
97
mcs/class/referencesource/System.Web/Util/CodePageUtils.cs
Normal file
@@ -0,0 +1,97 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="CodePageUtils.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace System.Web.Util {
|
||||
using System.Collections;
|
||||
|
||||
//
|
||||
// Utility class to help with determining if a given code page
|
||||
// is ASCII compatible (preserves 0-127 Unicode characters as is)
|
||||
//
|
||||
|
||||
internal static class CodePageUtils {
|
||||
|
||||
/* The following array of ASCII compatible code pages
|
||||
is generated by running this code on a machine that
|
||||
has _many_ codepages installed:
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Text;
|
||||
public class qq {
|
||||
public static void Main(string[] args) {
|
||||
ArrayList list = new ArrayList();
|
||||
byte[] bb = new byte[128]; for (int i = 0; i < 128; i++) bb[i] = (byte)i;
|
||||
String asciiString = Encoding.ASCII.GetString(bb);
|
||||
for (int i = 1; i < 100000; i++) {
|
||||
try {
|
||||
Encoding e = Encoding.GetEncoding(i);
|
||||
byte[] xx = e.GetBytes(asciiString);
|
||||
if (xx.Length == 128) {
|
||||
bool good = true;
|
||||
for (int j = 0; j < 128; j++) { if (bb[j] != xx[j]) { good = false; break; } }
|
||||
if (good) list.Add(i);
|
||||
}
|
||||
}
|
||||
catch {}
|
||||
}
|
||||
int n = list.Count;
|
||||
Console.Write("private const int[] _asciiCompatCodePages = new int[" + n + "] {\r\n ");
|
||||
for (int i = 0; i < n; i++) {
|
||||
Console.Write("{0,5}", list[i]);
|
||||
if (i < n-1) Console.Write(", ");
|
||||
if (((i+1) % 10) == 0) Console.Write("\r\n ");
|
||||
}
|
||||
Console.Write("\r\n};\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
private static int[] _asciiCompatCodePages = new int[79] {
|
||||
437, 708, 720, 737, 775, 850, 852, 855, 857, 858,
|
||||
860, 861, 862, 863, 864, 865, 866, 869, 874, 932,
|
||||
936, 949, 950, 1250, 1251, 1252, 1253, 1254, 1255, 1256,
|
||||
1257, 1258, 1361, 10000, 10001, 10002, 10003, 10004, 10005, 10006,
|
||||
10007, 10008, 10010, 10017, 10029, 10079, 10081, 10082, 20000, 20001,
|
||||
20002, 20003, 20004, 20005, 20127, 20866, 20932, 20936, 20949, 21866,
|
||||
28591, 28592, 28593, 28594, 28595, 28596, 28597, 28598, 28599, 28605,
|
||||
38598, 50220, 50221, 50222, 50225, 50227, 51932, 51949, 65001
|
||||
};
|
||||
|
||||
internal /*public*/ static bool IsAsciiCompatibleCodePage(int codepage) {
|
||||
//alternatives to binary search considered
|
||||
//Hashtable: static initialization increases startup up, perf relative
|
||||
//Byte array would consume ~8K, but lookups constant
|
||||
//with 80 entries, binary search limited to 7 indexes into array
|
||||
int lo = 0;
|
||||
int hi = 78;
|
||||
while(lo <= hi) {
|
||||
int i = (lo + hi) >> 1;
|
||||
int c;
|
||||
c = _asciiCompatCodePages[i] - codepage;
|
||||
if (c == 0) return true; //i is the index of the item
|
||||
if (c < 0) {
|
||||
lo = i + 1;
|
||||
}
|
||||
else {
|
||||
hi = i - 1;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
//lo is the index of the item immediately after
|
||||
//~lo returned in some implementations for false indicator with additional info
|
||||
}
|
||||
|
||||
internal const int CodePageUT8 = 65001;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
54
mcs/class/referencesource/System.Web/Util/CountdownTask.cs
Normal file
54
mcs/class/referencesource/System.Web/Util/CountdownTask.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="CountdownTask.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace System.Web.Util {
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
// This class is similar to CountdownEvent, but it uses Task under the covers
|
||||
// instead of ManualResetEvent. When the internal counter hits zero, the Task
|
||||
// is marked as complete.
|
||||
//
|
||||
// This type is thread-safe. Error checking is not performed in RET builds.
|
||||
|
||||
internal sealed class CountdownTask {
|
||||
|
||||
private int _pendingCount;
|
||||
private readonly TaskCompletionSource<object> _tcs = new TaskCompletionSource<object>();
|
||||
|
||||
public CountdownTask(int initialCount) {
|
||||
AddCount(initialCount);
|
||||
}
|
||||
|
||||
public int CurrentCount {
|
||||
get { return _pendingCount; }
|
||||
}
|
||||
|
||||
public Task Task {
|
||||
get { return _tcs.Task; }
|
||||
}
|
||||
|
||||
private void AddCount(int delta) {
|
||||
int newCount = Interlocked.Add(ref _pendingCount, delta);
|
||||
Debug.Assert(newCount >= 0, "The counter should never hit a negative value.");
|
||||
|
||||
if (newCount == 0) {
|
||||
bool success = _tcs.TrySetResult(null);
|
||||
Debug.Assert(success, "TrySetResult shouldn't have been already called.");
|
||||
}
|
||||
}
|
||||
|
||||
public void MarkOperationCompleted() {
|
||||
AddCount(-1);
|
||||
}
|
||||
|
||||
public void MarkOperationPending() {
|
||||
AddCount(+1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
67
mcs/class/referencesource/System.Web/Util/CultureUtil.cs
Normal file
67
mcs/class/referencesource/System.Web/Util/CultureUtil.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="CultureUtil.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace System.Web.Util {
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
// This class contains helper methods for obtaining a CultureInfo instance from a list of candidates.
|
||||
|
||||
internal static class CultureUtil {
|
||||
|
||||
// Given a single culture name, attempts to turn it into a CultureInfo.
|
||||
// If 'requireSpecific' is set, this method attempts to return an object where IsNeutral = false.
|
||||
public static CultureInfo CreateReadOnlyCulture(string cultureName, bool requireSpecific) {
|
||||
if (requireSpecific) {
|
||||
return HttpServerUtility.CreateReadOnlySpecificCultureInfo(cultureName);
|
||||
}
|
||||
else {
|
||||
return HttpServerUtility.CreateReadOnlyCultureInfo(cultureName);
|
||||
}
|
||||
}
|
||||
|
||||
// Given a list of culture names, loop through them until we find one we understand.
|
||||
// We expect 'cultureNames' to be the raw Accept-Languages header value, as we'll strip q-values.
|
||||
// Otherwise equivalent to the single-element overload.
|
||||
public static CultureInfo CreateReadOnlyCulture(string[] cultureNames, bool requireSpecific) {
|
||||
return ExtractCultureImpl(cultureNames, requireSpecific, AppSettings.MaxAcceptLanguageFallbackCount);
|
||||
}
|
||||
|
||||
// for unit testing, uses 'maxCount' instead of the <appSettings> switch
|
||||
internal static CultureInfo ExtractCultureImpl(string[] cultureNames, bool requireSpecific, int maxCount) {
|
||||
int lastIndex = Math.Min(cultureNames.Length, maxCount) - 1;
|
||||
|
||||
for (int i = 0; i < cultureNames.Length; i++) {
|
||||
string candidate = StripQValue(cultureNames[i]);
|
||||
|
||||
try {
|
||||
return CreateReadOnlyCulture(candidate, requireSpecific);
|
||||
}
|
||||
catch (CultureNotFoundException) {
|
||||
// If this is the last iteration before giving up, let the exception propagate upward.
|
||||
// Otherwise just ---- and move on to the next candidate.
|
||||
if (i == lastIndex) {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Given an input "foo;q=xx", returns "foo".
|
||||
private static string StripQValue(string input) {
|
||||
if (input != null) {
|
||||
int indexOfSemicolon = input.IndexOf(';');
|
||||
if (indexOfSemicolon >= 0) {
|
||||
return input.Substring(0, indexOfSemicolon);
|
||||
}
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
52
mcs/class/referencesource/System.Web/Util/DateTimeUtil.cs
Normal file
52
mcs/class/referencesource/System.Web/Util/DateTimeUtil.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="FileChangesMonitor.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace System.Web.Util {
|
||||
|
||||
using System;
|
||||
|
||||
internal sealed class DateTimeUtil {
|
||||
private DateTimeUtil() {}
|
||||
|
||||
const long FileTimeOffset = 504911232000000000;
|
||||
static readonly DateTime MinValuePlusOneDay = DateTime.MinValue.AddDays(1);
|
||||
static readonly DateTime MaxValueMinusOneDay = DateTime.MaxValue.AddDays(-1);
|
||||
|
||||
static internal DateTime FromFileTimeToUtc(long filetime) {
|
||||
long universalTicks = filetime + FileTimeOffset;
|
||||
// Dev10 733288: Caching: behavior change for CacheDependency when using UseMemoryCache=1
|
||||
// ObjectCacheHost converts DateTime to a DateTimeOffset, and the conversion requires
|
||||
// that DateTimeKind be set correctly
|
||||
return new DateTime(universalTicks, DateTimeKind.Utc);
|
||||
}
|
||||
|
||||
static internal DateTime ConvertToUniversalTime(DateTime localTime) {
|
||||
if (localTime < MinValuePlusOneDay) {
|
||||
return DateTime.MinValue;
|
||||
}
|
||||
|
||||
if (localTime > MaxValueMinusOneDay) {
|
||||
return DateTime.MaxValue;
|
||||
}
|
||||
|
||||
return localTime.ToUniversalTime();
|
||||
}
|
||||
|
||||
static internal DateTime ConvertToLocalTime(DateTime utcTime) {
|
||||
if (utcTime < MinValuePlusOneDay) {
|
||||
return DateTime.MinValue;
|
||||
}
|
||||
|
||||
if (utcTime > MaxValueMinusOneDay) {
|
||||
return DateTime.MaxValue;
|
||||
}
|
||||
|
||||
return utcTime.ToLocalTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
1097
mcs/class/referencesource/System.Web/Util/Debug.cs
Normal file
1097
mcs/class/referencesource/System.Web/Util/Debug.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,33 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="DisposableAction.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace System.Web.Util {
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
// Helper class for wrapping a continuation inside an IDisposable.
|
||||
// This class is thread-safe.
|
||||
|
||||
internal sealed class DisposableAction : IDisposable {
|
||||
|
||||
public static readonly DisposableAction Empty = new DisposableAction(null);
|
||||
|
||||
private Action _disposeAction;
|
||||
|
||||
public DisposableAction(Action disposeAction) {
|
||||
_disposeAction = disposeAction;
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
// Interlocked allows the continuation to be executed only once
|
||||
Action continuation = Interlocked.Exchange(ref _disposeAction, null);
|
||||
if (continuation != null) {
|
||||
continuation();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="DoNotResetAttribute.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace System.Web.Util {
|
||||
using System;
|
||||
|
||||
// If this attribute is applied to a field, it will not be reset by a call to ReflectionUtil.Reset().
|
||||
|
||||
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
|
||||
internal sealed class DoNotResetAttribute : Attribute {
|
||||
}
|
||||
|
||||
}
|
65
mcs/class/referencesource/System.Web/Util/DoubleLink.cs
Normal file
65
mcs/class/referencesource/System.Web/Util/DoubleLink.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="DoubleLink.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* DoubleLink
|
||||
*
|
||||
* Copyright (c) 1998-1999, Microsoft Corporation
|
||||
*
|
||||
*/
|
||||
|
||||
namespace System.Web.Util {
|
||||
using System.Runtime.Serialization.Formatters;
|
||||
|
||||
internal class DoubleLink {
|
||||
internal DoubleLink _next, _prev;
|
||||
internal Object Item;
|
||||
|
||||
internal DoubleLink() {
|
||||
_next = _prev = this;
|
||||
}
|
||||
internal DoubleLink(Object item) : this() {
|
||||
this.Item = item;
|
||||
}
|
||||
internal DoubleLink Next {get {return _next;}}
|
||||
|
||||
internal void InsertAfter(DoubleLink after) {
|
||||
this._prev = after;
|
||||
this._next = after._next;
|
||||
after._next = this;
|
||||
this._next._prev = this;
|
||||
}
|
||||
|
||||
internal void InsertBefore(DoubleLink before) {
|
||||
this._prev = before._prev;
|
||||
this._next = before;
|
||||
before._prev = this;
|
||||
this._prev._next = this;
|
||||
}
|
||||
|
||||
internal void Remove() {
|
||||
this._prev._next = this._next;
|
||||
this._next._prev = this._prev;
|
||||
_next = _prev = this;
|
||||
}
|
||||
|
||||
#if DBG
|
||||
internal virtual void DebugValidate() {
|
||||
Debug.CheckValid(this._next != this || this._prev == this, "Invalid link");
|
||||
}
|
||||
|
||||
internal virtual string DebugDescription(string indent) {
|
||||
string desc;
|
||||
|
||||
desc = indent + "_next=" + _next + ", _prev=" + _prev + "\nItem=";
|
||||
desc += Debug.GetDescription(Item, indent + " ");
|
||||
|
||||
return desc;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
114
mcs/class/referencesource/System.Web/Util/DoubleLinkList.cs
Normal file
114
mcs/class/referencesource/System.Web/Util/DoubleLinkList.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="DoubleLinkList.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* DoubleLinkList
|
||||
*
|
||||
* Copyright (c) 1998-1999, Microsoft Corporation
|
||||
*
|
||||
*/
|
||||
|
||||
namespace System.Web.Util {
|
||||
using System.Text;
|
||||
using System.Runtime.Serialization.Formatters;
|
||||
|
||||
internal class DoubleLinkList : DoubleLink {
|
||||
internal DoubleLinkList() {
|
||||
}
|
||||
|
||||
internal bool IsEmpty() {
|
||||
return _next == this;
|
||||
}
|
||||
|
||||
internal virtual void InsertHead(DoubleLink entry) {
|
||||
entry.InsertAfter(this);
|
||||
}
|
||||
internal virtual void InsertTail(DoubleLink entry) {
|
||||
entry.InsertBefore(this);
|
||||
}
|
||||
|
||||
internal DoubleLinkListEnumerator GetEnumerator() {
|
||||
return new DoubleLinkListEnumerator(this);
|
||||
}
|
||||
|
||||
#if DBG
|
||||
internal override void DebugValidate() {
|
||||
DoubleLink l1, l2;
|
||||
|
||||
base.DebugValidate();
|
||||
|
||||
/*
|
||||
* Detect loops by moving one pointer forward 2 for every 1
|
||||
* of the other.
|
||||
*/
|
||||
|
||||
l1 = l2 = this;
|
||||
for (;;) {
|
||||
/* move l2 forward */
|
||||
l2 = l2._next;
|
||||
if (l2 == this)
|
||||
break;
|
||||
|
||||
Debug.CheckValid(l2 != l1, "Invalid loop in list, first move.");
|
||||
l2.DebugValidate();
|
||||
|
||||
/* move l2 forward again */
|
||||
l2 = l2._next;
|
||||
if (l2 == this)
|
||||
break;
|
||||
|
||||
Debug.CheckValid(l2 != l1, "Invalid loop in list, second move.");
|
||||
l2.DebugValidate();
|
||||
|
||||
/* move l1 forward */
|
||||
l1 = l1._next;
|
||||
}
|
||||
}
|
||||
|
||||
internal override string DebugDescription(String indent) {
|
||||
string desc;
|
||||
DoubleLinkListEnumerator lenum;
|
||||
int c;
|
||||
StringBuilder sb;
|
||||
string i2 = indent + " ";
|
||||
|
||||
if (IsEmpty()) {
|
||||
desc = indent + "DoubleLinkList is empty\n";
|
||||
}
|
||||
else {
|
||||
c = Length;
|
||||
|
||||
sb = new StringBuilder(indent + "DoubleLinkList has " + c + " entries.\n");
|
||||
lenum = GetEnumerator();
|
||||
while (lenum.MoveNext()) {
|
||||
sb.Append(Debug.GetDescription(lenum.GetDoubleLink(), i2));
|
||||
}
|
||||
|
||||
desc = sb.ToString();
|
||||
}
|
||||
|
||||
return desc;
|
||||
}
|
||||
#endif
|
||||
|
||||
internal int Length {
|
||||
get {
|
||||
DoubleLinkListEnumerator lenum;
|
||||
int c;
|
||||
|
||||
Debug.Validate(this);
|
||||
|
||||
c = 0;
|
||||
lenum = GetEnumerator();
|
||||
while (lenum.MoveNext()) {
|
||||
c++;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="DoubleLinkListEnumerator.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* DoubleLinkList
|
||||
*
|
||||
* Copyright (c) 1998-1999, Microsoft Corporation
|
||||
*
|
||||
*/
|
||||
|
||||
namespace System.Web.Util {
|
||||
using System.Runtime.Serialization.Formatters;
|
||||
using System.Collections;
|
||||
|
||||
internal class DoubleLinkListEnumerator : IEnumerator {
|
||||
private DoubleLinkList _list;
|
||||
private DoubleLink _current;
|
||||
|
||||
internal DoubleLinkListEnumerator(DoubleLinkList list) {
|
||||
_list = list;
|
||||
_current = list;
|
||||
}
|
||||
|
||||
public void Reset() {
|
||||
_current = _list;
|
||||
}
|
||||
|
||||
public bool MoveNext() {
|
||||
if (_current.Next == _list) {
|
||||
_current = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
_current = _current.Next;
|
||||
return true;
|
||||
}
|
||||
|
||||
public Object Current {
|
||||
get {
|
||||
if (_current == null || _current == _list)
|
||||
throw new InvalidOperationException();
|
||||
return _current.Item;
|
||||
}
|
||||
}
|
||||
|
||||
internal DoubleLink GetDoubleLink() {
|
||||
return _current;
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user