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.

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

mercurial