示例#1
0
 private static FindingViewItem joinFindingViewItemAndFollowTreeNodeChilds_Recursive(
     FindingViewItem fviTargetFindingViewItem, TreeNode tnTreeNodeWithTraces)
 {
     if (tnTreeNodeWithTraces != null)
     {
         if (tnTreeNodeWithTraces.Tag != null)
         {
             if (fviTargetFindingViewItem.fFinding == null) // means this is the first one
             {
                 fviTargetFindingViewItem =
                     VirtualTraces.createNewFindingViewItemFromFindingViewItem(
                         (FindingViewItem) tnTreeNodeWithTraces.Tag);
             }
             else
             {
                 fviTargetFindingViewItem = VirtualTraces.connectTwoFindingNewItems(fviTargetFindingViewItem,
                                                                                    (FindingViewItem)
                                                                                    tnTreeNodeWithTraces.Tag);
                 /*( if (fviTargetFindingViewItem == null)
                 {                            
                      DI.log.info("appendTrace_FindingSourceToFindingSink error, happened for {0}", analyzer.getUniqueSignature(((FindingViewItem)tnTreeNodeWithTraces.Tag).fFinding, Analysis.TraceType.Known_Sink, ((FindingViewItem)tnTreeNodeWithTraces.Tag).oadO2AssessmentDataOunceV6, true));
                     return null;
                 }*/
             }
         }
         foreach (TreeNode tnChildNodes in tnTreeNodeWithTraces.Nodes)
             fviTargetFindingViewItem =
                 joinFindingViewItemAndFollowTreeNodeChilds_Recursive(fviTargetFindingViewItem, tnChildNodes);
     }
     return fviTargetFindingViewItem;
 }
示例#2
0
        public static FindingViewItem createJoinedUpFindingViewItemFromTreeNodeWithFindingViewItemAsTags(
            TreeNode tnTreeNode)
        {
            var fviFindingViewItem = new FindingViewItem();

            fviFindingViewItem = joinFindingViewItemAndFollowTreeNodeChilds_Recursive(fviFindingViewItem, tnTreeNode);

            return fviFindingViewItem;
        }
示例#3
0
        //public static createNewO2AssessmentDataAndFindingFrom

        public static FindingViewItem createNewFindingViewItemFromFindingViewItem(
            FindingViewItem fviFindingViewItemToDuplicate)
        {
            var nfviNewFindingViewItem = new NewFindingViewItem();

            AssessmentAssessmentFileFinding fNewFinding =
                nfviNewFindingViewItem.AddNewFindingFromExistingOne(fviFindingViewItemToDuplicate.fFinding,
                                                                    fviFindingViewItemToDuplicate.oadO2AssessmentDataOunceV6);

            nfviNewFindingViewItem.updateOadStringLists();

            return nfviNewFindingViewItem.getFindingViewItemForLastFindingAdded();
        }
示例#4
0
 public static TreeNode getRootNodeToView(O2TraceBlock_OunceV6 otbO2TraceBlockOfRootNode, String sMode)
 {
     //var tnTreeNode = new TreeNode(sRootFunction);
     var tnTreeNode = new TreeNode(otbO2TraceBlockOfRootNode.sUniqueName);
     if (sMode == "Sinks")
     {
         Dictionary<AssessmentAssessmentFileFinding, O2AssessmentData_OunceV6> dSinks = otbO2TraceBlockOfRootNode.dSinks;
         foreach (AssessmentAssessmentFileFinding fFinding in dSinks.Keys)
         {
             var fviFindingViewItem = new FindingViewItem(fFinding, fFinding.vuln_name, null, dSinks[fFinding]);
             String sNodeText = analyzer.getUniqueSignature(fFinding, TraceType.Known_Sink,
                                                            dSinks[fFinding], true);
             if (sNodeText != null)
             {
                 TreeNode tnChildNode = O2Forms.newTreeNode(sNodeText, sNodeText, 0, fviFindingViewItem);
                 tnTreeNode.Nodes.Add(tnChildNode);
             }
         }
     }
     return tnTreeNode;
 }
