private void Initalize()
        {
            UrlMappingConfig config = UrlMappingConfig.Instance;

            _provider = ServiceLocator.Instance.Resolve <IUrlMappingProvider>();

            _noMatchAction                 = config.NoMatchAction;
            _noMatchRedirectPage           = config.NoMatchRedirectUrl;
            _automaticallyUpdateFormAction = config.AutoUpdateFormAction;
            _qsBehavior      = config.IncomingQueryStringBehavior;
            _processingEvent = config.UrlProcessingEvent;

            if (_provider != null)
            {
                _provider.Initialize(config);
            }

            // save to config
            config.Provider = _provider;
        }
Example #2
0
        private static UrlMappingItem getUrlInfo(XmlNode node, NavigationItem menuItem, int index, int subIndex, int subsubIndex, IncomingQueryStringBehavior incomingQueryStringBehavior)
        {
            string name        = XmlUtil.GetStringAttribute(node, "name", string.Empty);
            string urlTemplate = XmlUtil.GetStringAttribute(node, "template", string.Empty);

            if (string.IsNullOrEmpty(urlTemplate))
            {
                throw new UrlMappingException("There is an XmlUrlMappingModule error.  All <url> tags in the mapping file require a 'template' attribute.");
            }

            string redirection = Utility.GetHref(XmlUtil.GetStringAttribute(node, "href", string.Empty));

            // still here, we can create the item and add to the collection
            UrlMappingItem item
                = Utility.CreateTemplatedMappingItem(
                      name, urlTemplate, redirection, incomingQueryStringBehavior
                      );

            item.UrlTemplate = urlTemplate;

            // set custom attributes
            foreach (XmlAttribute attr in node.Attributes)
            {
                item[attr.Name] = attr.Value;
            }

            if (XmlUtil.GetStringAttribute(node, "index", string.Empty) == "?")
            {
                item.Index = null;
            }
            else
            {
                item.Index = index;
            }

            if (XmlUtil.GetStringAttribute(node, "subindex", string.Empty) == "?")
            {
                item.SubIndex = null;
            }
            else
            {
                item.SubIndex = subIndex;
            }

            if (XmlUtil.GetStringAttribute(node, "subsubindex", string.Empty) == "?")
            {
                item.SubsubIndex = null;
            }
            else
            {
                item.SubsubIndex = subsubIndex;
            }

            item.Title = XmlUtil.GetStringAttribute(node, "title", menuItem.Title);

            item.Id     = XmlUtil.GetStringAttribute(node, "id", null);
            item.Action = XmlUtil.GetStringAttribute(node, "action", null);

            return(item);
        }
Example #3
0
        public static void ParseXml(string file, UrlMappingItemCollection routes, Dictionary <int, NavigationItem> menuItems, IncomingQueryStringBehavior incomingQueryStringBehavior)
        {
            if (!File.Exists(file))
            {
                return;
            }

            XmlDocument xml = new XmlDocument();

            try
            {
                xml.Load(file);
            }
            catch (Exception ex)
            {
                throw new UrlMappingException("The error occurred while loading the route files.  A virtual path is required and the file must be well-formed.", ex);
            }

            menuItems.Clear();

            int i = -1, j = -1, k = -1;

            foreach (XmlNode node in xml.DocumentElement.ChildNodes)
            {
                if (node.Name == "menu")
                {
                    i++;
                    NavigationItem menuItem = getMenuItem(node);
                    menuItem.Children = new Dictionary <int, NavigationItem>();

                    menuItems[i] = menuItem;

                    foreach (XmlNode subNode in node.ChildNodes)
                    {
                        if (subNode.Name == "menu")
                        {
                            j++;
                            NavigationItem sub_menuItem = getMenuItem(subNode);
                            sub_menuItem.Children = new Dictionary <int, NavigationItem>();

                            menuItems[i].Children[j] = sub_menuItem;

                            foreach (XmlNode subsubNode in subNode.ChildNodes)
                            {
                                if (subsubNode.Name == "menu")
                                {
                                    k++;
                                    NavigationItem subsub_menuItem = getMenuItem(subsubNode);
                                    sub_menuItem.Children[k] = subsub_menuItem;

                                    foreach (XmlNode last_node in subsubNode.ChildNodes)
                                    {
                                        if (last_node.Name == "url")
                                        {
                                            UrlMappingItem url = getUrlInfo(last_node, subsub_menuItem, i, j, k, incomingQueryStringBehavior);

                                            routes.Add(url);
                                        }
                                    }
                                }
                                else if (subsubNode.Name == "url")
                                {
                                    UrlMappingItem url = getUrlInfo(subsubNode, sub_menuItem, i, j, -1, incomingQueryStringBehavior);

                                    routes.Add(url);
                                }
                            }
                        }
                        else if (subNode.Name == "url")
                        {
                            UrlMappingItem url = getUrlInfo(subNode, menuItem, i, -1, -1, incomingQueryStringBehavior);

                            routes.Add(url);
                        }
                    }
                }
                else if (node.Name == "url")
                {
                    UrlMappingItem url = getUrlInfo(node, new NavigationItem(), -1, -1, -1, incomingQueryStringBehavior);

                    routes.Add(url);
                }
            }
        }
