MEDIUM: 51Degrees code refactoring and cleanup

Moved 51Degrees code from src/haproxy.c, src/sample.c and src/cfgparse.c
into a separate files src/51d.c and include/import/51d.h.

Added two new functions init_51degrees() and deinit_51degrees(), updated
Makefile and other code reorganizations related to 51Degrees.
This commit is contained in:
Dragan Dosen 2015-06-29 16:43:25 +02:00 committed by Willy Tarreau
parent e44136fe69
commit 93b38d9191
9 changed files with 309 additions and 271 deletions

View File

@ -39,7 +39,7 @@
# USE_NS : enable network namespace support. Supported on Linux >= 2.6.24.
# USE_DL : enable it if your system requires -ldl. Automatic on Linux.
# USE_DEVICEATLAS : enable DeviceAtlas api.
# USE_51DEGREES : enable third party device detection library from 51degrees
# USE_51DEGREES : enable third party device detection library from 51Degrees
#
# Options can be forced by specifying "USE_xxx=1" or can be disabled by using
# "USE_xxx=" (empty string).
@ -604,7 +604,7 @@ endif
ifneq ($(USE_DEVICEATLAS),)
# Use DEVICEATLAS_SRC and possibly DEVICEATLAS_INC and DEVICEATLAS_LIB to force path
# to 51degrees headers and libraries if needed.
# to DeviceAtlas headers and libraries if needed.
DEVICEATLAS_SRC =
DEVICEATLAS_INC = $(DEVICEATLAS_SRC)
DEVICEATLAS_LIB = $(DEVICEATLAS_SRC)
@ -621,6 +621,8 @@ ifneq ($(USE_51DEGREES),)
51DEGREES_SRC =
51DEGREES_INC = $(51DEGREES_SRC)
51DEGREES_LIB = $(51DEGREES_SRC)
OPTIONS_OBJS += $(51DEGREES_LIB)/51Degrees.o
OPTIONS_OBJS += src/51d.o
OPTIONS_CFLAGS += -DUSE_51DEGREES $(if $(51DEGREES_INC),-I$(51DEGREES_INC))
BUILD_OPTIONS += $(call ignore_implicit,USE_51DEGREES)
OPTIONS_LDFLAGS += $(if $(51DEGREES_LIB),-L$(51DEGREES_LIB)) -lz
@ -744,10 +746,6 @@ ifneq ($(TRACE),)
OBJS += src/trace.o
endif
ifneq ($(USE_51DEGREES),)
OBJS += $(51DEGREES_SRC)/51Degrees.o
endif
WRAPPER_OBJS = src/haproxy-systemd-wrapper.o
# Not used right now

6
README
View File

@ -282,13 +282,13 @@ The configuration file needs to set the following parameters:
51degrees-data-file path to the pattern or trie data file
51degrees-property-name-list list of 51Degrees properties to detect
51degrees-property-seperator seperator to use between values
51degrees-property-separator separator to use between values
The following is an example of the settings for Pattern.
51degrees-data-file '51D_REPO_PATH'/data/51Degrees-Lite.dat
51degrees-property-name-list IsTablet DeviceType IsMobile
51degrees-property-seperator ,
51degrees-property-separator ,
HAProxy needs a way to pass device information to the backend servers. This is
done by using the 51d converter, which intercepts the User-Agent header and
@ -307,7 +307,7 @@ and X-51D-Tablet. Any number of headers can be created this way and can be
named anything. The User-Agent header is passed to the converter in
req.fhdr(User-Agent). 51d( ) invokes the 51degrees converter. It can be passed
up to five property names of values to return. Values will be returned in the
same order, seperated by the 51-degrees-property-seperator configured earlier.
same order, seperated by the 51-degrees-property-separator configured earlier.
If a property name can't be found the value 'NoData' is returned instead.
The free Lite data file contains information about screen size in pixels and

View File

