Пример #1
0
Файл: iopen.c Проект: szfn/teddy
static gboolean iopen_add_result(struct iopen_result *r) {
	bool should_add = true;
	GtkTreeIter mah;

	if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(results_list), &mah)) {
		do {
			GValue path_value = { 0 }, show_value = { 0 };
			gtk_tree_model_get_value(GTK_TREE_MODEL(results_list), &mah, 1, &path_value);
			gtk_tree_model_get_value(GTK_TREE_MODEL(results_list), &mah, 0, &show_value);
			const char *path = g_value_get_string(&path_value);
			const char *show = g_value_get_string(&show_value);

			if ((null_strcmp(r->show, show) == 0) && (null_strcmp(r->path, path) == 0)) should_add = false;

			g_value_unset(&path_value);
			g_value_unset(&show_value);
		} while (should_add && gtk_tree_model_iter_next(GTK_TREE_MODEL(results_list), &mah));
	}

	if (should_add) {
		gtk_list_store_append(results_list, &mah);
		gtk_list_store_set(results_list, &mah, 0, r->show, 1, r->path, 2, (r->search != NULL) ? r->search : "", 3, r->rank, -1);
	}

	iopen_result_free(r);

	return FALSE;
}
Пример #2
0
static bool cmp_addr(const struct message_address *a1,
		     const struct message_address *a2)
{
	return null_strcmp(a1->name, a2->name) == 0 &&
		null_strcmp(a1->route, a2->route) == 0 &&
		null_strcmp(a1->mailbox, a2->mailbox) == 0 &&
		null_strcmp(a1->domain, a2->domain) == 0 &&
		a1->invalid_syntax == a2->invalid_syntax;
}
static void
auth_str_append_extra_fields(struct auth_request *request, string_t *dest)
{
	if (!auth_fields_is_empty(request->extra_fields)) {
		str_append_c(dest, '\t');
		auth_fields_append(request->extra_fields, dest,
				   AUTH_FIELD_FLAG_HIDDEN, 0);
	}

	if (request->original_username != NULL &&
	    null_strcmp(request->original_username, request->user) != 0) {
		auth_str_add_keyvalue(dest, "original_user",
				      request->original_username);
	}
	if (request->master_user != NULL)
		auth_str_add_keyvalue(dest, "auth_user", request->master_user);

	if (!request->auth_only &&
	    auth_fields_exists(request->extra_fields, "proxy")) {
		/* we're proxying */
		if (!auth_fields_exists(request->extra_fields, "pass") &&
		    request->mech_password != NULL) {
			/* send back the password that was sent by user
			   (not the password in passdb). */
			auth_str_add_keyvalue(dest, "pass",
					      request->mech_password);
		}
		if (request->master_user != NULL &&
		    !auth_fields_exists(request->extra_fields, "master")) {
			/* the master username needs to be forwarded */
			auth_str_add_keyvalue(dest, "master",
					      request->master_user);
		}
	}
}
Пример #4
0
void test_str_sanitize(void)
{
	static struct str_sanitize_test tests[] = {
		{ NULL,    2, NULL },
		{ "",      2, NULL },
		{ "a",     2, NULL },
		{ "ab",    2, NULL },
		{ "abc",   2, "..." },
		{ "abcd",  3, "..." },
		{ "abcde", 4, "a..." },
		{ "с",    10, NULL },
		{ "с",     1, NULL },
		{ "\001x\x1fy\x81", 10, "?x?y?" }
	};
	const char *str;
	unsigned int i;

	test_begin("str_sanitize");
	for (i = 0; i < N_ELEMENTS(tests); i++) {
		str = str_sanitize(tests[i].str, tests[i].max_len);
		if (tests[i].sanitized != NULL)
			test_assert_idx(null_strcmp(str, tests[i].sanitized) == 0, i);
		else
			test_assert_idx(str == tests[i].str, i);
	}
	test_end();
}
Пример #5
0
static bool
acl_mailbox_update_removed_id(struct acl_object *aclobj,
			      const struct acl_rights_update *update)
{
	struct acl_object_list_iter *iter;
	struct acl_rights rights;
	int ret;

	if (update->modify_mode != ACL_MODIFY_MODE_CLEAR &&
	    update->neg_modify_mode != ACL_MODIFY_MODE_CLEAR)
		return FALSE;
	if (update->modify_mode == ACL_MODIFY_MODE_CLEAR &&
	    update->neg_modify_mode == ACL_MODIFY_MODE_CLEAR)
		return TRUE;

	/* mixed clear/non-clear. see if the identifier exists anymore */
	iter = acl_object_list_init(aclobj);
	while ((ret = acl_object_list_next(iter, &rights)) > 0) {
		if (rights.id_type == update->rights.id_type &&
		    null_strcmp(rights.identifier, update->rights.identifier) == 0)
			break;
	}
	acl_object_list_deinit(&iter);
	return ret == 0;
}
Пример #6
0
void test_json_tree(void)
{
	struct json_tree *tree;
	struct json_tree_node *root, *node, *node1, *node2;
	unsigned int i;

	test_begin("json tree");
	tree = json_tree_init();
	for (i = 0; i < N_ELEMENTS(test_input); i++) {
		test_assert_idx(json_tree_append(tree, test_input[i].type,
						 test_input[i].value) == 0, i);
	}

	root = json_tree_root(tree);
	i_assert(root != NULL);
	test_assert(root->value_type == JSON_TYPE_OBJECT);
	root = root->value.child;
	i_assert(root != NULL);

	for (i = 0; i < 10+2; i += 2) {
		node = json_tree_find_key(root, test_input[i].value);
		test_assert(node != NULL &&
			    node->value_type == test_input[i+1].type &&
			    null_strcmp(node->value.str, test_input[i+1].value) == 0);
	}

	node = json_tree_find_key(root, "key-obj");
	test_assert(node != NULL);

	node = json_tree_find_key(root, "key-arr-empty");
	test_assert(node != NULL && node->value_type == JSON_TYPE_ARRAY &&
		    node->value.child == NULL);

	node = json_tree_find_key(root, "key-arr");
	test_assert(node != NULL && node->value_type == JSON_TYPE_ARRAY);
	node = node->value.child;
	test_assert(node != NULL && node->value_type == JSON_TYPE_STRING &&
		    strcmp(node->value.str, "foo") == 0);
	node = node->next;
	test_assert(node != NULL && node->value_type == JSON_TYPE_ARRAY &&
		    node->value.child != NULL &&
		    node->value.child->next == NULL &&
		    node->value.child->value_type == JSON_TYPE_TRUE);
	node = node->next;
	test_assert(node != NULL && node->value_type == JSON_TYPE_OBJECT &&
		    node->value.child != NULL &&
		    node->value.child->next == NULL &&
		    node->value.child->value_type == JSON_TYPE_ARRAY &&
		    node->value.child->value.child == NULL);

	node1 = json_tree_find_child_with(node->parent, "aobj-key", "value1");
	node2 = json_tree_find_child_with(node->parent, "aobj-key", "value2");
	test_assert(node1 != NULL && node2 != NULL && node1 != node2);
	test_assert(json_tree_find_child_with(node->parent, "aobj-key", "value3") == NULL);

	json_tree_deinit(&tree);
	test_end();
}
Пример #7
0
bool ldap_connection_have_settings(struct ldap_connection *conn,
				   const struct ldap_client_settings *set)
{
	const struct ldap_client_settings *conn_set = &conn->set;

	if (strcmp(conn_set->uri, set->uri) != 0)
		return FALSE;
	if (null_strcmp(conn_set->bind_dn, set->bind_dn) != 0)
		return FALSE;
	if (null_strcmp(conn_set->password, set->password) != 0)
		return FALSE;
	if (conn_set->timeout_secs != set->timeout_secs ||
	    conn_set->max_idle_time_secs != set->max_idle_time_secs ||
	    conn_set->debug != set->debug ||
	    conn_set->require_ssl != set->require_ssl ||
	    conn_set->start_tls != set->start_tls)
		return FALSE;

	if (set->ssl_set == NULL || !set->start_tls)
		return TRUE;

	/* check SSL settings */
	if (null_strcmp(conn->ssl_set.protocols, set->ssl_set->protocols) != 0)
		return FALSE;
	if (null_strcmp(conn->ssl_set.cipher_list, set->ssl_set->cipher_list) != 0)
		return FALSE;
	if (null_strcmp(conn->ssl_set.ca_file, set->ssl_set->ca_file) != 0)
		return FALSE;
	if (null_strcmp(conn->ssl_set.cert, set->ssl_set->cert) != 0)
		return FALSE;
	if (null_strcmp(conn->ssl_set.key, set->ssl_set->key) != 0)
		return FALSE;
	return TRUE;
}
Пример #8
0
void test_str_sanitize(void)
{
	static struct str_sanitize_test tests[] = {
		{ NULL,    2, NULL },
		{ "",      2, NULL },
		{ "a",     2, NULL },
		{ "ab",    2, NULL },
		{ "abc",   2, "..." },
		{ "abcd",  3, "..." },
		{ "abcde", 4, "a..." },
		{ "\xD1\x81",     1, "..." },
		{ "\xD1\x81",     2, "\xD1\x81" },
		{ "\xD1\x81",     3, NULL },
		{ "\xC3\xA4\xC3\xA4zyxa", 1, "..." },
		{ "\xC3\xA4\xC3\xA4zyxa", 2, "..." },
		{ "\xC3\xA4\xC3\xA4zyxa", 3, "..." },
		{ "\xC3\xA4\xC3\xA4zyxa", 4, "..." },
		{ "\xC3\xA4\xC3\xA4zyxa", 5, "\xC3\xA4..." },
		{ "\xC3\xA4\xC3\xA4zyxa", 6, "\xC3\xA4..." },
		{ "\xC3\xA4\xC3\xA4zyxa", 7, "\xC3\xA4\xC3\xA4..." },
		{ "\xC3\xA4\xC3\xA4zyxa", 8, "\xC3\xA4\xC3\xA4zyxa" },
		{ "\001x\x1fy\x81", 10, "?x?y?" }
	};
	const char *str;
	string_t *str2;
	unsigned int i;

	test_begin("str_sanitize");
	for (i = 0; i < N_ELEMENTS(tests); i++) {
		str = str_sanitize(tests[i].str, tests[i].max_len);
		if (tests[i].sanitized != NULL)
			test_assert_idx(null_strcmp(str, tests[i].sanitized) == 0, i);
		else
			test_assert_idx(str == tests[i].str, i);
	}
	test_end();

	test_begin("str_sanitize_append");
	str2 = t_str_new(128);
	for (i = 0; i < N_ELEMENTS(tests); i++) {
		if (tests[i].str == NULL)
			continue;
		str_truncate(str2, 0);
		str_append(str2, "1234567890");
		str_sanitize_append(str2, tests[i].str, tests[i].max_len);

		test_assert_idx(strncmp(str_c(str2), "1234567890", 10) == 0, i);
		if (tests[i].sanitized != NULL)
			test_assert_idx(strcmp(str_c(str2)+10, tests[i].sanitized) == 0, i);
		else
			test_assert_idx(strcmp(str_c(str2)+10, tests[i].str) == 0, i);
	}
	test_end();
}
static void test_json_parser_success(bool full_size)
{
	struct json_parser *parser;
	struct istream *input, *jsoninput = NULL;
	enum json_type type;
	const char *value, *error;
	unsigned int i, pos, json_input_len = strlen(json_input);
	int ret = 0;

	test_begin(full_size ? "json parser" : "json parser (nonblocking)");
	input = test_istream_create_data(json_input, json_input_len);
	test_istream_set_allow_eof(input, FALSE);
	parser = json_parser_init(input);

	i = full_size ? json_input_len : 0;
	for (pos = 0; i <= json_input_len; i++) {
		test_istream_set_size(input, i);

		for (;;) {
			value = NULL;
			if (pos < N_ELEMENTS(json_output) &&
			    json_output[pos].type == (enum json_type)TYPE_SKIP) {
				json_parse_skip_next(parser);
				pos++;
				continue;
			} else if (pos == N_ELEMENTS(json_output) ||
				   json_output[pos].type != (enum json_type)TYPE_STREAM) {
				ret = json_parse_next(parser, &type, &value);
			} else {
				ret = jsoninput != NULL ? 1 :
					json_parse_next_stream(parser, &jsoninput);
				if (jsoninput != NULL)
					ret = stream_read_value(&jsoninput, &value);
				type = TYPE_STREAM;
			}
			if (ret <= 0)
				break;

			i_assert(pos < N_ELEMENTS(json_output));
			test_assert(json_output[pos].type == type);
			test_assert(null_strcmp(json_output[pos].value, value) == 0);
			pos++;
		}
		test_assert(ret == 0);
	}
	test_assert(pos == N_ELEMENTS(json_output));
	test_istream_set_allow_eof(input, TRUE);
	test_assert(json_parse_next(parser, &type, &value) == -1);

	i_stream_unref(&input);
	test_assert(json_parser_deinit(&parser, &error) == 0);
	test_end();
}
Пример #10
0
bool config_filters_equal(const struct config_filter *f1,
			  const struct config_filter *f2)
{
	if (null_strcmp(f1->service, f2->service) != 0)
		return FALSE;

	if (f1->remote_bits != f2->remote_bits)
		return FALSE;
	if (!net_ip_compare(&f1->remote_net, &f2->remote_net))
		return FALSE;

	if (f1->local_bits != f2->local_bits)
		return FALSE;
	if (!net_ip_compare(&f1->local_net, &f2->local_net))
		return FALSE;

	if (null_strcmp(f1->local_name, f2->local_name) != 0)
		return FALSE;

	return TRUE;
}
Пример #11
0
static void test_fts_filter_english_possessive(void)
{
	struct fts_filter *norm = NULL;
	const char *input[] = {
		"foo'",

		"foo's",
		"foo\xC3\xA4's",
		"foo'S",
		"foos'S",
		"foo's's",
		"foo'ss",

		"foo\xE2\x80\x99s",
		"foo\xC3\xA4\xE2\x80\x99s",
		"foo\xE2\x80\x99S",
		"foos\xE2\x80\x99S",
		"foo\xE2\x80\x99s\xE2\x80\x99s",
		"foo\xE2\x80\x99ss"
	};
	const char *expected_output[] = {
		"foo'",

		"foo",
		"foo\xC3\xA4",
		"foo",
		"foos",
		"foo's",
		"foo'ss",

		"foo",
		"foo\xC3\xA4",
		"foo",
		"foos",
		"foo\xE2\x80\x99s",
		"foo\xE2\x80\x99ss"
	};
	const char *error = NULL;
	const char *token = NULL;
	unsigned int i;

	test_begin("fts filter english possessive");

	test_assert(fts_filter_create(fts_filter_english_possessive, NULL, NULL, NULL, &norm, &error) == 0);
	for (i = 0; i < N_ELEMENTS(input); i++) {
		token = input[i];
		test_assert_idx(fts_filter_filter(norm, &token, &error) == 1, i);
		test_assert_idx(null_strcmp(token, expected_output[i]) == 0, i);
	}
	fts_filter_unref(&norm);
	test_assert(norm == NULL);
	test_end();
}
Пример #12
0
static void test_fts_filter_stopwords_normalizer_stemmer_sv(void)
{
	int ret;
	struct fts_filter *normalizer;
	struct fts_filter *stemmer;
	struct fts_filter *filter;
	const char *error;
	const char *token = NULL;
	const char * const tokens[] = {
		"Enär", "erkännandet", "av", "det", "inneboende", "värdet",
		"hos", "alla", "medlemmar", "av", "människosläktet", "och",
		"av", "deras", "lika", "och", "oförytterliga", "rättigheter",
		"är", "grundvalen", "för", "frihet", "rättvisa", "och", "fred",
		"i", "världen",	NULL};
	const char * const bases[] = {
		"enar", "erkan", NULL, NULL, "inneboend", "vardet", "hos", NULL,
		"medlemm", NULL, "manniskoslaktet", NULL, NULL, NULL, "lik",
		NULL, "oforytter", "ratt", NULL, "grundval", NULL, "frihet",
		"rattvis", NULL, "fred", NULL, "varld", NULL};
	const char * const *tpp;
	const char * const *bpp;

	test_begin("fts filters with stopwords, default normalizer and stemming chained, Swedish");


	test_assert(fts_filter_create(fts_filter_stopwords, NULL, &swedish_language, stopword_settings, &filter, &error) == 0);
	test_assert(fts_filter_create(fts_filter_normalizer_icu, filter, NULL, NULL, &normalizer, &error) == 0);
	test_assert(fts_filter_create(fts_filter_stemmer_snowball, normalizer, &swedish_language, NULL, &stemmer, &error) == 0);

	bpp = bases;
	for (tpp = tokens; *tpp != NULL; tpp++) {
		token = *tpp;
		ret = fts_filter_filter(stemmer, &token, &error);
		if (ret <= 0) {
			test_assert(ret == 0);
			test_assert(*bpp == NULL);
		} else {
			test_assert(*bpp != NULL);
			test_assert(null_strcmp(*bpp, token) == 0);
		}
		bpp++;
	}
	fts_filter_unref(&stemmer);
	fts_filter_unref(&normalizer);
	fts_filter_unref(&filter);
	test_assert(stemmer == NULL);
	test_assert(filter == NULL);
	test_assert(normalizer == NULL);
	test_end();
}
Пример #13
0
int acl_rights_cmp(const struct acl_rights *r1, const struct acl_rights *r2)
{
	int ret;

	if (r1->global != r2->global) {
		/* globals have higher priority than locals */
		return r1->global ? 1 : -1;
	}

	ret = r1->id_type - r2->id_type;
	if (ret != 0)
		return ret;

	return null_strcmp(r1->identifier, r2->identifier);
}
static int acl_attribute_get_acl(struct mailbox *box, const char *key,
				 struct mail_attribute_value *value_r)
{
	struct acl_object *aclobj = acl_mailbox_get_aclobj(box);
	struct acl_object_list_iter *iter;
	struct acl_rights rights, wanted_rights;
	const char *id;
	int ret;