Example #4
0
 /// <summary>
 /// Return a regular expression translated from the given templated URL.
 /// </summary>
 /// <param name="templatedUrl">A URL pattern relative to the application, with [TokenNames] included for dynamic matching</param>
 /// <param name="qsBehavior">defines how the UrlMappingModule should treat querystring values on an incoming URL for pattern matching; this is typically provided through declarative configuration</param>
 /// <returns>A regular expression as a <see cref="Regex" /> object</returns>
 /// <remarks>
 /// <para>
 /// A templated URL uses token names surrounded by [SquareBrackets] to provide for dynamic
 /// matching and parsing.
 /// For example, the URL template:
 /// <i>Reports/[ID]/[Action].aspx</i>
 /// translates to the following regular expression:
 /// <i>Reports/(?&lt;ID&gt;[a-zA-Z0-9_+%]*)/(?&lt;Action&gt;[a-zA-Z0-9_+%]*).aspx"</i>
 /// </para>
 /// <para>
 /// The regular expression is then used by the UrlMappingModule to match incoming URLs.
 /// If a match is found, token names and values are automatically appended to the 
 /// redirection URL as querystring arguments.  So, given the above templated URL string
 /// of <i>Reports/[ID]/[Action].aspx</i> with a Redirection defined as 
 /// <i>ReportAction.aspx</i>, an incoming URL of <i>Reports/47/Edit.aspx</i>
 /// is redirected by the UrlMappingModule to the following:
 /// <i>ReportAction.aspx?ID=47&amp;Action=Edit</i>.
 /// </para>
 /// </remarks>
 public static Regex CreateTemplatedMappingRegex(string templatedUrl, IncomingQueryStringBehavior qsBehavior)
 {
     // return a case-insensitive regex that must match the url completely
     return CreateTemplatedMappingRegex(templatedUrl, false, true, qsBehavior);
 }
Example #5
0
 /// <summary>
 /// Creates a <see cref="UrlMappingItem" /> given a name, templated URL string, and redirection string.
 /// </summary>
 /// <param name="name">A name for this mapping item</param>
 /// <param name="templatedUrl">A template for URLs to be matched</param>
 /// <param name="redirection">The redirection that the UrlMappingModule should apply when incoming URLs match the template.</param>
 /// <param name="qsBehavior">defines how the UrlMappingModule should treat querystring values on an incoming URL for pattern matching; this is typically provided through declarative configuration</param>
 /// <returns>The created <see cref="UrlMappingItem" /></returns>
 /// <remarks>
 /// <para>
 /// The template URL string is relative to the web application and may or may not include
 /// the "~/" characters at the beginning.  The template may indicate an exact URL to match,
 /// for example <i>Reports/Summary.aspx</i> or may include token names surrounded
 /// by [SquareBrackets] for dynamic matching, such as <i>Reports/[ID]/[Action].aspx</i>.
 /// When dynamic templates are matched in runtime by the UrlMappingModule, dynamic tokens
 /// are appended to the redirection string as querystring items, 
 /// such as <i>?ID=<i>xxx</i>&amp;Action=<i>xxx</i></i>.
 /// </para>
 /// <para>
 /// The redirection string may be an absolute URL, such as <i>http://www.microsoft.com</i>,
 /// a server-relative URL beginning with a "/", such as <i>/AnotherAppOnThisServer/page.aspx</i>,
 /// or an application-relative URL to a concrete resource, optionally beginning with a "~/", such as
 /// <i>~/ReportSummary.aspx</i> or <i>ReportSummary.aspx</i>.
 /// </para>
 /// </remarks>
 public static UrlMappingItem CreateTemplatedMappingItem(string name, string templatedUrl, string redirection, IncomingQueryStringBehavior qsBehavior)
 {
     UrlMappingItem item = new UrlMappingItem(name, CreateTemplatedMappingRegex(templatedUrl, qsBehavior), redirection);
     item.UrlTemplate = templatedUrl;
     return item;
 }