示例#5
0
        public static FindingViewItem connectTwoFindingNewItems(FindingViewItem fviJoinAtSink,
                                                                FindingViewItem fviJoinAtSource)
        {
            var nfviNewFindingViewItem = new NewFindingViewItem();

            AssessmentAssessmentFileFinding fNewFinding =
                nfviNewFindingViewItem.AddNewFindingFromExistingOne(fviJoinAtSink.fFinding,
                                                                    fviJoinAtSink.oadO2AssessmentDataOunceV6);

            if (false == nfviNewFindingViewItem.appendTrace_FindingSourceToFindingSink(fNewFinding, fviJoinAtSource))
            {
                /*  DI.log.info("___ appendTrace_FindingSourceToFindingSink error, happened for Source: {0}", o2.analysis.Analysis.getSource(fNewFinding, fviJoinAtSink.oadO2AssessmentDataOunceV6));
                CallInvocation ciSink = AnalysisSearch.findTraceTypeInSmartTrace_Recursive_returnCallInvocation(fNewFinding.Trace, Analysis.TraceType.Known_Sink);
                if (ciSink != null)
                     DI.log.info("appendTrace_FindingSourceToFindingSink error, happened for Sink: {0}", Analysis.getStringIndexValue(ciSink.sig_id,fviJoinAtSink.oadO2AssessmentDataOunceV6));
                return null;*/
            }

//            oadNewO2AssessmentDataOunceV6.arAssessmentRun.Assessment = new AssessmentRunAssessment();

            nfviNewFindingViewItem.updateOadStringLists();

            return nfviNewFindingViewItem.getFindingViewItemForLastFindingAdded();
        }
示例#6
0
 public void removeFindingViewItemToList(FindingViewItem fviFindingViewItem)
 {
     if (lfviCurrentListOfFindingViewItems.Contains(fviFindingViewItem))
         lfviCurrentListOfFindingViewItems.Remove(fviFindingViewItem);
     else
         DI.log.error("{0} doesn't exist in lis5", fviFindingViewItem.sText);
 }
示例#7
0
 public void addFindingViewItemToList(FindingViewItem fviFindingViewItem)
 {
     lfviCurrentListOfFindingViewItems.Add(fviFindingViewItem);
     DI.log.debug("{0} item added to list", fviFindingViewItem.sText);
 }