	memset(value_r, 0, sizeof(*value_r));

	if (!box->storage->user->dsyncing) {
		mail_storage_set_error(box->storage, MAIL_ERROR_PERM,
				       MAIL_ERRSTR_NO_PERMISSION);
		return -1;
	}
	/* set last_change for all ACL objects, even if they don't exist
	   (because they could have been removed by the last change, and dsync
	   can use this information) */
	(void)acl_object_last_changed(aclobj, &value_r->last_change);

	memset(&wanted_rights, 0, sizeof(wanted_rights));
	id = key + strlen(MAILBOX_ATTRIBUTE_PREFIX_ACL);
	if (acl_identifier_parse(id, &wanted_rights) < 0) {
		mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
				       t_strdup_printf("Invalid ID: %s", id));
		return -1;
	}

	iter = acl_object_list_init(aclobj);
	while ((ret = acl_object_list_next(iter, &rights)) > 0) {
		if (!rights.global &&
		    rights.id_type == wanted_rights.id_type &&
		    null_strcmp(rights.identifier, wanted_rights.identifier) == 0) {
			value_r->value = acl_rights_export(&rights);
			break;
		}
	}
	if (ret < 0)
		mail_storage_set_internal_error(box->storage);
	acl_object_list_deinit(&iter);
	return ret;
}
Пример #15
0
static struct mail_log_group_changes *
mail_log_action_get_group(struct mail_log_transaction_context *lt,
			  enum mail_log_event event, const char *data)
{
	struct mail_log_group_changes *group;
	unsigned int i, count;

