Add complex redirection unit test. Cater for expiration of cookie in redirection flow

This commit is contained in:
Ai Lin Chia
2016-12-14 16:47:07 +01:00
parent 1ed7f50767
commit ce2b9c6834
3 changed files with 324 additions and 82 deletions

@ -508,9 +508,9 @@ bool HttpMime::parseSetCookie(const char *field, size_t fieldLen) {
time_t expiry = 0;
if (parseCookieDate(attributeValue, attributeValueLen, &expiry) && expiry < m_currentTime) {
// expired (skip cookie)
// expired
logTrace(g_conf.m_logTraceHttpMime, "expires='%.*s'. expiry=%ld currentTime=%ld expired cookie. ignoring", static_cast<int>(attributeValueLen), attributeValue, expiry, m_currentTime);
return true;
cookie.m_expired = true;
}
continue;
@ -528,9 +528,9 @@ bool HttpMime::parseSetCookie(const char *field, size_t fieldLen) {
foundMaxAge = true;
int32_t maxAge = strtol(attributeValue, NULL, 10);
if (maxAge == 0) {
// expired (skip cookie)
// expired
logTrace(g_conf.m_logTraceHttpMime, "max-age=%.*s. expired cookie. ignoring", static_cast<int>(attributeValueLen), attributeValue);
return true;
cookie.m_expired = true;
}
continue;
}
@ -1380,6 +1380,74 @@ bool HttpMime::init ( ) {
return true;
}
void HttpMime::addCookie(const httpcookie_t &cookie, const Url &currentUrl, SafeBuf *cookieJar) {
// don't add expired cookie into cookie jar
if (cookie.m_expired) {
return;
}
if (cookie.m_domain) {
cookieJar->safeMemcpy(cookie.m_domain, cookie.m_domainLen);
cookieJar->pushChar('\t');
cookieJar->safeStrcpy(cookie.m_defaultDomain ? "FALSE\t" : "TRUE\t");
} else {
cookieJar->safeMemcpy(currentUrl.getHost(), currentUrl.getHostLen());
cookieJar->pushChar('\t');
cookieJar->safeStrcpy("FALSE\t");
}
if (cookie.m_path) {
cookieJar->safeMemcpy(cookie.m_path, cookie.m_pathLen);
cookieJar->pushChar('\t');
} else {
if (currentUrl.getPathLen()) {
cookieJar->safeMemcpy(currentUrl.getPath(), currentUrl.getPathLen());
} else {
cookieJar->pushChar('/');
}
cookieJar->pushChar('\t');
}
if (cookie.m_secure) {
cookieJar->safeStrcpy("TRUE\t");
} else {
cookieJar->safeStrcpy("FALSE\t");
}
// we're not using expiration field
cookieJar->safeStrcpy("0\t");
int32_t currentLen = cookieJar->length();
cookieJar->safeMemcpy(cookie.m_cookie, cookie.m_cookieLen);
// cater for multiline cookie
const char *currentPos = cookieJar->getBufStart() + currentLen;
const char *delPosStart = NULL;
int32_t delLength = 0;
while (currentPos < cookieJar->getBufPtr() - 1) {
if (delPosStart) {
if (is_wspace_a(*currentPos) || *currentPos == '\n' || *currentPos == '\r') {
++delLength;
} else {
break;
}
} else {
if (*currentPos == '\n' || *currentPos == '\r') {
delPosStart = currentPos;
++delLength;
}
}
++currentPos;
}
cookieJar->removeChunk1(delPosStart, delLength);
/// @todo ALC handle httpOnly attribute
cookieJar->pushChar('\n');
}
bool HttpMime::addToCookieJar(Url *currentUrl, SafeBuf *sb) {
/// @note Slightly modified from Netscape HTTP Cookie File format
/// Difference is we only have one column for name/value
@ -1405,74 +1473,84 @@ bool HttpMime::addToCookieJar(Url *currentUrl, SafeBuf *sb) {
// * Among cookies that have equal-length path fields, cookies with earlier creation-times are listed
// before cookies with later creation-times.
for (auto &pair : m_cookies) {
auto &cookie = pair.second;
// fill in cookies from cookieJar
std::map<std::string, httpcookie_t> oldCookies;
/// @todo ALC cater for multiline cookie
const char *cookieJar = sb->getBufStart();
int32_t cookieJarLen = sb->length();
if (cookie.m_domain) {
sb->safeMemcpy(cookie.m_domain, cookie.m_domainLen);
sb->pushChar('\t');
sb->safeStrcpy("TRUE\t");
} else {
sb->safeMemcpy(currentUrl->getHost(), currentUrl->getHostLen());
sb->pushChar('\t');
const char *lineStartPos = cookieJar;
const char *lineEndPos = NULL;
while ((lineEndPos = (const char*)memchr(lineStartPos, '\n', cookieJarLen - (lineStartPos - cookieJar))) != NULL) {
const char *currentPos = lineStartPos;
const char *tabPos = NULL;
unsigned fieldCount = 0;
sb->safeStrcpy("FALSE\t");
}
if (cookie.m_path) {
sb->safeMemcpy(cookie.m_path, cookie.m_pathLen);
sb->pushChar('\t');
} else {
/// @todo ALC calculate default path
if (currentUrl->getPathLen()) {
sb->safeMemcpy(currentUrl->getPath(), currentUrl->getPathLen());
} else {
sb->pushChar('/');
}
sb->pushChar('\t');
}
if (cookie.m_secure) {
sb->safeStrcpy("TRUE\t");
} else {
sb->safeStrcpy("FALSE\t");
}
// we're not using expiration field
sb->safeStrcpy("0\t");
int32_t currentLen = sb->length();
sb->safeMemcpy(cookie.m_cookie, cookie.m_cookieLen);
// cater for multiline cookie
const char *currentPos = sb->getBufStart() + currentLen;
const char *delPosStart = NULL;
int32_t delLength = 0;
while (currentPos < sb->getBufPtr() - 1) {
if (delPosStart) {
if (is_wspace_a(*currentPos) || *currentPos == '\n' || *currentPos == '\r') {
++delLength;
} else {
httpcookie_t cookie = {};
while (fieldCount < 5 && (tabPos = (const char*)memchr(currentPos, '\t', lineEndPos - currentPos)) != NULL) {
switch (fieldCount) {
case 0:
// domain
cookie.m_domain = currentPos;
cookie.m_domainLen = tabPos - currentPos;
break;
case 1:
// flag
if (memcmp(currentPos, "TRUE", 4) != 0) {
cookie.m_defaultDomain = true;
}
break;
case 2: {
// path
cookie.m_path = currentPos;
cookie.m_pathLen = tabPos - currentPos;
} break;
case 3:
// secure
cookie.m_secure = (memcmp(currentPos, "TRUE", 4) == 0);
break;
case 4:
// expiration
break;
}
} else {
if (*currentPos == '\n' || *currentPos == '\r') {
delPosStart = currentPos;
++delLength;
}
}
++currentPos;
currentPos = tabPos + 1;
++fieldCount;
}
sb->removeChunk1(delPosStart, delLength);
/// @todo ALC handle httpOnly attribute
cookie.m_cookie = currentPos;
cookie.m_cookieLen = lineEndPos - currentPos;
sb->pushChar('\n');
const char *equalPos = (const char *)memchr(cookie.m_cookie, '=', cookie.m_cookieLen);
if (equalPos) {
cookie.m_nameLen = equalPos - cookie.m_cookie;
oldCookies[std::string(cookie.m_cookie, cookie.m_nameLen)] = cookie;
}
lineStartPos = lineEndPos + 1;
}
// we don't need to care about the last line (we always end on \n)
SafeBuf newCookieJar;
// add old cookies
for (auto &pair : oldCookies) {
if (m_cookies.find(pair.first) == m_cookies.end()) {
addCookie(pair.second, *currentUrl, &newCookieJar);
}
}
// add new cookies
for (auto &pair : m_cookies) {
addCookie(pair.second, *currentUrl, &newCookieJar);
}
newCookieJar.nullTerm();
// replace old with new
sb->reset();
sb->safeMemcpy(&newCookieJar);
sb->nullTerm();
return true;
@ -1507,12 +1585,15 @@ bool HttpMime::addCookieHeader(const char *cookieJar, const char *url, SafeBuf *
// flag
if (memcmp(currentPos, "TRUE", 4) == 0) {
// allow subdomain
if (tmpUrl.getHostLen() < domainLen) {
if (tmpUrl.getHostLen() >= domainLen) {
if (!endsWith(tmpUrl.getHost(), tmpUrl.getHostLen(), domain, domainLen)) {
// doesn't end with domain - ignore cookie
skipCookie = true;
break;
}
} else {
skipCookie = true;
break;
}
} else {
// only specific domain
@ -1578,13 +1659,16 @@ void HttpMime::print() const {
logf(LOG_TRACE, "Cookies :");
int i = 0;
for (auto &pair : m_cookies) {
auto &cookie = pair.second;
logf(LOG_TRACE, "\tcookie #%d :", i++);
logf(LOG_TRACE, "\t\tname : %.*s", static_cast<int>(cookie.m_nameLen), cookie.m_cookie);
logf(LOG_TRACE, "\t\tvalue : %.*s", static_cast<int>(cookie.m_cookieLen - cookie.m_nameLen - 1), cookie.m_cookie + cookie.m_nameLen + 1);
logf(LOG_TRACE, "\t\tpath : %.*s", static_cast<int>(cookie.m_pathLen), cookie.m_path);
logf(LOG_TRACE, "\t\tdomain : %.*s", static_cast<int>(cookie.m_domainLen), cookie.m_domain);
logf(LOG_TRACE, "\t\tsecure : %s", cookie.m_secure ? "true" : "false");
logf(LOG_TRACE, "\t\thttponly : %s", cookie.m_httpOnly ? "true" : "false");
print(pair.second, i++);
}
}
void HttpMime::print(const httpcookie_t &cookie, int count) {
logf(LOG_TRACE, "\tcookie #%d :", count);
logf(LOG_TRACE, "\t\tname : %.*s", static_cast<int>(cookie.m_nameLen), cookie.m_cookie);
logf(LOG_TRACE, "\t\tvalue : %.*s", static_cast<int>(cookie.m_cookieLen - cookie.m_nameLen - 1), cookie.m_cookie + cookie.m_nameLen + 1);
logf(LOG_TRACE, "\t\tpath : %.*s", static_cast<int>(cookie.m_pathLen), cookie.m_path);
logf(LOG_TRACE, "\t\tdomain : %.*s", static_cast<int>(cookie.m_domainLen), cookie.m_domain);
logf(LOG_TRACE, "\t\tsecure : %s", cookie.m_secure ? "true" : "false");
logf(LOG_TRACE, "\t\thttponly : %s", cookie.m_httpOnly ? "true" : "false");
}

@ -135,6 +135,7 @@ protected:
size_t m_nameLen;
bool m_defaultDomain;
const char *m_domain;
size_t m_domainLen;
@ -143,6 +144,8 @@ protected:
bool m_secure;
bool m_httpOnly;
bool m_expired;
};
bool getNextLine();
@ -186,6 +189,9 @@ private:
// used for bz2, gz files
const char *getContentEncodingFromExtension ( const char *ext ) ;
static void addCookie(const httpcookie_t &cookie, const Url &currentUrl, SafeBuf *cookieJar);
static void print(const httpcookie_t &cookie, int count = 0);
const char *m_currentLine;
size_t m_currentLineLen;

@ -38,12 +38,11 @@ public:
using HttpMime::parseCookieDate;
void verifyCookie(const char *cookieName, const char *expectedCookie, const char *path = "", const char *domain = "", bool httpOnly = false, bool secure = false);
void verifyCookie(const char *cookieName, const char *expectedCookie, const char *path = "", const char *domain = "", bool httpOnly = false, bool secure = false, bool expired = false);
bool addCookieHeader(const char *url, SafeBuf *sb) {
SafeBuf cookieJar;
if (HttpMime::addToCookieJar(&m_url, &cookieJar)) {
return HttpMime::addCookieHeader(cookieJar.getBufStart(), url, sb);
bool addCookieHeader(const char *url, SafeBuf *cookieJar, SafeBuf *sb) {
if (HttpMime::addToCookieJar(&m_url, cookieJar)) {
return HttpMime::addCookieHeader(cookieJar->getBufStart(), url, sb);
}
return false;
@ -229,7 +228,7 @@ TEST(HttpMimeTest, ParseCookieDateInvalid) {
}
}
void TestHttpMime::verifyCookie(const char *cookieName, const char *expectedCookie, const char *path, const char *domain, bool httpOnly, bool secure) {
void TestHttpMime::verifyCookie(const char *cookieName, const char *expectedCookie, const char *path, const char *domain, bool httpOnly, bool secure, bool expired) {
std::stringstream ss;
ss << __func__ << ":"
<< " expectedCookie='" << expectedCookie << "'";
@ -253,6 +252,8 @@ void TestHttpMime::verifyCookie(const char *cookieName, const char *expectedCook
EXPECT_EQ(httpOnly, cookie.m_httpOnly);
EXPECT_EQ(secure, cookie.m_secure);
EXPECT_EQ(expired, cookie.m_expired);
}
TEST(HttpMimeTest, SetCookieSingle) {
@ -625,7 +626,7 @@ TEST(HttpMimeTest, SetCookieExpiresExpired) {
TestHttpMime httpMime(httpResponse, "http://www.lawdepot.com/");
ASSERT_EQ(10, httpMime.getCookies().size());
ASSERT_EQ(16, httpMime.getCookies().size());
httpMime.verifyCookie("L", "L=US", "/");
httpMime.verifyCookie("cb_FirstVisit", "cb_FirstVisit=2016%2F11%2F25+17%3A22%3A27", "/");
httpMime.verifyCookie("brand", "brand=+", "/");
@ -636,6 +637,12 @@ TEST(HttpMimeTest, SetCookieExpiresExpired) {
httpMime.verifyCookie("___utmvmXEuIKXs", "___utmvmXEuIKXs=xscHtJOFkSw", "/");
httpMime.verifyCookie("___utmvaXEuIKXs", "___utmvaXEuIKXs=cEK^AyUTl", "/");
httpMime.verifyCookie("___utmvbXEuIKXs", "___utmvbXEuIKXs=mZd\r\n XGPOvala: PtX", "/");
httpMime.verifyCookie("cb_Referrer", "cb_Referrer=deleted", "/", "", false, false, true);
httpMime.verifyCookie("ASP.NET_SessionId", "ASP.NET_SessionId=deleted", "/", "", false, false, true);
httpMime.verifyCookie("UID", "UID=deleted", "/", "www.lawdepot.com", false, false, true);
httpMime.verifyCookie("LoginID", "LoginID=deleted", "/", "www.lawdepot.com", false, false, true);
httpMime.verifyCookie("pricing_region", "pricing_region=deleted", "/", "www.lawdepot.com", false, false, true);
httpMime.verifyCookie("free_account", "free_account=deleted", "/", "www.lawdepot.com", false, false, true);
}
@ -700,9 +707,10 @@ TEST(HttpMimeTest, SetCookieMaxAgeZero) {
TestHttpMime httpMime(httpResponse, "http://www.panelook.com/");
ASSERT_EQ(2, httpMime.getCookies().size());
ASSERT_EQ(3, httpMime.getCookies().size());
httpMime.verifyCookie("PHPSESSID", "PHPSESSID=iull787l2g108u2t3gnhrdnp81", "/", "", true);
httpMime.verifyCookie("safedog-flow-item", "safedog-flow-item=05291A2AAF3F4BEAD675A8148D837FA5", "/", "panelook.com");
httpMime.verifyCookie("too_user", "too_user=%2BfkOkj4w4rI", "", "", false, false, true);
}
TEST(HttpMimeTest, SetCookieEmptySemicolon) {
@ -837,8 +845,9 @@ TEST(HttpMimeTest, SetCookieMultipleLine) {
httpMime.verifyCookie("___utmvaLouNZtS", "___utmvaLouNZtS=VjM^AZrsi", "/");
httpMime.verifyCookie("___utmvbLouNZtS", "___utmvbLouNZtS=ZZQ\r\n XZKOgalf: ztw", "/");
SafeBuf cookieJar;
SafeBuf sb;
httpMime.addCookieHeader("http://138.com", &sb);
httpMime.addCookieHeader("http://138.com", &cookieJar, &sb);
EXPECT_STREQ("Cookie: "
"___utmvaLouNZtS=VjM^AZrsi;"
"___utmvbLouNZtS=ZZQXZKOgalf: ztw;"
@ -848,9 +857,10 @@ TEST(HttpMimeTest, SetCookieMultipleLine) {
"visid_incap_780362=ummcL4XfSPqPE6kzQWznBwGAOVgAAAAAQUIPAAAAAADFlgKMS3kveaymHYa2wup3;"
"\r\n", sb.getBufStart());
cookieJar.reset();
sb.reset();
httpMime.addCookieHeader("http://www.138.com", &sb);
httpMime.addCookieHeader("http://www.138.com", &cookieJar, &sb);
EXPECT_STREQ("Cookie: "
"incap_ses_543_780362=39xOCBhzFCWSlPLUqB+JBwGAOVgAAAAAkwB11WvDUCsxFSM3MZ5mWQ==;"
"nlbi_780362=Vxv4X1JzkTQAR/rHbnjLsgAAAADxUw2DWAG4Ije6+uOVG0N8;"
@ -889,8 +899,10 @@ TEST(HttpMimeTest, SetCookieMultiplePath) {
httpMime.verifyCookie("client_timestamp", "client_timestamp=1480096605", "/", "220-volt.ru");
httpMime.verifyCookie("session", "session=1480096605.66301394", "/", "220-volt.ru");
SafeBuf cookieJar;
SafeBuf sb;
httpMime.addCookieHeader("http://220-volt.ru/", &sb);
httpMime.addCookieHeader("http://220-volt.ru/", &cookieJar, &sb);
EXPECT_STREQ("Cookie: "
"advref=typein:;"
"advref_first=typein:;"
@ -898,9 +910,10 @@ TEST(HttpMimeTest, SetCookieMultiplePath) {
"session=1480096605.66301394;"
"\r\n", sb.getBufStart());
cookieJar.reset();
sb.reset();
httpMime.addCookieHeader("http://220-volt.ru/order/", &sb);
httpMime.addCookieHeader("http://220-volt.ru/order/", &cookieJar, &sb);
EXPECT_STREQ("Cookie: "
"advref=typein:;"
"advref_date=1480096605;"
@ -909,4 +922,143 @@ TEST(HttpMimeTest, SetCookieMultiplePath) {
"client_timestamp=1480096605;"
"session=1480096605.66301394;"
"\r\n", sb.getBufStart());
}
TEST(HttpMimeTest, SetCookieAnswersMicrosoftCom) {
SafeBuf cookieJar;
const char *url1 = "http://answers.microsoft.com/en-us/ie/";
const char *url2 = "https://answers.microsoft.com/en-us/site/startsignin?pageUrl=http%3A%2F%2Fanswers.microsoft.com%3A80%2Fen-us%2Fie%2F%3Fauth%3D1&silent=True";
const char *url3 = "https://login.live.com/login.srf?wa=wsignin1.0&rpsnv=13&checkda=1&ct=1479997321&rver=6.5.6509.0&wp=MBI_SSL&wreply=https:%2F%2Fanswers.microsoft.com%2Fen-us%2Fsite%2Fcompletesignin%3Fsilent%3DTrue%26returnUrl%3Dhttp%253A%252F%252Fanswers.microsoft.com%253A80%252Fen-us%252Fie%252F%253Fauth%253D1&id=273572";
const char *url4 = "https://answers.microsoft.com/en-us/site/completesignin?silent=True&returnUrl=http%3A%2F%2Fanswers.microsoft.com%3A80%2Fen-us%2Fie%2F%3Fauth%3D1";
const char *url5 = "http://answers.microsoft.com/en-us/ie/?auth=1";
char httpResponse1[] =
"HTTP/1.1 302 Moved Temporarily\r\n"
"Content-Type: text/html; charset=utf-8\r\n"
"Location: https://answers.microsoft.com/en-us/site/startsignin?pageUrl=http%3A%2F%2Fanswers.microsoft.com%3A80%2Fen-us%2Fie%2F%3Fauth%3D1&silent=True\r\n"
"Server: Microsoft-IIS/8.5\r\n"
"X-FRAME-OPTIONS: SAMEORIGIN\r\n"
"X-UA-Compatible: IE=edge\r\n"
"X-Content-Type-Options: nosniff\r\n"
"X-EdgeConnect-MidMile-RTT: 22\r\n"
"X-EdgeConnect-Origin-MEX-Latency: 30\r\n"
"Expires: Thu, 26 Nov 2016 14:22:00 GMT\r\n"
"Cache-Control: max-age=0, no-cache, no-store\r\n"
"Pragma: no-cache\r\n"
"Date: Thu, 26 Nov 2016 14:22:00 GMT\r\n"
"Connection: close\r\n"
"Set-Cookie: community.silentsignin=; domain=answers.microsoft.com; path=/; HttpOnly\r\n"
"Set-Cookie: MS-CACHE=CACHE-true; expires=Thu, 26-Nov-2016 13:31:41 GMT\r\n"
"Cache-Control: no-transform\r\n"
"\r\n";
TestHttpMime httpMime1(httpResponse1, url1);
SafeBuf sb1;
httpMime1.addCookieHeader(url2, &cookieJar, &sb1);
EXPECT_STREQ("Cookie: "
"community.silentsignin=;"
"\r\n", sb1.getBufStart());
char httpResponse2[] =
"HTTP/1.1 302 Moved Temporarily\r\n"
"Content-Type: text/html; charset=utf-8\r\n"
"Location: https://login.live.com/login.srf?wa=wsignin1.0&rpsnv=13&checkda=1&ct=1479997321&rver=6.5.6509.0&wp=MBI_SSL&wreply=https:%2F%2Fanswers.microsoft.com%2Fen-us%2Fsite%2Fcompletesignin%3Fsilent%3DTrue%26returnUrl%3Dhttp%253A%252F%252Fanswers.microsoft.com%253A80%252Fen-us%252Fie%252F%253Fauth%253D1&id=273572\r\n"
"Server: Microsoft-IIS/8.5\r\n"
"X-FRAME-OPTIONS: SAMEORIGIN\r\n"
"X-UA-Compatible: IE=edge\r\n"
"X-Content-Type-Options: nosniff\r\n"
"Content-Length: 577\r\n"
"Expires: Thu, 26 Nov 2016 14:22:00 GMT\r\n"
"Cache-Control: max-age=0, no-cache, no-store\r\n"
"Pragma: no-cache\r\n"
"Date: Thu, 26 Nov 2016 14:22:00 GMT\r\n"
"Connection: keep-alive\r\n"
"Set-Cookie: rtPage=http://answers.microsoft.com/en-us/ie/?auth=1; domain=answers.microsoft.com; path=/\r\n"
"Cache-Control: no-transform\r\n"
"\r\n";
TestHttpMime httpMime2(httpResponse2, url2);
SafeBuf sb2;
httpMime2.addCookieHeader(url3, &cookieJar, &sb2);
EXPECT_EQ(NULL, sb2.getBufStart());
char httpResponse3[] =
"HTTP/1.1 302 Found\r\n"
"Cache-Control: no-cache\r\n"
"Pragma: no-cache\r\n"
"Content-Length: 0\r\n"
"Content-Type: text/html; charset=utf-8\r\n"
"Expires: Thu, 26 Nov 2016 14:21:01 GMT\r\n"
"Location: https://answers.microsoft.com/en-us/site/completesignin?silent=True&returnUrl=http%3A%2F%2Fanswers.microsoft.com%3A80%2Fen-us%2Fie%2F%3Fauth%3D1\r\n"
"Server: Microsoft-IIS/8.5\r\n"
"P3P: CP=\"DSP CUR OTPi IND OTRi ONL FIN\"\r\n"
"Set-Cookie: uaid=0b67f5d4e948427a87b516f2362e5568; domain=login.live.com;secure= ;path=/;HTTPOnly= ;version=1\r\n"
"Set-Cookie: MSPRequ=lt=1479997321&co=1&id=273572; secure= ;path=/;HTTPOnly=;version=1\r\n"
"X-Content-Type-Options: nosniff\r\n"
"Strict-Transport-Security: max-age=31536000\r\n"
"X-XSS-Protection: 1; mode=block\r\n"
"Date: Thu, 26 Nov 2016 14:22:00 GMT\r\n"
"Connection: close\r\n"
"\r\n";
TestHttpMime httpMime3(httpResponse3, url3);
SafeBuf sb3;
httpMime3.addCookieHeader(url4, &cookieJar, &sb3);
EXPECT_STREQ("Cookie: "
"community.silentsignin=;"
"rtPage=http://answers.microsoft.com/en-us/ie/?auth=1;"
"\r\n", sb3.getBufStart());
char httpResponse4[] =
"HTTP/1.1 302 Moved Temporarily\r\n"
"Content-Type: text/html; charset=utf-8\r\n"
"Location: http://answers.microsoft.com/en-us/ie/?auth=1\r\n"
"Server: Microsoft-IIS/8.5\r\n"
"X-FRAME-OPTIONS: SAMEORIGIN\r\n"
"X-UA-Compatible: IE=edge\r\n"
"X-Content-Type-Options: nosniff\r\n"
"X-EdgeConnect-MidMile-RTT: 43\r\n"
"X-EdgeConnect-Origin-MEX-Latency: 7\r\n"
"Expires: Thu, 26 Nov 2016 14:22:01 GMT\r\n"
"Cache-Control: max-age=0, no-cache, no-store\r\n"
"Pragma: no-cache\r\n"
"Date: Thu, 26 Nov 2016 14:22:01 GMT\r\n"
"Connection: close\r\n"
"Set-Cookie: rtPage=; domain=answers.microsoft.com; expires=Tue, 24-Nov-2015 14:22:01 GMT; path=/\r\n"
"Cache-Control: no-transform\r\n"
"\r\n";
TestHttpMime httpMime4(httpResponse4, url4);
SafeBuf sb4;
httpMime4.addCookieHeader(url5, &cookieJar, &sb4);
EXPECT_STREQ("Cookie: "
"MS-CACHE=CACHE-true;"
"community.silentsignin=;"
"\r\n", sb4.getBufStart());
char httpResponse5[] =
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html; charset=utf-8\r\n"
"Server: Microsoft-IIS/8.5\r\n"
"X-FRAME-OPTIONS: SAMEORIGIN\r\n"
"X-UA-Compatible: IE=edge\r\n"
"X-Content-Type-Options: nosniff\r\n"
"Content-Length: 42688\r\n"
"X-EdgeConnect-MidMile-RTT: 0\r\n"
"X-EdgeConnect-Origin-MEX-Latency: 62\r\n"
"X-EdgeConnect-MidMile-RTT: 23\r\n"
"X-EdgeConnect-Origin-MEX-Latency: 62\r\n"
"Expires: Thu, 26 Nov 2016 14:22:01 GMT\r\n"
"Cache-Control: max-age=0, no-cache, no-store\r\n"
"Pragma: no-cache\r\n"
"Date: Thu, 26 Nov 2016 14:22:01 GMT\r\n"
"Connection: keep-alive\r\n"
"Set-Cookie: asid=b9a84e7b-1c0e-4b93-88bb-f4ad3b8dacfe; domain=answers.microsoft.com; path=/; HttpOnly\r\n"
"Set-Cookie: MS-CACHE=CACHE-true; expires=Thu, 24-Nov-2016 14:22:31 GMT\r\n"
"Cache-Control: no-transform\r\n"
"\r\n";
TestHttpMime httpMime5(httpResponse5, url5);
}