示例#8
0
            public static bool ResolveInterfacesOnTreeView_recursive(TreeNode tnStartNode, ICirData cdCirData,
                                                                     Dictionary<String, O2TraceBlock_OunceV6> dO2TraceBlock,
                                                                    Dictionary<String, O2TraceBlock_OunceV6> dRawData,
                                                                     //TreeView tvRawData_,
                                                                     String sHardCodedInterfaceKeywork)
            {
                var stStackTrace = new StackTrace();
                if (stStackTrace.FrameCount > 50)
                {
                    String sMsg =
                        String.Format(
                            "on ResolveInterfacesOnTreeView_recursive, max StackTrace reached, aborting this leaf:{0}",
                            tnStartNode.Text);
                    DI.log.error(sMsg);
                    return false;
                }
                if (tnStartNode != null)
                    foreach (TreeNode tnNode in tnStartNode.Nodes)
                    {
                        if (tnNode.Text.IndexOf(sHardCodedInterfaceKeywork) > -1)
                            if (tnNode.Tag != null)
                            {
                                var fviFindingViewItem = (FindingViewItem) tnNode.Tag;
                                String sSink = AnalysisUtils.getSink(fviFindingViewItem.fFinding,
                                                                     fviFindingViewItem.oadO2AssessmentDataOunceV6);
                                if (cdCirData.dFunctions_bySignature.ContainsKey(sSink))
                                {
                                    ICirFunction cfCirFunction = cdCirData.dFunctions_bySignature[sSink];
                                    ICirClass ccCirClass = cfCirFunction.ParentClass;
                                    foreach (ICirClass ccIsSuperClassedBy in ccCirClass.dIsSuperClassedBy.Values)
                                    {
                                        String sMappedMethodName =
                                            cfCirFunction.FunctionSignature.Replace(ccCirClass.Signature,
                                                                                    ccIsSuperClassedBy.Signature);
                                        List<O2TraceBlock_OunceV6> lotdMatches =
                                            analyzer.getO2TraceBlocksThatMatchSignature(sMappedMethodName, dO2TraceBlock);
                                        foreach (O2TraceBlock_OunceV6 otbO2TraceBlock in lotdMatches)
                                        {
                                            TreeNode tnNewNode_forImplementation =
                                                O2Forms.newTreeNode(otbO2TraceBlock.sUniqueName,
                                                                    otbO2TraceBlock.sUniqueName, 0, null);
                                            tnNode.ForeColor = Color.CadetBlue;
                                            tnNewNode_forImplementation.ForeColor = Color.DarkBlue;
                                            foreach (
                                                AssessmentAssessmentFileFinding fFinding in otbO2TraceBlock.dSinks.Keys)
                                            {
                                                var fviFindingViewItem_ForSink = new FindingViewItem(fFinding,
                                                                                                     fFinding.vuln_name ?? OzasmtUtils_OunceV6.
                                                                                                                               getStringIndexValue
                                                                                                                               (UInt32.Parse
                                                                                                                                    (fFinding
                                                                                                                                         .
                                                                                                                                         vuln_name_id),
                                                                                                                                otbO2TraceBlock.dSinks[fFinding]),
                                                                                                     null,
                                                                                                     otbO2TraceBlock.
                                                                                                         dSinks[fFinding
                                                                                                         ]);
                                                String sUniqueName_ForSink =
                                                    analyzer.getUniqueSignature(fviFindingViewItem_ForSink.fFinding,
                                                                                TraceType.Known_Sink,
                                                                                fviFindingViewItem_ForSink.
                                                                                    oadO2AssessmentDataOunceV6, true);
                                                TreeNode tnImplementation_Sink = O2Forms.newTreeNode(
                                                    sUniqueName_ForSink, sUniqueName_ForSink, 0,
                                                    fviFindingViewItem_ForSink);
                                                tnNewNode_forImplementation.Nodes.Add(tnImplementation_Sink);
                                                if (tnImplementation_Sink.Text != "")
                                                    if (false ==
                                                        analyzer.addCompatibleTracesToNode_recursive(
                                                            tnImplementation_Sink, fviFindingViewItem_ForSink,
                                                        dRawData[tnImplementation_Sink.Text], "Sinks",  dRawData))
//                                                            (O2TraceBlock_OunceV6)
//                                                            tvRawData.Nodes[tnImplementation_Sink.Text].Tag, "Sinks",
  //                                                          tvRawData))
                                                        return false;
                                                // need to see any posible side effects of this (false check was not there on small projects)
                                            }
                                            tnNode.Nodes.Add(tnNewNode_forImplementation);
                                        }
                                    }
                                }
                            }
                        foreach (TreeNode tnChildNode in tnNode.Nodes)
                        {
                            if (false ==
                                ResolveInterfacesOnTreeView_recursive(tnChildNode, cdCirData, dO2TraceBlock, dRawData, //tvRawData,
                                                                      sHardCodedInterfaceKeywork))
                                return false;
                        }
                    }
                return true;
            }