	if (!array_is_created(&lt->group_changes))
		p_array_init(&lt->group_changes, lt->pool, 8);

	group = array_get_modifiable(&lt->group_changes, &count);
	for (i = 0; i < count; i++) {
		if (group[i].event == event &&
		    null_strcmp(data, group[i].data) == 0)
			return &group[i];
	}

	group = array_append_space(&lt->group_changes);
	group->event = event;
	group->data = p_strdup(lt->pool, data);
	return group;
}
Пример #16
0
int mail_storage_service_read_settings(struct mail_storage_service_ctx *ctx,
				       const struct mail_storage_service_input *input,
				       pool_t pool,
				       const struct setting_parser_info **user_info_r,
				       const struct setting_parser_context **parser_r,
				       const char **error_r)
{
	struct master_service_settings_input set_input;
	const struct setting_parser_info *const *roots;
	struct master_service_settings_output set_output;
	const struct dynamic_settings_parser *dyn_parsers;
	enum mail_storage_service_flags flags;
	unsigned int i;

	ctx->config_permission_denied = FALSE;

	flags = input == NULL ? ctx->flags :
		mail_storage_service_input_get_flags(ctx, input);

	memset(&set_input, 0, sizeof(set_input));
	set_input.roots = ctx->set_roots;
	set_input.preserve_user = TRUE;
	/* settings reader may exec doveconf, which is going to clear
	   environment, and if we're not doing a userdb lookup we want to
	   use $HOME */
	set_input.preserve_home =
		(flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) == 0;
	set_input.use_sysexits =
		(flags & MAIL_STORAGE_SERVICE_FLAG_USE_SYSEXITS) != 0;

	if (input != NULL) {
		set_input.module = input->module;
		set_input.service = input->service;
		set_input.username = input->username;
		set_input.local_ip = input->local_ip;
		set_input.remote_ip = input->remote_ip;
	}
	if (input == NULL) {
		/* global settings read - don't create a cache for thi */
	} else if (ctx->set_cache == NULL) {
		ctx->set_cache_module = p_strdup(ctx->pool, set_input.module);
		ctx->set_cache_service = p_strdup(ctx->pool, set_input.service);
		ctx->set_cache = master_service_settings_cache_init(
			ctx->service, set_input.module, set_input.service);
	} else {
		/* already looked up settings at least once.
		   we really shouldn't be execing anymore. */
		set_input.never_exec = TRUE;
	}

	dyn_parsers = mail_storage_get_dynamic_parsers(pool);
	if (null_strcmp(set_input.module, ctx->set_cache_module) == 0 &&
	    null_strcmp(set_input.service, ctx->set_cache_service) == 0 &&
	    ctx->set_cache != NULL) {
		if (master_service_settings_cache_read(ctx->set_cache,
						       &set_input, dyn_parsers,
						       parser_r, error_r) < 0) {
			*error_r = t_strdup_printf(
				"Error reading configuration: %s", *error_r);
			return -1;
		}
	} else {
		settings_parser_dyn_update(pool, &set_input.roots, dyn_parsers);
		if (master_service_settings_read(ctx->service, &set_input,
						 &set_output, error_r) < 0) {
			*error_r = t_strdup_printf(
				"Error reading configuration: %s", *error_r);
			ctx->config_permission_denied =
				set_output.permission_denied;
			return -1;
		}
		*parser_r = ctx->service->set_parser;
	}

	roots = settings_parser_get_roots(*parser_r);
	for (i = 0; roots[i] != NULL; i++) {
		if (strcmp(roots[i]->module_name,
			   mail_user_setting_parser_info.module_name) == 0) {
			*user_info_r = roots[i];
			return 0;
		}
	}
	i_unreached();
	return -1;
}
Пример #17
0
static void test_fts_filter_stopwords_normalizer_stemmer_no(void)
{
	int ret;
	struct fts_filter *normalizer;
	struct fts_filter *stemmer;
	struct fts_filter *filter;
	const char *error;
	const char *token = NULL;
	const char * const tokens[] = {
		/* Nynorsk*/
		"Alle", "har", "plikter", "andsynes", "samfunnet", "d\xC3\xA5",
		"personlegdomen", "til", "den", "einskilde", "einast", "der",
		"kan", "f\xC3\xA5", "frie", "og", "fullgode",
		"voksterk\xC3\xA5r",
		/* Bokmal */
		"Alle", "mennesker", "er", "f\xC3\xB8""dt", "frie", "og", "med",
		"samme", "menneskeverd", "og", "menneskerettigheter", "De",
		"er", "utstyrt", "med", "fornuft", "og", "samvittighet",
		"og", "b\xC3\xB8r", "handle", "mot", "hverandre", "i",
		"brorskapets", "\xC3\xA5nd", NULL};

	const char * const bases[] = {
		/* Nynorsk*/
		"all", NULL, "plikt", "andsyn", "samfunn", NULL,
		"personlegdom", NULL, NULL, "einskild", "ein", NULL, NULL,
		"fa", "frie", NULL, "fullgod", "voksterk",
		/* Bokmal */
		"all", "mennesk", NULL, "f\xC3\xB8""dt", "frie", NULL, NULL,
		NULL, "menneskeverd", NULL, "menneskerett", "de", NULL,
		"utstyrt", NULL, "fornuft", NULL, "samvitt", NULL, "b\xC3\xB8r",
		"handl", NULL, "hverandr", NULL, "brorskap", "and", NULL};
	const char * const *tpp;
	const char * const *bpp;

	test_begin("fts filters with stopwords, default normalizer and stemming chained, Norwegian");

	test_assert(fts_filter_create(fts_filter_stopwords, NULL, &norwegian_language, stopword_settings, &filter, &error) == 0);
	test_assert(fts_filter_create(fts_filter_normalizer_icu, filter, NULL, NULL, &normalizer, &error) == 0);
	test_assert(fts_filter_create(fts_filter_stemmer_snowball, normalizer, &norwegian_language, NULL, &stemmer, &error) == 0);

	bpp = bases;
	for (tpp = tokens; *tpp != NULL; tpp++) {
		token = *tpp;
		ret = fts_filter_filter(stemmer, &token, &error);
		if (ret <= 0) {
			test_assert(ret == 0);
			test_assert(*bpp == NULL);
		} else {
			test_assert(*bpp != NULL);
			test_assert(null_strcmp(*bpp, token) == 0);
		}
		bpp++;
	}
	fts_filter_unref(&stemmer);
	fts_filter_unref(&normalizer);
	fts_filter_unref(&filter);
	test_assert(stemmer == NULL);
	test_assert(filter == NULL);
	test_assert(normalizer == NULL);
	test_end();
}
Пример #18
0
static void test_fts_filter_stopwords_fin(void)
{
	const struct fts_language finnish = { .name = "fi" };
	struct fts_filter *filter;
	const char *error;
	int ret;
	const char *input[] = {"olla", "vaiko", "eik\xC3\xB6", "olla",
	                       "kenest\xC3\xA4", "ja", "joista", "jonka",
	                       "testi", NULL};
	const char *output[] = {NULL, "vaiko", "eik\xC3\xB6", NULL, NULL,
	                        NULL, NULL, NULL, "testi"};
	const char *input2[] =
		{"kuka", "kenet", "keneen", "testi", "eiv\xC3\xA4t", NULL};
	const char *output2[] = {NULL, NULL, NULL, "testi", NULL};
	const char **ip, **op;
	const char *token;

	test_begin("fts filter stopwords, Finnish");
	test_assert(fts_filter_create(fts_filter_stopwords, NULL, &finnish, stopword_settings, &filter, &error) == 0);

	ip = input;
	op = output;
	while (*ip != NULL) {
		token = *ip;
		ret = fts_filter_filter(filter, &token, &error);
		if (ret <= 0) {
			test_assert(ret == 0);
			test_assert(*op == NULL);
		} else {
			test_assert(*op != NULL);
			test_assert(strcmp(*ip, token)  == 0);
		}
		op++;
		ip++;
	}

	fts_filter_unref(&filter);
	test_assert(filter == NULL);

	test_assert(fts_filter_create(fts_filter_stopwords, NULL, &finnish, stopword_settings, &filter, &error) == 0);
	ip = input2;
	op = output2;
	while (*ip != NULL) {
		token = *ip;
		ret = fts_filter_filter(filter, &token, &error);
		if (ret <= 0) {
			test_assert(ret == 0);
			test_assert(*op == NULL);
		} else {
			test_assert(*op != NULL);
			test_assert(strcmp(*ip, token)  == 0);
		}
		op++;
		ip++;
	}

	fts_filter_unref(&filter);
	test_assert(filter == NULL);
	test_end();
}

