Esempio n. 1
0
static void
rspamadm_confighelp_search_word_step (const ucl_object_t *obj,
		ucl_object_t *res,
		const gchar *str,
		gsize len,
		GString *path)
{
	ucl_object_iter_t it = NULL;
	const ucl_object_t *cur, *elt;
	const gchar *dot_pos;

	while ((cur = ucl_object_iterate (obj, &it, true)) != NULL) {
		if (cur->keylen > 0) {
			rspamd_printf_gstring (path, ".%*s", (int) cur->keylen, cur->key);

			if (rspamd_substring_search_caseless (cur->key,
					cur->keylen,
					str,
					len) != -1) {
				ucl_object_insert_key (res, ucl_object_ref (cur),
						path->str, path->len, true);
				goto fin;
			}
		}

		if (ucl_object_type (cur) == UCL_OBJECT) {
			elt = ucl_object_lookup (cur, "data");

			if (elt != NULL && ucl_object_type (elt) == UCL_STRING) {
				if (rspamd_substring_search_caseless (elt->value.sv,
						elt->len,
						str,
						len) != -1) {
					ucl_object_insert_key (res, ucl_object_ref (cur),
							path->str, path->len, true);
					goto fin;
				}
			}

			rspamadm_confighelp_search_word_step (cur, res, str, len, path);
		}

		fin:
		/* Remove the last component of the path */
		dot_pos = strrchr (path->str, '.');

		if (dot_pos) {
			g_string_erase (path, dot_pos - path->str,
					path->len - (dot_pos - path->str));
		}
	}
}
Esempio n. 2
0
ucl_object_t *
rspamd_redis_get_stat (gpointer runtime,
		gpointer ctx)
{
	struct redis_stat_runtime *rt = REDIS_RUNTIME (runtime);
	struct rspamd_redis_stat_elt *st;
	redisAsyncContext *redis;

	if (rt->ctx->stat_elt) {
		st = rt->ctx->stat_elt->ud;

		if (rt->redis) {
			redis = rt->redis;
			rt->redis = NULL;
			redisAsyncFree (redis);
		}

		if (st->stat) {
			return ucl_object_ref (st->stat);
		}
	}

	return NULL;
}
Esempio n. 3
0
bool
merge_recursive(ucl_object_t *top, ucl_object_t *elt, bool copy)
{
    const ucl_object_t *cur;
    ucl_object_iter_t it = NULL;
    ucl_object_t *found = NULL, *cp_obj = NULL;
    bool success = false;

    it = ucl_object_iterate_new(elt);

    while ((cur = ucl_object_iterate_safe(it, false))) {
	cp_obj = ucl_object_ref(cur);
	if (debug > 0) {
	    fprintf(stderr, "DEBUG: Looping over (elt)%s, found key: %s\n",
		ucl_object_key(top), ucl_object_key(cur));
	}
	if (ucl_object_type(cur) == UCL_OBJECT) {
	    found = __DECONST(ucl_object_t *, ucl_object_find_key(top, ucl_object_key(cur)));
	    if (found == NULL) {
		/* new key not found in old object, insert it */
		if (debug > 0) {
		    fprintf(stderr, "DEBUG: unmatched key, inserting: %s into top\n",
			ucl_object_key(cur));
		}
		success = ucl_object_insert_key_merged(top, cp_obj,
		    ucl_object_key(cp_obj), 0, true);
		if (success == false) { return false; }
		continue;
	    }
	    if (debug > 0) {
		fprintf(stderr, "DEBUG: (obj) Found key %s in (top)%s too, merging...\n",
		    ucl_object_key(found), ucl_object_key(top));
	    }
	    success = merge_recursive(found, cp_obj, copy);
	    if (success == false) { return false; }
	} else if (ucl_object_type(cur) == UCL_ARRAY) {
Esempio n. 4
0
int
pkg_ini(const char *path, const char *reposdir, pkg_init_flags flags)
{
	struct ucl_parser *p = NULL;
	size_t i;
	const char *val = NULL;
	const char *buf, *walk, *value, *key, *k;
	const char *evkey = NULL;
	const char *nsname = NULL;
	const char *evpipe = NULL;
	const ucl_object_t *cur, *object;
	ucl_object_t *obj = NULL, *o, *ncfg;
	ucl_object_iter_t it = NULL;
	struct sbuf *ukey = NULL;
	bool fatal_errors = false;

	k = NULL;
	o = NULL;

	pkg_get_myarch(myabi, BUFSIZ);
	pkg_get_myarch_legacy(myabi_legacy, BUFSIZ);
	if (parsed != false) {
		pkg_emit_error("pkg_init() must only be called once");
		return (EPKG_FATAL);
	}

	if (((flags & PKG_INIT_FLAG_USE_IPV4) == PKG_INIT_FLAG_USE_IPV4) &&
	    ((flags & PKG_INIT_FLAG_USE_IPV6) == PKG_INIT_FLAG_USE_IPV6)) {
		pkg_emit_error("Invalid flags for pkg_init()");
		return (EPKG_FATAL);
	}

	config = ucl_object_typed_new(UCL_OBJECT);

	for (i = 0; i < c_size; i++) {
		switch (c[i].type) {
		case PKG_STRING:
			obj = ucl_object_fromstring_common(
			    c[i].def != NULL ? c[i].def : "", 0, UCL_STRING_TRIM);
			ucl_object_insert_key(config, obj,
			    c[i].key, strlen(c[i].key), false);
			break;
		case PKG_INT:
			ucl_object_insert_key(config,
			    ucl_object_fromstring_common(c[i].def, 0, UCL_STRING_PARSE_INT),
			    c[i].key, strlen(c[i].key), false);
			break;
		case PKG_BOOL:
			ucl_object_insert_key(config,
			    ucl_object_fromstring_common(c[i].def, 0, UCL_STRING_PARSE_BOOLEAN),
			    c[i].key, strlen(c[i].key), false);
			break;
		case PKG_OBJECT:
			obj = ucl_object_typed_new(UCL_OBJECT);
			if (c[i].def != NULL) {
				walk = buf = c[i].def;
				while ((buf = strchr(buf, ',')) != NULL) {
					key = walk;
					value = walk;
					while (*value != ',') {
						if (*value == '=')
							break;
						value++;
					}
					ucl_object_insert_key(obj,
					    ucl_object_fromstring_common(value + 1, buf - value - 1, UCL_STRING_TRIM),
					    key, value - key, false);
					buf++;
					walk = buf;
				}
				key = walk;
				value = walk;
				while (*value != ',') {
					if (*value == '=')
						break;
					value++;
				}
				if (o == NULL)
					o = ucl_object_typed_new(UCL_OBJECT);
				ucl_object_insert_key(o,
				    ucl_object_fromstring_common(value + 1, strlen(value + 1), UCL_STRING_TRIM),
				    key, value - key, false);
			}
			ucl_object_insert_key(config, obj,
			    c[i].key, strlen(c[i].key), false);
			break;
		case PKG_ARRAY:
			obj = ucl_object_typed_new(UCL_ARRAY);
			if (c[i].def != NULL) {
				walk = buf = c[i].def;
				while ((buf = strchr(buf, ',')) != NULL) {
					ucl_array_append(obj,
					    ucl_object_fromstring_common(walk, buf - walk, UCL_STRING_TRIM));
					buf++;
					walk = buf;
				}
				ucl_array_append(obj,
				    ucl_object_fromstring_common(walk, strlen(walk), UCL_STRING_TRIM));
			}
			ucl_object_insert_key(config, obj,
			    c[i].key, strlen(c[i].key), false);
			break;
		}
	}

	if (path == NULL)
		path = PREFIX"/etc/pkg.conf";

	p = ucl_parser_new(0);

	errno = 0;
	obj = NULL;
	if (!ucl_parser_add_file(p, path)) {
		if (errno != ENOENT)
			pkg_emit_error("Invalid configuration file: %s", ucl_parser_get_error(p));
	} else {
		obj = ucl_parser_get_object(p);

	}

	ncfg = NULL;
	while (obj != NULL && (cur = ucl_iterate_object(obj, &it, true))) {
		sbuf_init(&ukey);
		key = ucl_object_key(cur);
		for (i = 0; key[i] != '\0'; i++)
			sbuf_putc(ukey, toupper(key[i]));
		sbuf_finish(ukey);
		object = ucl_object_find_keyl(config, sbuf_data(ukey), sbuf_len(ukey));

		if (strncasecmp(sbuf_data(ukey), "PACKAGESITE", sbuf_len(ukey))
		    == 0 || strncasecmp(sbuf_data(ukey), "PUBKEY",
		    sbuf_len(ukey)) == 0 || strncasecmp(sbuf_data(ukey),
		    "MIRROR_TYPE", sbuf_len(ukey)) == 0) {
			pkg_emit_error("%s in pkg.conf is no longer "
			    "supported.  Convert to the new repository style."
			    "  See pkg.conf(5)", sbuf_data(ukey));
			fatal_errors = true;
			continue;
		}

		/* ignore unknown keys */
		if (object == NULL)
			continue;

		if (object->type != cur->type) {
			pkg_emit_error("Malformed key %s, ignoring", key);
			continue;
		}

		if (ncfg == NULL)
			ncfg = ucl_object_typed_new(UCL_OBJECT);
		ucl_object_insert_key(ncfg, ucl_object_copy(cur), sbuf_data(ukey), sbuf_len(ukey), true);
	}

	if (fatal_errors) {
		ucl_object_unref(ncfg);
		ucl_parser_free(p);
		return (EPKG_FATAL);
	}

	if (ncfg != NULL) {
		it = NULL;
		while (( cur = ucl_iterate_object(ncfg, &it, true))) {
			key = ucl_object_key(cur);
			ucl_object_replace_key(config, ucl_object_ref(cur), key, strlen(key), true);
		}
		ucl_object_unref(ncfg);
	}

	ncfg = NULL;
	it = NULL;
	while ((cur = ucl_iterate_object(config, &it, true))) {
		o = NULL;
		key = ucl_object_key(cur);
		val = getenv(key);
		if (val == NULL)
			continue;
		switch (cur->type) {
		case UCL_STRING:
			o = ucl_object_fromstring_common(val, 0, UCL_STRING_TRIM);
			break;
		case UCL_INT:
			o = ucl_object_fromstring_common(val, 0, UCL_STRING_PARSE_INT);
			if (o->type != UCL_INT) {
				pkg_emit_error("Invalid type for environment "
				    "variable %s, got %s, while expecting an integer",
				    key, val);
				ucl_object_unref(o);
				continue;
			}
			break;
		case UCL_BOOLEAN:
			o = ucl_object_fromstring_common(val, 0, UCL_STRING_PARSE_BOOLEAN);
			if (o->type != UCL_BOOLEAN) {
				pkg_emit_error("Invalid type for environment "
				    "variable %s, got %s, while expecting a boolean",
				    key, val);
				ucl_object_unref(o);
				continue;
			}
			break;
		case UCL_OBJECT:
			o = ucl_object_typed_new(UCL_OBJECT);
			walk = buf = val;
			while ((buf = strchr(buf, ',')) != NULL) {
				k = walk;
				value = walk;
				while (*value != ',') {
					if (*value == '=')
						break;
					value++;
				}
				ucl_object_insert_key(o,
				    ucl_object_fromstring_common(value + 1, buf - value - 1, UCL_STRING_TRIM),
				    k, value - k, false);
				buf++;
				walk = buf;
			}
			key = walk;
			value = walk;
			while (*value != '\0') {
				if (*value == '=')
					break;
				value++;
			}
			ucl_object_insert_key(o,
			    ucl_object_fromstring_common(value + 1, strlen(value + 1), UCL_STRING_TRIM),
			    k, value - k, false);
			break;
		case UCL_ARRAY:
			o = ucl_object_typed_new(UCL_ARRAY);
			walk = buf = val;
			while ((buf = strchr(buf, ',')) != NULL) {
				ucl_array_append(o,
				    ucl_object_fromstring_common(walk, buf - walk, UCL_STRING_TRIM));
				buf++;
				walk = buf;
			}
			ucl_array_append(o,
			    ucl_object_fromstring_common(walk, strlen(walk), UCL_STRING_TRIM));
			break;
		default:
			/* ignore other types */
			break;
		}
		if (o != NULL) {
			if (ncfg == NULL)
				ncfg = ucl_object_typed_new(UCL_OBJECT);
			ucl_object_insert_key(ncfg, o, key, strlen(key), true);
		}
	}

	if (ncfg != NULL) {
		it = NULL;
		while (( cur = ucl_iterate_object(ncfg, &it, true))) {
			key = ucl_object_key(cur);
			ucl_object_replace_key(config, ucl_object_ref(cur), key, strlen(key), true);
		}
		ucl_object_unref(ncfg);
	}

	disable_plugins_if_static();

	parsed = true;
	ucl_object_unref(obj);
	ucl_parser_free(p);

	if (strcmp(pkg_object_string(pkg_config_get("ABI")), "unknown") == 0) {
		pkg_emit_error("Unable to determine ABI");
		return (EPKG_FATAL);
	}

	pkg_debug(1, "%s", "pkg initialized");

	/* Start the event pipe */
	evpipe = pkg_object_string(pkg_config_get("EVENT_PIPE"));
	if (evpipe != NULL)
		connect_evpipe(evpipe);

	debug_level = pkg_object_int(pkg_config_get("DEBUG_LEVEL"));

	it = NULL;
	object = ucl_object_find_key(config, "PKG_ENV");
	while ((cur = ucl_iterate_object(object, &it, true))) {
		evkey = ucl_object_key(cur);
		pkg_debug(1, "Setting env var: %s", evkey);
		if (evkey != NULL && evkey[0] != '\0')
			setenv(evkey, ucl_object_tostring_forced(cur), 1);
	}

	/* load the repositories */
	load_repositories(reposdir, flags);

	setenv("HTTP_USER_AGENT", "pkg/"PKGVERSION, 1);

	/* bypass resolv.conf with specified NAMESERVER if any */
	nsname = pkg_object_string(pkg_config_get("NAMESERVER"));
	if (nsname != NULL)
		set_nameserver(ucl_object_tostring_forced(o));

	return (EPKG_OK);
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
static void
rspamadm_confighelp (gint argc, gchar **argv, const struct rspamadm_command *cmd)
{
	struct rspamd_config *cfg;
	ucl_object_t *doc_obj;
	const ucl_object_t *elt;
	GOptionContext *context;
	GError *error = NULL;
	module_t *mod, **pmod;
	worker_t **pworker;
	struct module_ctx *mod_ctx;
	gint i, ret = 0, processed_args = 0;

	context = g_option_context_new (
			"confighelp - displays help for the configuration options");
	g_option_context_set_summary (context,
			"Summary:\n  Rspamd administration utility version "
					RVERSION
					"\n  Release id: "
					RID);
	g_option_context_add_main_entries (context, entries, NULL);
	g_option_context_set_ignore_unknown_options (context, TRUE);

	if (!g_option_context_parse (context, &argc, &argv, &error)) {
		rspamd_fprintf (stderr, "option parsing failed: %s\n", error->message);
		g_error_free (error);
		exit (1);
	}

	pworker = &workers[0];
	while (*pworker) {
		/* Init string quarks */
		(void) g_quark_from_static_string ((*pworker)->name);
		pworker++;
	}

	cfg = rspamd_config_new (RSPAMD_CONFIG_INIT_SKIP_LUA);
	cfg->lua_state = rspamd_main->cfg->lua_state;
	cfg->compiled_modules = modules;
	cfg->compiled_workers = workers;

	rspamd_rcl_config_init (cfg, NULL);
	lua_pushboolean (cfg->lua_state, true);
	lua_setglobal (cfg->lua_state, "confighelp");
	rspamd_rcl_add_lua_plugins_path (cfg, plugins_path, FALSE, NULL, NULL);

	/* Init modules to get documentation strings */
	i = 0;
	for (pmod = cfg->compiled_modules; pmod != NULL && *pmod != NULL; pmod++) {
		mod = *pmod;
		mod_ctx = g_malloc0 (sizeof (struct module_ctx));

		if (mod->module_init_func (cfg, &mod_ctx) == 0) {
			g_ptr_array_add (cfg->c_modules, mod_ctx);
			mod_ctx->mod = mod;
			mod->ctx_offset = i++;
			mod_ctx->mod = mod;
		}


	}
	/* Also init all workers */
	for (pworker = cfg->compiled_workers; *pworker != NULL; pworker ++) {
		(*pworker)->worker_init_func (cfg);
	}

	/* Init lua modules */
	rspamd_lua_set_path (cfg->lua_state, cfg->rcl_obj, ucl_vars);
	rspamd_init_lua_filters (cfg, TRUE);

	if (argc > 1) {
		for (i = 1; i < argc; i ++) {
			if (argv[i][0] != '-') {

				if (keyword) {
					doc_obj = rspamadm_confighelp_search_word (cfg->doc_strings,
							argv[i]);
				}
				else {
					doc_obj = ucl_object_typed_new (UCL_OBJECT);
					elt = ucl_object_lookup_path (cfg->doc_strings, argv[i]);

					if (elt) {
						ucl_object_insert_key (doc_obj, ucl_object_ref (elt),
								argv[i], 0, false);
					}
				}

				if (doc_obj != NULL) {
					rspamadm_confighelp_show (cfg, argc, argv, argv[i], doc_obj);
					ucl_object_unref (doc_obj);
				}
				else {
					rspamd_fprintf (stderr,
							"Cannot find help for %s\n",
							argv[i]);
					ret = EXIT_FAILURE;
				}
				processed_args ++;
			}
		}
	}

	if (processed_args == 0) {
		/* Show all documentation strings */
		rspamadm_confighelp_show (cfg, argc, argv, NULL, cfg->doc_strings);
	}

	rspamd_config_free (cfg);

	exit (ret);
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
int
merge_mode(char *destination_node, char *data)
{
    ucl_object_t *dst_obj = NULL;
    ucl_object_t *sub_obj = NULL;
    ucl_object_t *old_obj = NULL;
    ucl_object_t *tmp_obj = NULL;
    int success = 0;
    char *dst_frag;

    setparser = ucl_parser_new(UCL_PARSER_KEY_LOWERCASE |
	UCL_PARSER_NO_IMPLICIT_ARRAYS);

    /* Lookup the destination to write to */
    dst_obj = get_parent(destination_node);
    sub_obj = get_object(destination_node);

    if (sub_obj == NULL) {
	fprintf(stderr, "Failed to find destination node: %s\n",
	    destination_node);
	return false;
    }

    if (include_file != NULL) {
	/* get UCL to add from file */
	set_obj = parse_file(setparser, include_file);
    } else if (data == NULL || strcmp(data, "-") == 0) {
	/* get UCL to add from stdin */
	set_obj = parse_input(setparser, stdin);
    } else {
	/* User provided data inline */
	set_obj = parse_string(setparser, data);
    }

    if (debug > 0) {
	char *rt = NULL, *dt = NULL, *st = NULL;
	rt = objtype_as_string(dst_obj);
	dt = objtype_as_string(sub_obj);
	st = objtype_as_string(set_obj);
	fprintf(stderr, "root type: %s, destination type: %s, new type: %s\n",
	    rt, dt, st);
	if (rt != NULL) free(rt);
	if (dt != NULL) free(dt);
	if (st != NULL) free(st);

	fprintf(stderr, "Merging key %s to root: %s\n",
	    ucl_object_key(sub_obj), ucl_object_key(dst_obj));
    }

    dst_frag = strrchr(destination_node, input_sepchar);
    if (dst_frag == NULL) {
	dst_frag = destination_node;
    } else {
	dst_frag++;
    }
    /* Add it to the object here */
    if (sub_obj == dst_obj && *dst_frag != '\0') {
	/* Sub-object does not exist, create a new one */
	success = ucl_object_insert_key(dst_obj, set_obj, dst_frag, 0,
	    true);
    } else if (ucl_object_type(sub_obj) == UCL_ARRAY && ucl_object_type(set_obj) == UCL_ARRAY) {
	if (debug > 0) {
	    fprintf(stderr, "Merging array of size %u with array of size %u\n",
		sub_obj->len, set_obj->len);
	}
	success = ucl_array_merge(sub_obj, set_obj, true);
    } else if (ucl_object_type(sub_obj) == UCL_ARRAY) {
	if (debug > 0) {
	    fprintf(stderr, "Appending object to array of size %u\n",
		sub_obj->len);
	}
	success = ucl_array_append(sub_obj, ucl_object_ref(set_obj));
    } else if (ucl_object_type(sub_obj) == UCL_OBJECT && ucl_object_type(set_obj) == UCL_OBJECT) {
	if (debug > 0) {
	    fprintf(stderr, "Merging object %s with object %s\n",
		ucl_object_key(sub_obj), ucl_object_key(set_obj));
	}
	/* XXX not supported:
	 * success = ucl_object_merge(sub_obj, set_obj, false, true);
	 */
	
	/* Old non-recursive way */
	/*
	success = ucl_object_merge(sub_obj, set_obj, false);
	*/
	success = merge_recursive(sub_obj, set_obj, false);
    } else if (ucl_object_type(sub_obj) != UCL_OBJECT && ucl_object_type(sub_obj) != UCL_ARRAY) {
	/* Create an explicit array */
	if (debug > 0) {
	    fprintf(stderr, "Creating an array and appended the new item\n");
	}
	tmp_obj = ucl_object_typed_new(UCL_ARRAY);
	/*
	 * Reference and Append the original scalar
	 * The additional reference is required because the old object will be
	 * unreferenced as part of the ucl_object_replace_key operation
	 */
	ucl_array_append(tmp_obj, ucl_object_ref(sub_obj));
	/* Reference and Append the new scalar (unref in cleanup()) */
	ucl_array_append(tmp_obj, ucl_object_ref(set_obj));
	/* Replace the old object with the newly created one */
	if (ucl_object_type(dst_obj) == UCL_ARRAY) {
	    old_obj = ucl_array_replace_index(dst_obj, tmp_obj,
		ucl_array_index_of(dst_obj, sub_obj));
	    success = false;
	    if (old_obj != NULL) {
		ucl_object_unref(old_obj);
		success = true;
	    }
	} else {
	    success = ucl_object_replace_key(dst_obj, tmp_obj,
		ucl_object_key(sub_obj), 0, true);
	}
    } else {
	if (debug > 0) {
	    fprintf(stderr, "Merging object into key %s\n",
		ucl_object_key(sub_obj));
	}
	success = ucl_object_insert_key_merged(dst_obj, ucl_object_ref(set_obj),
	    ucl_object_key(sub_obj), 0, true);
    }

    return success;
}