示例#9
0
        public static bool addCompatibleTracesToNode_recursive(TreeNode tnTargetNode, FindingViewItem fviFindingViewItem,
                                                               O2TraceBlock_OunceV6 otbO2TraceBlockOunceV6OfToProcess,
                                                               String sMode,
                                                               Dictionary<String, O2TraceBlock_OunceV6> dRawData)
                                                               //TreeView tvRawData)
        {
            //TreeNode tnParentNode = O2Forms.getRootNode(tnTargetNode);
            //int iNumberOfNodes = tnParentNode.GetNodeCount(true);
            var iNumberOfNodes = O2Forms.getRootNode(tnTargetNode).GetNodeCount(true);

            if (O2Forms.getRootNode(tnTargetNode).GetNodeCount(true) > 1500)
            {
                DI.log.info(String.Format("Max number of subnodes reached (250), aborting this root node: {0}",
                                          O2Forms.getRootNode(tnTargetNode).Text));
                return false;
            }
            if (new StackTrace().FrameCount > 50)
            {
                DI.log.info(String.Format("Max StackTrace reached (50), aborting this leaf:{0}", tnTargetNode.Text));
                return false;
            }

            var tnTreeFor_Root = new TreeNode();
            AnalysisUtils.addCallsToNode_Recursive(fviFindingViewItem.fFinding.Trace, tnTreeFor_Root,
                                                   fviFindingViewItem.oadO2AssessmentDataOunceV6,
                                                   Analysis.SmartTraceFilter.MethodName);
            if (sMode == "Sinks")
            {
                // first add the normal sinks
                foreach (AssessmentAssessmentFileFinding fFinding in otbO2TraceBlockOunceV6OfToProcess.dSinks.Keys)
                {
                    var tnTreeFor_ChildTrace = new TreeNode();
                    var fviFindingViewItemForChildTrace = new FindingViewItem(fFinding,
                                                                              fFinding.vuln_name ?? OzasmtUtils_OunceV6.getStringIndexValue(
                                                                                                        UInt32.Parse(
                                                                                                            fFinding.vuln_name_id),
                                                                                                        otbO2TraceBlockOunceV6OfToProcess.
                                                                                                            dSinks[fFinding]), null,
                                                                              otbO2TraceBlockOunceV6OfToProcess.dSinks[fFinding
                                                                                  ]);
                    AnalysisUtils.addCallsToNode_Recursive(fviFindingViewItemForChildTrace.fFinding.Trace,
                                                           tnTreeFor_ChildTrace,
                                                           fviFindingViewItemForChildTrace.oadO2AssessmentDataOunceV6,
                                                           Analysis.SmartTraceFilter.MethodName);

                    TreeNode tnRootNode_Sink = getTreeNodeOfTraceType_recursive(tnTreeFor_Root,
                                                                                TraceType.Known_Sink);
                    TreeNode tnRootNode_Source = getTreeNodeOfTraceType_recursive(tnTreeFor_ChildTrace,
                                                                                  TraceType.Source);


                    if (AreNodesCompatible(tnRootNode_Sink, tnRootNode_Source))
                    {
                        String sNodeText = getUniqueSignature(fFinding, TraceType.Known_Sink,
                                                              otbO2TraceBlockOunceV6OfToProcess.dSinks[fFinding], true);

                        // ensures we don't add the same source more that once per line (needs to be more optimized
                        List<String> ltnAllNodesAddedSofar = O2Forms.getStringListWithAllParentNodesText(tnTargetNode);
                        if (false == ltnAllNodesAddedSofar.Contains(sNodeText))
                        {
                            if (sNodeText != tnTargetNode.Text) // don't add if the child call is the same as the parent
                                tnTargetNode.Nodes.Add(O2Forms.newTreeNode(sNodeText, sNodeText, 0,
                                                                           fviFindingViewItemForChildTrace));
                            if (sNodeText == null)
                            {
                                return false;
                            }
                        }
                    }
                }
                // then add the Glued Sinks

                foreach (AssessmentAssessmentFileFinding fFinding in otbO2TraceBlockOunceV6OfToProcess.dGluedSinks.Keys)
                {
                    var fviFindingViewItemForChildTrace = new FindingViewItem(fFinding,
                                                                              fFinding.vuln_name ?? OzasmtUtils_OunceV6.getStringIndexValue(
                                                                                                        UInt32.Parse(
                                                                                                            fFinding.vuln_name_id),
                                                                                                        otbO2TraceBlockOunceV6OfToProcess.
                                                                                                            dGluedSinks[fFinding]), null,
                                                                              otbO2TraceBlockOunceV6OfToProcess.dGluedSinks[
                                                                                  fFinding]);
                    String sNodeText = getUniqueSignature(fFinding, TraceType.Known_Sink,
                                                          otbO2TraceBlockOunceV6OfToProcess.dGluedSinks[fFinding], true);
                    tnTargetNode.Nodes.Add(O2Forms.newTreeNode(sNodeText, sNodeText, 0, fviFindingViewItemForChildTrace));
                }
            }
            foreach (TreeNode tnChildNode in tnTargetNode.Nodes)
            {
                //   int iNodeCount = tnChildNode.GetNodeCount(true);
                //    DI.log.info(iNodeCount + "   " + tnChildNode.Text);
                //if (tvRawData.Nodes[tnChildNode.Text] != null)
                if (dRawData.ContainsKey(tnChildNode.Text))
                    // (now back to false) was true (check side effects)
                    if (false ==
                        addCompatibleTracesToNode_recursive(tnChildNode, (FindingViewItem) tnChildNode.Tag,
                                            dRawData[tnChildNode.Text],
                                            //                (O2TraceBlock_OunceV6) tvRawData.Nodes[tnChildNode.Text].Tag,
                                                            "Sinks", dRawData))
                                                            //tvRawData))
                        return false;
            }
            return true;
        }
 public static Int32 getImageIdFromFilterAndFinding(String sFindingFilter, FindingViewItem fviFindingViewItem)
 {
     switch (sFindingFilter)
     {
         case "Confidence":
             switch (fviFindingViewItem.fFinding.confidence)
             {
                 case 0:
                     return 8;
                 case 1:
                     return 6;
                 case 2:
                     return 7;
                 case 3:
                     return 4;
             }
             break;
         case "Severity":
             switch (fviFindingViewItem.fFinding.severity)
             {
                 case 0:
                     return 1;
                 case 1:
                     return 3;
                 case 2:
                     return 2;
                 case 3:
                     return 4;
             }
             break;
         case "Sink":
             if (fviFindingViewItem.fFinding.Trace != null)
                 return 10;
             else
                 return 0;
     }
     return 9;
 }
