Convert Route Templates into Regex - c#

I have an application with ~300 of services. I would like to add authorization for a specific subroute.
I've created a custom authorization attribute to to verify routes. I would like to convert the route templates to regex, so I can assure that any changes in the future will be automatically be applied back to the authorization attribute.
e.g I have a route.
var benefitRoute = "/employees/{employeeId:Guid}/benefit/{benefitId:guid}/enrollments";
I would like to replace all of the {} and their contents with .*
"/employees/.*/benefit/.*/enrollments";
However I tried to match on \{.+\} However it grabs the larger one before the two smaller ones, when I run my regex.
Regex.Replace(route, "\{.+\}", ".*");
How can I convert the route templates into Regex.

You should add '?' which makes quantifiers "lazy", try
var benefitRoute = "/employees/{employeeId:Guid}/benefit/{benefitId:guid}/enrollments";
string pattern = #"{(.*?)}";
String result=Regex.Replace(benefitRoute, pattern, ".*");
You can find more info on it here http://www.regular-expressions.info/repeat.html

Related

Regular expressions redirection

I want to set redirection from
www.somesite.com/products/dynamicstring/randomtext1/randomtext2
to www.somesite.com/products/dynamicstring
Is it possible to do that through Regex ?
It means if my incming url is
www.somesite.com/products/myproducts/test1/test2 it should redirect to www.somesite.com/products/myproducts/
just briefing more about this :
#TomLord i am using HttpContext.Current.Response.RedirectPermanent(matchingDefinition.To) i have all the redirects "From" and "To" in a class object, in the form of REGEX expressions.Example in From "/product/*" and To "/products" , i am reading these object and trying to redirect them, but i am not able to redirect something like /products/dynamicstring/randomtext1/ to /products/dynamicstring where dynamic string is random string , i dont find any regular expression which can be use to do this. For example /products/samples/randomtext1 should redirect to /products/samples/
Redirection cannot be done with regex alone. Google a bit what is a regular expression in reality. The short answer is: it's string-like expression that describes search pattern. So it can't redirect, not even replace a substring with substring or do anything else then match and capture parts of the matched string.
That being said, regex can help us do what you wanna. I am gonna assume you can use Javascript, cause I can't put a solution in every language. I am also gonna assume you will try to go over the code not copy paste and press enter. If you only need that hire a programmer. If you use another language, principle should be the same:
obtain URL
define regex
use capture group to extract the part of your URL that you need
construct a new URL
redirect to it
While matching the URLs in general is a fair bit more complex, like:
^(?:https?://)?(?:[\w]+\.)(?:\.?[\w]{2,})+$
As long as you are sure you will only be getting URLs and in the format you wanna, we will do it far simpler.
Basically, let's say you have:
some text with 2 dots that ends in com
then a /products/dynamicstring/
then text
then /
then text
As a regex that is:
/\w*.\w*.com\/products\/dynamicstring\/\w*\/\w*/g
Curde matching is done, but we still need to add a capture group we will use to extract part of the string we need:
/(\w*.\w*.com\/products\/)dynamicstring\/\w*\/\w*/g
Oke, now let's leverage this regex to do rest of the work:
Define regex:
var regex = /\w*.\w*.com\/products\/dynamicstring\/\w*\/\w*/g;
Get current URL. If you already have URL use it.
var currUrl = window.location.href;
Extract capture group from string:
var match = regex.exec(currUrl);
Use that to get a new URL from old one:
var redirectUrl = match[1] + myproducts/
Finally, we redirect with:
window.location.replace(redirectUrl);
I wrote all this straight from my head so I recommend you go over each step, look how it works, read some documentation about functions used. You might find an error as well as learn a lot.

Regex for HTTP URL with Basic authentication

In my application, I must read a URL and do something if the URL contains Basic authentication credentials. An example of such a URL is
http://username:password#example.com
Is the regular expression below a good fit for my task? I am to capture four groups into local variables. The URL is passed to another internal library that will do further work to ensure the URL is valid before opening a connection.
^(.+?//)(.+?):(.+?)#(.+)$
It looks ok, and I think that a regular expression is good to use in this case. A couple of suggestions:
1) I think that named groups would make your code more readable, i.e:
^(?<protocol>.+?//)(?<username>.+?):(?<password>.+?)#(?<address>.+)$
Then you can simply write
Match match = Regex.Match(string, pattern);
if (match.Success) {
string user = match.Groups["username"];
2) then you could make the expression a little more strict, e.g. using \w when possible instead of .:
^(?<protocol>\w+://)...
Your regex seems OK, but why not use the thoroughly-tested and nearly-compliant Uri class? It's then trivial to access the pieces you want without worrying about spec-compatibility:
var url = new Uri("http://username:password#example.com");
var userInfo = url.UserInfo.Split(':');
var username = userInfo[0];
var password = userInfo[1];

Conditional Regex Replace in C# without MatchEvaluator

So, Im trying to make a program to rename some files. For the most part, I want them to look like this,
[Testing]StupidName - 2[720p].mkv
But, I would like to be able to change the format, if so desired. If I use MatchEvaluators, you would have to recompile every time. Thats why I don't want to use the MatchEvaluator.
The problem I have is that I don't know how, or if its possible, to tell Replace that if a group was found, include this string. The only syntax for this I have ever seen was something like (?<group>:data), but I can't get this to work. Well if anyone has an idea, im all for it.
EDIT:
Current Capture Regexes =
^(\[(?<FanSub>[^\]\)\}]+)\])?[. _]*(?<SeriesTitle>[\w. ]*?)[. _]*\-[. _]*(?<EpisodeNumber>\d+)[. _]*(\-[. _]*(?<EpisodeName>[\w. ]*?)[. _]*)?([\[\(\{](?<MiscInfo>[^\]\)\}]*)[\]\)\}][. _]*)*[\w. ]*(?<Extension>\.[a-zA-Z]+)$
^(?<SeriesTitle>[\w. ]*?)[. _]*[Ss](?<SeasonNumber>\d+)[Ee](?<EpisodeNumber>\d+).*?(?<Extension>\.[a-zA-Z]+)$
^(?<SeriesTitle>[\w. ]*?)[. _]*(?<SeasonNumber>\d)(?<EpisodeNumber>\d{2}).*?(?<Extension>\.[a-zA-Z]+)$
Current Replace Regex = [${FanSub}]${SeriesTitle} - ${EpisodeNumber} [${MiscInfo}]${Extension}
Using Regex.Replace, the file TestFile 101.mkv, I get []TestFile - 1[].mkv. What I want to do is make it so that [] is only included if the group FanSub or MiscInfo was found.
I can solve this with a MatchEvaluator because I actually get to compile a function. But this would not be a easy solution for users of the program. The only other idea I have to solve this is to actually make my own Regex.Replace function that accepts special syntax.
It sounds like you want to be able to specify an arbitrary format dynamically rather than hard-code it into your code.
Perhaps one solution is to break your filename parts into specific groups then pass in a replacement pattern that takes advantage of those group names. This would give you the ability to pass in different replacement patterns which return the desired filename structure using the Regex.Replace method.
Since you didn't explain the categories of your filename I came up with some random groups to demonstrate. Here's a quick example:
string input = "Testing StupidName Number2 720p.mkv";
string pattern = #"^(?<Category>\w+)\s+(?<Name>.+?)\s+Number(?<Number>\d+)\s+(?<Resolution>\d+p)(?<Extension>\.mkv)$";
string[] replacePatterns =
{
"[${Category}]${Name} - ${Number}[${Resolution}]${Extension}",
"${Category} - ${Name} - ${Number} - ${Resolution}${Extension}",
"(${Number}) - [${Resolution}] ${Name} [${Category}]${Extension}"
};
foreach (string replacePattern in replacePatterns)
{
Console.WriteLine(Regex.Replace(input, pattern, replacePattern));
}
As shown in the sample, named groups in the pattern, specified as (?<Name>pattern), are referred to in the replacement pattern by ${Name}.
With this approach you would need to know the group names beforehand and pass these in to rearrange the pattern as needed.

