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

kioslave

Skip menu "kioslave"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
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