示例#11
0
 public void setTraceDataAndRefresh(FindingViewItem fviFindingViewItem)
 {
     tvSmartTrace.Tag = fviFindingViewItem;
     refreshSmartTraceTreeView();
     FindingsView.showFindingDetailsInDataGridView(dgvFindingsDetails, fviFindingViewItem.fFinding,
                                                   fviFindingViewItem.oadO2AssessmentDataOunceV6);
 }
示例#12
0
            public bool appendTrace_FindingSourceToFindingSink(AssessmentAssessmentFileFinding fJoinAtSink,
                                                               FindingViewItem fviJoinAtSource)
            {
                //Get the Sink of the first trace                        
                CallInvocation ciSinkNode =
                    AnalysisSearch.findTraceTypeInSmartTrace_Recursive_returnCallInvocation(fJoinAtSink.Trace,
                                                                                            TraceType.Known_Sink);
                if (ciSinkNode == null)
                {
                    //              DI.log.error("in appendTrace_FindingSourceToFindingSink, could not find the Sink of fviJoinAtSink");
                    return false;
                }

                // get the source of the 2nd trace

                // There are 3 possible Gluing Scenarios
                //   a source that has child nodes (when it is a callback)
                //   a source trace that has a compatible signature with the sink trace (when it was creted via a source of tainded data rule).  For this one we will have to find the correct injection point
                //   a source trace that has nothing do with the source (interfaces gluing for example) and we have the same two cases above
                // the strategy to find a gluing point (on the fviJoinAtSource is to find the first trace that has a sink

                // try to get case 1 see if the current source has child nodes
                CallInvocation ciSourceNode =
                    AnalysisSearch.findTraceTypeInSmartTrace_Recursive_returnCallInvocation(
                        fviJoinAtSource.fFinding.Trace, TraceType.Source);

                if (ciSourceNode == null)
                {
                    DI.log.error(
                        "in appendTrace_FindingSourceToFindingSink, could not find the Source of fviJoinAtSource");
                    return false;
                }

                if (ciSourceNode.CallInvocation1 == null) // means we are case 2 or 3     
                {
                    CallInvocation ciSourceNodeWithSink =
                        AnalysisSearch.fromSourceFindFirstTraceWithAChildSink(fviJoinAtSource.fFinding,
                                                                              fviJoinAtSource.oadO2AssessmentDataOunceV6);
                    if (ciSourceNodeWithSink != null)
                        // if we found this it means that we are now on Trace that the first child node goes to the source and the 2nd goes to the Sink
                        ciSourceNode = ciSourceNodeWithSink.CallInvocation1[1];
                }

                // make the previous Sink that Type 4 that doesn't seem to be used (could make it sources but it is cleaner with using this extra trace type for the joins
                ciSinkNode.trace_type = (int) TraceType.Type_4;


                CallInvocation[] aciCallInvocation;
                if (AnalysisUtils.getSink(fJoinAtSink, oadNewO2AssessmentDataOunceV6) ==
                    AnalysisUtils.getSource(fviJoinAtSource.fFinding, fviJoinAtSource.oadO2AssessmentDataOunceV6))
                    aciCallInvocation = ciSourceNode.CallInvocation1;
                else
                    aciCallInvocation = new[] {ciSourceNode};
                var lciTempNewCallInvocation = new List<CallInvocation>(); // used by the recursive function

                ciSinkNode.CallInvocation1 = updateAssessmentRunWithTraceReferences_recursive(
                    lciTempNewCallInvocation,
                    aciCallInvocation,
                    dNewStringIndex,
                    dNewFileIndex,
                    fviJoinAtSource.oadO2AssessmentDataOunceV6);


                return true;
            }
