Reputation: 6428
I got this cookie returned from web-server in Set-Cookie header:
PHPSESSID=462rutd8g0sbg9sinh3hqa2ol6; path=/,wordpress_test_cookie=WP+Cookie+check; path=/,[email protected]; expires=Sun, 01-Jul-2012 05:11:02 GMT; path=/wp-content/plugins; httponly,[email protected]; expires=Sun, 01-Jul-2012 05:11:02 GMT; path=/wp-admin; httponly,wordpress_logged_in_ca07030412dd7fcd4dbeaae0bd9f5df9=testemail@example.com; expires=Sun, 01-Jul-2012 05:11:02 GMT; path=/; httponly
I am trying to use CookieContainer.SetCookies(new Uri(url),cookie);
But it throws exception '{"An error occurred when parsing the Cookie header for Uri 'http://www.smallbizads.us/'."} System.FormatException {System.Net.CookieException'
Some digging reveals that SetCookies uses , to break up the cookies. But that won't work obviously because I have Expires header which also has ,
Any idea how can I get around this issue?
Note: I can only use this method by fetching cookie from Set-Cookie
header due to Wordpress issue. So please do not suggest any other option.
Upvotes: 1
Views: 6820
Reputation: 841
Noting that the day-of-week adds no additional information and that the date can be parsed without it, we can use a Regex to remove the day and comma. Here's an extension method to use in place of CookieContainer.SetCookies()
.
/// <summary>
/// Although it's invalid, in the wild we sometimes see a Set-Cookie header with the form "Name=Value; expires=Sun, 23-Dec-2012 12:25:37 GMT".
/// Multiple cookies can be set with one header, comma separated, so CookieContainer.SetCookies() can't parse this due to the comma in the date.
/// Fortunately, the DayOfWeek provides no useful information, and the date can be parsed without it, so this removes the day and comma.
/// </summary>
public static void SetCookiesWithExpires(this CookieContainer cookies, Uri uri, String cookieHeader) {
// Note: The Regex may be created more than once in different threads. No problem; all but the last will be garbage collected.
Regex expiresEqualsDay = _expiresEqualsDay ?? (_expiresEqualsDay = new Regex(EXPIRES_EQUALS_DAY_PATTERN, RegexOptions.IgnoreCase | RegexOptions.Compiled));
cookies.SetCookies(uri, expiresEqualsDay.Replace(cookieHeader, EXPIRES_EQUALS));
}
private static Regex _expiresEqualsDay; // Lazy-initialized.
private const String EXPIRES_EQUALS_DAY_PATTERN = "; *expires=[A-Za-z]+, *";
private const String EXPIRES_EQUALS = "; Expires=";
Upvotes: 0
Reputation: 8962
Took me a while to dissect it.
As far as I can see you want to set the PHPSESSID (PHP Session Id) generated by WordPress for one domain (.smallbizads.us) for several paths. The expiration date is always the same.
First you take your cookie header:
string cookieHeader = "PHPSESSID=462rutd8g0sbg9sinh3hqa2ol6; ...etc;"
Split it by the ';' delimiter character.
var cookies = cookieHeader.Split(new[] {';'}).ToList();
You wind up with a list of 12 items. For example:
The expiration date is shown multiple times in this list, but it always has the same value. Just take the first expiration date and convert it to a DateTime.
var expiresValue = (from c in cookies
where c.Trim().StartsWith("expires")
select c).First();
var expiresOn = DateTime.Parse(expiresValue.Substring(expiresValue.IndexOf('=') + 1));
OK, now let's get the value for the cookie. The session id:
var sessionId = (from c in cookies
where c.Trim().StartsWith("PHPSESSID")
select c).Single();
sessionId = sessionId.Substring(sessionId.IndexOf('=') + 1);
Now get the paths for which you need to set the cookie.
var paths = (from c in cookies
where c.Trim().StartsWith("path=")
select c).ToList();
Now you can set the cookies using a CookieContainer and the System.Net.Cookie class.
foreach (var path in paths)
{
var cookie = new Cookie();
cookie.Name = "PHPSESSID";
cookie.Value = sessionId;
cookie.Domain = ".smallbizads.us";
cookie.Expires = expiresOn;
cookie.HttpOnly = true;
var container = new CookieContainer();
var startIndex = path.IndexOf('=') + 1;
var stopIndex = path.Contains(',') ? path.IndexOf(',') : path.Length;
cookie.Path = path.Substring(startIndex, stopIndex - startIndex);
container.Add(cookie);
}
Upvotes: 3