CookieMap* CookieManager::findOrCreateCookieMap(CookieMap* protocolMap, const String& domain, bool findOnly) { // Explode the domain with the '.' delimiter Vector<String> delimitedHost; domain.split(".", delimitedHost); CookieMap* curMap = protocolMap; size_t hostSize = delimitedHost.size(); CookieLog("CookieManager - looking at protocol map %s \n", protocolMap->getName().utf8().data()); // Find & create necessary CookieMaps by traversing down the domain tree // Each CookieMap represent a subsection of the domain, delimited by "." int i = hostSize - 1; while (i >= 0) { CookieLog("CookieManager - finding %s in currentmap\n", delimitedHost[i].utf8().data()); CookieMap* nextMap = curMap->getSubdomainMap(delimitedHost[i]); if (!nextMap) { CookieLog("CookieManager - cannot find map\n"); if (findOnly) return 0; CookieLog("CookieManager - creating %s in currentmap %s\n", delimitedHost[i].utf8().data(), curMap->getName().utf8().data()); nextMap = new CookieMap(delimitedHost[i]); CookieLog("CookieManager - adding subdomain to map\n"); curMap->addSubdomainMap(delimitedHost[i], nextMap); } curMap = nextMap; i--; } return curMap; }
void CookieManager::checkAndTreatCookie(ParsedCookie* cookie) { ASSERT(cookie->domain().length()); CookieMap* curMap = m_managerMap.get(cookie->domain()); // Check for cookie to remove in case it is not a session cookie and it has expired. if (cookie->hasExpired()) { // The cookie has expired so check we have a valid HashMap so try delete it. if (curMap) { // Check if we have a cookie to remove and update information accordingly. ParsedCookie* prevCookie = curMap->takePrevious(cookie); if (prevCookie) { cookieBackingStore().remove(cookie); removedCookie(); delete cookie; } } } else { if (!curMap) { curMap = new CookieMap(); m_managerMap.add(cookie->domain(), curMap); addCookieToMap(curMap, cookie); } else { // Check if there is a previous cookie. ParsedCookie* prevCookie = curMap->takePrevious(cookie); if (prevCookie) { update(curMap, prevCookie, cookie); delete prevCookie; } else addCookieToMap(curMap, cookie); } } }
//--------------------------------------------------------- void CookieJar::loadCookies() { // set all cookies from the cookie map CookieMap map = QSettings().value("cookies-" + serviceName, CookieMap()).toMap(); // we need to convert qvariants to qbytearrays and separate them with // a '\n' so that we easily join each byte array into a big array that // the base class can use to restore the streaming service cookies. QList<QVariant> variantValues = map.values(); QList<QByteArray> values; QByteArray array; foreach(QVariant value, variantValues){ array += value.toByteArray(); array += "\n"; }
void CookieManager::getBackingStoreCookies() { Vector<ParsedCookie*> cookies = cookieBackingStore().getAllCookies(); for (size_t i = 0; i < cookies.size(); ++i) { ParsedCookie* newCookie = cookies[i]; if (newCookie->hasExpired()) { cookieBackingStore().remove(newCookie); delete newCookie; } else { CookieMap* curMap = m_managerMap.get(newCookie->domain()); if (!curMap) { curMap = new CookieMap(); m_managerMap.add(newCookie->domain(), curMap); } // Use the straightforward add curMap->add(newCookie); m_count++; } } }
CookieMap* CookieManager::findOrCreateCookieMap(CookieMap* protocolMap, const ParsedCookie& candidateCookie) { // Explode the domain with the '.' delimiter Vector<String> delimitedHost; // If the domain is an IP address, don't split it. if (candidateCookie.domainIsIPAddress()) delimitedHost.append(candidateCookie.domain()); else candidateCookie.domain().split(".", delimitedHost); CookieMap* curMap = protocolMap; size_t hostSize = delimitedHost.size(); CookieLog("CookieManager - looking at protocol map %s \n", protocolMap->getName().utf8().data()); // Find & create necessary CookieMaps by traversing down the domain tree // Each CookieMap represent a subsection of the domain, delimited by "." int i = hostSize - 1; while (i >= 0) { CookieLog("CookieManager - finding %s in currentmap\n", delimitedHost[i].utf8().data()); CookieMap* nextMap = curMap->getSubdomainMap(delimitedHost[i]); if (!nextMap) { CookieLog("CookieManager - cannot find map\n"); if (candidateCookie.hasExpired()) return 0; CookieLog("CookieManager - creating %s in currentmap %s\n", delimitedHost[i].utf8().data(), curMap->getName().utf8().data()); nextMap = new CookieMap(delimitedHost[i]); CookieLog("CookieManager - adding subdomain to map\n"); curMap->addSubdomainMap(delimitedHost[i], nextMap); } curMap = nextMap; i--; } return curMap; }
void CookieManager::checkAndTreatCookie(ParsedCookie* candidateCookie, BackingStoreRemovalPolicy postToBackingStore, CookieFilter filter) { CookieLog("CookieManager - checkAndTreatCookie - processing url with domain - %s & protocol %s\n", candidateCookie->domain().utf8().data(), candidateCookie->protocol().utf8().data()); // Delete invalid cookies: // 1) A cookie which is not from http shouldn't have a httpOnly property. // 2) Cookies coming from schemes that we do not support and the special flag isn't on if ((filter == NoHttpOnlyCookie && candidateCookie->isHttpOnly()) || (shouldIgnoreScheme(candidateCookie->protocol()) && !m_shouldDumpAllCookies)) { delete candidateCookie; return; } const bool ignoreDomain = (candidateCookie->protocol() == "file" || candidateCookie->protocol() == "local"); // Determine which protocol tree to add the cookie to. Create one if necessary. CookieMap* curMap = 0; if (m_managerMap.contains(candidateCookie->protocol())) curMap = m_managerMap.get(candidateCookie->protocol()); else { // Check if it is a secure version, if it is, link it to the non-secure version // Link curMap to the new protocol as well as the old one if it doesn't exist if (candidateCookie->protocol() == "https") { curMap = m_managerMap.get("http"); if (!curMap) { curMap = new CookieMap("http"); m_managerMap.add("http", curMap); } } else if (candidateCookie->protocol() == "wss") { curMap = m_managerMap.get("ws"); if (!curMap) { curMap = new CookieMap("ws"); m_managerMap.add("ws", curMap); } } else curMap = new CookieMap(candidateCookie->protocol()); CookieLog("CookieManager - adding protocol cookiemap - %s\n", curMap->getName().utf8().data()); m_managerMap.add(candidateCookie->protocol(), curMap); } // If protocol support domain, we have to traverse the domain tree to find the right // cookieMap to handle with if (!ignoreDomain) curMap = findOrCreateCookieMap(curMap, *candidateCookie); // Now that we have the proper map for this cookie, we can modify it // If cookie does not exist and has expired, delete it // If cookie exists and it has expired, so we must remove it from the map, if not update it // If cookie expired and came from the BackingStore (therefore does not exist), we have to remove from database // If cookie does not exist & it's valid, add it to the current map if (candidateCookie->hasExpired() || candidateCookie->isForceExpired()) { // Special case for getBackingStoreCookies() to catch expired cookies if (postToBackingStore == BackingStoreCookieEntry) m_cookieBackingStore->remove(candidateCookie); else if (curMap) { // RemoveCookie will return 0 if the cookie doesn't exist. ParsedCookie* expired = curMap->removeCookie(candidateCookie, filter); // Cookie is useless, Remove the cookie from the backingstore if it exists. // Backup check for BackingStoreCookieEntry incase someone incorrectly uses this enum. if (expired && postToBackingStore != BackingStoreCookieEntry && !expired->isSession()) { CookieLog("CookieManager - expired cookie is nonsession, deleting from db"); m_cookieBackingStore->remove(expired); } delete expired; } else delete candidateCookie; } else { ASSERT(curMap); addCookieToMap(curMap, candidateCookie, postToBackingStore, filter); } }
void CookieManager::getRawCookies(Vector<ParsedCookie*> &stackOfCookies, const KURL& requestURL, CookieFilter filter) const { if (!m_syncedWithDatabase && !m_privateMode) { LOG_ERROR("CookieManager is calling getRawCookies before database values are loaded."); return; } CookieLog("CookieManager - getRawCookies - processing url with domain - %s & protocol: %s & path: %s\n", requestURL.host().utf8().data(), requestURL.protocol().utf8().data(), requestURL.path().utf8().data()); const bool invalidScheme = shouldIgnoreScheme(requestURL.protocol()); const bool specialCaseForWebWorks = invalidScheme && m_shouldDumpAllCookies; const bool isConnectionSecure = requestURL.protocolIs("https") || requestURL.protocolIs("wss") || specialCaseForWebWorks; Vector<ParsedCookie*> cookieCandidates; Vector<CookieMap*> protocolsToSearch; // Special Case: If a server sets a "secure" cookie over a non-secure channel and tries to access the cookie // over a secure channel, it will not succeed because the secure protocol isn't mapped to the insecure protocol yet. // Set the map to the non-secure version, so it'll search the mapping for a secure cookie. CookieMap* targetMap = m_managerMap.get(requestURL.protocol()); if (!targetMap && isConnectionSecure) { CookieLog("CookieManager - special case: secure protocol are not linked yet."); if (requestURL.protocolIs("https")) targetMap = m_managerMap.get("http"); else if (requestURL.protocolIs("wss")) targetMap = m_managerMap.get("ws"); } // Decide which scheme tree we should look at. // Return on invalid schemes. cookies are currently disabled on file and local. // We only want to enable them for WebWorks that enabled a special flag. if (specialCaseForWebWorks) copyValuesToVector(m_managerMap, protocolsToSearch); else if (invalidScheme) return; else { protocolsToSearch.append(targetMap); // FIXME: this is a hack for webworks apps; RFC 6265 says "Cookies do not provide isolation by scheme" // so we should not be checking protocols at all. See PR 135595 if (m_shouldDumpAllCookies) { protocolsToSearch.append(m_managerMap.get("file")); protocolsToSearch.append(m_managerMap.get("local")); } } Vector<String> delimitedHost; // IP addresses are stored in a particular format (due to ipv6). Reduce the ip address so we can match // it with the one in memory. string canonicalIP = BlackBerry::Platform::getCanonicalIPFormat(requestURL.host().utf8().data()); if (!canonicalIP.empty()) delimitedHost.append(String(canonicalIP.c_str())); else requestURL.host().lower().split(".", true, delimitedHost); // Go through all the protocol trees that we need to search for // and get all cookies that are valid for this domain for (size_t k = 0; k < protocolsToSearch.size(); k++) { CookieMap* currentMap = protocolsToSearch[k]; // if no cookies exist for this protocol, break right away if (!currentMap) continue; CookieLog("CookieManager - looking at protocol map %s \n", currentMap->getName().utf8().data()); // Special case for local and files - because WebApps expect to get ALL cookies from the backing-store on local protocol if (specialCaseForWebWorks) { CookieLog("CookieManager - special case find in protocol map - %s\n", currentMap->getName().utf8().data()); currentMap->getAllChildCookies(&cookieCandidates); } else { // Get cookies from the null domain map currentMap->getAllCookies(&cookieCandidates); // Get cookies from the valid domain maps int i = delimitedHost.size() - 1; while (i >= 0) { CookieLog("CookieManager - finding %s in currentmap\n", delimitedHost[i].utf8().data()); currentMap = currentMap->getSubdomainMap(delimitedHost[i]); // if this subdomain/domain does not exist in our mapping then we simply exit if (!currentMap) { CookieLog("CookieManager - cannot find next map exiting the while loop.\n"); break; } CookieLog("CookieManager - found the map, grabbing cookies from this map\n"); currentMap->getAllCookies(&cookieCandidates); i--; } } } CookieLog("CookieManager - there are %d cookies in candidate\n", cookieCandidates.size()); for (size_t i = 0; i < cookieCandidates.size(); ++i) { ParsedCookie* cookie = cookieCandidates[i]; // According to the path-matches rules in RFC6265, section 5.1.4, // we should add a '/' at the end of cookie-path for comparison if the cookie-path is not end with '/'. String path = cookie->path(); CookieLog("CookieManager - comparing cookie path %s (len %d) to request path %s (len %d)", path.utf8().data(), path.length(), requestURL.path().utf8().data(), path.length()); if (!equalIgnoringCase(path, requestURL.path()) && !path.endsWith("/", false)) path = path + "/"; // Only secure connections have access to secure cookies. Unless specialCaseForWebWorks is true. // Get the cookies filtering out HttpOnly cookies if requested. if (requestURL.path().startsWith(path, false) && (isConnectionSecure || !cookie->isSecure()) && (filter == WithHttpOnlyCookies || !cookie->isHttpOnly())) { CookieLog("CookieManager - cookie chosen - %s\n", cookie->toString().utf8().data()); cookie->setLastAccessed(currentTime()); stackOfCookies.append(cookie); } } std::stable_sort(stackOfCookies.begin(), stackOfCookies.end(), cookieSorter); }
void CookieManager::getRawCookies(Vector<ParsedCookie*> &stackOfCookies, const KURL& requestURL, CookieFilter filter) const { CookieLog("CookieManager - getRawCookies - processing url with domain - %s & protocol: %s & path: %s\n", requestURL.host().utf8().data(), requestURL.protocol().utf8().data(), requestURL.path().utf8().data()); bool specialCaseForLocal = (requestURL.protocolIs("local") || requestURL.protocolIs("file")) && m_shouldDumpAllCookies; bool isConnectionSecure = requestURL.protocolIs("https") || requestURL.protocolIs("wss") || specialCaseForLocal; Vector<ParsedCookie*> cookieCandidates; Vector<CookieMap*> protocolsToSearch; if (specialCaseForLocal) copyValuesToVector(m_managerMap, protocolsToSearch); else { protocolsToSearch.append(m_managerMap.get(requestURL.protocol())); // FIXME: this is a hack for webworks apps; RFC 6265 says "Cookies do not provide isolation by scheme" // so we should not be checking protocols at all. See PR 135595 if (m_shouldDumpAllCookies) { protocolsToSearch.append(m_managerMap.get("file")); protocolsToSearch.append(m_managerMap.get("local")); } } Vector<String> delimitedHost; requestURL.host().lower().split(".", true, delimitedHost); // Go through all the protocol trees that we need to search for // and get all cookies that are valid for this domain for (size_t k = 0; k < protocolsToSearch.size(); k++) { CookieMap* currentMap = protocolsToSearch[k]; // if no cookies exist for this protocol, break right away if (!currentMap) continue; CookieLog("CookieManager - looking at protocol map %s \n", currentMap->getName().utf8().data()); // Special case for local and files - because WebApps expect to get ALL cookies from the backing-store on local protocol if (specialCaseForLocal) { CookieLog("CookieManager - special case find in protocol map - %s\n", currentMap->getName().utf8().data()); currentMap->getAllChildCookies(&cookieCandidates); } else { // Get cookies from the null domain map currentMap->getAllCookies(&cookieCandidates); // Get cookies from the valid domain maps int i = delimitedHost.size() - 1; while (i >= 0) { CookieLog("CookieManager - finding %s in currentmap\n", delimitedHost[i].utf8().data()); currentMap = currentMap->getSubdomainMap(delimitedHost[i]); // if this subdomain/domain does not exist in our mapping then we simply exit if (!currentMap) { CookieLog("CookieManager - cannot find next map exiting the while loop.\n"); break; } CookieLog("CookieManager - found the map, grabbing cookies from this map\n"); currentMap->getAllCookies(&cookieCandidates); i--; } } } CookieLog("CookieManager - there are %d cookies in candidate\n", cookieCandidates.size()); for (size_t i = 0; i < cookieCandidates.size(); ++i) { ParsedCookie* cookie = cookieCandidates[i]; // According to the path-matches rules in RFC6265, section 5.1.4, // we should add a '/' at the end of cookie-path for comparison if the cookie-path is not end with '/'. String path = cookie->path(); CookieLog("CookieManager - comparing cookie path %s (len %d) to request path %s (len %d)", path.utf8().data(), path.length(), requestURL.path().utf8().data(), path.length()); if (!equalIgnoringCase(path, requestURL.path()) && !path.endsWith("/", false)) path += "/"; // Only secure connections have access to secure cookies. Unless specialCaseForLocal is true // Get the cookies filtering out HttpOnly cookies if requested. if (requestURL.path().startsWith(path, false) && (isConnectionSecure || !cookie->isSecure()) && (filter == WithHttpOnlyCookies || !cookie->isHttpOnly())) { CookieLog("CookieManager - cookie chosen - %s\n", cookie->toString().utf8().data()); cookie->setLastAccessed(currentTime()); stackOfCookies.append(cookie); } } std::stable_sort(stackOfCookies.begin(), stackOfCookies.end(), cookieSorter); }
void CookieManager::checkAndTreatCookie(ParsedCookie* candidateCookie, BackingStoreRemovalPolicy postToBackingStore) { CookieLog("CookieManager - checkAndTreatCookie - processing url with domain - %s & protocol %s\n", candidateCookie->domain().utf8().data(), candidateCookie->protocol().utf8().data()); const bool ignoreDomain = shouldIgnoreDomain(candidateCookie->protocol()); // Determine which protocol tree to add the cookie to. Create one if necessary. CookieMap* curMap = 0; if (m_managerMap.contains(candidateCookie->protocol())) curMap = m_managerMap.get(candidateCookie->protocol()); else { // Check if it is a secure version, if it is, link it to the non-secure version // Link curMap to the new protocol as well as the old one if it doesn't exist if (candidateCookie->protocol() == "https") { curMap = m_managerMap.get("http"); if (!curMap) { curMap = new CookieMap("http"); m_managerMap.add("http", curMap); } } else if (candidateCookie->protocol() == "wss") { curMap = m_managerMap.get("ws"); if (!curMap) { curMap = new CookieMap("ws"); m_managerMap.add("ws", curMap); } } else curMap = new CookieMap(candidateCookie->protocol()); CookieLog("CookieManager - adding protocol cookiemap - %s\n", curMap->getName().utf8().data()); m_managerMap.add(candidateCookie->protocol(), curMap); } // If protocol support domain, we have to traverse the domain tree to find the right // cookieMap to handle with if (!ignoreDomain) curMap = findOrCreateCookieMap(curMap, candidateCookie->domain(), candidateCookie->hasExpired()); // Now that we have the proper map for this cookie, we can modify it // If cookie does not exist and has expired, delete it // If cookie exists and it has expired, so we must remove it from the map, if not update it // If cookie expired and came from the BackingStore (therefore does not exist), we have to remove from database // If cookie does not exist & it's valid, add it to the current map if (candidateCookie->hasExpired() || candidateCookie->isForceExpired()) { // Special case for getBackingStoreCookies() to catch expired cookies if (postToBackingStore == BackingStoreCookieEntry) m_cookieBackingStore->remove(candidateCookie); else if (curMap) { bool cookieAlreadyExists = curMap->existsCookie(candidateCookie); if (cookieAlreadyExists) { CookieLog("CookieManager - expired cookie exists in memory"); ParsedCookie* expired = curMap->removeCookie(candidateCookie); // Cookie is useless, Remove the cookie from the backingstore if it exists // Backup check for BackingStoreCookieEntry incase someone incorrectly uses this enum if (postToBackingStore != BackingStoreCookieEntry && !expired->isSession()) { CookieLog("CookieManager - expired cookie is nonsession, deleting from db"); m_cookieBackingStore->remove(expired); } delete expired; } } else delete candidateCookie; } else { ASSERT(curMap); bool cookieAlreadyExists = curMap->existsCookie(candidateCookie); if (cookieAlreadyExists) update(curMap, candidateCookie, postToBackingStore); else addCookieToMap(curMap, candidateCookie, postToBackingStore); } }