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