bool HttpMime::addCookieHeader(const char *cookieJar, const char *url, SafeBuf *sb) { Url tmpUrl; tmpUrl.set(url); SafeBuf tmpSb; size_t cookieJarLen = strlen(cookieJar); 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; bool skipCookie = false; const char *domain = NULL; int32_t domainLen = 0; while (fieldCount < 5 && (tabPos = (const char*)memchr(currentPos, '\t', lineEndPos - currentPos)) != NULL) { switch (fieldCount) { case 0: // domain domain = currentPos; domainLen = tabPos - currentPos; break; case 1: // flag if (memcmp(currentPos, "TRUE", 4) == 0) { // allow subdomain 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 if (tmpUrl.getHostLen() != domainLen || strncasecmp(domain, tmpUrl.getHost(), domainLen) != 0) { // non-matching domain - ignore cookie skipCookie = true; break; } } break; case 2: { // path const char *path = currentPos; int32_t pathLen = tabPos - currentPos; if (strncasecmp(path, tmpUrl.getPath(), pathLen) == 0) { if (tmpUrl.getPathLen() != pathLen) { if (path[pathLen - 1] != '/' && tmpUrl.getPath()[tmpUrl.getPathLen() - 1] != '/') { // non-matching path - ignore cookie skipCookie = true; break; } } } else { // non-matching path - ignore cookie skipCookie = true; break; } } break; case 3: // secure break; case 4: // expiration break; } currentPos = tabPos + 1; ++fieldCount; } if (!skipCookie) { tmpSb.safeMemcpy(currentPos, lineEndPos - currentPos); tmpSb.pushChar(';'); } lineStartPos = lineEndPos + 1; } // we don't need to care about the last line (we always end on \n) if (tmpSb.length() > 0) { sb->safeStrcpy("Cookie: "); sb->safeMemcpy(&tmpSb); sb->safeStrcpy("\r\n"); } return true; }