static void test_fts_filter_stopwords_fra(void)
{
	struct fts_filter *filter;
	const char *error;
	int ret;

	const char *input[] = {"e\xC3\xBBt", "soyez", "soi", "peut", "que",
	                       "quelconque", "\xC3\xA9t\xC3\xA9",
	                       "l\xE2\x80\x99""av\xC3\xA8nement",
	                       NULL};
	const char *output[] = {NULL, NULL, NULL, "peut", NULL,
	                        "quelconque", NULL, 
	                        "l\xE2\x80\x99""av\xC3\xA8nement",};
	const char **ip, **op;
	const char *token;

	test_begin("fts filter stopwords, French");
	test_assert(fts_filter_create(fts_filter_stopwords, NULL, &french_language, stopword_settings, &filter, &error) == 0);

	ip = input;
	op = output;
	while (*ip != NULL) {
		token = *ip;
		ret = fts_filter_filter(filter, &token, &error);
		if (ret <= 0) {
			test_assert(ret == 0);
			test_assert(*op == NULL);
		} else {
			test_assert(*op != NULL);
			test_assert(strcmp(*ip, token)  == 0);
		}
		op++;
		ip++;
	}

	fts_filter_unref(&filter);
	test_assert(filter == NULL);
	test_end();
}

static void test_fts_filter_stopwords_no(void)
{
	struct fts_filter *filter;
	const char *error;
	int ret;

	const char *input[] = {"og", "d\xC3\xA5", "medlemsstatane", "har",
	                       "bunde", "seg", "til", "\xC3\xA5", "fremje",
	                       "allmenn", "v\xC3\xB8rdnad", "for", "pakta",
	                       "og", "halde", "seg", "etter", "menneskerettane",
	                       "og", "den", "grunnleggjande", "fridomen", "i",
	                       "samarbeid", "med", "Dei", "Sameinte",
	                       "Nasjonane", NULL};

	const char *output[] = {NULL, NULL, "medlemsstatane", NULL,
	                       "bunde", NULL, NULL, NULL, "fremje",
	                       "allmenn", "v\xC3\xB8rdnad", NULL, "pakta",
	                       NULL, "halde", NULL, NULL, "menneskerettane",
	                       NULL, NULL, "grunnleggjande", "fridomen", NULL,
	                       "samarbeid", NULL, "Dei", "Sameinte",
	                       "Nasjonane"};
	const char **ip, **op;
	const char *token;

	test_begin("fts filter stopwords, Norwegian");
	test_assert(fts_filter_create(fts_filter_stopwords, NULL, &norwegian_language, stopword_settings, &filter, &error) == 0);

	ip = input;
	op = output;
	while (*ip != NULL) {
		token = *ip;
		ret = fts_filter_filter(filter, &token, &error);
		if (ret <= 0) {
			test_assert(ret == 0);
			test_assert(*op == NULL);
		} else {
			test_assert(*op != NULL);
			test_assert(strcmp(*ip, token)  == 0);
		}
		op++;
		ip++;
	}

	fts_filter_unref(&filter);
	test_assert(filter == NULL);
	test_end();
}

