static bool ucl_schema_validate_string (const ucl_object_t *schema, const ucl_object_t *obj, struct ucl_schema_error *err) { const ucl_object_t *elt; ucl_object_iter_t iter = NULL; bool ret = true; int64_t constraint; #ifdef HAVE_REGEX_H regex_t re; #endif while (ret && (elt = ucl_iterate_object (schema, &iter, true)) != NULL) { if (elt->type == UCL_INT && strcmp (ucl_object_key (elt), "maxLength") == 0) { constraint = ucl_object_toint (elt); if (obj->len > constraint) { ucl_schema_create_error (err, UCL_SCHEMA_CONSTRAINT, obj, "string is too big: %.3f, maximum is: %.3f", obj->len, constraint); ret = false; break; } } else if (elt->type == UCL_INT && strcmp (ucl_object_key (elt), "minLength") == 0) { constraint = ucl_object_toint (elt); if (obj->len < constraint) { ucl_schema_create_error (err, UCL_SCHEMA_CONSTRAINT, obj, "string is too short: %.3f, minimum is: %.3f", obj->len, constraint); ret = false; break; } } #ifdef HAVE_REGEX_H else if (elt->type == UCL_STRING && strcmp (ucl_object_key (elt), "pattern") == 0) { if (regcomp (&re, ucl_object_tostring (elt), REG_EXTENDED | REG_NOSUB) != 0) { ucl_schema_create_error (err, UCL_SCHEMA_INVALID_SCHEMA, elt, "cannot compile pattern %s", ucl_object_tostring (elt)); ret = false; break; } if (regexec (&re, ucl_object_tostring (obj), 0, NULL, 0) != 0) { ucl_schema_create_error (err, UCL_SCHEMA_CONSTRAINT, obj, "string doesn't match regexp %s", ucl_object_tostring (elt)); ret = false; } regfree (&re); } #endif } return ret; }
int64_t pkg_object_int(const pkg_object *o) { if (o == NULL || o->type != UCL_INT) return (0); return (ucl_object_toint(o)); }
/** * Emit a single element * @param obj object * @param buf buffer */ static void ucl_elt_write_json (ucl_object_t *obj, struct ucl_emitter_functions *func, unsigned int tabs, bool start_tabs, bool compact) { bool flag; switch (obj->type) { case UCL_INT: if (start_tabs) { ucl_add_tabs (func, tabs, compact); } func->ucl_emitter_append_int (ucl_object_toint (obj), func->ud); break; case UCL_FLOAT: case UCL_TIME: if (start_tabs) { ucl_add_tabs (func, tabs, compact); } func->ucl_emitter_append_double (ucl_object_todouble (obj), func->ud); break; case UCL_BOOLEAN: if (start_tabs) { ucl_add_tabs (func, tabs, compact); } flag = ucl_object_toboolean (obj); if (flag) { func->ucl_emitter_append_len ("true", 4, func->ud); } else { func->ucl_emitter_append_len ("false", 5, func->ud); } break; case UCL_STRING: if (start_tabs) { ucl_add_tabs (func, tabs, compact); } ucl_elt_string_write_json (obj->value.sv, obj->len, func); break; case UCL_NULL: if (start_tabs) { ucl_add_tabs (func, tabs, compact); } func->ucl_emitter_append_len ("null", 4, func->ud); break; case UCL_OBJECT: ucl_elt_obj_write_json (obj, func, tabs, start_tabs, compact); break; case UCL_ARRAY: ucl_elt_array_write_json (obj->value.av, func, tabs, start_tabs, compact); break; case UCL_USERDATA: break; } }
static PyObject * _basic_ucl_type (ucl_object_t const *obj) { switch (obj->type) { case UCL_INT: return Py_BuildValue ("L", (long long)ucl_object_toint (obj)); case UCL_FLOAT: return Py_BuildValue ("d", ucl_object_todouble (obj)); case UCL_STRING: return Py_BuildValue ("s", ucl_object_tostring (obj)); case UCL_BOOLEAN: return ucl_object_toboolean (obj) ? Py_True : Py_False; case UCL_TIME: return Py_BuildValue ("d", ucl_object_todouble (obj)); } return NULL; }
/* * snprintkeys writes the value contained in obj to dst. */ static int snprintval(char *dst, size_t size, ucl_object_t const *obj) { switch (ucl_object_type(obj)) { case UCL_INT: return snprintf(dst, size, "%" PRId64, ucl_object_toint(obj)); case UCL_FLOAT: case UCL_TIME: return snprintf(dst, size, "%0.10f", ucl_object_todouble(obj)); case UCL_STRING: return snprintf(dst, size, "%s", ucl_object_tostring(obj)); case UCL_BOOLEAN: return snprintf(dst, size, "%s", ucl_object_toboolean(obj) ? "true": "false"); default: *dst = '\0'; return 0; } }
static int pkg_set_dirs_from_object(struct pkg *pkg, ucl_object_t *obj) { ucl_object_t *cur; ucl_object_iter_t it = NULL; const char *uname = NULL; const char *gname = NULL; void *set; mode_t perm = 0; bool try = false; struct sbuf *dirname = NULL; const char *key, *okey; okey = ucl_object_key(obj); if (okey == NULL) return (EPKG_FATAL); urldecode(okey, &dirname); while ((cur = ucl_iterate_object(obj, &it, true))) { key = ucl_object_key(cur); if (key == NULL) continue; if (!strcasecmp(key, "uname") && cur->type == UCL_STRING) uname = ucl_object_tostring(cur); else if (!strcasecmp(key, "gname") && cur->type == UCL_STRING) gname = ucl_object_tostring(cur); else if (!strcasecmp(key, "perm") && (cur->type == UCL_STRING || cur->type == UCL_INT)) { if ((set = setmode(ucl_object_tostring_forced(cur))) == NULL) pkg_emit_error("Not a valid mode: %s", ucl_object_tostring(cur)); else perm = getmode(set, 0); } else if (!strcasecmp(key, "try") && cur->type == UCL_BOOLEAN) { try = ucl_object_toint(cur); } else { pkg_emit_error("Skipping unknown key for dir(%s): %s", sbuf_data(dirname), key); } }
gint dkim_module_config (struct rspamd_config *cfg) { const ucl_object_t *value; gint res = TRUE, cb_id = -1, check_id = -1; guint cache_size; gboolean got_trusted = FALSE; if (!rspamd_config_is_module_enabled (cfg, "dkim")) { return TRUE; } dkim_module_ctx->whitelist_ip = radix_create_compressed (); if ((value = rspamd_config_get_module_opt (cfg, "dkim", "symbol_reject")) != NULL) { dkim_module_ctx->symbol_reject = ucl_obj_tostring (value); } else { dkim_module_ctx->symbol_reject = DEFAULT_SYMBOL_REJECT; } if ((value = rspamd_config_get_module_opt (cfg, "dkim", "symbol_tempfail")) != NULL) { dkim_module_ctx->symbol_tempfail = ucl_obj_tostring (value); } else { dkim_module_ctx->symbol_tempfail = DEFAULT_SYMBOL_TEMPFAIL; } if ((value = rspamd_config_get_module_opt (cfg, "dkim", "symbol_allow")) != NULL) { dkim_module_ctx->symbol_allow = ucl_obj_tostring (value); } else { dkim_module_ctx->symbol_allow = DEFAULT_SYMBOL_ALLOW; } if ((value = rspamd_config_get_module_opt (cfg, "dkim", "symbol_na")) != NULL) { dkim_module_ctx->symbol_na = ucl_obj_tostring (value); } else { dkim_module_ctx->symbol_na = DEFAULT_SYMBOL_NA; } if ((value = rspamd_config_get_module_opt (cfg, "dkim", "dkim_cache_size")) != NULL) { cache_size = ucl_obj_toint (value); } else { cache_size = DEFAULT_CACHE_SIZE; } if ((value = rspamd_config_get_module_opt (cfg, "dkim", "time_jitter")) != NULL) { dkim_module_ctx->time_jitter = ucl_obj_todouble (value); } else { dkim_module_ctx->time_jitter = DEFAULT_TIME_JITTER; } if ((value = rspamd_config_get_module_opt (cfg, "dkim", "max_sigs")) != NULL) { dkim_module_ctx->max_sigs = ucl_object_toint (value); } if ((value = rspamd_config_get_module_opt (cfg, "dkim", "whitelist")) != NULL) { rspamd_config_radix_from_ucl (cfg, value, "DKIM whitelist", &dkim_module_ctx->whitelist_ip, NULL); } if ((value = rspamd_config_get_module_opt (cfg, "dkim", "domains")) != NULL) { if (!rspamd_map_add_from_ucl (cfg, value, "DKIM domains", rspamd_kv_list_read, rspamd_kv_list_fin, (void **)&dkim_module_ctx->dkim_domains)) { msg_warn_config ("cannot load dkim domains list from %s", ucl_obj_tostring (value)); } else { got_trusted = TRUE; } } if (!got_trusted && (value = rspamd_config_get_module_opt (cfg, "dkim", "trusted_domains")) != NULL) { if (!rspamd_map_add_from_ucl (cfg, value, "DKIM domains", rspamd_kv_list_read, rspamd_kv_list_fin, (void **)&dkim_module_ctx->dkim_domains)) { msg_warn_config ("cannot load dkim domains list from %s", ucl_obj_tostring (value)); } else { got_trusted = TRUE; } } if ((value = rspamd_config_get_module_opt (cfg, "dkim", "strict_multiplier")) != NULL) { dkim_module_ctx->strict_multiplier = ucl_obj_toint (value); } else { dkim_module_ctx->strict_multiplier = 1; } if ((value = rspamd_config_get_module_opt (cfg, "dkim", "trusted_only")) != NULL) { dkim_module_ctx->trusted_only = ucl_obj_toboolean (value); } else { dkim_module_ctx->trusted_only = FALSE; } if ((value = rspamd_config_get_module_opt (cfg, "dkim", "skip_multi")) != NULL) { dkim_module_ctx->skip_multi = ucl_obj_toboolean (value); } else { dkim_module_ctx->skip_multi = FALSE; } if (dkim_module_ctx->trusted_only && !got_trusted) { msg_err_config ( "trusted_only option is set and no trusted domains are defined; disabling dkim module completely as it is useless in this case"); } else { cb_id = rspamd_symbols_cache_add_symbol (cfg->cache, dkim_module_ctx->symbol_reject, 0, dkim_symbol_callback, NULL, SYMBOL_TYPE_NORMAL|SYMBOL_TYPE_FINE, -1); rspamd_symbols_cache_add_symbol (cfg->cache, dkim_module_ctx->symbol_na, 0, NULL, NULL, SYMBOL_TYPE_VIRTUAL|SYMBOL_TYPE_FINE, cb_id); rspamd_symbols_cache_add_symbol (cfg->cache, dkim_module_ctx->symbol_tempfail, 0, NULL, NULL, SYMBOL_TYPE_VIRTUAL|SYMBOL_TYPE_FINE, cb_id); rspamd_symbols_cache_add_symbol (cfg->cache, dkim_module_ctx->symbol_allow, 0, NULL, NULL, SYMBOL_TYPE_VIRTUAL|SYMBOL_TYPE_FINE, cb_id); dkim_module_ctx->dkim_hash = rspamd_lru_hash_new ( cache_size, g_free, /* Keys are just C-strings */ dkim_module_key_dtor); msg_info_config ("init internal dkim module"); #ifndef HAVE_OPENSSL msg_warn_config ( "openssl is not found so dkim rsa check is disabled, only check body hash, it is NOT safe to trust these results"); #endif } if ((value = rspamd_config_get_module_opt (cfg, "dkim", "sign_condition")) != NULL) { const gchar *lua_script; lua_script = ucl_object_tostring (value); if (lua_script) { if (luaL_dostring (cfg->lua_state, lua_script) != 0) { msg_err_config ("cannot execute lua script for fuzzy " "learn condition: %s", lua_tostring (cfg->lua_state, -1)); } else { if (lua_type (cfg->lua_state, -1) == LUA_TFUNCTION) { dkim_module_ctx->sign_condition_ref = luaL_ref (cfg->lua_state, LUA_REGISTRYINDEX); dkim_module_ctx->dkim_sign_hash = rspamd_lru_hash_new ( 128, g_free, /* Keys are just C-strings */ (GDestroyNotify)rspamd_dkim_sign_key_unref); check_id = rspamd_symbols_cache_add_symbol (cfg->cache, "DKIM_SIGN", 0, dkim_sign_callback, NULL, SYMBOL_TYPE_CALLBACK|SYMBOL_TYPE_FINE, -1); msg_info_config ("init condition script for DKIM signing"); /* * Allow dkim signing to be executed only after dkim check */ if (cb_id > 0) { rspamd_symbols_cache_add_delayed_dependency (cfg->cache, "DKIM_SIGN", dkim_module_ctx->symbol_reject); } rspamd_config_add_metric_symbol (cfg, DEFAULT_METRIC, "DKIM_SIGN", 0.0, "DKIM signature fake symbol", "dkim", RSPAMD_SYMBOL_FLAG_IGNORE, 1); } else { msg_err_config ("lua script must return " "function(task) and not %s", lua_typename (cfg->lua_state, lua_type (cfg->lua_state, -1))); } } } } return res; }
static void add_repo(const ucl_object_t *obj, struct pkg_repo *r, const char *rname, pkg_init_flags flags) { const ucl_object_t *cur, *enabled; ucl_object_iter_t it = NULL; bool enable = true; const char *url = NULL, *pubkey = NULL, *mirror_type = NULL; const char *signature_type = NULL, *fingerprints = NULL; const char *key; const char *type = NULL; int use_ipvx = 0; pkg_debug(1, "PkgConfig: parsing repository object %s", rname); enabled = ucl_object_find_key(obj, "enabled"); if (enabled == NULL) enabled = ucl_object_find_key(obj, "ENABLED"); if (enabled != NULL) { enable = ucl_object_toboolean(enabled); if (!enable && r == NULL) { pkg_debug(1, "PkgConfig: skipping disabled repo %s", rname); return; } else if (!enable && r != NULL) { /* * We basically want to remove the existing repo r and * forget all stuff parsed */ pkg_debug(1, "PkgConfig: disabling repo %s", rname); HASH_DEL(repos, r); pkg_repo_free(r); return; } } while ((cur = ucl_iterate_object(obj, &it, true))) { key = ucl_object_key(cur); if (key == NULL) continue; if (strcasecmp(key, "url") == 0) { if (cur->type != UCL_STRING) { pkg_emit_error("Expecting a string for the " "'%s' key of the '%s' repo", key, rname); return; } url = ucl_object_tostring(cur); } else if (strcasecmp(key, "pubkey") == 0) { if (cur->type != UCL_STRING) { pkg_emit_error("Expecting a string for the " "'%s' key of the '%s' repo", key, rname); return; } pubkey = ucl_object_tostring(cur); } else if (strcasecmp(key, "mirror_type") == 0) { if (cur->type != UCL_STRING) { pkg_emit_error("Expecting a string for the " "'%s' key of the '%s' repo", key, rname); return; } mirror_type = ucl_object_tostring(cur); } else if (strcasecmp(key, "signature_type") == 0) { if (cur->type != UCL_STRING) { pkg_emit_error("Expecting a string for the " "'%s' key of the '%s' repo", key, rname); return; } signature_type = ucl_object_tostring(cur); } else if (strcasecmp(key, "fingerprints") == 0) { if (cur->type != UCL_STRING) { pkg_emit_error("Expecting a string for the " "'%s' key of the '%s' repo", key, rname); return; } fingerprints = ucl_object_tostring(cur); } else if (strcasecmp(key, "type") == 0) { if (cur->type != UCL_STRING) { pkg_emit_error("Expecting a string for the " "'%s' key of the '%s' repo", key, rname); return; } type = ucl_object_tostring(cur); } else if (strcasecmp(key, "ip_version") == 0) { if (cur->type != UCL_INT) { pkg_emit_error("Expecting a integer for the " "'%s' key of the '%s' repo", key, rname); return; } use_ipvx = ucl_object_toint(cur); if (use_ipvx != 4 && use_ipvx != 6) use_ipvx = 0; } } if (r == NULL && url == NULL) { pkg_debug(1, "No repo and no url for %s", rname); return; } if (r == NULL) r = pkg_repo_new(rname, url, type); else pkg_repo_overwrite(r, rname, url, type); if (signature_type != NULL) { if (strcasecmp(signature_type, "pubkey") == 0) r->signature_type = SIG_PUBKEY; else if (strcasecmp(signature_type, "fingerprints") == 0) r->signature_type = SIG_FINGERPRINT; else r->signature_type = SIG_NONE; } if (fingerprints != NULL) { free(r->fingerprints); r->fingerprints = strdup(fingerprints); } if (pubkey != NULL) { free(r->pubkey); r->pubkey = strdup(pubkey); } r->enable = enable; if (mirror_type != NULL) { if (strcasecmp(mirror_type, "srv") == 0) r->mirror_type = SRV; else if (strcasecmp(mirror_type, "http") == 0) r->mirror_type = HTTP; else r->mirror_type = NOMIRROR; } if ((flags & PKG_INIT_FLAG_USE_IPV4) == PKG_INIT_FLAG_USE_IPV4) use_ipvx = 4; else if ((flags & PKG_INIT_FLAG_USE_IPV6) == PKG_INIT_FLAG_USE_IPV6) use_ipvx = 6; if (use_ipvx != 4 && use_ipvx != 6) use_ipvx = pkg_object_int(pkg_config_get("IP_VERSION")); if (use_ipvx == 4) r->flags = REPO_FLAGS_USE_IPV4; else if (use_ipvx == 6) r->flags = REPO_FLAGS_USE_IPV6; }
void ucl_obj_dump (const ucl_object_t *obj, unsigned int shift) { int num = shift * 4 + 5; char *pre = (char *) malloc (num * sizeof(char)); const ucl_object_t *cur, *tmp; ucl_object_iter_t it = NULL, it_obj = NULL; pre[--num] = 0x00; while (num--) pre[num] = 0x20; tmp = obj; while ((obj = ucl_iterate_object (tmp, &it, false))) { printf ("%sucl object address: %p\n", pre + 4, obj); if (obj->key != NULL) { printf ("%skey: \"%s\"\n", pre, ucl_object_key (obj)); } printf ("%sref: %u\n", pre, obj->ref); printf ("%slen: %u\n", pre, obj->len); printf ("%sprev: %p\n", pre, obj->prev); printf ("%snext: %p\n", pre, obj->next); if (obj->type == UCL_OBJECT) { printf ("%stype: UCL_OBJECT\n", pre); printf ("%svalue: %p\n", pre, obj->value.ov); it_obj = NULL; while ((cur = ucl_iterate_object (obj, &it_obj, true))) { ucl_obj_dump (cur, shift + 2); } } else if (obj->type == UCL_ARRAY) { printf ("%stype: UCL_ARRAY\n", pre); printf ("%svalue: %p\n", pre, obj->value.av); it_obj = NULL; while ((cur = ucl_iterate_object (obj, &it_obj, true))) { ucl_obj_dump (cur, shift + 2); } } else if (obj->type == UCL_INT) { printf ("%stype: UCL_INT\n", pre); printf ("%svalue: %jd\n", pre, (intmax_t)ucl_object_toint (obj)); } else if (obj->type == UCL_FLOAT) { printf ("%stype: UCL_FLOAT\n", pre); printf ("%svalue: %f\n", pre, ucl_object_todouble (obj)); } else if (obj->type == UCL_STRING) { printf ("%stype: UCL_STRING\n", pre); printf ("%svalue: \"%s\"\n", pre, ucl_object_tostring (obj)); } else if (obj->type == UCL_BOOLEAN) { printf ("%stype: UCL_BOOLEAN\n", pre); printf ("%svalue: %s\n", pre, ucl_object_tostring_forced (obj)); } else if (obj->type == UCL_TIME) { printf ("%stype: UCL_TIME\n", pre); printf ("%svalue: %f\n", pre, ucl_object_todouble (obj)); } else if (obj->type == UCL_USERDATA) { printf ("%stype: UCL_USERDATA\n", pre); printf ("%svalue: %p\n", pre, obj->value.ud); } } free (pre); }
static int pkg_int(struct pkg *pkg, ucl_object_t *obj, int attr) { return (pkg_set(pkg, attr, ucl_object_toint(obj))); }
static struct rspamd_osb_tokenizer_config * rspamd_tokenizer_osb_config_from_ucl (rspamd_mempool_t * pool, const ucl_object_t *obj) { const ucl_object_t *elt; struct rspamd_osb_tokenizer_config *cf, *def; guchar *key = NULL; gsize keylen; if (pool != NULL) { cf = rspamd_mempool_alloc0 (pool, sizeof (*cf)); } else { cf = g_malloc0 (sizeof (*cf)); } /* Use default config */ def = rspamd_tokenizer_osb_default_config (); memcpy (cf, def, sizeof (*cf)); elt = ucl_object_lookup (obj, "hash"); if (elt != NULL && ucl_object_type (elt) == UCL_STRING) { if (g_ascii_strncasecmp (ucl_object_tostring (elt), "xxh", 3) == 0) { cf->ht = RSPAMD_OSB_HASH_XXHASH; elt = ucl_object_lookup (obj, "seed"); if (elt != NULL && ucl_object_type (elt) == UCL_INT) { cf->seed = ucl_object_toint (elt); } } else if (g_ascii_strncasecmp (ucl_object_tostring (elt), "sip", 3) == 0) { cf->ht = RSPAMD_OSB_HASH_SIPHASH; elt = ucl_object_lookup (obj, "key"); if (elt != NULL && ucl_object_type (elt) == UCL_STRING) { key = rspamd_decode_base32 (ucl_object_tostring (elt), 0, &keylen); if (keylen < sizeof (rspamd_sipkey_t)) { msg_warn ("siphash key is too short: %z", keylen); g_free (key); } else { memcpy (cf->sk, key, sizeof (cf->sk)); g_free (key); } } else { msg_warn_pool ("siphash cannot be used without key"); } } } else { elt = ucl_object_lookup (obj, "compat"); if (elt != NULL && ucl_object_toboolean (elt)) { cf->ht = RSPAMD_OSB_HASH_COMPAT; } } elt = ucl_object_lookup (obj, "window"); if (elt != NULL && ucl_object_type (elt) == UCL_INT) { cf->window_size = ucl_object_toint (elt); if (cf->window_size > DEFAULT_FEATURE_WINDOW_SIZE * 4) { msg_err_pool ("too large window size: %d", cf->window_size); cf->window_size = DEFAULT_FEATURE_WINDOW_SIZE; } } return cf; }
int main (int argc, char **argv) { ucl_object_t *obj, *cur, *ar, *ref; const ucl_object_t *found; FILE *out; unsigned char *emitted; const char *fname_out = NULL; int ret = 0; switch (argc) { case 2: fname_out = argv[1]; break; } if (fname_out != NULL) { out = fopen (fname_out, "w"); if (out == NULL) { exit (-errno); } } else { out = stdout; } obj = ucl_object_typed_new (UCL_OBJECT); /* Create some strings */ cur = ucl_object_fromstring_common (" test string ", 0, UCL_STRING_TRIM); ucl_object_insert_key (obj, cur, "key1", 0, false); cur = ucl_object_fromstring_common (" test \nstring\n ", 0, UCL_STRING_TRIM | UCL_STRING_ESCAPE); ucl_object_insert_key (obj, cur, "key2", 0, false); cur = ucl_object_fromstring_common (" test string \n", 0, 0); ucl_object_insert_key (obj, cur, "key3", 0, false); /* Array of numbers */ ar = ucl_object_typed_new (UCL_ARRAY); cur = ucl_object_fromint (10); ucl_array_append (ar, cur); cur = ucl_object_fromdouble (10.1); ucl_array_append (ar, cur); cur = ucl_object_fromdouble (9.999); ucl_array_prepend (ar, cur); /* Removing from an array */ cur = ucl_object_fromdouble (1.0); ucl_array_append (ar, cur); cur = ucl_array_delete (ar, cur); assert (ucl_object_todouble (cur) == 1.0); ucl_object_unref (cur); cur = ucl_object_fromdouble (2.0); ucl_array_append (ar, cur); cur = ucl_array_pop_last (ar); assert (ucl_object_todouble (cur) == 2.0); ucl_object_unref (cur); cur = ucl_object_fromdouble (3.0); ucl_array_prepend (ar, cur); cur = ucl_array_pop_first (ar); assert (ucl_object_todouble (cur) == 3.0); ucl_object_unref (cur); ucl_object_insert_key (obj, ar, "key4", 0, false); cur = ucl_object_frombool (true); /* Ref object to test refcounts */ ref = ucl_object_ref (cur); ucl_object_insert_key (obj, cur, "key4", 0, false); /* Empty strings */ cur = ucl_object_fromstring_common (" ", 0, UCL_STRING_TRIM); ucl_object_insert_key (obj, cur, "key5", 0, false); cur = ucl_object_fromstring_common ("", 0, UCL_STRING_ESCAPE); ucl_object_insert_key (obj, cur, "key6", 0, false); cur = ucl_object_fromstring_common (" \n", 0, UCL_STRING_ESCAPE); ucl_object_insert_key (obj, cur, "key7", 0, false); /* Numbers and booleans */ cur = ucl_object_fromstring_common ("1mb", 0, UCL_STRING_ESCAPE | UCL_STRING_PARSE); ucl_object_insert_key (obj, cur, "key8", 0, false); cur = ucl_object_fromstring_common ("3.14", 0, UCL_STRING_PARSE); ucl_object_insert_key (obj, cur, "key9", 0, false); cur = ucl_object_fromstring_common ("true", 0, UCL_STRING_PARSE); ucl_object_insert_key (obj, cur, "key10", 0, false); cur = ucl_object_fromstring_common (" off ", 0, UCL_STRING_PARSE | UCL_STRING_TRIM); ucl_object_insert_key (obj, cur, "key11", 0, false); cur = ucl_object_fromstring_common ("*****@*****.**", 0, UCL_STRING_PARSE_INT); ucl_object_insert_key (obj, cur, "key12", 0, false); cur = ucl_object_fromstring_common ("#test", 0, UCL_STRING_PARSE_INT); ucl_object_insert_key (obj, cur, "key13", 0, false); cur = ucl_object_frombool (true); ucl_object_insert_key (obj, cur, "k=3", 0, false); /* Try to find using path */ /* Should exist */ found = ucl_lookup_path (obj, "key4.1"); assert (found != NULL && ucl_object_toint (found) == 10); /* . should be ignored */ found = ucl_lookup_path (obj, ".key4.1"); assert (found != NULL && ucl_object_toint (found) == 10); /* moar dots... */ found = ucl_lookup_path (obj, ".key4........1..."); assert (found != NULL && ucl_object_toint (found) == 10); /* No such index */ found = ucl_lookup_path (obj, ".key4.3"); assert (found == NULL); /* No such key */ found = ucl_lookup_path (obj, "key9..key1"); assert (found == NULL); emitted = ucl_object_emit (obj, UCL_EMIT_CONFIG); fprintf (out, "%s\n", emitted); ucl_object_unref (obj); if (emitted != NULL) { free (emitted); } fclose (out); /* Ref should still be accessible */ ref->value.iv = 100500; ucl_object_unref (ref); return ret; }
int main (int argc, char **argv) { ucl_object_t *obj, *cur, *ar, *ar1, *ref, *test_obj, *comments; ucl_object_iter_t it; const ucl_object_t *found, *it_obj, *test; struct ucl_emitter_functions *fn; FILE *out; unsigned char *emitted; const char *fname_out = NULL; struct ucl_parser *parser; int ret = 0; switch (argc) { case 2: fname_out = argv[1]; break; } if (fname_out != NULL) { out = fopen (fname_out, "w"); if (out == NULL) { exit (-errno); } } else { out = stdout; } obj = ucl_object_typed_new (UCL_OBJECT); /* Keys replacing */ cur = ucl_object_fromstring_common ("value1", 0, UCL_STRING_TRIM); ucl_object_insert_key (obj, cur, "key0", 0, false); cur = ucl_object_fromdouble (0.1); assert (ucl_object_replace_key (obj, cur, "key0", 0, false)); /* Create some strings */ cur = ucl_object_fromstring_common (" test string ", 0, UCL_STRING_TRIM); ucl_object_insert_key (obj, cur, "key1", 0, false); cur = ucl_object_fromstring_common (" test \nstring\n\r\n\b\t\f\\\" ", 0, UCL_STRING_TRIM | UCL_STRING_ESCAPE); ucl_object_insert_key (obj, cur, "key2", 0, false); cur = ucl_object_fromstring_common (" test string \n", 0, 0); ucl_object_insert_key (obj, cur, "key3", 0, false); /* Array of numbers */ ar = ucl_object_typed_new (UCL_ARRAY); cur = ucl_object_fromint (10); ucl_array_append (ar, cur); assert (ucl_array_index_of (ar, cur) == 0); cur = ucl_object_fromdouble (10.1); ucl_array_append (ar, cur); assert (ucl_array_index_of (ar, cur) == 1); cur = ucl_object_fromdouble (9.999); ucl_array_prepend (ar, cur); assert (ucl_array_index_of (ar, cur) == 0); ar1 = ucl_object_copy (ar); cur = ucl_object_fromstring ("abc"); ucl_array_prepend (ar1, cur); cur = ucl_object_fromstring ("cde"); ucl_array_prepend (ar1, cur); cur = ucl_object_fromstring ("аАаБаВ"); /* UTF8 */ ucl_array_prepend (ar1, cur); cur = ucl_object_fromstring ("ааБаВ"); /* UTF8 */ ucl_array_prepend (ar1, cur); /* * This is ususally broken or fragile as utf collate is far from perfect cur = ucl_object_fromstring ("баБаВ"); ucl_array_prepend (ar1, cur); cur = ucl_object_fromstring ("ааБаВ"); // hello to @bapt ucl_array_prepend (ar1, cur); */ cur = ucl_object_fromstring ("№"); /* everybody likes emoji in the code */ ucl_array_prepend (ar1, cur); ucl_object_array_sort (ar1, ucl_object_compare_qsort); /* Removing from an array */ cur = ucl_object_fromdouble (1.0); ucl_array_append (ar, cur); cur = ucl_array_delete (ar, cur); assert (ucl_object_todouble (cur) == 1.0); ucl_object_unref (cur); cur = ucl_object_fromdouble (2.0); ucl_array_append (ar, cur); cur = ucl_array_pop_last (ar); assert (ucl_object_todouble (cur) == 2.0); ucl_object_unref (cur); cur = ucl_object_fromdouble (3.0); ucl_array_prepend (ar, cur); cur = ucl_array_pop_first (ar); assert (ucl_object_todouble (cur) == 3.0); ucl_object_unref (cur); ucl_object_insert_key (obj, ar, "key4", 0, false); cur = ucl_object_frombool (true); /* Ref object to test refcounts */ ref = ucl_object_ref (cur); ucl_object_insert_key (obj, cur, "key4", 0, false); /* Empty strings */ cur = ucl_object_fromstring_common (" ", 0, UCL_STRING_TRIM); ucl_object_insert_key (obj, cur, "key5", 0, false); cur = ucl_object_fromstring_common ("", 0, UCL_STRING_ESCAPE); ucl_object_insert_key (obj, cur, "key6", 0, false); cur = ucl_object_fromstring_common (" \n", 0, UCL_STRING_ESCAPE); ucl_object_insert_key (obj, cur, "key7", 0, false); /* Numbers and booleans */ cur = ucl_object_fromstring_common ("1mb", 0, UCL_STRING_ESCAPE | UCL_STRING_PARSE); ucl_object_insert_key (obj, cur, "key8", 0, false); cur = ucl_object_fromstring_common ("3.14", 0, UCL_STRING_PARSE); ucl_object_insert_key (obj, cur, "key9", 0, false); cur = ucl_object_fromstring_common ("true", 0, UCL_STRING_PARSE); ucl_object_insert_key (obj, cur, "key10", 0, false); cur = ucl_object_fromstring_common (" off ", 0, UCL_STRING_PARSE | UCL_STRING_TRIM); ucl_object_insert_key (obj, cur, "key11", 0, false); cur = ucl_object_fromstring_common ("*****@*****.**", 0, UCL_STRING_PARSE_INT); ucl_object_insert_key (obj, cur, "key12", 0, false); cur = ucl_object_fromstring_common ("#test", 0, UCL_STRING_PARSE_INT); ucl_object_insert_key (obj, cur, "key13", 0, false); cur = ucl_object_frombool (true); ucl_object_insert_key (obj, cur, "k=3", 0, false); ucl_object_insert_key (obj, ar1, "key14", 0, false); cur = ucl_object_new_userdata (ud_dtor, ud_emit, NULL); ucl_object_insert_key (obj, cur, "key15", 0, false); /* More tests for keys */ cur = ucl_object_fromlstring ("test", 3); ucl_object_insert_key (obj, cur, "key16", 0, false); test = ucl_object_lookup_any (obj, "key100", "key200", "key300", "key16", NULL); assert (test == cur); test = ucl_object_lookup_len (obj, "key160", 5); assert (test == cur); cur = ucl_object_pop_key (obj, "key16"); assert (test == cur); test = ucl_object_pop_key (obj, "key16"); assert (test == NULL); test = ucl_object_lookup_len (obj, "key160", 5); assert (test == NULL); /* Objects merging tests */ test_obj = ucl_object_new_full (UCL_OBJECT, 2); ucl_object_insert_key (test_obj, cur, "key16", 0, true); ucl_object_merge (obj, test_obj, true); ucl_object_unref (test_obj); /* Array merging test */ test_obj = ucl_object_new_full (UCL_ARRAY, 3); ucl_array_append (test_obj, ucl_object_fromstring ("test")); ucl_array_merge (test_obj, ar1, false); ucl_object_insert_key (obj, test_obj, "key17", 0, true); /* Object deletion */ cur = ucl_object_fromstring ("test"); ucl_object_insert_key (obj, cur, "key18", 0, true); assert (ucl_object_delete_key (obj, "key18")); assert (!ucl_object_delete_key (obj, "key18")); cur = ucl_object_fromlstring ("test", 4); ucl_object_insert_key (obj, cur, "key18\0\0", 7, true); assert (ucl_object_lookup_len (obj, "key18\0\0", 7) == cur); assert (ucl_object_lookup (obj, "key18") == NULL); assert (ucl_object_lookup_len (obj, "key18\0\1", 7) == NULL); assert (ucl_object_delete_keyl (obj, "key18\0\0", 7)); /* Comments */ comments = ucl_object_typed_new (UCL_OBJECT); found = ucl_object_lookup (obj, "key17"); test = ucl_object_lookup (obj, "key16"); ucl_comments_add (comments, found, "# test comment"); assert (ucl_comments_find (comments, found) != NULL); assert (ucl_comments_find (comments, test) == NULL); ucl_comments_move (comments, found, test); assert (ucl_comments_find (comments, found) == NULL); assert (ucl_comments_find (comments, test) != NULL); /* Array replace */ ar1 = ucl_object_typed_new (UCL_ARRAY); cur = ucl_object_fromstring ("test"); cur = ucl_elt_append (cur, ucl_object_fromstring ("test1")); ucl_array_append (ar1, cur); test = ucl_array_replace_index (ar1, ucl_object_fromstring ("test2"), 0); assert (test == cur); /* Try to find using path */ /* Should exist */ found = ucl_object_lookup_path (obj, "key4.1"); assert (found != NULL && ucl_object_toint (found) == 10); /* . should be ignored */ found = ucl_object_lookup_path (obj, ".key4.1"); assert (found != NULL && ucl_object_toint (found) == 10); /* moar dots... */ found = ucl_object_lookup_path (obj, ".key4........1..."); assert (found != NULL && ucl_object_toint (found) == 10); /* No such index */ found = ucl_object_lookup_path (obj, ".key4.3"); assert (found == NULL); /* No such key */ found = ucl_object_lookup_path (obj, "key9..key1"); assert (found == NULL); /* Test iteration */ it = ucl_object_iterate_new (obj); it_obj = ucl_object_iterate_safe (it, true); /* key0 = 0.1 */ assert (ucl_object_type (it_obj) == UCL_FLOAT); it_obj = ucl_object_iterate_safe (it, true); /* key1 = "" */ assert (ucl_object_type (it_obj) == UCL_STRING); it_obj = ucl_object_iterate_safe (it, true); /* key2 = "" */ assert (ucl_object_type (it_obj) == UCL_STRING); it_obj = ucl_object_iterate_safe (it, true); /* key3 = "" */ assert (ucl_object_type (it_obj) == UCL_STRING); it_obj = ucl_object_iterate_safe (it, true); /* key4 = ([float, int, float], boolean) */ ucl_object_iterate_reset (it, it_obj); it_obj = ucl_object_iterate_safe (it, true); assert (ucl_object_type (it_obj) == UCL_FLOAT); it_obj = ucl_object_iterate_safe (it, true); assert (ucl_object_type (it_obj) == UCL_INT); it_obj = ucl_object_iterate_safe (it, true); assert (ucl_object_type (it_obj) == UCL_FLOAT); it_obj = ucl_object_iterate_safe (it, true); assert (ucl_object_type (it_obj) == UCL_BOOLEAN); ucl_object_iterate_free (it); fn = ucl_object_emit_memory_funcs (&emitted); assert (ucl_object_emit_full (obj, UCL_EMIT_CONFIG, fn, comments)); fprintf (out, "%s\n", emitted); ucl_object_emit_funcs_free (fn); ucl_object_unref (obj); ucl_object_unref (comments); parser = ucl_parser_new (UCL_PARSER_NO_IMPLICIT_ARRAYS); if (ucl_parser_add_chunk_full (parser, emitted, strlen (emitted), 3, UCL_DUPLICATE_ERROR, UCL_PARSE_UCL)) { /* Should fail due to duplicate */ assert (0); } else { assert (ucl_parser_get_error (parser) != NULL); ucl_parser_clear_error (parser); ucl_parser_free (parser); parser = ucl_parser_new (0); ucl_parser_add_chunk_full (parser, emitted, strlen (emitted), 3, UCL_DUPLICATE_MERGE, UCL_PARSE_UCL); } assert (ucl_parser_get_column (parser) == 0); assert (ucl_parser_get_linenum (parser) != 0); ucl_parser_clear_error (parser); assert (ucl_parser_get_error_code (parser) == 0); obj = ucl_parser_get_object (parser); ucl_parser_free (parser); ucl_object_free (obj); if (emitted != NULL) { free (emitted); } fclose (out); /* Ref should still be accessible */ ref->value.iv = 100500; ucl_object_unref (ref); return ret; }
static gboolean rspamd_symbols_cache_load_items (struct symbols_cache *cache, const gchar *name) { struct rspamd_symbols_cache_header *hdr; struct stat st; struct ucl_parser *parser; ucl_object_t *top; const ucl_object_t *cur, *elt; ucl_object_iter_t it; struct cache_item *item, *parent; const guchar *p; gint fd; gpointer map; double w; fd = open (name, O_RDONLY); if (fd == -1) { msg_info ("cannot open file %s, error %d, %s", name, errno, strerror (errno)); return FALSE; } if (fstat (fd, &st) == -1) { close (fd); msg_info ("cannot stat file %s, error %d, %s", name, errno, strerror (errno)); return FALSE; } if (st.st_size < (gint)sizeof (*hdr)) { close (fd); errno = EINVAL; msg_info ("cannot use file %s, error %d, %s", name, errno, strerror (errno)); return FALSE; } map = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); if (map == MAP_FAILED) { close (fd); msg_info ("cannot mmap file %s, error %d, %s", name, errno, strerror (errno)); return FALSE; } close (fd); hdr = map; if (memcmp (hdr->magic, rspamd_symbols_cache_magic, sizeof (rspamd_symbols_cache_magic)) != 0) { msg_info ("cannot use file %s, bad magic", name); munmap (map, st.st_size); return FALSE; } parser = ucl_parser_new (0); p = (const guchar *)(hdr + 1); if (!ucl_parser_add_chunk (parser, p, st.st_size - sizeof (*hdr))) { msg_info ("cannot use file %s, cannot parse: %s", name, ucl_parser_get_error (parser)); munmap (map, st.st_size); ucl_parser_free (parser); return FALSE; } top = ucl_parser_get_object (parser); munmap (map, st.st_size); ucl_parser_free (parser); if (top == NULL || ucl_object_type (top) != UCL_OBJECT) { msg_info ("cannot use file %s, bad object", name); ucl_object_unref (top); return FALSE; } it = ucl_object_iterate_new (top); while ((cur = ucl_object_iterate_safe (it, true))) { item = g_hash_table_lookup (cache->items_by_symbol, ucl_object_key (cur)); if (item) { /* Copy saved info */ elt = ucl_object_find_key (cur, "weight"); if (elt) { w = ucl_object_todouble (elt); if (w != 0) { item->weight = w; } } elt = ucl_object_find_key (cur, "time"); if (elt) { item->avg_time = ucl_object_todouble (elt); } elt = ucl_object_find_key (cur, "count"); if (elt) { item->avg_counter = ucl_object_toint (elt); } elt = ucl_object_find_key (cur, "frequency"); if (elt) { item->frequency = ucl_object_toint (elt); } if (item->type == SYMBOL_TYPE_VIRTUAL && item->parent != -1) { g_assert (item->parent < (gint)cache->items_by_id->len); parent = g_ptr_array_index (cache->items_by_id, item->parent); if (parent->weight < item->weight) { parent->weight = item->weight; } /* * We maintain avg_time for virtual symbols equal to the * parent item avg_time */ parent->avg_time = item->avg_time; parent->avg_counter = item->avg_counter; } if (fabs (item->weight) > cache->max_weight) { cache->max_weight = fabs (item->weight); } cache->total_freq += item->frequency; } } ucl_object_iterate_free (it); ucl_object_unref (top); return TRUE; }