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 #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
00088
00089
00090
00091
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
00127
00128
00129
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
00156
00157 bool KHttpCookie::isExpired(time_t currentDate)
00158 {
00159 return (mExpireDate != 0) && (mExpireDate < currentDate);
00160 }
00161
00162
00163
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
00188 bool KHttpCookie::match(const QString &fqdn, const QStringList &domains,
00189 const QString &path)
00190 {
00191
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
00203 QString domain = '.' + mDomain;
00204 if ( !domains.contains( domain ) )
00205 if ( fqdn != mDomain )
00206 return false;
00207 }
00208
00209
00210 if (mPath.isEmpty())
00211 return true;
00212
00213
00214
00215
00216
00217
00218 if( path.startsWith(mPath) &&
00219 (
00220 (path.length() == mPath.length() ) ||
00221 (path[mPath.length()-1] == '/') ||
00222 (path[mPath.length()] == '/')
00223 ))
00224 return true;
00225
00226 return false;
00227 }
00228
00229
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
00246
00247
00248
00249
00250
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
00270
00271
00272
00273 KCookieJar::~KCookieJar()
00274 {
00275
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
00325
00326
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
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;
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;
00367 }
00368
00369 if (cookieList->getAdvice() != KCookieDunno)
00370 advice = cookieList->getAdvice();
00371
00372 for ( cookie=cookieList->first(); cookie != 0; cookie=cookieList->next() )
00373 {
00374
00375
00376
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
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 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
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 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());
00634
00635 while(partList.count())
00636 {
00637
00638 if (partList.count() == 1)
00639 break;
00640
00641 if ((partList.count() == 2) && (m_twoLevelTLD[partList[1].lower()]))
00642 {
00643
00644 break;
00645 }
00646
00647 if ((partList.count() == 2) && (partList[1].length() == 2))
00648 {
00649
00650
00651 if (partList[0].length() <= 2)
00652 break;
00653
00654
00655
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());
00665 }
00666
00667
00668
00669 _domains.prepend( '.' + _fqdn );
00670 _domains.prepend( _fqdn );
00671 }
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
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
00706
00707
00708
00709
00710
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
00729 return KHttpCookieList();
00730 }
00731 QString defaultPath;
00732 int i = path.findRev('/');
00733 if (i > 0)
00734 defaultPath = path.left(i);
00735
00736
00737 for(;;)
00738 {
00739
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
00750
00751
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
00759 cookieList.append(cookie);
00760 lastCookie = cookie;
00761 }
00762 else if (strncasecmp(cookieStr, "Set-Cookie2:", 12) == 0)
00763 {
00764
00765 cookieStr = parseNameValue(cookieStr+12, Name, Value, true, true);
00766
00767
00768
00769
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
00777 cookieList2.append(cookie);
00778 lastCookie = cookie;
00779 }
00780 else
00781 {
00782
00783 while (*cookieStr && *cookieStr != '\n')
00784 cookieStr++;
00785
00786 if (*cookieStr == '\n')
00787 cookieStr++;
00788
00789 if (!*cookieStr)
00790 break;
00791 else
00792 continue;
00793 }
00794
00795 while ((*cookieStr == ';') || (*cookieStr == ' '))
00796 {
00797 cookieStr++;
00798
00799
00800 cookieStr = parseNameValue(cookieStr, Name, Value);
00801
00802 QCString cName = Name.lower().latin1();
00803 if (cName == "domain")
00804 {
00805 QString dom = Value.lower();
00806
00807
00808 if(dom.length() && dom[0] != '.')
00809 dom.prepend(".");
00810
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
00828 lastCookie->mExpireDate = KRFCDate::parseDate(Value);
00829
00830
00831
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;
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;
00861
00862
00863 cookieStr++;
00864 }
00865
00866
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
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
00899 return KHttpCookieList();
00900 }
00901
00902
00903 while(*cookieStr)
00904 {
00905 cookieStr = parseNameValue(cookieStr, Name, Value);
00906
00907
00908
00909
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++;
00920 }
00921
00922 return cookieList;
00923 }
00924
00925 #ifdef MAX_COOKIE_LIMIT
00926 static void makeRoom(KHttpCookieList *cookieList, KHttpCookiePtr &cookiePtr)
00927 {
00928
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
00944
00945
00946
00947 void KCookieJar::addCookie(KHttpCookiePtr &cookiePtr)
00948 {
00949 QStringList domains;
00950 KHttpCookieList *cookieList = 0L;
00951
00952
00953
00954
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
00973 cookieList = new KHttpCookieList();
00974 cookieList->setAutoDelete(true);
00975
00976
00977
00978
00979 cookieList->setAdvice( KCookieDunno );
00980
00981 m_cookieDomains.insert( domain, cookieList);
00982
00983
00984 m_domainList.append(domain);
00985 }
00986
00987
00988
00989 if (!cookiePtr->isExpired(time(0)))
00990 {
00991 #ifdef MAX_COOKIE_LIMIT
00992 if (cookieList->count() >= MAX_COOKIES_PER_HOST)
00993 makeRoom(cookieList, cookiePtr);
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
01007
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
01019
01020
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;
01034 QStringList::Iterator it = domains.begin();
01035 while( (advice == KCookieDunno) && (it != domains.end()))
01036 {
01037 QString domain = *it;
01038
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();
01048 }
01049
01050 if (advice == KCookieDunno)
01051 advice = m_globalAdvice;
01052
01053 return advice;
01054 }
01055
01056
01057
01058
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
01079
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
01092 cookieList->setAdvice( _advice);
01093 }
01094
01095 if ((cookieList->isEmpty()) &&
01096 (_advice == KCookieDunno))
01097 {
01098
01099 m_cookieDomains.remove(domain);
01100 m_domainList.remove(domain);
01101 }
01102 }
01103 else
01104 {
01105
01106 if (_advice != KCookieDunno)
01107 {
01108
01109 m_configChanged = true;
01110
01111 cookieList = new KHttpCookieList();
01112 cookieList->setAutoDelete(true);
01113 cookieList->setAdvice( _advice);
01114 m_cookieDomains.insert( domain, cookieList);
01115
01116 m_domainList.append( domain);
01117 }
01118 }
01119 }
01120
01121
01122
01123
01124
01125 void KCookieJar::setDomainAdvice(KHttpCookiePtr cookiePtr, KCookieAdvice _advice)
01126 {
01127 QString domain;
01128 stripDomain(cookiePtr->host(), domain);
01129
01130 setDomainAdvice(domain, _advice);
01131 }
01132
01133
01134
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
01145
01146 const QStringList& KCookieJar::getDomainList()
01147 {
01148 return m_domainList;
01149 }
01150
01151
01152
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
01169
01170
01171 void KCookieJar::eatCookie(KHttpCookiePtr cookiePtr)
01172 {
01173 QString domain = stripDomain(cookiePtr);
01174 KHttpCookieList *cookieList = m_cookieDomains[domain];
01175
01176 if (cookieList)
01177 {
01178
01179 if (cookieList->removeRef( cookiePtr ))
01180 m_cookiesChanged = true;
01181
01182 if ((cookieList->isEmpty()) &&
01183 (cookieList->getAdvice() == KCookieDunno))
01184 {
01185
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
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
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
01268
01269
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
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
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
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
01348 buffer++;
01349 result = buffer;
01350 while((*buffer != '\"') && (*buffer))
01351 buffer++;
01352 }
01353 else
01354 {
01355
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
01366 while((*buffer == ' ') || (*buffer == '\t') || (*buffer == '\n'))
01367 buffer++;
01368
01369 return result;
01370 }
01371
01372
01373
01374
01375
01376
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
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
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';
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
01454 if (!value) continue;
01455
01456
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
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
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
01535 for ( QStringList::Iterator it=m_domainList.begin(); it != m_domainList.end(); )
01536 {
01537
01538
01539 QString domain = *it++;
01540 setDomainAdvice(domain, KCookieDunno);
01541 }
01542
01543
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 }