private static void GenerateHTMLOutput(Dictionary <uint, HTTPRequestFrame> Requests, Dictionary <uint, HTTPResponseFrame> Responses, Dictionary <uint, HTTPPayloadFrame> Payloads, string outputFile, string captureFileName) { /*Print the number of requests and response objects found*/ Console.WriteLine("Requests : {0}", Requests.Count); Console.WriteLine("Responses: {0}", Responses.Count); Console.WriteLine("Payloads: {0}", Payloads.Count); //Calculate Time taken by a request StringBuilder rawRequestHeaders = new StringBuilder(); StringBuilder rawResponseHeaders = new StringBuilder(); System.IO.StreamWriter sw = new System.IO.StreamWriter(outputFile); #region Prepare the Text File sw.Write(@"<HTML><HEAD><meta http-equiv='X-UA-Compatible' content='IE=EmulateIE7'/> "); sw.Write(@"<TITLE>Netmon HTTPAnalyzer REPORT</TITLE>"); sw.Write(@"<script src='http://code.jquery.com/jquery-latest.js'></script>"); sw.Write(@"<script>$(document).ready(function(){$('#sortedtable').tablesorter({sortList:[[0,0]], widgets: ['zebra']});});</script>"); sw.Write(@"<link href='http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css' rel='stylesheet' type='text/css'/>"); sw.Write(@"<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js'></script>"); sw.Write(@"<script src='http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js'></script>"); //sw.WriteLine(@"<SCRIPT language='JavaScript'>function ShowHide(index){$(index).dialog('open');return false;}</SCRIPT>"); sw.Write(@"<STYLE>TABLE{font-family: Verdana;font-size:10px;border-collapse:collapse;}BODY{font-family: Verdana;font-size:10px;}A:HOVER {font-weight:bold;text-decoration:underline}A.SSL {color:red}"); //Style for sorted table //sw.Write(@"TH.headerSortUp { background-image: url(../img/small_asc.gif); background-color: #3399FF; } TH.headerSortDown { background-image: url(../img/small_desc.gif); background-color: #3399FF; } TH.header { background-image: url(../img/small.gif);cursor: pointer; font-weight: bold; background-repeat: no-repeat; background-position: center left; padding-left: 20px; border-right: 1px solid black; margin-left: -1px;}"); sw.Write(@"TH{background:#5B9BD5;border:solid #5B9BD5 1.0pt;}TD {overflow:hidden;border:solid #9CC2E5 1.0pt}.alternateRow{background:#DEEAF6;}"); sw.Write(@"</STYLE></HEAD>"); sw.Write(@"<BODY>"); sw.Write(@"<script src='http://dev.jquery.com/view/trunk/plugins/tablesorter/2.0/jquery.tablesorter.js'></script>"); sw.Write("HTTP parsed output for the file \"" + captureFileName + "\"<BR/>"); sw.Write("HTTP parsed output written to the file \"" + outputFile + "\"<BR/>"); sw.Write(@"<li/>Total Number of HTTP Requests found : " + Requests.Count); sw.Write(@"<li/>Total Number of HTTP Responses found : " + Responses.Count); sw.Write(@"<li/>Total Number of HTTP Payload packets found : " + Payloads.Count + "<BR/><BR/>"); sw.Write("Hover your mouse over the title to see more information about each field<BR><BR/>"); sw.Write(@"<TABLE BORDER='1' id='sortedtable' class='tablesorter' WIDTH='100%'><THEAD><TR>"); sw.Write(@"<TH align=center><a title='Frame # in the netmon trace where the Request packet can be found'>Request Frame #</a></TH>"); sw.Write(@"<TH align=center><a title='Time in the netmon trace when the HTTP request was made'>Time</a></TH>"); sw.Write(@"<TH align=center><a title='IP and port FROM which the HTTP request was made'>Source IP:Port</a></TH>"); sw.Write(@"<TH align=center>Method</TH>"); sw.Write(@"<TH align=center><a title='Size of Request headers + ContentLength header (if present) '>Request length</a></TH>"); sw.Write(@"<TH align=center width = '400px'>Requested URL</TH>"); sw.Write(@"<TH align=center width = '300px'>Query String</TH>"); sw.Write(@"<TH align=center><a title='IP and port TO which the HTTP request was made'>Destination IP:Port</a></TH>"); sw.Write(@"<TH align=center><a title='Frame # in the netmon trace where the first Response packet can be found'>Response Frame #</a></TH>"); sw.Write(@"<TH align=center>Status</TH>"); sw.Write(@"<TH align=center><a title='Value of the ContentLength header'>Response length</a></TH>"); sw.Write(@"<TH align=center><a title='Time between the HTTP Request frame and Last Response Payload frame'>Time-Taken</a></TH>"); //sw.Write(@"<TH align=center>Content-Type</TH>"); sw.Write(@"<TH align=center><a title='Copy netmon filter for this conversation'>Filter</a></TH>"); sw.Write(@"</TR></THEAD><tbody>"); #endregion //int divId = 1; int rowId = 0; string styleForTR; foreach (KeyValuePair <uint, HTTPRequestFrame> request in Requests) { rowId++; if (rowId % 2 == 0) { styleForTR = " class='alternateRow' "; } else { styleForTR = ""; } #region Response Time calculation considering the Response Payload's { #region Get the Next Request on the same conversation HTTPRequestFrame nextRequest = Requests.FirstOrDefault(x => ( (x.Value.Number > request.Value.Number) && (x.Value.SourceIP == request.Value.SourceIP) && (x.Value.SourcePort == request.Value.SourcePort) && (x.Value.DestinationIP == request.Value.DestinationIP) && (x.Value.DestinationPort == request.Value.DestinationPort) ) ).Value; #endregion #region Get the Last Payload packet for the response (there might be more requests on the same conversation's) HTTPPayloadFrame lastPayload = null; if (nextRequest != null) { lastPayload = Payloads.LastOrDefault(x => ( (x.Value.Number < nextRequest.Number) && (x.Value.Number > request.Value.Number) && (x.Value.SourceIP == nextRequest.DestinationIP) && (x.Value.SourcePort == nextRequest.DestinationPort) && (x.Value.DestinationIP == nextRequest.SourceIP) && (x.Value.DestinationPort == nextRequest.SourcePort) && (x.Value.URL == request.Value.URL) ) ).Value; } else { lastPayload = Payloads.LastOrDefault(x => ( (x.Value.Number > request.Value.Number) && (x.Value.SourceIP == request.Value.DestinationIP) && (x.Value.SourcePort == request.Value.DestinationPort) && (x.Value.DestinationIP == request.Value.SourceIP) && (x.Value.DestinationPort == request.Value.SourcePort) && (x.Value.URL == request.Value.URL) ) ).Value; } #endregion #region Find the Response Packet HTTPResponseFrame response; if (nextRequest != null) { response = Responses.FirstOrDefault(x => ( (x.Value.SourceIP == request.Value.DestinationIP) && (x.Value.DestinationIP == request.Value.SourceIP) && (x.Value.SourcePort == request.Value.DestinationPort) && (x.Value.DestinationPort == request.Value.SourcePort) && (x.Value.Number > request.Value.Number) && (x.Value.Number < nextRequest.Number) && (x.Value.URL.Contains(request.Value.URL.Substring(0, (request.Value.URL.Length > 100) ? 100 : request.Value.URL.Length))) ) ).Value; } else { response = Responses.FirstOrDefault(x => ( (x.Value.SourceIP == request.Value.DestinationIP) && (x.Value.DestinationIP == request.Value.SourceIP) && (x.Value.SourcePort == request.Value.DestinationPort) && (x.Value.DestinationPort == request.Value.SourcePort) && (x.Value.Number > request.Value.Number) && (x.Value.URL.Contains(request.Value.URL.Substring(0, (request.Value.URL.Length > 100) ? 100 : request.Value.URL.Length))) ) ).Value; } #endregion #region Prepare Request Headers rawRequestHeaders.AppendLine(request.Value.Method + " " + request.Value.URL + ((request.Value.QueryString.Length > 0) ? request.Value.QueryString : string.Empty) + "<BR>"); foreach (KeyValuePair <int, HTTPHeader> pair in request.Value.Headers) { rawRequestHeaders.AppendLine(pair.Value.HeaderName + ":" + pair.Value.HeaderValue + "<BR>"); } #endregion #region Calculate the Response Time and Print the output to the file sw.WriteLine(@"<TR " + styleForTR + ">"); sw.WriteLine(@"<TD align=center>" + request.Value.Number + "</TD>"); sw.WriteLine(@"<TD align=center>" + request.Value.TimeStamp + "</TD>"); sw.WriteLine(@"<TD align=center>" + request.Value.SourceIP + ":" + request.Value.SourcePort.ToString() + "</TD>"); //sw.WriteLine("<TD align=center><a id='a_" + (divId - 1) + "' href='#'>" + request.Value.Method + "</a></TD>"); sw.WriteLine("<TD align=center>" + request.Value.Method + "</TD>"); #region Print Content-Length from Request headers { int headerLength = Convert.ToInt32(rawRequestHeaders.ToString().Replace("<BR>", "").Length); int contentLenght = request.Value.GetHeaderIndex("contentlength"); if (contentLenght > 0) { int contentLengthValue = Convert.ToInt32(request.Value.Headers[contentLenght].HeaderValue); sw.WriteLine(@"<TD align=center><span title='" + headerLength.ToString() + " + " + contentLengthValue.ToString() + "'>" + (headerLength + contentLengthValue).ToString() + "</span></TD>"); } else { sw.WriteLine(@"<TD align=center><span title='" + headerLength.ToString() + " + 0'>" + rawRequestHeaders.ToString().Replace("<BR>", "").Length.ToString() + "<span></TD>"); } } #endregion #region Print URL of the request and the QueryString if (request.Value.URL.Contains("http:")) { //sw.WriteLine(@"<TD align=left width='30%'>" + request.Value.URL + ((request.Value.QueryString.Length > 0) ? request.Value.QueryString : string.Empty) + "</TD>"); sw.WriteLine(@"<TD align=left><div style='overflow:hidden;width:400px;word-wrap:break-word;'>" + request.Value.URL + "</div></TD>"); sw.WriteLine(@"<TD align=left><div style='overflow:hidden;width:300px;word-wrap:break-word;'>" + ((request.Value.QueryString.Length > 0) ? request.Value.QueryString : "--") + "</div></TD>"); } else { if (request.Value.GetHeaderValue("host") == "") { //sw.WriteLine(@"<TD align=left width='30%'>" + request.Value.URL + ((request.Value.QueryString.Length > 0) ? request.Value.QueryString : string.Empty) + "</TD>"); sw.WriteLine(@"<TD align=left><div style='overflow:hidden;width:400px;word-wrap:break-word;'>" + request.Value.URL + "</div></TD>"); sw.WriteLine(@"<TD align=left><div style='overflow:hidden;width:300px;word-wrap:break-word;'>" + ((request.Value.QueryString.Length > 0) ? request.Value.QueryString : string.Empty) + "</div></TD>"); } else { //sw.WriteLine(@"<TD align=left width='30%'>http://" + request.Value.GetHeaderValue("host") + request.Value.URL + ((request.Value.QueryString.Length > 0) ? request.Value.QueryString : string.Empty) + "</TD>"); sw.WriteLine(@"<TD align=left><div style='overflow:hidden;width:400px;word-wrap:break-word;'>http://" + request.Value.GetHeaderValue("host") + request.Value.URL + "</div></TD>"); sw.WriteLine(@"<TD align=left><div style='overflow:hidden;width:300px;word-wrap:break-word;'>" + ((request.Value.QueryString.Length > 0) ? request.Value.QueryString : string.Empty) + "</div></TD>"); } } #endregion if (response != null) { sw.WriteLine(@"<TD align=center>" + response.SourceIP + ":" + response.SourcePort.ToString() + "</TD>"); sw.WriteLine(@"<TD align=center>" + response.Number + "</TD>"); //sw.WriteLine(@"<TD align=center><a href='#' id='a_" + divId + "' >" + response.StatusCode + "</a></TD>"); sw.WriteLine(@"<TD align=center>" + response.StatusCode + "</TD>"); #region Print Content-Length from Response headers { #region To-Do Enchancement //Here I am simply displaying the Content-Length header. There are times when the Content-Length header is not present //In such a case, I should add the size of Response and every Response Payload packet and then show the value here //This will require me to add a new field to the HTTPResponseFrame and HTTPPayloadFrame classes and populate them #endregion int contentLenght = response.GetHeaderIndex("contentlength"); if (contentLenght > 0) { sw.WriteLine(@"<TD align=center>" + response.Headers[contentLenght].HeaderValue + "</TD>"); } else { sw.WriteLine(@"<TD align=center> <a alt='Content-Length header not found'>--</a></TD>"); } } #endregion #region Print time-taken for a request if (lastPayload == null) { sw.WriteLine(@"<TD align=center>" + (response.TimeStamp - request.Value.TimeStamp) + "</TD>"); } else { sw.WriteLine(@"<TD align=center>" + (lastPayload.TimeStamp - request.Value.TimeStamp) + "</TD>"); } #endregion #region Print Content-Type from Response headers - NOT PRINTING FOR NOW AS IT IS MESSING THE REPORT LAYOUT {/* * int contentType = response.GetHeaderIndex("contenttype"); * if (contentType > 0) * sw.WriteLine(@"<TD align=center>" + response.Headers[contentType].HeaderValue + "</TD>"); * else * sw.WriteLine(@"<TD align=center> -- </TD>"); */ } #endregion #region Prepare Response Headers foreach (KeyValuePair <int, HTTPHeader> pair in response.Headers) { rawResponseHeaders.AppendLine(pair.Value.HeaderName + ":" + pair.Value.HeaderValue + "<BR>"); } #endregion } else { // No Response found for this request in this trace sw.WriteLine(@"<TD align=center>" + request.Value.DestinationIP + " (" + request.Value.DestinationPort.ToString() + ")</TD>"); sw.WriteLine(@"<TD align=center> -- </TD>"); sw.WriteLine(@"<TD align=center>RESPONSE_NOT_FOUND</TD>"); sw.WriteLine(@"<TD align=center> -- </TD>"); sw.WriteLine(@"<TD align=center> -- </TD>"); } #region Create netmon Conversation Filter { string filter = ""; if (request.Value.SourceIP.Contains(":")) { filter += "ipv6.Address==" + request.Value.SourceIP; } else { filter += "ipv4.Address==" + request.Value.SourceIP; } if (request.Value.DestinationIP.Contains(":")) { filter += " and ipv6.Address==" + request.Value.DestinationIP; } else { filter += " and ipv4.Address==" + request.Value.DestinationIP; } filter += " and tcp.port == " + request.Value.SourcePort.ToString() + " and tcp.port == " + request.Value.DestinationPort.ToString(); sw.WriteLine("<TD>"); //sw.WriteLine("<input type='button' value='CopyMe' onclick =\"var str = '" + filter + "';if (window.clipboardData){if(clipboardData.setData)clipboardData.setData('text', str);}else{window.prompt('Copy to clipboard: Ctrl+C, Enter', str);}\" />"); sw.WriteLine(filter); sw.WriteLine("</TD>"); } #endregion sw.WriteLine(@"</TR>"); { #region Print Request Headers /* * This is increasing the size of the report like crazy to an extent that IE is unable to even show the report for huge traces!!! So commenting ths part * sw.WriteLine(@"<DIV ID='div_" + (divId - 1) + "' style='DISPLAY: none'>"); divId++; * sw.WriteLine(@"<HR>"); * sw.WriteLine(rawRequestHeaders.ToString()); * sw.WriteLine(@"<HR>"); * sw.WriteLine(@"</DIV>"); * * sw.WriteLine("<script>$(document).ready(function(){$(\"#div_" + (divId - 2) + "\").dialog({autoOpen:false,title:'Request Header',width:'80%'});$(\"#a_" + (divId - 2) + "\").click(function(){$(\"#div_" + (divId - 2) + "\").dialog('open');return false;});})</script>"); * sw.WriteLine("<script>$</script>"); * * rawRequestHeaders.Clear(); * sw.Flush(); */ #endregion } if (response != null) { #region Print Response Headers /* * This is increasing the size of the report like crazy to an extent that IE is unable to even show the report for huge traces!!! So commenting ths part * sw.WriteLine(@"<DIV ID='div_" + (divId - 1) + "' style='DISPLAY: none'>"); divId++; * sw.WriteLine(@"<HR>"); * sw.WriteLine(rawResponseHeaders.ToString()); * sw.WriteLine(@"<HR>"); * sw.WriteLine(@"</DIV>"); * * sw.WriteLine("<script>$(document).ready(function(){$(\"#div_" + (divId - 2) + "\").dialog({autoOpen:false,title:'Response Header',width:'80%'});$(\"#a_" + (divId - 2) + "\").click(function(){$(\"#div_" + (divId - 2) + "\").dialog('open');return false;});})</script>"); * * rawResponseHeaders.Clear(); */ #endregion sw.Flush(); } #endregion sw.Flush(); } #endregion } sw.WriteLine(@"</tbody></TABLE>"); sw.WriteLine(@"</BODY>"); sw.WriteLine(@"</HTML>"); sw.Close(); }
//Need to fix this to match the new logic introduced in the generation of HTML output //No one requires CSV output so not investing time in this for now, will look into this if the need arises private static void GenerateCSVOutput(Dictionary <uint, HTTPRequestFrame> Requests, Dictionary <uint, HTTPResponseFrame> Responses, Dictionary <uint, HTTPPayloadFrame> Payloads, string outputFile, string captureFileName) { /*Print the number of requests and response objects found*/ Console.WriteLine("Requests : {0}", Requests.Count); Console.WriteLine("Responses: {0}", Responses.Count); Console.WriteLine("Payloads: {0}", Payloads.Count); //Calculate Time taken by a request StringBuilder rawRequestHeaders = new StringBuilder(); StringBuilder rawResponseHeaders = new StringBuilder(); System.IO.StreamWriter sw = new System.IO.StreamWriter(outputFile); #region Prepare the Text File sw.Write(@"<HTML><HEAD>"); sw.Write(@"<TITLE>Netmon HTTPAnalyzer REPORT</TITLE>"); sw.Write(@"</HEAD>"); sw.Write(@"<BODY>"); sw.Write("HTTP parsed output for the file \"" + captureFileName + "\"<BR/>"); sw.Write("HTTP parsed output written to the file \"" + outputFile + "\"<BR/>"); sw.Write(@"<li/>Total Number of HTTP Requests found : " + Requests.Count); sw.Write(@"<li/>Total Number of HTTP Responses found : " + Responses.Count); sw.Write(@"<li/>Total Number of HTTP Payload packets found : " + Payloads.Count + "<BR/><BR/>"); sw.Write(@"<TABLE BORDER='1'><THEAD><TR>"); sw.Write(@"<TH align=center><a title='HTTP Request Frame # in the netmon trace'>Request Frame #</a></TH>"); sw.Write(@"<TH align=center><a title='Time in the netmon trace when the HTTP request was made'>Time</a></TH>"); sw.Write(@"<TH align=center><a title='IP and port FROM which the HTTP request was made'>Source IP<BR>(Port)</a></TH>"); sw.Write(@"<TH align=center>Method</TH>"); sw.Write(@"<TH align=center><a title='Size of Request headers + ContentLength header (if present) '>Request length</a></TH>"); sw.Write(@"<TH align=center width = '30%'>Requested URL</TH>"); sw.Write(@"<TH align=center><a title='IP and port TO which the HTTP request was made'>Destination IP<BR>(Port)</a></TH>"); sw.Write(@"<TH align=center><a title='HTTP Request Frame # in the netmon trace'>Response Frame #</a></TH>"); sw.Write(@"<TH align=center>Status</TH>"); sw.Write(@"<TH align=center><a title='Value of the ContentLength header'>Response length</a></TH>"); sw.Write(@"<TH align=center><a title='Time between the HTTP Request frame and Last Response Payload frame'>Time-Taken</a></TH>"); sw.Write(@"<TH align=center>Content-Type</TH>"); sw.Write(@"<TH align=center><a title='Copy netmon filter for this conversation'>Filter</a></TH>"); sw.Write(@"<TH align=center>Request Headers</TH>"); sw.Write(@"<TH align=center>Response Headers</TH>"); sw.Write(@"</TR></THEAD><tbody>"); #endregion int divId = 1; foreach (KeyValuePair <uint, HTTPRequestFrame> request in Requests) { #region Response Time calculation considering the Response Payload's { #region Get the Next Request on the same conversation HTTPRequestFrame nextRequest = Requests.FirstOrDefault(x => ( (x.Value.Number > request.Value.Number) && (x.Value.SourceIP == request.Value.SourceIP) && (x.Value.SourcePort == request.Value.SourcePort) && (x.Value.DestinationIP == request.Value.DestinationIP) && (x.Value.DestinationPort == request.Value.DestinationPort) ) ).Value; #endregion #region Get the Last Payload packet for the response (there might be more requests on the same conversation's) HTTPPayloadFrame lastPayload = null; if (nextRequest != null) { lastPayload = Payloads.LastOrDefault(x => ( (x.Value.Number < nextRequest.Number) && (x.Value.Number > request.Value.Number) && (x.Value.SourceIP == nextRequest.DestinationIP) && (x.Value.SourcePort == nextRequest.DestinationPort) && (x.Value.DestinationIP == nextRequest.SourceIP) && (x.Value.DestinationPort == nextRequest.SourcePort) && (x.Value.URL.Contains(request.Value.URL.Substring(0, (request.Value.URL.Length > 100) ? 100 : request.Value.URL.Length))) ) ).Value; } else { lastPayload = Payloads.LastOrDefault(x => ( (x.Value.Number > request.Value.Number) && (x.Value.SourceIP == request.Value.DestinationIP) && (x.Value.SourcePort == request.Value.DestinationPort) && (x.Value.DestinationIP == request.Value.SourceIP) && (x.Value.DestinationPort == request.Value.SourcePort) && (x.Value.URL.Contains(request.Value.URL.Substring(0, (request.Value.URL.Length > 100) ? 100 : request.Value.URL.Length))) ) ).Value;; } #endregion #region Find the Response Packet HTTPResponseFrame response; if (nextRequest != null) { response = Responses.FirstOrDefault(x => ( (x.Value.SourceIP == request.Value.DestinationIP) && (x.Value.DestinationIP == request.Value.SourceIP) && (x.Value.SourcePort == request.Value.DestinationPort) && (x.Value.DestinationPort == request.Value.SourcePort) && (x.Value.Number > request.Value.Number) && (x.Value.Number < nextRequest.Number) && (x.Value.URL.Contains(request.Value.URL.Substring(0, (request.Value.URL.Length > 100) ? 100 : request.Value.URL.Length))) ) ).Value; } else { response = Responses.FirstOrDefault(x => ( (x.Value.SourceIP == request.Value.DestinationIP) && (x.Value.DestinationIP == request.Value.SourceIP) && (x.Value.SourcePort == request.Value.DestinationPort) && (x.Value.DestinationPort == request.Value.SourcePort) && (x.Value.Number > request.Value.Number) && (x.Value.URL.Contains(request.Value.URL.Substring(0, (request.Value.URL.Length > 100) ? 100 : request.Value.URL.Length))) ) ).Value; } #endregion #region Prepare Request Headers rawRequestHeaders.AppendLine(request.Value.Method + " " + request.Value.URL + ((request.Value.QueryString.Length > 0) ? request.Value.QueryString : string.Empty) + "<BR>"); foreach (KeyValuePair <int, HTTPHeader> pair in request.Value.Headers) { rawRequestHeaders.AppendLine(pair.Value.HeaderName + ":" + pair.Value.HeaderValue + "<BR>"); } #endregion #region Calculate the Response Time and Print the output to the file sw.WriteLine(@"<TR>"); sw.WriteLine(@"<TD align=center>" + request.Value.Number + "</TD>"); sw.WriteLine(@"<TD align=center>" + request.Value.TimeStamp + "</TD>"); sw.WriteLine(@"<TD align=center>" + request.Value.SourceIP + " (" + request.Value.SourcePort.ToString() + ")</TD>"); sw.WriteLine("<TD align=center><a id='a_" + (divId - 1) + "' href='#'>" + request.Value.Method + "</a></TD>"); #region Print Content-Length from Request headers { int headerLength = Convert.ToInt32(rawRequestHeaders.ToString().Replace("<BR>", "").Length); int contentLenght = request.Value.GetHeaderIndex("contentlength"); if (contentLenght > 0) { int contentLengthValue = Convert.ToInt32(request.Value.Headers[contentLenght].HeaderValue); sw.WriteLine(@"<TD align=center><span title='" + headerLength.ToString() + " + " + contentLengthValue.ToString() + "'>" + (headerLength + contentLengthValue).ToString() + "</span></TD>"); } else { sw.WriteLine(@"<TD align=center><span title='" + headerLength.ToString() + " + 0'>" + rawRequestHeaders.ToString().Replace("<BR>", "").Length.ToString() + "<span></TD>"); } } #endregion #region Print URL of the request if (request.Value.URL.Contains("http:")) { sw.WriteLine(@"<TD align=left width='30%'>" + request.Value.URL + ((request.Value.QueryString.Length > 0) ? request.Value.QueryString : string.Empty) + "</TD>"); } else if (request.Value.GetHeaderValue("host") == "") { sw.WriteLine(@"<TD align=left width='30%'>" + request.Value.URL + ((request.Value.QueryString.Length > 0) ? request.Value.QueryString : string.Empty) + "</TD>"); } else { sw.WriteLine(@"<TD align=left width='30%'>http://" + request.Value.GetHeaderValue("host") + request.Value.URL + ((request.Value.QueryString.Length > 0) ? request.Value.QueryString : string.Empty) + "</TD>"); } #endregion if (response != null) { sw.WriteLine(@"<TD align=center>" + response.SourceIP + " (" + response.SourcePort.ToString() + ")</TD>"); sw.WriteLine(@"<TD align=center>" + response.Number + "</TD>"); sw.WriteLine(@"<TD align=center><a href='#' id='a_" + divId + "' >" + response.StatusCode + "</a></TD>"); #region Print Content-Length from Response headers { int contentLenght = response.GetHeaderIndex("contentlength"); if (contentLenght > 0) { sw.WriteLine(@"<TD align=center>" + response.Headers[contentLenght].HeaderValue + "</TD>"); } else { sw.WriteLine(@"<TD align=center> -- </TD>"); } } #endregion #region Print time-taken for a request if (lastPayload == null) { sw.WriteLine(@"<TD align=center>" + (response.TimeStamp - request.Value.TimeStamp) + "</TD>"); } else { sw.WriteLine(@"<TD align=center>" + (lastPayload.TimeStamp - request.Value.TimeStamp) + "</TD>"); } #endregion #region Print Content-Type from Response headers { int contentType = response.GetHeaderIndex("contenttype"); if (contentType > 0) { sw.WriteLine(@"<TD align=center>" + response.Headers[contentType].HeaderValue + "</TD>"); } else { sw.WriteLine(@"<TD align=center> -- </TD>"); } } #endregion #region Prepare Response Headers foreach (KeyValuePair <int, HTTPHeader> pair in response.Headers) { rawResponseHeaders.AppendLine(pair.Value.HeaderName + ":" + pair.Value.HeaderValue + "<BR>"); } #endregion } else { // No Response found for this request in this trace sw.WriteLine(@"<TD align=center>" + request.Value.DestinationIP + " (" + request.Value.DestinationPort.ToString() + ")</TD>"); sw.WriteLine(@"<TD align=center> -- </TD>"); sw.WriteLine(@"<TD align=center>NO_RESPONSE</TD>"); sw.WriteLine(@"<TD align=center> -- </TD>"); sw.WriteLine(@"<TD align=center> -- </TD>"); sw.WriteLine(@"<TD align=center> -- </TD>"); } #region Create netmon Conversation Filter { string filter = ""; if (request.Value.SourceIP.Contains(":")) { filter += "ipv6.Address==" + request.Value.SourceIP; } else { filter += "ipv4.Address==" + request.Value.SourceIP; } if (request.Value.DestinationIP.Contains(":")) { filter += " and ipv6.Address==" + request.Value.DestinationIP; } else { filter += " and ipv4.Address==" + request.Value.DestinationIP; } filter += " and tcp.port == " + request.Value.SourcePort.ToString() + " and tcp.port == " + request.Value.DestinationPort.ToString(); sw.WriteLine("<TD>"); sw.WriteLine("<input type='button' value='CopyMe' onclick =\"var str = '" + filter + "';if (window.clipboardData){if(clipboardData.setData)clipboardData.setData('text', str);}else{window.prompt('Copy to clipboard: Ctrl+C, Enter', str);}\" />"); sw.WriteLine("</TD>"); } #endregion sw.WriteLine(@"</TR>"); { #region Print Request Headers sw.WriteLine(@"<DIV ID='div_" + (divId - 1) + "' style='DISPLAY: none'>"); divId++; sw.WriteLine(@"<HR>"); sw.WriteLine(rawRequestHeaders.ToString()); sw.WriteLine(@"<HR>"); sw.WriteLine(@"</DIV>"); sw.WriteLine("<script>$(document).ready(function(){$(\"#div_" + (divId - 2) + "\").dialog({autoOpen:false,title:'Request Header',width:'80%'});$(\"#a_" + (divId - 2) + "\").click(function(){$(\"#div_" + (divId - 2) + "\").dialog('open');return false;});})</script>"); sw.WriteLine("<script>$</script>"); rawRequestHeaders.Clear(); sw.Flush(); #endregion } if (response != null) { #region Print Response Headers sw.WriteLine(@"<DIV ID='div_" + (divId - 1) + "' style='DISPLAY: none'>"); divId++; sw.WriteLine(@"<HR>"); sw.WriteLine(rawResponseHeaders.ToString()); sw.WriteLine(@"<HR>"); sw.WriteLine(@"</DIV>"); sw.WriteLine("<script>$(document).ready(function(){$(\"#div_" + (divId - 2) + "\").dialog({autoOpen:false,title:'Response Header',width:'80%'});$(\"#a_" + (divId - 2) + "\").click(function(){$(\"#div_" + (divId - 2) + "\").dialog('open');return false;});})</script>"); rawResponseHeaders.Clear(); #endregion sw.Flush(); } #endregion sw.Flush(); } #endregion } sw.WriteLine(@"</tbody></TABLE>"); sw.WriteLine(@"</BODY>"); sw.WriteLine(@"</HTML>"); sw.Close(); }