Hi All.

Here attached you may find a new set of patches related to WURFL module
that should address Christopher and Willy suggestion.

Thank you in advance for a feedback

Regards
-Massimiliano


-- 
Massimiliano Bellomi
Senior Software Engineer
Scientiamobile Italy -  [email protected] +39 338 6990288
Milano Office : +39 02 620227260
skype: massimiliano.bellomi
From cb913efa7c2fb5ebea8bea480dc7f9449b520a82 Mon Sep 17 00:00:00 2001
From: mbellomi <[email protected]>
Date: Tue, 21 May 2019 15:51:46 +0200
Subject: [PATCH 3/8] MINOR WURFL fixed Engine load failed error when
 wurfl-information-list contains wurfl_root_id

---
 src/wurfl.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/wurfl.c b/src/wurfl.c
index 7167a929..d5c85add 100644
--- a/src/wurfl.c
+++ b/src/wurfl.c
@@ -102,9 +102,9 @@ static const struct {
 	{"wurfl_isdevroot", ha_wurfl_get_wurfl_isdevroot},
 	{"wurfl_last_load_time", ha_wurfl_get_wurfl_last_load_time},
 	{"wurfl_normalized_useragent", ha_wurfl_get_wurfl_normalized_useragent},
+	{"wurfl_root_id", ha_wurfl_get_wurfl_root_id},
 	{"wurfl_useragent", ha_wurfl_get_wurfl_useragent},
 	{"wurfl_useragent_priority", ha_wurfl_get_wurfl_useragent_priority }, // kept for backward conf file compat
-	{"wurfl_root_id", ha_wurfl_get_wurfl_root_id},
 };
 static const int HA_WURFL_PROPERTIES_NBR = 10;

@@ -602,7 +602,10 @@ INITCALL1(STG_REGISTER, sample_register_convs, &conv_kws);
 // WURFL properties wrapper functions
 static const char *ha_wurfl_get_wurfl_root_id (wurfl_handle wHandle, wurfl_device_handle dHandle)
 {
-	return wurfl_device_get_root_id(dHandle);
+	if (wurfl_device_get_root_id(dHandle))
+		return wurfl_device_get_root_id(dHandle);
+	else
+		return "";
 }

 static const char *ha_wurfl_get_wurfl_id (wurfl_handle wHandle, wurfl_device_handle dHandle)
--
2.17.1
From ed250908acdaf37133f429dd9b38534788ada079 Mon Sep 17 00:00:00 2001
From: mbellomi <[email protected]>
Date: Tue, 21 May 2019 16:11:42 +0200
Subject: [PATCH 4/8] MINOR WURFL shows log messages during module
 initialization. Now some useful startup information is logged to stderr

---
 src/wurfl.c | 42 +++++++++++++++++++-----------------------
 1 file changed, 19 insertions(+), 23 deletions(-)

diff --git a/src/wurfl.c b/src/wurfl.c
index d5c85add..0d03efa6 100644
--- a/src/wurfl.c
+++ b/src/wurfl.c
@@ -258,39 +258,35 @@ static int ha_wurfl_init(void)
 	int wurfl_result_code = WURFL_OK;
 	int len;

-	send_log(NULL, LOG_NOTICE, "WURFL: Loading module v.%s\n", HA_WURFL_MODULE_VERSION);
+	ha_notice("WURFL: Loading module v.%s\n", HA_WURFL_MODULE_VERSION);
 	// creating WURFL handler
 	global_wurfl.handle = wurfl_create();

 	if (global_wurfl.handle == NULL) {
-		ha_warning("WURFL: Engine handler creation failed");
-		send_log(NULL, LOG_WARNING, "WURFL: Engine handler creation failed\n");
+		ha_warning("WURFL: Engine handler creation failed\n");
 		return ERR_WARN;
 	}