Getting ASP.NET MVC to correctly escape the # (hash/pound) character in routes

I've got a route that looks like this:
routes.MapRoute(
"BlogTags",
"Blog/Tags/{tag}",
new { controller = "Blog", action = "BrowseTag", viewRss = false }
);
And I create a URL using that route like this:
<%= Html.RouteLink(Html.Encode(sortedTags[i].Tag),
new { action = "BrowseTag", tag = sortedTags[i].Tag })%>
However, when a tag with a # character (like "C#") is used, the routing engine doesn't escape it, so I get a URL that looks like this:
C#
What I need is the # escaped so that it looks like this:
C#
I tried doing a Url.Encode on the tag before it went into the route, like this:
<%= Html.RouteLink(Html.Encode(sortedTags[i].Tag),
new { action = "BrowseTag", tag = Url.Encode(sortedTags[i].Tag) })%>
But that makes the routing engine double escape the # (which causes an ASP.NET crash with a bad request error)):
C#
How can I get the routing engine to escape that # character for me correctly?
Thank you for your help in advance.
As a very bald solution, I would manually replace "#" with "%23" in the output of RouteLink. Provided you don't use fragments in your urls, it should work.
You could use regular expression to only apply replace to the last part of your url.
I have a similar SO question relating to "/". While researching that issue I learned that ASP.NET decodes the URL values before they get passed to the MVC framework, and since "#" has special meaning to URLs (just like the "/" I was dealing with) there's a good chance that something in the base routing engine is causing this behavior.
Like Levi mentioned in his comment, one solution is to use ASP.NET 4.0. Another solution would be to write a RouteLink helper that automatically replaces "#" with some marker (like "!MY_HASH_TOKEN!") and then reverse that replacement in your controller (or perhaps via a HttpModule of some sort).
Or, just throw in the towel and pass the tag value as a querystring argument. Not as sexy, but its simple and it works.

