internal static bool TransformFriendlyUrlPath(string newUrl,
                                                      string tabKeyVal,
                                                      string[] urlParms,
                                                      bool isSiteRootMatch,
                                                      ref UrlAction result,
                                                      FriendlyUrlSettings settings,
                                                      out string rewrittenUrl,
                                                      out bool newAction,
                                                      ref List <string> messages,
                                                      Guid parentTraceId)
        {
            bool rewriteDone = false;

            rewrittenUrl = newUrl;
            newAction    = false;
            ExtensionUrlProvider activeProvider = null;

            try
            {
                int tabId = result.TabId;
                if (isSiteRootMatch)
                {
                    tabId = RewriteController.SiteRootRewrite;
                }
                List <ExtensionUrlProvider> providersToCall = GetProvidersToCall(tabId,
                                                                                 result.PortalId,
                                                                                 settings,
                                                                                 parentTraceId);
                if (providersToCall != null && providersToCall.Count > 0)
                {
                    //now check for providers by calling the providers
                    int upperBound = urlParms.GetUpperBound(0);
                    //clean extension off parameters array
                    var parms = new string[upperBound + 1];
                    Array.ConstrainedCopy(urlParms, 0, parms, 0, upperBound + 1);
                    if (upperBound >= 0)
                    {
                        bool replaced;
                        parms[upperBound] = RewriteController.CleanExtension(parms[upperBound], settings, out replaced);
                    }
                    //get options from current settings
                    FriendlyUrlOptions options = UrlRewriterUtils.GetOptionsFromSettings(settings);
                    foreach (ExtensionUrlProvider provider in providersToCall)
                    {
                        //set active provider for exception handling
                        activeProvider = provider;
                        //call down to specific providers and see if we get a rewrite
                        string location;
                        int    status;
                        string queryString = provider.TransformFriendlyUrlToQueryString(parms,
                                                                                        result.TabId,
                                                                                        result.PortalId,
                                                                                        options,
                                                                                        result.CultureCode,
                                                                                        result.PortalAlias,
                                                                                        ref messages,
                                                                                        out status,
                                                                                        out location);
                        if (status == 0 || status == 200) //either not set, or set to '200 OK'.
                        {
                            if (!string.IsNullOrEmpty(queryString) && queryString != newUrl)
                            {
                                rewriteDone = true;
                                //check for duplicate tabIds.
                                string qsRemainder = null;
                                if (Regex.IsMatch(queryString, @"tabid=\d+", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant))
                                {
                                    //930 : look for other querystring information in the rewritten Url, or invalid rewritten urls can be created
                                    //pattern to determine which tab matches
                                    //look for any other querystirng information in the already rewritten Url (ie language parameters)
                                    Match rewrittenUrlMatch = RewrittenUrlRegex.Match(rewrittenUrl);
                                    if (rewrittenUrlMatch.Groups["qs"].Success)
                                    {
                                        //keep any other querystring remainders
                                        qsRemainder = rewrittenUrlMatch.Groups["qs"].Captures.Cast <Capture>().Aggregate("", (current, qsCapture) => current + qsCapture.Value); //initialise
                                    }
                                    //supplied value overwrites existing value, so remove from the rewritten url
                                    rewrittenUrl = RewrittenUrlRegex.Replace(rewrittenUrl, "");
                                }
                                if (rewrittenUrl.Contains("?") == false)
                                {
                                    //use a leading ?, not a leading &
                                    queryString = FriendlyUrlController.EnsureNotLeadingChar("&", queryString);
                                    queryString = FriendlyUrlController.EnsureLeadingChar("?", queryString);
                                }
                                else
                                {
                                    //use a leading &, not a leading ?
                                    queryString = FriendlyUrlController.EnsureNotLeadingChar("?", queryString);
                                    queryString = FriendlyUrlController.EnsureLeadingChar("&", queryString);
                                }

                                //add querystring onto rewritten Url
                                rewrittenUrl += queryString;
                                if (qsRemainder != null)
                                {
                                    rewrittenUrl += qsRemainder;
                                }
                                break;
                            }
                        }
                        else
                        {
                            switch (status)
                            {
                            case 301:
                                result.Action   = ActionType.Redirect301;
                                result.Reason   = RedirectReason.Module_Provider_Rewrite_Redirect;
                                result.FinalUrl = location;
                                break;

                            case 302:
                                result.Action   = ActionType.Redirect302;
                                result.Reason   = RedirectReason.Module_Provider_Rewrite_Redirect;
                                result.FinalUrl = location;
                                break;

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

                            case 500:
                                result.Action = ActionType.Output500;
                                break;
                            }
                            newAction = true; //not doing a 200 status
                            break;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                //log module provider exception
                LogModuleProviderExceptionInRequest(ex, "500 Internal Server Error", activeProvider, result, messages);
                //reset values to initial
                rewriteDone  = false;
                rewrittenUrl = newUrl;
                newAction    = false;
                string providerName = "Unknown";
                if (activeProvider != null)
                {
                    providerName = activeProvider.ProviderConfig.ProviderName;
                }
                if (result != null)
                {
                    result.DebugMessages.Add("Exception in provider [" + providerName + "] :" + ex.Message);
                }
            }
            return(rewriteDone);
        }
        internal static bool GetUrlFromExtensionUrlProviders(int portalId,
                                                             TabInfo tab,
                                                             FriendlyUrlSettings settings,
                                                             string friendlyUrlPath,
                                                             string cultureCode,
                                                             ref string endingPageName,
                                                             out string changedPath,
                                                             out bool changeToSiteRoot,
                                                             ref List <string> messages,
                                                             Guid parentTraceId)
        {
            bool wasChanged = false;

            changedPath      = friendlyUrlPath;
            changeToSiteRoot = false;
            ExtensionUrlProvider activeProvider = null;

            if (messages == null)
            {
                messages = new List <string>();
            }
            try
            {
                List <ExtensionUrlProvider> providersToCall = GetProvidersToCall(tab.TabID, portalId, settings,
                                                                                 parentTraceId);
                FriendlyUrlOptions options = UrlRewriterUtils.GetOptionsFromSettings(settings);
                foreach (ExtensionUrlProvider provider in providersToCall)
                {
                    activeProvider = provider; //keep for exception purposes
                    bool useDnnPagePath;
                    //go through and call each provider to generate the friendly urls for the module
                    string customPath = provider.ChangeFriendlyUrl(tab,
                                                                   friendlyUrlPath,
                                                                   options,
                                                                   cultureCode,
                                                                   ref endingPageName,
                                                                   out useDnnPagePath,
                                                                   ref messages);

                    if (string.IsNullOrEmpty(endingPageName))
                    {
                        endingPageName = Globals.glbDefaultPage; //set back to default.aspx if provider cleared it
                    }
                    //now check to see if a change was made or not.  Don't trust the provider.
                    if (!string.IsNullOrEmpty(customPath))
                    {
                        //was customPath any different to friendlyUrlPath?
                        if (String.CompareOrdinal(customPath, friendlyUrlPath) != 0)
                        {
                            wasChanged       = true;
                            changedPath      = customPath.Trim();
                            changeToSiteRoot = !useDnnPagePath; //useDNNpagePath means no change to site root.
                            const string format = "Path returned from {0} -> path:{1}, ending Page:{2}, use Page Path:{3}";
                            messages.Add(string.Format(format, provider.ProviderConfig.ProviderName, customPath, endingPageName, useDnnPagePath));
                            break; //first module provider to change the Url is the only one used
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogModuleProviderExceptionInRequest(ex, "500 Internal Server Error", activeProvider, null, messages);
                //reset all values to defaults
                wasChanged       = false;
                changedPath      = friendlyUrlPath;
                changeToSiteRoot = false;
            }
            return(wasChanged);
        }