CookielessHelper.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / xsp / System / Web / Security / CookielessHelper.cs / 1305376 / CookielessHelper.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

/* 
 * CookielessHelper class 
 *
 * Copyright (c) 1999 Microsoft Corporation 
 */

namespace System.Web.Security {
    using System; 
    using System.Web;
    using System.Text; 
    using System.Web.Configuration; 
    using System.Web.Caching;
    using System.Collections; 
    using System.Web.Util;
    using System.Security.Cryptography;
    using System.Security.Principal;
    using System.Threading; 
    using System.Globalization;
    using System.Security.Permissions; 
 
    internal sealed class CookielessHelperClass {
        //////////////////////////////////////////////////////////////////////// 
        ////////////////////////////////////////////////////////////////////////
        internal CookielessHelperClass(HttpContext context) {
            _Context = context;
        } 
        private void Init()
        { 
            if (_Headers != null) 
                return;
            if (_Headers == null) 
                GetCookielessValuesFromHeader();
            if (_Headers == null)
                RemoveCookielessValuesFromPath();
            if (_Headers == null) 
                _Headers = String.Empty;
            _OriginalHeaders = _Headers; 
        } 

        private void GetCookielessValuesFromHeader() 
        {
            _Headers = _Context.Request.Headers[COOKIELESS_SESSION_FILTER_HEADER];

            // Dev10 775061 Regression: FormsAuthentication.SignOut does not redirect if cookieless forms authentication is enabled. 
            // HttpContext.Init calls RemoveCookielessValues directly so we need to also store the OriginalHeaders for Redirect
            // calling Init directly causes regressions 
            _OriginalHeaders = _Headers; 
            if (!String.IsNullOrEmpty(_Headers)) {
                // QFE 4512: Ignore old V1.1 Session ids for cookieless in V2.0 
                if (_Headers.Length == 24 && !_Headers.Contains("(")) {
                    _Headers = null;
                }
                else { 
                    _Context.Response.SetAppPathModifier("(" + _Headers + ")");
                } 
            } 
        }
 
        // This function is called for all requests -- it must be performant.
        //    In the common case (i.e. value not present in the URI, it must not
        //    look at the headers collection
        internal void RemoveCookielessValuesFromPath() 
        {
            // See if the path contains "/(XXXXX)/" 
            string   path      = _Context.Request.ClientFilePath.VirtualPathString; 
            // Optimize for the common case where there is no cookie
            if (path.IndexOf('(') == -1) { 
                return;
            }
            int      endPos    = path.LastIndexOf(")/", StringComparison.Ordinal);
            int      startPos  = (endPos > 2 ?  path.LastIndexOf("/(", endPos - 1, endPos, StringComparison.Ordinal) : -1); 

            if (startPos < 0) // pattern not found: common case, exit immediately 
                return; 

            if (_Headers == null) // Header should always be processed first 
                GetCookielessValuesFromHeader();

            // if the path contains a cookie, remove it
            if (IsValidHeader(path, startPos + 2, endPos)) 
            {
                // only set _Headers if not already set 
                if (_Headers == null) { 
                    _Headers = path.Substring(startPos + 2, endPos - startPos - 2);
                } 
                // Rewrite the path
                path = path.Substring(0, startPos) + path.Substring(endPos+1);

                // remove cookie from ClientFilePath 
                _Context.Request.ClientFilePath = VirtualPath.CreateAbsolute(path);
                // get and append query string to path if it exists 
                string rawUrl = _Context.Request.RawUrl; 
                int qsIndex = rawUrl.IndexOf('?');
                if (qsIndex > -1) { 
                    path = path + rawUrl.Substring(qsIndex);
                }
                // remove cookie from RawUrl
                _Context.Request.RawUrl = path; 

                if (!String.IsNullOrEmpty(_Headers)) { 
                    _Context.Request.ValidateCookielessHeaderIfRequiredByConfig(_Headers); // ensure that the path doesn't contain invalid chars 
                    _Context.Response.SetAppPathModifier("(" + _Headers + ")");
 
                    // For Cassini and scenarios where aspnet_filter.dll is not used,
                    // HttpRequest.FilePath also needs to have the cookie removed.
                    string filePath = _Context.Request.FilePath;
                    string newFilePath = _Context.Response.RemoveAppPathModifier(filePath); 
                    if (!Object.ReferenceEquals(filePath, newFilePath)) {
                        _Context.RewritePath(VirtualPath.CreateAbsolute(newFilePath), 
                                             _Context.Request.PathInfoObject, 
                                             null /*newQueryString*/,
                                             false /*setClientFilePath*/); 
                    }
                }
            }
        } 

