/// <summary>
    /// Handler mapping handler.
    /// </summary>
    public static void CMSMapRequestHandler(object sender, EventArgs e)
    {
        URLRewritingResultEnum status = URLRewriter.CurrentStatus;
        if (ConnectionAvailable && (status != URLRewritingResultEnum.SentFromCache))
        {
            RequestHelper.LogRequestOperation("MapRequestHandler", null, 0);
            DebugHelper.SetContext("MapRequestHandler");

            // Handle the event
            var h = CMSRequestEvents.MapRequestHandler.StartEvent(e);
            if (h.Continue)
            {
                // Get request parameters
                string relativePath = URLHelper.CurrentRelativePath;

                ExcludedSystemEnum excludedEnum = RequestHelper.CurrentExcludedStatus;
                if (excludedEnum == ExcludedSystemEnum.Unknown)
                {
                    excludedEnum = URLHelper.IsExcludedSystemEnum(relativePath);
                }

                ViewModeOnDemand viewMode = new ViewModeOnDemand();
                SiteNameOnDemand siteName = new SiteNameOnDemand();

                // Handle the virtual context
                HandleVirtualContext(ref relativePath, ref excludedEnum);

                // Set flag to output filter for cms dialogs
                if (excludedEnum == ExcludedSystemEnum.CMSDialog)
                {
                    OutputFilter.UseFormActionWithCurrentURL = true;
                }

                // Perform the URL rewriting
                RewriteUrl(status, relativePath, excludedEnum, viewMode, siteName);
            }

            // Finalize the event
            h.FinishEvent();

            DebugHelper.ReleaseContext();
        }
    }
    /// <summary>
    /// Request authorization handler.
    /// </summary>
    public static void CMSAuthorizeRequest(object sender, EventArgs e)
    {
        RequestHelper.LogRequestOperation("AuthorizeRequest", null, 0);
        DebugHelper.SetContext("AuthorizeRequest");

        if (ConnectionAvailable)
        {
            // Handle the event
            var h = CMSRequestEvents.Authorize.StartEvent(e);
            if (h.Continue)
            {
                string relativePath = URLHelper.CurrentRelativePath;

                // Check the excluded status
                ExcludedSystemEnum excludedEnum = URLHelper.IsExcludedSystemEnum(relativePath);

                RequestHelper.CurrentExcludedStatus = excludedEnum;

                ViewModeOnDemand viewMode = new ViewModeOnDemand();
                SiteNameOnDemand siteName = new SiteNameOnDemand();

                // Try to send the output from the cache without URL rewriting
                if (URLRewriter.SendOutputFromCache(relativePath, excludedEnum, viewMode, siteName))
                {
                    if (OutputFilter.OutputFilterEndRequestRequired)
                    {
                        HttpContext.Current.RewritePath("~/CMSPages/blank.aspx");
                    }
                    return;
                }
            }

            // Finalize the event
            h.FinishEvent();
        }

        DebugHelper.ReleaseContext();
    }
    /// <summary>
    /// Custom cache parameters processing.
    /// </summary>
    public static string CMSGetVaryByCustomString(HttpContext context, string custom)
    {
        if (context == null)
        {
            return "";
        }

        HttpResponse response = context.Response;

        // Do not cache on postback
        if (URLHelper.IsPostback())
        {
            response.Cache.SetNoStore();
            return Guid.NewGuid().ToString();
        }

        PageInfo currentPage = CMSContext.CurrentPageInfo;
        string result = null;

        // Cache control
        if ((currentPage != null) && !custom.StartsWith("control;"))
        {
            // Check page caching minutes
            int cacheMinutes = currentPage.NodeCacheMinutes;
            if (cacheMinutes <= 0)
            {
                // Do not cache
                response.Cache.SetNoStore();
                return Guid.NewGuid().ToString();
            }
        }

        SiteNameOnDemand siteName = new SiteNameOnDemand();
        ViewModeOnDemand viewMode = new ViewModeOnDemand();

        // Parse the custom parameters
        string contextString = CMSContext.GetContextCacheString(custom, viewMode, siteName);
        if (contextString == null)
        {
            // Do not cache
            response.Cache.SetNoStore();
            return Guid.NewGuid().ToString();
        }
        else
        {
            result = "cached" + contextString;
        }

        return result.ToLower();
    }
    /// <summary>
    /// Sets the initial debugging settings.
    /// </summary>
    private static void SetInitialDebug()
    {
        if (CMSFunctions.AnyDebugEnabled)
        {
            // Prepare the context values
            ViewModeOnDemand viewMode = new ViewModeOnDemand();
            RequestSettingsOnDemand settings = new RequestSettingsOnDemand();

            bool isLiveSite = (viewMode.Value == ViewModeEnum.LiveSite);

            // Set request debugging
            if (RequestHelper.DebugRequests)
            {
                settings.Value.DebugRequest = RequestHelper.DebugAllRequests || isLiveSite;
                RequestHelper.LogRequestOperation("BeginRequest", null, 0);
            }
            if (SqlHelperClass.DebugQueries)
            {
                settings.Value.DebugSQLQueries = SqlHelperClass.DebugAllQueries || isLiveSite;
            }
            if (CacheHelper.DebugCache)
            {
                settings.Value.DebugCache = CacheHelper.DebugAllCaches || isLiveSite;
            }
            if (SecurityHelper.DebugSecurity)
            {
                settings.Value.DebugSecurity = SecurityHelper.DebugAllSecurity || isLiveSite;
            }
            if (File.DebugFiles)
            {
                settings.Value.DebugFiles = File.DebugAllFiles || isLiveSite;
            }
            if (MacroResolver.DebugMacros)
            {
                settings.Value.DebugMacros = MacroResolver.DebugAllMacros || isLiveSite;
            }
            if (OutputHelper.DebugOutput)
            {
                settings.Value.DebugOutput = OutputHelper.DebugAllOutputs || isLiveSite;
            }
            if (WebSyncHelperClass.DebugWebFarm)
            {
                settings.Value.DebugWebFarm = WebSyncHelperClass.DebugAllWebFarm || isLiveSite;
            }
            if (AnalyticsHelper.DebugAnalytics)
            {
                settings.Value.DebugAnalytics = AnalyticsHelper.DebugAllAnalytics || isLiveSite;
            }

        }
    }
    /// <summary>
    /// Rewrites the URL and performs all operations required after URL rewriting.
    /// </summary>
    /// <param name="status">Current rewriting status</param>
    /// <param name="relativePath">Relative path</param>
    /// <param name="excludedEnum">Excluded page status</param>
    /// <param name="viewMode">View mode</param>
    /// <param name="siteName">Site name</param>
    private static void RewriteUrl(URLRewritingResultEnum status, string relativePath, ExcludedSystemEnum excludedEnum, ViewModeOnDemand viewMode, SiteNameOnDemand siteName)
    {
        // Do the rewriting if status not yet determined
        if (status == URLRewritingResultEnum.Unknown)
        {
            RequestHelper.LogRequestOperation("RewriteURL", relativePath, 0);

            // Rewrite URL
            status = URLRewriter.RewriteUrl(relativePath, excludedEnum, siteName, viewMode);
        }

        // Process actions after rewriting
        URLRewriter.ProcessRewritingResult(status, excludedEnum, siteName, viewMode, relativePath);
    }
    /// <summary>
    /// Performs the application initialization on the first request.
    /// </summary>
    private static void FirstRequestInitialization(object sender, EventArgs e)
    {
        // Initialized properly
        if (mApplicationInitialized == true)
        {
            return;
        }

        // Not initialized, must install
        if ((mApplicationInitialized == false) && InstallerFunctions.InstallRedirect(true))
        {
            return;
        }

        // Do not init application on request to just physical file
        string relativePath = URLHelper.CurrentRelativePath;
        ExcludedSystemEnum excludedEnum = URLHelper.IsExcludedSystemEnum(relativePath);
        if (excludedEnum == ExcludedSystemEnum.PhysicalFile)
        {
            return;
        }

        // Initialize application in a locked context
        lock (mLock)
        {
            if (ApplicationInitialized)
            {
                return;
            }

            // Remember date and time of the application start
            mApplicationStart = DateTime.Now;

            // Init run from web applicaiton - DON'T MOVE LATER
            SystemHelper.IsWebSite = true;

            mWindowsIdentity = WindowsIdentity.GetCurrent();

            ViewModeOnDemand viewMode = new ViewModeOnDemand();

            // Log application start
            if (CMSFunctions.AnyDebugEnabled)
            {
                RequestSettings settings = RequestSettings.Current;
                bool liveSite = (viewMode.Value == ViewModeEnum.LiveSite);

                settings.DebugRequest = RequestHelper.DebugRequests && liveSite;
                RequestHelper.LogRequestOperation("BeforeApplicationStart", null, 0);

                settings.DebugSQLQueries = SqlHelperClass.DebugQueries && liveSite;
                settings.DebugFiles = File.DebugFiles && liveSite;
                settings.DebugCache = CacheHelper.DebugCache && liveSite;
                settings.DebugSecurity = SecurityHelper.DebugSecurity && liveSite;
                settings.DebugOutput = OutputHelper.DebugOutput && liveSite;
                settings.DebugMacros = MacroResolver.DebugMacros && liveSite;
                settings.DebugWebFarm = WebSyncHelperClass.DebugWebFarm && liveSite;
                settings.DebugAnalytics = AnalyticsHelper.DebugAnalytics && liveSite;

                DebugHelper.SetContext("App_Start");
            }

            // Handle the event
            var h = CMSApplicationEvents.Start.StartEvent(e);
            if (h.Continue)
            {
                //ConnectionHelper.UseContextConnection = true;
                //CacheHelper.CacheItemPriority = System.Web.Caching.CacheItemPriority.NotRemovable;

                if (SqlHelperClass.IsConnectionStringInitialized)
                {
                    using (CMSConnectionScope scope = new CMSConnectionScope())
                    {
                        // Use single open connection for the application start
                        GeneralConnection conn = (GeneralConnection)scope.Connection;
                        bool closeConnection = false;
                        try
                        {
                            // Open the connection
                            conn.Open();
                            closeConnection = true;

                            // Check for the table existence
                            if (!TableManager.TableExists("CMS_SettingsKey"))
                            {
                                mApplicationInitialized = false;

                                if (InstallerFunctions.InstallRedirect(true))
                                {
                                    return;
                                }
                            }

                            // Check the version
                            string version = SettingsKeyProvider.GetStringValue("CMSDBVersion");
                            if (version != CMSContext.SYSTEM_VERSION)
                            {
                                // Report error about not being able to connect
                                mConnectionErrorMessage = "The database version '" + version + "' does not match the project version '" + CMSContext.SYSTEM_VERSION + "', please check your connection string.";
                                HttpContext.Current.Server.Transfer("~/CMSMessages/error.aspx");
                            }
                            else
                            {
                                // Initialize the environment
                                CMSFunctions.Init();

                                // Update the system !! IMPORTANT - must be first
                                UpgradeProcedure.Update(conn);
                                try
                                {
                                    // Write "Application start" event to the event log
                                    EventLogProvider ev = new EventLogProvider();

                                    ev.DeleteOlderLogs = false;
                                    ev.LogEvent(EventLogProvider.EVENT_TYPE_INFORMATION, DateTime.Now, "Application_Start", "STARTAPP", 0, null, 0, null, null, null, 0, HTTPHelper.GetAbsoluteUri());
                                }
                                catch
                                {
                                    // can't write to log, do not process any code
                                }
                                UserInfoProvider.OnFormattedUserName += new UserInfoProvider.FormattedUserNameEventHandler(Functions.GetFormattedUserName);

                                // Delete memory synchronization tasks
                                WebSyncHelper.DeleteMemorySynchronizationTasks();

                                // Create web farm server if running on Azure
                                if (AzureHelper.IsRunningOnAzure)
                                {
                                    // Set webfarm server name
                                    WebSyncHelperClass.ServerName = ValidationHelper.GetCodeName(AzureHelper.CurrentInstanceID);

                                    if (WebFarmServerInfoProvider.GetWebFarmServerInfo(WebSyncHelperClass.ServerName) == null)
                                    {
                                        // Create webfarm server
                                        WebFarmServerInfo wfsi = new WebFarmServerInfo();
                                        wfsi.ServerName = WebSyncHelperClass.ServerName;
                                        wfsi.ServerEnabled = true;
                                        wfsi.ServerDisplayName = AzureHelper.CurrentInstanceID;
                                        wfsi.ServerURL = AzureHelper.CurrentInternalEndpoint;

                                        WebFarmServerInfoProvider.SetWebFarmServerInfo(wfsi);
                                    }
                                }

                                // Wait until initialization is complete
                                CMSFunctions.WaitForInitialization();
                            }
                        }
                        catch (Exception ex)
                        {
                            if (closeConnection)
                            {
                                // Server connected succesfully but something else went wrong
                                throw ex;
                            }
                            else
                            {
                                // Report error about not being able to connect
                                mConnectionErrorMessage = ex.Message;

                                HttpContext.Current.Server.Transfer("~/CMSMessages/error.aspx");
                            }
                        }
                        finally
                        {
                            if (closeConnection)
                            {
                                // Close the connection
                                conn.Close();
                            }
                        }
                    }
                }
                else
                {
                    // Register virtual path provider
                    if (ValidationHelper.GetBoolean(SettingsHelper.AppSettings["CMSUseVirtualPathProvider"], true))
                    {
                        CMS.VirtualPathHelper.VirtualPathHelper.RegisterVirtualPathProvider();
                    }
                }

                // Register the CMS view engine
                CMSViewEngine.RegisterViewEngine();
            }

            // Finalize the event
            h.FinishEvent();

            DebugHelper.ReleaseContext();

            // Log when the overall application start finished its execution
            mApplicationStartFinished = DateTime.Now;
            mApplicationInitialized = true;

            RequestHelper.LogRequestOperation("AfterApplicationStart", null, 0);
        }
    }
    /// <summary>
    /// Request authorization handler.
    /// </summary>
    public static void CMSAuthorizeRequest(object sender, EventArgs e)
    {
        RequestHelper.LogRequestOperation("AuthorizeRequest", null, 0);
        DebugHelper.SetContext("AuthorizeRequest");

        if (ConnectionAvailable)
        {
            // Handle the event
            using (var h = CMSRequestEvents.Authorize.StartEvent(e))
            {
                if (h.Continue)
                {
                    string relativePath = URLHelper.CurrentRelativePath;

                    // Check the excluded status
                    ExcludedSystemEnum excludedEnum = URLHelper.IsExcludedSystemEnum(relativePath);

                    RequestHelper.CurrentExcludedStatus = excludedEnum;

                    ViewModeOnDemand viewMode = new ViewModeOnDemand();
                    SiteNameOnDemand siteName = new SiteNameOnDemand();

                    // Try to send the output from the cache without URL rewriting
                    if (URLRewriter.SendOutputFromCache(relativePath, excludedEnum, viewMode, siteName))
                    {
                        if (OutputFilter.OutputFilterEndRequestRequired)
                        {
                            HttpContext context = HttpContext.Current;
                            string newQuery = null;

                            // Ensure the raw URL as a part of the request
                            if (URLRewriter.FixRewriteRedirect)
                            {
                                newQuery = "rawUrl=" + HttpUtility.UrlEncode(context.Request.RawUrl);
                            }

                            context.RewritePath("~/CMSPages/blank.aspx", null, newQuery);
                        }
                        return;
                    }

                    // Handle the virtual context
                    HandleVirtualContext(ref relativePath, ref excludedEnum);

                    // Ensure routes for current site
                    CMSMvcHandler.EnsureRoutes(CMSContext.CurrentSiteName);
                }

                // Finalize the event
                h.FinishEvent();
            }
        }

        DebugHelper.ReleaseContext();
    }
    /// <summary>
    /// Performs the application initialization on the first request.
    /// </summary>
    private static void FirstRequestInitialization(object sender, EventArgs e)
    {
        // PreInitialize the application
        if (!mApplicationPreInitialized)
        {
            lock (mLock)
            {
                if (!mApplicationPreInitialized)
                {
                    // Remember date and time of the application start
                    mApplicationStart = DateTime.Now;

                    // Init run from web application - DON'T MOVE LATER
                    SystemHelper.IsWebSite = true;

                    mWindowsIdentity = WindowsIdentity.GetCurrent();

                    // PreInitialize the environment
                    CMSFunctions.PreInit();

                    mApplicationPreInitialized = true;
                }
            }
        }

        // Initialized properly
        bool? initialized = mApplicationInitialized.Value;
        if (initialized == true)
        {
            return;
        }

        // Not initialized, must install
        if ((initialized == false) && InstallerFunctions.InstallRedirect(true))
        {
            return;
        }

        // Do not init application on request to just physical file
        string relativePath = URLHelper.CurrentRelativePath;
        ExcludedSystemEnum excludedEnum = URLHelper.IsExcludedSystemEnum(relativePath, true);

        if ((excludedEnum == ExcludedSystemEnum.PhysicalFile) ||
            (excludedEnum == ExcludedSystemEnum.GetResource) ||
            (excludedEnum == ExcludedSystemEnum.AppThemes))
        {
            return;
        }

        // Initialize application in a locked context
        lock (mLock)
        {
            if (ApplicationInitialized)
            {
                return;
            }

            ViewModeOnDemand viewMode = new ViewModeOnDemand();

            // Log application start
            if (CMSFunctions.AnyDebugEnabled)
            {
                RequestSettings settings = RequestSettings.Current;
                bool liveSite = (viewMode.Value == ViewModeEnum.LiveSite);

                settings.DebugRequest = RequestHelper.DebugRequests && liveSite;
                RequestHelper.LogRequestOperation("BeforeApplicationStart", null, 0);

                settings.DebugSQLQueries = SqlHelperClass.DebugQueries && liveSite;
                settings.DebugFiles = File.DebugFiles && liveSite;
                settings.DebugCache = CacheHelper.DebugCache && liveSite;
                settings.DebugSecurity = SecurityHelper.DebugSecurity && liveSite;
                settings.DebugOutput = OutputHelper.DebugOutput && liveSite;
                settings.DebugMacros = MacroResolver.DebugMacros && liveSite;
                settings.DebugWebFarm = WebSyncHelperClass.DebugWebFarm && liveSite;
                settings.DebugAnalytics = AnalyticsHelper.DebugAnalytics && liveSite;

                DebugHelper.SetContext("App_Start");
            }

            // Initialize MacroResolver with child of GlobalResolver
            MacroResolver.OnGetInstance += new MacroResolver.GetInstanceEventHandler(MacroResolver_OnGetInstance);

            // Handle the event
            using (var h = CMSApplicationEvents.Start.StartEvent(e))
            {
                if (h.Continue)
                {
                    // Initialize the storage methods
                    CMSFunctions.InitStorage();

                    if (SqlHelperClass.IsConnectionStringInitialized)
                    {
                        using (CMSConnectionScope scope = new CMSConnectionScope())
                        {
                            // Use single open connection for the application start
                            GeneralConnection conn = (GeneralConnection)scope.Connection;
                            bool closeConnection = false;
                            try
                            {
                                // Open the connection
                                conn.Open();
                                closeConnection = true;

                                TableManager tm = new TableManager(null);

                                // Check for the table existence
                                if (!tm.TableExists("CMS_SettingsKey"))
                                {
                                    ApplicationInitialized = false;

                                    if (InstallerFunctions.InstallRedirect(true))
                                    {
                                        return;
                                    }
                                }

                                // Check the version
                                string version = SettingsKeyProvider.GetStringValue("CMSDBVersion");
                                if (!CMSContext.IsCorrectDatabaseVersion)
                                {
                                    // Report error about not being able to connect
                                    ConnectionErrorMessage = "The database version '" + version + "' does not match the project version '" + CMSContext.SYSTEM_VERSION + "', please check your connection string.";
                                    HttpContext.Current.Server.Transfer("~/CMSMessages/error.aspx");
                                }
                                else
                                {
                                    // Initialize the environment
                                    CMSFunctions.Init();

                                    // Update the system !! IMPORTANT - must be first
                                    UpgradeProcedure.Update(conn);
                                    try
                                    {
                                        // Write "Application start" event to the event log
                                        EventLogProvider ev = new EventLogProvider();

                                        ev.DeleteOlderLogs = false;
                                        ev.LogEvent(EventLogProvider.EVENT_TYPE_INFORMATION, DateTime.Now, "Application_Start", "STARTAPP", 0, null, 0, null, null, null, 0, HTTPHelper.GetAbsoluteUri());
                                    }
                                    catch
                                    {
                                        // can't write to log, do not process any code
                                    }
                                    UserInfoProvider.OnFormattedUserName += new UserInfoProvider.FormattedUserNameEventHandler(Functions.GetFormattedUserName);

                                    // Initialize the web farm
                                    CMSFunctions.InitWebFarm();

                                    // Handle admin emergency reset
                                    string adminReset = ValidationHelper.GetString(SettingsHelper.AppSettings["CMSAdminEmergencyReset"], null);
                                    if (!string.IsNullOrEmpty(adminReset))
                                    {
                                        string[] resetParams = adminReset.Split(';');
                                        if ((resetParams.Length >= 1) && (resetParams.Length <= 3))
                                        {
                                            // Check if create user if she doesn't exist
                                            bool forceCreate = (resetParams.Length == 3) ? ValidationHelper.GetBoolean(resetParams[2], false) : false;
                                            string userName = resetParams[0];
                                            UserInfo ui = UserInfoProvider.GetUserInfo(userName);

                                            // Create new user
                                            if ((ui == null) && forceCreate)
                                            {
                                                if (UserInfoProvider.LicenseVersionCheck(URLHelper.GetCurrentDomain(), FeatureEnum.GlobalAdmininistrators, VersionActionEnum.Insert, false))
                                                {
                                                    if (ValidationHelper.IsUserName(userName))
                                                    {
                                                        ui = new UserInfo();
                                                        ui.UserName = resetParams[0];
                                                        ui.UserIsGlobalAdministrator = true;
                                                        ui.UserEnabled = true;

                                                        string error = null;
                                                        UserInfoProvider.CheckLicenseLimitation(ui, ref error);
                                                        if (!string.IsNullOrEmpty(error))
                                                        {
                                                            throw new Exception(string.Format("[FirstRequestInitialization.AdminEmergencyReset: {0}]", error));
                                                        }
                                                    }
                                                    else
                                                    {
                                                        throw new Exception("[FirstRequestInitialization.AdminEmergencyReset: Specified username for newly created user is not valid.]");
                                                    }
                                                }
                                            }

                                            // Unlock account and set new specified password
                                            if (ui != null)
                                            {
                                                UserInfoProvider.SetPassword(ui, (resetParams.Length > 1) ? resetParams[1] : "", false);
                                                AuthenticationHelper.UnlockUserAccount(ui);
                                            }

                                            // Remove key from web.config
                                            SettingsHelper.RemoveConfigValue("CMSAdminEmergencyReset");
                                            URLHelper.Redirect(URLHelper.CurrentURL);
                                        }
                                    }

                                    // Wait until initialization is complete
                                    CMSFunctions.WaitForInitialization();
                                }
                            }
                            catch (Exception ex)
                            {
                                if (closeConnection)
                                {
                                    // Server connected successfully but something else went wrong
                                    throw ex;
                                }
                                else
                                {
                                    // Report error about not being able to connect
                                    ConnectionErrorMessage = ex.Message;

                                    HttpContext.Current.Server.Transfer("~/CMSMessages/error.aspx");
                                }
                            }
                            finally
                            {
                                if (closeConnection)
                                {
                                    // Close the connection
                                    conn.Close();
                                }
                            }
                        }

                        DBSeparationCheck();
                    }
                    else
                    {
                        // Register virtual path provider
                        if (ValidationHelper.GetBoolean(SettingsHelper.AppSettings["CMSUseVirtualPathProvider"], true))
                        {
                            VirtualPathHelper.RegisterVirtualPathProvider();
                        }
                    }

                    // Register the CMS view engine
                    CMSWebFormViewEngine.RegisterViewEngine();
                }

                // Finalize the event
                h.FinishEvent();
            }

            DebugHelper.ReleaseContext();

            // Log when the overall application start finished its execution
            mApplicationStartFinished = DateTime.Now;
            ApplicationInitialized = true;

            RequestHelper.LogRequestOperation("AfterApplicationStart", null, 0);
        }
    }