/security/manager/pki/src/nsASN1Tree.cpp

http://github.com/zpao/v8monkey · C++ · 617 lines · 424 code · 93 blank · 100 comment · 51 complexity · fd99134799e7f69aa577191818e5bba8 MD5 · raw file

  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3. *
  4. * The contents of this file are subject to the Mozilla Public License Version
  5. * 1.1 (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. * http://www.mozilla.org/MPL/
  8. *
  9. * Software distributed under the License is distributed on an "AS IS" basis,
  10. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. * for the specific language governing rights and limitations under the
  12. * License.
  13. *
  14. * The Original Code is the Netscape security libraries.
  15. *
  16. * The Initial Developer of the Original Code is
  17. * Netscape Communications Corporation.
  18. * Portions created by the Initial Developer are Copyright (C) 1994-2000
  19. * the Initial Developer. All Rights Reserved.
  20. *
  21. * Contributor(s):
  22. * Javier Delgadillo <javi@netscape.com>
  23. *
  24. * Alternatively, the contents of this file may be used under the terms of
  25. * either the GNU General Public License Version 2 or later (the "GPL"), or
  26. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  27. * in which case the provisions of the GPL or the LGPL are applicable instead
  28. * of those above. If you wish to allow use of your version of this file only
  29. * under the terms of either the GPL or the LGPL, and not to allow others to
  30. * use your version of this file under the terms of the MPL, indicate your
  31. * decision by deleting the provisions above and replace them with the notice
  32. * and other provisions required by the GPL or the LGPL. If you do not delete
  33. * the provisions above, a recipient may use your version of this file under
  34. * the terms of any one of the MPL, the GPL or the LGPL.
  35. *
  36. * ***** END LICENSE BLOCK ***** */
  37. #include "nsASN1Tree.h"
  38. #include "nsIComponentManager.h"
  39. #include "nsString.h"
  40. #include "nsCRT.h"
  41. #include "nsIMutableArray.h"
  42. #include "nsArrayUtils.h"
  43. NS_IMPL_THREADSAFE_ISUPPORTS2(nsNSSASN1Tree, nsIASN1Tree,
  44. nsITreeView)
  45. nsNSSASN1Tree::nsNSSASN1Tree()
  46. :mTopNode(nsnull)
  47. {
  48. }
  49. nsNSSASN1Tree::~nsNSSASN1Tree()
  50. {
  51. ClearNodes();
  52. }
  53. void nsNSSASN1Tree::ClearNodesRecursively(myNode *n)
  54. {
  55. myNode *walk = n;
  56. while (walk) {
  57. myNode *kill = walk;
  58. if (walk->child) {
  59. ClearNodesRecursively(walk->child);
  60. }
  61. walk = walk->next;
  62. delete kill;
  63. }
  64. }
  65. void nsNSSASN1Tree::ClearNodes()
  66. {
  67. ClearNodesRecursively(mTopNode);
  68. mTopNode = nsnull;
  69. }
  70. void nsNSSASN1Tree::InitChildsRecursively(myNode *n)
  71. {
  72. if (!n->obj)
  73. return;
  74. n->seq = do_QueryInterface(n->obj);
  75. if (!n->seq)
  76. return;
  77. // If the object is a sequence, there might still be a reason
  78. // why it should not be displayed as a container.
  79. // If we decide that it has all the properties to justify
  80. // displaying as a container, we will create a new child chain.
  81. // If we decide, it does not make sense to display as a container,
  82. // we forget that it is a sequence by erasing n->seq.
  83. // That way, n->seq and n->child will be either both set or both null.
  84. bool isContainer;
  85. n->seq->GetIsValidContainer(&isContainer);
  86. if (!isContainer) {
  87. n->seq = nsnull;
  88. return;
  89. }
  90. nsCOMPtr<nsIMutableArray> asn1Objects;
  91. n->seq->GetASN1Objects(getter_AddRefs(asn1Objects));
  92. PRUint32 numObjects;
  93. asn1Objects->GetLength(&numObjects);
  94. if (!numObjects) {
  95. n->seq = nsnull;
  96. return;
  97. }
  98. myNode *walk = nsnull;
  99. myNode *prev = nsnull;
  100. PRUint32 i;
  101. nsCOMPtr<nsISupports> isupports;
  102. for (i=0; i<numObjects; i++) {
  103. if (0 == i) {
  104. n->child = walk = new myNode;
  105. }
  106. else {
  107. walk = new myNode;
  108. }
  109. walk->parent = n;
  110. if (prev) {
  111. prev->next = walk;
  112. }
  113. walk->obj = do_QueryElementAt(asn1Objects, i);
  114. InitChildsRecursively(walk);
  115. prev = walk;
  116. }
  117. }
  118. void nsNSSASN1Tree::InitNodes()
  119. {
  120. ClearNodes();
  121. mTopNode = new myNode;
  122. mTopNode->obj = mASN1Object;
  123. InitChildsRecursively(mTopNode);
  124. }
  125. /* void loadASN1Structure (in nsIASN1Object asn1Object); */
  126. NS_IMETHODIMP
  127. nsNSSASN1Tree::LoadASN1Structure(nsIASN1Object *asn1Object)
  128. {
  129. //
  130. // The tree won't automatically re-draw if the contents
  131. // have been changed. So I do a quick test here to let
  132. // me know if I should forced the tree to redraw itself
  133. // by calling RowCountChanged on it.
  134. //
  135. bool redraw = (mASN1Object && mTree);
  136. PRInt32 rowsToDelete = 0;
  137. if (redraw) {
  138. // This is the number of rows we will be deleting after
  139. // the contents have changed.
  140. rowsToDelete = 0-CountVisibleNodes(mTopNode);
  141. }
  142. mASN1Object = asn1Object;
  143. InitNodes();
  144. if (redraw) {
  145. // The number of rows in the new content.
  146. PRInt32 newRows = CountVisibleNodes(mTopNode);
  147. mTree->BeginUpdateBatch();
  148. // Erase all of the old rows.
  149. mTree->RowCountChanged(0, rowsToDelete);
  150. // Replace them with the new contents
  151. mTree->RowCountChanged(0, newRows);
  152. mTree->EndUpdateBatch();
  153. }
  154. return NS_OK;
  155. }
  156. /* readonly attribute long rowCount; */
  157. NS_IMETHODIMP
  158. nsNSSASN1Tree::GetRowCount(PRInt32 *aRowCount)
  159. {
  160. if (mASN1Object) {
  161. *aRowCount = CountVisibleNodes(mTopNode);
  162. } else {
  163. *aRowCount = 0;
  164. }
  165. return NS_OK;
  166. }
  167. /* attribute nsITreeSelection selection; */
  168. NS_IMETHODIMP
  169. nsNSSASN1Tree::GetSelection(nsITreeSelection * *aSelection)
  170. {
  171. *aSelection = mSelection;
  172. NS_IF_ADDREF(*aSelection);
  173. return NS_OK;
  174. }
  175. NS_IMETHODIMP
  176. nsNSSASN1Tree::SetSelection(nsITreeSelection * aSelection)
  177. {
  178. mSelection = aSelection;
  179. return NS_OK;
  180. }
  181. /* void getRowProperties (in long index, in nsISupportsArray properties); */
  182. NS_IMETHODIMP
  183. nsNSSASN1Tree::GetRowProperties(PRInt32 index, nsISupportsArray *properties)
  184. {
  185. return NS_OK;
  186. }
  187. /* void getCellProperties (in long row, in nsITreeColumn col,
  188. in nsISupportsArray properties); */
  189. NS_IMETHODIMP
  190. nsNSSASN1Tree::GetCellProperties(PRInt32 row, nsITreeColumn* col,
  191. nsISupportsArray *properties)
  192. {
  193. return NS_OK;
  194. }
  195. /* void getColumnProperties (in nsITreeColumn col,
  196. in nsISupportsArray properties); */
  197. NS_IMETHODIMP
  198. nsNSSASN1Tree::GetColumnProperties(nsITreeColumn* col,
  199. nsISupportsArray *properties)
  200. {
  201. return NS_OK;
  202. }
  203. /* boolean isContainer (in long index); */
  204. NS_IMETHODIMP
  205. nsNSSASN1Tree::IsContainer(PRInt32 index, bool *_retval)
  206. {
  207. myNode *n = FindNodeFromIndex(index);
  208. if (!n)
  209. return NS_ERROR_FAILURE;
  210. *_retval = (n->seq != nsnull);
  211. return NS_OK;
  212. }
  213. /* boolean isContainerOpen (in long index); */
  214. NS_IMETHODIMP
  215. nsNSSASN1Tree::IsContainerOpen(PRInt32 index, bool *_retval)
  216. {
  217. myNode *n = FindNodeFromIndex(index);
  218. if (!n || !n->seq)
  219. return NS_ERROR_FAILURE;
  220. n->seq->GetIsExpanded(_retval);
  221. return NS_OK;
  222. }
  223. /* boolean isContainerEmpty (in long index); */
  224. NS_IMETHODIMP
  225. nsNSSASN1Tree::IsContainerEmpty(PRInt32 index, bool *_retval)
  226. {
  227. *_retval = false;
  228. return NS_OK;
  229. }
  230. /* boolean isSeparator (in long index); */
  231. NS_IMETHODIMP
  232. nsNSSASN1Tree::IsSeparator(PRInt32 index, bool *_retval)
  233. {
  234. *_retval = false;
  235. return NS_OK;
  236. }
  237. /* long getLevel (in long index); */
  238. NS_IMETHODIMP
  239. nsNSSASN1Tree::GetLevel(PRInt32 index, PRInt32 *_retval)
  240. {
  241. PRInt32 parentIndex;
  242. PRInt32 nodeLevel;
  243. myNode *n = FindNodeFromIndex(index, &parentIndex, &nodeLevel);
  244. if (!n)
  245. return NS_ERROR_FAILURE;
  246. *_retval = nodeLevel;
  247. return NS_OK;
  248. }
  249. /* Astring getImageSrc (in long row, in nsITreeColumn col); */
  250. NS_IMETHODIMP
  251. nsNSSASN1Tree::GetImageSrc(PRInt32 row, nsITreeColumn* col,
  252. nsAString& _retval)
  253. {
  254. return NS_OK;
  255. }
  256. /* long getProgressMode (in long row, in nsITreeColumn col); */
  257. NS_IMETHODIMP
  258. nsNSSASN1Tree::GetProgressMode(PRInt32 row, nsITreeColumn* col, PRInt32* _retval)
  259. {
  260. return NS_OK;
  261. }
  262. /* Astring getCellValue (in long row, in nsITreeColumn col); */
  263. NS_IMETHODIMP
  264. nsNSSASN1Tree::GetCellValue(PRInt32 row, nsITreeColumn* col,
  265. nsAString& _retval)
  266. {
  267. return NS_OK;
  268. }
  269. /* Astring getCellText (in long row, in nsITreeColumn col); */
  270. NS_IMETHODIMP
  271. nsNSSASN1Tree::GetCellText(PRInt32 row, nsITreeColumn* col,
  272. nsAString& _retval)
  273. {
  274. _retval.Truncate();
  275. myNode* n = FindNodeFromIndex(row);
  276. if (!n)
  277. return NS_ERROR_FAILURE;
  278. // There's only one column for ASN1 dump.
  279. return n->obj->GetDisplayName(_retval);
  280. }
  281. /* wstring getDisplayData (in unsigned long index); */
  282. NS_IMETHODIMP
  283. nsNSSASN1Tree::GetDisplayData(PRUint32 index, nsAString &_retval)
  284. {
  285. myNode *n = FindNodeFromIndex(index);
  286. if (!n)
  287. return NS_ERROR_FAILURE;
  288. n->obj->GetDisplayValue(_retval);
  289. return NS_OK;
  290. }
  291. /* void setTree (in nsITreeBoxObject tree); */
  292. NS_IMETHODIMP
  293. nsNSSASN1Tree::SetTree(nsITreeBoxObject *tree)
  294. {
  295. mTree = tree;
  296. return NS_OK;
  297. }
  298. /* void toggleOpenState (in long index); */
  299. NS_IMETHODIMP
  300. nsNSSASN1Tree::ToggleOpenState(PRInt32 index)
  301. {
  302. myNode *n = FindNodeFromIndex(index);
  303. if (!n)
  304. return NS_ERROR_FAILURE;
  305. if (!n->seq)
  306. return NS_ERROR_FAILURE;
  307. bool IsExpanded;
  308. n->seq->GetIsExpanded(&IsExpanded);
  309. PRInt32 rowCountChange;
  310. if (IsExpanded) {
  311. rowCountChange = -CountVisibleNodes(n->child);
  312. n->seq->SetIsExpanded(false);
  313. } else {
  314. n->seq->SetIsExpanded(true);
  315. rowCountChange = CountVisibleNodes(n->child);
  316. }
  317. if (mTree)
  318. mTree->RowCountChanged(index, rowCountChange);
  319. return NS_OK;
  320. }
  321. /* void cycleHeader (in nsITreeColumn col); */
  322. NS_IMETHODIMP
  323. nsNSSASN1Tree::CycleHeader(nsITreeColumn* col)
  324. {
  325. return NS_OK;
  326. }
  327. /* void selectionChanged (); */
  328. NS_IMETHODIMP
  329. nsNSSASN1Tree::SelectionChanged()
  330. {
  331. return NS_ERROR_NOT_IMPLEMENTED;
  332. }
  333. /* void cycleCell (in long row, in nsITreeColumn col); */
  334. NS_IMETHODIMP
  335. nsNSSASN1Tree::CycleCell(PRInt32 row, nsITreeColumn* col)
  336. {
  337. return NS_OK;
  338. }
  339. /* boolean isEditable (in long row, in nsITreeColumn col); */
  340. NS_IMETHODIMP
  341. nsNSSASN1Tree::IsEditable(PRInt32 row, nsITreeColumn* col,
  342. bool *_retval)
  343. {
  344. *_retval = false;
  345. return NS_OK;
  346. }
  347. /* boolean isSelectable (in long row, in nsITreeColumn col); */
  348. NS_IMETHODIMP
  349. nsNSSASN1Tree::IsSelectable(PRInt32 row, nsITreeColumn* col,
  350. bool *_retval)
  351. {
  352. *_retval = false;
  353. return NS_OK;
  354. }
  355. /* void setCellValue (in long row, in nsITreeColumn col, in AString value); */
  356. NS_IMETHODIMP
  357. nsNSSASN1Tree::SetCellValue(PRInt32 row, nsITreeColumn* col,
  358. const nsAString& value)
  359. {
  360. return NS_OK;
  361. }
  362. /* void setCellText (in long row, in nsITreeColumn col, in AString value); */
  363. NS_IMETHODIMP
  364. nsNSSASN1Tree::SetCellText(PRInt32 row, nsITreeColumn* col,
  365. const nsAString& value)
  366. {
  367. return NS_OK;
  368. }
  369. /* void performAction (in wstring action); */
  370. NS_IMETHODIMP
  371. nsNSSASN1Tree::PerformAction(const PRUnichar *action)
  372. {
  373. return NS_OK;
  374. }
  375. /* void performActionOnRow (in wstring action, in long row); */
  376. NS_IMETHODIMP
  377. nsNSSASN1Tree::PerformActionOnRow(const PRUnichar *action, PRInt32 row)
  378. {
  379. return NS_OK;
  380. }
  381. /* void performActionOnCell (in wstring action, in long row, in nsITreeColumn col); */
  382. NS_IMETHODIMP
  383. nsNSSASN1Tree::PerformActionOnCell(const PRUnichar *action, PRInt32 row,
  384. nsITreeColumn* col)
  385. {
  386. return NS_OK;
  387. }
  388. //
  389. // CanDrop
  390. //
  391. NS_IMETHODIMP nsNSSASN1Tree::CanDrop(PRInt32 index, PRInt32 orientation,
  392. nsIDOMDataTransfer* aDataTransfer, bool *_retval)
  393. {
  394. NS_ENSURE_ARG_POINTER(_retval);
  395. *_retval = false;
  396. return NS_OK;
  397. }
  398. //
  399. // Drop
  400. //
  401. NS_IMETHODIMP nsNSSASN1Tree::Drop(PRInt32 row, PRInt32 orient, nsIDOMDataTransfer* aDataTransfer)
  402. {
  403. return NS_OK;
  404. }
  405. //
  406. // IsSorted
  407. //
  408. // ...
  409. //
  410. NS_IMETHODIMP nsNSSASN1Tree::IsSorted(bool *_retval)
  411. {
  412. *_retval = false;
  413. return NS_OK;
  414. }
  415. /* long getParentIndex (in long rowIndex); */
  416. NS_IMETHODIMP
  417. nsNSSASN1Tree::GetParentIndex(PRInt32 rowIndex, PRInt32 *_retval)
  418. {
  419. PRInt32 parentIndex = -1;
  420. myNode *n = FindNodeFromIndex(rowIndex, &parentIndex);
  421. if (!n)
  422. return NS_ERROR_FAILURE;
  423. *_retval = parentIndex;
  424. return NS_OK;
  425. }
  426. /* boolean hasNextSibling (in long rowIndex, in long afterIndex); */
  427. NS_IMETHODIMP
  428. nsNSSASN1Tree::HasNextSibling(PRInt32 rowIndex, PRInt32 afterIndex,
  429. bool *_retval)
  430. {
  431. myNode *n = FindNodeFromIndex(rowIndex);
  432. if (!n)
  433. return NS_ERROR_FAILURE;
  434. if (!n->next) {
  435. *_retval = false;
  436. }
  437. else {
  438. PRInt32 nTotalSize = CountVisibleNodes(n);
  439. PRInt32 nLastChildPos = rowIndex + nTotalSize -1;
  440. PRInt32 nextSiblingPos = nLastChildPos +1;
  441. *_retval = (nextSiblingPos > afterIndex);
  442. }
  443. return NS_OK;
  444. }
  445. PRInt32 nsNSSASN1Tree::CountVisibleNodes(myNode *n)
  446. {
  447. if (!n)
  448. return 0;
  449. myNode *walk = n;
  450. PRInt32 count = 0;
  451. while (walk) {
  452. ++count;
  453. if (walk->seq) {
  454. bool IsExpanded;
  455. walk->seq->GetIsExpanded(&IsExpanded);
  456. if (IsExpanded) {
  457. count += CountVisibleNodes(walk->child);
  458. }
  459. }
  460. walk = walk->next;
  461. }
  462. return count;
  463. }
  464. // Entry point for find
  465. nsNSSASN1Tree::myNode *
  466. nsNSSASN1Tree::FindNodeFromIndex(PRInt32 wantedIndex,
  467. PRInt32 *optionalOutParentIndex, PRInt32 *optionalOutLevel)
  468. {
  469. if (0 == wantedIndex) {
  470. if (optionalOutLevel) {
  471. *optionalOutLevel = 0;
  472. }
  473. if (optionalOutParentIndex) {
  474. *optionalOutParentIndex = -1;
  475. }
  476. return mTopNode;
  477. }
  478. else {
  479. PRInt32 index = 0;
  480. PRInt32 level = 0;
  481. return FindNodeFromIndex(mTopNode, wantedIndex, index, level,
  482. optionalOutParentIndex, optionalOutLevel);
  483. }
  484. }
  485. // Internal recursive helper function
  486. nsNSSASN1Tree::myNode *
  487. nsNSSASN1Tree::FindNodeFromIndex(myNode *n, PRInt32 wantedIndex,
  488. PRInt32 &index_counter, PRInt32 &level_counter,
  489. PRInt32 *optionalOutParentIndex, PRInt32 *optionalOutLevel)
  490. {
  491. if (!n)
  492. return nsnull;
  493. myNode *walk = n;
  494. PRInt32 parentIndex = index_counter-1;
  495. while (walk) {
  496. if (index_counter == wantedIndex) {
  497. if (optionalOutLevel) {
  498. *optionalOutLevel = level_counter;
  499. }
  500. if (optionalOutParentIndex) {
  501. *optionalOutParentIndex = parentIndex;
  502. }
  503. return walk;
  504. }
  505. if (walk->seq) {
  506. bool IsExpanded;
  507. walk->seq->GetIsExpanded(&IsExpanded);
  508. if (IsExpanded) {
  509. ++index_counter; // set to walk->child
  510. ++level_counter;
  511. myNode *found = FindNodeFromIndex(walk->child, wantedIndex, index_counter, level_counter,
  512. optionalOutParentIndex, optionalOutLevel);
  513. --level_counter;
  514. if (found)
  515. return found;
  516. }
  517. }
  518. walk = walk->next;
  519. if (walk) {
  520. ++index_counter;
  521. }
  522. }
  523. return nsnull;
  524. }