// // This function hands a KHttpCookie object over to the cookie jar. // // On return cookiePtr is set to 0. // void KCookieJar::addCookie(KHttpCookiePtr &cookiePtr) { QStringList domains; KHttpCookieList *cookieList = 0L; // We always need to do this to make sure that the // that cookies of type hostname == cookie-domainname // are properly removed and/or updated as necessary! extractDomains( cookiePtr->host(), domains ); for ( QStringList::ConstIterator it = domains.begin(); (it != domains.end() && !cookieList); ++it ) { QString key = (*it).isNull() ? L1("") : (*it); KHttpCookieList *list= m_cookieDomains[key]; if ( !list ) continue; removeDuplicateFromList(list, cookiePtr, false, true); } QString domain = stripDomain( cookiePtr ); QString key = domain.isNull() ? L1("") : domain; cookieList = m_cookieDomains[ key ]; if (!cookieList) { // Make a new cookie list cookieList = new KHttpCookieList(); cookieList->setAutoDelete(true); // All cookies whose domain is not already // known to us should be added with KCookieDunno. // KCookieDunno means that we use the global policy. cookieList->setAdvice( KCookieDunno ); m_cookieDomains.insert( domain, cookieList); // Update the list of domains m_domainList.append(domain); } // Add the cookie to the cookie list // The cookie list is sorted 'longest path first' if (!cookiePtr->isExpired(time(0))) { #ifdef MAX_COOKIE_LIMIT if (cookieList->count() >= MAX_COOKIES_PER_HOST) makeRoom(cookieList, cookiePtr); // Delete a cookie #endif cookieList->inSort( cookiePtr ); m_cookiesChanged = true; } else { delete cookiePtr; } cookiePtr = 0; }
bool KCookieServer::cookieMatches(KHttpCookiePtr c, QString domain, QString fqdn, QString path, QString name) { if(c) { bool hasDomain = !domain.isEmpty(); return ((hasDomain && c->domain() == domain) || fqdn == c->host()) && (c->path() == path) && (c->name() == name) && (!c->isExpired(time(0))); } return false; }
QString KCookieJar::stripDomain( KHttpCookiePtr cookiePtr) { QString domain; // We file the cookie under this domain. if (cookiePtr->domain().isEmpty()) stripDomain( cookiePtr->host(), domain); else stripDomain (cookiePtr->domain(), domain); return domain; }
// // This function sets the advice for all cookies originating from // the same domain as _cookie // void KCookieJar::setDomainAdvice(KHttpCookiePtr cookiePtr, KCookieAdvice _advice) { QString domain; stripDomain(cookiePtr->host(), domain); // We file the cookie under this domain. setDomainAdvice(domain, _advice); }
// // This function advices whether a single KHttpCookie object should // be added to the cookie jar. // KCookieAdvice KCookieJar::cookieAdvice(KHttpCookiePtr cookiePtr) { if (m_rejectCrossDomainCookies && cookiePtr->isCrossDomain()) return KCookieReject; QStringList domains; extractDomains(cookiePtr->host(), domains); // If the cookie specifies a domain, check whether it is valid. Otherwise, // accept the cookie anyways but remove the domain="" value to prevent // cross-site cookie injection. if (!cookiePtr->domain().isEmpty()) { if (!domains.contains(cookiePtr->domain()) && !cookiePtr->domain().endsWith("."+cookiePtr->host())) cookiePtr->fixDomain(QString::null); } if (m_autoAcceptSessionCookies && (cookiePtr->expireDate() == 0 || m_ignoreCookieExpirationDate)) return KCookieAccept; KCookieAdvice advice = KCookieDunno; bool isFQDN = true; // First is FQDN QStringList::Iterator it = domains.begin(); // Start with FQDN which first in the list. while( (advice == KCookieDunno) && (it != domains.end())) { QString domain = *it; // Check if a policy for the FQDN/domain is set. if ( domain[0] == '.' || isFQDN ) { isFQDN = false; KHttpCookieList *cookieList = m_cookieDomains[domain]; if (cookieList) advice = cookieList->getAdvice(); } domains.remove(it); it = domains.begin(); // Continue from begin of remaining list } if (advice == KCookieDunno) advice = m_globalAdvice; return advice; }
void KCookieServer::checkCookies(KHttpCookieList *cookieList) { KHttpCookieList *list; if(cookieList) list = cookieList; else list = mPendingCookies; KHttpCookiePtr cookie = list->first(); while(cookie) { kdDebug(7104) << "checkCookies: Asking cookie advice for " << cookie->host() << endl; KCookieAdvice advice = mCookieJar->cookieAdvice(cookie); switch(advice) { case KCookieAccept: list->take(); mCookieJar->addCookie(cookie); cookie = list->current(); break; case KCookieReject: list->take(); delete cookie; cookie = list->current(); break; default: cookie = list->next(); break; } } if(cookieList || list->isEmpty()) return; KHttpCookiePtr currentCookie = mPendingCookies->first(); KHttpCookieList currentList; currentList.append(currentCookie); QString currentHost = currentCookie->host(); cookie = mPendingCookies->next(); while(cookie) { if(cookie->host() == currentHost) { currentList.append(cookie); } cookie = mPendingCookies->next(); } KCookieWin *kw = new KCookieWin(0L, currentList, mCookieJar->preferredDefaultPolicy(), mCookieJar->showCookieDetails()); KCookieAdvice userAdvice = kw->advice(mCookieJar, currentCookie); delete kw; // Save the cookie config if it has changed mCookieJar->saveConfig(mConfig); // Apply the user's choice to all cookies that are currently // queued for this host. cookie = mPendingCookies->first(); while(cookie) { if(cookie->host() == currentHost) { switch(userAdvice) { case KCookieAccept: mPendingCookies->take(); mCookieJar->addCookie(cookie); cookie = mPendingCookies->current(); break; case KCookieReject: mPendingCookies->take(); delete cookie; cookie = mPendingCookies->current(); break; default: qWarning(__FILE__ ":%d Problem!", __LINE__); cookie = mPendingCookies->next(); break; } } else { cookie = mPendingCookies->next(); } } // Check if we can handle any request for(CookieRequest *request = mRequestList->first(); request;) { if(!cookiesPending(request->url)) { QCString replyType; QByteArray replyData; QString res = mCookieJar->findCookies(request->url, request->DOM, request->windowId); QDataStream stream2(replyData, IO_WriteOnly); stream2 << res; replyType = "QString"; request->client->endTransaction(request->transaction, replyType, replyData); CookieRequest *tmp = request; request = mRequestList->next(); mRequestList->removeRef(tmp); delete tmp; } else { request = mRequestList->next(); } } if(mCookieJar->changed()) saveCookieJar(); }
// // Looks for cookies in the cookie jar which are appropriate for _url. // Returned is a string containing all appropriate cookies in a format // which can be added to a HTTP-header without any additional processing. // QString KCookieJar::findCookies(const QString &_url, bool useDOMFormat, long windowId, KHttpCookieList *pendingCookies) { QString cookieStr; QStringList domains; QString fqdn; QString path; KHttpCookiePtr cookie; KCookieAdvice advice = m_globalAdvice; if (!parseURL(_url, fqdn, path)) return cookieStr; bool secureRequest = (_url.find( L1("https://"), 0, false) == 0 || _url.find( L1("webdavs://"), 0, false) == 0); // kdDebug(7104) << "findCookies: URL= " << _url << ", secure = " << secureRequest << endl; extractDomains(fqdn, domains); KHttpCookieList allCookies; for(QStringList::ConstIterator it = domains.begin(); true; ++it) { KHttpCookieList *cookieList; if (it == domains.end()) { cookieList = pendingCookies; // Add pending cookies pendingCookies = 0; if (!cookieList) break; } else { QString key = (*it).isNull() ? L1("") : (*it); cookieList = m_cookieDomains[key]; if (!cookieList) continue; // No cookies for this domain } if (cookieList->getAdvice() != KCookieDunno) advice = cookieList->getAdvice(); for ( cookie=cookieList->first(); cookie != 0; cookie=cookieList->next() ) { // If the we are setup to automatically accept all session cookies and to // treat all cookies as session cookies or the current cookie is a session // cookie, then send the cookie back regardless of either policy. if (advice == KCookieReject && !(m_autoAcceptSessionCookies && (m_ignoreCookieExpirationDate || cookie->expireDate() == 0))) continue; if (!cookie->match(fqdn, domains, path)) continue; if( cookie->isSecure() && !secureRequest ) continue; if( cookie->isHttpOnly() && useDOMFormat ) continue; // Do not send expired cookies. if ( cookie->isExpired (time(0)) ) { // Note there is no need to actually delete the cookie here // since the cookieserver will invoke ::saveCookieJar because // of the state change below. This will then do the job of // deleting the cookie for us. m_cookiesChanged = true; continue; } if (windowId && (cookie->windowIds().find(windowId) == cookie->windowIds().end())) { cookie->windowIds().append(windowId); } if (it == domains.end()) // Only needed when processing pending cookies removeDuplicateFromList(&allCookies, cookie); allCookies.append(cookie); } if (it == domains.end()) break; // Finished. } int cookieCount = 0; int protVersion=0; for ( cookie=allCookies.first(); cookie != 0; cookie=allCookies.next() ) { if (cookie->protocolVersion() > protVersion) protVersion = cookie->protocolVersion(); } for ( cookie=allCookies.first(); cookie != 0; cookie=allCookies.next() ) { if (useDOMFormat) { if (cookieCount > 0) cookieStr += L1("; "); cookieStr += cookie->cookieStr(true); } else { if (cookieCount == 0) { cookieStr += L1("Cookie: "); if (protVersion > 0) { QString version; version.sprintf("$Version=%d; ", protVersion); // Without quotes cookieStr += version; } } else { cookieStr += L1("; "); } cookieStr += cookie->cookieStr(false); } cookieCount++; } return cookieStr; }