• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KIOSlave

kcookiejar.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE File Manager
00002 
00003    Copyright (C) 1998-2000 Waldo Bastian (bastian@kde.org)
00004    Copyright (C) 2000,2001 Dawit Alemayehu (adawit@kde.org)
00005 
00006    Permission is hereby granted, free of charge, to any person obtaining a copy
00007    of this software and associated documentation files (the "Software"), to deal
00008    in the Software without restriction, including without limitation the rights
00009    to use, copy, modify, merge, publish, distribute, and/or sell copies of the
00010    Software, and to permit persons to whom the Software is furnished to do so,
00011    subject to the following conditions:
00012 
00013    The above copyright notice and this permission notice shall be included in
00014    all copies or substantial portions of the Software.
00015 
00016    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00017    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00018    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
00019    AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
00020    ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00021    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00022 */
00023 //----------------------------------------------------------------------------
00024 //
00025 // KDE File Manager -- HTTP Cookies
00026 
00027 //
00028 // The cookie protocol is a mess. RFC2109 is a joke since nobody seems to
00029 // use it. Apart from that it is badly written.
00030 // We try to implement Netscape Cookies and try to behave us according to
00031 // RFC2109 as much as we can.
00032 //
00033 // We assume cookies do not contain any spaces (Netscape spec.)
00034 // According to RFC2109 this is allowed though.
00035 //
00036 
00037 #include "kcookiejar.h"
00038 
00039 #include <config.h>
00040 #include <sys/types.h>
00041 #include <sys/stat.h>
00042 #ifdef HAVE_SYS_PARAM_H
00043 #include <sys/param.h>
00044 #endif
00045 #include <fcntl.h>
00046 #include <unistd.h>
00047 #include <stdio.h>
00048 #include <string.h>
00049 
00050 #ifdef USE_SOLARIS
00051 #include <strings.h>
00052 #endif
00053 
00054 #include <stdlib.h>
00055 
00056 //#include <netinet/in.h>
00057 //#include <arpa/inet.h>
00058 
00059 #include <QtCore/QString>
00060 #include <QtCore/QFile>
00061 #include <QtCore/QDir>
00062 #include <QtCore/QRegExp>
00063 #include <QtCore/QTextStream>
00064 
00065 #include <kurl.h>
00066 #include <kdatetime.h>
00067 #include <kconfig.h>
00068 #include <kconfiggroup.h>
00069 #include <ksavefile.h>
00070 #include <kdebug.h>
00071 
00072 #include <algorithm>
00073 
00074 // BR87227
00075 // Waba: Should the number of cookies be limited?
00076 // I am not convinced of the need of such limit
00077 // Mozilla seems to limit to 20 cookies / domain
00078 // but it is unclear which policy it uses to expire
00079 // cookies when it exceeds that amount
00080 #undef MAX_COOKIE_LIMIT
00081 
00082 #define MAX_COOKIES_PER_HOST 25
00083 #define READ_BUFFER_SIZE 8192
00084 #define IP_ADDRESS_EXPRESSION "(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
00085 
00086 // Note with respect to QString::fromLatin1( )
00087 // Cookies are stored as 8 bit data and passed to kio_http as
00088 // latin1 regardless of their actual encoding.
00089 
00090 // L1 is used to indicate latin1 constants
00091 #define L1(x) QLatin1String(x)
00092 
00093 QString KCookieJar::adviceToStr(KCookieAdvice _advice)
00094 {
00095     switch( _advice )
00096     {
00097     case KCookieAccept: return L1("Accept");
00098     case KCookieReject: return L1("Reject");
00099     case KCookieAsk: return L1("Ask");
00100     default: return L1("Dunno");
00101     }
00102 }
00103 
00104 KCookieAdvice KCookieJar::strToAdvice(const QString &_str)
00105 {
00106     if (_str.isEmpty())
00107         return KCookieDunno;
00108 
00109     QString advice = _str.toLower();
00110 
00111     if (advice == QLatin1String("accept"))
00112         return KCookieAccept;
00113     else if (advice == QLatin1String("reject"))
00114         return KCookieReject;
00115     else if (advice == QLatin1String("ask"))
00116         return KCookieAsk;
00117 
00118     return KCookieDunno;
00119 }
00120 
00121 // KHttpCookie
00123 
00124 //
00125 // Cookie constructor
00126 //
00127 KHttpCookie::KHttpCookie(const QString &_host,
00128                  const QString &_domain,
00129                  const QString &_path,
00130                  const QString &_name,
00131                  const QString &_value,
00132                  time_t _expireDate,
00133                  int _protocolVersion,
00134                  bool _secure,
00135                  bool _httpOnly,
00136                  bool _explicitPath) :
00137        mHost(_host),
00138        mDomain(_domain),
00139        mPath(_path.isEmpty() ? QString() : _path),
00140        mName(_name),
00141        mValue(_value),
00142        mExpireDate(_expireDate),
00143        mProtocolVersion(_protocolVersion),
00144        mSecure(_secure),
00145        mHttpOnly(_httpOnly),
00146        mExplicitPath(_explicitPath)
00147 {
00148 }
00149 
00150 //
00151 // Checks if a cookie has been expired
00152 //
00153 bool    KHttpCookie::isExpired(time_t currentDate) const
00154 {
00155     return (mExpireDate != 0) && (mExpireDate < currentDate);
00156 }
00157 
00158 //
00159 // Returns a string for a HTTP-header
00160 //
00161 QString KHttpCookie::cookieStr(bool useDOMFormat) const
00162 {
00163     QString result;
00164 
00165     if (useDOMFormat || (mProtocolVersion == 0))
00166     {
00167         if ( !mName.isEmpty() )
00168            result = mName + '=';
00169         result += mValue;
00170     }
00171     else
00172     {
00173         result = mName + '=' + mValue;
00174         if (mExplicitPath)
00175             result += L1("; $Path=\"") + mPath + L1("\"");
00176         if (!mDomain.isEmpty())
00177             result += L1("; $Domain=\"") + mDomain + L1("\"");
00178     }
00179     return result;
00180 }
00181 
00182 //
00183 // Returns whether this cookie should be send to this location.
00184 bool KHttpCookie::match(const QString &fqdn, const QStringList &domains,
00185                         const QString &path) const
00186 {
00187     // Cookie domain match check
00188     if (mDomain.isEmpty())
00189     {
00190        if (fqdn != mHost)
00191           return false;
00192     }
00193     else if (!domains.contains(mDomain))
00194     {
00195         if (mDomain[0] == '.')
00196             return false;
00197 
00198         // Maybe the domain needs an extra dot.
00199         QString domain = '.' + mDomain;
00200         if ( !domains.contains( domain ) )
00201           if ( fqdn != mDomain )
00202             return false;
00203     }
00204 
00205     // Cookie path match check
00206     if (mPath.isEmpty())
00207         return true;
00208 
00209     // According to the netscape spec both http://www.acme.com/foobar,
00210     // http://www.acme.com/foo.bar and http://www.acme.com/foo/bar
00211     // match http://www.acme.com/foo.
00212     // We only match http://www.acme.com/foo/bar
00213 
00214     if( path.startsWith(mPath) &&
00215         (
00216          (path.length() == mPath.length() ) ||  // Paths are exact match
00217           mPath.endsWith('/') ||            // mPath ended with a slash
00218          (path[mPath.length()] == '/')      // A slash follows
00219          ))
00220         return true; // Path of URL starts with cookie-path
00221 
00222     return false;
00223 }
00224 
00225 // KCookieJar
00227 
00228 //
00229 // Constructs a new cookie jar
00230 //
00231 // One jar should be enough for all cookies.
00232 //
00233 KCookieJar::KCookieJar()
00234 {
00235     m_globalAdvice = KCookieDunno;
00236     m_configChanged = false;
00237     m_cookiesChanged = false;
00238 
00239     KConfig cfg( "khtml/domain_info", KConfig::NoGlobals, "data" );
00240     KConfigGroup group( &cfg, QString() );
00241     QStringList countries = group.readEntry( "twoLevelTLD", QStringList() );
00242     foreach ( const QString& country, countries ) {
00243        m_twoLevelTLD.insert( country, 1 );
00244     }
00245 }
00246 
00247 //
00248 // Destructs the cookie jar
00249 //
00250 // Poor little cookies, they will all be eaten by the cookie monster!
00251 //
00252 KCookieJar::~KCookieJar()
00253 {
00254     qDeleteAll(m_cookieDomains);
00255     // Not much to do here
00256 }
00257 
00258 // cookiePtr is modified: the window ids of the existing cookie in the list are added to it
00259 static void removeDuplicateFromList(KHttpCookieList *list, KHttpCookie& cookiePtr, bool nameMatchOnly=false, bool updateWindowId=false)
00260 {
00261     QString domain1 = cookiePtr.domain();
00262     if (domain1.isEmpty())
00263        domain1 = cookiePtr.host();
00264 
00265     QMutableListIterator<KHttpCookie> cookieIterator(*list);
00266     while (cookieIterator.hasNext()) {
00267         const KHttpCookie& cookie = cookieIterator.next();
00268         QString domain2 = cookie.domain();
00269         if (domain2.isEmpty())
00270             domain2 = cookie.host();
00271 
00272         if (
00273             (cookiePtr.name() == cookie.name()) &&
00274             (
00275               nameMatchOnly ||
00276               ( (domain1 == domain2) && (cookiePtr.path() == cookie.path()) )
00277             )
00278           ) {
00279             if (updateWindowId) {
00280                 Q_FOREACH(long windowId, cookie.windowIds()) {
00281                     if (windowId && (!cookiePtr.windowIds().contains(windowId))) {
00282                         cookiePtr.windowIds().append(windowId);
00283                     }
00284                 }
00285             }
00286             cookieIterator.remove();
00287             break;
00288         }
00289     }
00290 }
00291 
00292 
00293 //
00294 // Looks for cookies in the cookie jar which are appropriate for _url.
00295 // Returned is a string containing all appropriate cookies in a format
00296 // which can be added to a HTTP-header without any additional processing.
00297 //
00298 QString KCookieJar::findCookies(const QString &_url, bool useDOMFormat, long windowId, KHttpCookieList *pendingCookies)
00299 {
00300     QString cookieStr;
00301     QStringList domains;
00302     QString fqdn;
00303     QString path;
00304     KCookieAdvice advice = m_globalAdvice;
00305 
00306     if (!parseUrl(_url, fqdn, path))
00307         return cookieStr;
00308 
00309     bool secureRequest = _url.startsWith( L1("https://"), Qt::CaseInsensitive ) ||
00310                          _url.startsWith( L1("webdavs://"), Qt::CaseInsensitive );
00311 
00312     extractDomains(fqdn, domains);
00313 
00314     KHttpCookieList allCookies;
00315 
00316     for(QStringList::ConstIterator it = domains.constBegin();
00317         true;
00318         ++it)
00319     {
00320        KHttpCookieList *cookieList;
00321        if (it == domains.constEnd())
00322        {
00323           cookieList = pendingCookies; // Add pending cookies
00324           pendingCookies = 0;
00325           if (!cookieList)
00326              break;
00327        }
00328        else
00329        {
00330           QString key = (*it).isNull() ? L1("") : (*it);
00331           cookieList = m_cookieDomains.value(key);
00332           if (!cookieList)
00333              continue; // No cookies for this domain
00334        }
00335 
00336        if (cookieList->getAdvice() != KCookieDunno)
00337           advice = cookieList->getAdvice();
00338 
00339         for (KHttpCookieList::iterator cookieIterator = cookieList->begin();
00340              cookieIterator != cookieList->end();
00341              ++cookieIterator ) {
00342             KHttpCookie& cookie = *cookieIterator;
00343             // If the we are setup to automatically accept all session cookies and to
00344             // treat all cookies as session cookies or the current cookie is a session
00345             // cookie, then send the cookie back regardless of domain policy.
00346             if (advice == KCookieReject &&
00347                 !(m_autoAcceptSessionCookies &&
00348                   (m_ignoreCookieExpirationDate || cookie.expireDate() == 0)))
00349                 continue;
00350 
00351           if (!cookie.match(fqdn, domains, path))
00352              continue;
00353 
00354           if( cookie.isSecure() && !secureRequest )
00355              continue;
00356 
00357           if( cookie.isHttpOnly() && useDOMFormat )
00358              continue;
00359 
00360           // Do not send expired cookies.
00361           if ( cookie.isExpired (time(0)) )
00362           {
00363              // Note there is no need to actually delete the cookie here
00364              // since the cookieserver will invoke ::saveCookieJar because
00365              // of the state change below. This will then do the job of
00366              // deleting the cookie for us.
00367              m_cookiesChanged = true;
00368              continue;
00369           }
00370 
00371           if (windowId && (cookie.windowIds().indexOf(windowId) == -1))
00372           {
00373              cookie.windowIds().append(windowId);
00374           }
00375 
00376           if (it == domains.constEnd()) // Only needed when processing pending cookies
00377              removeDuplicateFromList(&allCookies, cookie);
00378 
00379           allCookies.append(cookie);
00380        }
00381        if (it == domains.constEnd())
00382           break; // Finished.
00383     }
00384 
00385     int cookieCount = 0;
00386 
00387     int protVersion=0;
00388     Q_FOREACH(const KHttpCookie& cookie, allCookies) {
00389         if (cookie.protocolVersion() > protVersion)
00390             protVersion = cookie.protocolVersion();
00391     }
00392 
00393     Q_FOREACH(const KHttpCookie& cookie, allCookies) {
00394         if (useDOMFormat) {
00395             if (cookieCount > 0)
00396                 cookieStr += L1("; ");
00397             cookieStr += cookie.cookieStr(true);
00398         } else {
00399             if (cookieCount == 0) {
00400                 cookieStr += L1("Cookie: ");
00401                 if (protVersion > 0) {
00402                     QString version;
00403                     version.sprintf("$Version=%d; ", protVersion); // Without quotes
00404                     cookieStr += version;
00405                 }
00406             } else {
00407                 cookieStr += L1("; ");
00408             }
00409             cookieStr += cookie.cookieStr(false);
00410         }
00411         cookieCount++;
00412     }
00413 
00414     return cookieStr;
00415 }
00416 
00417 //
00418 // This function parses a string like 'my_name="my_value";' and returns
00419 // 'my_name' in Name and 'my_value' in Value.
00420 //
00421 // A pointer to the end of the parsed part is returned.
00422 // This pointer points either to:
00423 // '\0' - The end of the string has reached.
00424 // ';'  - Another my_name="my_value" pair follows
00425 // ','  - Another cookie follows
00426 // '\n' - Another header follows
00427 static const char * parseNameValue(const char *header,
00428                                   QString &Name,
00429                                   QString &Value,
00430                                   bool keepQuotes=false,
00431                                   bool rfcQuotes=false)
00432 {
00433     const char *s = header;
00434     // Parse 'my_name' part
00435     for(; (*s != '='); s++)
00436     {
00437         if ((*s=='\0') || (*s==';') || (*s=='\n'))
00438         {
00439             // No '=' sign -> use string as the value, name is empty
00440             // (behavior found in Mozilla and IE)
00441             Name = "";
00442             Value = QString::fromLatin1(header);
00443             Value.truncate( s - header );
00444             Value = Value.trimmed();
00445             return (s);
00446         }
00447     }
00448 
00449     Name = header;
00450     Name.truncate( s - header );
00451     Name = Name.trimmed();
00452 
00453     // *s == '='
00454     s++;
00455 
00456     // Skip any whitespace
00457     for(; (*s == ' ') || (*s == '\t'); s++)
00458     {
00459         if ((*s=='\0') || (*s==';') || (*s=='\n'))
00460         {
00461             // End of Name
00462             Value = "";
00463             return (s);
00464         }
00465     }
00466 
00467     if ((rfcQuotes || !keepQuotes) && (*s == '\"'))
00468     {
00469         // Parse '"my_value"' part (quoted value)
00470         if (keepQuotes)
00471            header = s++;
00472         else
00473            header = ++s; // skip "
00474         for(;(*s != '\"');s++)
00475         {
00476             if ((*s=='\0') || (*s=='\n'))
00477             {
00478                 // End of Name
00479                 Value = QString::fromLatin1(header);
00480                 Value.truncate(s - header);
00481                 return (s);
00482             }
00483         }
00484         Value = QString::fromLatin1(header);
00485         // *s == '\"';
00486         if (keepQuotes)
00487            Value.truncate( ++s - header );
00488         else
00489            Value.truncate( s++ - header );
00490 
00491         // Skip any remaining garbage
00492         for(;; s++)
00493         {
00494             if ((*s=='\0') || (*s==';') || (*s=='\n'))
00495                 break;
00496         }
00497     }
00498     else
00499     {
00500         // Parse 'my_value' part (unquoted value)
00501         header = s;
00502         while ((*s != '\0') && (*s != ';') && (*s != '\n'))
00503             s++;
00504         // End of Name
00505         Value = QString::fromLatin1(header);
00506         Value.truncate( s - header );
00507         Value = Value.trimmed();
00508     }
00509     return (s);
00510 
00511 }
00512 
00513 void KCookieJar::stripDomain(const QString &_fqdn, QString &_domain)
00514 {
00515    QStringList domains;
00516    extractDomains(_fqdn, domains);
00517    if (domains.count() > 3)
00518       _domain = domains[3];
00519    else if ( domains.count() > 0 )
00520       _domain = domains[0];
00521    else
00522       _domain = L1("");
00523 }
00524 
00525 QString KCookieJar::stripDomain(const KHttpCookie& cookie)
00526 {
00527     QString domain; // We file the cookie under this domain.
00528     if (cookie.domain().isEmpty())
00529        stripDomain( cookie.host(), domain);
00530     else
00531        stripDomain( cookie.domain(), domain);
00532     return domain;
00533 }
00534 
00535 bool KCookieJar::parseUrl(const QString &_url,
00536                           QString &_fqdn,
00537                           QString &_path)
00538 {
00539     KUrl kurl(_url);
00540     if (!kurl.isValid())
00541        return false;
00542 
00543     _fqdn = kurl.host().toLower();
00544     if (kurl.port() > 0)
00545     {
00546        if (((kurl.protocol() == L1("http")) && (kurl.port() != 80)) ||
00547            ((kurl.protocol() == L1("https")) && (kurl.port() != 443)))
00548        {
00549           // It's <port>:<host> so that the sorting works as expected
00550           _fqdn = QString::fromLatin1("%1:%2").arg(kurl.port()).arg(_fqdn);
00551        }
00552     }
00553 
00554     // Cookie spoofing protection.  Since there is no way a path separator
00555     // or escape encoded character is allowed in the hostname according
00556     // to RFC 2396, reject attempts to include such things there!
00557     if(_fqdn.contains('/') || _fqdn.contains('%'))
00558     {
00559         return false;  // deny everything!!
00560     }
00561 
00562     _path = kurl.path();
00563     if (_path.isEmpty())
00564        _path = L1("/");
00565 
00566     QRegExp exp(L1("[\\\\/]\\.\\.[\\\\/]"));
00567     // Weird path, cookie stealing attempt?
00568     if (exp.indexIn(_path) != -1)
00569        return false; // Deny everything!!
00570 
00571     return true;
00572 }
00573 
00574 void KCookieJar::extractDomains(const QString &_fqdn,
00575                                 QStringList &_domains) const
00576 {
00577     if (_fqdn.isEmpty()) // localhost...
00578         return;
00579 
00580     // Return numeric IPv6 addresses as is...
00581     if (_fqdn[0] == '[')
00582     {
00583        _domains.append( _fqdn );
00584        return;
00585     }
00586     // Return numeric IPv4 addresses as is...
00587     if ((_fqdn[0] >= '0') && (_fqdn[0] <= '9'))
00588     {
00589        if (_fqdn.indexOf(QRegExp(IP_ADDRESS_EXPRESSION)) > -1)
00590        {
00591           _domains.append( _fqdn );
00592           return;
00593        }
00594     }
00595 
00596     QStringList partList = _fqdn.split('.', QString::SkipEmptyParts);
00597 
00598     if (partList.count())
00599         partList.erase(partList.begin()); // Remove hostname
00600 
00601     while(partList.count())
00602     {
00603 
00604        if (partList.count() == 1)
00605          break; // We only have a TLD left.
00606 
00607        if ((partList.count() == 2) && (m_twoLevelTLD.value(partList[1].toLower(), 0) == 1))
00608        {
00609           // This domain uses two-level TLDs in the form xxxx.yy
00610           break;
00611        }
00612 
00613        if ((partList.count() == 2) && (partList[1].length() == 2))
00614        {
00615           // If this is a TLD, we should stop. (e.g. co.uk)
00616           // We assume this is a TLD if it ends with .xx.yy or .x.yy
00617           if (partList[0].length() <= 2)
00618              break; // This is a TLD.
00619 
00620           // Catch some TLDs that we miss with the previous check
00621           // e.g. com.au, org.uk, mil.co
00622           const QString t = partList[0].toLower();
00623           if ((t == "com") || (t == "net") || (t == "org") || (t == "gov") || (t == "edu") || (t == "mil") || (t == "int"))
00624               break;
00625        }
00626 
00627        QString domain = partList.join(L1("."));
00628        _domains.append(domain);
00629        _domains.append('.' + domain);
00630        partList.erase(partList.begin()); // Remove part
00631     }
00632 
00633     // Always add the FQDN at the start of the list for
00634     // hostname == cookie-domainname checks!
00635     _domains.prepend( '.' + _fqdn );
00636     _domains.prepend( _fqdn );
00637 }
00638 
00639 /*
00640    Changes dates in from the following format
00641 
00642       Wed Sep 12 07:00:00 2007 GMT
00643    to
00644       Wed Sep 12 2007 07:00:00 GMT
00645 
00646    to allow KDateTime::fromString to properly parse expiration date formats
00647    used in cookies by some servers such as amazon.com. See BR# 145244.
00648 */
00649 static QString fixupDateTime(const QString& date)
00650 {
00651   QStringList list = date.split(' ');
00652   const int index = list.indexOf(QRegExp("[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}"));
00653 
00654   if (index > -1 && (index+1) < list.count())
00655   {
00656     list.insert(index+1, list.takeAt(index));
00657     return list.join(" ");
00658   }
00659 
00660   return date;
00661 }
00662 
00663 //
00664 // This function parses cookie_headers and returns a linked list of
00665 // KHttpCookie objects for all cookies found in cookie_headers.
00666 // If no cookies could be found 0 is returned.
00667 //
00668 // cookie_headers should be a concatenation of all lines of a HTTP-header
00669 // which start with "Set-Cookie". The lines should be separated by '\n's.
00670 //
00671 KHttpCookieList KCookieJar::makeCookies(const QString &_url,
00672                                        const QByteArray &cookie_headers,
00673                                        long windowId)
00674 {
00675     KHttpCookieList cookieList;
00676     KHttpCookieList cookieList2;
00677     KHttpCookieList::iterator lastCookie = cookieList.end();
00678     const char *cookieStr = cookie_headers.data();
00679     QString Name;
00680     QString Value;
00681     QString fqdn;
00682     QString path;
00683     bool crossDomain = false;
00684 
00685     if (!parseUrl(_url, fqdn, path))
00686     {
00687         // Error parsing _url
00688         return KHttpCookieList();
00689     }
00690     QString defaultPath;
00691     int i = path.lastIndexOf('/');
00692     if (i > 0)
00693        defaultPath = path.left(i);
00694 
00695     //  The hard stuff :)
00696     for(;;)
00697     {
00698         // check for "Set-Cookie"
00699         if (strncmp(cookieStr, "Cross-Domain\n", 13) == 0)
00700         {
00701             cookieStr += 13;
00702             crossDomain = true;
00703         }
00704         else if (strncasecmp(cookieStr, "Set-Cookie:", 11) == 0)
00705         {
00706             cookieStr = parseNameValue(cookieStr+11, Name, Value, true);
00707 
00708             // Host = FQDN
00709             // Default domain = ""
00710             // Default path according to rfc2109
00711 
00712             KHttpCookie cookie(fqdn, L1(""), defaultPath, Name, Value);
00713             if (windowId)
00714                cookie.mWindowIds.append(windowId);
00715             cookie.mCrossDomain = crossDomain;
00716 
00717             // Insert cookie in chain
00718             cookieList.append(cookie);
00719             lastCookie = cookieList.end(); --lastCookie;
00720         }
00721         else if (strncasecmp(cookieStr, "Set-Cookie2:", 12) == 0)
00722         {
00723             // Attempt to follow rfc2965
00724             cookieStr = parseNameValue(cookieStr+12, Name, Value, true, true);
00725 
00726             // Host = FQDN
00727             // Default domain = ""
00728             // Default path according to rfc2965
00729 
00730             KHttpCookie cookie(fqdn, L1(""), defaultPath, Name, Value);
00731             if (windowId)
00732                cookie.mWindowIds.append(windowId);
00733             cookie.mCrossDomain = crossDomain;
00734 
00735             // Insert cookie in chain
00736             cookieList2.append(cookie);
00737             lastCookie = cookieList2.end(); --lastCookie;
00738         }
00739         else
00740         {
00741             // This is not the start of a cookie header, skip till next line.
00742             while (*cookieStr && *cookieStr != '\n')
00743                 cookieStr++;
00744 
00745             if (*cookieStr == '\n')
00746                 cookieStr++;
00747 
00748             if (!*cookieStr)
00749                 break; // End of cookie_headers
00750             else
00751                 continue; // end of this header, continue with next.
00752         }
00753 
00754         while ((*cookieStr == ';') || (*cookieStr == ' '))
00755         {
00756             cookieStr++;
00757 
00758             // Name-Value pair follows
00759             cookieStr = parseNameValue(cookieStr, Name, Value);
00760 
00761             QString cName = Name.toLower();
00762             if (cName == "domain")
00763             {
00764                 QString dom = Value.toLower();
00765                 // RFC2965 3.2.2: If an explicitly specified value does not
00766                 // start with a dot, the user agent supplies a leading dot
00767                 if(dom.length() && dom[0] != '.')
00768                     dom.prepend(".");
00769                 // remove a trailing dot
00770                 if(dom.length() > 2 && dom[dom.length()-1] == '.')
00771                     dom = dom.left(dom.length()-1);
00772 
00773                 if(dom.count('.') > 1 || dom == ".local")
00774                     lastCookie->mDomain = dom;
00775             }
00776             else if (cName == "max-age")
00777             {
00778                 int max_age = Value.toInt();
00779                 if (max_age == 0)
00780                     lastCookie->mExpireDate = 1;
00781                 else
00782                     lastCookie->mExpireDate = time(0)+max_age;
00783             }
00784             else if (cName == "expires")
00785             {
00786                 // Parse brain-dead netscape cookie-format
00787                 lastCookie->mExpireDate = KDateTime::fromString(Value, KDateTime::RFCDate).toTime_t();
00788 
00789                 // Workaround for servers that send the expiration date in
00790                 // 'Wed Sep 12 07:00:00 2007 GMT' format. See BR# 145244.
00791                 if (lastCookie->mExpireDate == -1)
00792                   lastCookie->mExpireDate = KDateTime::fromString(fixupDateTime(Value), KDateTime::RFCDate).toTime_t();
00793 
00794                 // We encode parse error/invalid as 0, but KDateTime likes -1, so convert
00795                 if (lastCookie->mExpireDate == -1)
00796                   lastCookie->mExpireDate = 0;
00797             }
00798             else if (cName == "path")
00799             {
00800                 if (Value.isEmpty())
00801                    lastCookie->mPath.clear(); // Catch "" <> QString()
00802                 else
00803                    lastCookie->mPath = QUrl::fromPercentEncoding(Value.toLatin1());
00804                 lastCookie->mExplicitPath = true;
00805             }
00806             else if (cName == "version")
00807             {
00808                 lastCookie->mProtocolVersion = Value.toInt();
00809             }
00810             else if ((cName == "secure") ||
00811                      (cName.isEmpty() && Value.toLower() == L1("secure")))
00812             {
00813                 lastCookie->mSecure = true;
00814             }
00815             else if ((cName == "httponly") ||
00816                      (cName.isEmpty() && Value.toLower() == L1("httponly")))
00817             {
00818                 lastCookie->mHttpOnly = true;
00819             }
00820         }
00821 
00822         if (*cookieStr == '\0')
00823             break; // End of header
00824 
00825         // Skip ';' or '\n'
00826         cookieStr++;
00827     }
00828 
00829     // RFC2965 cookies come last so that they override netscape cookies.
00830     while(!cookieList2.isEmpty()) {
00831         lastCookie = cookieList2.begin();
00832         removeDuplicateFromList(&cookieList, *lastCookie, true);
00833         cookieList.append(*lastCookie);
00834         cookieList2.removeFirst();
00835     }
00836 
00837     return cookieList;
00838 }
00839 
00846 KHttpCookieList KCookieJar::makeDOMCookies(const QString &_url,
00847                                            const QByteArray &cookie_domstring,
00848                                            long windowId)
00849 {
00850     // A lot copied from above
00851     KHttpCookieList cookieList;
00852 
00853     const char *cookieStr = cookie_domstring.data();
00854     QString fqdn;
00855     QString path;
00856 
00857     if (!parseUrl(_url, fqdn, path))
00858     {
00859         // Error parsing _url
00860         return KHttpCookieList();
00861     }
00862 
00863     QString Name;
00864     QString Value;
00865     //  This time it's easy
00866     while(*cookieStr)
00867     {
00868         cookieStr = parseNameValue(cookieStr, Name, Value);
00869 
00870         // Host = FQDN
00871         // Default domain = ""
00872         // Default path = ""
00873         KHttpCookie cookie(fqdn, QString(), QString(),
00874                            Name, Value );
00875         if (windowId)
00876             cookie.mWindowIds.append(windowId);
00877 
00878         cookieList.append(cookie);
00879 
00880         if (*cookieStr != '\0')
00881             cookieStr++;         // Skip ';' or '\n'
00882     }
00883 
00884     return cookieList;
00885 }
00886 
00887 // KHttpCookieList sorting
00889 
00890 // We want the longest path first
00891 static bool compareCookies(const KHttpCookie& item1, const KHttpCookie& item2)
00892 {
00893     return item1.path().length() > item2.path().length();
00894 }
00895 
00896 
00897 #ifdef MAX_COOKIE_LIMIT
00898 static void makeRoom(KHttpCookieList *cookieList, KHttpCookiePtr &cookiePtr)
00899 {
00900      // Too many cookies: throw one away, try to be somewhat clever
00901      KHttpCookiePtr lastCookie = 0;
00902      for(KHttpCookiePtr cookie = cookieList->first(); cookie; cookie = cookieList->next())
00903      {
00904          if (compareCookies(cookie, cookiePtr))
00905             break;
00906          lastCookie = cookie;
00907      }
00908      if (!lastCookie)
00909          lastCookie = cookieList->first();
00910      cookieList->removeRef(lastCookie);
00911 }
00912 #endif
00913 
00914 //
00915 // This function hands a KHttpCookie object over to the cookie jar.
00916 //
00917 void KCookieJar::addCookie(KHttpCookie &cookie)
00918 {
00919     QStringList domains;
00920     KHttpCookieList *cookieList = 0L;
00921 
00922     // We always need to do this to make sure that the
00923     // that cookies of type hostname == cookie-domainname
00924     // are properly removed and/or updated as necessary!
00925     extractDomains( cookie.host(), domains );
00926     for ( QStringList::ConstIterator it = domains.constBegin();
00927           (it != domains.constEnd() && !cookieList);
00928           ++it )
00929     {
00930         QString key = (*it).isNull() ? QString::fromLatin1("") : (*it);
00931         KHttpCookieList *list= m_cookieDomains.value(key);
00932         if ( !list ) continue;
00933 
00934         removeDuplicateFromList(list, cookie, false, true);
00935     }
00936 
00937     QString domain = stripDomain( cookie );
00938     QString key = domain.isNull() ? QString::fromLatin1("") : domain;
00939     cookieList = m_cookieDomains.value(key);
00940     if (!cookieList)
00941     {
00942         // Make a new cookie list
00943         cookieList = new KHttpCookieList();
00944 
00945         // All cookies whose domain is not already
00946         // known to us should be added with KCookieDunno.
00947         // KCookieDunno means that we use the global policy.
00948         cookieList->setAdvice( KCookieDunno );
00949 
00950         m_cookieDomains.insert( domain, cookieList);
00951 
00952         // Update the list of domains
00953         m_domainList.append(domain);
00954     }
00955 
00956     // Add the cookie to the cookie list
00957     // The cookie list is sorted 'longest path first'
00958     if (!cookie.isExpired(time(0)))
00959     {
00960 #ifdef MAX_COOKIE_LIMIT
00961         if (cookieList->count() >= MAX_COOKIES_PER_HOST)
00962            makeRoom(cookieList, cookie); // Delete a cookie
00963 #endif
00964         cookieList->push_back(cookie);
00965         // Use a stable sort so that unit tests are reliable.
00966         // In practice it doesn't matter though.
00967         qStableSort(cookieList->begin(), cookieList->end(), compareCookies);
00968 
00969         m_cookiesChanged = true;
00970     }
00971 }
00972 
00973 //
00974 // This function advices whether a single KHttpCookie object should
00975 // be added to the cookie jar.
00976 //
00977 KCookieAdvice KCookieJar::cookieAdvice(KHttpCookie& cookie)
00978 {
00979     if (m_rejectCrossDomainCookies && cookie.isCrossDomain())
00980        return KCookieReject;
00981 
00982     QStringList domains;
00983     extractDomains(cookie.host(), domains);
00984 
00985     // If the cookie specifies a domain, check whether it is valid. Otherwise,
00986     // accept the cookie anyways but removes the domain="" value to prevent
00987     // cross-site cookie injection.
00988     if (!cookie.domain().isEmpty())
00989     {
00990       if (!domains.contains(cookie.domain()) &&
00991           !cookie.domain().endsWith('.'+cookie.host()))
00992          cookie.fixDomain(QString());
00993     }
00994 
00995     if (m_autoAcceptSessionCookies && (cookie.expireDate() == 0 ||
00996         m_ignoreCookieExpirationDate))
00997        return KCookieAccept;
00998 
00999     KCookieAdvice advice = KCookieDunno;
01000     bool isFQDN = true; // First is FQDN
01001     QStringList::Iterator it = domains.begin(); // Start with FQDN which first in the list.
01002     while( (advice == KCookieDunno) && (it != domains.end()))
01003     {
01004        QString domain = *it;
01005        // Check if a policy for the FQDN/domain is set.
01006        if ( domain.startsWith('.') || isFQDN )
01007        {
01008           isFQDN = false;
01009           KHttpCookieList *cookieList = m_cookieDomains.value(domain);
01010           if (cookieList)
01011              advice = cookieList->getAdvice();
01012        }
01013        domains.erase(it);
01014        it = domains.begin(); // Continue from begin of remaining list
01015     }
01016 
01017     if (advice == KCookieDunno)
01018         advice = m_globalAdvice;
01019 
01020     return advice;
01021 }
01022 
01023 //
01024 // This function gets the advice for all cookies originating from
01025 // _domain.
01026 //
01027 KCookieAdvice KCookieJar::getDomainAdvice(const QString &_domain)
01028 {
01029     KHttpCookieList *cookieList = m_cookieDomains.value(_domain);
01030     KCookieAdvice advice;
01031 
01032     if (cookieList)
01033     {
01034         advice = cookieList->getAdvice();
01035     }
01036     else
01037     {
01038         advice = KCookieDunno;
01039     }
01040 
01041     return advice;
01042 }
01043 
01044 //
01045 // This function sets the advice for all cookies originating from
01046 // _domain.
01047 //
01048 void KCookieJar::setDomainAdvice(const QString &_domain, KCookieAdvice _advice)
01049 {
01050     QString domain(_domain);
01051     KHttpCookieList *cookieList = m_cookieDomains.value(domain);
01052 
01053     if (cookieList)
01054     {
01055         if (cookieList->getAdvice() != _advice)
01056         {
01057            m_configChanged = true;
01058            // domain is already known
01059            cookieList->setAdvice( _advice);
01060         }
01061 
01062         if ((cookieList->isEmpty()) &&
01063             (_advice == KCookieDunno))
01064         {
01065             // This deletes cookieList!
01066             delete m_cookieDomains.take(domain);
01067             m_domainList.removeAll(domain);
01068         }
01069     }
01070     else
01071     {
01072         // domain is not yet known
01073         if (_advice != KCookieDunno)
01074         {
01075             // We should create a domain entry
01076             m_configChanged = true;
01077             // Make a new cookie list
01078             cookieList = new KHttpCookieList();
01079             cookieList->setAdvice(_advice);
01080             m_cookieDomains.insert(domain, cookieList);
01081             // Update the list of domains
01082             m_domainList.append( domain);
01083         }
01084     }
01085 }
01086 
01087 //
01088 // This function sets the advice for all cookies originating from
01089 // the same domain as _cookie
01090 //
01091 void KCookieJar::setDomainAdvice(const KHttpCookie& cookie, KCookieAdvice _advice)
01092 {
01093     QString domain;
01094     stripDomain(cookie.host(), domain); // We file the cookie under this domain.
01095 
01096     setDomainAdvice(domain, _advice);
01097 }
01098 
01099 //
01100 // This function sets the global advice for cookies
01101 //
01102 void KCookieJar::setGlobalAdvice(KCookieAdvice _advice)
01103 {
01104     if (m_globalAdvice != _advice)
01105        m_configChanged = true;
01106     m_globalAdvice = _advice;
01107 }
01108 
01109 //
01110 // Get a list of all domains known to the cookie jar.
01111 //
01112 const QStringList& KCookieJar::getDomainList()
01113 {
01114     return m_domainList;
01115 }
01116 
01117 //
01118 // Get a list of all cookies in the cookie jar originating from _domain.
01119 //
01120 KHttpCookieList *KCookieJar::getCookieList(const QString & _domain,
01121                                            const QString & _fqdn )
01122 {
01123     QString domain;
01124 
01125     if (_domain.isEmpty())
01126         stripDomain( _fqdn, domain );
01127     else
01128         domain = _domain;
01129 
01130     return m_cookieDomains.value(domain);
01131 }
01132 
01133 //
01134 // Eat a cookie out of the jar.
01135 // cookieIterator should be one of the cookies returned by getCookieList()
01136 //
01137 void KCookieJar::eatCookie(KHttpCookieList::iterator cookieIterator)
01138 {
01139     const KHttpCookie& cookie = *cookieIterator;
01140     QString domain = stripDomain(cookie); // We file the cookie under this domain.
01141     KHttpCookieList *cookieList = m_cookieDomains.value(domain);
01142 
01143     if (cookieList) {
01144         // This deletes cookie!
01145         cookieList->erase(cookieIterator);
01146 
01147         if ((cookieList->isEmpty()) &&
01148             (cookieList->getAdvice() == KCookieDunno))
01149         {
01150             // This deletes cookieList!
01151             delete m_cookieDomains.take(domain);
01152 
01153             m_domainList.removeAll(domain);
01154         }
01155     }
01156 }
01157 
01158 void KCookieJar::eatCookiesForDomain(const QString &domain)
01159 {
01160    KHttpCookieList *cookieList = m_cookieDomains.value(domain);
01161    if (!cookieList || cookieList->isEmpty()) return;
01162 
01163    cookieList->clear();
01164    if (cookieList->getAdvice() == KCookieDunno)
01165    {
01166        // This deletes cookieList!
01167        delete m_cookieDomains.take(domain);
01168        m_domainList.removeAll(domain);
01169    }
01170    m_cookiesChanged = true;
01171 }
01172 
01173 void KCookieJar::eatSessionCookies( long windowId )
01174 {
01175     if (!windowId)
01176         return;
01177 
01178     QStringList::const_iterator it=m_domainList.constBegin();
01179     for ( ; it != m_domainList.constEnd(); ++it )
01180         eatSessionCookies( *it, windowId, false );
01181 }
01182 
01183 void KCookieJar::eatAllCookies()
01184 {
01185     Q_FOREACH(const QString& domain, m_domainList) {
01186         // This might remove domain from m_domainList!
01187         eatCookiesForDomain(domain);
01188     }
01189 }
01190 
01191 void KCookieJar::eatSessionCookies( const QString& fqdn, long windowId,
01192                                     bool isFQDN )
01193 {
01194     KHttpCookieList* cookieList;
01195     if ( !isFQDN )
01196         cookieList = m_cookieDomains.value(fqdn);
01197     else {
01198         QString domain;
01199         stripDomain( fqdn, domain );
01200         cookieList = m_cookieDomains.value(domain);
01201     }
01202 
01203     if (cookieList) {
01204         QMutableListIterator<KHttpCookie> cookieIterator(*cookieList);
01205         while (cookieIterator.hasNext()) {
01206             KHttpCookie& cookie = cookieIterator.next();
01207             if ((cookie.expireDate() != 0) && !m_ignoreCookieExpirationDate) {
01208                continue;
01209             }
01210 
01211             QList<long> &ids = cookie.windowIds();
01212 
01213 #ifndef NDEBUG
01214             if (ids.contains(windowId)) {
01215                 if (ids.count() > 1)
01216                     kDebug() << "removing window id" << windowId << "from session cookie";
01217                 else
01218                     kDebug() << "deleting session cookie";
01219             }
01220 #endif
01221             if (!ids.removeAll(windowId) || !ids.isEmpty()) {
01222                continue;
01223             }
01224             cookieIterator.remove();
01225         }
01226     }
01227 }
01228 
01229 //
01230 // Saves all cookies to the file '_filename'.
01231 // On succes 'true' is returned.
01232 // On failure 'false' is returned.
01233 bool KCookieJar::saveCookies(const QString &_filename)
01234 {
01235     KSaveFile saveFile(_filename);
01236 
01237     if (!saveFile.open())
01238        return false;
01239     saveFile.setPermissions(QFile::ReadUser|QFile::WriteUser);
01240 
01241     QTextStream ts(&saveFile);
01242 
01243     time_t curTime = time(0);
01244 
01245     ts << "# KDE Cookie File v2\n#\n";
01246 
01247     QString s;
01248     s.sprintf("%-20s %-20s %-12s %-10s %-4s %-20s %-4s %s\n",
01249               "# Host", "Domain", "Path", "Exp.date", "Prot",
01250               "Name", "Sec", "Value");
01251     ts << s.toLatin1().constData();
01252 
01253     for ( QStringList::const_iterator it=m_domainList.constBegin(); it != m_domainList.constEnd();
01254           it++ )
01255     {
01256         const QString &domain = *it;
01257         bool domainPrinted = false;
01258 
01259         KHttpCookieList *cookieList = m_cookieDomains.value(domain);
01260         QMutableListIterator<KHttpCookie> cookieIterator(*cookieList);
01261         while (cookieIterator.hasNext()) {
01262             const KHttpCookie& cookie = cookieIterator.next();
01263             if (cookie.isExpired(curTime)) {
01264                 // Delete expired cookies
01265                 cookieIterator.remove();
01266             } else if (cookie.expireDate() != 0 && !m_ignoreCookieExpirationDate) {
01267                 // Only save cookies that are not "session-only cookies"
01268                 if (!domainPrinted) {
01269                     domainPrinted = true;
01270                     ts << '[' << domain.toLocal8Bit().data() << "]\n";
01271                 }
01272                 // Store persistent cookies
01273                 QString path = L1("\"");
01274                 path += cookie.path();
01275                 path += '"';
01276                 QString domain = L1("\"");
01277                 domain += cookie.domain();
01278                 domain += '"';
01279                 // TODO: replace with direct QTextStream output ?
01280                 s.sprintf("%-20s %-20s %-12s %10lu  %3d %-20s %-4i %s\n",
01281                         cookie.host().toLatin1().constData(), domain.toLatin1().constData(),
01282                         path.toLatin1().constData(), (unsigned long) cookie.expireDate(),
01283                         cookie.protocolVersion(),
01284                         cookie.name().isEmpty() ? cookie.value().toLatin1().constData() : cookie.name().toLatin1().constData(),
01285                         (cookie.isSecure() ? 1 : 0) + (cookie.isHttpOnly() ? 2 : 0) +
01286                         (cookie.hasExplicitPath() ? 4 : 0) + (cookie.name().isEmpty() ? 8 : 0),
01287                         cookie.value().toLatin1().constData());
01288                 ts << s.toLatin1().constData();
01289             }
01290         }
01291     }
01292 
01293     return saveFile.finalize();
01294 }
01295 
01296 static const char *parseField(char* &buffer, bool keepQuotes=false)
01297 {
01298     char *result;
01299     if (!keepQuotes && (*buffer == '\"'))
01300     {
01301         // Find terminating "
01302         buffer++;
01303         result = buffer;
01304         while((*buffer != '\"') && (*buffer))
01305             buffer++;
01306     }
01307     else
01308     {
01309         // Find first white space
01310         result = buffer;
01311         while((*buffer != ' ') && (*buffer != '\t') && (*buffer != '\n') && (*buffer))
01312             buffer++;
01313     }
01314 
01315     if (!*buffer)
01316         return result; //
01317     *buffer++ = '\0';
01318 
01319     // Skip white-space
01320     while((*buffer == ' ') || (*buffer == '\t') || (*buffer == '\n'))
01321         buffer++;
01322 
01323     return result;
01324 }
01325 
01326 
01327 //
01328 // Reloads all cookies from the file '_filename'.
01329 // On succes 'true' is returned.
01330 // On failure 'false' is returned.
01331 bool KCookieJar::loadCookies(const QString &_filename)
01332 {
01333     FILE *fStream = fopen( QFile::encodeName(_filename), "r");
01334     if (fStream == 0)
01335     {
01336         return false;
01337     }
01338 
01339     time_t curTime = time(0);
01340 
01341     char *buffer = new char[READ_BUFFER_SIZE];
01342 
01343     bool err = false;
01344     err = (fgets(buffer, READ_BUFFER_SIZE, fStream) == 0);
01345 
01346     int version = 1;
01347     if (!err)
01348     {
01349         if (strcmp(buffer, "# KDE Cookie File\n") == 0)
01350         {
01351             // version 1
01352         }
01353         else if (sscanf(buffer, "# KDE Cookie File v%d\n", &version) != 1)
01354         {
01355             err = true;
01356         }
01357     }
01358 
01359     if (!err)
01360     {
01361         while(fgets(buffer, READ_BUFFER_SIZE, fStream) != 0)
01362         {
01363             char *line = buffer;
01364             // Skip lines which begin with '#' or '['
01365             if ((line[0] == '#') || (line[0] == '['))
01366                 continue;
01367 
01368             const QString host = QString::fromLatin1( parseField(line) );
01369             const QString domain = QString::fromLatin1( parseField(line) );
01370             if (host.isEmpty() && domain.isEmpty())
01371                 continue;
01372             const QString path = QString::fromLatin1( parseField(line) );
01373             const QString expStr = QString::fromLatin1( parseField(line) );
01374             if (expStr.isEmpty()) continue;
01375             const int expDate = expStr.toInt();
01376             const QString verStr = QString::fromLatin1( parseField(line) );
01377             if (verStr.isEmpty()) continue;
01378             int protVer  = verStr.toInt();
01379             QString name = QString::fromLatin1( parseField(line) );
01380             bool keepQuotes = false;
01381             bool secure = false;
01382             bool httpOnly = false;
01383             bool explicitPath = false;
01384             const char *value = 0;
01385             if ((version == 2) || (protVer >= 200))
01386             {
01387                 if (protVer >= 200)
01388                     protVer -= 200;
01389                 int i = atoi( parseField(line) );
01390                 secure = i & 1;
01391                 httpOnly = i & 2;
01392                 explicitPath = i & 4;
01393                 if (i & 8)
01394                     name = "";
01395                 line[strlen(line)-1] = '\0'; // Strip LF.
01396                 value = line;
01397             }
01398             else
01399             {
01400                 if (protVer >= 100)
01401                 {
01402                     protVer -= 100;
01403                     keepQuotes = true;
01404                 }
01405                 value = parseField(line, keepQuotes);
01406                 secure = atoi( parseField(line) );
01407             }
01408 
01409             // Parse error
01410             if (!value) continue;
01411 
01412             // Expired or parse error
01413             if ((expDate == 0) || (expDate < curTime))
01414                 continue;
01415 
01416             KHttpCookie cookie(host,
01417                                domain,
01418                                path,
01419                                name,
01420                                value,
01421                                expDate, protVer,
01422                                secure, httpOnly, explicitPath);
01423             addCookie(cookie);
01424         }
01425     }
01426     delete [] buffer;
01427     m_cookiesChanged = false;
01428 
01429     fclose( fStream);
01430     return err;
01431 }
01432 
01433 //
01434 // Save the cookie configuration
01435 //
01436 
01437 void KCookieJar::saveConfig(KConfig *_config)
01438 {
01439     if (!m_configChanged)
01440         return;
01441 
01442     KConfigGroup dlgGroup(_config, "Cookie Dialog");
01443     dlgGroup.writeEntry("PreferredPolicy", m_preferredPolicy);
01444     dlgGroup.writeEntry("ShowCookieDetails", m_showCookieDetails );
01445     KConfigGroup policyGroup(_config,"Cookie Policy");
01446     policyGroup.writeEntry("CookieGlobalAdvice", adviceToStr( m_globalAdvice));
01447 
01448     QStringList domainSettings;
01449     for ( QStringList::const_iterator it=m_domainList.constBegin();
01450           it != m_domainList.constEnd();
01451           ++it )
01452     {
01453          const QString &domain = *it;
01454          KCookieAdvice advice = getDomainAdvice( domain);
01455          if (advice != KCookieDunno)
01456          {
01457              QString value(domain);
01458              value += ':';
01459              value += adviceToStr(advice);
01460              domainSettings.append(value);
01461          }
01462     }
01463     policyGroup.writeEntry("CookieDomainAdvice", domainSettings);
01464     _config->sync();
01465     m_configChanged = false;
01466 }
01467 
01468 
01469 //
01470 // Load the cookie configuration
01471 //
01472 
01473 void KCookieJar::loadConfig(KConfig *_config, bool reparse )
01474 {
01475     if ( reparse )
01476         _config->reparseConfiguration();
01477 
01478     KConfigGroup dlgGroup(_config, "Cookie Dialog");
01479     m_showCookieDetails = dlgGroup.readEntry( "ShowCookieDetails" , false );
01480     m_preferredPolicy = dlgGroup.readEntry( "PreferredPolicy", 0 );
01481 
01482     KConfigGroup policyGroup(_config,"Cookie Policy");
01483     const QStringList domainSettings = policyGroup.readEntry("CookieDomainAdvice", QStringList());
01484     m_rejectCrossDomainCookies = policyGroup.readEntry("RejectCrossDomainCookies", true);
01485     m_autoAcceptSessionCookies = policyGroup.readEntry("AcceptSessionCookies", true);
01486     m_ignoreCookieExpirationDate = policyGroup.readEntry("IgnoreExpirationDate", false);
01487     QString value = policyGroup.readEntry("CookieGlobalAdvice", QString::fromLatin1("Accept"));
01488     m_globalAdvice = strToAdvice(value);
01489 
01490     // Reset current domain settings first.
01491     //  (must make a copy because setDomainAdvice() might delete the domain from m_domainList inside the for loop)
01492     const QStringList domains = m_domainList;
01493     foreach( const QString &domain, domains )
01494     {
01495          setDomainAdvice(domain, KCookieDunno);
01496     }
01497 
01498     // Now apply the domain settings read from config file...
01499     for ( QStringList::const_iterator it=domainSettings.begin();
01500           it != domainSettings.end(); )
01501     {
01502         const QString &value = *it++;
01503 
01504         int sepPos = value.lastIndexOf(':');
01505 
01506         if (sepPos <= 0)
01507           continue;
01508 
01509         QString domain(value.left(sepPos));
01510         KCookieAdvice advice = strToAdvice( value.mid(sepPos + 1) );
01511         setDomainAdvice(domain, advice);
01512     }
01513 }
01514 
01515 QDebug operator<<(QDebug dbg, const KHttpCookie& cookie)
01516 {
01517     dbg.nospace() << cookie.cookieStr(false);
01518     return dbg.space();
01519 }
01520 
01521 QDebug operator<<(QDebug dbg, const KHttpCookieList& list)
01522 {
01523     Q_FOREACH(const KHttpCookie& cookie, list)
01524         dbg << cookie;
01525     return dbg;
01526 }

KIOSlave

Skip menu "KIOSlave"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal