CookiecontainerHasBugOnHandling DomainName here
Https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx? Feedbackid = 478521
And Microsoft decided notFixIt In. NET 2.0/3.0/3.5.
I want to inspect the problem and want to do my own hack to solve this issue in. Net earlier than 4.0.
At first, there is three object related to Cookie management in this issue, Cookie, cookiecollection andCookiecontainer. Cookie is the cookie object, cookiecollection is just simply the collection of cookies andCookiecontainerIs a cookie or cookiecollection container that will manageDomainUri, path and expiry.
Now the issue resides inCookiecontainerWhich not handleDomainProperly.
Domain HandlingIs important because it tells client side browser or processor which cookie is visible to the client side code and can be sent back to the server. The theory is something like this:
Web from different Domain Can't access cookie which is belong to other Domain . For example http://www.yahoo.com can't see all cookies from Google.com.
Sub Domain Can access cookies for the sub Domain And all its parent subDomain And Domain Itself. For example http://groups.google.com can see cookies from groups.google.com and .google.com.
Parent sub Domain Or Domain Itself can't access cookies from any of its child sub Domain . So http :// Domain . Com can't see cookies from sub. Domain . Com.
However I have a little confusing about the dot at the beginning as the rfc2019 standard like.Domain. Com and. Groups.Domain. Com compare to non-dotDomain.
Back to the issue,CookiecontainerHas three interested Method for me to inspect. It is add, getcookies and setcookies.
To properly inspectCookiecontainerObject, I shocould not trust to all these three methods instead, I want to use reflection to see what happened inside the object.
After some reflection studuying, I reveal this fields:
CookiecontainerCC has m_domaintable Field
Hashtable m_domaintable
Hashtable key: StringDomain
Hashtable value: pathlist
Pathlist has m_list Field
Sortedlist m_list
Key: String path
Value: cookiecollection colcookies
So fromCookiecontainerObject, we can get the cookie object by this path:DomainString> path string> cookies. All cookies are grouped by path andDomain.
This is the code that helping me to studyCookiecontainerObject, I get from http://channel9.msdn.com/forums/TechOff/260235-Bug-In-Cookiecontainer-Where-do-I-Report/thanks to johnwinner:
Public list getallcookies (CookiecontainerCC)
{
List lstcookies = new list ();
Hashtable table = (hashtable) CC. getType (). invokemember ("m_domaintable", system. reflection. bindingflags. nonpublic | system. reflection. bindingflags. getfield | system. reflection. bindingflags. instance, null, CC, new object [] {});
Foreach (Object pathlist in table. values)
{
Sortedlist lstcookiecol = (sortedlist) pathlist. getType (). invokemember ("m_list", system. reflection. bindingflags. nonpublic | system. reflection. bindingflags. getfield | system. reflection. bindingflags. instance, null, pathlist, new object [] {});
Foreach (cookiecollection colcookies in lstcookiecol. values)
Foreach (cookie C in colcookies) lstcookies. Add (C );
}
Return lstcookies;
}
Now I want to test all ADD, getcookies and setcookies methods if it doing right.
Testing add method:
This are the code I use to test it:
Uri u = new uri ("http: // sub.Domain . Com ");
Cookie C1 = new cookie ("test1", httputility. urlencode ("www. Domain . Com "),"/"," www. Domain . Com ");
Cookie C11 = new cookie ("test11", httputility. urlencode (". www. Domain . Com "),"/",". www. Domain . Com ");
Cookie C2 = new cookie ("Test2", httputility. urlencode ("sub. Domain . Com "),"/"," sub. Domain . Com ");
Cookie C21 = new cookie ("test21", httputility. urlencode ("sub. Domain . Com "),"/"," sub. Domain . Com ");
Cookie c22 = new cookie ("test22", httputility. urlencode (". sub. Domain . Com "),"/",". sub. Domain . Com ");
Cookie C3 = new cookie ("test3", httputility. urlencode (". Domain . Com "),"/",". Domain . Com ");
Cookie C31 = new cookie ("test31", httputility. urlencode (". Domain . Com "),"/",". Domain . Com ");
Cookie C4 = new cookie ("test4", httputility. urlencode (" Domain . Com "),"/"," Domain . Com ");
Cookiecontainer Cc = new Cookiecontainer ();
I test Add the cookie by this,
Cc. Add (C2 );
Cc. Add (C21 );
Cc. Add (C3 );
Cc. Add (C31 );
Cc. Add (C4 );
And this
CC. add (u, C2);
CC. add (u, C21);
CC. add (u, C3);
CC. add (u, C31);
CC. add (u, C4);
note that C1 and C11 has been removed from testing add (Uri, cookie) and add (Uri, cookiecollection) Since using URI sub. domain . com will throw an exception the ' domain ' = 'www. domain . com 'part of the cookie is invalid. I think the WWW consider a diffrent 'sub domain 'which is not related to the sub domain (sub. domain . com ).
maybe the www. domain . com cookie used to let the cookie visible in the domain . com but not in its sub domain .
Checking the table, lstcookiecol, colcookies and C object in the getallcookies method above, I can conclude this:
Add and setcookie method:
Add (cookie) vs add (Uri, cookie) overloads:
Hashtable m_domaintable key store in different way. The key is Domain Name.
Add (cookie) stored in Domain Key which is direct get from Domain Property of the cookie.
Add (Uri, cookie) stored in Domain Key which are using the rfc2109 standard, all domains will start with Dot. So all cookiesDomain . Sub. Domain . Com and sub. Domain . Com will merge into. sub. Domain . Com hashtable key. Note that this modification Domain Name Only effect to hashtable Domain Key and not Domain Property in the cookie. Domain Property in cookie will remain unchange.
I get this result by checking table. keys value. another two add overloads add (cookiecollection) and add (Uri, cookiecollection) will result the same like add (cookie) and add (Uri, cookie) respectively. finction. setcookie (Uri, cookieheader) also use. add () internally.
So now we have two different way on how the cookie stored in the cookiecollection object.
#1 the key will be use direct fromDomainProperty of the cookie. This is related to add (cookie) which I thinkBug.
#2 the key will start with Dot. The dot will added in the beginningDomainProperty of the cookie if it doesn' t have. This is related to add (Uri, cookie)
In my point of view #1 isBugBecause it store. sub.Domain. Com and sub.Domain. Com in different group but logically we need the both cookies in the sub visible to http: // sub.Domain. Com.
Getcookies method:
During inspecting add method overloads, I also check the cookiecollection returned from CC. getcookies (u ).
To make easier to check the result I use this code (because list have better debugging visualization than cookiecollection ):
List lstcookies = mygetcookies (CC, new uri ("http: // sub.Domain. Com "));
Public list mygetcookies (CookiecontainerCC, Uri U)
{
List lstcookies = new list ();
Cookiecollection colcookies = cc. getcookies (U );
Foreach (cookie C in colcookies)
Lstcookies. Add (C );
Return lstcookies;
}
Using this. getcookies (URI), retrieving cookies which is specific in #1 and #2 will have different result. both result are not correct one and it resides into two different problems. problem #1 and problem #2 related to #1 and #2 respectively.
problem #1: It can't retrieve cookies for Current sub domain Start With Dot and from parent domain not start with dot. so I just get Cookie C2, C21, C3 and c31.
problem #2: It can't retrieve cookies for Current sub domain since the sub domain was added a dot at the beginning. I just get Cookie C3, C31 and C4.
I aspect all 6 cookies shocould be retrieved. after a few days, I just realize the problem #1 and problem #2 is the same thing on how getcookies retrieve the cookies. it can't retrieve cookies for Current sub domain Start With Dot and from domain not start with dot. since problem #2 use. add (Uri, cookie) and all domain key will start with dot, so it can only retrieve all parent domain .
remember back, we have 2 domain keys. sub. domain . COM and. domain . com. so when URI is http: // sub. domain . com. only all cookies in. domain . com. can be retrieve. to make the getcookies can retrieve the Current sub domain in. sub. domain . com key, we need to make another key which is don't have dot at the beginning. it is sub. domain . com. that means we shoshould have this 2 keys sub. domain . COM and. domain . com.
Consider that the subDomainHas another sub. So sub1.sub.Domain. Com need. sub.Domain. Com key in order to retrieve the cookie. So I can conclude that we need to make allDomainHave dot and non-dot version. Thus getcookies can retrieve cookies from the current subDomainAnd all its parent.
Since using Add (Uri, cookie) method only generate dotDomainKey, We need to copy it to a new non-dotDomainKey. Here is the functionFixIt.
private void bugfix_cookiedomain ( cookiecontainer cookiecontainer )
{< br> hashtable table = (hashtable) _ containertype. invokemember ("m_domaintable",
system. reflection. bindingflags. nonpublic |
system. reflection. bindingflags. getfield |
system. reflection. bindingflags. instance,
null,
cookiecontainer ,
new object [] {});
arraylist keys = new arraylist (table. keys);
foreach (string keyobj in keys)
{< br> string key = (keyobj as string );
If (Key [0] = '. ')
{< br> string newkey = key. remove (0, 1);
table [newkey] = table [keyobj];
}< BR >}
Thanks to salarsoft that solve thisBug Fix. I get it in the source of asproxy. This is an assumption that Method Add (Uri, cookie) is always used and dotDomainKey created. To be better coding you can modify this code to make sure DotDomainKey always mirror to non-dotDomainKey vice versa, then you can use add (cookie) method.
As a conclusionCookiecontainerCan beFixBy using this function with this simple two conditions:
Below isArticleThe key point is that the bug does not exist.
-Don't use add (cookie), always use add (Uri, cookie)
-Call bugfix_cookiedomain each time you add cookie or before you retrieve it using getcookies or before system use the container.