How to safely format URL - c#

I have a SharePoint application that uses a URL to access a resource.
code:
return web.GetList(web.ServerRelativeUrl + "/lists/UserSettings");
This works fine when I'm on a subsite, because ServerRelativeUrl will return "/sitename"
However, when this is a root site, ServerRelativeUrl will return "/" instead, leading to a poorly formed URL such as "//lists/UserSettings"
I know this seems like a simple problem (and it is) but is there a best practice for approaching this situation that is consistently safe?

Have you seen the System.Uri and System.UriBuilder classes?

new Uri(web.ServerRelativeUrl, "/lists/UserSettings");
Okay, hrm...try:
Path.Combine(web.ServerRelativeUrl, "/lists/UserSettings");

Use absolute url, this works for me:
web.GetList(web.Url + "/lists/UserSettings")

return web.GetList( (web.ServerRelativeUrl == "/" ? string.Empty : web.ServerRelativeUrl) + "/lists/UserSettings");

Related

How to encode a URL using Asp.net?

I have the following line of aspx link that I would like to encode:
Response.Redirect("countriesAttractions.aspx?=");
I have tried the following method:
Response.Redirect(Encoder.UrlPathEncode("countriesAttractions.aspx?="));
This is another method that I tried:
var encoded = Uri.EscapeUriString("countriesAttractions.aspx?=");
Response.Redirect(encoded);
Both redirects to the page without the URL being encoded:
http://localhost:52595/countriesAttractions?=
I tried this third method:
Response.Redirect(Server.UrlEncode("countriesAttractions.aspx?="));
This time the url itself gets encoded:
http://localhost:52595/countriesAttractions.aspx%3F%3D
However I get an error from the UI saying:
HTTP Error 404.0 Not Found
The resource you are looking for has been removed, had its name changed, or
is temporarily unavailable.
Most likely causes:
-The directory or file specified does not exist on the Web server.
-The URL contains a typographical error.
-A custom filter or module, such as URLScan, restricts access to the file.
Also, I would like to encode another kind of URL that involves parsing of session strings:
Response.Redirect("specificServices.aspx?service=" +
Session["service"].ToString().Trim() + "&price=" +
Session["price"].ToString().Trim()));
The method I tried to include the encoding method into the code above:
Response.Redirect(Server.UrlEncode("specificServices.aspx?service=" +
Session["service"].ToString().Trim() + "&price=" +
Session["price"].ToString().Trim()));
The above encoding method I used displayed the same kind of results I received with my previous Server URL encode methods. I am not sure on how I can encode url the correct way without getting errors.
As well as encoding URL with CommandArgument:
Response.Redirect("specificAttractions.aspx?attraction=" +
e.CommandArgument);
I have tried the following encoding:
Response.Redirect("specificAttractions.aspx?attraction=" +
HttpUtility.HtmlEncode(Convert.ToString(e.CommandArgument)));
But it did not work.
Is there any way that I can encode the url without receiving this kind of error?
I would like the output to be something like my second result but I want to see the page itself and not the error page.
I have tried other methods I found on stackoverflow such as self-coded methods but those did not work either.
I am using AntiXSS class library in this case for the methods I tried, so it would be great if I can get solutions using AntiXSS library.
I need to encode URL as part of my school project so it would be great if I can get solutions. Thank you.
You can use the UrlEncode or UrlPathEncode methods from the HttpUtility class to achieve what you need. See documentation at https://msdn.microsoft.com/en-us/library/system.web.httputility.urlencode(v=vs.110).aspx
It's important to understand however, that you should not need to encode the whole URL string. It's only the parameter values - which may contain arbitrary data and characters which aren't valid in a URL - that you need to encode.
To explain this concept, run the following in a simple .NET console application:
string url = "https://www.google.co.uk/search?q=";
//string url = "http://localhost:52595/specificAttractions.aspx?country=";
string parm = "Bora Bora, French Polynesia";
Console.WriteLine(url + parm);
Console.WriteLine(url + HttpUtility.UrlEncode(parm), System.Text.Encoding.UTF8);
Console.WriteLine(url + HttpUtility.UrlPathEncode(parm), System.Text.Encoding.UTF8);
Console.WriteLine(HttpUtility.UrlEncode(url + parm), System.Text.Encoding.UTF8);
You'll get the following output:
https://www.google.co.uk/search?q=Bora Bora, French Polynesia
https://www.google.co.uk/search?q=Bora+Bora%2c+French+Polynesia
https://www.google.co.uk/search?q=Bora%20Bora,%20French%20Polynesia
https%3a%2f%2fwww.google.co.uk%2fsearch%3fq%3dBora+Bora%2c+French+Polynesia
By pasting these into a browser and trying to use them, you'll soon see what is a valid URL and what is not.
(N.B. when pasting into modern browsers, many of them will URL-encode automatically for you, if your parameter is not valid - so you'll find the first output works too, but if you tried to call it via some C# code for instance, it would fail.)
Working demo: https://dotnetfiddle.net/gqFsdK
You can of course alter the values you input to anything you like. They can be hard-coded strings, or the result of some other code which returns a string (e.g. fetching from the session, or a database, or a UI element, or anywhere else).
N.B. It's also useful to clarify that a valid URL is simply a string in the correct format of a URL. It is not the same as a URL which actually exists. A URL may be valid but not exist if you try to use it, or may be valid and really exist.

Server.Transfer not tranfer some urls

i use server.transfer at the begining it works perfectly. but then i add another language to my site and i try to do it but it fails with the new language
my code is below
if (Request.RawUrl.Contains("/tr/"))
{
Server.Transfer("tr/" + dt.Rows[0]["SourceURL"].ToString());
}
else if (Request.RawUrl.Contains("/en/"))
{
Server.Transfer("en/" + dt.Rows[0]["SourceURL"].ToString());
}
the "tr" transfers work superb but en fails it stays on my pagenotfound and not transfer to the destination url. i also check to write the whole url like http://mysite.com/en/test.aspx?k=13 and it also works but when server.transfer it fails
can anybody say why?
thanks
I think Response.Redirect will work for in your situation for the website " www.mysite.com/en/home"
It won't be as efficient as Server.Transfer, but should work just as well. I'm not sure why it works with "tr/", but not "en/", this might be due to some issue with relative paths. You could try to include a tilda "~" in front of your URL.
Server.Transfer("~/en/" + dt.Rows[0]["SourceURL"].ToString());

Is it necessary to url encode the file name?

In my asp.net mvc application I have the code:
response.ContentType = "application/octet-stream";
response.AddHeader("Content-Disposition", "attachment;filename=" +
HttpUtility.UrlEncode(attachment.FileName));
So that all the Chinese characters are url-encoded to something like %5C%2D. In IE/Chrome when users download the file, they get the Chinese file name(that is, IE/Chrome will automatically url-decode the file name). But in Firefox, they will get something like %5C%2D%0A.docx. Now I'm going to remove HttpUtility.UrlEncode in the code. But before doing this, I want to confirm that there is no security issues in this case. Would you please give me some ideas?
EDIT Corbin's answer is correct. But after removing the url-encoding of the filename, some users using old version IE will get strange messy file names. At last I do url-encode for those users only.
The name is allowed to be in quotes if it's ASCII.
If it's non-ASCII, then you have to use the encoding defined in RFC 2231 or the one in RFC 5987 or the one in RFC 2047... which browsers support which of these is a fun game, of course. :(
If you just stick the raw non-ASCII bytes into the header, it will almost certainly look like garbage for a large fraction of users.
please change your code as follow:
if (Request.Browser.Browser == "IE" || Request.Browser.Browser == "Chrome")
{
filename = HttpUtility.UrlPathEncode(filename);
}
Response.AddHeader("Content-Disposition", "attachment;filename=\"" + filename + "\"");
notes: your code miss "\"" for wrap file name in quotes
http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html
Unless I'm misunderstanding it, it looks like the name should just be in quotes, not url encoded.

Problem redirecting to another page

I am getting "Internet Explorer cannot display the webpage" error while trying to redirect ot another page.
string targetURL = "~/AnotherForm.aspx?Xresult=" + HttpUtility.UrlEncode(res);
Response.Redirect(targetURL);
Thanks
BB
ResolveURL() which is used by Response.Redirect(), doesn't work nicely with UrlEncode, try this:
string targetURL = "~/AnotherForm.aspx?Xresult=" + HttpUtility.UrlEncode(res);
Also check this related SO answer: Response.Redirect using ~ Path
You're miscalling HttpUtility.UrlEncode.
You should only Encode the parameter value.
By Encodeing the entire URL, you are escaping the / characters, messing up your URL.

How does Response.Redirect calculate the URL for "~/folder1/folder2/some.aspx"

This might sound like a trivial problem but for some reason it is not.
Instead of needing to redirect
Response.Redirect("~/folder1/folder2/some.aspx")
I need the location as if it behaved like
string navigatingUrl = Response.Redirect("~/folder1/folder2/some.aspx")
Trying to replicate this I started with
string navigatingUrl = new Uri(HttpContext.Current.Request.Url,
new Uri("~/folder1/folder2/some.aspx", UriKind.Relative));
This instead generates "http://www.fullRequestUrl/~/folder1/folder2/some.aspx"
Edit: Well I've found out why I absolutely hate the URL API from Microsoft. I wish hellfire to whoever wrote this line of code
else if (uriKind == UriKind.Relative)
{
// Here we know that we can create an absolute Uri, but the user has requested
only a relative one
e = GetException(ParsingError.CannotCreateRelative);
}
What would possess someone to throw an error like that? This single if statement completely destroys the API.
I think you are looking for Control.ResolveUrl(). Typically you would probably use the method found on your Page object (if you are using WebForms).
Stealing from Get absolute url for a file in my asp.net project to include HTTP// etc for use externally? the only absolute way to do this is:
string url = Request.Url.GetLeftPart(UriPartial.Authority)
+ VirtualPathUtility.ToAbsolute(relativePath)
Response.Redirect(Page.ResolveUrl("~/folder1/forlder2/some.aspx"), false);

Categories

Resources