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 + -
显示快捷键?