security/manager/ssl/src/nsCertTree.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 #include "nsCertTree.h"
michael@0 6
michael@0 7 #include "pkix/pkixtypes.h"
michael@0 8 #include "nsNSSComponent.h" // for PIPNSS string bundle calls.
michael@0 9 #include "nsITreeColumns.h"
michael@0 10 #include "nsIX509Cert.h"
michael@0 11 #include "nsIX509CertValidity.h"
michael@0 12 #include "nsIX509CertDB.h"
michael@0 13 #include "nsXPIDLString.h"
michael@0 14 #include "nsReadableUtils.h"
michael@0 15 #include "nsUnicharUtils.h"
michael@0 16 #include "nsNSSCertificate.h"
michael@0 17 #include "nsNSSCertHelper.h"
michael@0 18 #include "nsINSSCertCache.h"
michael@0 19 #include "nsIMutableArray.h"
michael@0 20 #include "nsArrayUtils.h"
michael@0 21 #include "nsISupportsPrimitives.h"
michael@0 22 #include "nsXPCOMCID.h"
michael@0 23 #include "nsTHashtable.h"
michael@0 24 #include "nsHashKeys.h"
michael@0 25
michael@0 26 #include "prlog.h"
michael@0 27
michael@0 28 using namespace mozilla;
michael@0 29
michael@0 30 #ifdef PR_LOGGING
michael@0 31 extern PRLogModuleInfo* gPIPNSSLog;
michael@0 32 #endif
michael@0 33
michael@0 34 static NS_DEFINE_CID(kCertOverrideCID, NS_CERTOVERRIDE_CID);
michael@0 35
michael@0 36 // treeArrayElStr
michael@0 37 //
michael@0 38 // structure used to hold map of tree. Each thread (an organization
michael@0 39 // field from a cert) has an element in the array. The numChildren field
michael@0 40 // stores the number of certs corresponding to that thread.
michael@0 41 struct treeArrayElStr {
michael@0 42 nsString orgName; /* heading for thread */
michael@0 43 bool open; /* toggle open state for thread */
michael@0 44 int32_t certIndex; /* index into cert array for 1st cert */
michael@0 45 int32_t numChildren; /* number of chidren (certs) for thread */
michael@0 46 };
michael@0 47
michael@0 48 CompareCacheHashEntryPtr::CompareCacheHashEntryPtr()
michael@0 49 {
michael@0 50 entry = new CompareCacheHashEntry;
michael@0 51 }
michael@0 52
michael@0 53 CompareCacheHashEntryPtr::~CompareCacheHashEntryPtr()
michael@0 54 {
michael@0 55 delete entry;
michael@0 56 }
michael@0 57
michael@0 58 CompareCacheHashEntry::CompareCacheHashEntry()
michael@0 59 :key(nullptr)
michael@0 60 {
michael@0 61 for (int i = 0; i < max_criterions; ++i) {
michael@0 62 mCritInit[i] = false;
michael@0 63 }
michael@0 64 }
michael@0 65
michael@0 66 static bool
michael@0 67 CompareCacheMatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
michael@0 68 const void *key)
michael@0 69 {
michael@0 70 const CompareCacheHashEntryPtr *entryPtr = static_cast<const CompareCacheHashEntryPtr*>(hdr);
michael@0 71 return entryPtr->entry->key == key;
michael@0 72 }
michael@0 73
michael@0 74 static bool
michael@0 75 CompareCacheInitEntry(PLDHashTable *table, PLDHashEntryHdr *hdr,
michael@0 76 const void *key)
michael@0 77 {
michael@0 78 new (hdr) CompareCacheHashEntryPtr();
michael@0 79 CompareCacheHashEntryPtr *entryPtr = static_cast<CompareCacheHashEntryPtr*>(hdr);
michael@0 80 if (!entryPtr->entry) {
michael@0 81 return false;
michael@0 82 }
michael@0 83 entryPtr->entry->key = (void*)key;
michael@0 84 return true;
michael@0 85 }
michael@0 86
michael@0 87 static void
michael@0 88 CompareCacheClearEntry(PLDHashTable *table, PLDHashEntryHdr *hdr)
michael@0 89 {
michael@0 90 CompareCacheHashEntryPtr *entryPtr = static_cast<CompareCacheHashEntryPtr*>(hdr);
michael@0 91 entryPtr->~CompareCacheHashEntryPtr();
michael@0 92 }
michael@0 93
michael@0 94 static const PLDHashTableOps gMapOps = {
michael@0 95 PL_DHashAllocTable,
michael@0 96 PL_DHashFreeTable,
michael@0 97 PL_DHashVoidPtrKeyStub,
michael@0 98 CompareCacheMatchEntry,
michael@0 99 PL_DHashMoveEntryStub,
michael@0 100 CompareCacheClearEntry,
michael@0 101 PL_DHashFinalizeStub,
michael@0 102 CompareCacheInitEntry
michael@0 103 };
michael@0 104
michael@0 105 NS_IMPL_ISUPPORTS0(nsCertAddonInfo)
michael@0 106 NS_IMPL_ISUPPORTS(nsCertTreeDispInfo, nsICertTreeItem)
michael@0 107
michael@0 108 nsCertTreeDispInfo::nsCertTreeDispInfo()
michael@0 109 :mAddonInfo(nullptr)
michael@0 110 ,mTypeOfEntry(direct_db)
michael@0 111 ,mPort(-1)
michael@0 112 ,mOverrideBits(nsCertOverride::ob_None)
michael@0 113 ,mIsTemporary(true)
michael@0 114 {
michael@0 115 }
michael@0 116
michael@0 117 nsCertTreeDispInfo::nsCertTreeDispInfo(nsCertTreeDispInfo &other)
michael@0 118 {
michael@0 119 mAddonInfo = other.mAddonInfo;
michael@0 120 mTypeOfEntry = other.mTypeOfEntry;
michael@0 121 mAsciiHost = other.mAsciiHost;
michael@0 122 mPort = other.mPort;
michael@0 123 mOverrideBits = other.mOverrideBits;
michael@0 124 mIsTemporary = other.mIsTemporary;
michael@0 125 mCert = other.mCert;
michael@0 126 }
michael@0 127
michael@0 128 nsCertTreeDispInfo::~nsCertTreeDispInfo()
michael@0 129 {
michael@0 130 }
michael@0 131
michael@0 132 NS_IMETHODIMP
michael@0 133 nsCertTreeDispInfo::GetCert(nsIX509Cert **_cert)
michael@0 134 {
michael@0 135 NS_ENSURE_ARG(_cert);
michael@0 136 if (mCert) {
michael@0 137 // we may already have the cert for temporary overrides
michael@0 138 *_cert = mCert;
michael@0 139 NS_IF_ADDREF(*_cert);
michael@0 140 return NS_OK;
michael@0 141 }
michael@0 142 if (mAddonInfo) {
michael@0 143 *_cert = mAddonInfo->mCert.get();
michael@0 144 NS_IF_ADDREF(*_cert);
michael@0 145 }
michael@0 146 else {
michael@0 147 *_cert = nullptr;
michael@0 148 }
michael@0 149 return NS_OK;
michael@0 150 }
michael@0 151
michael@0 152 NS_IMETHODIMP
michael@0 153 nsCertTreeDispInfo::GetHostPort(nsAString &aHostPort)
michael@0 154 {
michael@0 155 nsAutoCString hostPort;
michael@0 156 nsCertOverrideService::GetHostWithPort(mAsciiHost, mPort, hostPort);
michael@0 157 aHostPort = NS_ConvertUTF8toUTF16(hostPort);
michael@0 158 return NS_OK;
michael@0 159 }
michael@0 160
michael@0 161 NS_IMPL_ISUPPORTS(nsCertTree, nsICertTree, nsITreeView)
michael@0 162
michael@0 163 nsCertTree::nsCertTree() : mTreeArray(nullptr)
michael@0 164 {
michael@0 165 static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
michael@0 166
michael@0 167 mCompareCache.ops = nullptr;
michael@0 168 mNSSComponent = do_GetService(kNSSComponentCID);
michael@0 169 mOverrideService = do_GetService("@mozilla.org/security/certoverride;1");
michael@0 170 // Might be a different service if someone is overriding the contract
michael@0 171 nsCOMPtr<nsICertOverrideService> origCertOverride =
michael@0 172 do_GetService(kCertOverrideCID);
michael@0 173 mOriginalOverrideService =
michael@0 174 static_cast<nsCertOverrideService*>(origCertOverride.get());
michael@0 175 mCellText = nullptr;
michael@0 176 }
michael@0 177
michael@0 178 void nsCertTree::ClearCompareHash()
michael@0 179 {
michael@0 180 if (mCompareCache.ops) {
michael@0 181 PL_DHashTableFinish(&mCompareCache);
michael@0 182 mCompareCache.ops = nullptr;
michael@0 183 }
michael@0 184 }
michael@0 185
michael@0 186 nsresult nsCertTree::InitCompareHash()
michael@0 187 {
michael@0 188 ClearCompareHash();
michael@0 189 if (!PL_DHashTableInit(&mCompareCache, &gMapOps, nullptr,
michael@0 190 sizeof(CompareCacheHashEntryPtr), 128, fallible_t())) {
michael@0 191 mCompareCache.ops = nullptr;
michael@0 192 return NS_ERROR_OUT_OF_MEMORY;
michael@0 193 }
michael@0 194 return NS_OK;
michael@0 195 }
michael@0 196
michael@0 197 nsCertTree::~nsCertTree()
michael@0 198 {
michael@0 199 ClearCompareHash();
michael@0 200 delete [] mTreeArray;
michael@0 201 }
michael@0 202
michael@0 203 void
michael@0 204 nsCertTree::FreeCertArray()
michael@0 205 {
michael@0 206 mDispInfo.Clear();
michael@0 207 }
michael@0 208
michael@0 209 CompareCacheHashEntry *
michael@0 210 nsCertTree::getCacheEntry(void *cache, void *aCert)
michael@0 211 {
michael@0 212 PLDHashTable &aCompareCache = *reinterpret_cast<PLDHashTable*>(cache);
michael@0 213 CompareCacheHashEntryPtr *entryPtr =
michael@0 214 static_cast<CompareCacheHashEntryPtr*>
michael@0 215 (PL_DHashTableOperate(&aCompareCache, aCert, PL_DHASH_ADD));
michael@0 216 return entryPtr ? entryPtr->entry : nullptr;
michael@0 217 }
michael@0 218
michael@0 219 void nsCertTree::RemoveCacheEntry(void *key)
michael@0 220 {
michael@0 221 PL_DHashTableOperate(&mCompareCache, key, PL_DHASH_REMOVE);
michael@0 222 }
michael@0 223
michael@0 224 // CountOrganizations
michael@0 225 //
michael@0 226 // Count the number of different organizations encountered in the cert
michael@0 227 // list.
michael@0 228 int32_t
michael@0 229 nsCertTree::CountOrganizations()
michael@0 230 {
michael@0 231 uint32_t i, certCount;
michael@0 232 certCount = mDispInfo.Length();
michael@0 233 if (certCount == 0) return 0;
michael@0 234 nsCOMPtr<nsIX509Cert> orgCert = nullptr;
michael@0 235 nsCertAddonInfo *addonInfo = mDispInfo.ElementAt(0)->mAddonInfo;
michael@0 236 if (addonInfo) {
michael@0 237 orgCert = addonInfo->mCert;
michael@0 238 }
michael@0 239 nsCOMPtr<nsIX509Cert> nextCert = nullptr;
michael@0 240 int32_t orgCount = 1;
michael@0 241 for (i=1; i<certCount; i++) {
michael@0 242 nextCert = nullptr;
michael@0 243 addonInfo = mDispInfo.SafeElementAt(i, nullptr)->mAddonInfo;
michael@0 244 if (addonInfo) {
michael@0 245 nextCert = addonInfo->mCert;
michael@0 246 }
michael@0 247 // XXX we assume issuer org is always criterion 1
michael@0 248 if (CmpBy(&mCompareCache, orgCert, nextCert, sort_IssuerOrg, sort_None, sort_None) != 0) {
michael@0 249 orgCert = nextCert;
michael@0 250 orgCount++;
michael@0 251 }
michael@0 252 }
michael@0 253 return orgCount;
michael@0 254 }
michael@0 255
michael@0 256 // GetThreadDescAtIndex
michael@0 257 //
michael@0 258 // If the row at index is an organization thread, return the collection
michael@0 259 // associated with that thread. Otherwise, return null.
michael@0 260 treeArrayEl *
michael@0 261 nsCertTree::GetThreadDescAtIndex(int32_t index)
michael@0 262 {
michael@0 263 int i, idx=0;
michael@0 264 if (index < 0) return nullptr;
michael@0 265 for (i=0; i<mNumOrgs; i++) {
michael@0 266 if (index == idx) {
michael@0 267 return &mTreeArray[i];
michael@0 268 }
michael@0 269 if (mTreeArray[i].open) {
michael@0 270 idx += mTreeArray[i].numChildren;
michael@0 271 }
michael@0 272 idx++;
michael@0 273 if (idx > index) break;
michael@0 274 }
michael@0 275 return nullptr;
michael@0 276 }
michael@0 277
michael@0 278 // GetCertAtIndex
michael@0 279 //
michael@0 280 // If the row at index is a cert, return that cert. Otherwise, return null.
michael@0 281 already_AddRefed<nsIX509Cert>
michael@0 282 nsCertTree::GetCertAtIndex(int32_t index, int32_t *outAbsoluteCertOffset)
michael@0 283 {
michael@0 284 RefPtr<nsCertTreeDispInfo> certdi(
michael@0 285 GetDispInfoAtIndex(index, outAbsoluteCertOffset));
michael@0 286 if (!certdi)
michael@0 287 return nullptr;
michael@0 288
michael@0 289 nsCOMPtr<nsIX509Cert> ret;
michael@0 290 if (certdi->mCert) {
michael@0 291 ret = certdi->mCert;
michael@0 292 } else if (certdi->mAddonInfo) {
michael@0 293 ret = certdi->mAddonInfo->mCert;
michael@0 294 }
michael@0 295 return ret.forget();
michael@0 296 }
michael@0 297
michael@0 298 // If the row at index is a cert, return that cert. Otherwise, return null.
michael@0 299 TemporaryRef<nsCertTreeDispInfo>
michael@0 300 nsCertTree::GetDispInfoAtIndex(int32_t index,
michael@0 301 int32_t *outAbsoluteCertOffset)
michael@0 302 {
michael@0 303 int i, idx = 0, cIndex = 0, nc;
michael@0 304 if (index < 0) return nullptr;
michael@0 305 // Loop over the threads
michael@0 306 for (i=0; i<mNumOrgs; i++) {
michael@0 307 if (index == idx) return nullptr; // index is for thread
michael@0 308 idx++; // get past the thread
michael@0 309 nc = (mTreeArray[i].open) ? mTreeArray[i].numChildren : 0;
michael@0 310 if (index < idx + nc) { // cert is within range of this thread
michael@0 311 int32_t certIndex = cIndex + index - idx;
michael@0 312 if (outAbsoluteCertOffset)
michael@0 313 *outAbsoluteCertOffset = certIndex;
michael@0 314 RefPtr<nsCertTreeDispInfo> certdi(mDispInfo.SafeElementAt(certIndex,
michael@0 315 nullptr));
michael@0 316 if (certdi) {
michael@0 317 return certdi.forget();
michael@0 318 }
michael@0 319 break;
michael@0 320 }
michael@0 321 if (mTreeArray[i].open)
michael@0 322 idx += mTreeArray[i].numChildren;
michael@0 323 cIndex += mTreeArray[i].numChildren;
michael@0 324 if (idx > index) break;
michael@0 325 }
michael@0 326 return nullptr;
michael@0 327 }
michael@0 328
michael@0 329 nsCertTree::nsCertCompareFunc
michael@0 330 nsCertTree::GetCompareFuncFromCertType(uint32_t aType)
michael@0 331 {
michael@0 332 switch (aType) {
michael@0 333 case nsIX509Cert2::ANY_CERT:
michael@0 334 case nsIX509Cert::USER_CERT:
michael@0 335 return CmpUserCert;
michael@0 336 case nsIX509Cert::CA_CERT:
michael@0 337 return CmpCACert;
michael@0 338 case nsIX509Cert::EMAIL_CERT:
michael@0 339 return CmpEmailCert;
michael@0 340 case nsIX509Cert::SERVER_CERT:
michael@0 341 default:
michael@0 342 return CmpWebSiteCert;
michael@0 343 }
michael@0 344 }
michael@0 345
michael@0 346 struct nsCertAndArrayAndPositionAndCounterAndTracker
michael@0 347 {
michael@0 348 RefPtr<nsCertAddonInfo> certai;
michael@0 349 nsTArray< RefPtr<nsCertTreeDispInfo> > *array;
michael@0 350 int position;
michael@0 351 int counter;
michael@0 352 nsTHashtable<nsCStringHashKey> *tracker;
michael@0 353 };
michael@0 354
michael@0 355 // Used to enumerate host:port overrides that match a stored
michael@0 356 // certificate, creates and adds a display-info-object to the
michael@0 357 // provided array. Increments insert position and entry counter.
michael@0 358 // We remove the given key from the tracker, which is used to
michael@0 359 // track entries that have not yet been handled.
michael@0 360 // The created display-info references the cert, so make a note
michael@0 361 // of that by incrementing the cert usage counter.
michael@0 362 static void
michael@0 363 MatchingCertOverridesCallback(const nsCertOverride &aSettings,
michael@0 364 void *aUserData)
michael@0 365 {
michael@0 366 nsCertAndArrayAndPositionAndCounterAndTracker *cap =
michael@0 367 (nsCertAndArrayAndPositionAndCounterAndTracker*)aUserData;
michael@0 368 if (!cap)
michael@0 369 return;
michael@0 370
michael@0 371 nsCertTreeDispInfo *certdi = new nsCertTreeDispInfo;
michael@0 372 if (certdi) {
michael@0 373 if (cap->certai)
michael@0 374 cap->certai->mUsageCount++;
michael@0 375 certdi->mAddonInfo = cap->certai;
michael@0 376 certdi->mTypeOfEntry = nsCertTreeDispInfo::host_port_override;
michael@0 377 certdi->mAsciiHost = aSettings.mAsciiHost;
michael@0 378 certdi->mPort = aSettings.mPort;
michael@0 379 certdi->mOverrideBits = aSettings.mOverrideBits;
michael@0 380 certdi->mIsTemporary = aSettings.mIsTemporary;
michael@0 381 certdi->mCert = aSettings.mCert;
michael@0 382 cap->array->InsertElementAt(cap->position, certdi);
michael@0 383 cap->position++;
michael@0 384 cap->counter++;
michael@0 385 }
michael@0 386
michael@0 387 // this entry is now associated to a displayed cert, remove
michael@0 388 // it from the list of remaining entries
michael@0 389 nsAutoCString hostPort;
michael@0 390 nsCertOverrideService::GetHostWithPort(aSettings.mAsciiHost, aSettings.mPort, hostPort);
michael@0 391 cap->tracker->RemoveEntry(hostPort);
michael@0 392 }
michael@0 393
michael@0 394 // Used to collect a list of the (unique) host:port keys
michael@0 395 // for all stored overrides.
michael@0 396 static void
michael@0 397 CollectAllHostPortOverridesCallback(const nsCertOverride &aSettings,
michael@0 398 void *aUserData)
michael@0 399 {
michael@0 400 nsTHashtable<nsCStringHashKey> *collectorTable =
michael@0 401 (nsTHashtable<nsCStringHashKey> *)aUserData;
michael@0 402 if (!collectorTable)
michael@0 403 return;
michael@0 404
michael@0 405 nsAutoCString hostPort;
michael@0 406 nsCertOverrideService::GetHostWithPort(aSettings.mAsciiHost, aSettings.mPort, hostPort);
michael@0 407 collectorTable->PutEntry(hostPort);
michael@0 408 }
michael@0 409
michael@0 410 struct nsArrayAndPositionAndCounterAndTracker
michael@0 411 {
michael@0 412 nsTArray< RefPtr<nsCertTreeDispInfo> > *array;
michael@0 413 int position;
michael@0 414 int counter;
michael@0 415 nsTHashtable<nsCStringHashKey> *tracker;
michael@0 416 };
michael@0 417
michael@0 418 // Used when enumerating the stored host:port overrides where
michael@0 419 // no associated certificate was found in the NSS database.
michael@0 420 static void
michael@0 421 AddRemaningHostPortOverridesCallback(const nsCertOverride &aSettings,
michael@0 422 void *aUserData)
michael@0 423 {
michael@0 424 nsArrayAndPositionAndCounterAndTracker *cap =
michael@0 425 (nsArrayAndPositionAndCounterAndTracker*)aUserData;
michael@0 426 if (!cap)
michael@0 427 return;
michael@0 428
michael@0 429 nsAutoCString hostPort;
michael@0 430 nsCertOverrideService::GetHostWithPort(aSettings.mAsciiHost, aSettings.mPort, hostPort);
michael@0 431 if (!cap->tracker->GetEntry(hostPort))
michael@0 432 return;
michael@0 433
michael@0 434 // This entry is not associated to any stored cert,
michael@0 435 // so we still need to display it.
michael@0 436
michael@0 437 nsCertTreeDispInfo *certdi = new nsCertTreeDispInfo;
michael@0 438 if (certdi) {
michael@0 439 certdi->mAddonInfo = nullptr;
michael@0 440 certdi->mTypeOfEntry = nsCertTreeDispInfo::host_port_override;
michael@0 441 certdi->mAsciiHost = aSettings.mAsciiHost;
michael@0 442 certdi->mPort = aSettings.mPort;
michael@0 443 certdi->mOverrideBits = aSettings.mOverrideBits;
michael@0 444 certdi->mIsTemporary = aSettings.mIsTemporary;
michael@0 445 certdi->mCert = aSettings.mCert;
michael@0 446 cap->array->InsertElementAt(cap->position, certdi);
michael@0 447 cap->position++;
michael@0 448 cap->counter++;
michael@0 449 }
michael@0 450 }
michael@0 451
michael@0 452 nsresult
michael@0 453 nsCertTree::GetCertsByTypeFromCertList(CERTCertList *aCertList,
michael@0 454 uint32_t aWantedType,
michael@0 455 nsCertCompareFunc aCertCmpFn,
michael@0 456 void *aCertCmpFnArg)
michael@0 457 {
michael@0 458 PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("GetCertsByTypeFromCertList"));
michael@0 459 if (!aCertList)
michael@0 460 return NS_ERROR_FAILURE;
michael@0 461
michael@0 462 if (!mOriginalOverrideService)
michael@0 463 return NS_ERROR_FAILURE;
michael@0 464
michael@0 465 nsTHashtable<nsCStringHashKey> allHostPortOverrideKeys;
michael@0 466
michael@0 467 if (aWantedType == nsIX509Cert::SERVER_CERT) {
michael@0 468 mOriginalOverrideService->
michael@0 469 EnumerateCertOverrides(nullptr,
michael@0 470 CollectAllHostPortOverridesCallback,
michael@0 471 &allHostPortOverrideKeys);
michael@0 472 }
michael@0 473
michael@0 474 CERTCertListNode *node;
michael@0 475 int count = 0;
michael@0 476 for (node = CERT_LIST_HEAD(aCertList);
michael@0 477 !CERT_LIST_END(node, aCertList);
michael@0 478 node = CERT_LIST_NEXT(node)) {
michael@0 479
michael@0 480 bool wantThisCert = (aWantedType == nsIX509Cert2::ANY_CERT);
michael@0 481 bool wantThisCertIfNoOverrides = false;
michael@0 482 bool wantThisCertIfHaveOverrides = false;
michael@0 483 bool addOverrides = false;
michael@0 484
michael@0 485 if (!wantThisCert) {
michael@0 486 uint32_t thisCertType = getCertType(node->cert);
michael@0 487
michael@0 488 // The output from getCertType is a "guess", which can be wrong.
michael@0 489 // The guess is based on stored trust flags, but for the host:port
michael@0 490 // overrides, we are storing certs without any trust flags associated.
michael@0 491 // So we must check whether the cert really belongs to the
michael@0 492 // server, email or unknown tab. We will lookup the cert in the override
michael@0 493 // list to come to the decision. Unfortunately, the lookup in the
michael@0 494 // override list is quite expensive. Therefore we are using this
michael@0 495 // lengthy if/else statement to minimize
michael@0 496 // the number of override-list-lookups.
michael@0 497
michael@0 498 if (aWantedType == nsIX509Cert::SERVER_CERT
michael@0 499 && thisCertType == nsIX509Cert::UNKNOWN_CERT) {
michael@0 500 // This unknown cert was stored without trust
michael@0 501 // Are there host:port based overrides stored?
michael@0 502 // If yes, display them.
michael@0 503 addOverrides = true;
michael@0 504 }
michael@0 505 else
michael@0 506 if (aWantedType == nsIX509Cert::UNKNOWN_CERT
michael@0 507 && thisCertType == nsIX509Cert::UNKNOWN_CERT) {
michael@0 508 // This unknown cert was stored without trust.
michael@0 509 // If there are associated overrides, do not show as unknown.
michael@0 510 // If there are no associated overrides, display as unknown.
michael@0 511 wantThisCertIfNoOverrides = true;
michael@0 512 }
michael@0 513 else
michael@0 514 if (aWantedType == nsIX509Cert::SERVER_CERT
michael@0 515 && thisCertType == nsIX509Cert::SERVER_CERT) {
michael@0 516 // This server cert is explicitly marked as a web site peer,
michael@0 517 // with or without trust, but editable, so show it
michael@0 518 wantThisCert = true;
michael@0 519 // Are there host:port based overrides stored?
michael@0 520 // If yes, display them.
michael@0 521 addOverrides = true;
michael@0 522 }
michael@0 523 else
michael@0 524 if (aWantedType == nsIX509Cert::SERVER_CERT
michael@0 525 && thisCertType == nsIX509Cert::EMAIL_CERT) {
michael@0 526 // This cert might have been categorized as an email cert
michael@0 527 // because it carries an email address. But is it really one?
michael@0 528 // Our cert categorization is uncertain when it comes to
michael@0 529 // distinguish between email certs and web site certs.
michael@0 530 // So, let's see if we have an override for that cert
michael@0 531 // and if there is, conclude it's really a web site cert.
michael@0 532 addOverrides = true;
michael@0 533 }
michael@0 534 else
michael@0 535 if (aWantedType == nsIX509Cert::EMAIL_CERT
michael@0 536 && thisCertType == nsIX509Cert::EMAIL_CERT) {
michael@0 537 // This cert might have been categorized as an email cert
michael@0 538 // because it carries an email address. But is it really one?
michael@0 539 // Our cert categorization is uncertain when it comes to
michael@0 540 // distinguish between email certs and web site certs.
michael@0 541 // So, let's see if we have an override for that cert
michael@0 542 // and if there is, conclude it's really a web site cert.
michael@0 543 wantThisCertIfNoOverrides = true;
michael@0 544 }
michael@0 545 else
michael@0 546 if (thisCertType == aWantedType) {
michael@0 547 wantThisCert = true;
michael@0 548 }
michael@0 549 }
michael@0 550
michael@0 551 nsCOMPtr<nsIX509Cert> pipCert = nsNSSCertificate::Create(node->cert);
michael@0 552 if (!pipCert)
michael@0 553 return NS_ERROR_OUT_OF_MEMORY;
michael@0 554
michael@0 555 if (wantThisCertIfNoOverrides || wantThisCertIfHaveOverrides) {
michael@0 556 uint32_t ocount = 0;
michael@0 557 nsresult rv =
michael@0 558 mOverrideService->IsCertUsedForOverrides(pipCert,
michael@0 559 true, // we want temporaries
michael@0 560 true, // we want permanents
michael@0 561 &ocount);
michael@0 562 if (wantThisCertIfNoOverrides) {
michael@0 563 if (NS_FAILED(rv) || ocount == 0) {
michael@0 564 // no overrides for this cert
michael@0 565 wantThisCert = true;
michael@0 566 }
michael@0 567 }
michael@0 568
michael@0 569 if (wantThisCertIfHaveOverrides) {
michael@0 570 if (NS_SUCCEEDED(rv) && ocount > 0) {
michael@0 571 // there are overrides for this cert
michael@0 572 wantThisCert = true;
michael@0 573 }
michael@0 574 }
michael@0 575 }
michael@0 576
michael@0 577 RefPtr<nsCertAddonInfo> certai(new nsCertAddonInfo);
michael@0 578 certai->mCert = pipCert;
michael@0 579 certai->mUsageCount = 0;
michael@0 580
michael@0 581 if (wantThisCert || addOverrides) {
michael@0 582 int InsertPosition = 0;
michael@0 583 for (; InsertPosition < count; ++InsertPosition) {
michael@0 584 nsCOMPtr<nsIX509Cert> cert = nullptr;
michael@0 585 RefPtr<nsCertTreeDispInfo> elem(
michael@0 586 mDispInfo.SafeElementAt(InsertPosition, nullptr));
michael@0 587 if (elem && elem->mAddonInfo) {
michael@0 588 cert = elem->mAddonInfo->mCert;
michael@0 589 }
michael@0 590 if ((*aCertCmpFn)(aCertCmpFnArg, pipCert, cert) < 0) {
michael@0 591 break;
michael@0 592 }
michael@0 593 }
michael@0 594 if (wantThisCert) {
michael@0 595 nsCertTreeDispInfo *certdi = new nsCertTreeDispInfo;
michael@0 596 certdi->mAddonInfo = certai;
michael@0 597 certai->mUsageCount++;
michael@0 598 certdi->mTypeOfEntry = nsCertTreeDispInfo::direct_db;
michael@0 599 // not necessary: certdi->mAsciiHost.Clear(); certdi->mPort = -1;
michael@0 600 certdi->mOverrideBits = nsCertOverride::ob_None;
michael@0 601 certdi->mIsTemporary = false;
michael@0 602 mDispInfo.InsertElementAt(InsertPosition, certdi);
michael@0 603 ++count;
michael@0 604 ++InsertPosition;
michael@0 605 }
michael@0 606 if (addOverrides) {
michael@0 607 nsCertAndArrayAndPositionAndCounterAndTracker cap;
michael@0 608 cap.certai = certai;
michael@0 609 cap.array = &mDispInfo;
michael@0 610 cap.position = InsertPosition;
michael@0 611 cap.counter = 0;
michael@0 612 cap.tracker = &allHostPortOverrideKeys;
michael@0 613
michael@0 614 mOriginalOverrideService->
michael@0 615 EnumerateCertOverrides(pipCert, MatchingCertOverridesCallback, &cap);
michael@0 616 count += cap.counter;
michael@0 617 }
michael@0 618 }
michael@0 619 }
michael@0 620
michael@0 621 if (aWantedType == nsIX509Cert::SERVER_CERT) {
michael@0 622 nsArrayAndPositionAndCounterAndTracker cap;
michael@0 623 cap.array = &mDispInfo;
michael@0 624 cap.position = 0;
michael@0 625 cap.counter = 0;
michael@0 626 cap.tracker = &allHostPortOverrideKeys;
michael@0 627 mOriginalOverrideService->
michael@0 628 EnumerateCertOverrides(nullptr, AddRemaningHostPortOverridesCallback, &cap);
michael@0 629 }
michael@0 630
michael@0 631 return NS_OK;
michael@0 632 }
michael@0 633
michael@0 634 nsresult
michael@0 635 nsCertTree::GetCertsByType(uint32_t aType,
michael@0 636 nsCertCompareFunc aCertCmpFn,
michael@0 637 void *aCertCmpFnArg)
michael@0 638 {
michael@0 639 nsNSSShutDownPreventionLock locker;
michael@0 640 nsCOMPtr<nsIInterfaceRequestor> cxt = new PipUIContext();
michael@0 641 mozilla::pkix::ScopedCERTCertList certList(
michael@0 642 PK11_ListCerts(PK11CertListUnique, cxt));
michael@0 643 return GetCertsByTypeFromCertList(certList.get(), aType, aCertCmpFn,
michael@0 644 aCertCmpFnArg);
michael@0 645 }
michael@0 646
michael@0 647 nsresult
michael@0 648 nsCertTree::GetCertsByTypeFromCache(nsINSSCertCache *aCache,
michael@0 649 uint32_t aType,
michael@0 650 nsCertCompareFunc aCertCmpFn,
michael@0 651 void *aCertCmpFnArg)
michael@0 652 {
michael@0 653 NS_ENSURE_ARG_POINTER(aCache);
michael@0 654 CERTCertList *certList = reinterpret_cast<CERTCertList*>(aCache->GetCachedCerts());
michael@0 655 if (!certList)
michael@0 656 return NS_ERROR_FAILURE;
michael@0 657 return GetCertsByTypeFromCertList(certList, aType, aCertCmpFn, aCertCmpFnArg);
michael@0 658 }
michael@0 659
michael@0 660 // LoadCerts
michael@0 661 //
michael@0 662 // Load all of the certificates in the DB for this type. Sort them
michael@0 663 // by token, organization, then common name.
michael@0 664 NS_IMETHODIMP
michael@0 665 nsCertTree::LoadCertsFromCache(nsINSSCertCache *aCache, uint32_t aType)
michael@0 666 {
michael@0 667 if (mTreeArray) {
michael@0 668 FreeCertArray();
michael@0 669 delete [] mTreeArray;
michael@0 670 mTreeArray = nullptr;
michael@0 671 mNumRows = 0;
michael@0 672 }
michael@0 673 nsresult rv = InitCompareHash();
michael@0 674 if (NS_FAILED(rv)) return rv;
michael@0 675
michael@0 676 rv = GetCertsByTypeFromCache(aCache, aType,
michael@0 677 GetCompareFuncFromCertType(aType), &mCompareCache);
michael@0 678 if (NS_FAILED(rv)) return rv;
michael@0 679 return UpdateUIContents();
michael@0 680 }
michael@0 681
michael@0 682 NS_IMETHODIMP
michael@0 683 nsCertTree::LoadCerts(uint32_t aType)
michael@0 684 {
michael@0 685 if (mTreeArray) {
michael@0 686 FreeCertArray();
michael@0 687 delete [] mTreeArray;
michael@0 688 mTreeArray = nullptr;
michael@0 689 mNumRows = 0;
michael@0 690 }
michael@0 691 nsresult rv = InitCompareHash();
michael@0 692 if (NS_FAILED(rv)) return rv;
michael@0 693
michael@0 694 rv = GetCertsByType(aType,
michael@0 695 GetCompareFuncFromCertType(aType), &mCompareCache);
michael@0 696 if (NS_FAILED(rv)) return rv;
michael@0 697 return UpdateUIContents();
michael@0 698 }
michael@0 699
michael@0 700 nsresult
michael@0 701 nsCertTree::UpdateUIContents()
michael@0 702 {
michael@0 703 uint32_t count = mDispInfo.Length();
michael@0 704 mNumOrgs = CountOrganizations();
michael@0 705 mTreeArray = new treeArrayEl[mNumOrgs];
michael@0 706
michael@0 707 mCellText = do_CreateInstance(NS_ARRAY_CONTRACTID);
michael@0 708
michael@0 709 if (count) {
michael@0 710 uint32_t j = 0;
michael@0 711 nsCOMPtr<nsIX509Cert> orgCert = nullptr;
michael@0 712 nsCertAddonInfo *addonInfo = mDispInfo.ElementAt(j)->mAddonInfo;
michael@0 713 if (addonInfo) {
michael@0 714 orgCert = addonInfo->mCert;
michael@0 715 }
michael@0 716 for (int32_t i=0; i<mNumOrgs; i++) {
michael@0 717 nsString &orgNameRef = mTreeArray[i].orgName;
michael@0 718 if (!orgCert) {
michael@0 719 mNSSComponent->GetPIPNSSBundleString("CertOrgUnknown", orgNameRef);
michael@0 720 }
michael@0 721 else {
michael@0 722 orgCert->GetIssuerOrganization(orgNameRef);
michael@0 723 if (orgNameRef.IsEmpty())
michael@0 724 orgCert->GetCommonName(orgNameRef);
michael@0 725 }
michael@0 726 mTreeArray[i].open = true;
michael@0 727 mTreeArray[i].certIndex = j;
michael@0 728 mTreeArray[i].numChildren = 1;
michael@0 729 if (++j >= count) break;
michael@0 730 nsCOMPtr<nsIX509Cert> nextCert = nullptr;
michael@0 731 nsCertAddonInfo *addonInfo = mDispInfo.SafeElementAt(j, nullptr)->mAddonInfo;
michael@0 732 if (addonInfo) {
michael@0 733 nextCert = addonInfo->mCert;
michael@0 734 }
michael@0 735 while (0 == CmpBy(&mCompareCache, orgCert, nextCert, sort_IssuerOrg, sort_None, sort_None)) {
michael@0 736 mTreeArray[i].numChildren++;
michael@0 737 if (++j >= count) break;
michael@0 738 nextCert = nullptr;
michael@0 739 addonInfo = mDispInfo.SafeElementAt(j, nullptr)->mAddonInfo;
michael@0 740 if (addonInfo) {
michael@0 741 nextCert = addonInfo->mCert;
michael@0 742 }
michael@0 743 }
michael@0 744 orgCert = nextCert;
michael@0 745 }
michael@0 746 }
michael@0 747 if (mTree) {
michael@0 748 mTree->BeginUpdateBatch();
michael@0 749 mTree->RowCountChanged(0, -mNumRows);
michael@0 750 }
michael@0 751 mNumRows = count + mNumOrgs;
michael@0 752 if (mTree)
michael@0 753 mTree->EndUpdateBatch();
michael@0 754 return NS_OK;
michael@0 755 }
michael@0 756
michael@0 757 NS_IMETHODIMP
michael@0 758 nsCertTree::DeleteEntryObject(uint32_t index)
michael@0 759 {
michael@0 760 if (!mTreeArray) {
michael@0 761 return NS_ERROR_FAILURE;
michael@0 762 }
michael@0 763
michael@0 764 nsCOMPtr<nsIX509CertDB> certdb =
michael@0 765 do_GetService("@mozilla.org/security/x509certdb;1");
michael@0 766 if (!certdb) {
michael@0 767 return NS_ERROR_FAILURE;
michael@0 768 }
michael@0 769
michael@0 770 int i;
michael@0 771 uint32_t idx = 0, cIndex = 0, nc;
michael@0 772 // Loop over the threads
michael@0 773 for (i=0; i<mNumOrgs; i++) {
michael@0 774 if (index == idx)
michael@0 775 return NS_OK; // index is for thread
michael@0 776 idx++; // get past the thread
michael@0 777 nc = (mTreeArray[i].open) ? mTreeArray[i].numChildren : 0;
michael@0 778 if (index < idx + nc) { // cert is within range of this thread
michael@0 779 int32_t certIndex = cIndex + index - idx;
michael@0 780
michael@0 781 bool canRemoveEntry = false;
michael@0 782 RefPtr<nsCertTreeDispInfo> certdi(mDispInfo.SafeElementAt(certIndex,
michael@0 783 nullptr));
michael@0 784
michael@0 785 // We will remove the element from the visual tree.
michael@0 786 // Only if we have a certdi, then we can check for additional actions.
michael@0 787 nsCOMPtr<nsIX509Cert> cert = nullptr;
michael@0 788 if (certdi) {
michael@0 789 if (certdi->mAddonInfo) {
michael@0 790 cert = certdi->mAddonInfo->mCert;
michael@0 791 }
michael@0 792 nsCertAddonInfo *addonInfo = certdi->mAddonInfo ? certdi->mAddonInfo : nullptr;
michael@0 793 if (certdi->mTypeOfEntry == nsCertTreeDispInfo::host_port_override) {
michael@0 794 mOverrideService->ClearValidityOverride(certdi->mAsciiHost, certdi->mPort);
michael@0 795 if (addonInfo) {
michael@0 796 addonInfo->mUsageCount--;
michael@0 797 if (addonInfo->mUsageCount == 0) {
michael@0 798 // The certificate stored in the database is no longer
michael@0 799 // referenced by any other object displayed.
michael@0 800 // That means we no longer need to keep it around
michael@0 801 // and really can remove it.
michael@0 802 canRemoveEntry = true;
michael@0 803 }
michael@0 804 }
michael@0 805 }
michael@0 806 else {
michael@0 807 if (addonInfo && addonInfo->mUsageCount > 1) {
michael@0 808 // user is trying to delete a perm trusted cert,
michael@0 809 // although there are still overrides stored,
michael@0 810 // so, we keep the cert, but remove the trust
michael@0 811
michael@0 812 mozilla::pkix::ScopedCERTCertificate nsscert;
michael@0 813
michael@0 814 nsCOMPtr<nsIX509Cert2> cert2 = do_QueryInterface(cert);
michael@0 815 if (cert2) {
michael@0 816 nsscert = cert2->GetCert();
michael@0 817 }
michael@0 818
michael@0 819 if (nsscert) {
michael@0 820 CERTCertTrust trust;
michael@0 821 memset((void*)&trust, 0, sizeof(trust));
michael@0 822
michael@0 823 SECStatus srv = CERT_DecodeTrustString(&trust, ""); // no override
michael@0 824 if (srv == SECSuccess) {
michael@0 825 CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), nsscert.get(),
michael@0 826 &trust);
michael@0 827 }
michael@0 828 }
michael@0 829 }
michael@0 830 else {
michael@0 831 canRemoveEntry = true;
michael@0 832 }
michael@0 833 }
michael@0 834 }
michael@0 835
michael@0 836 mDispInfo.RemoveElementAt(certIndex);
michael@0 837
michael@0 838 if (canRemoveEntry) {
michael@0 839 RemoveCacheEntry(cert);
michael@0 840 certdb->DeleteCertificate(cert);
michael@0 841 }
michael@0 842
michael@0 843 delete [] mTreeArray;
michael@0 844 mTreeArray = nullptr;
michael@0 845 return UpdateUIContents();
michael@0 846 }
michael@0 847 if (mTreeArray[i].open)
michael@0 848 idx += mTreeArray[i].numChildren;
michael@0 849 cIndex += mTreeArray[i].numChildren;
michael@0 850 if (idx > index)
michael@0 851 break;
michael@0 852 }
michael@0 853 return NS_ERROR_FAILURE;
michael@0 854 }
michael@0 855
michael@0 856 //////////////////////////////////////////////////////////////////////////////
michael@0 857 //
michael@0 858 // Begin nsITreeView methods
michael@0 859 //
michael@0 860 /////////////////////////////////////////////////////////////////////////////
michael@0 861
michael@0 862 /* nsIX509Cert getCert(in unsigned long index); */
michael@0 863 NS_IMETHODIMP
michael@0 864 nsCertTree::GetCert(uint32_t aIndex, nsIX509Cert **_cert)
michael@0 865 {
michael@0 866 NS_ENSURE_ARG(_cert);
michael@0 867 *_cert = GetCertAtIndex(aIndex).take();
michael@0 868 return NS_OK;
michael@0 869 }
michael@0 870
michael@0 871 NS_IMETHODIMP
michael@0 872 nsCertTree::GetTreeItem(uint32_t aIndex, nsICertTreeItem **_treeitem)
michael@0 873 {
michael@0 874 NS_ENSURE_ARG(_treeitem);
michael@0 875
michael@0 876 RefPtr<nsCertTreeDispInfo> certdi(GetDispInfoAtIndex(aIndex));
michael@0 877 if (!certdi)
michael@0 878 return NS_ERROR_FAILURE;
michael@0 879
michael@0 880 *_treeitem = certdi;
michael@0 881 NS_IF_ADDREF(*_treeitem);
michael@0 882 return NS_OK;
michael@0 883 }
michael@0 884
michael@0 885 NS_IMETHODIMP
michael@0 886 nsCertTree::IsHostPortOverride(uint32_t aIndex, bool *_retval)
michael@0 887 {
michael@0 888 NS_ENSURE_ARG(_retval);
michael@0 889
michael@0 890 RefPtr<nsCertTreeDispInfo> certdi(GetDispInfoAtIndex(aIndex));
michael@0 891 if (!certdi)
michael@0 892 return NS_ERROR_FAILURE;
michael@0 893
michael@0 894 *_retval = (certdi->mTypeOfEntry == nsCertTreeDispInfo::host_port_override);
michael@0 895 return NS_OK;
michael@0 896 }
michael@0 897
michael@0 898 /* readonly attribute long rowCount; */
michael@0 899 NS_IMETHODIMP
michael@0 900 nsCertTree::GetRowCount(int32_t *aRowCount)
michael@0 901 {
michael@0 902 if (!mTreeArray)
michael@0 903 return NS_ERROR_NOT_INITIALIZED;
michael@0 904 uint32_t count = 0;
michael@0 905 for (int32_t i=0; i<mNumOrgs; i++) {
michael@0 906 if (mTreeArray[i].open) {
michael@0 907 count += mTreeArray[i].numChildren;
michael@0 908 }
michael@0 909 count++;
michael@0 910 }
michael@0 911 *aRowCount = count;
michael@0 912 return NS_OK;
michael@0 913 }
michael@0 914
michael@0 915 /* attribute nsITreeSelection selection; */
michael@0 916 NS_IMETHODIMP
michael@0 917 nsCertTree::GetSelection(nsITreeSelection * *aSelection)
michael@0 918 {
michael@0 919 *aSelection = mSelection;
michael@0 920 NS_IF_ADDREF(*aSelection);
michael@0 921 return NS_OK;
michael@0 922 }
michael@0 923
michael@0 924 NS_IMETHODIMP
michael@0 925 nsCertTree::SetSelection(nsITreeSelection * aSelection)
michael@0 926 {
michael@0 927 mSelection = aSelection;
michael@0 928 return NS_OK;
michael@0 929 }
michael@0 930
michael@0 931 NS_IMETHODIMP
michael@0 932 nsCertTree::GetRowProperties(int32_t index, nsAString& aProps)
michael@0 933 {
michael@0 934 return NS_OK;
michael@0 935 }
michael@0 936
michael@0 937 NS_IMETHODIMP
michael@0 938 nsCertTree::GetCellProperties(int32_t row, nsITreeColumn* col,
michael@0 939 nsAString& aProps)
michael@0 940 {
michael@0 941 return NS_OK;
michael@0 942 }
michael@0 943
michael@0 944 NS_IMETHODIMP
michael@0 945 nsCertTree::GetColumnProperties(nsITreeColumn* col, nsAString& aProps)
michael@0 946 {
michael@0 947 return NS_OK;
michael@0 948 }
michael@0 949 /* boolean isContainer (in long index); */
michael@0 950 NS_IMETHODIMP
michael@0 951 nsCertTree::IsContainer(int32_t index, bool *_retval)
michael@0 952 {
michael@0 953 if (!mTreeArray)
michael@0 954 return NS_ERROR_NOT_INITIALIZED;
michael@0 955 treeArrayEl *el = GetThreadDescAtIndex(index);
michael@0 956 if (el) {
michael@0 957 *_retval = true;
michael@0 958 } else {
michael@0 959 *_retval = false;
michael@0 960 }
michael@0 961 return NS_OK;
michael@0 962 }
michael@0 963
michael@0 964 /* boolean isContainerOpen (in long index); */
michael@0 965 NS_IMETHODIMP
michael@0 966 nsCertTree::IsContainerOpen(int32_t index, bool *_retval)
michael@0 967 {
michael@0 968 if (!mTreeArray)
michael@0 969 return NS_ERROR_NOT_INITIALIZED;
michael@0 970 treeArrayEl *el = GetThreadDescAtIndex(index);
michael@0 971 if (el && el->open) {
michael@0 972 *_retval = true;
michael@0 973 } else {
michael@0 974 *_retval = false;
michael@0 975 }
michael@0 976 return NS_OK;
michael@0 977 }
michael@0 978
michael@0 979 /* boolean isContainerEmpty (in long index); */
michael@0 980 NS_IMETHODIMP
michael@0 981 nsCertTree::IsContainerEmpty(int32_t index, bool *_retval)
michael@0 982 {
michael@0 983 *_retval = !mTreeArray;
michael@0 984 return NS_OK;
michael@0 985 }
michael@0 986
michael@0 987 /* boolean isSeparator (in long index); */
michael@0 988 NS_IMETHODIMP
michael@0 989 nsCertTree::IsSeparator(int32_t index, bool *_retval)
michael@0 990 {
michael@0 991 *_retval = false;
michael@0 992 return NS_OK;
michael@0 993 }
michael@0 994
michael@0 995 /* long getParentIndex (in long rowIndex); */
michael@0 996 NS_IMETHODIMP
michael@0 997 nsCertTree::GetParentIndex(int32_t rowIndex, int32_t *_retval)
michael@0 998 {
michael@0 999 if (!mTreeArray)
michael@0 1000 return NS_ERROR_NOT_INITIALIZED;
michael@0 1001 int i, idx = 0;
michael@0 1002 for (i = 0; i < mNumOrgs && idx < rowIndex; i++, idx++) {
michael@0 1003 if (mTreeArray[i].open) {
michael@0 1004 if (rowIndex <= idx + mTreeArray[i].numChildren) {
michael@0 1005 *_retval = idx;
michael@0 1006 return NS_OK;
michael@0 1007 }
michael@0 1008 idx += mTreeArray[i].numChildren;
michael@0 1009 }
michael@0 1010 }
michael@0 1011 *_retval = -1;
michael@0 1012 return NS_OK;
michael@0 1013 }
michael@0 1014
michael@0 1015 /* boolean hasNextSibling (in long rowIndex, in long afterIndex); */
michael@0 1016 NS_IMETHODIMP
michael@0 1017 nsCertTree::HasNextSibling(int32_t rowIndex, int32_t afterIndex,
michael@0 1018 bool *_retval)
michael@0 1019 {
michael@0 1020 if (!mTreeArray)
michael@0 1021 return NS_ERROR_NOT_INITIALIZED;
michael@0 1022
michael@0 1023 int i, idx = 0;
michael@0 1024 for (i = 0; i < mNumOrgs && idx <= rowIndex; i++, idx++) {
michael@0 1025 if (mTreeArray[i].open) {
michael@0 1026 idx += mTreeArray[i].numChildren;
michael@0 1027 if (afterIndex <= idx) {
michael@0 1028 *_retval = afterIndex < idx;
michael@0 1029 return NS_OK;
michael@0 1030 }
michael@0 1031 }
michael@0 1032 }
michael@0 1033 *_retval = false;
michael@0 1034 return NS_OK;
michael@0 1035 }
michael@0 1036
michael@0 1037 /* long getLevel (in long index); */
michael@0 1038 NS_IMETHODIMP
michael@0 1039 nsCertTree::GetLevel(int32_t index, int32_t *_retval)
michael@0 1040 {
michael@0 1041 if (!mTreeArray)
michael@0 1042 return NS_ERROR_NOT_INITIALIZED;
michael@0 1043 treeArrayEl *el = GetThreadDescAtIndex(index);
michael@0 1044 if (el) {
michael@0 1045 *_retval = 0;
michael@0 1046 } else {
michael@0 1047 *_retval = 1;
michael@0 1048 }
michael@0 1049 return NS_OK;
michael@0 1050 }
michael@0 1051
michael@0 1052 /* Astring getImageSrc (in long row, in nsITreeColumn col); */
michael@0 1053 NS_IMETHODIMP
michael@0 1054 nsCertTree::GetImageSrc(int32_t row, nsITreeColumn* col,
michael@0 1055 nsAString& _retval)
michael@0 1056 {
michael@0 1057 _retval.Truncate();
michael@0 1058 return NS_OK;
michael@0 1059 }
michael@0 1060
michael@0 1061 /* long getProgressMode (in long row, in nsITreeColumn col); */
michael@0 1062 NS_IMETHODIMP
michael@0 1063 nsCertTree::GetProgressMode(int32_t row, nsITreeColumn* col, int32_t* _retval)
michael@0 1064 {
michael@0 1065 return NS_OK;
michael@0 1066 }
michael@0 1067
michael@0 1068 /* Astring getCellValue (in long row, in nsITreeColumn col); */
michael@0 1069 NS_IMETHODIMP
michael@0 1070 nsCertTree::GetCellValue(int32_t row, nsITreeColumn* col,
michael@0 1071 nsAString& _retval)
michael@0 1072 {
michael@0 1073 _retval.Truncate();
michael@0 1074 return NS_OK;
michael@0 1075 }
michael@0 1076
michael@0 1077 /* Astring getCellText (in long row, in nsITreeColumn col); */
michael@0 1078 NS_IMETHODIMP
michael@0 1079 nsCertTree::GetCellText(int32_t row, nsITreeColumn* col,
michael@0 1080 nsAString& _retval)
michael@0 1081 {
michael@0 1082 if (!mTreeArray)
michael@0 1083 return NS_ERROR_NOT_INITIALIZED;
michael@0 1084
michael@0 1085 nsresult rv;
michael@0 1086 _retval.Truncate();
michael@0 1087
michael@0 1088 const char16_t* colID;
michael@0 1089 col->GetIdConst(&colID);
michael@0 1090
michael@0 1091 treeArrayEl *el = GetThreadDescAtIndex(row);
michael@0 1092 if (el) {
michael@0 1093 if (NS_LITERAL_STRING("certcol").Equals(colID))
michael@0 1094 _retval.Assign(el->orgName);
michael@0 1095 else
michael@0 1096 _retval.Truncate();
michael@0 1097 return NS_OK;
michael@0 1098 }
michael@0 1099
michael@0 1100 int32_t absoluteCertOffset;
michael@0 1101 RefPtr<nsCertTreeDispInfo> certdi(GetDispInfoAtIndex(row, &absoluteCertOffset));
michael@0 1102 if (!certdi)
michael@0 1103 return NS_ERROR_FAILURE;
michael@0 1104
michael@0 1105 nsCOMPtr<nsIX509Cert> cert = certdi->mCert;
michael@0 1106 if (!cert && certdi->mAddonInfo) {
michael@0 1107 cert = certdi->mAddonInfo->mCert;
michael@0 1108 }
michael@0 1109
michael@0 1110 int32_t colIndex;
michael@0 1111 col->GetIndex(&colIndex);
michael@0 1112 uint32_t arrayIndex=absoluteCertOffset+colIndex*(mNumRows-mNumOrgs);
michael@0 1113 uint32_t arrayLength=0;
michael@0 1114 if (mCellText) {
michael@0 1115 mCellText->GetLength(&arrayLength);
michael@0 1116 }
michael@0 1117 if (arrayIndex < arrayLength) {
michael@0 1118 nsCOMPtr<nsISupportsString> myString(do_QueryElementAt(mCellText, arrayIndex));
michael@0 1119 if (myString) {
michael@0 1120 myString->GetData(_retval);
michael@0 1121 return NS_OK;
michael@0 1122 }
michael@0 1123 }
michael@0 1124
michael@0 1125 if (NS_LITERAL_STRING("certcol").Equals(colID)) {
michael@0 1126 if (!cert) {
michael@0 1127 mNSSComponent->GetPIPNSSBundleString("CertNotStored", _retval);
michael@0 1128 }
michael@0 1129 else {
michael@0 1130 rv = cert->GetCommonName(_retval);
michael@0 1131 if (NS_FAILED(rv) || _retval.IsEmpty()) {
michael@0 1132 // kaie: I didn't invent the idea to cut off anything before
michael@0 1133 // the first colon. :-)
michael@0 1134 nsAutoString nick;
michael@0 1135 rv = cert->GetNickname(nick);
michael@0 1136
michael@0 1137 nsAString::const_iterator start, end, end2;
michael@0 1138 nick.BeginReading(start);
michael@0 1139 nick.EndReading(end);
michael@0 1140 end2 = end;
michael@0 1141
michael@0 1142 if (FindInReadable(NS_LITERAL_STRING(":"), start, end)) {
michael@0 1143 // found. end points to the first char after the colon,
michael@0 1144 // that's what we want.
michael@0 1145 _retval = Substring(end, end2);
michael@0 1146 }
michael@0 1147 else {
michael@0 1148 _retval = nick;
michael@0 1149 }
michael@0 1150 }
michael@0 1151 }
michael@0 1152 } else if (NS_LITERAL_STRING("tokencol").Equals(colID) && cert) {
michael@0 1153 rv = cert->GetTokenName(_retval);
michael@0 1154 } else if (NS_LITERAL_STRING("emailcol").Equals(colID) && cert) {
michael@0 1155 rv = cert->GetEmailAddress(_retval);
michael@0 1156 } else if (NS_LITERAL_STRING("purposecol").Equals(colID) && mNSSComponent && cert) {
michael@0 1157 uint32_t verified;
michael@0 1158
michael@0 1159 nsAutoString theUsages;
michael@0 1160 rv = cert->GetUsagesString(false, &verified, theUsages); // allow OCSP
michael@0 1161 if (NS_FAILED(rv)) {
michael@0 1162 verified = nsIX509Cert::NOT_VERIFIED_UNKNOWN;
michael@0 1163 }
michael@0 1164
michael@0 1165 switch (verified) {
michael@0 1166 case nsIX509Cert::VERIFIED_OK:
michael@0 1167 _retval = theUsages;
michael@0 1168 break;
michael@0 1169
michael@0 1170 case nsIX509Cert::CERT_REVOKED:
michael@0 1171 rv = mNSSComponent->GetPIPNSSBundleString("VerifyRevoked", _retval);
michael@0 1172 break;
michael@0 1173 case nsIX509Cert::CERT_EXPIRED:
michael@0 1174 rv = mNSSComponent->GetPIPNSSBundleString("VerifyExpired", _retval);
michael@0 1175 break;
michael@0 1176 case nsIX509Cert::CERT_NOT_TRUSTED:
michael@0 1177 rv = mNSSComponent->GetPIPNSSBundleString("VerifyNotTrusted", _retval);
michael@0 1178 break;
michael@0 1179 case nsIX509Cert::ISSUER_NOT_TRUSTED:
michael@0 1180 rv = mNSSComponent->GetPIPNSSBundleString("VerifyIssuerNotTrusted", _retval);
michael@0 1181 break;
michael@0 1182 case nsIX509Cert::ISSUER_UNKNOWN:
michael@0 1183 rv = mNSSComponent->GetPIPNSSBundleString("VerifyIssuerUnknown", _retval);
michael@0 1184 break;
michael@0 1185 case nsIX509Cert::INVALID_CA:
michael@0 1186 rv = mNSSComponent->GetPIPNSSBundleString("VerifyInvalidCA", _retval);
michael@0 1187 break;
michael@0 1188 case nsIX509Cert::SIGNATURE_ALGORITHM_DISABLED:
michael@0 1189 rv = mNSSComponent->GetPIPNSSBundleString("VerifyDisabledAlgorithm", _retval);
michael@0 1190 break;
michael@0 1191 case nsIX509Cert::NOT_VERIFIED_UNKNOWN:
michael@0 1192 case nsIX509Cert::USAGE_NOT_ALLOWED:
michael@0 1193 default:
michael@0 1194 rv = mNSSComponent->GetPIPNSSBundleString("VerifyUnknown", _retval);
michael@0 1195 break;
michael@0 1196 }
michael@0 1197 } else if (NS_LITERAL_STRING("issuedcol").Equals(colID) && cert) {
michael@0 1198 nsCOMPtr<nsIX509CertValidity> validity;
michael@0 1199
michael@0 1200 rv = cert->GetValidity(getter_AddRefs(validity));
michael@0 1201 if (NS_SUCCEEDED(rv)) {
michael@0 1202 validity->GetNotBeforeLocalDay(_retval);
michael@0 1203 }
michael@0 1204 } else if (NS_LITERAL_STRING("expiredcol").Equals(colID) && cert) {
michael@0 1205 nsCOMPtr<nsIX509CertValidity> validity;
michael@0 1206
michael@0 1207 rv = cert->GetValidity(getter_AddRefs(validity));
michael@0 1208 if (NS_SUCCEEDED(rv)) {
michael@0 1209 validity->GetNotAfterLocalDay(_retval);
michael@0 1210 }
michael@0 1211 } else if (NS_LITERAL_STRING("serialnumcol").Equals(colID) && cert) {
michael@0 1212 rv = cert->GetSerialNumber(_retval);
michael@0 1213
michael@0 1214
michael@0 1215 } else if (NS_LITERAL_STRING("overridetypecol").Equals(colID)) {
michael@0 1216 // default to classic permanent-trust
michael@0 1217 nsCertOverride::OverrideBits ob = nsCertOverride::ob_Untrusted;
michael@0 1218 if (certdi->mTypeOfEntry == nsCertTreeDispInfo::host_port_override) {
michael@0 1219 ob = certdi->mOverrideBits;
michael@0 1220 }
michael@0 1221 nsAutoCString temp;
michael@0 1222 nsCertOverride::convertBitsToString(ob, temp);
michael@0 1223 _retval = NS_ConvertUTF8toUTF16(temp);
michael@0 1224 } else if (NS_LITERAL_STRING("sitecol").Equals(colID)) {
michael@0 1225 if (certdi->mTypeOfEntry == nsCertTreeDispInfo::host_port_override) {
michael@0 1226 nsAutoCString hostPort;
michael@0 1227 nsCertOverrideService::GetHostWithPort(certdi->mAsciiHost, certdi->mPort, hostPort);
michael@0 1228 _retval = NS_ConvertUTF8toUTF16(hostPort);
michael@0 1229 }
michael@0 1230 else {
michael@0 1231 _retval = NS_LITERAL_STRING("*");
michael@0 1232 }
michael@0 1233 } else if (NS_LITERAL_STRING("lifetimecol").Equals(colID)) {
michael@0 1234 const char *stringID =
michael@0 1235 (certdi->mIsTemporary) ? "CertExceptionTemporary" : "CertExceptionPermanent";
michael@0 1236 rv = mNSSComponent->GetPIPNSSBundleString(stringID, _retval);
michael@0 1237 } else if (NS_LITERAL_STRING("typecol").Equals(colID) && cert) {
michael@0 1238 nsCOMPtr<nsIX509Cert2> pipCert = do_QueryInterface(cert);
michael@0 1239 uint32_t type = nsIX509Cert::UNKNOWN_CERT;
michael@0 1240
michael@0 1241 if (pipCert) {
michael@0 1242 rv = pipCert->GetCertType(&type);
michael@0 1243 }
michael@0 1244
michael@0 1245 switch (type) {
michael@0 1246 case nsIX509Cert::USER_CERT:
michael@0 1247 rv = mNSSComponent->GetPIPNSSBundleString("CertUser", _retval);
michael@0 1248 break;
michael@0 1249 case nsIX509Cert::CA_CERT:
michael@0 1250 rv = mNSSComponent->GetPIPNSSBundleString("CertCA", _retval);
michael@0 1251 break;
michael@0 1252 case nsIX509Cert::SERVER_CERT:
michael@0 1253 rv = mNSSComponent->GetPIPNSSBundleString("CertSSL", _retval);
michael@0 1254 break;
michael@0 1255 case nsIX509Cert::EMAIL_CERT:
michael@0 1256 rv = mNSSComponent->GetPIPNSSBundleString("CertEmail", _retval);
michael@0 1257 break;
michael@0 1258 default:
michael@0 1259 rv = mNSSComponent->GetPIPNSSBundleString("CertUnknown", _retval);
michael@0 1260 break;
michael@0 1261 }
michael@0 1262
michael@0 1263 } else {
michael@0 1264 return NS_ERROR_FAILURE;
michael@0 1265 }
michael@0 1266 if (mCellText) {
michael@0 1267 nsCOMPtr<nsISupportsString> text(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv));
michael@0 1268 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1269 text->SetData(_retval);
michael@0 1270 mCellText->ReplaceElementAt(text, arrayIndex, false);
michael@0 1271 }
michael@0 1272 return rv;
michael@0 1273 }
michael@0 1274
michael@0 1275 /* void setTree (in nsITreeBoxObject tree); */
michael@0 1276 NS_IMETHODIMP
michael@0 1277 nsCertTree::SetTree(nsITreeBoxObject *tree)
michael@0 1278 {
michael@0 1279 mTree = tree;
michael@0 1280 return NS_OK;
michael@0 1281 }
michael@0 1282
michael@0 1283 /* void toggleOpenState (in long index); */
michael@0 1284 NS_IMETHODIMP
michael@0 1285 nsCertTree::ToggleOpenState(int32_t index)
michael@0 1286 {
michael@0 1287 if (!mTreeArray)
michael@0 1288 return NS_ERROR_NOT_INITIALIZED;
michael@0 1289 treeArrayEl *el = GetThreadDescAtIndex(index);
michael@0 1290 if (el) {
michael@0 1291 el->open = !el->open;
michael@0 1292 int32_t newChildren = (el->open) ? el->numChildren : -el->numChildren;
michael@0 1293 if (mTree) mTree->RowCountChanged(index + 1, newChildren);
michael@0 1294 }
michael@0 1295 return NS_OK;
michael@0 1296 }
michael@0 1297
michael@0 1298 /* void cycleHeader (in nsITreeColumn); */
michael@0 1299 NS_IMETHODIMP
michael@0 1300 nsCertTree::CycleHeader(nsITreeColumn* col)
michael@0 1301 {
michael@0 1302 return NS_OK;
michael@0 1303 }
michael@0 1304
michael@0 1305 /* void selectionChanged (); */
michael@0 1306 NS_IMETHODIMP
michael@0 1307 nsCertTree::SelectionChanged()
michael@0 1308 {
michael@0 1309 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 1310 }
michael@0 1311
michael@0 1312 /* void cycleCell (in long row, in nsITreeColumn col); */
michael@0 1313 NS_IMETHODIMP
michael@0 1314 nsCertTree::CycleCell(int32_t row, nsITreeColumn* col)
michael@0 1315 {
michael@0 1316 return NS_OK;
michael@0 1317 }
michael@0 1318
michael@0 1319 /* boolean isEditable (in long row, in nsITreeColumn col); */
michael@0 1320 NS_IMETHODIMP
michael@0 1321 nsCertTree::IsEditable(int32_t row, nsITreeColumn* col, bool *_retval)
michael@0 1322 {
michael@0 1323 *_retval = false;
michael@0 1324 return NS_OK;
michael@0 1325 }
michael@0 1326
michael@0 1327 /* boolean isSelectable (in long row, in nsITreeColumn col); */
michael@0 1328 NS_IMETHODIMP
michael@0 1329 nsCertTree::IsSelectable(int32_t row, nsITreeColumn* col, bool *_retval)
michael@0 1330 {
michael@0 1331 *_retval = false;
michael@0 1332 return NS_OK;
michael@0 1333 }
michael@0 1334
michael@0 1335 /* void setCellValue (in long row, in nsITreeColumn col, in AString value); */
michael@0 1336 NS_IMETHODIMP
michael@0 1337 nsCertTree::SetCellValue(int32_t row, nsITreeColumn* col,
michael@0 1338 const nsAString& value)
michael@0 1339 {
michael@0 1340 return NS_OK;
michael@0 1341 }
michael@0 1342
michael@0 1343 /* void setCellText (in long row, in nsITreeColumn col, in AString value); */
michael@0 1344 NS_IMETHODIMP
michael@0 1345 nsCertTree::SetCellText(int32_t row, nsITreeColumn* col,
michael@0 1346 const nsAString& value)
michael@0 1347 {
michael@0 1348 return NS_OK;
michael@0 1349 }
michael@0 1350
michael@0 1351 /* void performAction (in wstring action); */
michael@0 1352 NS_IMETHODIMP
michael@0 1353 nsCertTree::PerformAction(const char16_t *action)
michael@0 1354 {
michael@0 1355 return NS_OK;
michael@0 1356 }
michael@0 1357
michael@0 1358 /* void performActionOnRow (in wstring action, in long row); */
michael@0 1359 NS_IMETHODIMP
michael@0 1360 nsCertTree::PerformActionOnRow(const char16_t *action, int32_t row)
michael@0 1361 {
michael@0 1362 return NS_OK;
michael@0 1363 }
michael@0 1364
michael@0 1365 /* void performActionOnCell (in wstring action, in long row,
michael@0 1366 * in wstring colID);
michael@0 1367 */
michael@0 1368 NS_IMETHODIMP
michael@0 1369 nsCertTree::PerformActionOnCell(const char16_t *action, int32_t row,
michael@0 1370 nsITreeColumn* col)
michael@0 1371 {
michael@0 1372 return NS_OK;
michael@0 1373 }
michael@0 1374
michael@0 1375 #ifdef DEBUG_CERT_TREE
michael@0 1376 void
michael@0 1377 nsCertTree::dumpMap()
michael@0 1378 {
michael@0 1379 for (int i=0; i<mNumOrgs; i++) {
michael@0 1380 nsAutoString org(mTreeArray[i].orgName);
michael@0 1381 PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("ORG[%s]", NS_LossyConvertUTF16toASCII(org).get()));
michael@0 1382 PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("OPEN[%d]", mTreeArray[i].open));
michael@0 1383 PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("INDEX[%d]", mTreeArray[i].certIndex));
michael@0 1384 PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("NCHILD[%d]", mTreeArray[i].numChildren));
michael@0 1385 }
michael@0 1386 for (int i=0; i<mNumRows; i++) {
michael@0 1387 treeArrayEl *el = GetThreadDescAtIndex(i);
michael@0 1388 if (el) {
michael@0 1389 nsAutoString td(el->orgName);
michael@0 1390 PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("thread desc[%d]: %s", i, NS_LossyConvertUTF16toASCII(td).get()));
michael@0 1391 }
michael@0 1392 nsCOMPtr<nsIX509Cert> ct = GetCertAtIndex(i);
michael@0 1393 if (ct) {
michael@0 1394 char16_t *goo;
michael@0 1395 ct->GetCommonName(&goo);
michael@0 1396 nsAutoString doo(goo);
michael@0 1397 PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("cert [%d]: %s", i, NS_LossyConvertUTF16toASCII(doo).get()));
michael@0 1398 }
michael@0 1399 }
michael@0 1400 }
michael@0 1401 #endif
michael@0 1402
michael@0 1403 //
michael@0 1404 // CanDrop
michael@0 1405 //
michael@0 1406 NS_IMETHODIMP nsCertTree::CanDrop(int32_t index, int32_t orientation,
michael@0 1407 nsIDOMDataTransfer* aDataTransfer, bool *_retval)
michael@0 1408 {
michael@0 1409 NS_ENSURE_ARG_POINTER(_retval);
michael@0 1410 *_retval = false;
michael@0 1411
michael@0 1412 return NS_OK;
michael@0 1413 }
michael@0 1414
michael@0 1415
michael@0 1416 //
michael@0 1417 // Drop
michael@0 1418 //
michael@0 1419 NS_IMETHODIMP nsCertTree::Drop(int32_t row, int32_t orient, nsIDOMDataTransfer* aDataTransfer)
michael@0 1420 {
michael@0 1421 return NS_OK;
michael@0 1422 }
michael@0 1423
michael@0 1424
michael@0 1425 //
michael@0 1426 // IsSorted
michael@0 1427 //
michael@0 1428 // ...
michael@0 1429 //
michael@0 1430 NS_IMETHODIMP nsCertTree::IsSorted(bool *_retval)
michael@0 1431 {
michael@0 1432 *_retval = false;
michael@0 1433 return NS_OK;
michael@0 1434 }
michael@0 1435
michael@0 1436 #define RETURN_NOTHING
michael@0 1437
michael@0 1438 void
michael@0 1439 nsCertTree::CmpInitCriterion(nsIX509Cert *cert, CompareCacheHashEntry *entry,
michael@0 1440 sortCriterion crit, int32_t level)
michael@0 1441 {
michael@0 1442 NS_ENSURE_TRUE(cert && entry, RETURN_NOTHING);
michael@0 1443
michael@0 1444 entry->mCritInit[level] = true;
michael@0 1445 nsXPIDLString &str = entry->mCrit[level];
michael@0 1446
michael@0 1447 switch (crit) {
michael@0 1448 case sort_IssuerOrg:
michael@0 1449 cert->GetIssuerOrganization(str);
michael@0 1450 if (str.IsEmpty())
michael@0 1451 cert->GetCommonName(str);
michael@0 1452 break;
michael@0 1453 case sort_Org:
michael@0 1454 cert->GetOrganization(str);
michael@0 1455 break;
michael@0 1456 case sort_Token:
michael@0 1457 cert->GetTokenName(str);
michael@0 1458 break;
michael@0 1459 case sort_CommonName:
michael@0 1460 cert->GetCommonName(str);
michael@0 1461 break;
michael@0 1462 case sort_IssuedDateDescending:
michael@0 1463 {
michael@0 1464 nsresult rv;
michael@0 1465 nsCOMPtr<nsIX509CertValidity> validity;
michael@0 1466 PRTime notBefore;
michael@0 1467
michael@0 1468 rv = cert->GetValidity(getter_AddRefs(validity));
michael@0 1469 if (NS_SUCCEEDED(rv)) {
michael@0 1470 rv = validity->GetNotBefore(&notBefore);
michael@0 1471 }
michael@0 1472
michael@0 1473 if (NS_SUCCEEDED(rv)) {
michael@0 1474 PRExplodedTime explodedTime;
michael@0 1475 PR_ExplodeTime(notBefore, PR_GMTParameters, &explodedTime);
michael@0 1476 char datebuf[20]; // 4 + 2 + 2 + 2 + 2 + 2 + 1 = 15
michael@0 1477 if (0 != PR_FormatTime(datebuf, sizeof(datebuf), "%Y%m%d%H%M%S", &explodedTime)) {
michael@0 1478 str = NS_ConvertASCIItoUTF16(nsDependentCString(datebuf));
michael@0 1479 }
michael@0 1480 }
michael@0 1481 }
michael@0 1482 break;
michael@0 1483 case sort_Email:
michael@0 1484 cert->GetEmailAddress(str);
michael@0 1485 break;
michael@0 1486 case sort_None:
michael@0 1487 default:
michael@0 1488 break;
michael@0 1489 }
michael@0 1490 }
michael@0 1491
michael@0 1492 int32_t
michael@0 1493 nsCertTree::CmpByCrit(nsIX509Cert *a, CompareCacheHashEntry *ace,
michael@0 1494 nsIX509Cert *b, CompareCacheHashEntry *bce,
michael@0 1495 sortCriterion crit, int32_t level)
michael@0 1496 {
michael@0 1497 NS_ENSURE_TRUE(a && ace && b && bce, 0);
michael@0 1498
michael@0 1499 if (!ace->mCritInit[level]) {
michael@0 1500 CmpInitCriterion(a, ace, crit, level);
michael@0 1501 }
michael@0 1502
michael@0 1503 if (!bce->mCritInit[level]) {
michael@0 1504 CmpInitCriterion(b, bce, crit, level);
michael@0 1505 }
michael@0 1506
michael@0 1507 nsXPIDLString &str_a = ace->mCrit[level];
michael@0 1508 nsXPIDLString &str_b = bce->mCrit[level];
michael@0 1509
michael@0 1510 int32_t result;
michael@0 1511 if (str_a && str_b)
michael@0 1512 result = Compare(str_a, str_b, nsCaseInsensitiveStringComparator());
michael@0 1513 else
michael@0 1514 result = !str_a ? (!str_b ? 0 : -1) : 1;
michael@0 1515
michael@0 1516 if (sort_IssuedDateDescending == crit)
michael@0 1517 result *= -1; // reverse compare order
michael@0 1518
michael@0 1519 return result;
michael@0 1520 }
michael@0 1521
michael@0 1522 int32_t
michael@0 1523 nsCertTree::CmpBy(void *cache, nsIX509Cert *a, nsIX509Cert *b,
michael@0 1524 sortCriterion c0, sortCriterion c1, sortCriterion c2)
michael@0 1525 {
michael@0 1526 // This will be called when comparing items for display sorting.
michael@0 1527 // Some items might have no cert associated, so either a or b is null.
michael@0 1528 // We want all those orphans show at the top of the list,
michael@0 1529 // so we treat a null cert as "smaller" by returning -1.
michael@0 1530 // We don't try to sort within the group of no-cert entries,
michael@0 1531 // so we treat them as equal wrt sort order.
michael@0 1532
michael@0 1533 if (!a && !b)
michael@0 1534 return 0;
michael@0 1535
michael@0 1536 if (!a)
michael@0 1537 return -1;
michael@0 1538
michael@0 1539 if (!b)
michael@0 1540 return 1;
michael@0 1541
michael@0 1542 NS_ENSURE_TRUE(cache && a && b, 0);
michael@0 1543
michael@0 1544 CompareCacheHashEntry *ace = getCacheEntry(cache, a);
michael@0 1545 CompareCacheHashEntry *bce = getCacheEntry(cache, b);
michael@0 1546
michael@0 1547 int32_t cmp;
michael@0 1548 cmp = CmpByCrit(a, ace, b, bce, c0, 0);
michael@0 1549 if (cmp != 0)
michael@0 1550 return cmp;
michael@0 1551
michael@0 1552 if (c1 != sort_None) {
michael@0 1553 cmp = CmpByCrit(a, ace, b, bce, c1, 1);
michael@0 1554 if (cmp != 0)
michael@0 1555 return cmp;
michael@0 1556
michael@0 1557 if (c2 != sort_None) {
michael@0 1558 return CmpByCrit(a, ace, b, bce, c2, 2);
michael@0 1559 }
michael@0 1560 }
michael@0 1561
michael@0 1562 return cmp;
michael@0 1563 }
michael@0 1564
michael@0 1565 int32_t
michael@0 1566 nsCertTree::CmpCACert(void *cache, nsIX509Cert *a, nsIX509Cert *b)
michael@0 1567 {
michael@0 1568 // XXX we assume issuer org is always criterion 1
michael@0 1569 return CmpBy(cache, a, b, sort_IssuerOrg, sort_Org, sort_Token);
michael@0 1570 }
michael@0 1571
michael@0 1572 int32_t
michael@0 1573 nsCertTree::CmpWebSiteCert(void *cache, nsIX509Cert *a, nsIX509Cert *b)
michael@0 1574 {
michael@0 1575 // XXX we assume issuer org is always criterion 1
michael@0 1576 return CmpBy(cache, a, b, sort_IssuerOrg, sort_CommonName, sort_None);
michael@0 1577 }
michael@0 1578
michael@0 1579 int32_t
michael@0 1580 nsCertTree::CmpUserCert(void *cache, nsIX509Cert *a, nsIX509Cert *b)
michael@0 1581 {
michael@0 1582 // XXX we assume issuer org is always criterion 1
michael@0 1583 return CmpBy(cache, a, b, sort_IssuerOrg, sort_Token, sort_IssuedDateDescending);
michael@0 1584 }
michael@0 1585
michael@0 1586 int32_t
michael@0 1587 nsCertTree::CmpEmailCert(void *cache, nsIX509Cert *a, nsIX509Cert *b)
michael@0 1588 {
michael@0 1589 // XXX we assume issuer org is always criterion 1
michael@0 1590 return CmpBy(cache, a, b, sort_IssuerOrg, sort_Email, sort_CommonName);
michael@0 1591 }
michael@0 1592

mercurial