Example #6
0
        /// <summary>
        /// Return a regular expression translated from the given templated URL.
        /// </summary>
        /// <param name="templatedUrl">A URL pattern relative to the application, with [TokenNames] included for dynamic matching</param>
        /// <param name="caseSensitive"><i>true</i> if the returned expression should be case sensitive, <i>false</i> if not</param>
        /// <param name="matchCompletely"><i>true</i> if the returned expression should include beginning and ending anchors, ensuring that a match will require the complete URL and not a portion of it</param>
        /// <param name="qsBehavior">defines how the UrlMappingModule should treat querystring values on an incoming URL for pattern matching; this is typically provided through declarative configuration</param>
        /// <returns>A regular expression as a <see cref="Regex" /> object</returns>
        /// <remarks>
        /// <para>
        /// A templated URL uses token names surrounded by [SquareBrackets] to provide for dynamic
        /// matching and parsing.
        /// For example, the URL template:
        /// <i>Reports/[ID]/[Action].aspx</i>
        /// translates to the following regular expression:
        /// <i>Reports/(?&lt;ID&gt;[a-zA-Z0-9_+%]*)/(?&lt;Action&gt;[a-zA-Z0-9_+%]*).aspx"</i>
        /// </para>
        /// <para>
        /// The regular expression is then used by the UrlMappingModule to match incoming URLs.
        /// If a match is found, token names and values are automatically appended to the 
        /// redirection URL as querystring arguments.  So, given the above templated URL string
        /// of <i>Reports/[ID]/[Action].aspx</i> with a Redirection defined as 
        /// <i>ReportAction.aspx</i>, an incoming URL of <i>Reports/47/Edit.aspx</i>
        /// is redirected by the UrlMappingModule to the following:
        /// <i>ReportAction.aspx?ID=47&amp;Action=Edit</i>.
        /// </para>
        /// </remarks>
        public static Regex CreateTemplatedMappingRegex(string templatedUrl, bool caseSensitive, bool matchCompletely, IncomingQueryStringBehavior qsBehavior)
        {
            // return a regex that parses an app-relative url string and constructs an appropriate
            // Regular Expression for matching it; the template may include tokens in the form
            // of [TokenItem] which are matched as groups;
            // e.g. the url template "Reports/Display/[ID].aspx" becomes the regular expression:
            //   Reports/Display/(?<ID>[a-zA-Z0-9_+%]*).aspx"

            // if matchCompletely is true, the regex is anchored; if false, the match can occur
            // anywhere within the url

            // options for the returned regular expression
            RegexOptions options = (caseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase);

            // if the templatedUrl contains a querystring ? and we're incorporating querystring values in the regex
            //then escape it
            if (qsBehavior == IncomingQueryStringBehavior.Include)
                templatedUrl = templatedUrl.Replace("?", "\\?");

            // use a regex now to parse for [Tokens]
            Regex r = new Regex(@"(\[[a-zA-Z0-9_]*\])");
            MatchCollection matches = r.Matches(templatedUrl);
            string s = templatedUrl;
            foreach (Match m in matches)
            {
                if (m.Value.Length == 2)
                {
                    s = s.Replace(m.Value, @"(?<_pre_>[/\-~?.a-zA-Z0-9_\u00a4-\uffe5+]*)");
                }
                else
                {
                    string tokenName = m.Value.Substring(1, m.Value.Length - 2);
                    s = s.Replace(m.Value, string.Format(@"(?<{0}>[\-~?a-zA-Z0-9_\u00a4-\uffe5+]*)", tokenName));
                }
            }

            // if the matchCompletely option is desired, add anchors to the regex string
            if (matchCompletely)
                s = "^" + s + "$";

            // now construct and return the regular expression to test for these kinds of URLs
            return new Regex(s, options);
        }
        private void Initalize()
        {
            UrlMappingConfig config = UrlMappingConfig.Instance;

            _provider = ServiceLocator.Instance.Resolve<IUrlMappingProvider>();

            _noMatchAction = config.NoMatchAction;
            _noMatchRedirectPage = config.NoMatchRedirectUrl;
            _automaticallyUpdateFormAction = config.AutoUpdateFormAction;
            _qsBehavior = config.IncomingQueryStringBehavior;
            _processingEvent = config.UrlProcessingEvent;

            if (_provider != null)
            {
                _provider.Initialize(config);
            }

            // save to config
            config.Provider = _provider;
        }
        private static UrlMappingItem getUrlInfo(XmlNode node, NavigationItem menuItem, int index, int subIndex, int subsubIndex, IncomingQueryStringBehavior incomingQueryStringBehavior)
        {
            string name = XmlUtil.GetStringAttribute(node, "name", string.Empty);
            string urlTemplate = XmlUtil.GetStringAttribute(node, "template", string.Empty);

            if (string.IsNullOrEmpty(urlTemplate))
                throw new UrlMappingException("There is an XmlUrlMappingModule error.  All <url> tags in the mapping file require a 'template' attribute.");

            string redirection = Utility.GetHref(XmlUtil.GetStringAttribute(node, "href", string.Empty));

            // still here, we can create the item and add to the collection
            UrlMappingItem item
                  = Utility.CreateTemplatedMappingItem(
                    name, urlTemplate, redirection, incomingQueryStringBehavior
                   );
            item.UrlTemplate = urlTemplate;

            // set custom attributes
            foreach (XmlAttribute attr in node.Attributes)
            {
                item[attr.Name] = attr.Value;
            }

            if (XmlUtil.GetStringAttribute(node, "index", string.Empty) == "?")
                item.Index = null;
            else
                item.Index = index;

            if (XmlUtil.GetStringAttribute(node, "subindex", string.Empty) == "?")
                item.SubIndex = null;
            else
                item.SubIndex = subIndex;

            if (XmlUtil.GetStringAttribute(node, "subsubindex", string.Empty) == "?")
                item.SubsubIndex = null;
            else
                item.SubsubIndex = subsubIndex;

            item.Title = XmlUtil.GetStringAttribute(node, "title", menuItem.Title);

            item.Id = XmlUtil.GetStringAttribute(node, "id", null);
            item.Action = XmlUtil.GetStringAttribute(node, "action", null);

            return item;
        }
        public static void ParseXml(string file, UrlMappingItemCollection routes, Dictionary<int, NavigationItem> menuItems, IncomingQueryStringBehavior incomingQueryStringBehavior)
        {
            if (!File.Exists(file))
                return;

            XmlDocument xml = new XmlDocument();
            try
            {
                xml.Load(file);
            }
            catch (Exception ex)
            {
                throw new UrlMappingException("The error occurred while loading the route files.  A virtual path is required and the file must be well-formed.", ex);
            }

            menuItems.Clear();

            int i = -1, j = -1, k = -1;
            foreach (XmlNode node in xml.DocumentElement.ChildNodes)
            {
                if (node.Name == "menu")
                {
                    i++;
                    NavigationItem menuItem = getMenuItem(node);
                    menuItem.Children = new Dictionary<int, NavigationItem>();

                    menuItems[i] = menuItem;

                    foreach (XmlNode subNode in node.ChildNodes)
                    {
                        if (subNode.Name == "menu")
                        {
                            j++;
                            NavigationItem sub_menuItem = getMenuItem(subNode);
                            sub_menuItem.Children = new Dictionary<int, NavigationItem>();

                            menuItems[i].Children[j] = sub_menuItem;

                            foreach (XmlNode subsubNode in subNode.ChildNodes)
                            {
                                if (subsubNode.Name == "menu")
                                {
                                    k++;
                                    NavigationItem subsub_menuItem = getMenuItem(subsubNode);
                                    sub_menuItem.Children[k] = subsub_menuItem;

                                    foreach (XmlNode last_node in subsubNode.ChildNodes)
                                    {
                                        if (last_node.Name == "url")
                                        {
                                            UrlMappingItem url = getUrlInfo(last_node, subsub_menuItem, i, j, k, incomingQueryStringBehavior);

                                            routes.Add(url);
                                        }
                                    }
                                }
                                else if (subsubNode.Name == "url")
                                {
                                    UrlMappingItem url = getUrlInfo(subsubNode, sub_menuItem, i, j, -1, incomingQueryStringBehavior);

                                    routes.Add(url);
                                }
                            }
                        }
                        else if (subNode.Name == "url")
                        {
                            UrlMappingItem url = getUrlInfo(subNode, menuItem, i, -1, -1, incomingQueryStringBehavior);

                            routes.Add(url);
                        }
                    }
                }
                else if (node.Name == "url")
                {
                    UrlMappingItem url = getUrlInfo(node, new NavigationItem(), -1, -1, -1, incomingQueryStringBehavior);

                    routes.Add(url);
                }
            }
        }
