/// <summary> 
        /// Gets the Tab Dictionary from the DataCache memory location, if it's empty or missing, builds a new one 
        /// </summary>
        /// <param name="portalId"></param>
        /// <param name="minTabPathDepth">ByRef parameter to return the minimum tab path depth (the number of '/' in the tab path)</param> 
        /// <param name="maxTabPathDepth">ByRef parameter to return the maximum tab path depth (the number of '/' in the tab path)</param> 
        /// <param name="minAliasPathDepth">ByRef parameter to return the minimum alias path depth (the number of '/' in the alias path</param> 
        /// <param name="maxAliasPathDepth">ByRef parameter to return the maximum alias path depth (the number of '/' in the alias path)</param>
        /// <param name="settings"></param>
        /// <param name="forceRebuild"></param>
        /// <param name="bypassCache"></param>
        /// <param name="parentTraceId"></param>
        /// <returns>Dictionary (string, string) of Tab paths in tab key, with the rewrite path as the value</returns> 
        /// <remarks>
        /// Changes
        /// Task 608 : Incrementally build tab dictionary instead of building entire dicitionary all at once
        /// Task 609 : If usePortalAlias is specified, only build dictionary with specific portal alias : ignore others
        /// Task 791 : allow for specification of true/false for using thread locking to prevent multiple rebuilds on threads
        /// </remarks> 
        internal static SharedDictionary<string, string> FetchTabDictionary(int portalId,
                                                                                out int minTabPathDepth,
                                                                                out int maxTabPathDepth,
                                                                                out int minAliasPathDepth,
                                                                                out int maxAliasPathDepth,
                                                                                FriendlyUrlSettings settings,
                                                                                bool forceRebuild,
                                                                                bool bypassCache,
                                                                                Guid parentTraceId)
        {
            SharedDictionary<int, PathSizes> portalDepths;
            SharedDictionary<string, string> dict;

            //place threadlock to prevent two threads getting a null object
            //check for the tab dictionary in the DataCache
            var cc = new CacheController();
            cc.GetPageIndexFromCache(out dict, out portalDepths, settings);

            string reason = "";
            if (dict == null)
            {
                reason += "No Page index in cache;";
            }
            if (forceRebuild)
            {
                reason += "Force Rebuild;";
            }
            if (bypassCache)
            {
                reason += "Bypass Cache;";
            }
            if (dict != null)
            {
                using (dict.GetReadLock())
                {
                    reason += "Existing Page Index=" + dict.Count.ToString() + " items;";
                }
            }

            Hashtable homePageSkins; //keeps a list of skins set per home page and culture
            SharedDictionary<string, string> portalTabPathDictionary;
            if (dict != null && portalDepths != null && forceRebuild == false && bypassCache == false)
            {
                PathSizes depthInfo;
                bool changed = false;
                using (portalDepths.GetWriteLock())
                {
                    if (!portalDepths.ContainsKey(portalId))
                    {
                        reason += "Portal " + portalId.ToString() + " added to index;";

                        //tab dictionary built, but portal not in it
                        dict = BuildTabDictionary(out depthInfo,
                                                    settings,
                                                    portalId,
                                                    dict,
                                                    out homePageSkins,
                                                    out portalTabPathDictionary,
                                                    parentTraceId);

                        //recheck portal add, when running with locks can get duplicate key exceptions
                        if (portalDepths.ContainsKey(portalId) == false)
                        {
                            portalDepths.Add(portalId, depthInfo);
                            changed = true;
                        }

                        cc.StoreTabPathsInCache(portalId, portalTabPathDictionary, settings);
                        CacheController.StoreHomePageSkinsInCache(portalId, homePageSkins);
                    }
                    else
                    {
                        depthInfo = portalDepths[portalId];
                    }
                }
                if (changed)
                {
                    //restash dictionary
                    cc.StorePageIndexInCache(dict, portalDepths, settings, reason);
                }

                if (depthInfo != null)
                {
                    minTabPathDepth = depthInfo.MinTabPathDepth;
                    maxTabPathDepth = depthInfo.MaxTabPathDepth;
                    minAliasPathDepth = depthInfo.MinAliasDepth;
                    maxAliasPathDepth = depthInfo.MaxAliasDepth;
                }
                else
                {
                    //fallback values, should never get here: mainly for compiler wranings
                    minTabPathDepth = 1;
                    maxTabPathDepth = 10;
                    minAliasPathDepth = 1;
                    maxAliasPathDepth = 4;
                }
            }
            else
            {
                //the cached dictionary was null or forceRebuild = true or bypassCache = true, so go get a new dictionary
                PathSizes depthInfo;
                dict = BuildTabDictionary(out depthInfo,
                                            settings,
                                            portalId,
                                            null,
                                            out homePageSkins,
                                            out portalTabPathDictionary,
                                            parentTraceId);

                //store the fact that this portal has been built
                portalDepths = new SharedDictionary<int, PathSizes>();
                using (portalDepths.GetWriteLock())
                {
                    portalDepths.Add(portalId, depthInfo);
                }
                if (bypassCache == false) //only cache if bypass not switched on
                {
                    cc.StorePageIndexInCache(dict, portalDepths, settings, reason);
                }
                cc.StoreTabPathsInCache(portalId, portalTabPathDictionary, settings);
                CacheController.StoreHomePageSkinsInCache(portalId, homePageSkins);
                minTabPathDepth = depthInfo.MinTabPathDepth;
                maxTabPathDepth = depthInfo.MaxTabPathDepth;
                minAliasPathDepth = depthInfo.MinAliasDepth;
                maxAliasPathDepth = depthInfo.MaxAliasDepth;
            }
            return dict;
        }
        /// <summary>
        /// returns a tabId indexed dictionary of Friendly Urls
        /// </summary>
        /// <param name="portalId"></param>
        /// <param name="forceRebuild"></param>
        /// <param name="bypassCache"></param>
        /// <param name="settings"></param>
        /// <param name="customAliasForTabs"></param>
        /// <param name="parentTraceId"></param>
        /// <returns></returns>
        internal static SharedDictionary<int, SharedDictionary<string, string>> FetchCustomUrlDictionary(int portalId, 
                                    bool forceRebuild, 
                                    bool bypassCache, 
                                    FriendlyUrlSettings settings,
                                    out SharedDictionary<string, string> customAliasForTabs, 
                                    Guid parentTraceId)
        {
            SharedDictionary<int, SharedDictionary<string, string>> urlDict;
            //this contains a list of all tabs for all the portals that have been retrieved
            List<int> urlPortals; //this contains a list of the portals that have been retrieved
            //get the objects from the cache
            var cc = new CacheController();
            cc.GetFriendlyUrlIndexFromCache(out urlDict, out urlPortals, out customAliasForTabs);

            if (urlDict != null && forceRebuild == false && bypassCache == false)
            {
                if (urlPortals == null)
                //no portals retrieved from cache, but was a dictionary.  Bit weird, but we'll run with it
                {
                    urlPortals = new List<int>();
                }

                //check to see if this portal has been included in the dict
                if (urlPortals.Contains(portalId) == false)
                {
                    //ok, there is a url dictionary, but this portal isn't in it, so 
                    //put it in and get the urls for this portal
                    //this call appends extra portals to the list
                    urlDict = BuildUrlDictionary(urlDict, portalId, settings, ref customAliasForTabs);
                    urlPortals.Add(portalId);

                    cc.StoreFriendlyUrlIndexInCache(urlDict,
                                                urlPortals,
                                                customAliasForTabs, settings,
                                                "Portal Id " + portalId.ToString() + " added to index.");
                }
            }
            else //either values are null (Not in cache) or we want to force the rebuild, or we want to bypass the cache
            {
                //rebuild the dictionary for this portal
                urlDict = BuildUrlDictionary(urlDict, portalId, settings, ref customAliasForTabs);
                urlPortals = new List<int> { portalId }; //always rebuild the portal list
                if (bypassCache == false) //if we are to cache this item (byPassCache = false)
                {
                    //cache these items
                    string reason = forceRebuild ? "Force Rebuild of Index" : "Index not in cache";
                    cc.StoreFriendlyUrlIndexInCache(urlDict, urlPortals, customAliasForTabs, settings, reason);
                }
            }
            return urlDict;
        }