        //////////////////////////////////////////////////////////////////////// 
        //////////////////////////////////////////////////////////////////////// 
        // Get the cookie value from the header/path based on the identifying char
        internal string GetCookieValue(char identifier) { 
            int      startPos = 0;
            int      endPos = 0;
            string   returnValue;
 
            Init();
            //////////////////////////////////////////////////////////// 
            // Step 1: Get the positions 
            if (!GetValueStartAndEnd(_Headers, identifier, out startPos, out endPos))
                return null; 

            returnValue = _Headers.Substring(startPos, endPos-startPos); // get the substring
            return returnValue;
        } 
        internal bool DoesCookieValueExistInOriginal(char identifier) {
            int      startPos = 0; 
            int      endPos = 0; 
            Init();
            return GetValueStartAndEnd(_OriginalHeaders, identifier, out startPos, out endPos); 
        }


        //////////////////////////////////////////////////////////////////////// 
        ////////////////////////////////////////////////////////////////////////
        // Add/Change/Delete a cookie value, given the tag 
        internal void SetCookieValue(char identifier, string cookieValue) { 
            int      startPos = 0;
            int      endPos = 0; 

            Init();
            ////////////////////////////////////////////////////////////
            // Step 1: Remove old values 
            while (GetValueStartAndEnd(_Headers, identifier, out startPos, out endPos)) { // find old value position
                _Headers = _Headers.Substring(0, startPos-2) + _Headers.Substring(endPos+1); // Remove old value 
            } 

            //////////////////////////////////////////////////////////// 
            // Step 2: Add new Value if value is specified
            if (!String.IsNullOrEmpty(cookieValue)) {
                _Headers += new string(new char[] {identifier, '('}) + cookieValue + ")";
            } 

            //////////////////////////////////////////////////////////// 
            // Step 3: Set path for redirection 
            if (_Headers.Length > 0)
                _Context.Response.SetAppPathModifier("(" + _Headers + ")"); 
            else
                _Context.Response.SetAppPathModifier(null);
        }
        //////////////////////////////////////////////////////////////////////// 
        ////////////////////////////////////////////////////////////////////////
        // Get the position (start & end) of cookie value given the identifier 
        private static bool GetValueStartAndEnd(string headers, char identifier, out int startPos, out int endPos) { 

            //////////////////////////////////////////////////////////// 
            // Step 1: Check if the header is non-empty
            if (String.IsNullOrEmpty(headers)) {
                startPos = endPos = -1;
                return false; 
            }
 
            //////////////////////////////////////////////////////////// 
            // Step 2: Get the start pos
            string tag = new string(new char[] {identifier, '('}); // Tag is: "X(" 
            startPos = headers.IndexOf(tag, StringComparison.Ordinal); // Search for "X("
            if (startPos < 0) { // Not Found
                startPos = endPos = -1;
                return false; 
            }
            startPos += 2; 
 
            ////////////////////////////////////////////////////////////
            // Step 3: Find the end position 
            endPos = headers.IndexOf(')', startPos);
            if (endPos < 0) {
                startPos = endPos = -1;
                return false; 
            }
            return true; 
        } 
        ////////////////////////////////////////////////////////////////////////
        //////////////////////////////////////////////////////////////////////// 
        // Look at config () and (maybe) current request, and return
        //     whether to use cookie-less feature
        internal static bool UseCookieless(HttpContext context, bool doRedirect, HttpCookieMode cookieMode) {
 
            ////////////////////////////////////////////////////////////
            // Step 2: Look at config 
            switch(cookieMode) 
            {
            case HttpCookieMode.UseUri: // Use cookieless always 
                return true;

            case HttpCookieMode.UseCookies: // Never use cookieless
                return false; 

            case HttpCookieMode.UseDeviceProfile: // Use browser config 
                if (context == null) 
                    context = HttpContext.Current;
                if (context == null) 
                    return false;
                bool fRet = (!context.Request.Browser.Cookies ||
                             !context.Request.Browser.SupportsRedirectWithCookie);
                return fRet; 

            case HttpCookieMode.AutoDetect: // Detect based on whether the client supports cookieless 
                if (context == null) 
                    context = HttpContext.Current;
                if (context == null) 
                    return false;

                if (!context.Request.Browser.Cookies || !context.Request.Browser.SupportsRedirectWithCookie) {
                    return true; 
                }
 
                ////////////////////////////////////////////////////////////////// 
                // Look in the header
                string cookieDetectHeader = context.CookielessHelper.GetCookieValue('X'); 
                if (cookieDetectHeader != null && cookieDetectHeader == "1") {
                    return true;
                }
 
                //////////////////////////////////////////////////
                // Step 3a: See if the client sent any (request) cookies 
                string cookieHeader = context.Request.Headers["Cookie"]; 
                if (!String.IsNullOrEmpty(cookieHeader)) { // Yes, client sent request cookies
                    return false; 
                }


                ////////////////////////////////////////////////// 
                // Step 3b: See if we have done a challenge-response to detect cookie support
                string qs = context.Request.QueryString[s_AutoDetectName]; 
                if (qs != null && qs == s_AutoDetectValue) { // Yes, we have done a challenge-response: No cookies present => no cookie support 
                    context.CookielessHelper.SetCookieValue('X', "1");
                    return true; 
                }


                ////////////////////////////////////////////////// 
                // Step 3c: Do a challenge-response (redirect) to detect cookie support
                if (doRedirect) { 
                    context.CookielessHelper.RedirectWithDetection(null); 
                }
                // Note: if doRedirect==true, execution won't reach here 

                return false;

            default: // Config broken? 
                return false;
            } 
        } 