示例#13
0
        public static List<FindingViewItem> calculateDictionaryWithFilteredFindingsResults(
            List<FindingsResult> lfrFindingsResults, ref Dictionary<String, List<FindingViewItem>> dFilteredFindings,
            String sFindingFilter, bool bUniqueList)
        {
            bool bSkipAddingItemsToReturnList = false;
            dFilteredFindings = new Dictionary<string, List<FindingViewItem>>();
            var lfviFindingViewItems = new List<FindingViewItem>();
            int iMaxItemToAdd = 1000;
            int iMaxUniqueFindings = 10000;
            var lsTextOfItemsAdded = new List<string>();
            if (lfrFindingsResults != null)
            {
                //Calculate unique List of findings
                var lfUniqueFindings = new List<AssessmentAssessmentFileFinding>();

                foreach (FindingsResult frFindingsResult in lfrFindingsResults)
                {
                    //if (false == lfUniqueFindings.Contains(frFindingsResult.fFinding))
                    //{
                    //    lfUniqueFindings.Add(frFindingsResult.fFinding);
                    String sText = "";
                    switch (sFindingFilter)
                    {
                        case "Vuln Name":
                            sText = frFindingsResult.sVulnerabilityName;
                            break;
                        case "Vuln Type":
                            sText = frFindingsResult.sVulnerabilityType;
                            break;
                        case "Context":
                            sText = frFindingsResult.sContext;
                            break;
                        case "SourceCode":
                            sText = frFindingsResult.sSourceCodeSnippet;
                            break;
                        case "File":
                            sText = frFindingsResult.sSourceCodeSnippet;
                            break;
                        case "Source":
                            sText = frFindingsResult.sSource;
                            break;
                        case "Sink":
                            sText = frFindingsResult.sSink;
                            break;
                        case "Lost Sink":
                            sText = frFindingsResult.sLostSink;
                            break;
                        case "Known Sink":
                            sText = frFindingsResult.sKnownSink;
                            break;
                        case "Severity":
                            sText = frFindingsResult.sSeverity;
                            break;
                        case "Confidence":
                            sText = frFindingsResult.sConfidence;
                            break;
                        case "Search Text":
                            sText = frFindingsResult.sStringThatMatchedCriteria;
                            break;
                        default:
                            sText = "NOT IMPLEMENTED YET";
                            break;
                    }
                    // create the global dictionary with the items indexed by sText
                    if (sText != null)
                    {
                        var fviFindingViewItem = new FindingViewItem(frFindingsResult.fFinding, sText, frFindingsResult,
                                                                     frFindingsResult.oadO2AssessmentDataOunceV6);
                        if (false == dFilteredFindings.ContainsKey(sText))
                            dFilteredFindings.Add(sText, new List<FindingViewItem>());
                        dFilteredFindings[sText].Add(fviFindingViewItem);

                        if (false == bSkipAddingItemsToReturnList)
                        {
                            // create the main list of fidings that match sFindingFilter
                            if (sText != "" &&
                                (bUniqueList == false || (bUniqueList && false == lsTextOfItemsAdded.Contains(sText))))
                            {
                                lfviFindingViewItems.Add(fviFindingViewItem);

                                if (bUniqueList)
                                    lsTextOfItemsAdded.Add(sText);
                            }
                        }
                    }
                    //}
                    //else
                    //{ 
                    //}
                    if (lfviFindingViewItems.Count > iMaxItemToAdd)
                    {
                        DI.log.error("Max number of items reach ({0}), canceling adding search results to listbox",
                                     iMaxItemToAdd);
                        break;
                    }
                    if (false == bSkipAddingItemsToReturnList && lfUniqueFindings.Count > iMaxUniqueFindings)
                    {
                        DI.log.error(
                            "Max number of unique Findings reached ({0}), canceling adding search results to listbox",
                            iMaxUniqueFindings);
                        bSkipAddingItemsToReturnList = true;
                        // break;
                    }
                }
            }
            return lfviFindingViewItems;
        }
示例#14
0
 public static String getSource(FindingViewItem fviFindingViewItem)
 {
     return getSource(fviFindingViewItem.fFinding, fviFindingViewItem.oadO2AssessmentDataOunceV6);
 }