Need C# regexp for URL validation

How to validate by a single regular expression the urls:
http://83.222.4.42:8880/listen.pls
http://www.my_site.com/listen.pls
http://www.my.site.com/listen.pls
to be true?
I see that I formulated the question not exactly :(, sorry my mistake. The idea is that I want to validate with the help of regexp valid urls, let it be an external ip address or the domain name. This is the idea, other valid urls can be considered:
http://93.122.34.342/
http://193.122.34.342/abc/1.html
http://www.my_site.com/listen2.pls
http://www.my.site.com/listen.php
and so on.
The road to hell is paved with string parsing.
URL parsing in particular is the source of many, many exploited security issues. Don't do it.
For example, do you want this to match?
Note the uppercase scheme section. Remember that some parts of a URL are case sensitive, and some are not. Then there's encoding rules. Etc.
Start by using System.Uri to parse the URLs you provide:
var uri = new Uri("http://83.222.4.42:8880/listen.pls");
Then you can write things like:
if (uri.Scheme == "http" &&
uri.Host == "83.222.4.42" &&
uri.AbsolutePath == "/listen.pls"
)
{
// ...
}
^http://.+/listen\.pls$
If there are strictly only 3 of them don't bother with a regular expression because there is not necessarily a good pattern match when everything is already strictly known - in fact you might accidentally match more than these three urls - which becomes a problem if the urls are intended for security purposes or something equally important. Instead, test the three cases directly - maybe put them in a configuration file.
In the future if you want to add more URLs to the list you'll likely end up with an overly complicated regular expression that's increasingly hard to maintain and takes the place of a simpler check against a small list.
You won't necessarily get speed gains by running Regex to find these three strings - in fact it might be quite expensive.
Note: If you wantUri regular expressions also try websites hosting libraries like Regex Library - there are many to pick and choose from if your needs change.
/^http:\/\/[-_a-zA-Z0-9.]+(:\d+)?\/listen\.pls$/
Do you mean any URL ending with /listen.pls? In that case try this:
^http://[^/]+/listen\.pls$
or if the protocol identifier must be optional:
^[http://]?[^/]+/listen\.pls$
Anyway take a look here, maybe it is useful for you: Url and Email validation using Regex
A modified version base upon Jay Bazuzi's solution above since I can't post code in comment, it checks a blacklisted extensions (I do this only for demonstration purpose, you should strongly consider to build a whitelist rather than a blacklist) :
string myurl = "http://www.my_site.com/listen.pls";
Uri myUri = new Uri(myurl);
string[] invalidExtensions = {
".pls",
".abc"
};
foreach(string invalidExtension in invalidExtensions) {
if (invalidExtension.ToLower().Equals(System.IO.Path.GetExtension(myUri.AbsolutePath))) {
//Logic here
}
}

Categories