@ -542,7 +542,7 @@ The following keywords are supported in the "global" section :
- unix-bind
- 51degrees-data-file
- 51degrees-property-name-list
- 51degrees-property-seperator
- 51degrees-property-separator
* Performance tuning
- max-spread-checks
@ -886,7 +886,7 @@ description <text>
Please note that this options is only available when haproxy has been
compiled with USE_51DEGREES.
51degrees-property-seperator <char>
51degrees-property-separator <char>
A char that will be appended to every property value in a response header
containing 51Degrees results. If not set that will be set as ','.

9
include/import/51d.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef _IMPORT_51D_H
#define _IMPORT_51D_H
#include <51Degrees.h>
int init_51degrees(void);
void deinit_51degrees(void);
#endif

View File

@ -33,7 +33,7 @@
#include <types/task.h>
#ifdef USE_51DEGREES
#include <51Degrees.h>
#include <import/51d.h>
#endif
#ifndef UNIX_MAX_PATH
@ -185,25 +185,18 @@ struct global {
char separator;
} deviceatlas;
#endif
#ifdef USE_51DEGREES
char _51d_property_seperator; /* the seperator to use in the response for the values. this is taken from 51degrees-property-seperator from config. */
struct list _51d_property_names; /* list of properties to load into the data set. this is taken from 51degrees-property-name-list from config. */
char * _51d_data_file_path;
struct {
char property_separator; /* the separator to use in the response for the values. this is taken from 51degrees-property-separator from config. */
struct list property_names; /* list of properties to load into the data set. this is taken from 51degrees-property-name-list from config. */
char *data_file_path;
#ifdef FIFTYONEDEGREES_H_PATTERN_INCLUDED
fiftyoneDegreesDataSet _51d_data_set; /* data set used with the pattern detection method. */
fiftyoneDegreesDataSet data_set; /* data set used with the pattern detection method. */
#endif
} _51degrees;
#endif
};
#ifdef USE_51DEGREES
struct _51d_property_names {
struct list list;
char *name;
};
#endif
extern struct global global;
extern int pid; /* current process id */
extern int relative_pid; /* process id starting at 1 */

271
src/51d.c Normal file
View File