Example #10
0
 /// <summary>
 /// Return a regular expression translated from the given templated URL.
 /// </summary>
 /// <param name="templatedUrl">A URL pattern relative to the application, with [TokenNames] included for dynamic matching</param>
 /// <param name="qsBehavior">defines how the UrlMappingModule should treat querystring values on an incoming URL for pattern matching; this is typically provided through declarative configuration</param>
 /// <returns>A regular expression as a <see cref="Regex" /> object</returns>
 /// <remarks>
 /// <para>
 /// A templated URL uses token names surrounded by [SquareBrackets] to provide for dynamic
 /// matching and parsing.
 /// For example, the URL template:
 /// <i>Reports/[ID]/[Action].aspx</i>
 /// translates to the following regular expression:
 /// <i>Reports/(?&lt;ID&gt;[a-zA-Z0-9_+%]*)/(?&lt;Action&gt;[a-zA-Z0-9_+%]*).aspx"</i>
 /// </para>
 /// <para>
 /// The regular expression is then used by the UrlMappingModule to match incoming URLs.
 /// If a match is found, token names and values are automatically appended to the
 /// redirection URL as querystring arguments.  So, given the above templated URL string
 /// of <i>Reports/[ID]/[Action].aspx</i> with a Redirection defined as
 /// <i>ReportAction.aspx</i>, an incoming URL of <i>Reports/47/Edit.aspx</i>
 /// is redirected by the UrlMappingModule to the following:
 /// <i>ReportAction.aspx?ID=47&amp;Action=Edit</i>.
 /// </para>
 /// </remarks>
 public static Regex CreateTemplatedMappingRegex(string templatedUrl, IncomingQueryStringBehavior qsBehavior)
 {
     // return a case-insensitive regex that must match the url completely
     return(CreateTemplatedMappingRegex(templatedUrl, false, true, qsBehavior));
 }
