I set cookies based on the referral links and they all start with the same letters, lets say "google", but they end with _xxx, _yyy, _zzz or whatever is the reference.
Now, when I try to get the cookies later, I have the problem that I don't want to check for all of the different cookies, I would like to check for all cookies that start with "google" and based on that I will start a script that goes on with processing.
if (Request.Cookies("google"))
{
run other stuff
}
Any idea how I can add StartWith or something to it? I am a newbie, so not really that into C# yet.
Thanks in advance,
Pat
Well.. HttpRequest.Cookies is a collection. So use LINQ:
var qry = from cookieName in Request.Cookies.Keys
where cookieName.StartsWith("google")
select cookieName;
foreach(var item in qry)
{
// get the cookie and deal with it.
var cookie = Request.Cookies[item];
}
Bottom line: you can't get away from iterating over the entire cookie collection. But you can do it easily using LINQ.
You have to check all the cookies if you want to find ones with a certain suffix (Randolpho's answer will work).
It's not a particularly good idea to do it that way. The problem is that the more cookies you create, the more overhead you put on the server and connection. Say you have 10 cookies: google_aaa, google_bbb, etc. Each request will send all 10 cookies to your server (this includes requests for images, css, etc.
You're better off using a single cookie which is some sort of key to all the information stored on your server. Something like this:
var cookie = Cookies["google"];
if(cookie!=null)
{
// cookie.Value is a unique key for this user. Lookup this
// key in your database or other store to find out the
// information about this user.
}
If you prefer, use lambda expression, this way
var cookie = Request.Cookies.AllKeys.FirstOrDefault(s => s.Contains("yourName"));
Hope this help!
Related
I'm trying to web-crawl a site that uses php sessions via cookies. It is a good-ol' Squirrelmail webmail server.
I saw a couple of posts like this one, but it's not working for me.
When reaching the part when the cookies are sent by the host, I tried to retrieve the cookies using:
HttpWebResponse rs = (HttpWebResponse)rq.GetResponse();
CookieCollection cc = new CookieCollection();
cc.Add(rs.Cookies);
But rs.Cookies comes empty. However, there are set-cookie headers on the response, which I try to use as a guide to build actual cookies, like this:
for (int i = 0; i < rs.Headers.Count; i++)
{
if (rs.Headers.Keys[i].ToLower().Contains("cookie"))
{
string val = rs.Headers[i];
string[] vv = val.Split(";=,".ToCharArray());
Cookie co = new Cookie(vv[0], vv[1]);
// I know this is not the cleanest way to do it
// I've tried to manually set different values for
// co.Domain, co.Path and co.HttpOnly, just to get a working
// example. I tried different alternatives, but it doesn't
// seem to change anything
cc.Add(co);
}
}
Next, I send the cookies to request the next page, which is nothing but a frameset. The fact that I reach the frameset means I've been successfully authenticated and the session cookie is working. However, when I request one of the frames, I get an authentication-error web page. I've done my research, and the cookies do not change in the meantime. What may be going wrong?
Some may wonder why I'm trying to access webmail when there is pop/smtp to do a cleaner job. The answer is this is just a first example to learn the basics, I don't really care what the site is as long as I can successfully manage sessions.
I don't think posting all the code is a good idea yet, since it is a bit messy, and long: I planned to clean it once it worked (I'll post it, if you think it's worth the confusion). Moreover, I think I may have a conceptual error related to the frames, that may be the key to solve the problem.
I'm trying to create a parsing system for c#, to block my program from fetching images from "banned" websites that are located in a list. I have tried using bool class, to do a Regex.Replace operation, unfortunately it didn't work out.
To elaborate on what I exactly would like, this is an example:
I have a List BannedSites = new List { "site" };
if(Bannedsites.Contains(input))
{
Don't go to that site
}
else
{
Go to that site
}
Though the error I mostly get is I have "site" in the list, though if someone does "site " with a space afterwards it goes to the else statement, since it doesn't directly exist in the list, or if someone does "site?" and we know a questionmark at the end of the url doesn't make a difference usually to access the site, so they bypass it again. Is it possible to do something that if the input contains "site", WITHING the string, for it to not go to the site. Sorry if this is a simple code, though I haven't been able to figure it out and google didn't help.
Thanks in advance!
You can use LINQ's .Any to help with that:
if(Bannedsites.Any(x => input.Contains(x)) {
// Don't go to that site
} else {
// Go to that site
}
Remember to use .ToUpperInvariant() on everything to make it case-insensitive.
If you make sure that you only have the domain names (and arguably ips) in the list Bannedsites then you can look for the domain only.
To get the domain of a Uri, do as follows:
var uri = new Uri("http://stackoverflow.com/questions/11060418/c-sharp-string-parsing-containing-in-a-list");
Console.WriteLine(uri.DnsSafeHost);
The output is:
stackoverflow.com
Now you can get it to work like this (remember to store in upper case in Bannedsites):
var uri = new Uri(input)
if(Bannedsites.Contains(uri.DnsSafeHost.ToUpper(CultureInfo.InvariantCulture)))
{
//Don't go to that site
}
else
{
//Go to that site
}
This will also ensure that the domain didn't appear as a part of another string by chance, for example as part of a parameter.
Also note that this method will give you subdomains, so:
var uri = new Uri("http://msdn.microsoft.com/en-US/");
Console.WriteLine(uri.DnsSafeHost);
returns:
msdn.microsoft.com
and not only:
microsoft.com
You may also verify that the uri is valid with uri.IsWellFormedOriginalString():
var uri = new Uri(input)
if(uri.IsWellFormedOriginalString() && Bannedsites.Contains(uri.DnsSafeHost))
{
//Don't go to that site
}
else
{
//Go to that site
}
Now, let's say that you want to take into account the detail of subdomains, well, you can do this:
var uri = new Uri(input)
if(uri.IsWellFormedOriginalString() && Bannedsites.Any(x => uri.DnsSafeHost.EndsWith(x))
{
// Don't go to that site
}
else
{
// Go to that site
}
Lastly if you are banning particular pages not whole webs (in which case caring for the subdomains makes no sense), then you can do as follows:
var uri = new Uri(input)
if(uri.IsWellFormedOriginalString() && Bannedsites.Contains((uri.DnsSafeHost + uri.AbsolutePath)))
{
//Don't go to that site
}
else
{
//Go to that site
}
Using AbsolutePath you take care of those "?" and "#" often used to pass parameters, and any other character that doesn't change the requested page.
You may also consider using Uri.Compare and store a list of Uri instead of a list of strings.
I leave you the task of making the comparisons case invariant as RFC 1035 says:
"
For all parts of the DNS that are part of the official protocol, all
comparisons between character strings (e.g., labels, domain names, etc.)
are done in a case-insensitive manner.
"
I have this following code:
if (Request.UrlReferrer != null)
{
if (Request.UrlReferrer.PathAndQuery.ToLowerInvariant() == "/test/content.htm")
{
postbacklink = Request.UrlReferrer.AbsoluteUri.Replace("/TEST/Content.htm", "/Testing.aspx?") + Request.QueryString;
}
else
{
postbacklink = Request.UrlReferrer.AbsoluteUri;
}
}
ExtendedLoanView.PostbackLink = postbacklink;
Now this page can be accessed by two different locations. Which means this code:
postbacklink = Request.UrlReferrer.AbsoluteUri.Replace("/TEST/Content.htm", "/Test.aspx?") + Request.QueryString;
can only work with one page (Test.aspx) and is hard coded. So in IE7 Request.UrlReferrer shows me this:
Request.UrlReferrer = {http://Testing:12345/PPP/Content.htm}
Whereas in IE8+ I am getting this value:
Request.UrlReferrer = {http://Testing:12345/PPP/TestingPage.aspx?Name=Xyz&Address=123 YYY
How should I solve this issue? Its been bugging me for past month.
I would definitely advice not to base your logic on request information (not anymore than user entered values). The thing is that it will be different across browsers, and it is really hackable.
If you still need to pass information from client to server, make sure to have those validated. If you need those to stay in sync and have valid information, do not rely on what the browsers give you, but set it yourself and then take it from a place in the request you did set (for example, a hidden input, a control, a variable on the viewstate, or whatever allows the technology you're using).
Most sites handle the situation you're trying to solve by passing the destination URL in the URL itself, in a query parameter. For example:
http://www.example.com/Login.aspx?returnUrl=/TEST/content.htm
EDIT: I do realize that everything you send to the client is very hackable anyway, but if you set it yourself, it's easier for you to validate that it hasn't been tampered with. An example is the ViewState validation methods.
Is there any property in HttpRequest that can make sure if the request is a POST request and it is coming from specific domain?
private bool IsRequestedFromDomain(string domain)
{
// Request.Form is from domain ?
return false;
}
Try to use
Request.ServerVariables["HTTP_REFERER"]
Note this header can be faked.
For a list of server variables, please take a look: ASP ServerVariables Collection
HTTP Referer, but it can be modified.
Only way how to be sure is to send some , randomly generated value to form, store it to session, and in IsRequestedFromDomain compare it.
Use:
Request.UrlReferrer, though it isn't reliable as it can be easily faked and may be changed by proxies.
I would like to take the original URL, truncate the query string parameters, and return a cleaned up version of the URL. I would like it to occur across the whole application, so performing through the global.asax would be ideal. Also, I think a 301 redirect would be in order as well.
ie.
in: www.website.com/default.aspx?utm_source=twitter&utm_medium=social-media
out: www.website.com/default.aspx
What would be the best way to achieve this?
System.Uri is your friend here. This has many helpful utilities on it, but the one you want is GetLeftPart:
string url = "http://www.website.com/default.aspx?utm_source=twitter&utm_medium=social-media";
Uri uri = new Uri(url);
Console.WriteLine(uri.GetLeftPart(UriPartial.Path));
This gives the output: http://www.website.com/default.aspx
[The Uri class does require the protocol, http://, to be specified]
GetLeftPart basicallys says "get the left part of the uri up to and including the part I specify". This can be Scheme (just the http:// bit), Authority (the www.website.com part), Path (the /default.aspx) or Query (the querystring).
Assuming you are on an aspx web page, you can then use Response.Redirect(newUrl) to redirect the caller.
Here is a simple trick
Dim uri = New Uri(Request.Url.AbsoluteUri)
dim reqURL = uri.GetLeftPart(UriPartial.Path)
Here is a quick way of getting the root path sans the full path and query.
string path = Request.Url.AbsoluteUri.Replace(Request.Url.PathAndQuery,"");
This may look a little better.
string rawUrl = String.Concat(this.GetApplicationUrl(), Request.RawUrl);
if (rawUrl.Contains("/post/"))
{
bool hasQueryStrings = Request.QueryString.Keys.Count > 1;
if (hasQueryStrings)
{
Uri uri = new Uri(rawUrl);
rawUrl = uri.GetLeftPart(UriPartial.Path);
HtmlLink canonical = new HtmlLink();
canonical.Href = rawUrl;
canonical.Attributes["rel"] = "canonical";
Page.Header.Controls.Add(canonical);
}
}
Followed by a function to properly fetch the application URL.
Works perfectly.
I'm guessing that you want to do this because you want your users to see pretty looking URLs. The only way to get the client to "change" the URL in its address bar is to send it to a new location - i.e. you need to redirect them.
Are the query string parameters going to affect the output of your page? If so, you'll have to look at how to maintain state between requests (session variables, cookies, etc.) because your query string parameters will be lost as soon as you redirect to a page without them.
There are a few ways you can do this globally (in order of preference):
If you have direct control over your server environment then a configurable server module like ISAPI_ReWrite or IIS 7.0 URL Rewrite Module is a great approach.
A custom IHttpModule is a nice, reusable roll-your-own approach.
You can also do this in the global.asax as you suggest
You should only use the 301 response code if the resource has indeed moved permanently. Again, this depends on whether your application needs to use the query string parameters. If you use a permanent redirect a browser (that respects the 301 response code) will skip loading a URL like .../default.aspx?utm_source=twitter&utm_medium=social-media and load .../default.aspx - you'll never even know about the query string parameters.
Finally, you can use POST method requests. This gives you clean URLs and lets you pass parameters in, but will only work with <form> elements or requests you create using JavaScript.
Take a look at the UriBuilder class. You can create one with a url string, and the object will then parse this url and let you access just the elements you desire.
After completing whatever processing you need to do on the query string, just split the url on the question mark:
Dim _CleanUrl as String = Request.Url.AbsoluteUri.Split("?")(0)
Response.Redirect(_CleanUrl)
Granted, my solution is in VB.NET, but I'd imagine that it could be ported over pretty easily. And since we are only looking for the first element of the split, it even "fails" gracefully when there is no querystring.