kcookiejar.cpp
来自「konqueror3 embedded版本, KDE环境下的当家浏览器的嵌入式版」· C++ 代码 · 共 1,549 行 · 第 1/3 页
CPP
1,549 行
// End of Name Value = QString::fromLatin1(header); Value.truncate(s - header); return (s); } } Value = QString::fromLatin1(header); // *s == '\"'; if (keepQuotes) Value.truncate( ++s - header ); else Value.truncate( s++ - header ); // Skip any remaining garbage for(;; s++) { if ((*s=='\0') || (*s==';') || (*s=='\n')) break; } } else { // Parse 'my_value' part (unquoted value) header = s; while ((*s != '\0') && (*s != ';') && (*s != '\n')) s++; // End of Name Value = QString::fromLatin1(header); Value.truncate( s - header ); Value = Value.stripWhiteSpace(); } return (s);}void KCookieJar::stripDomain(const QString &_fqdn, QString &_domain){ QStringList domains; extractDomains(_fqdn, domains); if (domains.count() > 3) _domain = domains[3]; else _domain = domains[0];}QString KCookieJar::stripDomain( KHttpCookiePtr cookiePtr){ QString domain; // We file the cookie under this domain. if (cookiePtr->domain().isEmpty()) stripDomain( cookiePtr->host(), domain); else domain = cookiePtr->domain(); return domain;}bool KCookieJar::parseURL(const QString &_url, QString &_fqdn, QString &_path){ KURL kurl(_url); if (!kurl.isValid()) return false; _fqdn = kurl.host().lower(); if (kurl.port()) { if (((kurl.protocol() == L1("http")) && (kurl.port() != 80)) || ((kurl.protocol() == L1("https")) && (kurl.port() != 443))) { _fqdn = L1("%1:%2").arg(kurl.port()).arg(_fqdn); } } // Cookie spoofing protection. Since there is no way a path separator // or escape encoded character is allowed in the hostname according // to RFC 2396, reject attempts to include such things there! if(_fqdn.find('/') > -1 || _fqdn.find('%') > -1) { return false; // deny everything!! } _path = kurl.path(); if (_path.isEmpty()) _path = L1("/"); QRegExp exp(L1("[\\\\/]\\.\\.[\\\\/]")); // Weird path, cookie stealing attempt? if (exp.search(_path) != -1) return false; // Deny everything!! return true;}void KCookieJar::extractDomains(const QString &_fqdn, QStringList &_domains){ // Return numeric IPv6 addresses as is... if (_fqdn[0] == '[') { _domains.append( _fqdn ); return; } // Return numeric IPv4 addresses as is... if ((_fqdn[0] >= '0') && (_fqdn[0] <= '9')) { bool allNumeric = true; for(int i = _fqdn.length(); i--;) { if (!strchr("0123456789:.", _fqdn[i].latin1())) { allNumeric = false; break; } } if (allNumeric) { _domains.append( _fqdn ); return; } } QStringList partList = QStringList::split('.', _fqdn, false); if (partList.count()) partList.remove(partList.begin()); // Remove hostname while(partList.count()) { if (partList.count() == 1) break; // We only have a TLD left. if ((partList.count() == 2) && (m_twoLevelTLD[partList[1].lower()])) { // This domain uses two-level TLDs in the form xxxx.yy break; } if ((partList.count() == 2) && (partList[1].length() == 2)) { // If this is a TLD, we should stop. (e.g. co.uk) // We assume this is a TLD if it ends with .xx.yy or .x.yy if (partList[0].length() <= 2) break; // This is a TLD. // Catch some TLDs that we miss with the previous check // e.g. com.au, org.uk, mil.co QCString t = partList[0].lower().utf8(); if ((t == "com") || (t == "net") || (t == "org") || (t == "gov") || (t == "edu") || (t == "mil") || (t == "int")) break; } QString domain = partList.join(L1(".")); _domains.append(domain); _domains.append('.' + domain); partList.remove(partList.begin()); // Remove part } // Always add the FQDN at the start of the list for // hostname == cookie-domainname checks! _domains.prepend( '.' + _fqdn ); _domains.prepend( _fqdn );}//// This function parses cookie_headers and returns a linked list of// KHttpCookie objects for all cookies found in cookie_headers.// If no cookies could be found 0 is returned.//// cookie_headers should be a concatenation of all lines of a HTTP-header// which start with "Set-Cookie". The lines should be separated by '\n's.//KHttpCookieList KCookieJar::makeCookies(const QString &_url, const QCString &cookie_headers, long windowId){ KHttpCookieList cookieList; KHttpCookieList cookieList2; KHttpCookiePtr lastCookie = 0; const char *cookieStr = cookie_headers.data(); QString Name; QString Value; QString fqdn; QString path; bool crossDomain = false; if (!parseURL(_url, fqdn, path)) { // Error parsing _url return KHttpCookieList(); } QString defaultPath; int i = path.findRev('/'); if (i > 0) defaultPath = path.left(i); // The hard stuff :) for(;;) { // check for "Set-Cookie" if (strncmp(cookieStr, "Cross-Domain\n", 13) == 0) { cookieStr += 13; crossDomain = true; } else if (strncasecmp(cookieStr, "Set-Cookie:", 11) == 0) { cookieStr = parseNameValue(cookieStr+11, Name, Value, true); // Host = FQDN // Default domain = "" // Default path according to rfc2109 KHttpCookie *cookie = new KHttpCookie(fqdn, L1(""), defaultPath, Name, Value); if (windowId) cookie->mWindowIds.append(windowId); cookie->mCrossDomain = crossDomain; // Insert cookie in chain cookieList.append(cookie); lastCookie = cookie; } else if (strncasecmp(cookieStr, "Set-Cookie2:", 12) == 0) { // Attempt to follow rfc2965 cookieStr = parseNameValue(cookieStr+12, Name, Value, true, true); // Host = FQDN // Default domain = "" // Default path according to rfc2965 KHttpCookie *cookie = new KHttpCookie(fqdn, L1(""), defaultPath, Name, Value); if (windowId) cookie->mWindowIds.append(windowId); cookie->mCrossDomain = crossDomain; // Insert cookie in chain cookieList2.append(cookie); lastCookie = cookie; } else { // This is not the start of a cookie header, skip till next line. while (*cookieStr && *cookieStr != '\n') cookieStr++; if (*cookieStr == '\n') cookieStr++; if (!*cookieStr) break; // End of cookie_headers else continue; // end of this header, continue with next. } while ((*cookieStr == ';') || (*cookieStr == ' ')) { cookieStr++; // Name-Value pair follows cookieStr = parseNameValue(cookieStr, Name, Value); QCString cName = Name.lower().latin1(); if (cName == "domain") { QString dom = Value.lower(); // RFC2965 3.2.2: If an explicitly specified value does not // start with a dot, the user agent supplies a leading dot if(dom.length() && dom[0] != '.') dom.prepend("."); // remove a trailing dot if(dom.length() > 2 && dom[dom.length()-1] == '.') dom = dom.left(dom.length()-1); if(dom.contains('.') > 1 || dom == ".local") lastCookie->mDomain = dom; } else if (cName == "max-age") { int max_age = Value.toInt(); if (max_age == 0) lastCookie->mExpireDate = 1; else lastCookie->mExpireDate = time(0)+max_age; } else if (cName == "expires") { // Parse brain-dead netscape cookie-format lastCookie->mExpireDate = KRFCDate::parseDate(Value); } else if (cName == "path") { if (Value.isEmpty()) lastCookie->mPath = QString::null; // Catch "" <> QString::null else lastCookie->mPath = KURL::decode_string(Value); lastCookie->mExplicitPath = true; } else if (cName == "version") { lastCookie->mProtocolVersion = Value.toInt(); } else if ((cName == "secure") || (cName.isEmpty() && Value.lower() == L1("secure"))) { lastCookie->mSecure = true; } else if ((cName == "httponly") || (cName.isEmpty() && Value.lower() == L1("httponly"))) { lastCookie->mHttpOnly = true; } } if (*cookieStr == '\0') break; // End of header // Skip ';' or '\n' cookieStr++; } // RFC2965 cookies come last so that they override netscape cookies. while( !cookieList2.isEmpty() && (lastCookie = cookieList2.take(0)) ) { removeDuplicateFromList(&cookieList, lastCookie, true); cookieList.append(lastCookie); } return cookieList;}/*** Parses cookie_domstr and returns a linked list of KHttpCookie objects.* cookie_domstr should be a semicolon-delimited list of "name=value"* pairs. Any whitespace before "name" or around '=' is discarded.* If no cookies are found, 0 is returned.*/KHttpCookieList KCookieJar::makeDOMCookies(const QString &_url, const QCString &cookie_domstring, long windowId){ // A lot copied from above KHttpCookieList cookieList; KHttpCookiePtr lastCookie = 0; const char *cookieStr = cookie_domstring.data(); QString Name; QString Value; QString fqdn; QString path; if (!parseURL(_url, fqdn, path)) { // Error parsing _url return KHttpCookieList(); } // This time it's easy while(*cookieStr) { cookieStr = parseNameValue(cookieStr, Name, Value); // Host = FQDN // Default domain = "" // Default path = "" KHttpCookie *cookie = new KHttpCookie(fqdn, QString::null, QString::null, Name, Value ); if (windowId) cookie->mWindowIds.append(windowId); cookieList.append(cookie); lastCookie = cookie; if (*cookieStr != '\0') cookieStr++; // Skip ';' or '\n' } return cookieList;}#ifdef MAX_COOKIE_LIMITstatic void makeRoom(KHttpCookieList *cookieList, KHttpCookiePtr &cookiePtr){ // Too much cookies: throw one away, try to be somewhat clever KHttpCookiePtr lastCookie = 0; for(KHttpCookiePtr cookie = cookieList->first(); cookie; cookie = cookieList->next()) { if (cookieList->compareItems(cookie, cookiePtr) < 0) break; lastCookie = cookie; } if (!lastCookie) lastCookie = cookieList->first(); cookieList->removeRef(lastCookie);}#endif//// 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;}//// This function advices whether a single KHttpCookie object should// be added to the cookie jar.//KCookieAdvice KCookieJar::cookieAdvice(KHttpCookiePtr cookiePtr){ QStringList domains; if (m_rejectCrossDomainCookies && cookiePtr->isCrossDomain()) return KCookieReject; if (m_autoAcceptSessionCookies && (cookiePtr->expireDate() == 0 || m_ignoreCookieExpirationDate)) return KCookieAccept; extractDomains(cookiePtr->host(), domains); // If the cookie specifies a domain, check whether it is valid and // correct otherwise. if (!cookiePtr->domain().isEmpty()) { bool valid = false; // This checks whether the cookie is valid based on // what ::extractDomains returns if (!valid) { if (domains.contains(cookiePtr->domain())) valid = true; } if (!valid) { // Maybe it points to a sub-domain if (cookiePtr->domain().endsWith("."+cookiePtr->host())) valid = true; } if (!valid) { cookiePtr->fixDomain(QString::null); } } 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();
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?