static void test_fts_filter_stopwords_fail_lazy_init(void)
{
	const struct fts_language unknown = { .name = "bebobidoop" };
	struct fts_filter *filter = NULL;
	const char *error = NULL, *token = "foobar";

	test_begin("fts filter stopwords, fail filter() (lazy init)");
	test_assert(fts_filter_create(fts_filter_stopwords, NULL, &unknown, stopword_settings, &filter, &error) == 0);
	test_assert(filter != NULL && error == NULL);
	test_assert(fts_filter_filter(filter, &token, &error) < 0 && error != NULL);
	fts_filter_unref(&filter);
	test_end();

}

#ifdef HAVE_FTS_STEMMER
static void test_fts_filter_stemmer_snowball_stem_english(void)
{
	struct fts_filter *stemmer;
	const char *error;
	const char *token = NULL;
	const char * const tokens[] = {
		"dries" ,"friendlies", "All", "human", "beings", "are",
		 "born", "free", "and", "equal", "in", "dignity", "and",
		 "rights", "They", "are", "endowed", "with", "reason", "and",
		 "conscience", "and", "should", "act", "towards", "one",
		 "another", "in", "a", "spirit", "of", "brotherhood", NULL};
	const char * const bases[] = {
		"dri" ,"friend", "All", "human", "be", "are", "born", "free",
		"and", "equal", "in", "digniti", "and", "right", "They", "are",
		"endow", "with", "reason", "and", "conscienc", "and", "should",
		"act", "toward", "one", "anoth", "in", "a", "spirit", "of",
		"brotherhood", NULL};
	const char * const *tpp;
	const char * const *bpp;

	test_begin("fts filter stem English");
	test_assert(fts_filter_create(fts_filter_stemmer_snowball, NULL, &english_language, NULL, &stemmer, &error) == 0);
	bpp = bases;
	for (tpp=tokens; *tpp != NULL; tpp++) {
		token = *tpp;
		test_assert(fts_filter_filter(stemmer, &token, &error) > 0);
		test_assert(token != NULL);
		test_assert(null_strcmp(token, *bpp) == 0);
		bpp++;
	}
	fts_filter_unref(&stemmer);
	test_assert(stemmer == NULL);
	test_end();
}