Example #3
0
        internal static bool CheckForParameterRedirect(
            Uri requestUri,
            ref UrlAction result,
            NameValueCollection queryStringCol,
            FriendlyUrlSettings settings)
        {
            // check for parameter replaced works by inspecting the parameters on a rewritten request, comparing
            // them agains the list of regex expressions on the friendlyurls.config file, and redirecting to the same page
            // but with new parameters, if there was a match
            bool redirect = false;

            // get the redirect actions for this portal
            var messages = new List <string>();
            Dictionary <int, List <ParameterRedirectAction> > redirectActions = CacheController.GetParameterRedirects(settings, result.PortalId, ref messages);

            if (redirectActions != null && redirectActions.Count > 0)
            {
                try
                {
                    string rewrittenUrl = result.RewritePath ?? result.RawUrl;

                    List <ParameterRedirectAction> parmRedirects = null;

                    // find the matching redirects for the tabid
                    int tabId = result.TabId;
                    if (tabId > -1)
                    {
                        if (redirectActions.ContainsKey(tabId))
                        {
                            // find the right set of replaced actions for this tab
                            parmRedirects = redirectActions[tabId];
                        }
                    }

                    // check for 'all tabs' redirections
                    if (redirectActions.ContainsKey(-1)) // -1 means 'all tabs' - rewriting across all tabs
                    {
                        // initialise to empty collection if there are no specific tab redirects
                        if (parmRedirects == null)
                        {
                            parmRedirects = new List <ParameterRedirectAction>();
                        }

                        // add in the all redirects
                        List <ParameterRedirectAction> allRedirects = redirectActions[-1];
                        parmRedirects.AddRange(allRedirects); // add the 'all' range to the tab range
                        tabId = result.TabId;
                    }

                    if (redirectActions.ContainsKey(-2) && result.OriginalPath.ToLowerInvariant().Contains("default.aspx"))
                    {
                        // for the default.aspx page
                        if (parmRedirects == null)
                        {
                            parmRedirects = new List <ParameterRedirectAction>();
                        }

                        List <ParameterRedirectAction> defaultRedirects = redirectActions[-2];
                        parmRedirects.AddRange(defaultRedirects); // add the default.aspx redirects to the list
                        tabId = result.TabId;
                    }

                    // 726 : allow for site-root redirects, ie redirects where no page match
                    if (redirectActions.ContainsKey(-3))
                    {
                        // request is for site root
                        if (parmRedirects == null)
                        {
                            parmRedirects = new List <ParameterRedirectAction>();
                        }

                        List <ParameterRedirectAction> siteRootRedirects = redirectActions[-3];
                        parmRedirects.AddRange(siteRootRedirects); // add the site root redirects to the collection
                    }

                    // OK what we have now is a list of redirects for the currently requested tab (either because it was specified by tab id,
                    // or because there is a replaced for 'all tabs'
                    if (parmRedirects != null && parmRedirects.Count > 0 && rewrittenUrl != null)
                    {
                        foreach (ParameterRedirectAction parmRedirect in parmRedirects)
                        {
                            // regex test each replaced to see if there is a match between the parameter string
                            // and the parmRedirect
                            string compareWith   = rewrittenUrl;
                            var    redirectRegex = RegexUtils.GetCachedRegex(
                                parmRedirect.LookFor,
                                RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
                            Match regexMatch    = redirectRegex.Match(compareWith);
                            bool  success       = regexMatch.Success;
                            bool  siteRootTried = false;

                            // if no match, but there is a site root redirect to try
                            if (!success && parmRedirect.TabId == -3)
                            {
                                siteRootTried = true;
                                compareWith   = result.OriginalPathNoAlias;
                                regexMatch    = redirectRegex.Match(compareWith);
                                success       = regexMatch.Success;
                            }

                            if (!success)
                            {
                                result.DebugMessages.Add(parmRedirect.Name + " redirect not matched (" + rewrittenUrl +
                                                         ")");
                                if (siteRootTried)
                                {
                                    result.DebugMessages.Add(parmRedirect.Name + " redirect not matched [site root] (" +
                                                             result.OriginalPathNoAlias + ")");
                                }
                            }
                            else
                            {
                                // success! there was a match in the parameters
                                string parms = redirectRegex.Replace(compareWith, parmRedirect.RedirectTo);
                                if (siteRootTried)
                                {
                                    result.DebugMessages.Add(parmRedirect.Name + " redirect matched [site root] with (" +
                                                             result.OriginalPathNoAlias + "), replaced with " + parms);
                                }
                                else
                                {
                                    result.DebugMessages.Add(parmRedirect.Name + " redirect matched with (" +
                                                             compareWith + "), replaced with " + parms);
                                }

                                string finalUrl = string.Empty;

                                // now we need to generate the friendly Url

                                // first check to see if the parameter replacement string has a destination tabid specified
                                if (parms.ToLowerInvariant().Contains("tabid/"))
                                {
                                    // if so, using a feature whereby the dest tabid can be changed within the parameters, which will
                                    // redirect the page as well as redirecting the parameter values
                                    string[] parmParts = parms.Split('/');
                                    bool     tabIdNext = false;
                                    foreach (string parmPart in parmParts)
                                    {
                                        if (tabIdNext)
                                        {
                                            // changes the tabid of page, effects a page redirect along with a parameter redirect
                                            int.TryParse(parmPart, out tabId);
                                            parms = parms.Replace("tabid/" + tabId.ToString(), string.Empty);

                                            // remove the tabid/xx from the path
                                            break; // that's it, we're finished
                                        }

                                        if (parmPart.Equals("tabid", StringComparison.InvariantCultureIgnoreCase))
                                        {
                                            tabIdNext = true;
                                        }
                                    }
                                }
                                else if (tabId == -1)
                                {
                                    // find the home tabid for this portal
                                    // 735 : switch to custom method for getting portal
                                    PortalInfo portal = CacheController.GetPortal(result.PortalId, true);
                                    tabId = portal.HomeTabId;
                                }

                                if (parmRedirect.ChangeToSiteRoot)
                                {
                                    // when change to siteroot requested, new path goes directly off the portal alias
                                    // so set the finalUrl as the poratl alias
                                    finalUrl = result.Scheme + result.HttpAlias + "/";
                                }
                                else
                                {
                                    // if the tabid has been supplied, do a friendly url provider lookup to get the correct format for the tab url
                                    if (tabId > -1)
                                    {
                                        TabInfo tab = TabController.Instance.GetTab(tabId, result.PortalId, false);
                                        if (tab != null)
                                        {
                                            string path = Globals.glbDefaultPage + TabIndexController.CreateRewritePath(tab.TabID, string.Empty);
                                            string friendlyUrlNoParms = AdvancedFriendlyUrlProvider.ImprovedFriendlyUrl(
                                                tab,
                                                path,
                                                Globals.glbDefaultPage,
                                                result.HttpAlias,
                                                false,
                                                settings,
                                                Guid.Empty);
                                            if (friendlyUrlNoParms.EndsWith("/") == false)
                                            {
                                                friendlyUrlNoParms += "/";
                                            }

                                            finalUrl = friendlyUrlNoParms;
                                        }

                                        if (tab == null)
                                        {
                                            result.DebugMessages.Add(parmRedirect.Name +
                                                                     " tabId in redirect rule (tabId:" +
                                                                     tabId.ToString() + ", portalId:" +
                                                                     result.PortalId.ToString() +
                                                                     " ), tab was not found");
                                        }
                                        else
                                        {
                                            result.DebugMessages.Add(parmRedirect.Name +
                                                                     " tabId in redirect rule (tabId:" +
                                                                     tabId.ToString() + ", portalId:" +
                                                                     result.PortalId.ToString() + " ), tab found : " +
                                                                     tab.TabName);
                                        }
                                    }
                                }

                                if (parms.StartsWith("//"))
                                {
                                    parms = parms.Substring(2);
                                }

                                if (parms.StartsWith("/"))
                                {
                                    parms = parms.Substring(1);
                                }

                                if (settings.PageExtensionUsageType != PageExtensionUsageType.Never)
                                {
                                    if (parms.EndsWith("/"))
                                    {
                                        parms = parms.TrimEnd('/');
                                    }

                                    if (parms.Length > 0)
                                    {
                                        // we are adding more parms onto the end, so remove the page extension
                                        // from the parameter list
                                        // 946 : exception when settings.PageExtension value is empty
                                        parms += settings.PageExtension;

                                        // 816: if page extension is /, then don't do this
                                        if (settings.PageExtension != "/" &&
                                            string.IsNullOrEmpty(settings.PageExtension) == false)
                                        {
                                            finalUrl = finalUrl.Replace(settings.PageExtension, string.Empty);
                                        }
                                    }
                                    else
                                    {
                                        // we are removing all the parms altogether, so
                                        // the url needs to end in the page extension only
                                        // 816: if page extension is /, then don't do this
                                        if (settings.PageExtension != "/" &&
                                            string.IsNullOrEmpty(settings.PageExtension) == false)
                                        {
                                            finalUrl = finalUrl.Replace(
                                                settings.PageExtension + "/",
                                                settings.PageExtension);
                                        }
                                    }
                                }

                                // put the replaced parms back on the end
                                finalUrl += parms;

                                // set the final url
                                result.FinalUrl = finalUrl;
                                result.Reason   = RedirectReason.Custom_Redirect;
                                switch (parmRedirect.Action)
                                {
                                case "301":
                                    result.Action = ActionType.Redirect301;
                                    break;

                                case "302":
                                    result.Action = ActionType.Redirect302;
                                    break;

                                case "404":
                                    result.Action = ActionType.Output404;
                                    break;
                                }

                                redirect = true;
                                break;
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Services.Exceptions.Exceptions.LogException(ex);
                    messages.Add("Exception: " + ex.Message + "\n" + ex.StackTrace);
                }
                finally
                {
                    if (messages.Count > 0)
                    {
                        result.DebugMessages.AddRange(messages);
                    }
                }
            }

            return(redirect);
        }
Example #4
0
        /// <summary>
        /// This method checks the list of rules for parameter replacement and modifies the parameter path accordingly
        /// </summary>
        /// <param name="parameterPath"></param>
        /// <param name="tab"></param>
        /// <param name="settings"></param>
        /// <param name="portalId"></param>
        /// <param name="replacedPath"></param>
        /// <param name="messages"></param>
        /// <param name="changeToSiteRoot"></param>
        /// <param name="parentTraceId"></param>
        /// <returns></returns>
        internal static bool CheckParameterRegexReplacement(string parameterPath,
                                                            TabInfo tab,
                                                            FriendlyUrlSettings settings,
                                                            int portalId,
                                                            out string replacedPath,
                                                            ref List <string> messages,
                                                            out bool changeToSiteRoot,
                                                            Guid parentTraceId)
        {
            bool replaced = false;

            replacedPath     = "";
            changeToSiteRoot = false;
            if (messages == null)
            {
                messages = new List <string>();
            }

            var replaceActions = CacheController.GetParameterReplacements(settings, portalId, ref messages);

            if (replaceActions != null && replaceActions.Count > 0)
            {
                List <ParameterReplaceAction> parmReplaces = null;
                int tabId = tab.TabID;

                if (replaceActions.ContainsKey(tabId))
                {
                    //find the right set of replaced actions for this tab
                    parmReplaces = replaceActions[tabId];
                }

                //check for 'all tabs' replaceions
                if (replaceActions.ContainsKey(-1)) //-1 means 'all tabs' - replacing across all tabs
                {
                    //initialise to empty collection if there are no specific tab replaces
                    if (parmReplaces == null)
                    {
                        parmReplaces = new List <ParameterReplaceAction>();
                    }
                    //add in the all replaces
                    List <ParameterReplaceAction> allReplaces = replaceActions[-1];
                    parmReplaces.AddRange(allReplaces); //add the 'all' range to the tab range
                }
                if (parmReplaces != null)
                {
                    //OK what we have now is a list of replaces for the currently requested tab (either because it was specified by tab id,
                    // or because there is a replaced for 'all tabs'
                    try
                    {
                        foreach (ParameterReplaceAction parmReplace in parmReplaces)
                        {
                            //do a regex on the 'lookFor' in the parameter path
                            var parmRegex = RegexUtils.GetCachedRegex(parmReplace.LookFor,
                                                                      RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
                            if (parmRegex.IsMatch(parameterPath))
                            {
                                replacedPath = parmRegex.Replace(parameterPath, parmReplace.ReplaceWith);
                                messages.Add(parmReplace.Name + " replace rule match, replaced : " + parameterPath + " with: " + replacedPath);
                                replaced = true;
                                //593: if this replacement is marked as a site root replacement, we will be
                                //removing the page path from the final url
                                changeToSiteRoot = parmReplace.ChangeToSiteRoot;
                                break;
                            }
                            messages.Add(parmReplace.Name + " replace rule not matched {" + parameterPath + "}");
                        }
                    }
                    catch (Exception ex)
                    {
                        //catch exceptions here because most likely to be related to regular expressions
                        //don't want to kill entire site because of this
                        Services.Exceptions.Exceptions.LogException(ex);
                        messages.Add("Exception : " + ex.Message + "\n" + ex.StackTrace);
                    }
                }
            }
            return(replaced);
        }
Example #5
0
 internal static void InvalidateDictionary()
 {
     CacheController.FlushPageIndexFromCache();
 }