-	send_log(NULL, LOG_NOTICE, "WURFL: Engine handler created - API version %s\n", wurfl_get_api_version() );
+	ha_notice("WURFL: Engine handler created - API version %s\n", wurfl_get_api_version() );

 	// set wurfl data file
 	if (global_wurfl.data_file == NULL) {
 		ha_warning("WURFL: missing wurfl-data-file parameter in global configuration\n");
-		send_log(NULL, LOG_WARNING, "WURFL: missing wurfl-data-file parameter in global configuration\n");
 		return ERR_WARN;
 	}

 	if (wurfl_set_root(global_wurfl.handle, global_wurfl.data_file) != WURFL_OK) {
 		ha_warning("WURFL: Engine setting root file failed - %s\n", wurfl_get_error_message(global_wurfl.handle));
-		send_log(NULL, LOG_WARNING, "WURFL: Engine setting root file failed - %s\n", wurfl_get_error_message(global_wurfl.handle));
 		return ERR_WARN;
 	}

-	send_log(NULL, LOG_NOTICE, "WURFL: Engine root file set to %s\n", global_wurfl.data_file);
+	ha_notice("WURFL: Engine root file set to %s\n", global_wurfl.data_file);
 	// just a log to inform which separator char has to be used
-	send_log(NULL, LOG_NOTICE, "WURFL: Information list separator set to '%c'\n", global_wurfl.information_list_separator);
+	ha_notice("WURFL: Information list separator set to '%c'\n", global_wurfl.information_list_separator);

 	// load wurfl data needed ( and filter whose are supposed to be capabilities )
 	if (LIST_ISEMPTY(&global_wurfl.information_list)) {
 		ha_warning("WURFL: missing wurfl-information-list parameter in global configuration\n");
-		send_log(NULL, LOG_WARNING, "WURFL: missing wurfl-information-list parameter in global configuration\n");
 		return ERR_WARN;
 	} else {
 		// ebtree initialization
@@ -302,21 +298,24 @@ static int ha_wurfl_init(void)
 			if (ebst_lookup(&global_wurfl.btree, wi->data.name) == NULL) {
 				if ((wi->data.func_callback = (PROP_CALLBACK_FUNC) ha_wurfl_get_property_callback(wi->data.name)) != NULL) {
 					wi->data.type = HA_WURFL_DATA_TYPE_PROPERTY;
-					ha_wurfl_log("WURFL: [%s] is a valid wurfl data [property]\n",wi->data.name);
+#ifdef WURFL_DEBUG
+					ha_notice("WURFL: [%s] is a valid wurfl data [property]\n",wi->data.name);
+#endif
 				} else if (wurfl_has_virtual_capability(global_wurfl.handle, wi->data.name)) {
 					wi->data.type = HA_WURFL_DATA_TYPE_VCAP;
-					ha_wurfl_log("WURFL: [%s] is a valid wurfl data [virtual capability]\n",wi->data.name);
+#ifdef WURFL_DEBUG
+					ha_notice("WURFL: [%s] is a valid wurfl data [virtual capability]\n",wi->data.name);
+#endif
 				} else {
 					// by default a cap type is assumed to be and we control it on engine load
 					wi->data.type = HA_WURFL_DATA_TYPE_CAP;

 					if (wurfl_add_requested_capability(global_wurfl.handle, wi->data.name) != WURFL_OK) {
 						ha_warning("WURFL: capability filtering failed - %s\n", wurfl_get_error_message(global_wurfl.handle));
-						send_log(NULL, LOG_WARNING, "WURFL: capability filtering failed - %s\n", wurfl_get_error_message(global_wurfl.handle));
 						return ERR_WARN;
 					}

-					ha_wurfl_log("WURFL: [%s] treated as wurfl capability. Will check its validity later, on engine load\n",wi->data.name);
+					ha_notice("WURFL: [%s] treated as wurfl capability. Will check its validity later, on engine load\n",wi->data.name);
 				}

 				// ebtree insert here
@@ -326,7 +325,6 @@ static int ha_wurfl_init(void)

 				if (wn == NULL) {
 					ha_warning("WURFL: Error allocating memory for information tree element.\n");
-					send_log(NULL, LOG_WARNING, "WURFL: Error allocating memory for information tree element.\n");
 					return ERR_WARN;
 				}

@@ -338,12 +336,13 @@ static int ha_wurfl_init(void)

 				if (!ebst_insert(&global_wurfl.btree, &wn->nd)) {
 					ha_warning("WURFL: [%s] not inserted in btree\n",wn->name);
-					send_log(NULL, LOG_WARNING, "WURFL: [%s] not inserted in btree\n",wn->name);
 					return ERR_WARN;
 				}

 			} else {
-				ha_wurfl_log("WURFL: [%s] already loaded\n",wi->data.name);
+#ifdef WURFL_DEBUG
+				ha_notice("WURFL: [%s] already loaded\n",wi->data.name);
+#endif
 			}

 		}