static void test_fts_filter_stemmer_snowball_stem_french(void)
{
	struct fts_filter *stemmer;
	const char *error;
	const char *token = NULL;
	const char * const tokens[] = {
		"Tous", "les", "\xC3\xAAtres", "humains", "naissent",
		"libres", "et",	"\xC3\xA9gaux", "en", "dignit\xC3\xA9",
		"et", "en", "droits", NULL};
	const char * const bases[] = {
		"Tous" ,"le", "\xC3\xAAtre", "humain", "naissent", "libr", "et",
		"\xC3\xA9gal", "en", "dignit", "et", "en", "droit", NULL};
	const char * const *tpp;
	const char * const *bpp;

	test_begin("fts filter stem French");
	test_assert(fts_filter_create(fts_filter_stemmer_snowball, NULL, &french_language, NULL, &stemmer, &error) == 0);
	bpp = bases;
	for (tpp=tokens; *tpp != NULL; tpp++) {
		token = *tpp;
		test_assert(fts_filter_filter(stemmer, &token, &error) > 0);
		test_assert(token != NULL);
		test_assert(null_strcmp(token, *bpp) == 0);
		bpp++;
	}
	fts_filter_unref(&stemmer);
	test_assert(stemmer == NULL);
	test_end();
}

static void test_fts_filter_stopwords_stemmer_eng(void)
{
	int ret;
	struct fts_filter *stemmer;
	struct fts_filter *filter;
	const char *error;
	const char *token = NULL;
	const char * const tokens[] = {
		"dries" ,"friendlies", "All", "human", "beings", "are",
		 "born", "free", "and", "equal", "in", "dignity", "and",
		 "rights", "They", "are", "endowed", "with", "reason", "and",
		 "conscience", "and", "should", "act", "towards", "one",
		 "another", "in", "a", "spirit", "of", "brotherhood", NULL};
	const char * const bases[] = {
		"dri" ,"friend", "All", "human", "be", NULL, "born", "free",
		NULL, "equal", NULL, "digniti", NULL, "right", "They", NULL,
		"endow", NULL, "reason", NULL, "conscienc", NULL, "should",
		"act", "toward", "one", "anoth", NULL, NULL, "spirit", NULL,
		"brotherhood", NULL};
	const char * const *tpp;
	const char * const *bpp;

	test_begin("fts filters stopwords and stemming chained, English");

	test_assert(fts_filter_create(fts_filter_stopwords, NULL, &english_language, stopword_settings, &filter, &error) == 0);
	test_assert(fts_filter_create(fts_filter_stemmer_snowball, filter, &english_language, NULL, &stemmer, &error) == 0);

	bpp = bases;
	for (tpp=tokens; *tpp != NULL; tpp++) {
		token = *tpp;
		ret = fts_filter_filter(stemmer, &token, &error);
		test_assert(ret >= 0);
		if (ret == 0)
			test_assert(*bpp == NULL);
		else {
			test_assert(*bpp != NULL);
			test_assert(null_strcmp(*bpp, token)  == 0);
		}
		bpp++;
	}
	fts_filter_unref(&stemmer);
	fts_filter_unref(&filter);
	test_assert(stemmer == NULL);
	test_assert(filter == NULL);
	test_end();
}
#endif