@ -0,0 +1,271 @@
#include <stdio.h>
#include <common/cfgparse.h>
#include <common/chunk.h>
#include <proto/arg.h>
#include <proto/log.h>
#include <proto/sample.h>
#include <import/xxhash.h>
#include <import/51d.h>
struct _51d_property_names {
struct list list;
char *name;
};
static int _51d_data_file(char **args, int section_type, struct proxy *curpx,
struct proxy *defpx, const char *file, int line,
char **err)
{
if (*(args[1]) == 0) {
memprintf(err,
"'%s' expects a filepath to a 51Degrees trie or pattern data file.",
args[0]);
return -1;
}
if (global._51degrees.data_file_path)
free(global._51degrees.data_file_path);
global._51degrees.data_file_path = strdup(args[1]);
return 0;
}
static int _51d_property_name_list(char **args, int section_type, struct proxy *curpx,
struct proxy *defpx, const char *file, int line,
char **err)
{
int cur_arg = 1;
struct _51d_property_names *name;
if (*(args[cur_arg]) == 0) {
memprintf(err,
"'%s' expects at least one 51Degrees property name.",
args[0]);
return -1;
}
while (*(args[cur_arg])) {
name = calloc(1, sizeof(struct _51d_property_names));
name->name = strdup(args[cur_arg]);
LIST_ADDQ(&global._51degrees.property_names, &name->list);
++cur_arg;
}
return 0;
}
static int _51d_property_separator(char **args, int section_type, struct proxy *curpx,
struct proxy *defpx, const char *file, int line,
char **err)
{
if (*(args[1]) == 0) {
memprintf(err,
"'%s' expects a single character.",
args[0]);
return -1;
}
if (strlen(args[1]) > 1) {
memprintf(err,
"'%s' expects a single character, got '%s'.",
args[0], args[1]);
return -1;
}
global._51degrees.property_separator = *args[1];
return 0;
}
static int _51d_conv(const struct arg *args, struct sample *smp, void *private)
{
int i;
char no_data[] = "NoData"; /* response when no data could be found */
struct chunk *temp;
#ifdef FIFTYONEDEGREES_H_PATTERN_INCLUDED
int j, found;
const char* property_name;
fiftyoneDegreesWorkset* ws; /* workset for detection */
#endif
#ifdef FIFTYONEDEGREES_H_TRIE_INCLUDED
int device_offset;
int property_index;
#endif
#ifdef FIFTYONEDEGREES_H_PATTERN_INCLUDED
/* Create workset. This will later contain detection results. */
ws = fiftyoneDegreesCreateWorkset(&global._51degrees.data_set);
if (!ws)
return 0;
#endif
smp->data.str.str[smp->data.str.len] = '\0';
/* Perform detection. */
#ifdef FIFTYONEDEGREES_H_PATTERN_INCLUDED
fiftyoneDegreesMatch(ws, smp->data.str.str);
#endif
#ifdef FIFTYONEDEGREES_H_TRIE_INCLUDED
device_offset = fiftyoneDegreesGetDeviceOffset(smp->data.str.str);
#endif
i = 0;
temp = get_trash_chunk();
chunk_reset(temp);
/* Loop through property names passed to the filter and fetch them from the dataset. */
while (args[i].data.str.str) {
/* Try to find request property in dataset. */
#ifdef FIFTYONEDEGREES_H_PATTERN_INCLUDED
found = 0;
for (j = 0; j < ws->dataSet->requiredPropertyCount; j++) {
property_name = fiftyoneDegreesGetPropertyName(ws->dataSet, ws->dataSet->requiredProperties[j]);
if (strcmp(property_name, args[i].data.str.str) == 0) {
found = 1;
fiftyoneDegreesSetValues(ws, j);
chunk_appendf(temp, "%s", fiftyoneDegreesGetValueName(ws->dataSet, *ws->values));
break;
}
}
if (!found) {
chunk_appendf(temp, "%s", no_data);
}
#endif
#ifdef FIFTYONEDEGREES_H_TRIE_INCLUDED
property_index = fiftyoneDegreesGetPropertyIndex(args[i].data.str.str);
if (property_index > 0) {
chunk_appendf(temp, "%s", fiftyoneDegreesGetValue(device_offset, property_index));
}
else {
chunk_appendf(temp, "%s", no_data);
}
#endif
/* Add separator. */
chunk_appendf(temp, "%c", global._51degrees.property_separator);
++i;
}
if (temp->len) {
--temp->len;
temp->str[temp->len] = '\0';
}
smp->data.str.str = temp->str;
smp->data.str.len = strlen(smp->data.str.str);
#ifdef FIFTYONEDEGREES_H_PATTERN_INCLUDED
fiftyoneDegreesFreeWorkset(ws);
#endif
return 1;
}
int init_51degrees(void)
{
int i = 0;
struct chunk *temp;
struct _51d_property_names *name;
char **_51d_property_list = NULL;
fiftyoneDegreesDataSetInitStatus _51d_dataset_status = DATA_SET_INIT_STATUS_NOT_SET;
if (!LIST_ISEMPTY(&global._51degrees.property_names)) {
i = 0;
list_for_each_entry(name, &global._51degrees.property_names, list)
++i;
_51d_property_list = calloc(i, sizeof(char *));
i = 0;
list_for_each_entry(name, &global._51degrees.property_names, list)
_51d_property_list[i++] = name->name;
}
#ifdef FIFTYONEDEGREES_H_PATTERN_INCLUDED
_51d_dataset_status = fiftyoneDegreesInitWithPropertyArray(global._51degrees.data_file_path, &global._51degrees.data_set, _51d_property_list, i);
#endif
#ifdef FIFTYONEDEGREES_H_TRIE_INCLUDED
_51d_dataset_status = fiftyoneDegreesInitWithPropertyArray(global._51degrees.data_file_path, _51d_property_list, i);
#endif
temp = get_trash_chunk();
chunk_reset(temp);
switch (_51d_dataset_status) {
case DATA_SET_INIT_STATUS_SUCCESS:
break;
case DATA_SET_INIT_STATUS_INSUFFICIENT_MEMORY:
chunk_printf(temp, "Insufficient memory.");
break;
case DATA_SET_INIT_STATUS_CORRUPT_DATA:
#ifdef FIFTYONEDEGREES_H_PATTERN_INCLUDED
chunk_printf(temp, "Corrupt data file. Check that the data file provided is uncompressed and Pattern data format.");
#endif
#ifdef FIFTYONEDEGREES_H_TRIE_INCLUDED
chunk_printf(temp, "Corrupt data file. Check that the data file provided is uncompressed and Trie data format.");
#endif
break;
case DATA_SET_INIT_STATUS_INCORRECT_VERSION:
#ifdef FIFTYONEDEGREES_H_PATTERN_INCLUDED
chunk_printf(temp, "Incorrect version. Check that the data file provided is uncompressed and Pattern data format.");
#endif
#ifdef FIFTYONEDEGREES_H_TRIE_INCLUDED
chunk_printf(temp, "Incorrect version. Check that the data file provided is uncompressed and Trie data format.");
#endif
break;
case DATA_SET_INIT_STATUS_FILE_NOT_FOUND:
chunk_printf(temp, "File not found.");
break;
case DATA_SET_INIT_STATUS_NOT_SET:
chunk_printf(temp, "Data set not initialised.");
break;
}
if (_51d_dataset_status != DATA_SET_INIT_STATUS_SUCCESS) {
if (temp->len)
Alert("51Degrees Setup - Error reading 51Degrees data file. %s\n", temp->str);
else
Alert("51Degrees Setup - Error reading 51Degrees data file.\n");
exit(1);
}
free(_51d_property_list);
return 0;
}
void deinit_51degrees(void)
{
struct _51d_property_names *_51d_prop_name, *_51d_prop_nameb;
#ifdef FIFTYONEDEGREES_H_PATTERN_INCLUDED
fiftyoneDegreesDestroy(&global._51degrees.data_set);
#endif
#ifdef FIFTYONEDEGREES_H_TRIE_INCLUDED
fiftyoneDegreesDestroy();
#endif
free(global._51degrees.data_file_path); global._51degrees.data_file_path = NULL;
list_for_each_entry_safe(_51d_prop_name, _51d_prop_nameb, &global._51degrees.property_names, list) {
LIST_DEL(&_51d_prop_name->list);
free(_51d_prop_name);
}
}
static struct cfg_kw_list _51dcfg_kws = {{ }, {
{ CFG_GLOBAL, "51degrees-data-file", _51d_data_file },
{ CFG_GLOBAL, "51degrees-property-name-list", _51d_property_name_list },
{ CFG_GLOBAL, "51degrees-property-separator", _51d_property_separator },
{ 0, NULL, NULL },
}};
/* Note: must not be declared <const> as its list will be overwritten */
static struct sample_conv_kw_list conv_kws = {ILH, {
{ "51d", _51d_conv, ARG5(1,STR,STR,STR,STR,STR), NULL, SMP_T_STR, SMP_T_STR },
{ NULL, NULL, 0, 0, 0 },
}};
__attribute__((constructor))
static void __51d_init(void)
{
/* register sample fetch and format conversion keywords */
sample_register_convs(&conv_kws);
cfg_register_keywords(&_51dcfg_kws);
}

