/// <summary> /// Inserts a column into a data row. /// </summary> /// <remarks> /// This method may update an existing column, making it multivalue, if necessary. /// </remarks> /// <param name="row">Row to modify.</param> /// <param name="columnName">Name of the column to insert.</param> /// <param name="typedValue">Column value to insert.</param> private static void InsertColumn(CapDataRow row, string columnName, object typedValue) { object existingValue; if (row.Columns.TryGetValue(columnName, out existingValue)) { object[] combinedValue = existingValue as object[]; if (combinedValue != null) { object[] oldCombinedValue = combinedValue; combinedValue = new object[oldCombinedValue.Length + 1]; Array.Copy(oldCombinedValue, combinedValue, oldCombinedValue.Length); combinedValue[combinedValue.Length - 1] = typedValue; } else { combinedValue = new object[] { existingValue, typedValue }; } row.Columns[columnName] = combinedValue; } else { row.Columns[columnName] = typedValue; } }
/// <summary> /// Reads a protocol entry. /// </summary> /// <param name="state">The parse state.</param> private static void ReadProtocol(ParseState state) { XmlReader xmlReader = state.Reader; XmlDocument xmlDocument = state.Document; XmlNode xmlNode = xmlDocument.ReadNode(xmlReader); TreeNode treeNode = GetTreeNode(state, null, xmlNode); CapDataRow protocolRow = Flatten(treeNode); if (protocolRow != null) { if (state.DataRow != null) { state.DataRow.ChildRows.Add(protocolRow); } // add the source file if (treeNode.Name == "geninfo") { protocolRow.Columns["file"] = state.File.Path; } state.DataRow = protocolRow; } }
/// <summary> /// Reads a packet entry. /// </summary> /// <param name="state">The parse state.</param> private static void ReadPacket(ParseState state) { XmlReader xmlReader = state.Reader; if (!xmlReader.ReadToDescendant("proto")) { return; } CapDataRow packetRow = null; state.DataRow = null; TSharkDataReaderCallback callback = state.Callback; int index = 0; while (true) { if (xmlReader.Name != "proto") { if (packetRow != null && callback != null) { callback(packetRow); } return; } CapProtocol capProtocol = new CapProtocol(); capProtocol.Packet = state.Packet; capProtocol.NestingLevel = index++; try { state.Protocol = capProtocol; ReadProtocol(state); } finally { state.Protocol = null; if (packetRow == null) { packetRow = state.DataRow; } } } }
/// <summary> /// Inserts a column into a data row. /// </summary> /// <remarks> /// This method may update an existing column, making it multivalue, if necessary. /// </remarks> /// <param name="row">Row to modify.</param> /// <param name="columnName">Name of the column to insert.</param> /// <param name="typedValue">Column value to insert.</param> private static void InsertColumn(CapDataRow row, string columnName, object typedValue) { object existingValue; if (row.Columns.TryGetValue(columnName, out existingValue)) { object[] combinedValue = existingValue as object[]; if (combinedValue != null) { object[] oldCombinedValue = combinedValue; combinedValue = new object[oldCombinedValue.Length + 1]; Array.Copy(oldCombinedValue, combinedValue, oldCombinedValue.Length); combinedValue[combinedValue.Length - 1] = typedValue; } else { combinedValue = new object[] { existingValue, typedValue }; } row.Columns[columnName] = combinedValue; } else { row.Columns[columnName] = typedValue; } }
/// <summary> /// Flattens a parsed tree node into a data row. /// </summary> /// <param name="node">Node to flatten.</param> /// <param name="namingPrefix">Current naming prefix.</param> /// <param name="lastParentName">The last assigned parent name in the tree being flattened.</param> /// <returns>A data row.</returns> private static CapDataRow Flatten(TreeNode node, string namingPrefix, string lastParentName) { int namelessLeafChildren = 0; int namelessBranchChildren = 0; List<TreeNode> leafChildren = new List<TreeNode>(); List<TreeNode> branchChildren = new List<TreeNode>(); foreach (TreeNode childNode in node.ChildNodes) { bool nameless = string.IsNullOrEmpty(childNode.Name); if (childNode.ChildNodes.Count > 0) { branchChildren.Add(childNode); if (nameless) { namelessBranchChildren++; } } else { leafChildren.Add(childNode); if (nameless) { namelessLeafChildren++; } } } string name; if (!string.IsNullOrEmpty(node.Name)) { name = FilterName(node.Name); } else { if (!string.IsNullOrEmpty(lastParentName)) { name = string.Concat(lastParentName, ".", "_group"); } else { name = "_group"; } } string tableName = CombineNames(namingPrefix, name); string innerNamingPrefix = namingPrefix; if (string.IsNullOrEmpty(innerNamingPrefix)) { innerNamingPrefix = tableName; } // uncomment this line to ensure that fields are always prefixed with their parent field/protocol name (overlap removed) // this can generate very long table names so it's not recommended //innerNamingPrefix = tableName; CapDataRow row = new CapDataRow(); row.Table = tableName; // unnamed columns if (namelessLeafChildren > 0) { int index = 0; string unnamedTableName = string.Concat(tableName, ".", "_value"); foreach (TreeNode leafChild in leafChildren) { if (string.IsNullOrEmpty(leafChild.Name)) { CapDataRow childRow = new CapDataRow(); childRow.Table = unnamedTableName; childRow.Columns["_index"] = index; childRow.Columns["_value"] = leafChild.TypedValue; row.ChildRows.Add(childRow); index++; } } } // named columns if (namelessLeafChildren < leafChildren.Count) { foreach (TreeNode leafChild in leafChildren) { if (!string.IsNullOrEmpty(leafChild.Name)) { string columnName = FilterName(leafChild.Name); object typedValue = leafChild.TypedValue; string typedValueString = leafChild.TypedValueString; if (typedValue != null) { InsertColumn(row, columnName, typedValue); if (typedValueString != null) { InsertColumn(row, string.Concat(columnName, "_string"), typedValueString); } } } } } // unnamed branches if (namelessBranchChildren > 0) { int index = 0; foreach (TreeNode branchChild in branchChildren) { if (string.IsNullOrEmpty(branchChild.Name)) { CapDataRow childRow = Flatten(branchChild, innerNamingPrefix, name); if (childRow != null) { childRow.Columns["_index"] = index; index++; row.ChildRows.Add(childRow); } } } } // named branches if (namelessBranchChildren < branchChildren.Count) { foreach (TreeNode branchChild in branchChildren) { if (!string.IsNullOrEmpty(branchChild.Name)) { CapDataRow childRow = Flatten(branchChild, innerNamingPrefix, name); if (childRow != null) { row.ChildRows.Add(childRow); } } } } object typedLocalData = node.TypedValue; string typedLocalDataString = node.TypedValueString; if (typedLocalData != null) { row.Columns["_value"] = typedLocalData; if (typedLocalDataString != null) { row.Columns["_string"] = typedLocalDataString; } } if (row.Columns.Count > 0 || row.ChildRows.Count > 0) { return row; } else { return null; } }
/// <summary> /// Flattens a parsed tree node into a data row. /// </summary> /// <param name="node">Node to flatten.</param> /// <param name="namingPrefix">Current naming prefix.</param> /// <param name="lastParentName">The last assigned parent name in the tree being flattened.</param> /// <returns>A data row.</returns> private static CapDataRow Flatten(TreeNode node, string namingPrefix, string lastParentName) { int namelessLeafChildren = 0; int namelessBranchChildren = 0; List <TreeNode> leafChildren = new List <TreeNode>(); List <TreeNode> branchChildren = new List <TreeNode>(); foreach (TreeNode childNode in node.ChildNodes) { bool nameless = string.IsNullOrEmpty(childNode.Name); if (childNode.ChildNodes.Count > 0) { branchChildren.Add(childNode); if (nameless) { namelessBranchChildren++; } } else { leafChildren.Add(childNode); if (nameless) { namelessLeafChildren++; } } } string name; if (!string.IsNullOrEmpty(node.Name)) { name = FilterName(node.Name); } else { if (!string.IsNullOrEmpty(lastParentName)) { name = string.Concat(lastParentName, ".", "_group"); } else { name = "_group"; } } string tableName = CombineNames(namingPrefix, name); string innerNamingPrefix = namingPrefix; if (string.IsNullOrEmpty(innerNamingPrefix)) { innerNamingPrefix = tableName; } // uncomment this line to ensure that fields are always prefixed with their parent field/protocol name (overlap removed) // this can generate very long table names so it's not recommended //innerNamingPrefix = tableName; CapDataRow row = new CapDataRow(); row.Table = tableName; // unnamed columns if (namelessLeafChildren > 0) { int index = 0; string unnamedTableName = string.Concat(tableName, ".", "_value"); foreach (TreeNode leafChild in leafChildren) { if (string.IsNullOrEmpty(leafChild.Name)) { CapDataRow childRow = new CapDataRow(); childRow.Table = unnamedTableName; childRow.Columns["_index"] = index; childRow.Columns["_value"] = leafChild.TypedValue; row.ChildRows.Add(childRow); index++; } } } // named columns if (namelessLeafChildren < leafChildren.Count) { foreach (TreeNode leafChild in leafChildren) { if (!string.IsNullOrEmpty(leafChild.Name)) { string columnName = FilterName(leafChild.Name); object typedValue = leafChild.TypedValue; string typedValueString = leafChild.TypedValueString; if (typedValue != null) { InsertColumn(row, columnName, typedValue); if (typedValueString != null) { InsertColumn(row, string.Concat(columnName, "_string"), typedValueString); } } } } } // unnamed branches if (namelessBranchChildren > 0) { int index = 0; foreach (TreeNode branchChild in branchChildren) { if (string.IsNullOrEmpty(branchChild.Name)) { CapDataRow childRow = Flatten(branchChild, innerNamingPrefix, name); if (childRow != null) { childRow.Columns["_index"] = index; index++; row.ChildRows.Add(childRow); } } } } // named branches if (namelessBranchChildren < branchChildren.Count) { foreach (TreeNode branchChild in branchChildren) { if (!string.IsNullOrEmpty(branchChild.Name)) { CapDataRow childRow = Flatten(branchChild, innerNamingPrefix, name); if (childRow != null) { row.ChildRows.Add(childRow); } } } } object typedLocalData = node.TypedValue; string typedLocalDataString = node.TypedValueString; if (typedLocalData != null) { row.Columns["_value"] = typedLocalData; if (typedLocalDataString != null) { row.Columns["_string"] = typedLocalDataString; } } if (row.Columns.Count > 0 || row.ChildRows.Count > 0) { return(row); } else { return(null); } }
/// <summary> /// Writes a single data row. /// </summary> /// <param name="row">Row to write.</param> public abstract void WriteRow(CapDataRow row);