#ifdef HAVE_LIBICU
static void test_fts_filter_normalizer_swedish_short(void)
{
	struct fts_filter *norm = NULL;
	const char *input[] = {
		"Vem",
		"\xC3\x85",
		"\xC3\x85\xC3\x84\xC3\x96",
		"Vem kan segla f\xC3\xB6rutan vind?\n"
		"\xC3\x85\xC3\x84\xC3\x96\xC3\xB6\xC3\xA4\xC3\xA5"
	};
	const char *expected_output[] = {
		"vem",
		"a",
		"aao",
		"vem kan segla forutan vind?\naaooaa"
	};
	const char * const settings[] =
		{"id", "Any-Lower; NFKD; [: Nonspacing Mark :] Remove; NFC", NULL};
	const char *error = NULL;
	const char *token = NULL;
	unsigned int i;

	test_begin("fts filter normalizer Swedish short text");

	test_assert(fts_filter_create(fts_filter_normalizer_icu, NULL, NULL, settings, &norm, &error) == 0);
	for (i = 0; i < N_ELEMENTS(input); i++) {
		token = input[i];
		test_assert_idx(fts_filter_filter(norm, &token, &error) == 1, i);
		test_assert_idx(null_strcmp(token, expected_output[i]) == 0, i);
	}
	fts_filter_unref(&norm);
	test_assert(norm == NULL);
	test_end();
}

static void test_fts_filter_normalizer_swedish_short_default_id(void)
{
	struct fts_filter *norm = NULL;
	const char *input[] = {
		"Vem",
		"\xC3\x85",
		"\xC3\x85\xC3\x84\xC3\x96",
		"Vem kan segla f\xC3\xB6rutan vind?\n"
		"\xC3\x85\xC3\x84\xC3\x96\xC3\xB6\xC3\xA4\xC3\xA5"
	};
	const char *expected_output[] = {
		"vem",
		"a",
		"aao",
		"vemkanseglaforutanvind?\naaooaa"
	};
	const char *error = NULL;
	const char *token = NULL;
	unsigned int i;

	test_begin("fts filter normalizer Swedish short text using default ID");

	test_assert(fts_filter_create(fts_filter_normalizer_icu, NULL, NULL, NULL, &norm, &error) == 0);
	for (i = 0; i < N_ELEMENTS(input); i++) {
		token = input[i];
		test_assert_idx(fts_filter_filter(norm, &token, &error) == 1, i);
		test_assert_idx(null_strcmp(token, expected_output[i]) == 0, i);
	}
	fts_filter_unref(&norm);
	test_assert(norm == NULL);
	test_end();
}

/* UDHRDIR comes from Automake AM_CPPFLAGS */
#define UDHR_FRA_NAME "/udhr_fra.txt"
static void test_fts_filter_normalizer_french(void)
{
	struct fts_filter *norm = NULL;
	FILE *input;
	const char * const settings[] =
		{"id", "Any-Lower; NFKD; [: Nonspacing Mark :] Remove", NULL};
	char buf[4096] = {0};
	const char *error = NULL;
	const char *tokens;
	unsigned char sha512_digest[SHA512_RESULTLEN];
	struct sha512_ctx ctx;
	const unsigned char correct_digest[] = {
		0x78, 0x1e, 0xb9, 0x04, 0xa4, 0x92, 0xca, 0x88,
		0x1e, 0xef, 0x7b, 0xc8, 0x3e, 0x4a, 0xa8, 0xdb,
		0x9c, 0xd4, 0x42, 0x5c, 0x64, 0x81, 0x06, 0xd5,
		0x72, 0x93, 0x38, 0x0c, 0x09, 0xce, 0xbe, 0xdf,
		0x65, 0xff, 0x36, 0x35, 0x05, 0x77, 0xcc, 0xc6,
		0xff, 0x44, 0x2c, 0x31, 0x10, 0x00, 0xf6, 0x8d,
		0x15, 0x25, 0x1e, 0x54, 0x67, 0x2a, 0x5b, 0xc1,
		0xdb, 0x84, 0xc5, 0x0d, 0x43, 0x7e, 0x8c, 0x70};
	const char *udhr_path;

	test_begin("fts filter normalizer French UDHR");

	udhr_path = t_strconcat(UDHRDIR, UDHR_FRA_NAME, NULL);
	test_assert(fts_filter_create(fts_filter_normalizer_icu, NULL, NULL, settings, &norm, &error) == 0);
	input = fopen(udhr_path, "r");
	test_assert(input != NULL);
	sha512_init(&ctx);
	while (NULL != fgets(buf, sizeof(buf), input)) {
		tokens = buf;
		if (fts_filter_filter(norm, &tokens, &error) != 1){
			break;
		}
		sha512_loop(&ctx, tokens, strlen(tokens));
	}
	fclose(input);
	sha512_result(&ctx, sha512_digest);
	test_assert(memcmp(sha512_digest, correct_digest,
			   sizeof(sha512_digest)) == 0);
	fts_filter_unref(&norm);
	test_assert(norm == NULL);
	test_end();
}

static void test_fts_filter_normalizer_empty(void)
{
	/* test just a couple of these */
	static const char *empty_tokens[] = {
		"\xC2\xAF", /* U+00AF */
		"\xCC\x80", /* U+0300 */
		"\xF3\xA0\x87\xAF", /* U+E01EF */
		"\xCC\x80\xF3\xA0\x87\xAF" /* U+0300 U+E01EF */
	};
	const char * const settings[] =
		{"id", "Any-Lower; NFKD; [: Nonspacing Mark :] Remove; [\\x20] Remove", NULL};
	struct fts_filter *norm;
	const char *error;
	unsigned int i;

	test_begin("fts filter normalizer empty tokens");
	test_assert(fts_filter_create(fts_filter_normalizer_icu, NULL, NULL, settings, &norm, &error) == 0);
	for (i = 0; i < N_ELEMENTS(empty_tokens); i++) {
		const char *token = empty_tokens[i];
		test_assert_idx(fts_filter_filter(norm, &token, &error) == 0, i);
	}
	fts_filter_unref(&norm);
	test_end();
}