View File

@ -1766,48 +1766,6 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
goto out;
#endif
}
#ifdef USE_51DEGREES
else if (strcmp(args[0], "51degrees-data-file") == 0) {
if(!*(args[1])) {
Alert("parsing [%s:%d]: '%s' expects a filepath to a 51Degrees trie or pattern data file.\n", file, linenum, args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
global._51d_data_file_path = strdup(args[1]);
}
else if (strcmp(args[0], "51degrees-property-seperator") == 0) {
if(!*(args[1])) {
Alert("parsing [%s:%d]: '%s' expects a single character.\n", file, linenum, args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
if (strlen(args[1]) > 1) {
Alert("parsing [%s:%d]: '%s' expects a single character, got '%s'.\n", file, linenum, args[0], args[1]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
global._51d_property_seperator = *args[1];
}
else if (strcmp(args[0], "51degrees-property-name-list") == 0) {
int arg;
struct _51d_property_names *name;
arg = 1;
if (!*args[arg]) {
Alert("parsing [%s:%d]: '%s' expects at least one 51Degrees property name.\n", file, linenum, args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
LIST_INIT(&global._51d_property_names);
while (*args[arg]) {
name = calloc(1, sizeof(struct _51d_property_names));
name->name = strdup(args[arg]);
LIST_ADDQ(&global._51d_property_names, &name->list);
++arg;
}
}
#endif
else {
struct cfg_kw_list *kwl;
int index;

View File

@ -117,7 +117,7 @@
#endif
#ifdef USE_51DEGREES
#include <51Degrees.h>
#include <import/51d.h>
#endif
/*********************************************************************/
@ -189,7 +189,14 @@ struct global global = {
},
#endif
#ifdef USE_51DEGREES
._51d_property_names = LIST_HEAD_INIT(global._51d_property_names),
._51degrees = {
.property_separator = ',',
.property_names = LIST_HEAD_INIT(global._51degrees.property_names),
.data_file_path = NULL,
#ifdef FIFTYONEDEGREES_H_PATTERN_INCLUDED
.data_set = { },
#endif
},
#endif
/* others NULL OK */
};
@ -550,12 +557,6 @@ void init(int argc, char **argv)
char *progname;
char *change_dir = NULL;
struct tm curtime;
#ifdef USE_51DEGREES
int i = 0;
struct _51d_property_names *name;
char **_51d_property_list = NULL;
fiftyoneDegreesDataSetInitStatus _51d_dataset_status = DATA_SET_INIT_STATUS_NOT_SET;
#endif
chunk_init(&trash, malloc(global.tune.bufsize), global.tune.bufsize);
alloc_trash_buffers(global.tune.bufsize);
@ -819,6 +820,9 @@ void init(int argc, char **argv)
#if defined(USE_DEVICEATLAS)
init_deviceatlas();
#endif
#ifdef USE_51DEGREES
init_51degrees();
#endif
if (have_appsession)
appsession_init();
@ -1106,65 +1110,6 @@ void init(int argc, char **argv)
/* initialize structures for name resolution */
if (!dns_init_resolvers())
exit(1);
#ifdef USE_51DEGREES
if (!LIST_ISEMPTY(&global._51d_property_names)) {
i = 0;
list_for_each_entry(name, &global._51d_property_names, list)
++i;
_51d_property_list = calloc(i, sizeof(char *));
i = 0;
list_for_each_entry(name, &global._51d_property_names, list)
_51d_property_list[i++] = name->name;
}
#ifdef FIFTYONEDEGREES_H_TRIE_INCLUDED
_51d_dataset_status = fiftyoneDegreesInitWithPropertyArray(global._51d_data_file_path, _51d_property_list, i);
#endif
#ifdef FIFTYONEDEGREES_H_PATTERN_INCLUDED
_51d_dataset_status = fiftyoneDegreesInitWithPropertyArray(global._51d_data_file_path, &global._51d_data_set, _51d_property_list, i);
#endif
chunk_reset(&trash);
switch (_51d_dataset_status) {
case DATA_SET_INIT_STATUS_SUCCESS:
break;
case DATA_SET_INIT_STATUS_INSUFFICIENT_MEMORY:
chunk_printf(&trash, "Insufficient memory.");
break;
case DATA_SET_INIT_STATUS_CORRUPT_DATA:
#ifdef FIFTYONEDEGREES_H_TRIE_INCLUDED
chunk_printf(&trash, "Corrupt data file. Check that the data file provided is uncompressed and Trie data format.");
#endif
#ifdef FIFTYONEDEGREES_H_PATTERN_INCLUDED
chunk_printf(&trash, "Corrupt data file. Check that the data file provided is uncompressed and Pattern data format.");
#endif
break;
case DATA_SET_INIT_STATUS_INCORRECT_VERSION:
#ifdef FIFTYONEDEGREES_H_TRIE_INCLUDED
chunk_printf(&trash, "Incorrect version. Check that the data file provided is uncompressed and Trie data format.");
#endif
#ifdef FIFTYONEDEGREES_H_PATTERN_INCLUDED
chunk_printf(&trash, "Incorrect version. Check that the data file provided is uncompressed and Pattern data format.");
#endif
break;
case DATA_SET_INIT_STATUS_FILE_NOT_FOUND:
chunk_printf(&trash, "File not found.");
break;
case DATA_SET_INIT_STATUS_NOT_SET:
chunk_printf(&trash, "Data set not initialised.");
break;
}
if (_51d_dataset_status != DATA_SET_INIT_STATUS_SUCCESS) {
if (trash.len)
Alert("51Degrees Setup - Error reading 51Degrees data file. %s\n", trash.str);
else
Alert("51Degrees Setup - Error reading 51Degrees data file.\n");
exit(1);
}
free(_51d_property_list);
#endif // USE_51DEGREES
}
static void deinit_acl_cond(struct acl_cond *cond)
@ -1261,9 +1206,6 @@ void deinit(void)
struct logsrv *log, *logb;
struct logformat_node *lf, *lfb;
struct bind_conf *bind_conf, *bind_back;
#ifdef USE_51DEGREES
struct _51d_property_names *_51d_prop_name, *_51d_prop_nameb;
#endif
int i;
deinit_signals();
@ -1517,18 +1459,8 @@ void deinit(void)
#endif
#ifdef USE_51DEGREES
#ifdef FIFTYONEDEGREES_H_TRIE_INCLUDED
fiftyoneDegreesDestroy();
deinit_51degrees();
#endif
#ifdef FIFTYONEDEGREES_H_PATTERN_INCLUDED
fiftyoneDegreesDestroy(&global._51d_data_set);
#endif
free(global._51d_data_file_path); global._51d_data_file_path = NULL;
list_for_each_entry_safe(_51d_prop_name, _51d_prop_nameb, &global._51d_property_names, list) {
LIST_DEL(&_51d_prop_name->list);
free(_51d_prop_name);
}
#endif // USE_51DEGREES
free(global.log_send_hostname); global.log_send_hostname = NULL;
free(global.log_tag); global.log_tag = NULL;

View File

@ -32,10 +32,6 @@
#include <proto/sample.h>
#include <proto/stick_table.h>
#ifdef USE_51DEGREES
#include <51Degrees.h>
#endif
/* sample type names */
const char *smp_to_type[SMP_TYPES] = {
[SMP_T_ANY] = "any",
@ -2187,122 +2183,6 @@ static int sample_conv_arith_even(const struct arg *arg_p,
return 1;
}
#ifdef USE_51DEGREES
#ifdef FIFTYONEDEGREES_H_TRIE_INCLUDED
static int
sample_fiftyone_degrees(const struct arg *args, struct sample *smp, void *private)
{
int i; // used in loops.
int device_offset;
int property_index;
char no_data[] = "NoData"; // response when no data could be found.
struct chunk *tmp;
// use a temporary trash buffer and copy data in it
smp->data.str.str[smp->data.str.len] = '\0';
// perform detection.
device_offset = fiftyoneDegreesGetDeviceOffset(smp->data.str.str);
i = 0;
tmp = get_trash_chunk();
chunk_reset(tmp);
// loop through property names passed to the filter and fetch them from the dataset.
while (args[i].data.str.str) {
// try to find request property in dataset.
property_index = fiftyoneDegreesGetPropertyIndex(args[i].data.str.str);
if (property_index > 0) {
chunk_appendf(tmp, "%s", fiftyoneDegreesGetValue(device_offset, property_index));
}
else {
chunk_appendf(tmp, "%s", no_data);
}
// add seperator
if (global._51d_property_seperator)
chunk_appendf(tmp, "%c", global._51d_property_seperator);
else
chunk_appendf(tmp, ",");
++i;
}
if (tmp->len) {
--tmp->len;
tmp->str[tmp->len] = '\0';
}
smp->data.str.str = tmp->str;
smp->data.str.len = strlen(smp->data.str.str);
return 1;
}
#endif // FIFTYONEDEGREES_H_TRIE_INCLUDED
#ifdef FIFTYONEDEGREES_H_PATTERN_INCLUDED
static int
sample_fiftyone_degrees(const struct arg *args, struct sample *smp, void *private)
{
int i, j, found; // used in loops.
fiftyoneDegreesWorkset* ws; // workset for detection.
char no_data[] = "NoData"; // response when no data could be found.
const char* property_name;
struct chunk *tmp;
// use a temporary trash buffer and copy data in it
smp->data.str.str[smp->data.str.len] = '\0';
// create workset. this will later contain detection results.
ws = fiftyoneDegreesCreateWorkset(&global._51d_data_set);
if (!ws)
return 0;
// perform detection.
fiftyoneDegreesMatch(ws, smp->data.str.str);
i = 0;
tmp = get_trash_chunk();
chunk_reset(tmp);
// loop through property names passed to the filter and fetch them from the dataset.
while (args[i].data.str.str) {
found = j = 0;
// try to find request property in dataset.
for (j = 0; j < ws->dataSet->requiredPropertyCount; j++) {
property_name = fiftyoneDegreesGetPropertyName(ws->dataSet, ws->dataSet->requiredProperties[j]);
if (strcmp(property_name, args[i].data.str.str) == 0) {
found = 1;
fiftyoneDegreesSetValues(ws, j);
chunk_appendf(tmp, "%s", fiftyoneDegreesGetValueName(ws->dataSet, *ws->values));
break;
}
}
if (!found) {
chunk_appendf(tmp, "%s", no_data);
}
// add seperator
if (global._51d_property_seperator)
chunk_appendf(tmp, "%c", global._51d_property_seperator);
else
chunk_appendf(tmp, ",");
++i;
}
if (tmp->len) {
--tmp->len;
tmp->str[tmp->len] = '\0';
}
smp->data.str.str = tmp->str;
smp->data.str.len = strlen(smp->data.str.str);
fiftyoneDegreesFreeWorkset(ws);
return 1;
}
#endif // FIFTYONEDEGREES_H_PATTERN_INCLUDED
#endif // USE_51DEGREES
/************************************************************************/
/* All supported sample fetch functions must be declared here */
/************************************************************************/
@ -2596,9 +2476,6 @@ static struct sample_conv_kw_list sample_conv_kws = {ILH, {
{ "div", sample_conv_arith_div, ARG1(1,UINT), NULL, SMP_T_UINT, SMP_T_UINT },
{ "mod", sample_conv_arith_mod, ARG1(1,UINT), NULL, SMP_T_UINT, SMP_T_UINT },
{ "neg", sample_conv_arith_neg, 0, NULL, SMP_T_UINT, SMP_T_UINT },
#ifdef USE_51DEGREES
{ "51d", sample_fiftyone_degrees,ARG5(1,STR,STR,STR,STR,STR), NULL, SMP_T_STR, SMP_T_STR },
#endif
{ NULL, NULL, 0, 0, 0 },
}};