        //////////////////////////////////////////////////////////////////////// 
        ////////////////////////////////////////////////////////////////////////
        // Do a redirect to figure out cookies are supported or not.
        ///    The way we do it: write the cookie and in the query-string,
        //     write the cookie-name value pair. 
        internal void  RedirectWithDetection(string redirectPath) {
 
            Init(); 
            ////////////////////////////////////////////////////////////
            // Step 1: If URL to redirect to, has not been specified, 
            //         the use the current URL
            if (String.IsNullOrEmpty(redirectPath)) {
                redirectPath = _Context.Request.RawUrl;
            } 

            //////////////////////////////////////////////////////////// 
            // Step 2: Add cookie name and value to query-string 
            if (redirectPath.IndexOf("?", StringComparison.Ordinal) > 0)
                redirectPath += "&" + s_AutoDetectName + "=" + s_AutoDetectValue; 
            else
                redirectPath += "?" + s_AutoDetectName + "=" + s_AutoDetectValue;

 
            ////////////////////////////////////////////////////////////
            // Step 3: Add cookie 
            _Context.Response.Cookies.Add(new HttpCookie(s_AutoDetectName, s_AutoDetectValue)); 

            //////////////////////////////////////////////////////////// 
            // Step 4: Do redirect
            _Context.Response.Redirect(redirectPath, true);
        }
 
        ////////////////////////////////////////////////////////////////////////
        //////////////////////////////////////////////////////////////////////// 
        // RedirectWithDetection if we need to 
        internal void RedirectWithDetectionIfRequired(string redirectPath, HttpCookieMode cookieMode) {
 
            Init();
            ////////////////////////////////////////////////////////////
            // Step 1: Check if config wants us to do a challenge-reponse
            if (cookieMode != HttpCookieMode.AutoDetect) { 
                return;
            } 
 
            ////////////////////////////////////////////////////////////
            // Step 2: Check browser caps 
            if (!_Context.Request.Browser.Cookies || !_Context.Request.Browser.SupportsRedirectWithCookie) {
                return;
            }
 
            ////////////////////////////////////////////////////////////
            // Step 3: Check header 
            string cookieDetectHeader = GetCookieValue('X'); 
            if (cookieDetectHeader != null && cookieDetectHeader == "1") {
                return; 
            }

            ////////////////////////////////////////////////////////////
            // Step 4: see if the client sent any cookies 
            string cookieHeader = _Context.Request.Headers["Cookie"];
            if (!String.IsNullOrEmpty(cookieHeader)) { 
                return; 
            }
 
            ////////////////////////////////////////////////////////////
            // Step 5: See if we already did a challenge-reponse
            string qs = _Context.Request.QueryString[s_AutoDetectName];
            if (qs != null && qs == s_AutoDetectValue) { // Yes, we have done a challenge-response 
                                                          // No cookies present => no cookie support
                SetCookieValue('X', "1"); 
                return; 
            }
            //////////////////////////////////////////////////////////// 
            // Do a challenge response
            RedirectWithDetection(redirectPath);
        }
 