static void test_fts_filter_normalizer_baddata(void)
{
	const char * const settings[] =
		{"id", "Any-Lower; NFKD; [: Nonspacing Mark :] Remove", NULL};
	struct fts_filter *norm;
	const char *token, *error;
	string_t *str;
	unsigned int i;

	test_begin("fts filter normalizer bad data");

	test_assert(fts_filter_create(fts_filter_normalizer_icu, NULL, NULL, settings, &norm, &error) == 0);
	str = t_str_new(128);
	for (i = 1; i < 0x1ffff; i++) {
		str_truncate(str, 0);
		uni_ucs4_to_utf8_c(i, str);
		token = str_c(str);
		T_BEGIN {
			test_assert_idx(fts_filter_filter(norm, &token, &error) >= 0, i);
		} T_END;
	}

	str_truncate(str, 0);
	uni_ucs4_to_utf8_c(0x7fffffff, str);
	token = str_c(str);
	test_assert(fts_filter_filter(norm, &token, &error) >= 0);

	fts_filter_unref(&norm);
	test_end();
}

static void test_fts_filter_normalizer_invalid_id(void)
{
	struct fts_filter *norm = NULL;
	const char *settings[] =
		{"id", "Any-One-Out-There; DKFN; [: Nonspacing Mark :] Remove",
		 NULL};
	const char *error = NULL, *token = "foo";

	test_begin("fts filter normalizer invalid id");
	test_assert(fts_filter_create(fts_filter_normalizer_icu, NULL, NULL, settings, &norm, &error) == 0);
	test_assert(error == NULL);
	test_assert(fts_filter_filter(norm, &token, &error) < 0 && error != NULL);
	fts_filter_unref(&norm);
	test_end();
}

#ifdef HAVE_FTS_STEMMER
static void test_fts_filter_normalizer_stopwords_stemmer_eng(void)
{
	int ret;
	struct fts_filter *normalizer;
	struct fts_filter *stemmer;
	struct fts_filter *filter;
	const char *error;
	const char * const id_settings[] =
		//{"id", "Any-Lower; NFKD; [: Nonspacing Mark :] Remove; NFC", NULL};
		{"id", "Lower", NULL};
	const char *token = NULL;
	const char * const tokens[] = {
		"dries" ,"friendlies", "All", "human", "beings", "are",
		"born", "free", "and", "equal", "in", "dignity", "and",
		"rights", "They", "are", "endowed", "with", "reason", "and",
		"conscience", "and", "should", "act", "towards", "one",
		"another", "in", "a", "spirit", "of", "brotherhood", "ABCFoo",
		NULL};
	const char * const bases[] = {
		"dri" ,"friend", "all", "human", "be", NULL, "born", "free",
		NULL, "equal", NULL, "digniti", NULL, "right", NULL, NULL,
		"endow", NULL, "reason", NULL, "conscienc", NULL, "should",
		"act", "toward", "one", "anoth", NULL, NULL, "spirit", NULL,
		"brotherhood", "abcfoo", NULL};
	const char * const *tpp;
	const char * const *bpp;

	test_begin("fts filters normalizer, stopwords and stemming chained, English");

	test_assert(fts_filter_create(fts_filter_normalizer_icu, NULL, NULL, id_settings, &normalizer, &error) == 0);
	test_assert(fts_filter_create(fts_filter_stopwords, normalizer, &english_language, stopword_settings, &filter, &error) == 0);
	test_assert(fts_filter_create(fts_filter_stemmer_snowball, filter, &english_language, NULL, &stemmer, &error) == 0);

	bpp = bases;
	for (tpp = tokens; *tpp != NULL; tpp++) {
		token = *tpp;
		ret = fts_filter_filter(stemmer, &token, &error);
		if (ret <= 0) {
			test_assert(ret == 0);
			test_assert(*bpp == NULL);
		} else {
			test_assert(*bpp != NULL);
			test_assert(strcmp(*bpp, token)  == 0);
		}
		bpp++;
	}
	fts_filter_unref(&stemmer);
	fts_filter_unref(&filter);
	fts_filter_unref(&normalizer);
	test_assert(stemmer == NULL);
	test_assert(filter == NULL);
	test_assert(normalizer == NULL);
	test_end();
}
Пример #19
0
bool config_export_type(string_t *str, const void *value,
			const void *default_value,
			enum setting_type type, bool dump_default,
			bool *dump_r)
{
	switch (type) {
	case SET_BOOL: {
		const bool *val = value, *dval = default_value;

		if (dump_default || dval == NULL || *val != *dval)
			str_append(str, *val ? "yes" : "no");
		break;
	}
	case SET_SIZE: {
		const uoff_t *val = value, *dval = default_value;

		if (dump_default || dval == NULL || *val != *dval)
			config_export_size(str, *val);
		break;
	}
	case SET_UINT:
	case SET_UINT_OCT:
	case SET_TIME: {
		const unsigned int *val = value, *dval = default_value;

		if (dump_default || dval == NULL || *val != *dval) {
			switch (type) {
			case SET_UINT_OCT:
				str_printfa(str, "0%o", *val);
				break;
			case SET_TIME:
				config_export_time(str, *val);
				break;
			default:
				str_printfa(str, "%u", *val);
				break;
			}
		}
		break;
	}
	case SET_STR_VARS: {
		const char *const *val = value, *sval;
		const char *const *_dval = default_value;
		const char *dval = _dval == NULL ? NULL : *_dval;

		i_assert(*val == NULL ||
			 **val == SETTING_STRVAR_UNEXPANDED[0]);

		sval = *val == NULL ? NULL : (*val + 1);
		if ((dump_default || null_strcmp(sval, dval) != 0) &&
		    sval != NULL) {
			str_append(str, sval);
			*dump_r = TRUE;
		}
		break;
	}
	case SET_STR: {
		const char *const *val = value;
		const char *const *_dval = default_value;
		const char *dval = _dval == NULL ? NULL : *_dval;

		if ((dump_default || null_strcmp(*val, dval) != 0) &&
		    *val != NULL) {
			str_append(str, *val);
			*dump_r = TRUE;
		}
		break;
	}
	case SET_ENUM: {
		const char *const *val = value;
		unsigned int len = strlen(*val);

		if (dump_default)
			str_append(str, *val);
		else {
			const char *const *_dval = default_value;
			const char *dval = _dval == NULL ? NULL : *_dval;

			i_assert(dval != NULL);
			if (strncmp(*val, dval, len) != 0 ||
			    ((*val)[len] != ':' && (*val)[len] != '\0'))
				str_append(str, *val);
		}
		break;
	}
	default:
		return FALSE;
	}
	return TRUE;
}