[core/modules] refactor config handling

* should be more robust now: taking list of wanted value, handling NULL
   pointers instead of value type NONE, fixed some bugs (wrong checks,
   mem leaks, ...)
 * add many methods to make handling of values easier; most methods
   can handle NULL value pointers safely (li_value_type(v) instead of
   v->type and so on)
personal/stbuehler/wip
Stefan Bühler 10 years ago
parent b783bd5aaa
commit a1fbaab86b

@ -126,7 +126,7 @@ LI_API gboolean li_plugin_config_setup(liServer *srv, const char *name, liValue
LI_API void li_plugins_init_lua(liLuaState *LL, liServer *srv, liWorker *wrk);
extern liOptionPtrValue li_option_ptr_zero;
extern const liOptionPtrValue li_option_ptr_zero;
/* needs vrequest *vr and plugin *p */
#define OPTION(idx) _OPTION(vr, p, idx)

@ -46,7 +46,8 @@ LI_API void li_value_clear(liValue *val); /* frees content, sets value to LI_VAL
LI_API void li_value_free(liValue* val);
LI_API void li_value_move(liValue *dest, liValue *src);
LI_API const char* li_value_type_string(liValueType type);
LI_API const char* li_valuetype_string(liValueType type);
INLINE const char* li_value_type_string(liValue *val);
LI_API GString *li_value_to_string(liValue *val);
@ -66,7 +67,65 @@ LI_API liCondition* li_value_extract_condition(liValue *val);
/* move the value content to a new value, set the old type to none */
LI_API liValue* li_value_extract(liValue *val);
/* converts value type to LI_VALUE_LIST, makes sure list contains (key,value) tuples, and the keys are all LI_VALUE_STRING or LI_VALUE_NONE */
/* converts value type to LI_VALUE_LIST, makes sure list contains (key,value) tuples, and the keys are all LI_VALUE_STRING or NULL / LI_VALUE_NONE */
LI_API liValue* li_value_to_key_value_list(liValue *val);
/* if val is list with exactly one element, return the element. otherwise return val */
INLINE liValue* li_value_get_single_argument(liValue *val);
/* returns whether val == 0 || (val->type == NONE) || (val->type == LIST && 0 == val->list->len) */
INLINE gboolean li_value_is_nothing(liValue *val);
/* returns type of value or LI_VALUE_NONE for NULL */
INLINE liValueType li_value_type(liValue *val);
/* returns whether val is a list and has length len */
INLINE gboolean li_value_list_has_len(liValue *val, guint len);
/* returns length of list or 0 if not a list */
INLINE guint li_value_list_len(liValue *val);
/* returns entry of list or NULL if not a list or out of bounds */
INLINE liValue* li_value_list_at(liValue* val, guint ndx);
/* returns type of list entry, or LI_VALUE_NONE if not a list or NULL entry or out of bounds */
INLINE liValueType li_value_list_type_at(liValue *val, guint ndx);
#define LI_VALUE_FOREACH(entry, list) { \
guint _ ## entry ## _i, _ ## entry ## _len = li_value_list_len(list); \
for (_ ## entry ## _i = 0; _ ## entry ## _i < _ ## entry ## _len; ++ _ ## entry ## _i ) { \
liValue *entry = li_value_list_at(list, _ ## entry ## _i);
#define LI_VALUE_END_FOREACH() } }
/* inline implementations */
INLINE const char* li_value_type_string(liValue *val) {
return NULL == val ? "NULL" : li_valuetype_string(val->type);
}
INLINE liValue* li_value_get_single_argument(liValue *val) {
return li_value_list_has_len(val, 1) ? li_value_list_at(val, 0) : val;
}
INLINE gboolean li_value_is_nothing(liValue *val) {
return NULL == val || LI_VALUE_NONE == val->type || (LI_VALUE_LIST == val->type && 0 == val->data.list->len);
}
INLINE liValueType li_value_type(liValue *val) {
return NULL == val ? LI_VALUE_NONE : val->type;
}
INLINE gboolean li_value_list_has_len(liValue *val, guint len) {
return (NULL != val && LI_VALUE_LIST == val->type && len == val->data.list->len);
}
INLINE guint li_value_list_len(liValue *val) {
return (NULL != val && LI_VALUE_LIST == val->type) ? val->data.list->len : 0;
}
INLINE liValue* li_value_list_at(liValue* val, guint ndx) {
if (NULL == val || LI_VALUE_LIST != val->type || ndx >= val->data.list->len) return NULL;
return g_array_index(val->data.list, liValue*, ndx);
}
INLINE liValueType li_value_list_type_at(liValue *val, guint ndx) {
return li_value_type(li_value_list_at(val, ndx));
}
#endif

@ -184,7 +184,7 @@ static gboolean config_parser_include(liServer *srv, GList *ctx_stack, gchar *pa
g_array_append_val(l->data.list, v);
_printf("list_push %s\n", li_value_type_string(v->type));
_printf("list_push %s\n", li_value_type_string(v));
}
action list_end {
@ -214,7 +214,7 @@ static gboolean config_parser_include(liServer *srv, GList *ctx_stack, gchar *pa
g_hash_table_insert(h->data.hash, str, v);
_printf("hash_push: %s: %s => %s\n", li_value_type_string(k->type), li_value_type_string(v->type), li_value_type_string(h->type));
_printf("hash_push: %s: %s => %s\n", li_value_type_string(k), li_value_type_string(v), li_value_type_string(h));
li_value_free(k);
}
@ -251,7 +251,7 @@ static gboolean config_parser_include(liServer *srv, GList *ctx_stack, gchar *pa
g_array_append_val(l->list, k);
g_array_append_val(l->list, v);
_printf("key-value pair: %s => %s in line %zd\n", li_value_type_string(k->type), li_value_type_string(v->type), ctx->line);
_printf("key-value pair: %s => %s in line %zd\n", li_value_type_string(k), li_value_type_string(v), ctx->line);
/* push list on the stack */
g_queue_push_head(ctx->value_stack, l);
@ -275,7 +275,7 @@ static gboolean config_parser_include(liServer *srv, GList *ctx_stack, gchar *pa
gboolean negative = FALSE;
if (v->type != LI_VALUE_STRING) {
ERROR(srv, "can only cast strings to integers, %s given", li_value_type_string(v->type));
ERROR(srv, "can only cast strings to integers, %s given", li_value_type_string(v));
return FALSE;
}
@ -305,7 +305,7 @@ static gboolean config_parser_include(liServer *srv, GList *ctx_stack, gchar *pa
GString *str;
if (v->type != LI_VALUE_NUMBER) {
ERROR(srv, "can only cast integers to strings, %s given", li_value_type_string(v->type));
ERROR(srv, "can only cast integers to strings, %s given", li_value_type_string(v));
return FALSE;
}
@ -318,7 +318,7 @@ static gboolean config_parser_include(liServer *srv, GList *ctx_stack, gchar *pa
ctx->cast = LI_CFG_PARSER_CAST_NONE;
}
_printf("value (%s) in line %zd\n", li_value_type_string(v->type), ctx->line);
_printf("value (%s) in line %zd\n", li_value_type_string(v), ctx->line);
}
action value_statement_start {
@ -424,17 +424,17 @@ static gboolean config_parser_include(liServer *srv, GList *ctx_stack, gchar *pa
if (v == NULL) {
WARNING(srv, "erronous value statement: %s %c %s in line %zd\n",
li_value_type_string(l->type), op,
li_value_type_string(r->type), ctx->line);
li_value_type_string(l), op,
li_value_type_string(r), ctx->line);
return FALSE;
}
_printf("value statement: %s %c%s %s => %s in line %zd\n",
li_value_type_string(l->type),
li_value_type_string(l),
op,
op == '=' ? ">" : "",
li_value_type_string(r->type),
li_value_type_string(v->type),
li_value_type_string(r),
li_value_type_string(v),
ctx->line);
if (free_l)
@ -555,7 +555,7 @@ static gboolean config_parser_include(liServer *srv, GList *ctx_stack, gchar *pa
assert(name->type == LI_VALUE_STRING);
_printf("got action call: %s %s; in line %zd\n", name->data.string->str, val ? li_value_type_string(val->type) : "<none>", ctx->line);
_printf("got action call: %s %s; in line %zd\n", name->data.string->str, val ? li_value_type_string(val) : "<none>", ctx->line);
/* internal functions */
if (g_str_equal(name->data.string->str, "include")) {
@ -591,7 +591,7 @@ static gboolean config_parser_include(liServer *srv, GList *ctx_stack, gchar *pa
}
if (val->type != LI_VALUE_STRING) {
WARNING(srv, "include_shell directive takes a string as parameter, %s given", li_value_type_string(val->type));
WARNING(srv, "include_shell directive takes a string as parameter, %s given", li_value_type_string(val));
li_value_free(val);
return FALSE;
}
@ -618,7 +618,7 @@ static gboolean config_parser_include(liServer *srv, GList *ctx_stack, gchar *pa
}
if (val->type != LI_VALUE_STRING) {
WARNING(srv, "include_lua directive takes a string as parameter, %s given", li_value_type_string(val->type));
WARNING(srv, "include_lua directive takes a string as parameter, %s given", li_value_type_string(val));
li_value_free(val);
return FALSE;
}
@ -647,7 +647,7 @@ static gboolean config_parser_include(liServer *srv, GList *ctx_stack, gchar *pa
}
tmpstr = li_value_to_string(val);
DEBUG(srv, "%s:%zd type: %s, value: %s", ctx->filename, ctx->line, li_value_type_string(val->type), tmpstr->str);
DEBUG(srv, "%s:%zd type: %s, value: %s", ctx->filename, ctx->line, li_value_type_string(val), tmpstr->str);
g_string_free(tmpstr, TRUE);
}
@ -662,7 +662,7 @@ static gboolean config_parser_include(liServer *srv, GList *ctx_stack, gchar *pa
_printf("%s", "... which is a user defined action\n");
if (uservar->type != LI_VALUE_ACTION) {
WARNING(srv, "value of type action expected, got %s", li_value_type_string(uservar->type));
WARNING(srv, "value of type action expected, got %s", li_value_type_string(uservar));
li_value_free(name);
if (val)
li_value_free(val);
@ -743,7 +743,7 @@ static gboolean config_parser_include(liServer *srv, GList *ctx_stack, gchar *pa
name = g_queue_pop_head(ctx->value_stack);
assert(name->type == LI_VALUE_STRING);
_printf("uservar definition %s = %s in line %zd\n", name->data.string->str, li_value_type_string(v->type), ctx->line);
_printf("uservar definition %s = %s in line %zd\n", name->data.string->str, li_value_type_string(v), ctx->line);
if (NULL != g_hash_table_lookup(srv->setups, name->data.string->str)) {
WARNING(srv, "cannot define uservar with name '%s', a setup action with same name exists already", name->data.string->str);
@ -853,9 +853,9 @@ static gboolean config_parser_include(liServer *srv, GList *ctx_stack, gchar *pa
if (ctx->condition_nonbool) {
if (ctx->condition_with_key) {
_printf("got condition: %s[%s] %s %s in line %zd\n", varname->data.string->str, key->data.string->str, li_comp_op_to_string(ctx->op), li_value_type_string(val->type), ctx->line);
_printf("got condition: %s[%s] %s %s in line %zd\n", varname->data.string->str, key->data.string->str, li_comp_op_to_string(ctx->op), li_value_type_string(val), ctx->line);
} else {
_printf("got condition: %s %s %s in line %zd\n", varname->data.string->str, li_comp_op_to_string(ctx->op), li_value_type_string(val->type), ctx->line);
_printf("got condition: %s %s %s in line %zd\n", varname->data.string->str, li_comp_op_to_string(ctx->op), li_value_type_string(val), ctx->line);
}
} else {
if (ctx->condition_with_key) {

@ -61,11 +61,11 @@ struct liServerSetup {
gpointer userdata;
};
static gboolean plugin_load_default_option(liServer *srv, liServerOption *sopt);
static gboolean plugin_load_default_optionptr(liServer *srv, liServerOptionPtr *sopt);
static gboolean plugin_load_default_option(liServer *srv, liServerOption *sopt, const char *name);
static gboolean plugin_load_default_optionptr(liServer *srv, liServerOptionPtr *sopt, const char *name);
static void li_plugin_free_default_options(liServer *srv, liPlugin *p);
liOptionPtrValue li_option_ptr_zero = { 0, { 0 } , 0 };
const liOptionPtrValue li_option_ptr_zero = { 0, { 0 } , 0 };
static liPlugin* plugin_new(const gchar *name) {
liPlugin *p = g_slice_new0(liPlugin);
@ -294,7 +294,7 @@ liPlugin *li_plugin_register(liServer *srv, const gchar *name, liPluginInitCB in
so->p = p;
so->default_value = po->default_value;
g_hash_table_insert(srv->options, (gchar*) po->name, so);
plugin_load_default_option(srv, so);
plugin_load_default_option(srv, so, po->name);
}
}
@ -314,7 +314,7 @@ liPlugin *li_plugin_register(liServer *srv, const gchar *name, liPluginInitCB in
so->p = p;
so->default_value = po->default_value;
g_hash_table_insert(srv->optionptrs, (gchar*) po->name, so);
plugin_load_default_optionptr(srv, so);
plugin_load_default_optionptr(srv, so, po->name);
}
}
@ -361,25 +361,25 @@ static liServerOption* find_option(liServer *srv, const char *name) {
}
static gboolean li_parse_option(liServer *srv, liWorker *wrk, liServerOption *sopt, const char *name, liValue *val, liOptionSet *mark) {
assert(NULL != srv && NULL != wrk && NULL != sopt && NULL != name && NULL != val && NULL != mark);
assert(NULL != srv && NULL != wrk && NULL != sopt && NULL != name && NULL != mark);
if (sopt->type != val->type && sopt->type != LI_VALUE_NONE) {
if (NULL != val && sopt->type != val->type && sopt->type != LI_VALUE_NONE) {
ERROR(srv, "Unexpected value type '%s', expected '%s' for option %s",
li_value_type_string(val->type), li_value_type_string(sopt->type), name);
li_value_type_string(val), li_valuetype_string(sopt->type), name);
return FALSE;
}
if (!sopt->parse_option) {
if (NULL == sopt->parse_option) {
switch (sopt->type) {
case LI_VALUE_BOOLEAN:
mark->value.boolean = val->data.boolean;
mark->value.boolean = (NULL == val) ? GPOINTER_TO_INT(sopt->default_value) : val->data.boolean;
break;
case LI_VALUE_NUMBER:
mark->value.number = val->data.number;
mark->value.number = (NULL == val) ? GPOINTER_TO_INT(sopt->default_value) : val->data.number;
break;
default:
ERROR(srv, "Invalid scalar option type '%s' for option %s",
li_value_type_string(sopt->type), name);
li_valuetype_string(sopt->type), name);
return FALSE;
}
} else {
@ -402,16 +402,26 @@ static gboolean li_parse_optionptr(liServer *srv, liWorker *wrk, liServerOptionP
liOptionPtrValue *oval;
gpointer ptr = NULL;
assert(NULL != srv && NULL != wrk && NULL != sopt && NULL != name && NULL != val && NULL != mark);
assert(NULL != srv && NULL != wrk && NULL != sopt && NULL != name && NULL != mark);
if (sopt->type != val->type && sopt->type != LI_VALUE_NONE) {
if (NULL != val && sopt->type != val->type && sopt->type != LI_VALUE_NONE) {
ERROR(srv, "Unexpected value type '%s', expected '%s' for option %s",
li_value_type_string(val->type), li_value_type_string(sopt->type), name);
li_value_type_string(val), li_valuetype_string(sopt->type), name);
return FALSE;
}
if (!sopt->parse_option) {
ptr = li_value_extract_ptr(val);
if (NULL == sopt->parse_option) {
if (NULL == val) {
switch (sopt->type) {
case LI_VALUE_STRING:
ptr = g_string_new((const char*) sopt->default_value);
break;
default:
ptr = NULL;
}
} else {
ptr = li_value_extract_ptr(val);
}
} else {
if (!sopt->parse_option(srv, wrk, sopt->p, sopt->module_index, val, &ptr)) {
/* errors should be logged by parse function */
@ -419,7 +429,7 @@ static gboolean li_parse_optionptr(liServer *srv, liWorker *wrk, liServerOptionP
}
}
if (ptr) {
if (NULL != ptr) {
oval = g_slice_new0(liOptionPtrValue);
oval->refcount = 1;
oval->sopt = sopt;
@ -479,6 +489,12 @@ void li_release_optionptr(liServer *srv, liOptionPtrValue *value) {
g_slice_free(liOptionPtrValue, value);
}
static liValue* option_value(liValue *val) {
if (li_value_list_has_len(val, 1)) return li_value_list_at(val, 0);
if (li_value_list_has_len(val, 0)) return NULL;
return val;
}
liAction *li_plugin_config_action(liServer *srv, liWorker *wrk, const gchar *name, liValue *val) {
liAction *a = NULL;
liServerAction *sa;
@ -492,13 +508,13 @@ liAction *li_plugin_config_action(liServer *srv, liWorker *wrk, const gchar *nam
} else if (NULL != (sopt = find_option(srv, name))) {
liOptionSet setting;
if (!li_parse_option(srv, wrk, sopt, name, val, &setting)) goto exit;
if (!li_parse_option(srv, wrk, sopt, name, option_value(val), &setting)) goto exit;
a = li_action_new_setting(setting);
} else if (NULL != (soptptr = find_optionptr(srv, name))) {
liOptionPtrSet setting;
if (!li_parse_optionptr(srv, wrk, soptptr, name, val, &setting)) goto exit;
if (!li_parse_optionptr(srv, wrk, soptptr, name, option_value(val), &setting)) goto exit;
a = li_action_new_settingptr(setting);
} else if (NULL != g_hash_table_lookup(srv->setups, name)) {
@ -527,14 +543,14 @@ gboolean li_plugin_config_setup(liServer *srv, const char *name, liValue *val) {
} else if (NULL != (sopt = find_option(srv, name))) {
liOptionSet setting;
if (!li_parse_option(srv, srv->main_worker, sopt, name, val, &setting)) goto exit;
if (!li_parse_option(srv, srv->main_worker, sopt, name, option_value(val), &setting)) goto exit;
g_array_index(srv->option_def_values, liOptionValue, sopt->index) = setting.value;
result = TRUE;
} else if (NULL != (soptptr = find_optionptr(srv, name))) {
liOptionPtrSet setting;
if (!li_parse_optionptr(srv, srv->main_worker, soptptr, name, val, &setting)) goto exit;
if (!li_parse_optionptr(srv, srv->main_worker, soptptr, name, option_value(val), &setting)) goto exit;
li_release_optionptr(srv, g_array_index(srv->optionptr_def_values, liOptionPtrValue*, soptptr->index));
g_array_index(srv->optionptr_def_values, liOptionPtrValue*, soptptr->index) = setting.value;
@ -583,74 +599,33 @@ void li_plugins_handle_vrclose(liVRequest *vr) {
}
}
static gboolean plugin_load_default_option(liServer *srv, liServerOption *sopt) {
liOptionValue oval = {0};
static gboolean plugin_load_default_option(liServer *srv, liServerOption *sopt, const char *name) {
liOptionSet setting;
assert(NULL != sopt);
if (!sopt)
return FALSE;
if (!sopt->parse_option) {
switch (sopt->type) {
case LI_VALUE_BOOLEAN:
oval.boolean = GPOINTER_TO_INT(sopt->default_value);
break;
case LI_VALUE_NUMBER:
oval.number = GPOINTER_TO_INT(sopt->default_value);
break;
default:
ERROR(srv, "Invalid type '%s' for scalar option",
li_value_type_string(sopt->type));
return FALSE;
}
} else {
if (!sopt->parse_option(srv, srv->main_worker, sopt->p, sopt->module_index, NULL, &oval)) {
/* errors should be logged by parse function */
return FALSE;
}
}
if (!li_parse_option(srv, srv->main_worker, sopt, name, NULL, &setting)) return FALSE;
assert(setting.ndx == sopt->index);
if (srv->option_def_values->len <= sopt->index)
g_array_set_size(srv->option_def_values, sopt->index + 1);
g_array_index(srv->option_def_values, liOptionValue, sopt->index) = oval;
g_array_index(srv->option_def_values, liOptionValue, sopt->index) = setting.value;
return TRUE;
}
static gboolean plugin_load_default_optionptr(liServer *srv, liServerOptionPtr *sopt) {
gpointer ptr = NULL;
liOptionPtrValue *oval = NULL;
static gboolean plugin_load_default_optionptr(liServer *srv, liServerOptionPtr *sopt, const char *name) {
liOptionPtrSet setting;
assert(NULL != sopt);
if (!sopt)
return FALSE;
if (!sopt->parse_option) {
switch (sopt->type) {
case LI_VALUE_STRING:
ptr = g_string_new((const char*) sopt->default_value);
break;
default:
ptr = NULL;
}
} else {
if (!sopt->parse_option(srv, srv->main_worker, sopt->p, sopt->module_index, NULL, &ptr)) {
/* errors should be logged by parse function */
return FALSE;
}
}
if (ptr) {
oval = g_slice_new0(liOptionPtrValue);
oval->refcount = 1;
oval->data.ptr = ptr;
oval->sopt = sopt;
}
if (!li_parse_optionptr(srv, srv->main_worker, sopt, name, NULL, &setting)) return FALSE;
assert(setting.ndx == sopt->index);
if (srv->optionptr_def_values->len <= sopt->index)
g_array_set_size(srv->optionptr_def_values, sopt->index + 1);
li_release_optionptr(srv, g_array_index(srv->optionptr_def_values, liOptionPtrValue*, sopt->index));
g_array_index(srv->optionptr_def_values, liOptionPtrValue*, sopt->index) = oval;
g_array_index(srv->optionptr_def_values, liOptionPtrValue*, sopt->index) = setting.value;
return TRUE;
}

File diff suppressed because it is too large Load Diff

@ -77,7 +77,10 @@ void li_value_list_append(liValue *list, liValue *item) {
}
void li_value_wrap_in_list(liValue *val) {
liValue *item = li_value_extract(val);
liValue *item;
assert(NULL != val);
item = li_value_extract(val);
val->type = LI_VALUE_LIST;
val->data.list = g_array_new(FALSE, TRUE, sizeof(liValue*));
g_array_append_val(val->data.list, item);
@ -85,6 +88,7 @@ void li_value_wrap_in_list(liValue *val) {
liValue* li_value_copy(liValue* val) {
liValue *n;
if (NULL == val) return NULL;
switch (val->type) {
case LI_VALUE_NONE: return li_value_new_none();
@ -168,7 +172,7 @@ void li_value_move(liValue *dest, liValue *src) {
_li_value_clear(src);
}
const char* li_value_type_string(liValueType type) {
const char* li_valuetype_string(liValueType type) {
switch(type) {
case LI_VALUE_NONE:
return "none";
@ -191,7 +195,7 @@ const char* li_value_type_string(liValueType type) {
}
void li_value_list_free(GArray *vallist) {
if (!vallist) return;
if (NULL == vallist) return;
for (gsize i = 0; i < vallist->len; i++) {
li_value_free(g_array_index(vallist, liValue*, i));
}
@ -202,67 +206,67 @@ GString *li_value_to_string(liValue *val) {
GString *str;
switch (val->type) {
case LI_VALUE_NONE:
return NULL;
case LI_VALUE_BOOLEAN:
str = g_string_new(val->data.boolean ? "true" : "false");
break;
case LI_VALUE_NUMBER:
str = g_string_sized_new(0);
g_string_printf(str, "%" G_GINT64_FORMAT, val->data.number);
break;
case LI_VALUE_STRING:
str = g_string_new_len(CONST_STR_LEN("\""));
g_string_append_len(str, GSTR_LEN(val->data.string));
g_string_append_c(str, '"');
break;
case LI_VALUE_LIST:
str = g_string_new_len(CONST_STR_LEN("("));
if (val->data.list->len) {
GString *tmp = li_value_to_string(g_array_index(val->data.list, liValue*, 0));
case LI_VALUE_NONE:
return NULL;
case LI_VALUE_BOOLEAN:
str = g_string_new(val->data.boolean ? "true" : "false");
break;
case LI_VALUE_NUMBER:
str = g_string_sized_new(0);
g_string_printf(str, "%" G_GINT64_FORMAT, val->data.number);
break;
case LI_VALUE_STRING:
str = g_string_new_len(CONST_STR_LEN("\""));
g_string_append_len(str, GSTR_LEN(val->data.string));
g_string_append_c(str, '"');
break;
case LI_VALUE_LIST:
str = g_string_new_len(CONST_STR_LEN("("));
if (val->data.list->len) {
GString *tmp = li_value_to_string(g_array_index(val->data.list, liValue*, 0));
g_string_append(str, tmp->str);
g_string_free(tmp, TRUE);
for (guint i = 1; i < val->data.list->len; i++) {
tmp = li_value_to_string(g_array_index(val->data.list, liValue*, i));
g_string_append_len(str, CONST_STR_LEN(", "));
g_string_append(str, tmp->str);
g_string_free(tmp, TRUE);
for (guint i = 1; i < val->data.list->len; i++) {
tmp = li_value_to_string(g_array_index(val->data.list, liValue*, i));
g_string_append_len(str, CONST_STR_LEN(", "));
g_string_append(str, tmp->str);
g_string_free(tmp, TRUE);
}
}
g_string_append_c(str, ')');
break;
case LI_VALUE_HASH:
{
GHashTableIter iter;
gpointer k, v;
GString *tmp;
guint i = 0;
str = g_string_new_len(CONST_STR_LEN("["));
g_hash_table_iter_init(&iter, val->data.hash);
while (g_hash_table_iter_next(&iter, &k, &v)) {
if (i)
g_string_append_len(str, CONST_STR_LEN(", "));
tmp = li_value_to_string((liValue*)v);
g_string_append_len(str, GSTR_LEN((GString*)k));
g_string_append_len(str, CONST_STR_LEN(" => "));
g_string_append_len(str, GSTR_LEN(tmp));
g_string_free(tmp, TRUE);
i++;
}
g_string_append_c(str, ']');
break;
}
case LI_VALUE_ACTION:
str = g_string_new_len(CONST_STR_LEN("<action>"));
break;
case LI_VALUE_CONDITION:
str = g_string_new_len(CONST_STR_LEN("<condition>"));
break;
default:
return NULL;
g_string_append_c(str, ')');
break;
case LI_VALUE_HASH:
{
GHashTableIter iter;
gpointer k, v;
GString *tmp;
guint i = 0;
str = g_string_new_len(CONST_STR_LEN("["));
g_hash_table_iter_init(&iter, val->data.hash);
while (g_hash_table_iter_next(&iter, &k, &v)) {
if (i)
g_string_append_len(str, CONST_STR_LEN(", "));
tmp = li_value_to_string((liValue*)v);
g_string_append_len(str, GSTR_LEN((GString*)k));
g_string_append_len(str, CONST_STR_LEN(" => "));
g_string_append_len(str, GSTR_LEN(tmp));
g_string_free(tmp, TRUE);
i++;
}
g_string_append_c(str, ']');
break;
}
case LI_VALUE_ACTION:
str = g_string_new_len(CONST_STR_LEN("<action>"));
break;
case LI_VALUE_CONDITION:
str = g_string_new_len(CONST_STR_LEN("<condition>"));
break;
default:
return NULL;
}
return str;
@ -353,7 +357,7 @@ liValue* li_value_extract(liValue *val) {
liValue* li_value_to_key_value_list(liValue *val) {
if (NULL == val) return NULL;
if (val->type == LI_VALUE_HASH) {
if (LI_VALUE_HASH == val->type) {
GHashTable *table = li_value_extract_hash(val);
GArray *list;
@ -381,21 +385,19 @@ liValue* li_value_to_key_value_list(liValue *val) {
g_hash_table_destroy(table);
return val;
} else if (val->type == LI_VALUE_LIST) {
/* verify key-value list properties */
GArray *list = val->data.list;
guint i;
for (i = 0; i < list->len; ++i) {
liValue *lentry = g_array_index(list, liValue*, i);
GArray *entrylist;
liValue *key;
if (lentry->type != LI_VALUE_LIST) return NULL;
entrylist = lentry->data.list;
if (2 != entrylist->len) return NULL;
key = g_array_index(entrylist, liValue*, 0);
if (key->type != LI_VALUE_STRING && key->type != LI_VALUE_NONE) return NULL;
} else if (LI_VALUE_LIST == val->type) {
if (li_value_list_has_len(val, 2) &&
(LI_VALUE_STRING == li_value_list_type_at(val, 0) || LI_VALUE_NONE == li_value_list_type_at(val, 0))) {
/* single key-value pair */
li_value_wrap_in_list(val);
return val;
}
/* verify key-value list properties */
LI_VALUE_FOREACH(lentry, val)
if (!li_value_list_has_len(lentry, 2)) return NULL;
if (LI_VALUE_STRING != li_value_list_type_at(lentry, 0) && LI_VALUE_NONE != li_value_list_type_at(lentry, 0)) return NULL;
LI_VALUE_END_FOREACH()
return val;
}
return NULL;

@ -115,24 +115,20 @@ static void access_check_free(liServer *srv, gpointer param) {
}
static liAction* access_check_create(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) {
GArray *arr;
liValue *v, *ip;
guint i, j;
guint32 ipv4, netmaskv4;
gboolean deny = FALSE;
access_check_data *acd = NULL;
UNUSED(srv);
UNUSED(wrk);
UNUSED(userdata);
UNUSED(srv); UNUSED(wrk); UNUSED(userdata);
val = li_value_get_single_argument(val);
if (LI_VALUE_STRING == li_value_list_type_at(val, 0)) {
li_value_wrap_in_list(val);
}
if (!val || val->type != LI_VALUE_LIST || (val->data.list->len != 1 && val->data.list->len != 2)) {
if (!li_value_list_has_len(val, 1) && !li_value_list_has_len(val, 2)) {
ERROR(srv, "%s", "access_check expects a list of one or two string,list tuples as parameter");
return NULL;
}
arr = val->data.list;
acd = g_slice_new0(access_check_data);
acd->p = p;
acd->ipv4 = li_radixtree_new();
@ -140,43 +136,44 @@ static liAction* access_check_create(liServer *srv, liWorker *wrk, liPlugin* p,
li_radixtree_insert(acd->ipv4, NULL, 0, GINT_TO_POINTER(ACCESS_DENY));
li_radixtree_insert(acd->ipv6, NULL, 0, GINT_TO_POINTER(ACCESS_DENY));
for (i = 0; i < arr->len; i++) {
v = g_array_index(arr, liValue*, i);
LI_VALUE_FOREACH(v, val)
liValue *vAD, *vIPs;
gboolean deny = FALSE;
if (v->type != LI_VALUE_LIST || v->data.list->len != 2) {
if (!li_value_list_has_len(v, 2)) {
ERROR(srv, "%s", "access_check expects a list of one or two string,list tuples as parameter");
goto failed_free_acd;
}
v = g_array_index(v->data.list, liValue*, 0);
vAD = li_value_list_at(v, 0);
if (v->type != LI_VALUE_STRING) {
if (LI_VALUE_STRING != li_value_type(vAD)) {
ERROR(srv, "%s", "access_check expects a list of one or two string,list tuples as parameter");
goto failed_free_acd;
}
if (g_str_equal(v->data.string->str, "allow")) {
if (g_str_equal(vAD->data.string->str, "allow")) {
deny = FALSE;
} else if (g_str_equal(v->data.string->str, "deny")) {
} else if (g_str_equal(vAD->data.string->str, "deny")) {
deny = TRUE;
} else {
ERROR(srv, "access_check: invalid option \"%s\"", v->data.string->str);
ERROR(srv, "access_check: invalid option \"%s\"", vAD->data.string->str);
goto failed_free_acd;
}
v = g_array_index(g_array_index(arr, liValue*, i)->data.list, liValue*, 1);
vIPs = li_value_list_at(v, 1);
if (v->type != LI_VALUE_LIST) {
if (LI_VALUE_LIST != li_value_type(vIPs)) {
ERROR(srv, "%s", "access_check expects a list of one or two string,list tuples as parameter");
goto failed_free_acd;
}
for (j = 0; j < v->data.list->len; j++) {
LI_VALUE_FOREACH(ip, vIPs)
guint32 ipv4, netmaskv4;
guint8 ipv6_addr[16];
guint ipv6_network;
ip = g_array_index(v->data.list, liValue*, j);
if (ip->type != LI_VALUE_STRING) {
if (LI_VALUE_STRING != li_value_type(ip)) {
ERROR(srv, "%s", "access_check expects a list of one or two string,list tuples as parameter");
goto failed_free_acd;
}
@ -196,8 +193,8 @@ static liAction* access_check_create(liServer *srv, liWorker *wrk, liPlugin* p,
ERROR(srv, "access_check: error parsing ip: %s", ip->data.string->str);
goto failed_free_acd;
}
}
}
LI_VALUE_END_FOREACH()
LI_VALUE_END_FOREACH()
return li_action_new_function(access_check, NULL, access_check_free, acd);
@ -231,7 +228,7 @@ static liHandlerResult access_deny(liVRequest *vr, gpointer param, gpointer *con
static liAction* access_deny_create(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) {
UNUSED(srv); UNUSED(wrk); UNUSED(userdata);
if (val) {
if (!li_value_is_nothing(val)) {
ERROR(srv, "%s", "access.deny doesn't expect any parameters");
return NULL;
}

@ -403,7 +403,7 @@ static void al_option_accesslog_free(liServer *srv, liPlugin *p, size_t ndx, gpo
UNUSED(p);
UNUSED(ndx);
if (!oval) return;
if (NULL == oval) return;
g_string_free(oval, TRUE);
}
@ -413,13 +413,13 @@ static gboolean al_option_accesslog_parse(liServer *srv, liWorker *wrk, liPlugin
UNUSED(p);
UNUSED(ndx);
if (!val) {
if (NULL == val) {
/* default */
return TRUE;
}
if (val->type != LI_VALUE_STRING) {
ERROR(srv, "accesslog option expects a string as parameter, %s given", li_value_type_string(val->type));
if (LI_VALUE_STRING != li_value_type(val)) {
ERROR(srv, "accesslog option expects a string as parameter, %s given", li_value_type_string(val));
return FALSE;
}
@ -436,13 +436,13 @@ static void al_option_accesslog_format_free(liServer *srv, liPlugin *p, size_t n
UNUSED(p);
UNUSED(ndx);
if (!oval) return;
if (NULL == oval) return;
arr = oval;
for (i = 0; i < arr->len; i++) {
al_format_entry *afe = &g_array_index(arr, al_format_entry, i);
if (afe->key)
if (NULL != afe->key)
g_string_free(afe->key, TRUE);
}
@ -452,21 +452,19 @@ static void al_option_accesslog_format_free(liServer *srv, liPlugin *p, size_t n
static gboolean al_option_accesslog_format_parse(liServer *srv, liWorker *wrk, liPlugin *p, size_t ndx, liValue *val, gpointer *oval) {
GArray *arr;
UNUSED(wrk);
UNUSED(p);
UNUSED(ndx);
UNUSED(wrk); UNUSED(p); UNUSED(ndx);
if (!val) {
if (NULL == val) {
/* default */
arr = al_parse_format(srv, AL_DEFAULT_FORMAT);
} else if (val->type != LI_VALUE_STRING) {
ERROR(srv, "accesslog.format option expects a string as parameter, %s given", li_value_type_string(val->type));
} else if (LI_VALUE_STRING != li_value_type(val)) {
ERROR(srv, "accesslog.format option expects a string as parameter, %s given", li_value_type_string(val));
return FALSE;
} else {
arr = al_parse_format(srv, val->data.string->str);
}
if (!arr) {
if (NULL == arr) {
ERROR(srv, "%s", "failed to parse accesslog format");
return FALSE;
}

@ -492,29 +492,27 @@ static liAction* auth_generic_create(liServer *srv, liWorker *wrk, liPlugin* p,
liValue *realm = NULL;
gboolean have_ttl_parameter = FALSE;
gint ttl = 10;
GArray *list;
guint i;
val = li_value_get_single_argument(val);
if (NULL == (val = li_value_to_key_value_list(val))) {
ERROR(srv, "%s expects a hashtable/key-value list with at least 3 elements: method, realm and file", actname);
return NULL;
}
list = val->data.list;
for (i = 0; i < list->len; ++i) {
liValue *entryKey = g_array_index(g_array_index(list, liValue*, i)->data.list, liValue*, 0);
liValue *entryValue = g_array_index(g_array_index(list, liValue*, i)->data.list, liValue*, 1);
LI_VALUE_FOREACH(entry, val)
liValue *entryKey = li_value_list_at(entry, 0);
liValue *entryValue = li_value_list_at(entry, 1);
GString *entryKeyStr;
if (entryKey->type == LI_VALUE_NONE) {
ERROR(srv, "%s doesn't take null keys", actname);
if (LI_VALUE_NONE == li_value_type(entryKey)) {
ERROR(srv, "%s doesn't take default keys", actname);
return NULL;
}
entryKeyStr = entryKey->data.string; /* keys are either NONE or STRING */
if (g_string_equal(entryKeyStr, &aon_method)) {
if (entryValue->type != LI_VALUE_STRING) {
if (LI_VALUE_STRING != li_value_type(entryValue)) {
ERROR(srv, "auth option '%s' expects string as parameter", entryKeyStr->str);
return NULL;
}
@ -524,7 +522,7 @@ static liAction* auth_generic_create(liServer *srv, liWorker *wrk, liPlugin* p,
}
method = entryValue->data.string;
} else if (g_string_equal(entryKeyStr, &aon_realm)) {
if (entryValue->type != LI_VALUE_STRING) {
if (LI_VALUE_STRING != li_value_type(entryValue)) {
ERROR(srv, "auth option '%s' expects string as parameter", entryKeyStr->str);
return NULL;
}
@ -534,7 +532,7 @@ static liAction* auth_generic_create(liServer *srv, liWorker *wrk, liPlugin* p,
}
realm = entryValue;
} else if (g_string_equal(entryKeyStr, &aon_file)) {
if (entryValue->type != LI_VALUE_STRING) {
if (LI_VALUE_STRING != li_value_type(entryValue)) {
ERROR(srv, "auth option '%s' expects string as parameter", entryKeyStr->str);
return NULL;
}
@ -544,7 +542,7 @@ static liAction* auth_generic_create(liServer *srv, liWorker *wrk, liPlugin* p,
}
file = entryValue->data.string;
} else if (g_string_equal(entryKeyStr, &aon_ttl)) {
if (entryValue->type != LI_VALUE_NUMBER || entryValue->data.number < 0) {
if (LI_VALUE_NUMBER != li_value_type(entryValue) || entryValue->data.number < 0) {
ERROR(srv, "auth option '%s' expects non-negative number as parameter", entryKeyStr->str);
return NULL;
}
@ -558,7 +556,7 @@ static liAction* auth_generic_create(liServer *srv, liWorker *wrk, liPlugin* p,
ERROR(srv, "unknown auth option '%s'", entryKeyStr->str);
return NULL;
}
}
LI_VALUE_END_FOREACH()
if (NULL == method || NULL == realm || NULL == file) {
ERROR(srv, "%s expects a hashtable/key-value list with 3 elements: method, realm and file", actname);
@ -634,7 +632,7 @@ static liAction* auth_deny(liServer *srv, liWorker *wrk, liPlugin* p, liValue *v
UNUSED(wrk);
UNUSED(userdata);
if (val) {
if (!li_value_is_nothing(val)) {
ERROR(srv, "%s", "'auth.deny' action doesn't have parameters");
return NULL;
}

@ -126,34 +126,38 @@ static void balancer_free(liServer *srv, balancer *b) {
}
static gboolean balancer_fill_backends(balancer *b, liServer *srv, liValue *val) {
if (val->type == LI_VALUE_ACTION) {
backend be = { val->data.val_action.action, 0, BE_ALIVE, 0 };
val = li_value_get_single_argument(val);
if (LI_VALUE_ACTION == li_value_type(val)) {
backend be;
be.act = val->data.val_action.action;
be.load = 0; be.state = BE_ALIVE; be.wake = 0;
assert(srv == val->data.val_action.srv);
li_action_acquire(be.act);
g_array_append_val(b->backends, be);
return TRUE;
} else if (val->type == LI_VALUE_LIST) {
guint i;
if (val->data.list->len == 0) {
} else if (LI_VALUE_LIST == li_value_type(val)) {
if (li_value_list_has_len(val, 0)) {
ERROR(srv, "%s", "expected non-empty list");
return FALSE;
}
for (i = 0; i < val->data.list->len; i++) {
liValue *oa = g_array_index(val->data.list, liValue*, i);
if (oa->type != LI_VALUE_ACTION) {
ERROR(srv, "expected action at entry %u of list, got %s", i, li_value_type_string(oa->type));
LI_VALUE_FOREACH(oa, val)
if (LI_VALUE_ACTION != li_value_type(oa)) {
ERROR(srv, "expected action at entry %u of list, got %s", _oa_i, li_value_type_string(oa));
return FALSE;
}
assert(srv == oa->data.val_action.srv);
{
backend be = { oa->data.val_action.action, 0, BE_ALIVE, 0 };
backend be;
be.act = oa->data.val_action.action;
be.load = 0; be.state = BE_ALIVE; be.wake = 0;
li_action_acquire(be.act);
g_array_append_val(b->backends, be);
}
}
LI_VALUE_END_FOREACH()
return TRUE;
} else {
ERROR(srv, "expected list, got %s", li_value_type_string(val->type));
ERROR(srv, "expected list, got %s", li_value_type_string(val));
return FALSE;
}
}
@ -520,7 +524,7 @@ static void balancer_act_free(liServer *srv, gpointer param) {
static liAction* balancer_create(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) {
balancer *b;
if (!val) {
if (NULL == val) {
ERROR(srv, "%s", "need parameter");
return NULL;
}

@ -339,7 +339,9 @@ static liAction* cache_etag_create(liServer *srv, liWorker *wrk, liPlugin* p, li
cache_etag_context *ctx;
UNUSED(wrk); UNUSED(p); UNUSED(userdata);
if (val->type != LI_VALUE_STRING) {
val = li_value_get_single_argument(val);
if (LI_VALUE_STRING != li_value_type(val)) {
ERROR(srv, "%s", "cache.disk.etag expects a string as parameter");
return FALSE;
}

@ -333,7 +333,7 @@ static liHandlerResult debug_show_connections(liVRequest *vr, gpointer param, gp
static liAction* debug_show_connections_create(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) {
UNUSED(wrk); UNUSED(userdata);
if (val) {
if (!li_value_is_nothing(val)) {
ERROR(srv, "%s", "debug.show_connections doesn't expect any parameters");
return NULL;
}
@ -357,16 +357,19 @@ static liHandlerResult debug_profiler_dump(liVRequest *vr, gpointer param, gpoin
static liAction* debug_profiler_dump_create(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) {
gpointer ptr;
UNUSED(wrk); UNUSED(p); UNUSED(userdata);
if (val && val->type != LI_VALUE_NUMBER) {
val = li_value_get_single_argument(val);
if (LI_VALUE_NONE == li_value_type(val)) {
ptr = GINT_TO_POINTER(10240);
} else if (LI_VALUE_NUMBER == li_value_type(val)) {
ptr = GINT_TO_POINTER(val->data.number);
} else {
ERROR(srv, "%s", "debug.profiler_dump takes an optional integer (minsize) as parameter");
return NULL;
}
ptr = GINT_TO_POINTER(val ? val->data.number : 10240);
return li_action_new_function(debug_profiler_dump, NULL, NULL, ptr);
}
#endif

@ -700,8 +700,20 @@ static const GString
static liAction* deflate_create(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) {
deflate_config *conf;
gboolean
have_encodings_parameter = FALSE,
have_blocksize_parameter = FALSE,
have_outputbuffer_parameter = FALSE,
have_compression_level_parameter = FALSE;
UNUSED(wrk); UNUSED(userdata);
val = li_value_get_single_argument(val);
if (NULL != val && NULL == (val = li_value_to_key_value_list(val))) {
ERROR(srv, "%s", "deflate expects a optional hash/key-value list as parameter");
return NULL;
}
conf = g_slice_new0(deflate_config);
conf->p = p;
conf->allowed_encodings = encoding_available_mask;
@ -709,81 +721,66 @@ static liAction* deflate_create(liServer *srv, liWorker *wrk, liPlugin* p, liVal
conf->output_buffer = 4*1024;
conf->compression_level = 1;
if (NULL != val) {
gboolean
have_encodings_parameter = FALSE,
have_blocksize_parameter = FALSE,
have_outputbuffer_parameter = FALSE,
have_compression_level_parameter = FALSE;
GArray *list;
guint i;
if (NULL == (val = li_value_to_key_value_list(val))) {
ERROR(srv, "%s", "deflate expects a optional hash/key-value list as parameter");
LI_VALUE_FOREACH(entry, val)
liValue *entryKey = li_value_list_at(entry, 0);
liValue *entryValue = li_value_list_at(entry, 1);
GString *entryKeyStr;
if (LI_VALUE_STRING != li_value_type(entryKey)) {
ERROR(srv, "%s", "deflate doesn't take default keys");
goto option_failed;
}
entryKeyStr = entryKey->data.string; /* keys are either NONE or STRING */
list = val->data.list;
for (i = 0; i < list->len; ++i) {
liValue *entryKey = g_array_index(g_array_index(list, liValue*, i)->data.list, liValue*, 0);
liValue *entryValue = g_array_index(g_array_index(list, liValue*, i)->data.list, liValue*, 1);
GString *entryKeyStr;
if (entryKey->type == LI_VALUE_NONE) {
ERROR(srv, "%s", "deflate doesn't take null keys");
if (g_string_equal(entryKeyStr, &don_encodings)) {
if (LI_VALUE_STRING != li_value_type(entryValue)) {
ERROR(srv, "deflate option '%s' expects string as parameter", entryKeyStr->str);
goto option_failed;
}
if (have_encodings_parameter) {
ERROR(srv, "duplicate deflate option '%s'", entryKeyStr->str);
goto option_failed;
}
have_encodings_parameter = TRUE;
conf->allowed_encodings = header_to_endocing_mask(entryValue->data.string->str);
} else if (g_string_equal(entryKeyStr, &don_blocksize)) {
if (LI_VALUE_NUMBER != li_value_type(entryValue) || entryValue->data.number <= 0) {
ERROR(srv, "deflate option '%s' expects positive integer as parameter", entryKeyStr->str);
goto option_failed;
}
entryKeyStr = entryKey->data.string; /* keys are either NONE or STRING */
if (g_string_equal(entryKeyStr, &don_encodings)) {
if (LI_VALUE_STRING != entryValue->type) {
ERROR(srv, "deflate option '%s' expects string as parameter", entryKeyStr->str);
goto option_failed;
}
if (have_encodings_parameter) {
ERROR(srv, "duplicate deflate option '%s'", entryKeyStr->str);
goto option_failed;
}
have_encodings_parameter = TRUE;
conf->allowed_encodings = header_to_endocing_mask(entryValue->data.string->str);
} else if (g_string_equal(entryKeyStr, &don_blocksize)) {
if (LI_VALUE_NUMBER != entryValue->type || entryValue->data.number <= 0) {
ERROR(srv, "deflate option '%s' expects positive integer as parameter", entryKeyStr->str);
goto option_failed;
}
if (have_blocksize_parameter) {
ERROR(srv, "duplicate deflate option '%s'", entryKeyStr->str);
goto option_failed;
}
have_blocksize_parameter = TRUE;
conf->blocksize = entryValue->data.number;
} else if (g_string_equal(entryKeyStr, &don_outputbuffer)) {
if (LI_VALUE_NUMBER != entryValue->type || entryValue->data.number <= 0) {
ERROR(srv, "deflate option '%s' expects positive integer as parameter", entryKeyStr->str);
goto option_failed;
}
if (have_outputbuffer_parameter) {
ERROR(srv, "duplicate deflate option '%s'", entryKeyStr->str);
goto option_failed;
}
have_outputbuffer_parameter = TRUE;
conf->output_buffer = entryValue->data.number;
} else if (g_string_equal(entryKeyStr, &don_compression_level)) {
if (LI_VALUE_NUMBER != entryValue->type || entryValue->data.number <= 0 || entryValue->data.number > 9) {
ERROR(srv, "deflate option '%s' expects an integer between 1 and 9 as parameter", entryKeyStr->str);
goto option_failed;
}
if (have_compression_level_parameter) {
ERROR(srv, "duplicate deflate option '%s'", entryKeyStr->str);
goto option_failed;
}
have_compression_level_parameter = TRUE;
conf->compression_level = entryValue->data.number;
} else {
ERROR(srv, "unknown option for deflate '%s'", entryKeyStr->str);
if (have_blocksize_parameter) {
ERROR(srv, "duplicate deflate option '%s'", entryKeyStr->str);
goto option_failed;
}
have_blocksize_parameter = TRUE;
conf->blocksize = entryValue->data.number;
} else if (g_string_equal(entryKeyStr, &don_outputbuffer)) {
if (LI_VALUE_NUMBER != li_value_type(entryValue) || entryValue->data.number <= 0) {
ERROR(srv, "deflate option '%s' expects positive integer as parameter", entryKeyStr->str);
goto option_failed;
}
if (have_outputbuffer_parameter) {
ERROR(srv, "duplicate deflate option '%s'", entryKeyStr->str);
goto option_failed;
}
have_outputbuffer_parameter = TRUE;
conf->output_buffer = entryValue->data.number;
} else if (g_string_equal(entryKeyStr, &don_compression_level)) {
if (LI_VALUE_NUMBER != li_value_type(entryValue) || entryValue->data.number <= 0 || entryValue->data.number > 9) {
ERROR(srv, "deflate option '%s' expects an integer between 1 and 9 as parameter", entryKeyStr->str);
goto option_failed;
}
if (have_compression_level_parameter) {
ERROR(srv, "duplicate deflate option '%s'", entryKeyStr->str);
goto option_failed;
}
have_compression_level_parameter = TRUE;
conf->compression_level = entryValue->data.number;
} else {
ERROR(srv, "unknown option for deflate '%s'", entryKeyStr->str);
goto option_failed;
}
}
LI_VALUE_END_FOREACH()
return li_action_new_function(deflate_handle, NULL, deflate_free, conf);

@ -590,15 +590,18 @@ static void dirlist_free(liServer *srv, gpointer param) {
UNUSED(srv);
if (data->css)
if (NULL != data->css) {
g_string_free(data->css, TRUE);
}
for (i = 0; i < data->exclude_suffix->len; i++)
for (i = 0; i < data->exclude_suffix->len; i++) {
g_string_free(g_ptr_array_index(data->exclude_suffix, i), TRUE);
}
g_ptr_array_free(data->exclude_suffix, TRUE);
for (i = 0; i < data->exclude_prefix->len; i++)
for (i = 0; i < data->exclude_prefix->len; i++) {
g_string_free(g_ptr_array_index(data->exclude_prefix, i), TRUE);
}
g_ptr_array_free(data->exclude_prefix, TRUE);
g_string_free(data->content_type, TRUE);
@ -608,13 +611,11 @@ static void dirlist_free(liServer *srv, gpointer param) {
static liAction* dirlist_create(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) {
dirlist_data *data;
guint i;
guint j;
liValue *v, *tmpval;
GString *k;
UNUSED(wrk); UNUSED(userdata);
if (val && val->type != LI_VALUE_LIST) {
val = li_value_get_single_argument(val);
if (NULL != val && NULL == (val = li_value_to_key_value_list(val))) {
ERROR(srv, "%s", "dirlist expects an optional list of string-value pairs");
return NULL;
}
@ -631,148 +632,148 @@ static liAction* dirlist_create(liServer *srv, liWorker *wrk, liPlugin* p, liVal
data->exclude_prefix = g_ptr_array_new();
data->content_type = g_string_new("text/html; charset=utf-8");
if (val) {
for (i = 0; i < val->data.list->len; i++) {
tmpval = g_array_index(val->data.list, liValue*, i);
if (tmpval->type != LI_VALUE_LIST || tmpval->data.list->len != 2 ||
g_array_index(tmpval->data.list, liValue*, 0)->type != LI_VALUE_STRING) {