        ///////////////////////////////////////////////////////////////////////
        /////////////////////////////////////////////////////////////////////// 
        // Make sure sub-string if of the pattern: A(XXXX)N(XXXXX)P(XXXXX) and so on. 
        static private bool IsValidHeader(string path, int startPos, int endPos)
        { 
            if (endPos - startPos < 3) // Minimum len is "X()"
                return false;

            while (startPos <= endPos - 3) { // Each iteration deals with one "A(XXXX)" pattern 

                if (path[startPos] < 'A' || path[startPos] > 'Z') // Make sure pattern starts with a capital letter 
                    return false; 

                if (path[startPos + 1] != '(') // Make sure next char is '(' 
                    return false;

                startPos += 2;
                bool found = false; 
                for (; startPos < endPos; startPos++) { // Find the ending ')'
 
                    if (path[startPos] == ')') { // found it! 
                        startPos++; // Set position for the next pattern
                        found = true; 
                        break; // Break out of this for-loop.
                    }

                    if (path[startPos] == '/') { // Can't contain path separaters 
                        return false;
                    } 
                } 
                if (!found)  {
                    return false; // Ending ')' not found! 
                }
            }

            if (startPos < endPos) // All chars consumed? 
                return false;
 
            return true; 
        }
 
        ////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////
        // Static data
        internal const String COOKIELESS_SESSION_FILTER_HEADER  = "AspFilterSessionId"; 
        const string         s_AutoDetectName                 = "AspxAutoDetectCookieSupport";
        const string         s_AutoDetectValue                = "1"; 
 
        // Private instance data
        private HttpContext  _Context; 
        private string       _Headers;
        private string       _OriginalHeaders;
    }
 
    /////////////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////// 
    ///////////////////////////////////////////////////////////////////////////// 
    internal enum CookiesSupported {
        Supported, NotSupported, Unknown 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

/* 
 * CookielessHelper class 
 *
 * Copyright (c) 1999 Microsoft Corporation 
 */

namespace System.Web.Security {
    using System; 
    using System.Web;
    using System.Text; 
    using System.Web.Configuration; 
    using System.Web.Caching;
    using System.Collections; 
    using System.Web.Util;
    using System.Security.Cryptography;
    using System.Security.Principal;
    using System.Threading; 
    using System.Globalization;
    using System.Security.Permissions; 
 
    internal sealed class CookielessHelperClass {
        //////////////////////////////////////////////////////////////////////// 
        ////////////////////////////////////////////////////////////////////////
        internal CookielessHelperClass(HttpContext context) {
            _Context = context;
        } 
        private void Init()
        { 
            if (_Headers != null) 
                return;
            if (_Headers == null) 
                GetCookielessValuesFromHeader();
            if (_Headers == null)
                RemoveCookielessValuesFromPath();
            if (_Headers == null) 
                _Headers = String.Empty;
            _OriginalHeaders = _Headers; 
        } 

        private void GetCookielessValuesFromHeader() 
        {
            _Headers = _Context.Request.Headers[COOKIELESS_SESSION_FILTER_HEADER];

            // Dev10 775061 Regression: FormsAuthentication.SignOut does not redirect if cookieless forms authentication is enabled. 
            // HttpContext.Init calls RemoveCookielessValues directly so we need to also store the OriginalHeaders for Redirect
            // calling Init directly causes regressions 
            _OriginalHeaders = _Headers; 
            if (!String.IsNullOrEmpty(_Headers)) {
                // QFE 4512: Ignore old V1.1 Session ids for cookieless in V2.0 
                if (_Headers.Length == 24 && !_Headers.Contains("(")) {
                    _Headers = null;
                }
                else { 
                    _Context.Response.SetAppPathModifier("(" + _Headers + ")");
                } 
            } 
        }
 