Example #11
0
        /// <summary>
        /// Creates a <see cref="UrlMappingItem" /> given a name, templated URL string, and redirection string.
        /// </summary>
        /// <param name="name">A name for this mapping item</param>
        /// <param name="templatedUrl">A template for URLs to be matched</param>
        /// <param name="redirection">The redirection that the UrlMappingModule should apply when incoming URLs match the template.</param>
        /// <param name="qsBehavior">defines how the UrlMappingModule should treat querystring values on an incoming URL for pattern matching; this is typically provided through declarative configuration</param>
        /// <returns>The created <see cref="UrlMappingItem" /></returns>
        /// <remarks>
        /// <para>
        /// The template URL string is relative to the web application and may or may not include
        /// the "~/" characters at the beginning.  The template may indicate an exact URL to match,
        /// for example <i>Reports/Summary.aspx</i> or may include token names surrounded
        /// by [SquareBrackets] for dynamic matching, such as <i>Reports/[ID]/[Action].aspx</i>.
        /// When dynamic templates are matched in runtime by the UrlMappingModule, dynamic tokens
        /// are appended to the redirection string as querystring items,
        /// such as <i>?ID=<i>xxx</i>&amp;Action=<i>xxx</i></i>.
        /// </para>
        /// <para>
        /// The redirection string may be an absolute URL, such as <i>http://www.microsoft.com</i>,
        /// a server-relative URL beginning with a "/", such as <i>/AnotherAppOnThisServer/page.aspx</i>,
        /// or an application-relative URL to a concrete resource, optionally beginning with a "~/", such as
        /// <i>~/ReportSummary.aspx</i> or <i>ReportSummary.aspx</i>.
        /// </para>
        /// </remarks>
        public static UrlMappingItem CreateTemplatedMappingItem(string name, string templatedUrl, string redirection, IncomingQueryStringBehavior qsBehavior)
        {
            UrlMappingItem item = new UrlMappingItem(name, CreateTemplatedMappingRegex(templatedUrl, qsBehavior), redirection);

            item.UrlTemplate = templatedUrl;
            return(item);
        }
