1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/manager/pki/src/nsASN1Tree.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,577 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 +#include "nsASN1Tree.h" 1.8 +#include "nsIComponentManager.h" 1.9 +#include "nsString.h" 1.10 +#include "nsCRT.h" 1.11 +#include "nsIMutableArray.h" 1.12 +#include "nsArrayUtils.h" 1.13 + 1.14 +NS_IMPL_ISUPPORTS(nsNSSASN1Tree, nsIASN1Tree, nsITreeView) 1.15 + 1.16 +nsNSSASN1Tree::nsNSSASN1Tree() 1.17 +:mTopNode(nullptr) 1.18 +{ 1.19 +} 1.20 + 1.21 +nsNSSASN1Tree::~nsNSSASN1Tree() 1.22 +{ 1.23 + ClearNodes(); 1.24 +} 1.25 + 1.26 +void nsNSSASN1Tree::ClearNodesRecursively(myNode *n) 1.27 +{ 1.28 + myNode *walk = n; 1.29 + while (walk) { 1.30 + myNode *kill = walk; 1.31 + 1.32 + if (walk->child) { 1.33 + ClearNodesRecursively(walk->child); 1.34 + } 1.35 + 1.36 + walk = walk->next; 1.37 + delete kill; 1.38 + } 1.39 +} 1.40 + 1.41 +void nsNSSASN1Tree::ClearNodes() 1.42 +{ 1.43 + ClearNodesRecursively(mTopNode); 1.44 + mTopNode = nullptr; 1.45 +} 1.46 + 1.47 +void nsNSSASN1Tree::InitChildsRecursively(myNode *n) 1.48 +{ 1.49 + if (!n->obj) 1.50 + return; 1.51 + 1.52 + n->seq = do_QueryInterface(n->obj); 1.53 + if (!n->seq) 1.54 + return; 1.55 + 1.56 + // If the object is a sequence, there might still be a reason 1.57 + // why it should not be displayed as a container. 1.58 + // If we decide that it has all the properties to justify 1.59 + // displaying as a container, we will create a new child chain. 1.60 + // If we decide, it does not make sense to display as a container, 1.61 + // we forget that it is a sequence by erasing n->seq. 1.62 + // That way, n->seq and n->child will be either both set or both null. 1.63 + 1.64 + bool isContainer; 1.65 + n->seq->GetIsValidContainer(&isContainer); 1.66 + if (!isContainer) { 1.67 + n->seq = nullptr; 1.68 + return; 1.69 + } 1.70 + 1.71 + nsCOMPtr<nsIMutableArray> asn1Objects; 1.72 + n->seq->GetASN1Objects(getter_AddRefs(asn1Objects)); 1.73 + uint32_t numObjects; 1.74 + asn1Objects->GetLength(&numObjects); 1.75 + 1.76 + if (!numObjects) { 1.77 + n->seq = nullptr; 1.78 + return; 1.79 + } 1.80 + 1.81 + myNode *walk = nullptr; 1.82 + myNode *prev = nullptr; 1.83 + 1.84 + uint32_t i; 1.85 + nsCOMPtr<nsISupports> isupports; 1.86 + for (i=0; i<numObjects; i++) { 1.87 + if (0 == i) { 1.88 + n->child = walk = new myNode; 1.89 + } 1.90 + else { 1.91 + walk = new myNode; 1.92 + } 1.93 + 1.94 + walk->parent = n; 1.95 + if (prev) { 1.96 + prev->next = walk; 1.97 + } 1.98 + 1.99 + walk->obj = do_QueryElementAt(asn1Objects, i); 1.100 + 1.101 + InitChildsRecursively(walk); 1.102 + 1.103 + prev = walk; 1.104 + } 1.105 +} 1.106 + 1.107 +void nsNSSASN1Tree::InitNodes() 1.108 +{ 1.109 + ClearNodes(); 1.110 + 1.111 + mTopNode = new myNode; 1.112 + mTopNode->obj = mASN1Object; 1.113 + 1.114 + InitChildsRecursively(mTopNode); 1.115 +} 1.116 + 1.117 +/* void loadASN1Structure (in nsIASN1Object asn1Object); */ 1.118 +NS_IMETHODIMP 1.119 +nsNSSASN1Tree::LoadASN1Structure(nsIASN1Object *asn1Object) 1.120 +{ 1.121 + // 1.122 + // The tree won't automatically re-draw if the contents 1.123 + // have been changed. So I do a quick test here to let 1.124 + // me know if I should forced the tree to redraw itself 1.125 + // by calling RowCountChanged on it. 1.126 + // 1.127 + bool redraw = (mASN1Object && mTree); 1.128 + int32_t rowsToDelete = 0; 1.129 + 1.130 + if (redraw) { 1.131 + // This is the number of rows we will be deleting after 1.132 + // the contents have changed. 1.133 + rowsToDelete = 0-CountVisibleNodes(mTopNode); 1.134 + } 1.135 + 1.136 + mASN1Object = asn1Object; 1.137 + InitNodes(); 1.138 + 1.139 + if (redraw) { 1.140 + // The number of rows in the new content. 1.141 + int32_t newRows = CountVisibleNodes(mTopNode); 1.142 + mTree->BeginUpdateBatch(); 1.143 + // Erase all of the old rows. 1.144 + mTree->RowCountChanged(0, rowsToDelete); 1.145 + // Replace them with the new contents 1.146 + mTree->RowCountChanged(0, newRows); 1.147 + mTree->EndUpdateBatch(); 1.148 + } 1.149 + 1.150 + return NS_OK; 1.151 +} 1.152 + 1.153 +/* readonly attribute long rowCount; */ 1.154 +NS_IMETHODIMP 1.155 +nsNSSASN1Tree::GetRowCount(int32_t *aRowCount) 1.156 +{ 1.157 + if (mASN1Object) { 1.158 + *aRowCount = CountVisibleNodes(mTopNode); 1.159 + } else { 1.160 + *aRowCount = 0; 1.161 + } 1.162 + return NS_OK; 1.163 +} 1.164 + 1.165 +/* attribute nsITreeSelection selection; */ 1.166 +NS_IMETHODIMP 1.167 +nsNSSASN1Tree::GetSelection(nsITreeSelection * *aSelection) 1.168 +{ 1.169 + *aSelection = mSelection; 1.170 + NS_IF_ADDREF(*aSelection); 1.171 + return NS_OK; 1.172 +} 1.173 + 1.174 +NS_IMETHODIMP 1.175 +nsNSSASN1Tree::SetSelection(nsITreeSelection * aSelection) 1.176 +{ 1.177 + mSelection = aSelection; 1.178 + return NS_OK; 1.179 +} 1.180 + 1.181 +NS_IMETHODIMP 1.182 +nsNSSASN1Tree::GetRowProperties(int32_t index, nsAString& aProps) 1.183 +{ 1.184 + return NS_OK; 1.185 +} 1.186 + 1.187 +NS_IMETHODIMP 1.188 +nsNSSASN1Tree::GetCellProperties(int32_t row, nsITreeColumn* col, 1.189 + nsAString& aProps) 1.190 +{ 1.191 + return NS_OK; 1.192 +} 1.193 + 1.194 +NS_IMETHODIMP 1.195 +nsNSSASN1Tree::GetColumnProperties(nsITreeColumn* col, nsAString& aProps) 1.196 +{ 1.197 + return NS_OK; 1.198 +} 1.199 + 1.200 +/* boolean isContainer (in long index); */ 1.201 +NS_IMETHODIMP 1.202 +nsNSSASN1Tree::IsContainer(int32_t index, bool *_retval) 1.203 +{ 1.204 + myNode *n = FindNodeFromIndex(index); 1.205 + if (!n) 1.206 + return NS_ERROR_FAILURE; 1.207 + 1.208 + *_retval = (n->seq != nullptr); 1.209 + return NS_OK; 1.210 +} 1.211 + 1.212 +/* boolean isContainerOpen (in long index); */ 1.213 +NS_IMETHODIMP 1.214 +nsNSSASN1Tree::IsContainerOpen(int32_t index, bool *_retval) 1.215 +{ 1.216 + myNode *n = FindNodeFromIndex(index); 1.217 + if (!n || !n->seq) 1.218 + return NS_ERROR_FAILURE; 1.219 + 1.220 + n->seq->GetIsExpanded(_retval); 1.221 + return NS_OK; 1.222 +} 1.223 + 1.224 +/* boolean isContainerEmpty (in long index); */ 1.225 +NS_IMETHODIMP 1.226 +nsNSSASN1Tree::IsContainerEmpty(int32_t index, bool *_retval) 1.227 +{ 1.228 + *_retval = false; 1.229 + return NS_OK; 1.230 +} 1.231 + 1.232 +/* boolean isSeparator (in long index); */ 1.233 +NS_IMETHODIMP 1.234 +nsNSSASN1Tree::IsSeparator(int32_t index, bool *_retval) 1.235 +{ 1.236 + *_retval = false; 1.237 + return NS_OK; 1.238 +} 1.239 + 1.240 +/* long getLevel (in long index); */ 1.241 +NS_IMETHODIMP 1.242 +nsNSSASN1Tree::GetLevel(int32_t index, int32_t *_retval) 1.243 +{ 1.244 + int32_t parentIndex; 1.245 + int32_t nodeLevel; 1.246 + 1.247 + myNode *n = FindNodeFromIndex(index, &parentIndex, &nodeLevel); 1.248 + if (!n) 1.249 + return NS_ERROR_FAILURE; 1.250 + 1.251 + *_retval = nodeLevel; 1.252 + return NS_OK; 1.253 +} 1.254 + 1.255 +/* Astring getImageSrc (in long row, in nsITreeColumn col); */ 1.256 +NS_IMETHODIMP 1.257 +nsNSSASN1Tree::GetImageSrc(int32_t row, nsITreeColumn* col, 1.258 + nsAString& _retval) 1.259 +{ 1.260 + return NS_OK; 1.261 +} 1.262 + 1.263 +/* long getProgressMode (in long row, in nsITreeColumn col); */ 1.264 +NS_IMETHODIMP 1.265 +nsNSSASN1Tree::GetProgressMode(int32_t row, nsITreeColumn* col, int32_t* _retval) 1.266 +{ 1.267 + return NS_OK; 1.268 +} 1.269 + 1.270 +/* Astring getCellValue (in long row, in nsITreeColumn col); */ 1.271 +NS_IMETHODIMP 1.272 +nsNSSASN1Tree::GetCellValue(int32_t row, nsITreeColumn* col, 1.273 + nsAString& _retval) 1.274 +{ 1.275 + return NS_OK; 1.276 +} 1.277 + 1.278 +/* Astring getCellText (in long row, in nsITreeColumn col); */ 1.279 +NS_IMETHODIMP 1.280 +nsNSSASN1Tree::GetCellText(int32_t row, nsITreeColumn* col, 1.281 + nsAString& _retval) 1.282 +{ 1.283 + _retval.Truncate(); 1.284 + 1.285 + myNode* n = FindNodeFromIndex(row); 1.286 + if (!n) 1.287 + return NS_ERROR_FAILURE; 1.288 + 1.289 + // There's only one column for ASN1 dump. 1.290 + return n->obj->GetDisplayName(_retval); 1.291 +} 1.292 + 1.293 +/* wstring getDisplayData (in unsigned long index); */ 1.294 +NS_IMETHODIMP 1.295 +nsNSSASN1Tree::GetDisplayData(uint32_t index, nsAString &_retval) 1.296 +{ 1.297 + myNode *n = FindNodeFromIndex(index); 1.298 + if (!n) 1.299 + return NS_ERROR_FAILURE; 1.300 + 1.301 + n->obj->GetDisplayValue(_retval); 1.302 + return NS_OK; 1.303 +} 1.304 + 1.305 +/* void setTree (in nsITreeBoxObject tree); */ 1.306 +NS_IMETHODIMP 1.307 +nsNSSASN1Tree::SetTree(nsITreeBoxObject *tree) 1.308 +{ 1.309 + mTree = tree; 1.310 + return NS_OK; 1.311 +} 1.312 + 1.313 +/* void toggleOpenState (in long index); */ 1.314 +NS_IMETHODIMP 1.315 +nsNSSASN1Tree::ToggleOpenState(int32_t index) 1.316 +{ 1.317 + myNode *n = FindNodeFromIndex(index); 1.318 + if (!n) 1.319 + return NS_ERROR_FAILURE; 1.320 + 1.321 + if (!n->seq) 1.322 + return NS_ERROR_FAILURE; 1.323 + 1.324 + bool IsExpanded; 1.325 + n->seq->GetIsExpanded(&IsExpanded); 1.326 + int32_t rowCountChange; 1.327 + if (IsExpanded) { 1.328 + rowCountChange = -CountVisibleNodes(n->child); 1.329 + n->seq->SetIsExpanded(false); 1.330 + } else { 1.331 + n->seq->SetIsExpanded(true); 1.332 + rowCountChange = CountVisibleNodes(n->child); 1.333 + } 1.334 + if (mTree) 1.335 + mTree->RowCountChanged(index, rowCountChange); 1.336 + return NS_OK; 1.337 +} 1.338 + 1.339 +/* void cycleHeader (in nsITreeColumn col); */ 1.340 +NS_IMETHODIMP 1.341 +nsNSSASN1Tree::CycleHeader(nsITreeColumn* col) 1.342 +{ 1.343 + return NS_OK; 1.344 +} 1.345 + 1.346 +/* void selectionChanged (); */ 1.347 +NS_IMETHODIMP 1.348 +nsNSSASN1Tree::SelectionChanged() 1.349 +{ 1.350 + return NS_ERROR_NOT_IMPLEMENTED; 1.351 +} 1.352 + 1.353 +/* void cycleCell (in long row, in nsITreeColumn col); */ 1.354 +NS_IMETHODIMP 1.355 +nsNSSASN1Tree::CycleCell(int32_t row, nsITreeColumn* col) 1.356 +{ 1.357 + return NS_OK; 1.358 +} 1.359 + 1.360 +/* boolean isEditable (in long row, in nsITreeColumn col); */ 1.361 +NS_IMETHODIMP 1.362 +nsNSSASN1Tree::IsEditable(int32_t row, nsITreeColumn* col, 1.363 + bool *_retval) 1.364 +{ 1.365 + *_retval = false; 1.366 + return NS_OK; 1.367 +} 1.368 + 1.369 +/* boolean isSelectable (in long row, in nsITreeColumn col); */ 1.370 +NS_IMETHODIMP 1.371 +nsNSSASN1Tree::IsSelectable(int32_t row, nsITreeColumn* col, 1.372 + bool *_retval) 1.373 +{ 1.374 + *_retval = false; 1.375 + return NS_OK; 1.376 +} 1.377 + 1.378 +/* void setCellValue (in long row, in nsITreeColumn col, in AString value); */ 1.379 +NS_IMETHODIMP 1.380 +nsNSSASN1Tree::SetCellValue(int32_t row, nsITreeColumn* col, 1.381 + const nsAString& value) 1.382 +{ 1.383 + return NS_OK; 1.384 +} 1.385 + 1.386 +/* void setCellText (in long row, in nsITreeColumn col, in AString value); */ 1.387 +NS_IMETHODIMP 1.388 +nsNSSASN1Tree::SetCellText(int32_t row, nsITreeColumn* col, 1.389 + const nsAString& value) 1.390 +{ 1.391 + return NS_OK; 1.392 +} 1.393 + 1.394 +/* void performAction (in wstring action); */ 1.395 +NS_IMETHODIMP 1.396 +nsNSSASN1Tree::PerformAction(const char16_t *action) 1.397 +{ 1.398 + return NS_OK; 1.399 +} 1.400 + 1.401 +/* void performActionOnRow (in wstring action, in long row); */ 1.402 +NS_IMETHODIMP 1.403 +nsNSSASN1Tree::PerformActionOnRow(const char16_t *action, int32_t row) 1.404 +{ 1.405 + return NS_OK; 1.406 +} 1.407 + 1.408 +/* void performActionOnCell (in wstring action, in long row, in nsITreeColumn col); */ 1.409 +NS_IMETHODIMP 1.410 +nsNSSASN1Tree::PerformActionOnCell(const char16_t *action, int32_t row, 1.411 + nsITreeColumn* col) 1.412 +{ 1.413 + return NS_OK; 1.414 +} 1.415 + 1.416 +// 1.417 +// CanDrop 1.418 +// 1.419 +NS_IMETHODIMP nsNSSASN1Tree::CanDrop(int32_t index, int32_t orientation, 1.420 + nsIDOMDataTransfer* aDataTransfer, bool *_retval) 1.421 +{ 1.422 + NS_ENSURE_ARG_POINTER(_retval); 1.423 + *_retval = false; 1.424 + 1.425 + return NS_OK; 1.426 +} 1.427 + 1.428 + 1.429 +// 1.430 +// Drop 1.431 +// 1.432 +NS_IMETHODIMP nsNSSASN1Tree::Drop(int32_t row, int32_t orient, nsIDOMDataTransfer* aDataTransfer) 1.433 +{ 1.434 + return NS_OK; 1.435 +} 1.436 + 1.437 + 1.438 +// 1.439 +// IsSorted 1.440 +// 1.441 +// ... 1.442 +// 1.443 +NS_IMETHODIMP nsNSSASN1Tree::IsSorted(bool *_retval) 1.444 +{ 1.445 + *_retval = false; 1.446 + return NS_OK; 1.447 +} 1.448 + 1.449 + 1.450 +/* long getParentIndex (in long rowIndex); */ 1.451 +NS_IMETHODIMP 1.452 +nsNSSASN1Tree::GetParentIndex(int32_t rowIndex, int32_t *_retval) 1.453 +{ 1.454 + int32_t parentIndex = -1; 1.455 + 1.456 + myNode *n = FindNodeFromIndex(rowIndex, &parentIndex); 1.457 + if (!n) 1.458 + return NS_ERROR_FAILURE; 1.459 + 1.460 + *_retval = parentIndex; 1.461 + return NS_OK; 1.462 +} 1.463 + 1.464 +/* boolean hasNextSibling (in long rowIndex, in long afterIndex); */ 1.465 +NS_IMETHODIMP 1.466 +nsNSSASN1Tree::HasNextSibling(int32_t rowIndex, int32_t afterIndex, 1.467 + bool *_retval) 1.468 +{ 1.469 + myNode *n = FindNodeFromIndex(rowIndex); 1.470 + if (!n) 1.471 + return NS_ERROR_FAILURE; 1.472 + 1.473 + if (!n->next) { 1.474 + *_retval = false; 1.475 + } 1.476 + else { 1.477 + int32_t nTotalSize = CountVisibleNodes(n); 1.478 + int32_t nLastChildPos = rowIndex + nTotalSize -1; 1.479 + int32_t nextSiblingPos = nLastChildPos +1; 1.480 + *_retval = (nextSiblingPos > afterIndex); 1.481 + } 1.482 + 1.483 + return NS_OK; 1.484 +} 1.485 + 1.486 +int32_t nsNSSASN1Tree::CountVisibleNodes(myNode *n) 1.487 +{ 1.488 + if (!n) 1.489 + return 0; 1.490 + 1.491 + myNode *walk = n; 1.492 + int32_t count = 0; 1.493 + 1.494 + while (walk) { 1.495 + ++count; 1.496 + 1.497 + if (walk->seq) { 1.498 + bool IsExpanded; 1.499 + walk->seq->GetIsExpanded(&IsExpanded); 1.500 + if (IsExpanded) { 1.501 + count += CountVisibleNodes(walk->child); 1.502 + } 1.503 + } 1.504 + 1.505 + walk = walk->next; 1.506 + } 1.507 + 1.508 + return count; 1.509 +} 1.510 + 1.511 +// Entry point for find 1.512 +nsNSSASN1Tree::myNode * 1.513 +nsNSSASN1Tree::FindNodeFromIndex(int32_t wantedIndex, 1.514 + int32_t *optionalOutParentIndex, int32_t *optionalOutLevel) 1.515 +{ 1.516 + if (0 == wantedIndex) { 1.517 + if (optionalOutLevel) { 1.518 + *optionalOutLevel = 0; 1.519 + } 1.520 + if (optionalOutParentIndex) { 1.521 + *optionalOutParentIndex = -1; 1.522 + } 1.523 + return mTopNode; 1.524 + } 1.525 + else { 1.526 + int32_t index = 0; 1.527 + int32_t level = 0; 1.528 + return FindNodeFromIndex(mTopNode, wantedIndex, index, level, 1.529 + optionalOutParentIndex, optionalOutLevel); 1.530 + } 1.531 +} 1.532 + 1.533 +// Internal recursive helper function 1.534 +nsNSSASN1Tree::myNode * 1.535 +nsNSSASN1Tree::FindNodeFromIndex(myNode *n, int32_t wantedIndex, 1.536 + int32_t &index_counter, int32_t &level_counter, 1.537 + int32_t *optionalOutParentIndex, int32_t *optionalOutLevel) 1.538 +{ 1.539 + if (!n) 1.540 + return nullptr; 1.541 + 1.542 + myNode *walk = n; 1.543 + int32_t parentIndex = index_counter-1; 1.544 + 1.545 + while (walk) { 1.546 + if (index_counter == wantedIndex) { 1.547 + if (optionalOutLevel) { 1.548 + *optionalOutLevel = level_counter; 1.549 + } 1.550 + if (optionalOutParentIndex) { 1.551 + *optionalOutParentIndex = parentIndex; 1.552 + } 1.553 + return walk; 1.554 + } 1.555 + 1.556 + if (walk->seq) { 1.557 + bool IsExpanded; 1.558 + walk->seq->GetIsExpanded(&IsExpanded); 1.559 + if (IsExpanded) { 1.560 + ++index_counter; // set to walk->child 1.561 + 1.562 + ++level_counter; 1.563 + myNode *found = FindNodeFromIndex(walk->child, wantedIndex, index_counter, level_counter, 1.564 + optionalOutParentIndex, optionalOutLevel); 1.565 + --level_counter; 1.566 + 1.567 + if (found) 1.568 + return found; 1.569 + } 1.570 + } 1.571 + 1.572 + walk = walk->next; 1.573 + if (walk) { 1.574 + ++index_counter; 1.575 + } 1.576 + } 1.577 + 1.578 + return nullptr; 1.579 +} 1.580 +