        // This function is called for all requests -- it must be performant.
        //    In the common case (i.e. value not present in the URI, it must not
        //    look at the headers collection
        internal void RemoveCookielessValuesFromPath() 
        {
            // See if the path contains "/(XXXXX)/" 
            string   path      = _Context.Request.ClientFilePath.VirtualPathString; 
            // Optimize for the common case where there is no cookie
            if (path.IndexOf('(') == -1) { 
                return;
            }
            int      endPos    = path.LastIndexOf(")/", StringComparison.Ordinal);
            int      startPos  = (endPos > 2 ?  path.LastIndexOf("/(", endPos - 1, endPos, StringComparison.Ordinal) : -1); 

            if (startPos < 0) // pattern not found: common case, exit immediately 
                return; 

            if (_Headers == null) // Header should always be processed first 
                GetCookielessValuesFromHeader();

            // if the path contains a cookie, remove it
            if (IsValidHeader(path, startPos + 2, endPos)) 
            {
                // only set _Headers if not already set 
                if (_Headers == null) { 
                    _Headers = path.Substring(startPos + 2, endPos - startPos - 2);
                } 
                // Rewrite the path
                path = path.Substring(0, startPos) + path.Substring(endPos+1);

                // remove cookie from ClientFilePath 
                _Context.Request.ClientFilePath = VirtualPath.CreateAbsolute(path);
                // get and append query string to path if it exists 
                string rawUrl = _Context.Request.RawUrl; 
                int qsIndex = rawUrl.IndexOf('?');
                if (qsIndex > -1) { 
                    path = path + rawUrl.Substring(qsIndex);
                }
                // remove cookie from RawUrl
                _Context.Request.RawUrl = path; 

                if (!String.IsNullOrEmpty(_Headers)) { 
                    _Context.Request.ValidateCookielessHeaderIfRequiredByConfig(_Headers); // ensure that the path doesn't contain invalid chars 
                    _Context.Response.SetAppPathModifier("(" + _Headers + ")");
 
                    // For Cassini and scenarios where aspnet_filter.dll is not used,
                    // HttpRequest.FilePath also needs to have the cookie removed.
                    string filePath = _Context.Request.FilePath;
                    string newFilePath = _Context.Response.RemoveAppPathModifier(filePath); 
                    if (!Object.ReferenceEquals(filePath, newFilePath)) {
                        _Context.RewritePath(VirtualPath.CreateAbsolute(newFilePath), 
                                             _Context.Request.PathInfoObject, 
                                             null /*newQueryString*/,
                                             false /*setClientFilePath*/); 
                    }
                }
            }
        } 

        //////////////////////////////////////////////////////////////////////// 
        //////////////////////////////////////////////////////////////////////// 
        // Get the cookie value from the header/path based on the identifying char
        internal string GetCookieValue(char identifier) { 
            int      startPos = 0;
            int      endPos = 0;
            string   returnValue;
 
            Init();
            //////////////////////////////////////////////////////////// 
            // Step 1: Get the positions 
            if (!GetValueStartAndEnd(_Headers, identifier, out startPos, out endPos))
                return null; 

            returnValue = _Headers.Substring(startPos, endPos-startPos); // get the substring
            return returnValue;
        } 
        internal bool DoesCookieValueExistInOriginal(char identifier) {
            int      startPos = 0; 
            int      endPos = 0; 
            Init();
            return GetValueStartAndEnd(_OriginalHeaders, identifier, out startPos, out endPos); 
        }