Example #12
0
        /// <summary>
        /// Return a regular expression translated from the given templated URL.
        /// </summary>
        /// <param name="templatedUrl">A URL pattern relative to the application, with [TokenNames] included for dynamic matching</param>
        /// <param name="caseSensitive"><i>true</i> if the returned expression should be case sensitive, <i>false</i> if not</param>
        /// <param name="matchCompletely"><i>true</i> if the returned expression should include beginning and ending anchors, ensuring that a match will require the complete URL and not a portion of it</param>
        /// <param name="qsBehavior">defines how the UrlMappingModule should treat querystring values on an incoming URL for pattern matching; this is typically provided through declarative configuration</param>
        /// <returns>A regular expression as a <see cref="Regex" /> object</returns>
        /// <remarks>
        /// <para>
        /// A templated URL uses token names surrounded by [SquareBrackets] to provide for dynamic
        /// matching and parsing.
        /// For example, the URL template:
        /// <i>Reports/[ID]/[Action].aspx</i>
        /// translates to the following regular expression:
        /// <i>Reports/(?&lt;ID&gt;[a-zA-Z0-9_+%]*)/(?&lt;Action&gt;[a-zA-Z0-9_+%]*).aspx"</i>
        /// </para>
        /// <para>
        /// The regular expression is then used by the UrlMappingModule to match incoming URLs.
        /// If a match is found, token names and values are automatically appended to the
        /// redirection URL as querystring arguments.  So, given the above templated URL string
        /// of <i>Reports/[ID]/[Action].aspx</i> with a Redirection defined as
        /// <i>ReportAction.aspx</i>, an incoming URL of <i>Reports/47/Edit.aspx</i>
        /// is redirected by the UrlMappingModule to the following:
        /// <i>ReportAction.aspx?ID=47&amp;Action=Edit</i>.
        /// </para>
        /// </remarks>
        public static Regex CreateTemplatedMappingRegex(string templatedUrl, bool caseSensitive, bool matchCompletely, IncomingQueryStringBehavior qsBehavior)
        {
            // return a regex that parses an app-relative url string and constructs an appropriate
            // Regular Expression for matching it; the template may include tokens in the form
            // of [TokenItem] which are matched as groups;
            // e.g. the url template "Reports/Display/[ID].aspx" becomes the regular expression:
            //   Reports/Display/(?<ID>[a-zA-Z0-9_+%]*).aspx"

            // if matchCompletely is true, the regex is anchored; if false, the match can occur
            // anywhere within the url

            // options for the returned regular expression
            RegexOptions options = (caseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase);

            // if the templatedUrl contains a querystring ? and we're incorporating querystring values in the regex
            //then escape it
            if (qsBehavior == IncomingQueryStringBehavior.Include)
            {
                templatedUrl = templatedUrl.Replace("?", "\\?");
            }

            // use a regex now to parse for [Tokens]
            Regex           r       = new Regex(@"(\[[a-zA-Z0-9_]*\])");
            MatchCollection matches = r.Matches(templatedUrl);
            string          s       = templatedUrl;

            foreach (Match m in matches)
            {
                if (m.Value.Length == 2)
                {
                    s = s.Replace(m.Value, @"(?<_pre_>[/\-~?.a-zA-Z0-9_\u00a4-\uffe5+]*)");
                }
                else
                {
                    string tokenName = m.Value.Substring(1, m.Value.Length - 2);
                    s = s.Replace(m.Value, string.Format(@"(?<{0}>[\-~?a-zA-Z0-9_\u00a4-\uffe5+]*)", tokenName));
                }
            }

            // if the matchCompletely option is desired, add anchors to the regex string
            if (matchCompletely)
            {
                s = "^" + s + "$";
            }

            // now construct and return the regular expression to test for these kinds of URLs
            return(new Regex(s, options));
        }