00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
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
00056
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
00076
00077
00078
00079
00080
00081 #undef MAX_COOKIE_LIMIT
00082
00083 #define MAX_COOKIES_PER_HOST 25
00084 #define READ_BUFFER_SIZE 8192
00085
00086
00087
00088
00089
00090
00091 #define L1(x) QString::fromLatin1(x)
00092
00093 template class QPtrList<KHttpCookie>;
00094 template class QPtrDict<KHttpCookieList>;
00095
00096 QString KCookieJar::adviceToStr(KCookieAdvice _advice)
00097 {
00098 switch( _advice )
00099 {
00100 case KCookieAccept: return L1("Accept");
00101 case KCookieReject: return L1("Reject");
00102 case KCookieAsk: return L1("Ask");
00103 default: return L1("Dunno");
00104 }
00105 }
00106
00107 KCookieAdvice KCookieJar::strToAdvice(const QString &_str)
00108 {
00109 if (_str.isEmpty())
00110 return KCookieDunno;
00111
00112 QCString advice = _str.lower().latin1();
00113
00114 if (advice == "accept")
00115 return KCookieAccept;
00116 else if (advice == "reject")
00117 return KCookieReject;
00118 else if (advice == "ask")
00119 return KCookieAsk;
00120
00121 return KCookieDunno;
00122 }
00123
00124
00126
00127
00128
00129
00130 KHttpCookie::KHttpCookie(const QString &_host,
00131 const QString &_domain,
00132 const QString &_path,
00133 const QString &_name,
00134 const QString &_value,
00135 time_t _expireDate,
00136 int _protocolVersion,
00137 bool _secure,
00138 bool _httpOnly,
00139 bool _explicitPath) :
00140 mHost(_host),
00141 mDomain(_domain),
00142 mPath(_path.isEmpty() ? QString::null : _path),
00143 mName(_name),
00144 mValue(_value),
00145 mExpireDate(_expireDate),
00146 mProtocolVersion(_protocolVersion),
00147 mSecure(_secure),
00148 mHttpOnly(_httpOnly),
00149 mExplicitPath(_explicitPath)
00150 {
00151 }
00152
00153
00154
00155
00156 bool KHttpCookie::isExpired(time_t currentDate)
00157 {
00158 return (mExpireDate != 0) && (mExpireDate < currentDate);
00159 }
00160
00161
00162
00163
00164 QString KHttpCookie::cookieStr(bool useDOMFormat)
00165 {
00166 QString result;
00167
00168 if (useDOMFormat || (mProtocolVersion == 0))
00169 {
00170 if ( !mName.isEmpty() )
00171 result = mName + '=';
00172 result += mValue;
00173 }
00174 else
00175 {
00176 result = mName + '=' + mValue;
00177 if (mExplicitPath)
00178 result += L1("; $Path=\"") + mPath + L1("\"");
00179 if (!mDomain.isEmpty())
00180 result += L1("; $Domain=\"") + mDomain + L1("\"");
00181 }
00182 return result;
00183 }
00184
00185
00186
00187 bool KHttpCookie::match(const QString &fqdn, const QStringList &domains,
00188 const QString &path)
00189 {
00190
00191 if (mDomain.isEmpty())
00192 {
00193 if (fqdn != mHost)
00194 return false;
00195 }
00196 else if (!domains.contains(mDomain))
00197 {
00198 if (mDomain[0] == '.')
00199 return false;
00200
00201
00202 QString domain = '.' + mDomain;
00203 if ( !domains.contains( domain ) )
00204 if ( fqdn != mDomain )
00205 return false;
00206 }
00207
00208
00209 if (mPath.isEmpty())
00210 return true;
00211
00212
00213
00214
00215
00216
00217 if( path.startsWith(mPath) &&
00218 (
00219 (path.length() == mPath.length() ) ||
00220 (path[mPath.length()-1] == '/') ||
00221 (path[mPath.length()] == '/')
00222 ))
00223 return true;
00224
00225 return false;
00226 }
00227
00228
00230
00231 int KHttpCookieList::compareItems( void * item1, void * item2)
00232 {
00233 int pathLen1 = ((KHttpCookie *)item1)->path().length();
00234 int pathLen2 = ((KHttpCookie *)item2)->path().length();
00235 if (pathLen1 > pathLen2)
00236 return -1;
00237 if (pathLen1 < pathLen2)
00238 return 1;
00239 return 0;
00240 }
00241
00242
00243
00245
00246
00247
00248
00249
00250
00251 KCookieJar::KCookieJar()
00252 {
00253 m_cookieDomains.setAutoDelete( true );
00254 m_globalAdvice = KCookieDunno;
00255 m_configChanged = false;
00256 m_cookiesChanged = false;
00257
00258 KConfig cfg("khtml/domain_info", true, false, "data");
00259 QStringList countries = cfg.readListEntry("twoLevelTLD");
00260 for(QStringList::ConstIterator it = countries.begin();
00261 it != countries.end(); ++it)
00262 {
00263 m_twoLevelTLD.replace(*it, (int *) 1);
00264 }
00265 }
00266
00267
00268
00269
00270
00271
00272 KCookieJar::~KCookieJar()
00273 {
00274
00275 }
00276
00277 static void removeDuplicateFromList(KHttpCookieList *list, KHttpCookie *cookiePtr, bool nameMatchOnly=false, bool updateWindowId=false)
00278 {
00279 QString domain1 = cookiePtr->domain();
00280 if (domain1.isEmpty())
00281 domain1 = cookiePtr->host();
00282
00283 for ( KHttpCookiePtr cookie=list->first(); cookie != 0; )
00284 {
00285 QString domain2 = cookie->domain();
00286 if (domain2.isEmpty())
00287 domain2 = cookie->host();
00288
00289 if (
00290 (cookiePtr->name() == cookie->name()) &&
00291 (
00292 nameMatchOnly ||
00293 ( (domain1 == domain2) && (cookiePtr->path() == cookie->path()) )
00294 )
00295 )
00296 {
00297 if (updateWindowId)
00298 {
00299 for(QValueList<long>::ConstIterator it = cookie->windowIds().begin();
00300 it != cookie->windowIds().end(); ++it)
00301 {
00302 long windowId = *it;
00303 if (windowId && (cookiePtr->windowIds().find(windowId) == cookiePtr->windowIds().end()))
00304 {
00305 cookiePtr->windowIds().append(windowId);
00306 }
00307 }
00308 }
00309 KHttpCookiePtr old_cookie = cookie;
00310 cookie = list->next();
00311 list->removeRef( old_cookie );
00312 break;
00313 }
00314 else
00315 {
00316 cookie = list->next();
00317 }
00318 }
00319 }
00320
00321
00322
00323
00324
00325
00326
00327 QString KCookieJar::findCookies(const QString &_url, bool useDOMFormat, long windowId, KHttpCookieList *pendingCookies)
00328 {
00329 QString cookieStr;
00330 QStringList domains;
00331 QString fqdn;
00332 QString path;
00333 KHttpCookiePtr cookie;
00334 KCookieAdvice advice = m_globalAdvice;
00335
00336 if (!parseURL(_url, fqdn, path))
00337 return cookieStr;
00338
00339 bool secureRequest = (_url.find( L1("https://"), 0, false) == 0 ||
00340 _url.find( L1("webdavs://"), 0, false) == 0);
00341
00342 extractDomains(fqdn, domains);
00343
00344 KHttpCookieList allCookies;
00345
00346 for(QStringList::ConstIterator it = domains.begin();
00347 true;
00348 ++it)
00349 {
00350 KHttpCookieList *cookieList;
00351 if (it == domains.end())
00352 {
00353 cookieList = pendingCookies;
00354 pendingCookies = 0;
00355 if (!cookieList)
00356 break;
00357 }
00358 else
00359 {
00360 QString key = (*it).isNull() ? L1("") : (*it);
00361 cookieList = m_cookieDomains[key];
00362 if (!cookieList)
00363 continue;
00364 }
00365
00366 if (cookieList->getAdvice() != KCookieDunno)
00367 advice = cookieList->getAdvice();
00368
00369
00370
00371
00372 if (advice == KCookieReject &&
00373 !(m_ignoreCookieExpirationDate && m_autoAcceptSessionCookies))
00374 {
00375 if (it == domains.end())
00376 break;
00377 continue;
00378 }
00379
00380 for ( cookie=cookieList->first(); cookie != 0; cookie=cookieList->next() )
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
00392 if ( cookie->isExpired (time(0)) )
00393 {
00394
00395
00396
00397
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())
00408 removeDuplicateFromList(&allCookies, cookie);
00409
00410 allCookies.append(cookie);
00411 }
00412 if (it == domains.end())
00413 break;
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);
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
00459
00460
00461
00462
00463
00464
00465
00466
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
00475 for(; (*s != '='); s++)
00476 {
00477 if ((*s=='\0') || (*s==';') || (*s=='\n'))
00478 {
00479
00480
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
00494 s++;
00495
00496
00497 for(; (*s == ' ') || (*s == '\t'); s++)
00498 {
00499 if ((*s=='\0') || (*s==';') || (*s=='\n'))
00500 {
00501
00502 Value = "";
00503 return (s);
00504 }
00505 }
00506
00507 if ((rfcQuotes || !keepQuotes) && (*s == '\"'))
00508 {
00509
00510 if (keepQuotes)
00511 header = s++;
00512 else
00513 header = ++s;
00514 for(;(*s != '\"');s++)
00515 {
00516 if ((*s=='\0') || (*s=='\n'))
00517 {
00518
00519 Value = QString::fromLatin1(header);
00520 Value.truncate(s - header);
00521 return (s);
00522 }
00523 }
00524 Value = QString::fromLatin1(header);
00525
00526 if (keepQuotes)
00527 Value.truncate( ++s - header );
00528 else
00529 Value.truncate( s++ - header );
00530
00531
00532 for(;; s++)
00533 {
00534 if ((*s=='\0') || (*s==';') || (*s=='\n'))
00535 break;
00536 }
00537 }
00538 else
00539 {
00540
00541 header = s;
00542 while ((*s != '\0') && (*s != ';') && (*s != '\n'))
00543 s++;
00544
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;
00566 if (cookiePtr->domain().isEmpty())
00567 stripDomain( cookiePtr->host(), domain);
00568 else
00569 domain = cookiePtr->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
00592
00593
00594 if(_fqdn.find('/') > -1 || _fqdn.find('%') > -1)
00595 {
00596 return false;
00597 }
00598
00599 _path = kurl.path();
00600 if (_path.isEmpty())
00601 _path = L1("/");
00602
00603 QRegExp exp(L1("[\\\\/]\\.\\.[\\\\/]"));
00604
00605 if (exp.search(_path) != -1)
00606 return false;
00607
00608 return true;
00609 }
00610
00611 void KCookieJar::extractDomains(const QString &_fqdn,
00612 QStringList &_domains)
00613 {
00614
00615 if (_fqdn[0] == '[')
00616 {
00617 _domains.append( _fqdn );
00618 return;
00619 }
00620
00621 if ((_fqdn[0] >= '0') && (_fqdn[0] <= '9'))
00622 {
00623 bool allNumeric = true;
00624 for(int i = _fqdn.length(); i--;)
00625 {
00626 if (!strchr("0123456789:.", _fqdn[i].latin1()))
00627 {
00628 allNumeric = false;
00629 break;
00630 }
00631 }
00632 if (allNumeric)
00633 {
00634 _domains.append( _fqdn );
00635 return;
00636 }
00637 }
00638
00639 QStringList partList = QStringList::split('.', _fqdn, false);
00640
00641 if (partList.count())
00642 partList.remove(partList.begin());
00643
00644 while(partList.count())
00645 {
00646
00647 if (partList.count() == 1)
00648 break;
00649
00650 if ((partList.count() == 2) && (m_twoLevelTLD[partList[1].lower()]))
00651 {
00652
00653 break;
00654 }
00655
00656 if ((partList.count() == 2) && (partList[1].length() == 2))
00657 {
00658
00659
00660 if (partList[0].length() <= 2)
00661 break;
00662
00663
00664
00665 QCString t = partList[0].lower().utf8();
00666 if ((t == "com") || (t == "net") || (t == "org") || (t == "gov") || (t == "edu") || (t == "mil") || (t == "int"))
00667 break;
00668 }
00669
00670 QString domain = partList.join(L1("."));
00671 _domains.append(domain);
00672 _domains.append('.' + domain);
00673 partList.remove(partList.begin());
00674 }
00675
00676
00677
00678 _domains.prepend( '.' + _fqdn );
00679 _domains.prepend( _fqdn );
00680 }
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690 KHttpCookieList KCookieJar::makeCookies(const QString &_url,
00691 const QCString &cookie_headers,
00692 long windowId)
00693 {
00694 KHttpCookieList cookieList;
00695 KHttpCookieList cookieList2;
00696 KHttpCookiePtr lastCookie = 0;
00697 const char *cookieStr = cookie_headers.data();
00698 QString Name;
00699 QString Value;
00700 QString fqdn;
00701 QString path;
00702 bool crossDomain = false;
00703
00704 if (!parseURL(_url, fqdn, path))
00705 {
00706
00707 return KHttpCookieList();
00708 }
00709 QString defaultPath;
00710 int i = path.findRev('/');
00711 if (i > 0)
00712 defaultPath = path.left(i);
00713
00714
00715 for(;;)
00716 {
00717
00718 if (strncmp(cookieStr, "Cross-Domain\n", 13) == 0)
00719 {
00720 cookieStr += 13;
00721 crossDomain = true;
00722 }
00723 else if (strncasecmp(cookieStr, "Set-Cookie:", 11) == 0)
00724 {
00725 cookieStr = parseNameValue(cookieStr+11, Name, Value, true);
00726
00727
00728
00729
00730
00731 KHttpCookie *cookie = new KHttpCookie(fqdn, L1(""), defaultPath, Name, Value);
00732 if (windowId)
00733 cookie->mWindowIds.append(windowId);
00734 cookie->mCrossDomain = crossDomain;
00735
00736
00737 cookieList.append(cookie);
00738 lastCookie = cookie;
00739 }
00740 else if (strncasecmp(cookieStr, "Set-Cookie2:", 12) == 0)
00741 {
00742
00743 cookieStr = parseNameValue(cookieStr+12, Name, Value, true, true);
00744
00745
00746
00747
00748
00749 KHttpCookie *cookie = new KHttpCookie(fqdn, L1(""), defaultPath, Name, Value);
00750 if (windowId)
00751 cookie->mWindowIds.append(windowId);
00752 cookie->mCrossDomain = crossDomain;
00753
00754
00755 cookieList2.append(cookie);
00756 lastCookie = cookie;
00757 }
00758 else
00759 {
00760
00761 while (*cookieStr && *cookieStr != '\n')
00762 cookieStr++;
00763
00764 if (*cookieStr == '\n')
00765 cookieStr++;
00766
00767 if (!*cookieStr)
00768 break;
00769 else
00770 continue;
00771 }
00772
00773 while ((*cookieStr == ';') || (*cookieStr == ' '))
00774 {
00775 cookieStr++;
00776
00777
00778 cookieStr = parseNameValue(cookieStr, Name, Value);
00779
00780 QCString cName = Name.lower().latin1();
00781 if (cName == "domain")
00782 {
00783 QString dom = Value.lower();
00784
00785
00786 if(dom.length() && dom[0] != '.')
00787 dom.prepend(".");
00788
00789 if(dom.length() > 2 && dom[dom.length()-1] == '.')
00790 dom = dom.left(dom.length()-1);
00791
00792 if(dom.contains('.') > 1 || dom == ".local")
00793 lastCookie->mDomain = dom;
00794 }
00795 else if (cName == "max-age")
00796 {
00797 int max_age = Value.toInt();
00798 if (max_age == 0)
00799 lastCookie->mExpireDate = 1;
00800 else
00801 lastCookie->mExpireDate = time(0)+max_age;
00802 }
00803 else if (cName == "expires")
00804 {
00805
00806 lastCookie->mExpireDate = KRFCDate::parseDate(Value);
00807 }
00808 else if (cName == "path")
00809 {
00810 if (Value.isEmpty())
00811 lastCookie->mPath = QString::null;
00812 else
00813 lastCookie->mPath = KURL::decode_string(Value);
00814 lastCookie->mExplicitPath = true;
00815 }
00816 else if (cName == "version")
00817 {
00818 lastCookie->mProtocolVersion = Value.toInt();
00819 }
00820 else if ((cName == "secure") ||
00821 (cName.isEmpty() && Value.lower() == L1("secure")))
00822 {
00823 lastCookie->mSecure = true;
00824 }
00825 else if ((cName == "httponly") ||
00826 (cName.isEmpty() && Value.lower() == L1("httponly")))
00827 {
00828 lastCookie->mHttpOnly = true;
00829 }
00830 }
00831
00832 if (*cookieStr == '\0')
00833 break;
00834
00835
00836 cookieStr++;
00837 }
00838
00839
00840 while( !cookieList2.isEmpty() && (lastCookie = cookieList2.take(0)) )
00841 {
00842 removeDuplicateFromList(&cookieList, lastCookie, true);
00843 cookieList.append(lastCookie);
00844 }
00845
00846 return cookieList;
00847 }
00848
00855 KHttpCookieList KCookieJar::makeDOMCookies(const QString &_url,
00856 const QCString &cookie_domstring,
00857 long windowId)
00858 {
00859
00860 KHttpCookieList cookieList;
00861 KHttpCookiePtr lastCookie = 0;
00862
00863 const char *cookieStr = cookie_domstring.data();
00864 QString Name;
00865 QString Value;
00866 QString fqdn;
00867 QString path;
00868
00869 if (!parseURL(_url, fqdn, path))
00870 {
00871
00872 return KHttpCookieList();
00873 }
00874
00875
00876 while(*cookieStr)
00877 {
00878 cookieStr = parseNameValue(cookieStr, Name, Value);
00879
00880
00881
00882
00883 KHttpCookie *cookie = new KHttpCookie(fqdn, QString::null, QString::null,
00884 Name, Value );
00885 if (windowId)
00886 cookie->mWindowIds.append(windowId);
00887
00888 cookieList.append(cookie);
00889 lastCookie = cookie;
00890
00891 if (*cookieStr != '\0')
00892 cookieStr++;
00893 }
00894
00895 return cookieList;
00896 }
00897
00898 #ifdef MAX_COOKIE_LIMIT
00899 static void makeRoom(KHttpCookieList *cookieList, KHttpCookiePtr &cookiePtr)
00900 {
00901
00902 KHttpCookiePtr lastCookie = 0;
00903 for(KHttpCookiePtr cookie = cookieList->first(); cookie; cookie = cookieList->next())
00904 {
00905 if (cookieList->compareItems(cookie, cookiePtr) < 0)
00906 break;
00907 lastCookie = cookie;
00908 }
00909 if (!lastCookie)
00910 lastCookie = cookieList->first();
00911 cookieList->removeRef(lastCookie);
00912 }
00913 #endif
00914
00915
00916
00917
00918
00919
00920 void KCookieJar::addCookie(KHttpCookiePtr &cookiePtr)
00921 {
00922 QStringList domains;
00923 KHttpCookieList *cookieList = 0L;
00924
00925
00926
00927
00928 extractDomains( cookiePtr->host(), domains );
00929 for ( QStringList::ConstIterator it = domains.begin();
00930 (it != domains.end() && !cookieList);
00931 ++it )
00932 {
00933 QString key = (*it).isNull() ? L1("") : (*it);
00934 KHttpCookieList *list= m_cookieDomains[key];
00935 if ( !list ) continue;
00936
00937 removeDuplicateFromList(list, cookiePtr, false, true);
00938 }
00939
00940 QString domain = stripDomain( cookiePtr );
00941 QString key = domain.isNull() ? L1("") : domain;
00942 cookieList = m_cookieDomains[ key ];
00943 if (!cookieList)
00944 {
00945
00946 cookieList = new KHttpCookieList();
00947 cookieList->setAutoDelete(true);
00948
00949
00950
00951
00952 cookieList->setAdvice( KCookieDunno );
00953
00954 m_cookieDomains.insert( domain, cookieList);
00955
00956
00957 m_domainList.append(domain);
00958 }
00959
00960
00961
00962 if (!cookiePtr->isExpired(time(0)))
00963 {
00964 #ifdef MAX_COOKIE_LIMIT
00965 if (cookieList->count() >= MAX_COOKIES_PER_HOST)
00966 makeRoom(cookieList, cookiePtr);
00967 #endif
00968 cookieList->inSort( cookiePtr );
00969 m_cookiesChanged = true;
00970 }
00971 else
00972 {
00973 delete cookiePtr;
00974 }
00975 cookiePtr = 0;
00976 }
00977
00978
00979
00980
00981
00982 KCookieAdvice KCookieJar::cookieAdvice(KHttpCookiePtr cookiePtr)
00983 {
00984 QStringList domains;
00985
00986 if (m_rejectCrossDomainCookies && cookiePtr->isCrossDomain())
00987 return KCookieReject;
00988
00989 if (m_autoAcceptSessionCookies && (cookiePtr->expireDate() == 0 ||
00990 m_ignoreCookieExpirationDate))
00991 return KCookieAccept;
00992
00993 extractDomains(cookiePtr->host(), domains);
00994
00995
00996
00997 if (!cookiePtr->domain().isEmpty())
00998 {
00999 bool valid = false;
01000
01001
01002
01003 if (!valid)
01004 {
01005 if (domains.contains(cookiePtr->domain()))
01006 valid = true;
01007 }
01008
01009 if (!valid)
01010 {
01011
01012 if (cookiePtr->domain().endsWith("."+cookiePtr->host()))
01013 valid = true;
01014 }
01015
01016 if (!valid)
01017 {
01018 cookiePtr->fixDomain(QString::null);
01019 }
01020 }
01021
01022 KCookieAdvice advice = KCookieDunno;
01023 bool isFQDN = true;
01024 QStringList::Iterator it = domains.begin();
01025 while( (advice == KCookieDunno) && (it != domains.end()))
01026 {
01027 QString domain = *it;
01028
01029 if ( domain[0] == '.' || isFQDN )
01030 {
01031 isFQDN = false;
01032 KHttpCookieList *cookieList = m_cookieDomains[domain];
01033 if (cookieList)
01034 advice = cookieList->getAdvice();
01035 }
01036 domains.remove(it);
01037 it = domains.begin();
01038 }
01039
01040 if (advice == KCookieDunno)
01041 advice = m_globalAdvice;
01042
01043 return advice;
01044 }
01045
01046
01047
01048
01049
01050 KCookieAdvice KCookieJar::getDomainAdvice(const QString &_domain)
01051 {
01052 KHttpCookieList *cookieList = m_cookieDomains[_domain];
01053 KCookieAdvice advice;
01054
01055 if (cookieList)
01056 {
01057 advice = cookieList->getAdvice();
01058 }
01059 else
01060 {
01061 advice = KCookieDunno;
01062 }
01063
01064 return advice;
01065 }
01066
01067
01068
01069
01070
01071 void KCookieJar::setDomainAdvice(const QString &_domain, KCookieAdvice _advice)
01072 {
01073 QString domain(_domain);
01074 KHttpCookieList *cookieList = m_cookieDomains[domain];
01075
01076 if (cookieList)
01077 {
01078 if (cookieList->getAdvice() != _advice)
01079 {
01080 m_configChanged = true;
01081
01082 cookieList->setAdvice( _advice);
01083 }
01084
01085 if ((cookieList->isEmpty()) &&
01086 (_advice == KCookieDunno))
01087 {
01088
01089 m_cookieDomains.remove(domain);
01090 m_domainList.remove(domain);
01091 }
01092 }
01093 else
01094 {
01095
01096 if (_advice != KCookieDunno)
01097 {
01098
01099 m_configChanged = true;
01100
01101 cookieList = new KHttpCookieList();
01102 cookieList->setAutoDelete(true);
01103 cookieList->setAdvice( _advice);
01104 m_cookieDomains.insert( domain, cookieList);
01105
01106 m_domainList.append( domain);
01107 }
01108 }
01109 }
01110
01111
01112
01113
01114
01115 void KCookieJar::setDomainAdvice(KHttpCookiePtr cookiePtr, KCookieAdvice _advice)
01116 {
01117 QString domain;
01118 stripDomain(cookiePtr->host(), domain);
01119
01120 setDomainAdvice(domain, _advice);
01121 }
01122
01123
01124
01125
01126 void KCookieJar::setGlobalAdvice(KCookieAdvice _advice)
01127 {
01128 if (m_globalAdvice != _advice)
01129 m_configChanged = true;
01130 m_globalAdvice = _advice;
01131 }
01132
01133
01134
01135
01136 const QStringList& KCookieJar::getDomainList()
01137 {
01138 return m_domainList;
01139 }
01140
01141
01142
01143
01144 const KHttpCookieList *KCookieJar::getCookieList(const QString & _domain,
01145 const QString & _fqdn )
01146 {
01147 QString domain;
01148
01149 if (_domain.isEmpty())
01150 stripDomain( _fqdn, domain );
01151 else
01152 domain = _domain;
01153
01154 return m_cookieDomains[domain];
01155 }
01156
01157
01158
01159
01160
01161 void KCookieJar::eatCookie(KHttpCookiePtr cookiePtr)
01162 {
01163 QString domain = stripDomain(cookiePtr);
01164 KHttpCookieList *cookieList = m_cookieDomains[domain];
01165
01166 if (cookieList)
01167 {
01168
01169 if (cookieList->removeRef( cookiePtr ))
01170 m_cookiesChanged = true;
01171
01172 if ((cookieList->isEmpty()) &&
01173 (cookieList->getAdvice() == KCookieDunno))
01174 {
01175
01176 m_cookieDomains.remove(domain);
01177
01178 m_domainList.remove(domain);
01179 }
01180 }
01181 }
01182
01183 void KCookieJar::eatCookiesForDomain(const QString &domain)
01184 {
01185 KHttpCookieList *cookieList = m_cookieDomains[domain];
01186 if (!cookieList || cookieList->isEmpty()) return;
01187
01188 cookieList->clear();
01189 if (cookieList->getAdvice() == KCookieDunno)
01190 {
01191
01192 m_cookieDomains.remove(domain);
01193 m_domainList.remove(domain);
01194 }
01195 m_cookiesChanged = true;
01196 }
01197
01198 void KCookieJar::eatSessionCookies( long windowId )
01199 {
01200 if (!windowId)
01201 return;
01202
01203 QStringList::Iterator it=m_domainList.begin();
01204 for ( ; it != m_domainList.end(); ++it )
01205 eatSessionCookies( *it, windowId, false );
01206 }
01207
01208 void KCookieJar::eatAllCookies()
01209 {
01210 for ( QStringList::Iterator it=m_domainList.begin();
01211 it != m_domainList.end();)
01212 {
01213 QString domain = *it++;
01214
01215 eatCookiesForDomain(domain);
01216 }
01217 }
01218
01219 void KCookieJar::eatSessionCookies( const QString& fqdn, long windowId,
01220 bool isFQDN )
01221 {
01222 KHttpCookieList* cookieList;
01223 if ( !isFQDN )
01224 cookieList = m_cookieDomains[fqdn];
01225 else
01226 {
01227 QString domain;
01228 stripDomain( fqdn, domain );
01229 cookieList = m_cookieDomains[domain];
01230 }
01231
01232 if ( cookieList )
01233 {
01234 KHttpCookiePtr cookie=cookieList->first();
01235 for (; cookie != 0;)
01236 {
01237 if ((cookie->expireDate() != 0) && !m_ignoreCookieExpirationDate)
01238 {
01239 cookie = cookieList->next();
01240 continue;
01241 }
01242
01243 QValueList<long> &ids = cookie->windowIds();
01244 if (!ids.remove(windowId) || !ids.isEmpty())
01245 {
01246 cookie = cookieList->next();
01247 continue;
01248 }
01249 KHttpCookiePtr old_cookie = cookie;
01250 cookie = cookieList->next();
01251 cookieList->removeRef( old_cookie );
01252 }
01253 }
01254 }
01255
01256
01257
01258
01259
01260 bool KCookieJar::saveCookies(const QString &_filename)
01261 {
01262 KSaveFile saveFile(_filename, 0600);
01263
01264 if (saveFile.status() != 0)
01265 return false;
01266
01267 FILE *fStream = saveFile.fstream();
01268
01269 time_t curTime = time(0);
01270
01271 fprintf(fStream, "# KDE Cookie File v2\n#\n");
01272
01273 fprintf(fStream, "%-20s %-20s %-12s %-10s %-4s %-20s %-4s %s\n",
01274 "# Host", "Domain", "Path", "Exp.date", "Prot",
01275 "Name", "Sec", "Value");
01276
01277 for ( QStringList::Iterator it=m_domainList.begin(); it != m_domainList.end();
01278 it++ )
01279 {
01280 const QString &domain = *it;
01281 bool domainPrinted = false;
01282
01283 KHttpCookieList *cookieList = m_cookieDomains[domain];
01284 KHttpCookiePtr cookie=cookieList->last();
01285
01286 for (; cookie != 0;)
01287 {
01288 if (cookie->isExpired(curTime))
01289 {
01290
01291 KHttpCookiePtr old_cookie = cookie;
01292 cookie = cookieList->prev();
01293 cookieList->removeRef( old_cookie );
01294 }
01295 else if (cookie->expireDate() != 0 && !m_ignoreCookieExpirationDate)
01296 {
01297 if (!domainPrinted)
01298 {
01299 domainPrinted = true;
01300 fprintf(fStream, "[%s]\n", domain.local8Bit().data());
01301 }
01302
01303 QString path = L1("\"");
01304 path += cookie->path();
01305 path += '"';
01306 QString domain = L1("\"");
01307 domain += cookie->domain();
01308 domain += '"';
01309 fprintf(fStream, "%-20s %-20s %-12s %10lu %3d %-20s %-4i %s\n",
01310 cookie->host().latin1(), domain.latin1(),
01311 path.latin1(), (unsigned long) cookie->expireDate(),
01312 cookie->protocolVersion(),
01313 cookie->name().isEmpty() ? cookie->value().latin1() : cookie->name().latin1(),
01314 (cookie->isSecure() ? 1 : 0) + (cookie->isHttpOnly() ? 2 : 0) +
01315 (cookie->hasExplicitPath() ? 4 : 0) + (cookie->name().isEmpty() ? 8 : 0),
01316 cookie->value().latin1());
01317 cookie = cookieList->prev();
01318 }
01319 else
01320 {
01321
01322 cookie = cookieList->prev();
01323 }
01324 }
01325 }
01326
01327 return saveFile.close();
01328 }
01329
01330 typedef char *charPtr;
01331
01332 static const char *parseField(charPtr &buffer, bool keepQuotes=false)
01333 {
01334 char *result;
01335 if (!keepQuotes && (*buffer == '\"'))
01336 {
01337
01338 buffer++;
01339 result = buffer;
01340 while((*buffer != '\"') && (*buffer))
01341 buffer++;
01342 }
01343 else
01344 {
01345
01346 result = buffer;
01347 while((*buffer != ' ') && (*buffer != '\t') && (*buffer != '\n') && (*buffer))
01348 buffer++;
01349 }
01350
01351 if (!*buffer)
01352 return result;
01353 *buffer++ = '\0';
01354
01355
01356 while((*buffer == ' ') || (*buffer == '\t') || (*buffer == '\n'))
01357 buffer++;
01358
01359 return result;
01360 }
01361
01362
01363
01364
01365
01366
01367 bool KCookieJar::loadCookies(const QString &_filename)
01368 {
01369 FILE *fStream = fopen( QFile::encodeName(_filename), "r");
01370 if (fStream == 0)
01371 {
01372 return false;
01373 }
01374
01375 time_t curTime = time(0);
01376
01377 char *buffer = new char[READ_BUFFER_SIZE];
01378
01379 bool err = false;
01380 err = (fgets(buffer, READ_BUFFER_SIZE, fStream) == 0);
01381
01382 int version = 1;
01383 if (!err)
01384 {
01385 if (strcmp(buffer, "# KDE Cookie File\n") == 0)
01386 {
01387
01388 }
01389 else if (sscanf(buffer, "# KDE Cookie File v%d\n", &version) != 1)
01390 {
01391 err = true;
01392 }
01393 }
01394
01395 if (!err)
01396 {
01397 while(fgets(buffer, READ_BUFFER_SIZE, fStream) != 0)
01398 {
01399 char *line = buffer;
01400
01401 if ((line[0] == '#') || (line[0] == '['))
01402 continue;
01403
01404 const char *host( parseField(line) );
01405 const char *domain( parseField(line) );
01406 const char *path( parseField(line) );
01407 const char *expStr( parseField(line) );
01408 if (!expStr) continue;
01409 int expDate = (time_t) strtoul(expStr, 0, 10);
01410 const char *verStr( parseField(line) );
01411 if (!verStr) continue;
01412 int protVer = (time_t) strtoul(verStr, 0, 10);
01413 const char *name( parseField(line) );
01414 bool keepQuotes = false;
01415 bool secure = false;
01416 bool httpOnly = false;
01417 bool explicitPath = false;
01418 const char *value = 0;
01419 if ((version == 2) || (protVer >= 200))
01420 {
01421 if (protVer >= 200)
01422 protVer -= 200;
01423 int i = atoi( parseField(line) );
01424 secure = i & 1;
01425 httpOnly = i & 2;
01426 explicitPath = i & 4;
01427 if (i & 8)
01428 name = "";
01429 line[strlen(line)-1] = '\0';
01430 value = line;
01431 }
01432 else
01433 {
01434 if (protVer >= 100)
01435 {
01436 protVer -= 100;
01437 keepQuotes = true;
01438 }
01439 value = parseField(line, keepQuotes);
01440 secure = atoi( parseField(line) );
01441 }
01442
01443
01444 if (!value) continue;
01445
01446
01447 if ((expDate == 0) || (expDate < curTime))
01448 continue;
01449
01450 KHttpCookie *cookie = new KHttpCookie(QString::fromLatin1(host),
01451 QString::fromLatin1(domain),
01452 QString::fromLatin1(path),
01453 QString::fromLatin1(name),
01454 QString::fromLatin1(value),
01455 expDate, protVer,
01456 secure, httpOnly, explicitPath);
01457 addCookie(cookie);
01458 }
01459 }
01460 delete [] buffer;
01461 m_cookiesChanged = false;
01462
01463 fclose( fStream);
01464 return err;
01465 }
01466
01467
01468
01469
01470
01471 void KCookieJar::saveConfig(KConfig *_config)
01472 {
01473 if (!m_configChanged)
01474 return;
01475
01476 _config->setGroup("Cookie Dialog");
01477 _config->writeEntry("PreferredPolicy", m_preferredPolicy);
01478 _config->writeEntry("ShowCookieDetails", m_showCookieDetails );
01479 _config->setGroup("Cookie Policy");
01480 _config->writeEntry("CookieGlobalAdvice", adviceToStr( m_globalAdvice));
01481
01482 QStringList domainSettings;
01483 for ( QStringList::Iterator it=m_domainList.begin();
01484 it != m_domainList.end();
01485 it++ )
01486 {
01487 const QString &domain = *it;
01488 KCookieAdvice advice = getDomainAdvice( domain);
01489 if (advice != KCookieDunno)
01490 {
01491 QString value(domain);
01492 value += ':';
01493 value += adviceToStr(advice);
01494 domainSettings.append(value);
01495 }
01496 }
01497 _config->writeEntry("CookieDomainAdvice", domainSettings);
01498 _config->sync();
01499 m_configChanged = false;
01500 }
01501
01502
01503
01504
01505
01506
01507 void KCookieJar::loadConfig(KConfig *_config, bool reparse )
01508 {
01509 if ( reparse )
01510 _config->reparseConfiguration();
01511
01512 _config->setGroup("Cookie Dialog");
01513 m_showCookieDetails = _config->readBoolEntry( "ShowCookieDetails" );
01514 m_preferredPolicy = _config->readNumEntry( "PreferredPolicy", 0 );
01515
01516 _config->setGroup("Cookie Policy");
01517 QStringList domainSettings = _config->readListEntry("CookieDomainAdvice");
01518 m_rejectCrossDomainCookies = _config->readBoolEntry( "RejectCrossDomainCookies", true );
01519 m_autoAcceptSessionCookies = _config->readBoolEntry( "AcceptSessionCookies", true );
01520 m_ignoreCookieExpirationDate = _config->readBoolEntry( "IgnoreExpirationDate", false );
01521 QString value = _config->readEntry("CookieGlobalAdvice", L1("Ask"));
01522 m_globalAdvice = strToAdvice(value);
01523
01524
01525 for ( QStringList::Iterator it=m_domainList.begin(); it != m_domainList.end(); )
01526 {
01527
01528
01529 QString domain = *it++;
01530 setDomainAdvice(domain, KCookieDunno);
01531 }
01532
01533
01534 for ( QStringList::Iterator it=domainSettings.begin();
01535 it != domainSettings.end(); )
01536 {
01537 const QString &value = *it++;
01538
01539 int sepPos = value.findRev(':');
01540
01541 if (sepPos <= 0)
01542 continue;
01543
01544 QString domain(value.left(sepPos));
01545 KCookieAdvice advice = strToAdvice( value.mid(sepPos + 1) );
01546 setDomainAdvice(domain, advice);
01547 }
01548 }