        //////////////////////////////////////////////////////////////////////// 
        ////////////////////////////////////////////////////////////////////////
        // Add/Change/Delete a cookie value, given the tag 
        internal void SetCookieValue(char identifier, string cookieValue) { 
            int      startPos = 0;
            int      endPos = 0; 

            Init();
            ////////////////////////////////////////////////////////////
            // Step 1: Remove old values 
            while (GetValueStartAndEnd(_Headers, identifier, out startPos, out endPos)) { // find old value position
                _Headers = _Headers.Substring(0, startPos-2) + _Headers.Substring(endPos+1); // Remove old value 
            } 

            //////////////////////////////////////////////////////////// 
            // Step 2: Add new Value if value is specified
            if (!String.IsNullOrEmpty(cookieValue)) {
                _Headers += new string(new char[] {identifier, '('}) + cookieValue + ")";
            } 

            //////////////////////////////////////////////////////////// 
            // Step 3: Set path for redirection 
            if (_Headers.Length > 0)
                _Context.Response.SetAppPathModifier("(" + _Headers + ")"); 
            else
                _Context.Response.SetAppPathModifier(null);
        }
        //////////////////////////////////////////////////////////////////////// 
        ////////////////////////////////////////////////////////////////////////
        // Get the position (start & end) of cookie value given the identifier 
        private static bool GetValueStartAndEnd(string headers, char identifier, out int startPos, out int endPos) { 

            //////////////////////////////////////////////////////////// 
            // Step 1: Check if the header is non-empty
            if (String.IsNullOrEmpty(headers)) {
                startPos = endPos = -1;
                return false; 
            }
 
            //////////////////////////////////////////////////////////// 
            // Step 2: Get the start pos
            string tag = new string(new char[] {identifier, '('}); // Tag is: "X(" 
            startPos = headers.IndexOf(tag, StringComparison.Ordinal); // Search for "X("
            if (startPos < 0) { // Not Found
                startPos = endPos = -1;
                return false; 
            }
            startPos += 2; 
 
            ////////////////////////////////////////////////////////////
            // Step 3: Find the end position 
            endPos = headers.IndexOf(')', startPos);
            if (endPos < 0) {
                startPos = endPos = -1;
                return false; 
            }
            return true; 
        } 
        ////////////////////////////////////////////////////////////////////////
        //////////////////////////////////////////////////////////////////////// 
        // Look at config () and (maybe) current request, and return
        //     whether to use cookie-less feature
        internal static bool UseCookieless(HttpContext context, bool doRedirect, HttpCookieMode cookieMode) {
 
            ////////////////////////////////////////////////////////////
            // Step 2: Look at config 
            switch(cookieMode) 
            {
            case HttpCookieMode.UseUri: // Use cookieless always 
                return true;

            case HttpCookieMode.UseCookies: // Never use cookieless
                return false; 

            case HttpCookieMode.UseDeviceProfile: // Use browser config 
                if (context == null) 
                    context = HttpContext.Current;
                if (context == null) 
                    return false;
                bool fRet = (!context.Request.Browser.Cookies ||
                             !context.Request.Browser.SupportsRedirectWithCookie);
                return fRet; 

            case HttpCookieMode.AutoDetect: // Detect based on whether the client supports cookieless 
                if (context == null) 
                    context = HttpContext.Current;
                if (context == null) 
                    return false;

                if (!context.Request.Browser.Cookies || !context.Request.Browser.SupportsRedirectWithCookie) {
                    return true; 
                }
 
                ////////////////////////////////////////////////////////////////// 
                // Look in the header
                string cookieDetectHeader = context.CookielessHelper.GetCookieValue('X'); 
                if (cookieDetectHeader != null && cookieDetectHeader == "1") {
                    return true;
                }
 
                //////////////////////////////////////////////////
                // Step 3a: See if the client sent any (request) cookies 
                string cookieHeader = context.Request.Headers["Cookie"]; 
                if (!String.IsNullOrEmpty(cookieHeader)) { // Yes, client sent request cookies
                    return false; 
                }


                ////////////////////////////////////////////////// 
                // Step 3b: See if we have done a challenge-response to detect cookie support
                string qs = context.Request.QueryString[s_AutoDetectName]; 
                if (qs != null && qs == s_AutoDetectValue) { // Yes, we have done a challenge-response: No cookies present => no cookie support 
                    context.CookielessHelper.SetCookieValue('X', "1");
                    return true; 
                }


                ////////////////////////////////////////////////// 
                // Step 3c: Do a challenge-response (redirect) to detect cookie support
                if (doRedirect) { 
                    context.CookielessHelper.RedirectWithDetection(null); 
                }
                // Note: if doRedirect==true, execution won't reach here 

                return false;

            default: // Config broken? 
                return false;
            } 
        } 

