--- packet-http.c	2007-11-07 09:18:09.062500000 +0200
+++ /cygdrive/c/packet-http.c	2007-11-07 00:34:21.093750000 +0200
@@ -191,7 +191,7 @@
 	char	*transfer_encoding;
 } headers_t;
 
-static int is_http_request_or_reply(const gchar *data, int linelen,
+static int is_http_request_or_reply(tvbuff_t *tvb, const int offset, int linelen,
 				    http_type_t *type, ReqRespDissector
 				    *reqresp_dissector, http_conv_t *conv_data);
 static int chunked_encoding_dissector(tvbuff_t **tvb_ptr, packet_info *pinfo,
@@ -202,7 +202,7 @@
 static void process_header(tvbuff_t *tvb, int offset, int next_offset,
     const guchar *line, int linelen, int colon_offset, packet_info *pinfo,
     proto_tree *tree, headers_t *eh_ptr, http_conv_t *conv_data);
-static gint find_header_hf_value(tvbuff_t *tvb, int offset, guint header_len);
+static gint find_header_hf_value(const guchar *line, const guint header_len);
 static gboolean check_auth_ntlmssp(proto_item *hdr_item, tvbuff_t *tvb,
     packet_info *pinfo, gchar *value);
 static gboolean check_auth_basic(proto_item *hdr_item, tvbuff_t *tvb,
@@ -299,12 +299,12 @@
 	int reqs_by_this_host;
 	int reqs_by_this_addr;
 	int resps_by_this_addr;
-	int i = v->response_code;
+	guint i = v->response_code;
 	static gchar ip_str[256];
 
 
 	if (v->request_method) {
-		g_snprintf(ip_str,sizeof(ip_str),"%s",address_to_str(&pinfo->dst));
+		g_snprintf(ip_str,sizeof(ip_str), address_to_str(&pinfo->dst));
 
 		tick_stat_node(st, st_str_reqs, 0, FALSE);
 		tick_stat_node(st, st_str_reqs_by_srv_addr, st_node_reqs, TRUE);
@@ -321,7 +321,7 @@
 		return 1;
 
 	} else if (i != 0) {
-		g_snprintf(ip_str,sizeof(ip_str),"%s",address_to_str(&pinfo->src));
+		g_snprintf(ip_str,sizeof(ip_str), address_to_str(&pinfo->src));
 
 		tick_stat_node(st, st_str_resps_by_srv_addr, 0, FALSE);
 		resps_by_this_addr = tick_stat_node(st, ip_str, st_node_resps_by_srv_addr, TRUE);
@@ -559,10 +559,11 @@
 	/*
 	 * Is the first line a request or response?
 	 */
-	line = tvb_get_ptr(tvb, offset, first_linelen);
 	http_type = HTTP_OTHERS;	/* type not known yet */
-	is_request_or_reply = is_http_request_or_reply((const gchar *)line,
-	    first_linelen, &http_type, NULL, conv_data);
+	stat_info = ep_alloc0(sizeof(http_info_value_t));
+	reqresp_dissector = NULL;
+	is_request_or_reply = is_http_request_or_reply(tvb, offset,
+			first_linelen, &http_type, &reqresp_dissector, conv_data);
 	if (is_request_or_reply) {
 		/*
 		 * Yes, it's a request or response.
@@ -579,12 +580,7 @@
 		}
 	}
 
-	stat_info = ep_alloc(sizeof(http_info_value_t));
 	stat_info->framenum = pinfo->fd->num;
-	stat_info->response_code = 0;
-	stat_info->request_method = NULL;
-	stat_info->request_uri = NULL;
-	stat_info->http_host = NULL;
 
 	switch (pinfo->match_port) {
 
@@ -635,7 +631,6 @@
 	/*
 	 * Process the packet data, a line at a time.
 	 */
-	http_type = HTTP_OTHERS;	/* type not known yet */
 	headers.content_type = NULL;	/* content type not known yet */
 	headers.content_type_parameters = NULL;	/* content type parameters too */
 	headers.have_content_length = FALSE;	/* content length not known yet */
@@ -662,26 +657,15 @@
 		 */
 		line = tvb_get_ptr(tvb, offset, linelen);
 		lineend = line + linelen;
-		colon_offset = -1;
 
 		/*
-		 * OK, does it look like an HTTP request or response?
+		 * OK, does it look like an HTTP request or response? or is it a blank like (as would appear
+		* at the end of a HTTP request)?
 		 */
-		reqresp_dissector = NULL;
-		is_request_or_reply =
-		    is_http_request_or_reply((const gchar *)line,
-		    linelen, &http_type, &reqresp_dissector, conv_data);
-		if (is_request_or_reply)
+		if (is_request_or_reply || linelen == 0)
 			goto is_http;
 
 		/*
-		 * No.  Does it look like a blank line (as would appear
-		 * at the end of an HTTP request)?
-		 */
-		if (linelen == 0)
-			goto is_http;	/* Yes. */
-
-		/*
 		 * No.  Does it look like a header?
 		 */
 		linep = line;
@@ -712,6 +696,13 @@
 			 */
 			switch (c) {
 
+			case ':':
+				/*
+				 * This ends the token; we consider this
+				 * to be a header.
+				 */
+				goto is_http;
+
 			case '(':
 			case ')':
 			case '<':
@@ -739,13 +730,6 @@
 				 */
 				goto not_http;
 
-			case ':':
-				/*
-				 * This ends the token; we consider this
-				 * to be a header.
-				 */
-				goto is_http;
-
 			default:
 				colon_offset++;
 				break;
@@ -798,7 +782,7 @@
 			 * request or reply.
 			 */
 			proto_tree_add_text(http_tree, tvb, offset,
-			    next_offset - offset, "%s",
+			    next_offset - offset,
 			    tvb_format_text(tvb, offset, next_offset - offset));
 			offset = next_offset;
 			break;
@@ -810,14 +794,14 @@
 		 */
 		saw_req_resp_or_header = TRUE;
 		if (is_request_or_reply) {
+			is_request_or_reply = FALSE; /* for the next line, do not assume it's a request/reply header, it's probably another internal header */
 			if (tree) {
 				hdr_item = proto_tree_add_text(http_tree, tvb,
-				    offset, next_offset - offset, "%s",
+				    offset, next_offset - offset,
 				    tvb_format_text(tvb, offset,
 				      next_offset - offset));
 			}
 			expert_add_info_format(pinfo, hdr_item, PI_SEQUENCE, PI_CHAT,
-				"%s",
 				tvb_format_text(tvb, offset, next_offset - offset));
 			if (reqresp_dissector) {
 				if (tree) req_tree = proto_item_add_subtree(hdr_item, ett_http_request);
@@ -840,11 +824,6 @@
 	if (tree) {
 		switch (http_type) {
 
-		case HTTP_NOTIFICATION:
-			proto_tree_add_boolean_hidden(http_tree,
-			    hf_http_notification, tvb, 0, 0, 1);
-			break;
-
 		case HTTP_RESPONSE:
 			proto_tree_add_boolean_hidden(http_tree,
 			    hf_http_response, tvb, 0, 0, 1);
@@ -855,6 +834,11 @@
 			    hf_http_request, tvb, 0, 0, 1);
 			break;
 
+			case HTTP_NOTIFICATION:
+			proto_tree_add_boolean_hidden(http_tree,
+			    hf_http_notification, tvb, 0, 0, 1);
+			break;
+
 		case HTTP_OTHERS:
 		default:
 			break;
@@ -1530,20 +1514,62 @@
 	}
 }
 
-
-
 /*
  * XXX - this won't handle HTTP 0.9 replies, but they're all data
  * anyway.
  */
 static int
-is_http_request_or_reply(const gchar *data, int linelen, http_type_t *type,
+is_http_request_or_reply(tvbuff_t *tvb, const int offset, int linelen, http_type_t *type,
 			 ReqRespDissector *reqresp_dissector,
 			 http_conv_t *conv_data)
 {
 	int isHttpRequestOrReply = FALSE;
 	int prefix_len = 0;
+	const guchar *data;
+	const guchar *ptr;
+	int index = 3;
+	/*
+	* Perform a fast comparison for the 3 most common headers in HTTP packets (in the first line)
+	* which all happen to be 4 bytes long: 'HTTP' (response), 'GET ', or 'POST' (requests).
+	* For 'HTTP', we should really look for the '/', so we do that too.
+	* For the 'GET', we didn't have to look for the ' '(space) at the end, but it was faster and not
+	* too wrong to do anyway.
+	*/
+	if(linelen >= 4) {
+		const guint32 text = tvb_get_ntohl(tvb, offset);
+		if (text == 0x48545450 && tvb_get_guint8(tvb, 4) == 0x2f) { /* 'HTTP' = 0x48545450  , '/' = 0x2f */
+			*type = HTTP_RESPONSE;
+			isHttpRequestOrReply = TRUE;	/* response */
+			if (reqresp_dissector)
+				*reqresp_dissector = basic_response_dissector;
+			
+			return TRUE;
+		}
+		else if (text == 0x47455420) {  /* 'GET ' = 0x47455420 */
+			*type = HTTP_REQUEST;
+			isHttpRequestOrReply = TRUE;	/* request */
+			if (reqresp_dissector)
+				*reqresp_dissector = basic_request_dissector;
+
+			stat_info->request_method = ep_strndup("GET" , 3);
+			conv_data->request_method = ep_strndup("GET", 3);
+			
+			return TRUE;
+		} 
+		else if (text == 0x504f5354) { /*  'POST' = 0x504f5354 */
+			*type = HTTP_REQUEST;
+			isHttpRequestOrReply = TRUE;	/* request */
+			if (reqresp_dissector)
+				*reqresp_dissector = basic_request_dissector;
+
+			stat_info->request_method = ep_strndup("POST", 4);
+			conv_data->request_method = ep_strndup("POST", 4);
+			
+			return TRUE;
+		}
+	}
 
+	data = tvb_get_ptr(tvb, offset, linelen);
 	/*
 	 * From RFC 2774 - An HTTP Extension Framework
 	 *
@@ -1563,14 +1589,9 @@
 	 * From draft-ietf-dasl-protocol-00.txt, a now vanished Microsoft draft:
 	 *	SEARCH
 	 */
-	if (linelen >= 5 && strncmp(data, "HTTP/", 5) == 0) {
-		*type = HTTP_RESPONSE;
-		isHttpRequestOrReply = TRUE;	/* response */
-		if (reqresp_dissector)
-			*reqresp_dissector = basic_response_dissector;
-	} else {
-		const guchar * ptr = (const guchar *)data;
-		int		 index = 0;
+	 /* begin from the 3rd character. The first three are not important - the smallest string is 3 bytes long anyways */
+	ptr = (const guchar *)data + 3; 
+
 
 		/* Look for the space following the Method */
 		while (index < linelen) {
@@ -1598,12 +1619,11 @@
 			break;
 
 		case 4:
-			if (strncmp(data, "COPY", index) == 0 ||
-			    strncmp(data, "HEAD", index) == 0 ||
+			if (strncmp(data, "HEAD", index) == 0 ||
+			    strncmp(data, "COPY", index) == 0 ||
 			    strncmp(data, "LOCK", index) == 0 ||
 			    strncmp(data, "MOVE", index) == 0 ||
-			    strncmp(data, "POLL", index) == 0 ||
-			    strncmp(data, "POST", index) == 0) {
+			    strncmp(data, "POLL", index) == 0) {
 				*type = HTTP_REQUEST;
 				isHttpRequestOrReply = TRUE;
 			}
@@ -1622,8 +1642,8 @@
 			break;
 
 		case 6:
-			if (strncmp(data, "DELETE", index) == 0 ||
-				strncmp(data, "SEARCH", index) == 0 ||
+			if (strncmp(data, "SEARCH", index) == 0 ||
+				strncmp(data, "DELETE", index) == 0 ||
 				strncmp(data, "UNLOCK", index) == 0 ||
 				strncmp(data, "REPORT", index) == 0 ||  /* RFC 3253 3.6 */
 				strncmp(data, "UPDATE", index) == 0) {  /* RFC 3253 7.1 */
@@ -1637,8 +1657,8 @@
 			break;
 
 		case 7:
-			if (strncmp(data, "BDELETE", index) == 0 ||
-			    strncmp(data, "CONNECT", index) == 0 ||
+			if (strncmp(data, "CONNECT", index) == 0 ||
+			    strncmp(data, "BDELETE", index) == 0 ||
 			    strncmp(data, "OPTIONS", index) == 0 ||
 			    strncmp(data, "CHECKIN", index) == 0) {  /* RFC 3253 4.4, 9.4 */
 				*type = HTTP_REQUEST;
@@ -1715,7 +1735,6 @@
 
 
 
-	}
 
 	return isHttpRequestOrReply;
 }
@@ -1725,6 +1744,7 @@
  */
 typedef struct {
 	const char	*name;
+	const guint namelen;
 	gint		*hf;
 	int		special;
 } header_info;
@@ -1739,29 +1759,29 @@
 #define HDR_HOST  7
 
 static const header_info headers[] = {
-	{ "Authorization", &hf_http_authorization, HDR_AUTHORIZATION },
-	{ "Proxy-Authorization", &hf_http_proxy_authorization, HDR_AUTHORIZATION },
-	{ "Proxy-Authenticate", &hf_http_proxy_authenticate, HDR_AUTHENTICATE },
-	{ "WWW-Authenticate", &hf_http_www_authenticate, HDR_AUTHENTICATE },
-	{ "Content-Type", &hf_http_content_type, HDR_CONTENT_TYPE },
-	{ "Content-Length", &hf_http_content_length, HDR_CONTENT_LENGTH },
-	{ "Content-Encoding", &hf_http_content_encoding, HDR_CONTENT_ENCODING },
-	{ "Transfer-Encoding", &hf_http_transfer_encoding, HDR_TRANSFER_ENCODING },
-	{ "User-Agent",	&hf_http_user_agent, HDR_NO_SPECIAL },
-	{ "Host", &hf_http_host, HDR_HOST },
-	{ "Connection", &hf_http_connection, HDR_NO_SPECIAL },
-	{ "Cookie", &hf_http_cookie, HDR_NO_SPECIAL },
-	{ "Accept", &hf_http_accept, HDR_NO_SPECIAL },
-	{ "Referer", &hf_http_referer, HDR_NO_SPECIAL },
-	{ "Accept-Language", &hf_http_accept_language, HDR_NO_SPECIAL },
-	{ "Accept-Encoding", &hf_http_accept_encoding, HDR_NO_SPECIAL },
-	{ "Date", &hf_http_date, HDR_NO_SPECIAL },
-	{ "Cache-Control", &hf_http_cache_control, HDR_NO_SPECIAL },
-	{ "Server", &hf_http_server, HDR_NO_SPECIAL },
-	{ "Location", &hf_http_location, HDR_NO_SPECIAL },
-	{ "Set-Cookie", &hf_http_set_cookie, HDR_NO_SPECIAL },
-	{ "Last-Modified", &hf_http_last_modified, HDR_NO_SPECIAL },
-	{ "X-Forwarded-For", &hf_http_x_forwarded_for, HDR_NO_SPECIAL },
+	{ "Content-Type", sizeof("Content-Type"), &hf_http_content_type, HDR_CONTENT_TYPE },
+	{ "Content-Length", sizeof("Content-Length"), &hf_http_content_length, HDR_CONTENT_LENGTH },
+	{ "User-Agent",	sizeof("User-Agent"), &hf_http_user_agent, HDR_NO_SPECIAL },
+	{ "Accept", sizeof("Accept"), &hf_http_accept, HDR_NO_SPECIAL },
+	{ "Accept-Language", sizeof("Accept-Language"), &hf_http_accept_language, HDR_NO_SPECIAL },
+	{ "Accept-Encoding", sizeof("Accept-Encoding"), &hf_http_accept_encoding, HDR_NO_SPECIAL },
+	{ "Host", sizeof("Host"), &hf_http_host, HDR_HOST },
+	{ "Connection", sizeof("Connection"), &hf_http_connection, HDR_NO_SPECIAL },
+	{ "Server", sizeof("Server"), &hf_http_server, HDR_NO_SPECIAL },
+	{ "Content-Encoding", sizeof("Content-Encoding"), &hf_http_content_encoding, HDR_CONTENT_ENCODING },
+	{ "Transfer-Encoding", sizeof("Transfer-Encoding"), &hf_http_transfer_encoding, HDR_TRANSFER_ENCODING },
+	{ "Cookie", sizeof("Cookie"), &hf_http_cookie, HDR_NO_SPECIAL },
+	{ "Referer", sizeof("Referer"), &hf_http_referer, HDR_NO_SPECIAL },
+	{ "Authorization", sizeof("Authorization"), &hf_http_authorization, HDR_AUTHORIZATION },
+	{ "Proxy-Authorization", sizeof("Proxy-Authorization"), &hf_http_proxy_authorization, HDR_AUTHORIZATION },
+	{ "Proxy-Authenticate", sizeof("Proxy-Authenticate"), &hf_http_proxy_authenticate, HDR_AUTHENTICATE },
+	{ "WWW-Authenticate", sizeof("WWW-Authenticate"), &hf_http_www_authenticate, HDR_AUTHENTICATE },
+	{ "Date", sizeof("Date"), &hf_http_date, HDR_NO_SPECIAL },
+	{ "Cache-Control", sizeof("Cache-Control"), &hf_http_cache_control, HDR_NO_SPECIAL },
+	{ "Location", sizeof("Location"), &hf_http_location, HDR_NO_SPECIAL },
+	{ "Set-Cookie", sizeof("Set-Cookie"), &hf_http_set_cookie, HDR_NO_SPECIAL },
+	{ "Last-Modified", sizeof("Last-Modified"), &hf_http_last_modified, HDR_NO_SPECIAL },
+	{ "X-Forwarded-For", sizeof("X-Forwarded-For"), &hf_http_x_forwarded_for, HDR_NO_SPECIAL },
 };
 
 static void
@@ -1786,7 +1806,7 @@
 	len = next_offset - offset;
 	line_end_offset = offset + linelen;
 	header_len = colon_offset - offset;
-	hf_index = find_header_hf_value(tvb, offset, header_len);
+	hf_index = find_header_hf_value(line, header_len);
 
 	if (hf_index == -1) {
 		/*
@@ -1795,7 +1815,7 @@
 		 */
 		if (tree) {
 			proto_tree_add_text(tree, tvb, offset, len,
-			    "%s", format_text(line, len));
+			    format_text(line, len));
 		}
 	} else {
 		/*
@@ -1836,7 +1856,7 @@
 			default:
 				hdr_item = proto_tree_add_string_format(tree,
 				    *headers[hf_index].hf, tvb, offset, len,
-				    value, "%s", format_text(line, len));
+				    value, format_text(line, len));
 			}
 		} else
 			hdr_item = NULL;
@@ -1847,16 +1867,6 @@
 		 */
 		switch (headers[hf_index].special) {
 
-		case HDR_AUTHORIZATION:
-			if (check_auth_ntlmssp(hdr_item, tvb, pinfo, value))
-				break;	/* dissected NTLMSSP */
-			check_auth_basic(hdr_item, tvb, value);
-			break;
-
-		case HDR_AUTHENTICATE:
-			check_auth_ntlmssp(hdr_item, tvb, pinfo, value);
-			break;
-
 		case HDR_CONTENT_TYPE:
 			eh_ptr->content_type = (gchar*) ep_memdup((guint8*)value,value_len + 1);
 
@@ -1917,6 +1927,11 @@
 			}
 			break;
 
+		case HDR_HOST:
+			stat_info->http_host = ep_strndup(value, value_len);
+			conv_data->http_host = se_strndup(value, value_len);
+			break;
+
 		case HDR_CONTENT_ENCODING:
 			eh_ptr->content_encoding = ep_strndup(value, value_len);
 			break;
@@ -1925,9 +1940,14 @@
 			eh_ptr->transfer_encoding = ep_strndup(value, value_len);
 			break;
 
-		case HDR_HOST:
-			stat_info->http_host = ep_strndup(value, value_len);
-			conv_data->http_host = se_strndup(value, value_len);
+		case HDR_AUTHORIZATION:
+			if (check_auth_ntlmssp(hdr_item, tvb, pinfo, value))
+				break;	/* dissected NTLMSSP */
+			check_auth_basic(hdr_item, tvb, value);
+			break;
+
+		case HDR_AUTHENTICATE:
+			check_auth_ntlmssp(hdr_item, tvb, pinfo, value);
 			break;
 
 		}
@@ -1936,14 +1956,13 @@
 
 /* Returns index of header tag in headers */
 static gint
-find_header_hf_value(tvbuff_t *tvb, int offset, guint header_len)
+find_header_hf_value(const guchar *line, const guint header_len)
 {
         guint i;
-
+		
         for (i = 0; i < array_length(headers); i++) {
-                if (header_len == strlen(headers[i].name) &&
-                    tvb_strncaseeql(tvb, offset,
-						headers[i].name, header_len) == 0)
+                if ((header_len) == (headers[i].namelen - 1) &&
+                    strncmp(line, headers[i].name, header_len) == 0)
                         return i;
         }
 
@@ -2379,7 +2398,7 @@
 			if (len == -1)
 				break;
 			proto_tree_add_text(subtree, tvb, offset, next_offset - offset,
-					"%s", tvb_format_text(tvb, offset, len));
+					tvb_format_text(tvb, offset, len));
 			offset = next_offset;
 		}
 	}
