public static List <IO2Finding> mapJoinPoints_HashTagsOn_Sources(List <IO2Finding> o2findings) { var results = new List <IO2Finding>(); foreach (O2Finding o2Finding in o2findings) { var hashTagName = JoinOnAttributes.extractNameFromContext(o2Finding.SourceContext, "\"", "\""); // make this the first trace if (hashTagName != "") { //var newO2Trace = new O2Trace(hashTagName, TraceType.O2JoinSource); var copyOfO2Finding = (O2Finding)OzasmtCopy.createCopy(o2Finding); var joinLocation = copyOfO2Finding.o2Traces[0].file; // insert JoinSource copyOfO2Finding.insertTrace(hashTagName, TraceType.O2JoinSource); // insert Location copyOfO2Finding.insertTrace(joinLocation, TraceType.O2JoinLocation); //newO2Trace.childTraces.AddRange(o2Finding.o2Traces); //copyOfO2Finding.o2Traces = new List<IO2Trace> { newO2Trace }; results.Add(copyOfO2Finding); } } return(results); }
public static List <IO2Finding> joinTracesWhereSinkMatchesSource(List <IO2Finding> sinkFindings, List <IO2Finding> sourceFindings) { var results = new List <IO2Finding>(); foreach (var o2SinkFinding in sinkFindings) { foreach (var o2SourcesFinding in sourceFindings) { if (o2SourcesFinding.vulnName.IndexOf(o2SinkFinding.vulnName) > -1) { var o2NewFinding = (O2Finding)OzasmtCopy.createCopy(o2SinkFinding); results.Add(o2NewFinding); var sink = o2NewFinding.getSink(); var newTrace = new O2Trace( string.Format("O2 Auto Join Point::: {0} -> {1}", o2SinkFinding.vulnName, o2SourcesFinding.vulnName)); newTrace.traceType = TraceType.Type_4; sink.childTraces.Add(newTrace); newTrace.childTraces.AddRange(o2SourcesFinding.o2Traces); log.info("we have a match: {0} -> {1}", o2SinkFinding.vulnName, o2SourcesFinding.vulnName); } } } return(results); }
public static bool invokeOnAllPartialTraces(IEnumerable <IO2Trace> o2TracesToFollow, ICollection <IO2Trace> o2PartialTraces, Func <ICollection <IO2Trace>, IO2Trace, bool> onTraceEnter) { // process all traces foreach (var o2TraceToFollow in o2TracesToFollow) { // invoke onTraceEnter and only continue if true if (onTraceEnter(o2PartialTraces, o2TraceToFollow)) { // create a copy of the current trace var newO2Trace = OzasmtCopy.createCopy(o2TraceToFollow, false); // add it to the trace we are building o2PartialTraces.Add(newO2Trace); if (false == invokeOnAllPartialTraces(o2TraceToFollow.childTraces, newO2Trace.childTraces, onTraceEnter)) { return(false); // means we are not supposed to continue with this trace } } else { return(false); } } return(true); }
public static List <IO2Finding> mapSinksToSources(Dictionary <string, List <IO2Finding> > lostSinks, Dictionary <string, List <IO2Finding> > sources) { DI.log.info("Looking for matches"); var results = new List <IO2Finding>(); foreach (string lostSinkSignature in lostSinks.Keys) { if (sources.ContainsKey(lostSinkSignature)) { foreach (O2Finding lostSink in lostSinks[lostSinkSignature]) { foreach (O2Finding source in sources[lostSinkSignature]) { var sinkCopy = (O2Finding)OzasmtCopy.createCopy(lostSink); var sourceCopy = (O2Finding)OzasmtCopy.createCopy(source); var lostSinkNode = sinkCopy.getLostSink(); lostSinkNode.traceType = TraceType.Type_4; var interfaceJoinPoint = new O2Trace("---- Interface join --- "); interfaceJoinPoint.childTraces.AddRange(sourceCopy.o2Traces); lostSinkNode.childTraces.Add(interfaceJoinPoint); sinkCopy.vulnName = sinkCopy.Sink; results.Add(sinkCopy); //return results; } } } } //log.info("We have a match on: {0}", lostSink); return(results); }
public static List <IO2Finding> joinTracesWhereSinkMatchesSource(List <IO2Finding> sinkFindings, List <IO2Finding> sourceFindings) { var results = new List <IO2Finding>(); foreach (var o2SinkFinding in sinkFindings) { foreach (var o2SourcesFinding in sourceFindings) { if (o2SourcesFinding.vulnName.IndexOf(o2SinkFinding.vulnName) > -1) { var o2NewFinding = (O2Finding)OzasmtCopy.createCopy(o2SinkFinding); results.Add(o2NewFinding); var sink = o2NewFinding.getSink(); var joinPointTrace = new O2Trace( string.Format("O2 Auto Join Point::: {0} -> {1}", o2SinkFinding.vulnName, o2SourcesFinding.vulnName)); sink.traceType = TraceType.Type_4; joinPointTrace.traceType = TraceType.Type_4; sink.childTraces.Add(joinPointTrace); var jspSignature = o2SourcesFinding.o2Traces[0].signature; var indexofJsp = jspSignature.IndexOf("._jsp"); if (indexofJsp > -1) { jspSignature = jspSignature.Substring(0, indexofJsp) + ".jsp"; } jspSignature = jspSignature.Replace("jsp_servlet", "").Replace("_45_", @"-").Replace(".__", @"/").Replace("._", @"/"); var jspTrace = new O2Trace("JSP: " + jspSignature); joinPointTrace.childTraces.Add(jspTrace); jspTrace.childTraces.AddRange(o2SourcesFinding.o2Traces); //var copyOfSourcesFinding = (O2Finding)OzasmtCopy.createCopy(o2SourcesFinding); //copyOfSourcesFinding.o2Traces[0].signature = modifiedSignature; //newTrace.childTraces.AddRange(copyOfSourcesFinding.o2Traces); //newTrace.childTraces.AddRange(o2SourcesFinding.o2Traces); //log.info("we have a match: {0} -> {1}", o2SinkFinding.vulnName, o2SourcesFinding.vulnName); //return results; } } } return(results); }
public void calculateJoinnedTraces() { try { var matches2 = from O2Finding sinkFinding in getFindingsIn_Sinks() join O2Finding sourceFinding in getFindingsIn_Sources() on sinkFinding.Sink equals sourceFinding.Source where ( sinkFinding.Sink != "" && sourceFinding.Source != "" //&& sourceFinding.LostSink == "" /* && * sinkFinding.lineNumber == sourceFinding.lineNumber && * sinkFinding.file == sourceFinding.file*/ ) select new { sinkFinding, sourceFinding }; var findingsResults = new List <IO2Finding>(); foreach (var match in matches2) { //var aa = match.sinkFinding.Sink; //var bb = match.sourceFinding.Source; foreach (var o2TraceInSource in match.sourceFinding.o2Traces) { var joinnedFinding = (O2Finding)OzasmtCopy.createCopy(match.sinkFinding); var sink = joinnedFinding.getSink(); sink.traceType = TraceType.Type_4; var joinnedTrace = new O2Trace("{TraceJoin}"); sink.childTraces.Add(joinnedTrace); //findingsResults.Add(OzasmtGlue.createCopyAndGlueTraceSinkWithSource(match.sinkFinding, o2TraceInSource)); joinnedTrace.childTraces.Add(OzasmtCopy.createCopy(o2TraceInSource)); joinnedFinding.vulnName = joinnedFinding.Sink; findingsResults.Add(joinnedFinding); } } findingsViewer_JoinnedTraces.loadO2Findings(findingsResults); } catch (Exception ex) { DI.log.ex(ex, "in calculateJoinnedTraces"); throw; } }
public static void createAllPartialTraces(IEnumerable <IO2Trace> o2TracesToFollow, ICollection <IO2Trace> o2PartialTraces, IO2Finding parentFinding, ICollection <IO2Finding> findingsCreated) { // process all traces foreach (var o2TraceToFollow in o2TracesToFollow) { // create a copy of the current trace var newO2Trace = OzasmtCopy.createCopy(o2TraceToFollow, false); //newO2Trace.childTraces = new List<IO2Trace>(); // remove the child traces // add it to the trace we are building o2PartialTraces.Add(newO2Trace); // create a copy of the parent finding var newO2Finding = OzasmtCopy.createCopy(parentFinding); findingsCreated.Add(newO2Finding); // and trigger the recursive execution on all child traces createAllPartialTraces(o2TraceToFollow.childTraces, newO2Trace.childTraces, parentFinding, findingsCreated); } }
private static bool applyRuleToTrace(IO2Trace o2Trace, ICollection <IO2Trace> o2PartialTraces, IO2Finding parentO2Finding, List <IO2Finding> findingsCreated, IDictionary <string, List <IO2Rule> > indexedRules) { // if (o2Trace.signature.IndexOf("System.Data.SqlClient.SqlCommand") > -1) // DI.log.info(o2Trace.signature); var signatureToFind = MakeSignatureCompatibleWithOunceRules(o2Trace.signature); // if (signatureToFind.IndexOf("System.Data.SqlClient") > -1) // DI.log.info(signatureToFind); if (indexedRules.ContainsKey(signatureToFind)) // means we have a match { // rename to shouldAbortRulesCreation if (shouldAbortRulesExecution(indexedRules[signatureToFind])) { if (o2Trace.traceType == TraceType.Known_Sink || o2Trace.traceType == TraceType.Lost_Sink) { return(false); } return(true); } // check if we are a sink at the root of the tree with no child nodes (and if so skip trace creation) if (parentO2Finding.o2Traces.Count == 0) //; && (o2Trace.traceType == TraceType.Known_Sink || o2Trace.traceType == TraceType.Lost_Sink || o2Trace.traceType == TraceType.Root_Call)) { return(true); } // check if there are no sources on the trace if (((O2Finding)parentO2Finding).Source == "") { return(false); } var newTrace = OzasmtCopy.createCopy(o2Trace, false); //create new trace (which will be modified newTrace.traceType = TraceType.Known_Sink; // make the trace a sink o2PartialTraces.Add(newTrace); // add it to the partial trace var newFindingWithSinkTrace = OzasmtCopy.createCopy(parentO2Finding); // create template finding which will be applied the rules findingsCreated.AddRange(FiltersUtils.applySinkRuleToFindingAndTrace(newFindingWithSinkTrace, signatureToFind, indexedRules)); // apply rules and add resulting findings to findingsCreated list //remove the new trace since the invokeOnAllPartialTraces loop will add its own copy o2PartialTraces.Remove(newTrace); } return(true); // in this case return true since we want to process ALL traces }
public static List <IO2Finding> applySinkRuleToFindingAndTrace(IO2Finding o2Finding, string traceSignature, IDictionary <string, List <IO2Rule> > indexedRules) { var newFindings = new List <IO2Finding>(); if (traceSignature != "" && indexedRules.ContainsKey(traceSignature)) { // apply rules settings to it foreach (var o2Rule in indexedRules[traceSignature]) { // create copy of finding var newO2Finding = OzasmtCopy.createCopy(o2Finding); // apply rule newO2Finding.severity = OzasmtUtils.getSeverityFromString(o2Rule.Severity); newO2Finding.vulnName = o2Rule.Signature; newO2Finding.vulnType = o2Rule.VulnType; newFindings.Add(newO2Finding); } } return(newFindings); }
public static List <IO2Finding> applyFilter(IEnumerable <IO2Finding> o2TargetO2Findings, List <IO2Rule> o2Rules) { var findingsCreated = new List <IO2Finding>(); var numberOfItemsToProcess = o2TargetO2Findings.Count(); var itemsProcessed = 0; foreach (IO2Finding targetO2Finding in o2TargetO2Findings) { var parentO2Finding = OzasmtCopy.createCopy(targetO2Finding, false); //parentO2Finding.o2Traces = new List<IO2Trace>(); createAllPartialTraces(targetO2Finding.o2Traces, parentO2Finding.o2Traces, parentO2Finding, findingsCreated); itemsProcessed++; if (itemsProcessed % 5000 == 0) { DI.log.info("applyFllter_MapSinksToAllTraces: {0} Findings created so far [{1}/{2}]", findingsCreated.Count, itemsProcessed, numberOfItemsToProcess); } } DI.log.info("applyFllter_MapSinksToAllTraces: {0} Findings created in total", findingsCreated.Count); return(findingsCreated); }
public static List <IO2Finding> applyFilter(IEnumerable <IO2Finding> o2TargetO2Findings, List <IO2Rule> o2Rules, bool addFindingsWithNoMatches) { var findingsCreated = new List <IO2Finding>(); var numberOfItemsToProcess = o2TargetO2Findings.Count(); var itemsProcessed = 0; // create index of Sinks var indexedRules = IndexedO2Rules.indexOnSinks(o2Rules); // IndexedO2Rules.indexAll(o2Rules); // process add findings foreach (IO2Finding targetO2Finding in o2TargetO2Findings) { var currentNumberOfCreatedFindings = findingsCreated.Count; // create copy of parent with no child traces var parentO2Finding = OzasmtCopy.createCopy(targetO2Finding, false); // start recursive loop that will invoke the Lambda callback for every node if (invokeOnAllPartialTraces(targetO2Finding.o2Traces, parentO2Finding.o2Traces, (o2PartialTraces, o2Trace) => applyRuleToTrace(o2Trace, o2PartialTraces, parentO2Finding, findingsCreated, indexedRules))) { // if invokeOnAllPartialTraces returned true (which means we didn't hit a don't propagate item) check if there was any rule created with this finding if (addFindingsWithNoMatches) { if (currentNumberOfCreatedFindings == findingsCreated.Count) { parentO2Finding.vulnType = "_O2.Lost.Sources"; // These are Lost sources (i.e. findings where the Sink happens first than the source parentO2Finding.vulnName = ((O2Finding)parentO2Finding).Sink; // this patch should be done when the joinned traces are created findingsCreated.Add(parentO2Finding); } } } //update user on progress itemsProcessed++; if (itemsProcessed % 5000 == 0) { DI.log.info("applyFllter_MapSinksToAllTraces: {0} Findings created so far [{1}/{2}]", findingsCreated.Count, itemsProcessed, numberOfItemsToProcess); } } DI.log.info("applyFllter_MapSinksToAllTraces: {0} Findings created in total", findingsCreated.Count); return(findingsCreated); }
public static List <IO2Finding> mapJoinPoints_HashTagsOn_Sinks(List <IO2Finding> o2findings) { var results = new List <IO2Finding>(); foreach (O2Finding o2Finding in o2findings) { var hashTagName = JoinOnAttributes.extractNameFromContext(o2Finding.SinkContext, "\"", "\""); // make this the last trace if (hashTagName != "") { var copyOfO2Finding = (O2Finding)OzasmtCopy.createCopy(o2Finding); var joinLocation = copyOfO2Finding.o2Traces[0].file; // insert JoinSink copyOfO2Finding.addTrace(copyOfO2Finding.getSink(), hashTagName, TraceType.O2JoinSink); // insert Location copyOfO2Finding.insertTrace(joinLocation, TraceType.O2JoinLocation); results.Add(copyOfO2Finding); } } return(results); }
private static bool applyRuleToTrace(IO2Trace o2Trace, IO2Finding parentO2Finding, List <IO2Finding> findingsCreated, IDictionary <string, List <IO2Rule> > indexedRules) { var signatureToFind = o2Trace.signature; if (indexedRules.ContainsKey(signatureToFind)) // means we have a match { if (o2Trace.traceType == TraceType.Source) { // if the trace is of TraceType.Source by there is a rule with O2RuleType.NotASource we need are not going to add the current finding foreach (var o2Rule in indexedRules[signatureToFind]) { if (o2Rule.RuleType == O2RuleType.NotASource) { return(false); } } // since this is a Source, we can just add it and terminate the trace (this assumes that there is only one trace per finding findingsCreated.Add(parentO2Finding); return(true); } // if we have a source lets add it has a new finding foreach (var o2Rule in indexedRules[signatureToFind]) { if (o2Rule.RuleType != O2RuleType.NotASource) { // before we copy the finding we have to sort out who is a source in this finding var currentSource = ((O2Finding)parentO2Finding).getSource(); // make it a normal trace if (currentSource != null) { currentSource.traceType = TraceType.Type_4; } // then save the current trace trace type var currentO2TraceTraceType = o2Trace.traceType; // set it to Source o2Trace.traceType = TraceType.Source; // copy the whole finding and traces var newSourceFinding = OzasmtCopy.createCopy(parentO2Finding); // add it to the list of created findings findingsCreated.Add(newSourceFinding); // and restore the trace types we modified above if (currentSource != null) { currentSource.traceType = TraceType.Source; } o2Trace.traceType = currentO2TraceTraceType; // all done :) } } /* // rename to shouldAbortRulesCreation * if (shouldAbortRulesExecution(indexedRules[signatureToFind])) * { * if (o2Trace.traceType == TraceType.Known_Sink || o2Trace.traceType == TraceType.Lost_Sink) * return false; * return true; * } * // check if we are a sink at the root of the tree with no child nodes (and if so cancel) * if (parentO2Finding.o2Traces.Count == 0)//; && (o2Trace.traceType == TraceType.Known_Sink || o2Trace.traceType == TraceType.Lost_Sink || o2Trace.traceType == TraceType.Root_Call)) * return true; * // check if there are no sources on the trace * if (((O2Finding)parentO2Finding).Source == "") * return false; * * var newTrace = OzasmtCopy.createCopy(o2Trace, false); //create new trace (which will be modified * newTrace.traceType = TraceType.Known_Sink; // make the trace a sink * o2PartialTraces.Add(newTrace); // add it to the partial trace * * var newFindingWithSinkTrace = OzasmtCopy.createCopy(parentO2Finding); // create template finding which will be applied the rules * findingsCreated.AddRange(FiltersUtils.applySinkRuleToFindingAndTrace(newFindingWithSinkTrace, o2Trace.signature, indexedRules)); // apply rules and add resulting findings to findingsCreated list * //remove the new trace since the invokeOnAllPartialTraces loop will add its own copy * o2PartialTraces.Remove(newTrace); */ } return(true); // in this case return true since we want to process ALL traces }
public static List <IO2Finding> getSourcesMappedToInterfaces(List <IO2Finding> o2Findings, ICirData cirData) { var results = new List <IO2Finding>(); if (cirData == null || o2Findings == null) { return(results); } foreach (O2Finding o2Finding in o2Findings) { var source = o2Finding.getSource(); if (source != null) { if (cirData.dFunctions_bySignature.ContainsKey(source.signature)) { var cirFunction = cirData.dFunctions_bySignature[source.signature]; var cirClass = cirFunction.ParentClass; if (cirClass.dSuperClasses.Count > 0) { var sourceSig = cirFunction.FunctionSignature.Substring(cirClass.Signature.Length); //log.info(cirFunction.FunctionSignature); foreach (var superClass in cirClass.dSuperClasses.Values) { foreach (var function in superClass.dFunctions.Values) { var interfaceName = function.FunctionSignature.Substring(superClass.Signature.Length); if (sourceSig == interfaceName) { // we have an implementation of a method: var newO2Finding = OzasmtCopy.createCopy(o2Finding); var currentSource = ((O2Finding)newO2Finding).getSource(); currentSource.traceType = TraceType.Type_4; currentSource.signature = "[old source]: " + currentSource.signature; var interfaceTrace = new O2Trace(function.FunctionSignature); interfaceTrace.traceType = TraceType.Source; //interfaceTrace.childTraces.Add(new O2Trace("[interface function Signature (that matched)]: " + sourceSig)); //interfaceTrace.childTraces.Add(new O2Trace("interface: " + interfaceName)); //interfaceTrace.childTraces.Add(new O2Trace("source: " + currentSource.signature)); //interfaceTrace.childTraces.Add(new O2Trace("interface: " + function.FunctionSignature)); //interfaceTrace.childTraces.AddRange(newO2Finding.o2Traces); interfaceTrace.childTraces.AddRange(currentSource.childTraces); newO2Finding.o2Traces = new List <IO2Trace>(); newO2Finding.o2Traces.Add(interfaceTrace); results.Add(newO2Finding); //return results; } } } } //log.info(" {2} : {0} -> {1}", cirFunction.FunctionSignature, cirClass.Name, cirClass.dSuperClasses.Count); } } } DI.log.info("There were {0} sources mapped to its interfaces (i.e. superclasses))", results.Count); return(results); }
public static IO2Finding copy(this IO2Finding o2Finding) { return(OzasmtCopy.createCopy(o2Finding)); }
/// <summary> /// This will populate the parent finding with all traces from the provided ICirFunction /// caution: use the createNewFindingOnExternalCall carefully since it can create a stupid amount of traces (and it is much slower) /// </summary> /// <param name="cirFunction"></param> /// <param name="lineNumber"></param> /// <param name="o2Traces"></param> /// <param name="parentTraces"></param> /// <param name="rootO2Finding"></param> /// <param name="o2FindingsCreated"></param> /// <param name="createNewFindingOnExternalCall"></param> /// <param name="fileName"></param> public static void createTracesAndFindingsFromCirFunction(ICirFunction cirFunction, string fileName, UInt32 lineNumber, List <IO2Trace> o2Traces, List <IO2Trace> parentTraces, IO2Finding rootO2Finding, List <IO2Finding> o2FindingsCreated, bool createNewFindingOnExternalCall) { int maxParentDepth = 10; //30; //10; var maxNumberOfTraces = 20; //50; //300; //50 var filteredSignature = new FilteredSignature(cirFunction); var functionSignature = filteredSignature.sSignature; var o2Trace = new O2Trace(functionSignature, cirFunction.ClassNameFunctionNameAndParameters) { file = fileName, lineNumber = lineNumber }; // add file references // handle the case where this is a recursive call or a call to a method already added in the current tree var recursiveCall = false; foreach (var o2ParentTrace in parentTraces) { if (o2ParentTrace.signature == functionSignature) { recursiveCall = true; break; } } parentTraces.Add(o2Trace); // add this trace to the current trace tree (since we might need to create a copy of it below o2Traces.Add(o2Trace); if (recursiveCall) { var nodeText = String.Format("{0} : {1} : {2}", cirFunction, "....(Recursive Call so not expanding child traces", functionSignature); o2Trace.childTraces.Add(new O2Trace(nodeText)); } else { if (parentTraces.Count > maxParentDepth) { o2Trace.childTraces.Add(new O2Trace(" ... {Max trace depth reached} (" + maxParentDepth + ")")); } else { // var numberOfTraces = OzasmtUtils.getAllTraces(rootO2Finding.o2Traces); if (numberOfTraces.Count > maxNumberOfTraces) { o2Trace.childTraces.Add(new O2Trace("**** Max number of traces reached(" + maxNumberOfTraces + ") aborting trace execution")); return; } if (cirFunction.FunctionsCalled.Count == 0) // means we don't have the code for this one, so { // let make it a lost sink var originalTraceTypeValue = o2Trace.traceType; // we might need this below o2Trace.traceType = TraceType.Lost_Sink; if (createNewFindingOnExternalCall) // and if createNewFindingOnExternalCall add it as finding { // create a copy of the parent finding (which incudes the above trace var newFinding = OzasmtCopy.createCopy(rootO2Finding); // make the first call a source (so that we have a source-> pair newFinding.o2Traces[0].traceType = TraceType.Source; // add it o2FindingsCreated.Add(newFinding); // since the crawl will continue we must restore the originalTraceTypeValue o2Trace.traceType = originalTraceTypeValue; } } else { foreach (var functionCalled in cirFunction.FunctionsCalled) { createTracesAndFindingsFromCirFunction(functionCalled.cirFunction, functionCalled.fileName, (UInt32)functionCalled.lineNumber, o2Trace.childTraces, parentTraces, rootO2Finding, o2FindingsCreated, createNewFindingOnExternalCall); } } } } // now remove the signature since we are only interrested in non repeats on the same parent parentTraces.Remove(o2Trace); }
private void handleDragDrop(DragEventArgs e) { var droppedObject = Dnd.tryToGetObjectFromDroppedObject(e); switch (droppedObject.GetType().Name) { case "O2Trace": var droppedTrace = (IO2Trace)droppedObject; var selectedO2Trace = o2Trace; if (selectedO2Trace == droppedTrace) { DI.log.error("on tvSmartTrace_DragDrop: It is not possible to drop a trace on it seft"); } else if (bMoveTraces && (OzasmtSearch.isO2TraceAChildTraceOfO2Trace(selectedO2Trace, droppedTrace))) { // if we draged into a parent, we need to make a copy first, then copy it then delete the original IO2Trace copiedO2Trace = OzasmtCopy.createCopy(droppedTrace); OzasmtGlue.deleteO2Trace(o2Finding.o2Traces, droppedTrace); selectedO2Trace.childTraces.Add(copiedO2Trace); } else if (bMoveTraces && OzasmtSearch.isO2TraceAChildTraceOfO2Trace(droppedTrace, selectedO2Trace)) { DI.log.error( "on tvSmartTrace_DragDrop: Could not move trace since it is not possible to drop a trace into its own child node"); } else { IO2Trace copiedO2Trace = OzasmtCopy.createCopy(droppedTrace); if (bMoveTraces) { OzasmtGlue.deleteO2Trace(o2Finding.o2Traces, droppedTrace); } selectedO2Trace.childTraces.Add(copiedO2Trace); } showO2TraceTree(); break; case "O2Finding": loadO2Finding((O2Finding)droppedObject); break; case "TreeNode": var tagObject = ((TreeNode)droppedObject).Tag; if (tagObject != null) { if (tagObject is O2Finding) { loadO2Finding((O2Finding)tagObject); } } break; } /* var droppedTrace2 = (O2Trace)Dnd.tryToGetObjectFromDroppedObject(e, typeof(O2Trace)); * if (droppedTrace2 != null) * { * * } * else * { * var droppedO2Finding = (O2Finding)Dnd.tryToGetObjectFromDroppedObject(e, typeof(O2Finding)); * if (droppedO2Finding != null) * loadO2Finding(droppedO2Finding); * else * { * droppedO2Finding = (O2Finding)Dnd.tryToGetObjectFromDroppedObject(e, typeof(TreeNode)); * * } * }*/ }