@@ -357,10 +356,9 @@ static int ha_wurfl_init(void)
 		list_for_each_entry(wp, &global_wurfl.patch_file_list, list) {
 			if (wurfl_add_patch(global_wurfl.handle, wp->patch_file_path) != WURFL_OK) {
 				ha_warning("WURFL: Engine adding patch file failed - %s\n", wurfl_get_error_message(global_wurfl.handle));
-				send_log(NULL, LOG_WARNING, "WURFL: Adding engine patch file failed - %s\n", wurfl_get_error_message(global_wurfl.handle));
 				return ERR_WARN;
 			}
-			send_log(NULL, LOG_NOTICE, "WURFL: Engine patch file added %s\n", wp->patch_file_path);
+			ha_notice("WURFL: Engine patch file added %s\n", wp->patch_file_path);

 		}

@@ -381,22 +379,20 @@ static int ha_wurfl_init(void)

 		if (wurfl_result_code != WURFL_OK) {
 			ha_warning("WURFL: Setting cache to [%s] failed - %s\n", global_wurfl.cache_size, wurfl_get_error_message(global_wurfl.handle));
-			send_log(NULL, LOG_WARNING, "WURFL: Setting cache to [%s] failed - %s\n", global_wurfl.cache_size, wurfl_get_error_message(global_wurfl.handle));
 			return ERR_WARN;
 		}

-		send_log(NULL, LOG_NOTICE, "WURFL: Cache set to [%s]\n", global_wurfl.cache_size);
+		ha_notice("WURFL: Cache set to [%s]\n", global_wurfl.cache_size);
 	}

 	// loading WURFL engine
 	if (wurfl_load(global_wurfl.handle) != WURFL_OK) {
 		ha_warning("WURFL: Engine load failed - %s\n", wurfl_get_error_message(global_wurfl.handle));
-		send_log(NULL, LOG_WARNING, "WURFL: Engine load failed - %s\n", wurfl_get_error_message(global_wurfl.handle));
 		return ERR_WARN;
 	}

-	send_log(NULL, LOG_NOTICE, "WURFL: Engine loaded\n");
-	send_log(NULL, LOG_NOTICE, "WURFL: Module load completed\n");
+	ha_notice("WURFL: Engine loaded\n");
+	ha_notice("WURFL: Module load completed\n");
 	return 0;
 }

--
2.17.1
From 3d937ba8528c7c8a02e506a0ee4463f369452cad Mon Sep 17 00:00:00 2001
From: mbellomi <[email protected]>
Date: Tue, 21 May 2019 15:32:48 +0200
Subject: [PATCH 1/8] BUG/MEDIUM WURFL fixed segfault when a wurfl information
 not present in wurfl-information-list is referenced in wurfl-get() method

---
 src/wurfl.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/wurfl.c b/src/wurfl.c