        //////////////////////////////////////////////////////////////////////// 
        ////////////////////////////////////////////////////////////////////////
        // Do a redirect to figure out cookies are supported or not.
        ///    The way we do it: write the cookie and in the query-string,
        //     write the cookie-name value pair. 
        internal void  RedirectWithDetection(string redirectPath) {
 
            Init(); 
            ////////////////////////////////////////////////////////////
            // Step 1: If URL to redirect to, has not been specified, 
            //         the use the current URL
            if (String.IsNullOrEmpty(redirectPath)) {
                redirectPath = _Context.Request.RawUrl;
            } 

            //////////////////////////////////////////////////////////// 
            // Step 2: Add cookie name and value to query-string 
            if (redirectPath.IndexOf("?", StringComparison.Ordinal) > 0)
                redirectPath += "&" + s_AutoDetectName + "=" + s_AutoDetectValue; 
            else
                redirectPath += "?" + s_AutoDetectName + "=" + s_AutoDetectValue;

 
            ////////////////////////////////////////////////////////////
            // Step 3: Add cookie 
            _Context.Response.Cookies.Add(new HttpCookie(s_AutoDetectName, s_AutoDetectValue)); 

            //////////////////////////////////////////////////////////// 
            // Step 4: Do redirect
            _Context.Response.Redirect(redirectPath, true);
        }
 
        ////////////////////////////////////////////////////////////////////////
        //////////////////////////////////////////////////////////////////////// 
        // RedirectWithDetection if we need to 
        internal void RedirectWithDetectionIfRequired(string redirectPath, HttpCookieMode cookieMode) {
 
            Init();
            ////////////////////////////////////////////////////////////
            // Step 1: Check if config wants us to do a challenge-reponse
            if (cookieMode != HttpCookieMode.AutoDetect) { 
                return;
            } 
 
            ////////////////////////////////////////////////////////////
            // Step 2: Check browser caps 
            if (!_Context.Request.Browser.Cookies || !_Context.Request.Browser.SupportsRedirectWithCookie) {
                return;
            }
 
            ////////////////////////////////////////////////////////////
            // Step 3: Check header 
            string cookieDetectHeader = GetCookieValue('X'); 
            if (cookieDetectHeader != null && cookieDetectHeader == "1") {
                return; 
            }

            ////////////////////////////////////////////////////////////
            // Step 4: see if the client sent any cookies 
            string cookieHeader = _Context.Request.Headers["Cookie"];
            if (!String.IsNullOrEmpty(cookieHeader)) { 
                return; 
            }
 
            ////////////////////////////////////////////////////////////
            // Step 5: See if we already did a challenge-reponse
            string qs = _Context.Request.QueryString[s_AutoDetectName];
            if (qs != null && qs == s_AutoDetectValue) { // Yes, we have done a challenge-response 
                                                          // No cookies present => no cookie support
                SetCookieValue('X', "1"); 
                return; 
            }
            //////////////////////////////////////////////////////////// 
            // Do a challenge response
            RedirectWithDetection(redirectPath);
        }
 
        ///////////////////////////////////////////////////////////////////////
        /////////////////////////////////////////////////////////////////////// 
        // Make sure sub-string if of the pattern: A(XXXX)N(XXXXX)P(XXXXX) and so on. 
        static private bool IsValidHeader(string path, int startPos, int endPos)
        { 
            if (endPos - startPos < 3) // Minimum len is "X()"
                return false;

            while (startPos <= endPos - 3) { // Each iteration deals with one "A(XXXX)" pattern 

                if (path[startPos] < 'A' || path[startPos] > 'Z') // Make sure pattern starts with a capital letter 
                    return false; 

                if (path[startPos + 1] != '(') // Make sure next char is '(' 
                    return false;

                startPos += 2;
                bool found = false; 
                for (; startPos < endPos; startPos++) { // Find the ending ')'
 
                    if (path[startPos] == ')') { // found it! 
                        startPos++; // Set position for the next pattern
                        found = true; 
                        break; // Break out of this for-loop.
                    }

                    if (path[startPos] == '/') { // Can't contain path separaters 
                        return false;
                    } 
                } 
                if (!found)  {
                    return false; // Ending ')' not found! 
                }
            }

            if (startPos < endPos) // All chars consumed? 
                return false;
 
            return true; 
        }
 
        ////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////
        // Static data
        internal const String COOKIELESS_SESSION_FILTER_HEADER  = "AspFilterSessionId"; 
        const string         s_AutoDetectName                 = "AspxAutoDetectCookieSupport";
        const string         s_AutoDetectValue                = "1"; 
 
        // Private instance data
        private HttpContext  _Context; 
        private string       _Headers;
        private string       _OriginalHeaders;
    }
 
    /////////////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////// 
    ///////////////////////////////////////////////////////////////////////////// 
    internal enum CookiesSupported {
        Supported, NotSupported, Unknown 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK