netwerk/protocol/http/nsHttpAuthCache.cpp

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 // HttpLog.h should generally be included first
michael@0 7 #include "HttpLog.h"
michael@0 8
michael@0 9 #include "nsHttpAuthCache.h"
michael@0 10
michael@0 11 #include <stdlib.h>
michael@0 12
michael@0 13 #include "mozilla/Attributes.h"
michael@0 14 #include "nsString.h"
michael@0 15 #include "nsCRT.h"
michael@0 16 #include "mozIApplicationClearPrivateDataParams.h"
michael@0 17 #include "nsIObserverService.h"
michael@0 18 #include "mozilla/Services.h"
michael@0 19 #include "nsNetUtil.h"
michael@0 20
michael@0 21 namespace mozilla {
michael@0 22 namespace net {
michael@0 23
michael@0 24 static inline void
michael@0 25 GetAuthKey(const char *scheme, const char *host, int32_t port, uint32_t appId, bool inBrowserElement, nsCString &key)
michael@0 26 {
michael@0 27 key.Truncate();
michael@0 28 key.AppendInt(appId);
michael@0 29 key.Append(':');
michael@0 30 key.AppendInt(inBrowserElement);
michael@0 31 key.Append(':');
michael@0 32 key.Append(scheme);
michael@0 33 key.AppendLiteral("://");
michael@0 34 key.Append(host);
michael@0 35 key.Append(':');
michael@0 36 key.AppendInt(port);
michael@0 37 }
michael@0 38
michael@0 39 // return true if the two strings are equal or both empty. an empty string
michael@0 40 // is either null or zero length.
michael@0 41 static bool
michael@0 42 StrEquivalent(const char16_t *a, const char16_t *b)
michael@0 43 {
michael@0 44 static const char16_t emptyStr[] = {0};
michael@0 45
michael@0 46 if (!a)
michael@0 47 a = emptyStr;
michael@0 48 if (!b)
michael@0 49 b = emptyStr;
michael@0 50
michael@0 51 return nsCRT::strcmp(a, b) == 0;
michael@0 52 }
michael@0 53
michael@0 54 //-----------------------------------------------------------------------------
michael@0 55 // nsHttpAuthCache <public>
michael@0 56 //-----------------------------------------------------------------------------
michael@0 57
michael@0 58 nsHttpAuthCache::nsHttpAuthCache()
michael@0 59 : mDB(nullptr)
michael@0 60 , mObserver(new AppDataClearObserver(MOZ_THIS_IN_INITIALIZER_LIST()))
michael@0 61 {
michael@0 62 nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService();
michael@0 63 if (obsSvc) {
michael@0 64 obsSvc->AddObserver(mObserver, "webapps-clear-data", false);
michael@0 65 }
michael@0 66 }
michael@0 67
michael@0 68 nsHttpAuthCache::~nsHttpAuthCache()
michael@0 69 {
michael@0 70 if (mDB)
michael@0 71 ClearAll();
michael@0 72 nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService();
michael@0 73 if (obsSvc) {
michael@0 74 obsSvc->RemoveObserver(mObserver, "webapps-clear-data");
michael@0 75 mObserver->mOwner = nullptr;
michael@0 76 }
michael@0 77 }
michael@0 78
michael@0 79 nsresult
michael@0 80 nsHttpAuthCache::Init()
michael@0 81 {
michael@0 82 NS_ENSURE_TRUE(!mDB, NS_ERROR_ALREADY_INITIALIZED);
michael@0 83
michael@0 84 LOG(("nsHttpAuthCache::Init\n"));
michael@0 85
michael@0 86 mDB = PL_NewHashTable(128, (PLHashFunction) PL_HashString,
michael@0 87 (PLHashComparator) PL_CompareStrings,
michael@0 88 (PLHashComparator) 0, &gHashAllocOps, this);
michael@0 89 if (!mDB)
michael@0 90 return NS_ERROR_OUT_OF_MEMORY;
michael@0 91
michael@0 92 return NS_OK;
michael@0 93 }
michael@0 94
michael@0 95 nsresult
michael@0 96 nsHttpAuthCache::GetAuthEntryForPath(const char *scheme,
michael@0 97 const char *host,
michael@0 98 int32_t port,
michael@0 99 const char *path,
michael@0 100 uint32_t appId,
michael@0 101 bool inBrowserElement,
michael@0 102 nsHttpAuthEntry **entry)
michael@0 103 {
michael@0 104 LOG(("nsHttpAuthCache::GetAuthEntryForPath [key=%s://%s:%d path=%s]\n",
michael@0 105 scheme, host, port, path));
michael@0 106
michael@0 107 nsAutoCString key;
michael@0 108 nsHttpAuthNode *node = LookupAuthNode(scheme, host, port, appId, inBrowserElement, key);
michael@0 109 if (!node)
michael@0 110 return NS_ERROR_NOT_AVAILABLE;
michael@0 111
michael@0 112 *entry = node->LookupEntryByPath(path);
michael@0 113 return *entry ? NS_OK : NS_ERROR_NOT_AVAILABLE;
michael@0 114 }
michael@0 115
michael@0 116 nsresult
michael@0 117 nsHttpAuthCache::GetAuthEntryForDomain(const char *scheme,
michael@0 118 const char *host,
michael@0 119 int32_t port,
michael@0 120 const char *realm,
michael@0 121 uint32_t appId,
michael@0 122 bool inBrowserElement,
michael@0 123 nsHttpAuthEntry **entry)
michael@0 124
michael@0 125 {
michael@0 126 LOG(("nsHttpAuthCache::GetAuthEntryForDomain [key=%s://%s:%d realm=%s]\n",
michael@0 127 scheme, host, port, realm));
michael@0 128
michael@0 129 nsAutoCString key;
michael@0 130 nsHttpAuthNode *node = LookupAuthNode(scheme, host, port, appId, inBrowserElement, key);
michael@0 131 if (!node)
michael@0 132 return NS_ERROR_NOT_AVAILABLE;
michael@0 133
michael@0 134 *entry = node->LookupEntryByRealm(realm);
michael@0 135 return *entry ? NS_OK : NS_ERROR_NOT_AVAILABLE;
michael@0 136 }
michael@0 137
michael@0 138 nsresult
michael@0 139 nsHttpAuthCache::SetAuthEntry(const char *scheme,
michael@0 140 const char *host,
michael@0 141 int32_t port,
michael@0 142 const char *path,
michael@0 143 const char *realm,
michael@0 144 const char *creds,
michael@0 145 const char *challenge,
michael@0 146 uint32_t appId,
michael@0 147 bool inBrowserElement,
michael@0 148 const nsHttpAuthIdentity *ident,
michael@0 149 nsISupports *metadata)
michael@0 150 {
michael@0 151 nsresult rv;
michael@0 152
michael@0 153 LOG(("nsHttpAuthCache::SetAuthEntry [key=%s://%s:%d realm=%s path=%s metadata=%x]\n",
michael@0 154 scheme, host, port, realm, path, metadata));
michael@0 155
michael@0 156 if (!mDB) {
michael@0 157 rv = Init();
michael@0 158 if (NS_FAILED(rv)) return rv;
michael@0 159 }
michael@0 160
michael@0 161 nsAutoCString key;
michael@0 162 nsHttpAuthNode *node = LookupAuthNode(scheme, host, port, appId, inBrowserElement, key);
michael@0 163
michael@0 164 if (!node) {
michael@0 165 // create a new entry node and set the given entry
michael@0 166 node = new nsHttpAuthNode();
michael@0 167 if (!node)
michael@0 168 return NS_ERROR_OUT_OF_MEMORY;
michael@0 169 rv = node->SetAuthEntry(path, realm, creds, challenge, ident, metadata);
michael@0 170 if (NS_FAILED(rv))
michael@0 171 delete node;
michael@0 172 else
michael@0 173 PL_HashTableAdd(mDB, strdup(key.get()), node);
michael@0 174 return rv;
michael@0 175 }
michael@0 176
michael@0 177 return node->SetAuthEntry(path, realm, creds, challenge, ident, metadata);
michael@0 178 }
michael@0 179
michael@0 180 void
michael@0 181 nsHttpAuthCache::ClearAuthEntry(const char *scheme,
michael@0 182 const char *host,
michael@0 183 int32_t port,
michael@0 184 const char *realm,
michael@0 185 uint32_t appId,
michael@0 186 bool inBrowserElement)
michael@0 187 {
michael@0 188 if (!mDB)
michael@0 189 return;
michael@0 190
michael@0 191 nsAutoCString key;
michael@0 192 GetAuthKey(scheme, host, port, appId, inBrowserElement, key);
michael@0 193 PL_HashTableRemove(mDB, key.get());
michael@0 194 }
michael@0 195
michael@0 196 nsresult
michael@0 197 nsHttpAuthCache::ClearAll()
michael@0 198 {
michael@0 199 LOG(("nsHttpAuthCache::ClearAll\n"));
michael@0 200
michael@0 201 if (mDB) {
michael@0 202 PL_HashTableDestroy(mDB);
michael@0 203 mDB = 0;
michael@0 204 }
michael@0 205 return NS_OK;
michael@0 206 }
michael@0 207
michael@0 208 //-----------------------------------------------------------------------------
michael@0 209 // nsHttpAuthCache <private>
michael@0 210 //-----------------------------------------------------------------------------
michael@0 211
michael@0 212 nsHttpAuthNode *
michael@0 213 nsHttpAuthCache::LookupAuthNode(const char *scheme,
michael@0 214 const char *host,
michael@0 215 int32_t port,
michael@0 216 uint32_t appId,
michael@0 217 bool inBrowserElement,
michael@0 218 nsCString &key)
michael@0 219 {
michael@0 220 if (!mDB)
michael@0 221 return nullptr;
michael@0 222
michael@0 223 GetAuthKey(scheme, host, port, appId, inBrowserElement, key);
michael@0 224
michael@0 225 return (nsHttpAuthNode *) PL_HashTableLookup(mDB, key.get());
michael@0 226 }
michael@0 227
michael@0 228 void *
michael@0 229 nsHttpAuthCache::AllocTable(void *self, size_t size)
michael@0 230 {
michael@0 231 return malloc(size);
michael@0 232 }
michael@0 233
michael@0 234 void
michael@0 235 nsHttpAuthCache::FreeTable(void *self, void *item)
michael@0 236 {
michael@0 237 free(item);
michael@0 238 }
michael@0 239
michael@0 240 PLHashEntry *
michael@0 241 nsHttpAuthCache::AllocEntry(void *self, const void *key)
michael@0 242 {
michael@0 243 return (PLHashEntry *) malloc(sizeof(PLHashEntry));
michael@0 244 }
michael@0 245
michael@0 246 void
michael@0 247 nsHttpAuthCache::FreeEntry(void *self, PLHashEntry *he, unsigned flag)
michael@0 248 {
michael@0 249 if (flag == HT_FREE_VALUE) {
michael@0 250 // this would only happen if PL_HashTableAdd were to replace an
michael@0 251 // existing entry in the hash table, but we _always_ do a lookup
michael@0 252 // before adding a new entry to avoid this case.
michael@0 253 NS_NOTREACHED("should never happen");
michael@0 254 }
michael@0 255 else if (flag == HT_FREE_ENTRY) {
michael@0 256 // three wonderful flavors of freeing memory ;-)
michael@0 257 delete (nsHttpAuthNode *) he->value;
michael@0 258 free((char *) he->key);
michael@0 259 free(he);
michael@0 260 }
michael@0 261 }
michael@0 262
michael@0 263 PLHashAllocOps nsHttpAuthCache::gHashAllocOps =
michael@0 264 {
michael@0 265 nsHttpAuthCache::AllocTable,
michael@0 266 nsHttpAuthCache::FreeTable,
michael@0 267 nsHttpAuthCache::AllocEntry,
michael@0 268 nsHttpAuthCache::FreeEntry
michael@0 269 };
michael@0 270
michael@0 271 NS_IMPL_ISUPPORTS(nsHttpAuthCache::AppDataClearObserver, nsIObserver)
michael@0 272
michael@0 273 NS_IMETHODIMP
michael@0 274 nsHttpAuthCache::AppDataClearObserver::Observe(nsISupports *subject,
michael@0 275 const char * topic,
michael@0 276 const char16_t * data_unicode)
michael@0 277 {
michael@0 278 NS_ENSURE_TRUE(mOwner, NS_ERROR_NOT_AVAILABLE);
michael@0 279
michael@0 280 nsCOMPtr<mozIApplicationClearPrivateDataParams> params =
michael@0 281 do_QueryInterface(subject);
michael@0 282 if (!params) {
michael@0 283 NS_ERROR("'webapps-clear-data' notification's subject should be a mozIApplicationClearPrivateDataParams");
michael@0 284 return NS_ERROR_UNEXPECTED;
michael@0 285 }
michael@0 286
michael@0 287 uint32_t appId;
michael@0 288 bool browserOnly;
michael@0 289
michael@0 290 nsresult rv = params->GetAppId(&appId);
michael@0 291 NS_ENSURE_SUCCESS(rv, rv);
michael@0 292 rv = params->GetBrowserOnly(&browserOnly);
michael@0 293 NS_ENSURE_SUCCESS(rv, rv);
michael@0 294
michael@0 295 MOZ_ASSERT(appId != NECKO_UNKNOWN_APP_ID);
michael@0 296 mOwner->ClearAppData(appId, browserOnly);
michael@0 297 return NS_OK;
michael@0 298 }
michael@0 299
michael@0 300 static int
michael@0 301 RemoveEntriesForApp(PLHashEntry *entry, int32_t number, void *arg)
michael@0 302 {
michael@0 303 nsDependentCString key(static_cast<const char*>(entry->key));
michael@0 304 nsAutoCString* prefix = static_cast<nsAutoCString*>(arg);
michael@0 305 if (StringBeginsWith(key, *prefix)) {
michael@0 306 return HT_ENUMERATE_NEXT | HT_ENUMERATE_REMOVE;
michael@0 307 }
michael@0 308 return HT_ENUMERATE_NEXT;
michael@0 309 }
michael@0 310
michael@0 311 void
michael@0 312 nsHttpAuthCache::ClearAppData(uint32_t appId, bool browserOnly)
michael@0 313 {
michael@0 314 if (!mDB) {
michael@0 315 return;
michael@0 316 }
michael@0 317 nsAutoCString keyPrefix;
michael@0 318 keyPrefix.AppendInt(appId);
michael@0 319 keyPrefix.Append(':');
michael@0 320 if (browserOnly) {
michael@0 321 keyPrefix.AppendInt(browserOnly);
michael@0 322 keyPrefix.Append(':');
michael@0 323 }
michael@0 324 PL_HashTableEnumerateEntries(mDB, RemoveEntriesForApp, &keyPrefix);
michael@0 325 }
michael@0 326
michael@0 327 //-----------------------------------------------------------------------------
michael@0 328 // nsHttpAuthIdentity
michael@0 329 //-----------------------------------------------------------------------------
michael@0 330
michael@0 331 nsresult
michael@0 332 nsHttpAuthIdentity::Set(const char16_t *domain,
michael@0 333 const char16_t *user,
michael@0 334 const char16_t *pass)
michael@0 335 {
michael@0 336 char16_t *newUser, *newPass, *newDomain;
michael@0 337
michael@0 338 int domainLen = domain ? NS_strlen(domain) : 0;
michael@0 339 int userLen = user ? NS_strlen(user) : 0;
michael@0 340 int passLen = pass ? NS_strlen(pass) : 0;
michael@0 341
michael@0 342 int len = userLen + 1 + passLen + 1 + domainLen + 1;
michael@0 343 newUser = (char16_t *) malloc(len * sizeof(char16_t));
michael@0 344 if (!newUser)
michael@0 345 return NS_ERROR_OUT_OF_MEMORY;
michael@0 346
michael@0 347 if (user)
michael@0 348 memcpy(newUser, user, userLen * sizeof(char16_t));
michael@0 349 newUser[userLen] = 0;
michael@0 350
michael@0 351 newPass = &newUser[userLen + 1];
michael@0 352 if (pass)
michael@0 353 memcpy(newPass, pass, passLen * sizeof(char16_t));
michael@0 354 newPass[passLen] = 0;
michael@0 355
michael@0 356 newDomain = &newPass[passLen + 1];
michael@0 357 if (domain)
michael@0 358 memcpy(newDomain, domain, domainLen * sizeof(char16_t));
michael@0 359 newDomain[domainLen] = 0;
michael@0 360
michael@0 361 // wait until the end to clear member vars in case input params
michael@0 362 // reference our members!
michael@0 363 if (mUser)
michael@0 364 free(mUser);
michael@0 365 mUser = newUser;
michael@0 366 mPass = newPass;
michael@0 367 mDomain = newDomain;
michael@0 368 return NS_OK;
michael@0 369 }
michael@0 370
michael@0 371 void
michael@0 372 nsHttpAuthIdentity::Clear()
michael@0 373 {
michael@0 374 if (mUser) {
michael@0 375 free(mUser);
michael@0 376 mUser = nullptr;
michael@0 377 mPass = nullptr;
michael@0 378 mDomain = nullptr;
michael@0 379 }
michael@0 380 }
michael@0 381
michael@0 382 bool
michael@0 383 nsHttpAuthIdentity::Equals(const nsHttpAuthIdentity &ident) const
michael@0 384 {
michael@0 385 // we could probably optimize this with a single loop, but why bother?
michael@0 386 return StrEquivalent(mUser, ident.mUser) &&
michael@0 387 StrEquivalent(mPass, ident.mPass) &&
michael@0 388 StrEquivalent(mDomain, ident.mDomain);
michael@0 389 }
michael@0 390
michael@0 391 //-----------------------------------------------------------------------------
michael@0 392 // nsHttpAuthEntry
michael@0 393 //-----------------------------------------------------------------------------
michael@0 394
michael@0 395 nsHttpAuthEntry::~nsHttpAuthEntry()
michael@0 396 {
michael@0 397 if (mRealm)
michael@0 398 free(mRealm);
michael@0 399
michael@0 400 while (mRoot) {
michael@0 401 nsHttpAuthPath *ap = mRoot;
michael@0 402 mRoot = mRoot->mNext;
michael@0 403 free(ap);
michael@0 404 }
michael@0 405 }
michael@0 406
michael@0 407 nsresult
michael@0 408 nsHttpAuthEntry::AddPath(const char *aPath)
michael@0 409 {
michael@0 410 // null path matches empty path
michael@0 411 if (!aPath)
michael@0 412 aPath = "";
michael@0 413
michael@0 414 nsHttpAuthPath *tempPtr = mRoot;
michael@0 415 while (tempPtr) {
michael@0 416 const char *curpath = tempPtr->mPath;
michael@0 417 if (strncmp(aPath, curpath, strlen(curpath)) == 0)
michael@0 418 return NS_OK; // subpath already exists in the list
michael@0 419
michael@0 420 tempPtr = tempPtr->mNext;
michael@0 421
michael@0 422 }
michael@0 423
michael@0 424 //Append the aPath
michael@0 425 nsHttpAuthPath *newAuthPath;
michael@0 426 int newpathLen = strlen(aPath);
michael@0 427 newAuthPath = (nsHttpAuthPath *) malloc(sizeof(nsHttpAuthPath) + newpathLen);
michael@0 428 if (!newAuthPath)
michael@0 429 return NS_ERROR_OUT_OF_MEMORY;
michael@0 430
michael@0 431 memcpy(newAuthPath->mPath, aPath, newpathLen+1);
michael@0 432 newAuthPath->mNext = nullptr;
michael@0 433
michael@0 434 if (!mRoot)
michael@0 435 mRoot = newAuthPath; //first entry
michael@0 436 else
michael@0 437 mTail->mNext = newAuthPath; // Append newAuthPath
michael@0 438
michael@0 439 //update the tail pointer.
michael@0 440 mTail = newAuthPath;
michael@0 441 return NS_OK;
michael@0 442 }
michael@0 443
michael@0 444 nsresult
michael@0 445 nsHttpAuthEntry::Set(const char *path,
michael@0 446 const char *realm,
michael@0 447 const char *creds,
michael@0 448 const char *chall,
michael@0 449 const nsHttpAuthIdentity *ident,
michael@0 450 nsISupports *metadata)
michael@0 451 {
michael@0 452 char *newRealm, *newCreds, *newChall;
michael@0 453
michael@0 454 int realmLen = realm ? strlen(realm) : 0;
michael@0 455 int credsLen = creds ? strlen(creds) : 0;
michael@0 456 int challLen = chall ? strlen(chall) : 0;
michael@0 457
michael@0 458 int len = realmLen + 1 + credsLen + 1 + challLen + 1;
michael@0 459 newRealm = (char *) malloc(len);
michael@0 460 if (!newRealm)
michael@0 461 return NS_ERROR_OUT_OF_MEMORY;
michael@0 462
michael@0 463 if (realm)
michael@0 464 memcpy(newRealm, realm, realmLen);
michael@0 465 newRealm[realmLen] = 0;
michael@0 466
michael@0 467 newCreds = &newRealm[realmLen + 1];
michael@0 468 if (creds)
michael@0 469 memcpy(newCreds, creds, credsLen);
michael@0 470 newCreds[credsLen] = 0;
michael@0 471
michael@0 472 newChall = &newCreds[credsLen + 1];
michael@0 473 if (chall)
michael@0 474 memcpy(newChall, chall, challLen);
michael@0 475 newChall[challLen] = 0;
michael@0 476
michael@0 477 nsresult rv = NS_OK;
michael@0 478 if (ident) {
michael@0 479 rv = mIdent.Set(*ident);
michael@0 480 }
michael@0 481 else if (mIdent.IsEmpty()) {
michael@0 482 // If we are not given an identity and our cached identity has not been
michael@0 483 // initialized yet (so is currently empty), initialize it now by
michael@0 484 // filling it with nulls. We need to do that because consumers expect
michael@0 485 // that mIdent is initialized after this function returns.
michael@0 486 rv = mIdent.Set(nullptr, nullptr, nullptr);
michael@0 487 }
michael@0 488 if (NS_FAILED(rv)) {
michael@0 489 free(newRealm);
michael@0 490 return rv;
michael@0 491 }
michael@0 492
michael@0 493 rv = AddPath(path);
michael@0 494 if (NS_FAILED(rv)) {
michael@0 495 free(newRealm);
michael@0 496 return rv;
michael@0 497 }
michael@0 498
michael@0 499 // wait until the end to clear member vars in case input params
michael@0 500 // reference our members!
michael@0 501 if (mRealm)
michael@0 502 free(mRealm);
michael@0 503
michael@0 504 mRealm = newRealm;
michael@0 505 mCreds = newCreds;
michael@0 506 mChallenge = newChall;
michael@0 507 mMetaData = metadata;
michael@0 508
michael@0 509 return NS_OK;
michael@0 510 }
michael@0 511
michael@0 512 //-----------------------------------------------------------------------------
michael@0 513 // nsHttpAuthNode
michael@0 514 //-----------------------------------------------------------------------------
michael@0 515
michael@0 516 nsHttpAuthNode::nsHttpAuthNode()
michael@0 517 {
michael@0 518 LOG(("Creating nsHttpAuthNode @%x\n", this));
michael@0 519 }
michael@0 520
michael@0 521 nsHttpAuthNode::~nsHttpAuthNode()
michael@0 522 {
michael@0 523 LOG(("Destroying nsHttpAuthNode @%x\n", this));
michael@0 524
michael@0 525 mList.Clear();
michael@0 526 }
michael@0 527
michael@0 528 nsHttpAuthEntry *
michael@0 529 nsHttpAuthNode::LookupEntryByPath(const char *path)
michael@0 530 {
michael@0 531 nsHttpAuthEntry *entry;
michael@0 532
michael@0 533 // null path matches empty path
michael@0 534 if (!path)
michael@0 535 path = "";
michael@0 536
michael@0 537 // look for an entry that either matches or contains this directory.
michael@0 538 // ie. we'll give out credentials if the given directory is a sub-
michael@0 539 // directory of an existing entry.
michael@0 540 for (uint32_t i=0; i<mList.Length(); ++i) {
michael@0 541 entry = mList[i];
michael@0 542 nsHttpAuthPath *authPath = entry->RootPath();
michael@0 543 while (authPath) {
michael@0 544 const char *entryPath = authPath->mPath;
michael@0 545 // proxy auth entries have no path, so require exact match on
michael@0 546 // empty path string.
michael@0 547 if (entryPath[0] == '\0') {
michael@0 548 if (path[0] == '\0')
michael@0 549 return entry;
michael@0 550 }
michael@0 551 else if (strncmp(path, entryPath, strlen(entryPath)) == 0)
michael@0 552 return entry;
michael@0 553
michael@0 554 authPath = authPath->mNext;
michael@0 555 }
michael@0 556 }
michael@0 557 return nullptr;
michael@0 558 }
michael@0 559
michael@0 560 nsHttpAuthEntry *
michael@0 561 nsHttpAuthNode::LookupEntryByRealm(const char *realm)
michael@0 562 {
michael@0 563 nsHttpAuthEntry *entry;
michael@0 564
michael@0 565 // null realm matches empty realm
michael@0 566 if (!realm)
michael@0 567 realm = "";
michael@0 568
michael@0 569 // look for an entry that matches this realm
michael@0 570 uint32_t i;
michael@0 571 for (i=0; i<mList.Length(); ++i) {
michael@0 572 entry = mList[i];
michael@0 573 if (strcmp(realm, entry->Realm()) == 0)
michael@0 574 return entry;
michael@0 575 }
michael@0 576 return nullptr;
michael@0 577 }
michael@0 578
michael@0 579 nsresult
michael@0 580 nsHttpAuthNode::SetAuthEntry(const char *path,
michael@0 581 const char *realm,
michael@0 582 const char *creds,
michael@0 583 const char *challenge,
michael@0 584 const nsHttpAuthIdentity *ident,
michael@0 585 nsISupports *metadata)
michael@0 586 {
michael@0 587 // look for an entry with a matching realm
michael@0 588 nsHttpAuthEntry *entry = LookupEntryByRealm(realm);
michael@0 589 if (!entry) {
michael@0 590 entry = new nsHttpAuthEntry(path, realm, creds, challenge, ident, metadata);
michael@0 591 if (!entry)
michael@0 592 return NS_ERROR_OUT_OF_MEMORY;
michael@0 593 mList.AppendElement(entry);
michael@0 594 }
michael@0 595 else {
michael@0 596 // update the entry...
michael@0 597 entry->Set(path, realm, creds, challenge, ident, metadata);
michael@0 598 }
michael@0 599
michael@0 600 return NS_OK;
michael@0 601 }
michael@0 602
michael@0 603 void
michael@0 604 nsHttpAuthNode::ClearAuthEntry(const char *realm)
michael@0 605 {
michael@0 606 nsHttpAuthEntry *entry = LookupEntryByRealm(realm);
michael@0 607 if (entry) {
michael@0 608 mList.RemoveElement(entry); // double search OK
michael@0 609 }
michael@0 610 }
michael@0 611
michael@0 612 } // namespace mozilla::net
michael@0 613 } // namespace mozilla

mercurial