index 325cba64..7167a929 100644
--- a/src/wurfl.c
+++ b/src/wurfl.c
@@ -514,9 +514,10 @@ static int ha_wurfl_get(const struct arg *args, struct sample *smp, const char *
 	while (args[i].data.str.area) {
 		chunk_appendf(temp, "%c", global_wurfl.information_list_separator);
 		node = ebst_lookup(&global_wurfl.btree, args[i].data.str.area);
-		wn = container_of(node, wurfl_data_t, nd);

-		if (wn) {
+		if (node) {
+
+			wn = container_of(node, wurfl_data_t, nd);

 			switch(wn->type) {
 			case HA_WURFL_DATA_TYPE_UNKNOWN :
--
2.17.1
From 5d06dbc78945a072fceef4c9bd52898f5b0b8003 Mon Sep 17 00:00:00 2001
From: mbellomi <[email protected]>
Date: Tue, 21 May 2019 15:44:53 +0200
Subject: [PATCH 2/8] MINOR WURFL calls header_retrieve_callback from within
 wurfl dummy library. With this patch, module's code coverage is extended to
 ha_wurfl_retrieve_header() too

---
 contrib/wurfl/dummy-wurfl.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/contrib/wurfl/dummy-wurfl.c b/contrib/wurfl/dummy-wurfl.c
index c87d9b95..8c7909d1 100644
--- a/contrib/wurfl/dummy-wurfl.c
+++ b/contrib/wurfl/dummy-wurfl.c
@@ -67,6 +67,11 @@ wurfl_error wurfl_load(wurfl_handle hwurfl)

 wurfl_device_handle wurfl_lookup(wurfl_handle hwurfl, wurfl_header_retrieve_callback header_retrieve_callback, const void *header_retrieve_callback_data)
 {
+  // call callback, on a probably existing header
+  const char *hvalue = header_retrieve_callback("User-Agent", header_retrieve_callback_data);
+  // and on a non existing one
+  hvalue = header_retrieve_callback("Non-Existing-Header", header_retrieve_callback_data);
+
   return (void *) 0xdeffa;
 }

--
2.17.1
From 4585f2a1823d900a4e94877062f347c22c84f138 Mon Sep 17 00:00:00 2001
From: mbellomi <[email protected]>
Date: Tue, 21 May 2019 16:29:22 +0200
Subject: [PATCH 5/8] MINOR WURFL removes heading wurfl-information-separator
 from wurfl-get-all() and wurfl-get() results

---
 src/wurfl.c | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/src/wurfl.c b/src/wurfl.c
index 0d03efa6..dc159704 100644
--- a/src/wurfl.c
+++ b/src/wurfl.c
@@ -442,7 +442,6 @@ static int ha_wurfl_get_all(const struct arg *args, struct sample *smp, const ch
 	chunk_reset(temp);

 	list_for_each_entry(wi, &global_wurfl.information_list, list) {
-		chunk_appendf(temp, "%c", global_wurfl.information_list_separator);

 		switch(wi->data.type) {
 		case HA_WURFL_DATA_TYPE_UNKNOWN :
@@ -478,11 +477,20 @@ static int ha_wurfl_get_all(const struct arg *args, struct sample *smp, const ch
 			break;
 		}

+		// append wurfl-information-list-separator
+		chunk_appendf(temp, "%c", global_wurfl.information_list_separator);
 	}

 	wurfl_device_destroy(dHandle);
 	smp->data.u.str.area = temp->area;
 	smp->data.u.str.data = temp->data;
+
+	// remove trailing wurfl-information-list-separator
+	if (temp->data) {
+		temp->area[temp->data] = '\0';
+		--smp->data.u.str.data;
+	}
+
 	return 1;
 }

@@ -508,7 +516,6 @@ static int ha_wurfl_get(const struct arg *args, struct sample *smp, const char *
 	chunk_reset(temp);

 	while (args[i].data.str.area) {
-		chunk_appendf(temp, "%c", global_wurfl.information_list_separator);
 		node = ebst_lookup(&global_wurfl.btree, args[i].data.str.area);

 		if (node) {
@@ -549,6 +556,9 @@ static int ha_wurfl_get(const struct arg *args, struct sample *smp, const char *
 				break;
 			}

+			// append wurfl-information-list-separator
+			chunk_appendf(temp, "%c", global_wurfl.information_list_separator);
+
 		} else {
 			ha_wurfl_log("WURFL: %s not in wurfl-information-list \n",
 				     args[i].data.str.area);
@@ -560,6 +570,13 @@ static int ha_wurfl_get(const struct arg *args, struct sample *smp, const char *
 	wurfl_device_destroy(dHandle);
 	smp->data.u.str.area = temp->area;
 	smp->data.u.str.data = temp->data;
+
+	// remove trailing wurfl-information-list-separator
+	if (temp->data) {
+		temp->area[temp->data] = '\0';
+		--smp->data.u.str.data;
+	}
+
 	return 1;
 }

--
2.17.1
From a50b9f4cdb1949fe482f904c63d0dc86de128934 Mon Sep 17 00:00:00 2001
From: mbellomi <[email protected]>
Date: Tue, 21 May 2019 16:41:24 +0200
Subject: [PATCH 6/8] MINOR WURFL wurfl_get() and wurfl_get_all() now return an
 empty string if device detection fails

---
 src/wurfl.c | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/src/wurfl.c b/src/wurfl.c
index dc159704..ae3d2fc0 100644
--- a/src/wurfl.c
+++ b/src/wurfl.c
@@ -433,14 +433,14 @@ static int ha_wurfl_get_all(const struct arg *args, struct sample *smp, const ch
 	wh.wsmp = smp;
 	dHandle = wurfl_lookup(global_wurfl.handle, &ha_wurfl_retrieve_header, &wh);

+	temp = get_trash_chunk();
+	chunk_reset(temp);
+
 	if (!dHandle) {
 		ha_wurfl_log("WURFL: unable to retrieve device from request %s\n", wurfl_get_error_message(global_wurfl.handle));
-		return 1;
+		goto wurfl_get_all_completed;
 	}

-	temp = get_trash_chunk();
-	chunk_reset(temp);
-
 	list_for_each_entry(wi, &global_wurfl.information_list, list) {

 		switch(wi->data.type) {
@@ -481,6 +481,8 @@ static int ha_wurfl_get_all(const struct arg *args, struct sample *smp, const ch
 		chunk_appendf(temp, "%c", global_wurfl.information_list_separator);
 	}

+wurfl_get_all_completed:
+
 	wurfl_device_destroy(dHandle);
 	smp->data.u.str.area = temp->area;
 	smp->data.u.str.data = temp->data;
@@ -507,14 +509,14 @@ static int ha_wurfl_get(const struct arg *args, struct sample *smp, const char *
 	wh.wsmp = smp;
 	dHandle = wurfl_lookup(global_wurfl.handle, &ha_wurfl_retrieve_header, &wh);

+	temp = get_trash_chunk();
+	chunk_reset(temp);
+
 	if (!dHandle) {
 		ha_wurfl_log("WURFL: unable to retrieve device from request %s\n", wurfl_get_error_message(global_wurfl.handle));
-		return 1;
+		goto wurfl_get_completed;
 	}

-	temp = get_trash_chunk();
-	chunk_reset(temp);
-
 	while (args[i].data.str.area) {
 		node = ebst_lookup(&global_wurfl.btree, args[i].data.str.area);

@@ -567,10 +569,12 @@ static int ha_wurfl_get(const struct arg *args, struct sample *smp, const char *
 		i++;
 	}

+wurfl_get_completed:
+
 	wurfl_device_destroy(dHandle);
 	smp->data.u.str.area = temp->area;
 	smp->data.u.str.data = temp->data;
-
+
 	// remove trailing wurfl-information-list-separator
 	if (temp->data) {
 		temp->area[temp->data] = '\0';
--
2.17.1
From ddf796b3d62fce7cd66ee7d3398ac33602fad6cf Mon Sep 17 00:00:00 2001
From: mbellomi <[email protected]>
Date: Tue, 21 May 2019 17:15:59 +0200
Subject: [PATCH 8/8] MINOR WURFL module version bump

---
 src/wurfl.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/wurfl.c b/src/wurfl.c
index d1876014..5d720af6 100644
--- a/src/wurfl.c
+++ b/src/wurfl.c
@@ -70,7 +70,7 @@ typedef struct {
 	struct ebmb_node nd;
 } wurfl_data_t;

-static const char HA_WURFL_MODULE_VERSION[] = "1.0";
+static const char HA_WURFL_MODULE_VERSION[] = "2.0";
 static const char HA_WURFL_ISDEVROOT_FALSE[] = "FALSE";
 static const char HA_WURFL_ISDEVROOT_TRUE[] = "TRUE";

--
2.17.1
From 27074e6c827605a79dd271b813b162dfbc088e0f Mon Sep 17 00:00:00 2001
From: mbellomi <[email protected]>
Date: Tue, 21 May 2019 17:15:07 +0200
Subject: [PATCH 7/8] MEDIUM WURFL HTX awareness. Now wurfl fetch process is
 fully  HTX aware

---
 src/wurfl.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 107 insertions(+), 12 deletions(-)

diff --git a/src/wurfl.c b/src/wurfl.c
index ae3d2fc0..d1876014 100644
--- a/src/wurfl.c
+++ b/src/wurfl.c
@@ -10,6 +10,8 @@
 #include <proto/arg.h>
 #include <proto/log.h>
 #include <proto/proto_http.h>
+#include <proto/http_fetch.h>
+#include <proto/http_htx.h>
 #include <proto/sample.h>
 #include <ebsttree.h>
 #include <ebmbtree.h>
@@ -428,9 +430,27 @@ static int ha_wurfl_get_all(const struct arg *args, struct sample *smp, const ch
 	struct buffer *temp;
 	wurfl_information_t *wi;
 	ha_wurfl_header_t wh;
+	struct channel *chn;

 	ha_wurfl_log("WURFL: starting ha_wurfl_get_all\n");
+
+	chn = (smp->strm ? &smp->strm->req : NULL);
+
+	if (smp->px->options2 & PR_O2_USE_HTX) {
+		/* HTX version */
+		struct htx *htx = smp_prefetch_htx(smp, chn, 1);
+
+		if (!htx) {
+			return 0;
+		}
+
+	} else {
+		/* Legacy version */
+		CHECK_HTTP_MESSAGE_FIRST(chn);
+	}
+
 	wh.wsmp = smp;
+
 	dHandle = wurfl_lookup(global_wurfl.handle, &ha_wurfl_retrieve_header, &wh);

 	temp = get_trash_chunk();
@@ -493,6 +513,7 @@ wurfl_get_all_completed:
 		--smp->data.u.str.data;
 	}

+	smp->data.type = SMP_T_STR;
 	return 1;
 }

@@ -504,9 +525,27 @@ static int ha_wurfl_get(const struct arg *args, struct sample *smp, const char *
 	struct ebmb_node *node;
 	ha_wurfl_header_t wh;
 	int i = 0;
+	struct channel *chn;

 	ha_wurfl_log("WURFL: starting ha_wurfl_get\n");
+
+	chn = (smp->strm ? &smp->strm->req : NULL);
+
+	if (smp->px->options2 & PR_O2_USE_HTX) {
+		/* HTX version */
+		struct htx *htx = smp_prefetch_htx(smp, chn, 1);
+
+		if (!htx) {
+			return 0;
+		}
+
+	} else {
+		/* Legacy version */
+		CHECK_HTTP_MESSAGE_FIRST(chn);
+	}
+
 	wh.wsmp = smp;
+
 	dHandle = wurfl_lookup(global_wurfl.handle, &ha_wurfl_retrieve_header, &wh);

 	temp = get_trash_chunk();
@@ -581,6 +620,7 @@ wurfl_get_completed:
 		--smp->data.u.str.data;
 	}

+	smp->data.type = SMP_T_STR;
 	return 1;
 }

@@ -700,25 +740,80 @@ static const char *(*ha_wurfl_get_property_callback(char *name)) (wurfl_handle w
 static const char *ha_wurfl_retrieve_header(const char *header_name, const void *wh)
 {
 	struct sample *smp;
-	struct hdr_idx *idx;
-	struct hdr_ctx ctx;
-	const struct http_msg *msg;
+	struct channel *chn;
 	int header_len = HA_WURFL_MAX_HEADER_LENGTH;

-	ha_wurfl_log("WURFL: retrieve header request [%s]\n", header_name);
 	smp =  ((ha_wurfl_header_t *)wh)->wsmp;
-	idx = &smp->strm->txn->hdr_idx;
-	msg = &smp->strm->txn->req;
-	ctx.idx = 0;
+	chn = (smp->strm ? &smp->strm->req : NULL);
+
+	if (smp->px->options2 & PR_O2_USE_HTX) {
+		/* HTX version */
+		struct htx *htx;
+		struct http_hdr_ctx ctx;
+		struct ist name;

-	if (http_find_full_header2(header_name, strlen(header_name), ci_head(msg->chn), idx, &ctx) == 0)
-		return 0;
+		ha_wurfl_log("WURFL: retrieve header (HTX) request [%s]\n", header_name);

-	if (header_len > ctx.vlen)
-		header_len = ctx.vlen;
+		//the header is searched from the beginning
+		ctx.blk = NULL;
+
+		// We could skip this chek since ha_wurfl_retrieve_header is called from inside
+		// ha_wurfl_get()/ha_wurfl_get_all() that already perform the same check
+		// We choose to keep it in case ha_wurfl_retrieve_header will be called directly
+		htx = smp_prefetch_htx(smp, chn, 1);
+		if (!htx) {
+			return NULL;
+		}
+
+		name.ptr = (char *)header_name;
+		name.len = strlen(header_name);
+
+		// If 4th param is set, it works on full-line headers in whose comma is not a delimiter but is
+		// part of the syntax
+		if (!http_find_header(htx, name, &ctx, 1)) {
+			return NULL;
+		}
+
+		if (header_len > ctx.value.len)
+			header_len = ctx.value.len;
+
+		strncpy(((ha_wurfl_header_t *)wh)->header_value, ctx.value.ptr, header_len);
+
+	} else {
+		/* Legacy version */
+		struct http_txn *txn;
+		struct hdr_idx *idx;
+		struct hdr_ctx ctx;
+		int res;
+
+		ha_wurfl_log("WURFL: retrieve header (legacy) request [%s]\n", header_name);
+
+		// We could skip this chek since ha_wurfl_retrieve_header is called from inside
+		// ha_wurfl_get()/ha_wurfl_get_all() that already perform the same check
+		// We choose to keep it in case ha_wurfl_retrieve_header will be called directly
+		// This is a version of CHECK_HTTP_MESSAGE_FIRST(chn) which returns NULL in case of error
+		res = smp_prefetch_http(smp->px, smp->strm, smp->opt, (chn), smp, 1);
+		if (res <= 0) {
+			return NULL;
+		}
+
+		txn = smp->strm->txn;
+		idx = &txn->hdr_idx;
+
+		ctx.idx = 0;
+
+		if (http_find_full_header2(header_name, strlen(header_name), ci_head(chn), idx, &ctx) == 0)
+			return NULL;
+
+		if (header_len > ctx.vlen)
+			header_len = ctx.vlen;
+
+		strncpy(((ha_wurfl_header_t *)wh)->header_value, ctx.line + ctx.val, header_len);
+
+	}

-	strncpy(((ha_wurfl_header_t *)wh)->header_value, ctx.line + ctx.val, header_len);
 	((ha_wurfl_header_t *)wh)->header_value[header_len] = '\0';
+
 	ha_wurfl_log("WURFL: retrieve header request returns [%s]\n", ((ha_wurfl_header_t *)wh)->header_value);
 	return ((ha_wurfl_header_t *)wh)->header_value;
 }
--
2.17.1

Reply via email to