NetworkCookieJar: don't leak a new cookie if it has expired

This commit is contained in:
Hamish Morrison
2013-02-09 16:01:43 +00:00
parent dcaec19c9a
commit 2e7b5f9e18
+93 -95
View File
@@ -20,14 +20,14 @@ const char* kArchivedCookieMessageName = "be:cookie";
BNetworkCookieJar::BNetworkCookieJar() BNetworkCookieJar::BNetworkCookieJar()
: :
fCookieHashMap(new PrivateHashMap) fCookieHashMap(new PrivateHashMap)
{ {
} }
BNetworkCookieJar::BNetworkCookieJar(const BNetworkCookieJar&) BNetworkCookieJar::BNetworkCookieJar(const BNetworkCookieJar&)
: :
BArchivable(), BArchivable(),
fCookieHashMap(new PrivateHashMap) fCookieHashMap(new PrivateHashMap)
{ {
@@ -36,7 +36,7 @@ BNetworkCookieJar::BNetworkCookieJar(const BNetworkCookieJar&)
BNetworkCookieJar::BNetworkCookieJar(const BNetworkCookieList& otherList) BNetworkCookieJar::BNetworkCookieJar(const BNetworkCookieList& otherList)
: :
fCookieHashMap(new PrivateHashMap) fCookieHashMap(new PrivateHashMap)
{ {
AddCookies(otherList); AddCookies(otherList);
@@ -44,18 +44,18 @@ BNetworkCookieJar::BNetworkCookieJar(const BNetworkCookieList& otherList)
BNetworkCookieJar::BNetworkCookieJar(BMessage* archive) BNetworkCookieJar::BNetworkCookieJar(BMessage* archive)
: :
fCookieHashMap(new PrivateHashMap) fCookieHashMap(new PrivateHashMap)
{ {
BMessage extractedCookie; BMessage extractedCookie;
for (int32 i = 0; for (int32 i = 0;
archive->FindMessage(kArchivedCookieMessageName, i, &extractedCookie) archive->FindMessage(kArchivedCookieMessageName, i, &extractedCookie)
== B_OK; == B_OK;
i++) { i++) {
BNetworkCookie* heapCookie BNetworkCookie* heapCookie
= new(std::nothrow) BNetworkCookie(&extractedCookie); = new(std::nothrow) BNetworkCookie(&extractedCookie);
if (heapCookie == NULL || !AddCookie(heapCookie)) if (heapCookie == NULL || !AddCookie(heapCookie))
break; break;
} }
@@ -65,7 +65,7 @@ BNetworkCookieJar::BNetworkCookieJar(BMessage* archive)
BNetworkCookieJar::~BNetworkCookieJar() BNetworkCookieJar::~BNetworkCookieJar()
{ {
BNetworkCookie* cookiePtr; BNetworkCookie* cookiePtr;
for (Iterator it(GetIterator()); (cookiePtr = it.Next()); ) for (Iterator it(GetIterator()); (cookiePtr = it.Next()); )
delete it.Remove(); delete it.Remove();
} }
@@ -78,12 +78,12 @@ bool
BNetworkCookieJar::AddCookie(const BNetworkCookie& cookie) BNetworkCookieJar::AddCookie(const BNetworkCookie& cookie)
{ {
BNetworkCookie* heapCookie = new(std::nothrow) BNetworkCookie(cookie); BNetworkCookie* heapCookie = new(std::nothrow) BNetworkCookie(cookie);
if (!AddCookie(heapCookie)) { if (!AddCookie(heapCookie)) {
delete heapCookie; delete heapCookie;
return false; return false;
} }
return true; return true;
} }
@@ -91,29 +91,27 @@ BNetworkCookieJar::AddCookie(const BNetworkCookie& cookie)
bool bool
BNetworkCookieJar::AddCookie(BNetworkCookie* cookie) BNetworkCookieJar::AddCookie(BNetworkCookie* cookie)
{ {
if (cookie != NULL) { if (cookie == NULL || cookie->ShouldDeleteNow())
HashString key(cookie->Domain()); return false;
if (!fCookieHashMap->fHashMap.ContainsKey(key)) HashString key(cookie->Domain());
fCookieHashMap->fHashMap.Put(key, new BList);
if (!fCookieHashMap->fHashMap.ContainsKey(key))
BNetworkCookieList* list = fCookieHashMap->fHashMap.Get(key); fCookieHashMap->fHashMap.Put(key, new BList);
for (int32 i = 0; i < list->CountItems(); i++) { BNetworkCookieList* list = fCookieHashMap->fHashMap.Get(key);
BNetworkCookie* c
= reinterpret_cast<BNetworkCookie*>(list->ItemAt(i)); for (int32 i = 0; i < list->CountItems(); i++) {
BNetworkCookie* c
if (c->Name() == cookie->Name()) { = reinterpret_cast<BNetworkCookie*>(list->ItemAt(i));
list->RemoveItem(i);
break; if (c->Name() == cookie->Name()) {
} list->RemoveItem(i);
break;
} }
// Discard the cookie if it's to be deleted
if (!cookie->ShouldDeleteNow())
list->AddItem(cookie);
} }
list->AddItem(cookie);
return true; return true;
} }
@@ -122,15 +120,15 @@ bool
BNetworkCookieJar::AddCookies(const BNetworkCookieList& cookies) BNetworkCookieJar::AddCookies(const BNetworkCookieList& cookies)
{ {
for (int32 i = 0; i < cookies.CountItems(); i++) { for (int32 i = 0; i < cookies.CountItems(); i++) {
BNetworkCookie* cookiePtr BNetworkCookie* cookiePtr
= reinterpret_cast<BNetworkCookie*>(cookies.ItemAt(i)); = reinterpret_cast<BNetworkCookie*>(cookies.ItemAt(i));
// Using AddCookie by reference in order to avoid multiple // Using AddCookie by reference in order to avoid multiple
// cookie jar share the same cookie pointers // cookie jar share the same cookie pointers
if (!AddCookie(*cookiePtr)) if (!AddCookie(*cookiePtr))
return false; return false;
} }
return true; return true;
} }
@@ -143,8 +141,8 @@ BNetworkCookieJar::DeleteOutdatedCookies()
{ {
int32 deleteCount = 0; int32 deleteCount = 0;
BNetworkCookie* cookiePtr; BNetworkCookie* cookiePtr;
for (Iterator it(GetIterator()); (cookiePtr = it.Next()); ) { for (Iterator it = GetIterator(); (cookiePtr = it.Next()) != NULL;) {
if (cookiePtr->ShouldDeleteNow()) { if (cookiePtr->ShouldDeleteNow()) {
delete it.Remove(); delete it.Remove();
deleteCount++; deleteCount++;
@@ -160,8 +158,8 @@ BNetworkCookieJar::PurgeForExit()
{ {
int32 deleteCount = 0; int32 deleteCount = 0;
BNetworkCookie* cookiePtr; BNetworkCookie* cookiePtr;
for (Iterator it(GetIterator()); (cookiePtr = it.Next()); ) { for (Iterator it = GetIterator(); (cookiePtr = it.Next()) != NULL;) {
if (cookiePtr->ShouldDeleteAtExit()) { if (cookiePtr->ShouldDeleteAtExit()) {
delete it.Remove(); delete it.Remove();
deleteCount++; deleteCount++;
@@ -182,10 +180,10 @@ BNetworkCookieJar::Archive(BMessage* into, bool deep) const
if (error == B_OK) { if (error == B_OK) {
BNetworkCookie* cookiePtr; BNetworkCookie* cookiePtr;
for (Iterator it(GetIterator()); (cookiePtr = it.Next()); ) { for (Iterator it = GetIterator(); (cookiePtr = it.Next()) != NULL;) {
BMessage subArchive; BMessage subArchive;
error = cookiePtr->Archive(&subArchive, deep); error = cookiePtr->Archive(&subArchive, deep);
if (error != B_OK) if (error != B_OK)
return error; return error;
@@ -205,7 +203,7 @@ BNetworkCookieJar::Instantiate(BMessage* archive)
{ {
if (archive->HasMessage(kArchivedCookieMessageName)) if (archive->HasMessage(kArchivedCookieMessageName))
return new(std::nothrow) BNetworkCookieJar(archive); return new(std::nothrow) BNetworkCookieJar(archive);
return NULL; return NULL;
} }
@@ -242,11 +240,11 @@ BNetworkCookieJar::Flatten(void* buffer, ssize_t size) const
{ {
if (FlattenedSize() > size) if (FlattenedSize() > size)
return B_ERROR; return B_ERROR;
fFlattened.CopyInto(reinterpret_cast<char*>(buffer), 0, fFlattened.CopyInto(reinterpret_cast<char*>(buffer), 0,
fFlattened.Length()); fFlattened.Length());
reinterpret_cast<char*>(buffer)[fFlattened.Length()] = 0; reinterpret_cast<char*>(buffer)[fFlattened.Length()] = 0;
return B_OK; return B_OK;
} }
@@ -262,13 +260,13 @@ BNetworkCookieJar::AllowsTypeCode(type_code) const
status_t status_t
BNetworkCookieJar::Unflatten(type_code, const void* buffer, ssize_t size) BNetworkCookieJar::Unflatten(type_code, const void* buffer, ssize_t size)
{ {
BString flattenedCookies; BString flattenedCookies;
flattenedCookies.SetTo(reinterpret_cast<const char*>(buffer), size); flattenedCookies.SetTo(reinterpret_cast<const char*>(buffer), size);
while (flattenedCookies.Length() > 0) { while (flattenedCookies.Length() > 0) {
BNetworkCookie tempCookie; BNetworkCookie tempCookie;
BString tempCookieLine; BString tempCookieLine;
int32 endOfLine = flattenedCookies.FindFirst('\n', 0); int32 endOfLine = flattenedCookies.FindFirst('\n', 0);
if (endOfLine == -1) if (endOfLine == -1)
tempCookieLine = flattenedCookies; tempCookieLine = flattenedCookies;
@@ -276,11 +274,11 @@ BNetworkCookieJar::Unflatten(type_code, const void* buffer, ssize_t size)
flattenedCookies.MoveInto(tempCookieLine, 0, endOfLine); flattenedCookies.MoveInto(tempCookieLine, 0, endOfLine);
flattenedCookies.Remove(0, 1); flattenedCookies.Remove(0, 1);
} }
if (tempCookieLine.Length() != 0 && tempCookieLine[0] != '#') { if (tempCookieLine.Length() != 0 && tempCookieLine[0] != '#') {
for (int32 field = 0; field < 7; field++) { for (int32 field = 0; field < 7; field++) {
BString tempString; BString tempString;
int32 endOfField = tempCookieLine.FindFirst('\t', 0); int32 endOfField = tempCookieLine.FindFirst('\t', 0);
if (endOfField == -1) if (endOfField == -1)
tempString = tempCookieLine; tempString = tempCookieLine;
@@ -288,42 +286,42 @@ BNetworkCookieJar::Unflatten(type_code, const void* buffer, ssize_t size)
tempCookieLine.MoveInto(tempString, 0, endOfField); tempCookieLine.MoveInto(tempString, 0, endOfField);
tempCookieLine.Remove(0, 1); tempCookieLine.Remove(0, 1);
} }
switch (field) { switch (field) {
case 0: case 0:
tempCookie.SetDomain(tempString); tempCookie.SetDomain(tempString);
break; break;
case 1: case 1:
// TODO: Useless field ATM // TODO: Useless field ATM
break; break;
case 2: case 2:
tempCookie.SetPath(tempString); tempCookie.SetPath(tempString);
break; break;
case 3: case 3:
tempCookie.SetSecure(tempString == "TRUE"); tempCookie.SetSecure(tempString == "TRUE");
break; break;
case 4: case 4:
tempCookie.SetExpirationDate(atoi(tempString)); tempCookie.SetExpirationDate(atoi(tempString));
break; break;
case 5: case 5:
tempCookie.SetName(tempString); tempCookie.SetName(tempString);
break; break;
case 6: case 6:
tempCookie.SetValue(tempString); tempCookie.SetValue(tempString);
break; break;
} // switch } // switch
} // for loop } // for loop
AddCookie(tempCookie); AddCookie(tempCookie);
} }
} }
return B_OK; return B_OK;
} }
@@ -346,7 +344,7 @@ BNetworkCookieJar::GetUrlIterator(const BUrl& url) const
copy.SetPath("/"); copy.SetPath("/");
return BNetworkCookieJar::UrlIterator(this, copy); return BNetworkCookieJar::UrlIterator(this, copy);
} }
return BNetworkCookieJar::UrlIterator(this, url); return BNetworkCookieJar::UrlIterator(this, url);
} }
@@ -357,10 +355,10 @@ BNetworkCookieJar::_DoFlatten() const
fFlattened.Truncate(0); fFlattened.Truncate(0);
BNetworkCookie* cookiePtr; BNetworkCookie* cookiePtr;
for (Iterator it(GetIterator()); (cookiePtr = it.Next()); ) { for (Iterator it = GetIterator(); (cookiePtr = it.Next()) != NULL;) {
fFlattened << cookiePtr->Domain() << '\t' << "TRUE" << '\t' fFlattened << cookiePtr->Domain() << '\t' << "TRUE" << '\t'
<< cookiePtr->Path() << '\t' << cookiePtr->Path() << '\t'
<< (cookiePtr->Secure()?"TRUE":"FALSE") << '\t' << (cookiePtr->Secure()?"TRUE":"FALSE") << '\t'
<< (int32)cookiePtr->ExpirationDate() << '\t' << (int32)cookiePtr->ExpirationDate() << '\t'
<< cookiePtr->Name() << '\t' << cookiePtr->Value() << '\n'; << cookiePtr->Name() << '\t' << cookiePtr->Value() << '\n';
} }
@@ -395,7 +393,7 @@ BNetworkCookieJar::Iterator::Iterator(const BNetworkCookieJar* cookieJar)
{ {
fIterator = new(std::nothrow) PrivateIterator( fIterator = new(std::nothrow) PrivateIterator(
fCookieJar->fCookieHashMap->fHashMap.GetIterator()); fCookieJar->fCookieHashMap->fHashMap.GetIterator());
// Locate first cookie // Locate first cookie
_FindNext(); _FindNext();
} }
@@ -419,7 +417,7 @@ BNetworkCookieJar::Iterator::Next()
{ {
if (!fElement) if (!fElement)
return NULL; return NULL;
BNetworkCookie* result = fElement; BNetworkCookie* result = fElement;
_FindNext(); _FindNext();
return result; return result;
@@ -431,18 +429,18 @@ BNetworkCookieJar::Iterator::NextDomain()
{ {
if (!fElement) if (!fElement)
return NULL; return NULL;
BNetworkCookie* result = fElement; BNetworkCookie* result = fElement;
if (!fIterator->fCookieMapIterator.HasNext()) { if (!fIterator->fCookieMapIterator.HasNext()) {
fElement = NULL; fElement = NULL;
return NULL; return NULL;
} }
fList = *(fIterator->fCookieMapIterator.NextValue()); fList = *(fIterator->fCookieMapIterator.NextValue());
fIndex = 0; fIndex = 0;
fElement = reinterpret_cast<BNetworkCookie*>(fList->ItemAt(fIndex)); fElement = reinterpret_cast<BNetworkCookie*>(fList->ItemAt(fIndex));
return result; return result;
} }
@@ -452,7 +450,7 @@ BNetworkCookieJar::Iterator::Remove()
{ {
if (!fLastElement) if (!fLastElement)
return NULL; return NULL;
BNetworkCookie* result = fLastElement; BNetworkCookie* result = fLastElement;
if (fIndex == 0) { if (fIndex == 0) {
@@ -466,7 +464,7 @@ BNetworkCookieJar::Iterator::Remove()
fList->RemoveItem(fIndex-1); fList->RemoveItem(fIndex-1);
fIndex--; fIndex--;
} }
fLastElement = NULL; fLastElement = NULL;
return result; return result;
} }
@@ -490,18 +488,18 @@ void
BNetworkCookieJar::Iterator::_FindNext() BNetworkCookieJar::Iterator::_FindNext()
{ {
fLastElement = fElement; fLastElement = fElement;
fIndex++; fIndex++;
if (fList && fIndex < fList->CountItems()) { if (fList && fIndex < fList->CountItems()) {
fElement = reinterpret_cast<BNetworkCookie*>(fList->ItemAt(fIndex)); fElement = reinterpret_cast<BNetworkCookie*>(fList->ItemAt(fIndex));
return; return;
} }
if (!fIterator->fCookieMapIterator.HasNext()) { if (!fIterator->fCookieMapIterator.HasNext()) {
fElement = NULL; fElement = NULL;
return; return;
} }
fLastList = fList; fLastList = fList;
fList = *(fIterator->fCookieMapIterator.NextValue()); fList = *(fIterator->fCookieMapIterator.NextValue());
fIndex = 0; fIndex = 0;
@@ -538,11 +536,11 @@ BNetworkCookieJar::UrlIterator::UrlIterator(const BNetworkCookieJar* cookieJar,
if (domain[0] != '.') if (domain[0] != '.')
domain.Prepend("."); domain.Prepend(".");
// Prepending another dot since _FindNext is going to // Prepending another dot since _FindNext is going to
// call _SupDomain() // call _SupDomain()
domain.Prepend("."); domain.Prepend(".");
fIterator = new(std::nothrow) PrivateIterator( fIterator = new(std::nothrow) PrivateIterator(
fCookieJar->fCookieHashMap->fHashMap.GetIterator()); fCookieJar->fCookieHashMap->fHashMap.GetIterator());
fIterator->fKey.SetTo(domain, domain.Length()); fIterator->fKey.SetTo(domain, domain.Length());
@@ -569,7 +567,7 @@ BNetworkCookieJar::UrlIterator::Next()
{ {
if (!fElement) if (!fElement)
return NULL; return NULL;
BNetworkCookie* result = fElement; BNetworkCookie* result = fElement;
_FindNext(); _FindNext();
return result; return result;
@@ -581,15 +579,15 @@ BNetworkCookieJar::UrlIterator::Remove()
{ {
if (!fLastElement) if (!fLastElement)
return NULL; return NULL;
BNetworkCookie* result = fLastElement; BNetworkCookie* result = fLastElement;
fLastList->RemoveItem(fLastIndex); fLastList->RemoveItem(fLastIndex);
if (fLastList->CountItems() == 0) { if (fLastList->CountItems() == 0) {
HashString lastKey(fLastElement->Domain(), HashString lastKey(fLastElement->Domain(),
fLastElement->Domain().Length()); fLastElement->Domain().Length());
delete fCookieJar->fCookieHashMap->fHashMap.Remove(lastKey); delete fCookieJar->fCookieHashMap->fHashMap.Remove(lastKey);
} }
@@ -620,10 +618,10 @@ BNetworkCookieJar::UrlIterator::_SupDomain()
{ {
BString domain(fIterator->fKey.GetString()); BString domain(fIterator->fKey.GetString());
int32 nextDot = domain.FindFirst('.', 1); int32 nextDot = domain.FindFirst('.', 1);
if (nextDot == -1) if (nextDot == -1)
return false; return false;
domain.Remove(0, nextDot); domain.Remove(0, nextDot);
fIterator->fKey.SetTo(domain.String(), domain.Length()); fIterator->fKey.SetTo(domain.String(), domain.Length());
return true; return true;
@@ -635,17 +633,17 @@ BNetworkCookieJar::UrlIterator::_FindNext()
{ {
fLastIndex = fIndex; fLastIndex = fIndex;
fLastElement = fElement; fLastElement = fElement;
if (_FindPath()) if (_FindPath())
return; return;
fLastList = fList; fLastList = fList;
do { do {
if (!_SupDomain()) { if (!_SupDomain()) {
fElement = NULL; fElement = NULL;
return; return;
} }
_FindDomain(); _FindDomain();
} while (!_FindPath()); } while (!_FindPath());
} }
@@ -655,10 +653,10 @@ void
BNetworkCookieJar::UrlIterator::_FindDomain() BNetworkCookieJar::UrlIterator::_FindDomain()
{ {
fList = fCookieJar->fCookieHashMap->fHashMap.Get(fIterator->fKey); fList = fCookieJar->fCookieHashMap->fHashMap.Get(fIterator->fKey);
if (fList == NULL) if (fList == NULL)
fElement = NULL; fElement = NULL;
fIndex = -1; fIndex = -1;
} }
@@ -669,15 +667,15 @@ BNetworkCookieJar::UrlIterator::_FindPath()
fIndex++; fIndex++;
if (fList && fIndex < fList->CountItems()) { if (fList && fIndex < fList->CountItems()) {
do { do {
fElement fElement
= reinterpret_cast<BNetworkCookie*>(fList->ItemAt(fIndex)); = reinterpret_cast<BNetworkCookie*>(fList->ItemAt(fIndex));
if (fElement->IsValidForPath(fUrl.Path())) if (fElement->IsValidForPath(fUrl.Path()))
return true; return true;
fIndex++; fIndex++;
} while (fList && fIndex < fList->CountItems()); } while (fList && fIndex < fList->CountItems());
} }
return false; return false;
} }