bool sieve_extprogram_command_validate
(struct sieve_validator *valdtr, struct sieve_command *cmd)
{
    struct sieve_ast_argument *arg = cmd->first_positional;
    struct sieve_ast_argument *stritem;
    struct _arg_validate_context actx;
    string_t *program_name;

    if ( arg == NULL ) {
        sieve_command_validate_error(valdtr, cmd,
                                     "the %s %s expects at least one positional argument, but none was found",
                                     sieve_command_identifier(cmd), sieve_command_type_name(cmd));
        return FALSE;
    }

    /* <program-name: string> argument */

    if ( !sieve_validate_positional_argument
            (valdtr, cmd, arg, "program-name", 1, SAAT_STRING) ) {
        return FALSE;
    }

    if ( !sieve_validator_argument_activate(valdtr, cmd, arg, FALSE) )
        return FALSE;

    /* Variables are not allowed */
    if ( !sieve_argument_is_string_literal(arg) ) {
        sieve_argument_validate_error(valdtr, arg,
                                      "the %s %s requires a constant string "
                                      "for its program-name argument",
                                      sieve_command_identifier(cmd), sieve_command_type_name(cmd));
        return FALSE;
    }

    /* Check program name */
    program_name = sieve_ast_argument_str(arg);
    if ( !sieve_extprogram_name_is_valid(program_name) ) {
        sieve_argument_validate_error(valdtr, arg,
                                      "%s %s: invalid program name '%s'",
                                      sieve_command_identifier(cmd), sieve_command_type_name(cmd),
                                      str_sanitize(str_c(program_name), 80));
        return FALSE;
    }

    /* Optional <arguments: string-list> argument */

    arg = sieve_ast_argument_next(arg);
    if ( arg == NULL )
        return TRUE;

    if ( !sieve_validate_positional_argument
            (valdtr, cmd, arg, "arguments", 2, SAAT_STRING_LIST) ) {
        return FALSE;
    }

    if ( !sieve_validator_argument_activate(valdtr, cmd, arg, FALSE) )
        return FALSE;

    /* Check arguments */
    actx.valdtr = valdtr;
    actx.cmd = cmd;
    stritem = arg;
    if ( sieve_ast_stringlist_map
            (&stritem, (void *)&actx, _arg_validate) <= 0 ) {
        return FALSE;
    }

    if ( sieve_ast_argument_next(arg) != NULL ) {
        sieve_command_validate_error(valdtr, cmd,
                                     "the %s %s expects at most two positional arguments, but more were found",
                                     sieve_command_identifier(cmd), sieve_command_type_name(cmd));
        return FALSE;
    }

    return TRUE;
}
Esempio n. 2
0
int mailbox_list_delete_mailbox_nonrecursive(struct mailbox_list *list,
					     const char *name, const char *path,
					     bool rmdir_path)
{
	DIR *dir;
	struct dirent *d;
	string_t *full_path;
	unsigned int dir_len;
	bool mailbox_dir, unlinked_something = FALSE;

	if (mailbox_list_check_root_delete(list, name, path) < 0)
		return -1;

	dir = opendir(path);
	if (dir == NULL) {
		if (errno == ENOENT) {
			mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
				T_MAILBOX_LIST_ERR_NOT_FOUND(list, name));
		} else {
			if (!mailbox_list_set_error_from_errno(list)) {
				mailbox_list_set_critical(list,
					"opendir(%s) failed: %m", path);
			}
		}
		return -1;
	}

	full_path = t_str_new(256);
	str_append(full_path, path);
	str_append_c(full_path, '/');
	dir_len = str_len(full_path);

	for (errno = 0; (d = readdir(dir)) != NULL; errno = 0) {
		if (d->d_name[0] == '.') {
			/* skip . and .. */
			if (d->d_name[1] == '\0')
				continue;
			if (d->d_name[1] == '.' && d->d_name[2] == '\0')
				continue;
		}

		mailbox_dir = list->v.is_internal_name != NULL &&
			list->v.is_internal_name(list, d->d_name);

		str_truncate(full_path, dir_len);
		str_append(full_path, d->d_name);

		if (mailbox_dir) {
			if (mailbox_list_delete_trash(str_c(full_path)) < 0) {
				mailbox_list_set_critical(list,
					"unlink_directory(%s) failed: %m",
					str_c(full_path));
			} else {
				unlinked_something = TRUE;
			}
			continue;
		}

		/* trying to unlink() a directory gives either EPERM or EISDIR
		   (non-POSIX). it doesn't really work anywhere in practise,
		   so don't bother stat()ing the file first */
		if (unlink(str_c(full_path)) == 0)
			unlinked_something = TRUE;
		else if (errno != ENOENT && !UNLINK_EISDIR(errno)) {
			mailbox_list_set_critical(list,
				"unlink_directory(%s) failed: %m",
				str_c(full_path));
		}
	}
	if (errno != 0)
		mailbox_list_set_critical(list, "readdir(%s) failed: %m", path);
	if (closedir(dir) < 0) {
		mailbox_list_set_critical(list, "closedir(%s) failed: %m",
					  path);
	}

	if (rmdir_path) {
		if (rmdir(path) == 0)
			unlinked_something = TRUE;
		else if (errno != ENOENT &&
			 errno != ENOTEMPTY && errno != EEXIST) {
			mailbox_list_set_critical(list, "rmdir(%s) failed: %m",
						  path);
			return -1;
		}
	}

	if (!unlinked_something) {
		mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE,
				       "Mailbox has children, can't delete it");
		return -1;
	}
	return 0;
}
Esempio n. 3
0
static
void test_gen_and_get_info_rsa_pem(void)
{
	test_begin("test_gen_and_get_info_rsa_pem");

	const char *error = NULL;
	bool ret = FALSE;
	struct dcrypt_keypair pair;
	string_t* buf = str_new(default_pool, 4096);

	ret = dcrypt_keypair_generate(&pair, DCRYPT_KEY_RSA, 1024, NULL, NULL);
	test_assert(ret == TRUE);

	/* test public key */
	enum dcrypt_key_format format;
	enum dcrypt_key_version version;
	enum dcrypt_key_kind kind;
	enum dcrypt_key_encryption_type encryption_type;
	const char *encryption_key_hash;
	const char *key_hash;

	ret = dcrypt_key_store_public(pair.pub, DCRYPT_FORMAT_PEM, buf,
			&error);
	test_assert(ret == TRUE);

	ret = dcrypt_key_string_get_info(str_c(buf), &format, &version,
			&kind, &encryption_type, &encryption_key_hash,
			&key_hash, &error);
	test_assert(ret == TRUE);
	test_assert(format == DCRYPT_FORMAT_PEM);
	test_assert(version == DCRYPT_KEY_VERSION_NA);

	test_assert(kind == DCRYPT_KEY_KIND_PUBLIC);
	test_assert(encryption_type == DCRYPT_KEY_ENCRYPTION_TYPE_NONE);
	test_assert(encryption_key_hash == NULL);
	test_assert(key_hash == NULL);

	/* test private key */
	buffer_set_used_size(buf, 0);
	ret = dcrypt_key_store_private(pair.priv, DCRYPT_FORMAT_PEM, NULL,
			buf, NULL, NULL, &error);

	test_assert(ret == TRUE);

	ret = dcrypt_key_string_get_info(str_c(buf), &format, &version,
			&kind, &encryption_type, &encryption_key_hash,
			&key_hash, &error);

	test_assert(ret == TRUE);
	test_assert(format == DCRYPT_FORMAT_PEM);
	test_assert(version == DCRYPT_KEY_VERSION_NA);

	test_assert(kind == DCRYPT_KEY_KIND_PRIVATE);

	test_assert(encryption_type == DCRYPT_KEY_ENCRYPTION_TYPE_NONE);
	test_assert(encryption_key_hash == NULL);
	test_assert(key_hash == NULL);

	dcrypt_keypair_free(&pair);
	buffer_free(&buf);

	test_end();
}
Esempio n. 4
0
static void
service_dup_fds(struct service *service)
{
	struct service_listener *const *listeners;
	ARRAY_TYPE(dup2) dups;
	string_t *listener_names;
	int fd = MASTER_LISTEN_FD_FIRST;
	unsigned int i, count, socket_listener_count, ssl_socket_count;

	/* stdin/stdout is already redirected to /dev/null. Other master fds
	   should have been opened with fd_close_on_exec() so we don't have to
	   worry about them.

	   because the destination fd might be another one's source fd we have
	   to be careful not to overwrite anything. dup() the fd when needed */

        socket_listener_count = 0;
	listeners = array_get(&service->listeners, &count);
	t_array_init(&dups, count + 10);
	listener_names = t_str_new(256);

	switch (service->type) {
	case SERVICE_TYPE_LOG:
		i_assert(fd == MASTER_LISTEN_FD_FIRST);
		services_log_dup2(&dups, service->list, fd,
				  &socket_listener_count);
		fd += socket_listener_count;
		break;
	case SERVICE_TYPE_ANVIL:
		dup2_append(&dups, service_anvil_global->log_fdpass_fd[0],
			    MASTER_ANVIL_LOG_FDPASS_FD);
		/* nonblocking anvil fd must be the first one. anvil treats it
		   as the master's fd */
		dup2_append(&dups, service_anvil_global->nonblocking_fd[0], fd++);
		dup2_append(&dups, service_anvil_global->blocking_fd[0], fd++);
		socket_listener_count += 2;
		break;
	default:
		break;
	}

	/* anvil/log fds have no names */
	for (i = MASTER_LISTEN_FD_FIRST; i < (unsigned int)fd; i++)
		str_append_c(listener_names, '\t');

	/* first add non-ssl listeners */
	for (i = 0; i < count; i++) {
		if (listeners[i]->fd != -1 &&
		    (listeners[i]->type != SERVICE_LISTENER_INET ||
		     !listeners[i]->set.inetset.set->ssl)) {
			str_append_tabescaped(listener_names, listeners[i]->name);
			str_append_c(listener_names, '\t');
			dup2_append(&dups, listeners[i]->fd, fd++);
			socket_listener_count++;
		}
	}
	/* then ssl-listeners */
	ssl_socket_count = 0;
	for (i = 0; i < count; i++) {
		if (listeners[i]->fd != -1 &&
		    listeners[i]->type == SERVICE_LISTENER_INET &&
		    listeners[i]->set.inetset.set->ssl) {
			str_append_tabescaped(listener_names, listeners[i]->name);
			str_append_c(listener_names, '\t');
			dup2_append(&dups, listeners[i]->fd, fd++);
			socket_listener_count++;
			ssl_socket_count++;
		}
	}

	if (service->login_notify_fd != -1) {
		dup2_append(&dups, service->login_notify_fd,
			    MASTER_LOGIN_NOTIFY_FD);
	}
	switch (service->type) {
	case SERVICE_TYPE_LOG:
	case SERVICE_TYPE_ANVIL:
	case SERVICE_TYPE_CONFIG:
		dup2_append(&dups, null_fd, MASTER_ANVIL_FD);
		break;
	case SERVICE_TYPE_UNKNOWN:
	case SERVICE_TYPE_LOGIN:
	case SERVICE_TYPE_STARTUP:
		dup2_append(&dups, service_anvil_global->blocking_fd[1],
			    MASTER_ANVIL_FD);
		break;
	}
	dup2_append(&dups, service->status_fd[1], MASTER_STATUS_FD);
	if (service->type != SERVICE_TYPE_ANVIL) {
		dup2_append(&dups, service->list->master_dead_pipe_fd[1],
			    MASTER_DEAD_FD);
	} else {
		dup2_append(&dups, global_master_dead_pipe_fd[1],
			    MASTER_DEAD_FD);
	}

	if (service->type == SERVICE_TYPE_LOG) {
		/* keep stderr as-is. this is especially important when
		   log_path=/dev/stderr, but might be helpful even in other
		   situations for logging startup errors */
	} else {
		/* set log file to stderr. dup2() here immediately so that
		   we can set up logging to it without causing any log messages
		   to be lost. */
		i_assert(service->log_fd[1] != -1);

		env_put("LOG_SERVICE=1");
		if (dup2(service->log_fd[1], STDERR_FILENO) < 0)
			i_fatal("dup2(log fd) failed: %m");
		i_set_failure_internal();
	}

	/* make sure we don't leak syslog fd. try to do it as late as possible,
	   but also before dup2()s in case syslog fd is one of them. */
	closelog();

	if (dup2_array(&dups) < 0)
		i_fatal("service(%s): dup2s failed", service->set->name);

	i_assert(fd == MASTER_LISTEN_FD_FIRST + (int)socket_listener_count);
	env_put(t_strdup_printf("SOCKET_COUNT=%d", socket_listener_count));
	env_put(t_strdup_printf("SSL_SOCKET_COUNT=%d", ssl_socket_count));
	env_put(t_strdup_printf("SOCKET_NAMES=%s", str_c(listener_names)));
}
Esempio n. 5
0
static void test_message_address(void)
{
	static const char *input[] = {
		"user@domain", NULL,
		"<user@domain>", "user@domain",
		"foo bar <user@domain>", NULL,
		"\"foo bar\" <user@domain>", "foo bar <user@domain>",
		"<@route:user@domain>", NULL,
		"<@route@route2:user@domain>", "<@route,@route2:user@domain>",
		"hello <@route ,@route2:user@domain>", "hello <@route,@route2:user@domain>",
		"user (hello)", NULL,
		"hello <user>", NULL,
		"@domain", NULL
	};
	static struct message_address group_prefix = {
		NULL, NULL, NULL, "group", NULL, FALSE
	};
	static struct message_address group_suffix = {
		NULL, NULL, NULL, NULL, NULL, FALSE
	};
	static struct message_address output[] = {
		{ NULL, NULL, NULL, "user", "domain", FALSE },
		{ NULL, NULL, NULL, "user", "domain", FALSE },
		{ NULL, "foo bar", NULL, "user", "domain", FALSE },
		{ NULL, "foo bar", NULL, "user", "domain", FALSE },
		{ NULL, NULL, "@route", "user", "domain", FALSE },
		{ NULL, NULL, "@route,@route2", "user", "domain", FALSE },
		{ NULL, "hello", "@route,@route2", "user", "domain", FALSE },
		{ NULL, "hello", NULL, "user", "", TRUE },
		{ NULL, "hello", NULL, "user", "", TRUE },
		{ NULL, NULL, NULL, "", "domain", TRUE }
	};
	struct message_address *addr;
	string_t *str, *group;
	const char *wanted_string;
	unsigned int i;

	i_assert(N_ELEMENTS(input) == N_ELEMENTS(output)*2);

	test_begin("message address parsing");
	str = t_str_new(128);
	group = t_str_new(256);
	str_append(group, "group: ");

	for (i = 0; i < N_ELEMENTS(output); i++) {
		addr = message_address_parse(pool_datastack_create(),
					     (const unsigned char *)input[i*2],
					     strlen(input[i*2]), UINT_MAX, FALSE);
		test_assert(addr != NULL && addr->next == NULL &&
			    cmp_addr(addr, &output[i]));

		if (!output[i].invalid_syntax) {
			str_truncate(str, 0);
			message_address_write(str, addr);
			wanted_string = input[i*2+1] != NULL ?
				input[i*2+1] : input[i*2];
			test_assert(strcmp(str_c(str), wanted_string) == 0);
			if (i != 0) {
				if ((i % 2) == 0)
					str_append(group, ",");
				else
					str_append(group, " , \n ");
			}
			str_append(group, input[i*2]);
		}
	}
	str_append_c(group, ';');
	test_end();

	test_begin("message address parsing with groups");
	addr = message_address_parse(pool_datastack_create(), str_data(group),
				     str_len(group), UINT_MAX, FALSE);
	test_assert(addr != NULL && cmp_addr(addr, &group_prefix));
	addr = addr->next;
	for (i = 0; i < N_ELEMENTS(output) && addr != NULL; i++) {
		if (output[i].invalid_syntax)
			continue;
		test_assert(cmp_addr(addr, &output[i]));
		addr = addr->next;
	}
	test_assert(addr != NULL && addr->next == NULL &&
		    cmp_addr(addr, &group_suffix));
	test_end();

	test_begin("message address parsing with empty group");
	str_truncate(group, 0);
	str_append(group, "group:;");
	addr = message_address_parse(pool_datastack_create(), str_data(group),
				     str_len(group), UINT_MAX, FALSE);
	test_assert(addr != NULL && cmp_addr(addr, &group_prefix));
	addr = addr->next;
	test_assert(addr != NULL && addr->next == NULL &&
		    cmp_addr(addr, &group_suffix));
	test_end();
}
Esempio n. 6
0
static void
mail_log_append_mail_message_real(struct mail_log_mail_txn_context *ctx,
				  struct mail *mail, enum mail_log_event event,
				  const char *desc)
{
	struct mail_log_user *muser =
		MAIL_LOG_USER_CONTEXT(mail->box->storage->user);
	struct mail_log_message *msg;
	string_t *text;
	uoff_t size;
	
	msg = p_new(ctx->pool, struct mail_log_message, 1);

	text = t_str_new(128);
	str_append(text, desc);
	str_append(text, ": ");
	if ((muser->fields & MAIL_LOG_FIELD_BOX) != 0) {
		mail_log_append_mailbox_name(text, mail);
		str_append(text, ", ");
	}
	if ((muser->fields & MAIL_LOG_FIELD_UID) != 0) {
		if (event != MAIL_LOG_EVENT_SAVE &&
		    event != MAIL_LOG_EVENT_COPY)
			mail_log_append_uid(ctx, msg, text, mail->uid);
		else {
			/* with mbox mail->uid contains the uid, but handle
			   this consistently with all mailbox formats */
			mail_log_append_uid(ctx, msg, text, 0);
		}
		str_append(text, ", ");
	}
	if ((muser->fields & MAIL_LOG_FIELD_MSGID) != 0) {
		mail_log_append_mail_header(text, mail, "msgid", "Message-ID");
		str_append(text, ", ");
	}
	if ((muser->fields & MAIL_LOG_FIELD_PSIZE) != 0) {
		if (mail_get_physical_size(mail, &size) == 0)
			str_printfa(text, "size=%"PRIuUOFF_T, size);
		else
			str_printfa(text, "size=error");
		str_append(text, ", ");
	}
	if ((muser->fields & MAIL_LOG_FIELD_VSIZE) != 0) {
		if (mail_get_virtual_size(mail, &size) == 0)
			str_printfa(text, "vsize=%"PRIuUOFF_T, size);
		else
			str_printfa(text, "vsize=error");
		str_append(text, ", ");
	}
	if ((muser->fields & MAIL_LOG_FIELD_FROM) != 0) {
		mail_log_append_mail_header(text, mail, "from", "From");
		str_append(text, ", ");
	}
	if ((muser->fields & MAIL_LOG_FIELD_SUBJECT) != 0) {
		mail_log_append_mail_header(text, mail, "subject", "Subject");
		str_append(text, ", ");
	}
	if ((muser->fields & MAIL_LOG_FIELD_FLAGS) != 0) {
		str_printfa(text, "flags=(");
		imap_write_flags(text, mail_get_flags(mail),
				 mail_get_keywords(mail));
		str_append(text, "), ");
	}
	str_truncate(text, str_len(text)-2);

	msg->event = event;
	msg->text = p_strdup(ctx->pool, str_c(text));
	DLLIST2_APPEND(&ctx->messages, &ctx->messages_tail, msg);
}
Esempio n. 7
0
static void lmtp_address_translate(struct client *client, const char **address)
{
	const char *transpos = client->lmtp_set->lmtp_address_translate;
	const char *p, *nextstr, *addrpos = *address;
	unsigned int len;
	string_t *username, *domain, *dest = NULL;

	if (*transpos == '\0')
		return;

	username = t_str_new(64);
	domain = t_str_new(64);

	/* check that string matches up to the first '%' */
	p = strchr(transpos, '%');
	if (p == NULL)
		len = strlen(transpos);
	else
		len = p-transpos;
	if (strncmp(transpos, addrpos, len) != 0)
		return;
	transpos += len;
	addrpos += len;

	while (*transpos != '\0') {
		switch (transpos[1]) {
		case 'n':
		case 'u':
			dest = username;
			break;
		case 'd':
			dest = domain;
			break;
		default:
			return;
		}
		transpos += 2;

		/* find where the next string starts */
		if (*transpos == '\0') {
			str_append(dest, addrpos);
			break;
		}
		p = strchr(transpos, '%');
		if (p == NULL)
			nextstr = transpos;
		else
			nextstr = t_strdup_until(transpos, p);
		p = strstr(addrpos, nextstr);
		if (p == NULL)
			return;
		str_append_n(dest, addrpos, p-addrpos);

		len = strlen(nextstr);
		transpos += len;
		addrpos = p + len;
	}
	str_append_c(username, '@');
	if (domain != NULL)
		str_append_str(username, domain);
	*address = str_c(username);
}
Esempio n. 8
0
static int cmd_test_config_reload_operation_execute
(const struct sieve_runtime_env *renv, sieve_size_t *address)
{
	const struct sieve_extension *ext;
	int opt_code = 0;
	string_t *extension = NULL;
	int ret;

	/* 
	 * Read operands 
	 */
	
	/* Optional operands */
	for (;;) {
		int opt;

		if ( (opt=sieve_opr_optional_read(renv, address, &opt_code)) < 0 )
			return SIEVE_EXEC_BIN_CORRUPT;

		if ( opt == 0 ) break;

		switch ( opt_code ) {
		case OPT_EXTENSION:
			ret = sieve_opr_string_read(renv, address, "extension", &extension);
			break;
		default:
			sieve_runtime_trace_error(renv, "unknown optional operand");
			ret = SIEVE_EXEC_BIN_CORRUPT;
		}

		if ( ret <= 0 ) return ret;
	}

	/*
	 * Perform operation
	 */

	if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS) ) {
		sieve_runtime_trace(renv, 0,
			"testsuite: test_config_reload command");
		sieve_runtime_trace_descend(renv);
	}

	if ( extension == NULL ) {
		testsuite_test_failf("test_config_reload: "
			":extension argument is currently mandatory");
		return SIEVE_EXEC_OK;
	}	

	if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS) ) {
		sieve_runtime_trace(renv, 0, "reload configuration for extension `%s'", 
			str_c(extension));
	}

	ext = sieve_extension_get_by_name(renv->svinst, str_c(extension));
	if ( ext == NULL ) {
		testsuite_test_failf("test_config_reload: "
			"unknown extension '%s'", str_c(extension));
		return SIEVE_EXEC_OK;
	}	

	sieve_extension_reload(ext);
	return SIEVE_EXEC_OK;
}
Esempio n. 9
0
static void
dsync_fix_mailbox_name(struct mail_namespace *ns, string_t *vname_str,
		       char alt_char)
{
	const char *old_vname;
	char *vname, list_sep = mailbox_list_get_hierarchy_sep(ns->list);
	guid_128_t guid;
	unsigned int i, start_pos;

	vname = str_c_modifiable(vname_str);
	if (strncmp(vname, ns->prefix, ns->prefix_len) == 0)
		start_pos = ns->prefix_len;
	else
		start_pos = 0;

	/* replace control chars */
	for (i = start_pos; vname[i] != '\0'; i++) {
		if ((unsigned char)vname[i] < ' ')
			vname[i] = alt_char;
	}
	/* make it valid UTF8 */
	if (!uni_utf8_str_is_valid(vname)) {
		old_vname = t_strdup(vname + start_pos);
		str_truncate(vname_str, start_pos);
		if (uni_utf8_get_valid_data((const void *)old_vname,
					    strlen(old_vname), vname_str))
			i_unreached();
		vname = str_c_modifiable(vname_str);
	}
	if (dsync_is_valid_name(ns, vname))
		return;

	/* 1) change any real separators to alt separators (this wouldn't
	   be necessary with listescape, but don't bother detecting it) */
	if (list_sep != mail_namespace_get_sep(ns)) {
		for (i = start_pos; vname[i] != '\0'; i++) {
			if (vname[i] == list_sep)
				vname[i] = alt_char;
		}
		if (dsync_is_valid_name(ns, vname))
			return;
	}
	/* 2) '/' characters aren't valid without listescape */
	if (mail_namespace_get_sep(ns) != '/' && list_sep != '/') {
		for (i = start_pos; vname[i] != '\0'; i++) {
			if (vname[i] == '/')
				vname[i] = alt_char;
		}
		if (dsync_is_valid_name(ns, vname))
			return;
	}
	/* 3) probably some reserved name (e.g. dbox-Mails) */
	str_insert(vname_str, ns->prefix_len, "_");
	if (dsync_is_valid_name(ns, str_c(vname_str)))
		return;

	/* 4) name is too long? just give up and generate a unique name */
	guid_128_generate(guid);
	str_truncate(vname_str, 0);
	str_append(vname_str, ns->prefix);
	str_append(vname_str, guid_128_to_string(guid));
	i_assert(dsync_is_valid_name(ns, str_c(vname_str)));
}
Esempio n. 10
0
static void
mail_search_arg_to_cmdline(string_t *dest, const struct mail_search_arg *arg)
{
	struct mail_search_arg new_arg;
	const char *error;

	if (arg->match_not)
		str_append(dest, "NOT ");
	switch (arg->type) {
	case SEARCH_OR:
		mail_search_subargs_to_cmdline(dest, arg->value.subargs, " OR ");
		return;
	case SEARCH_SUB:
		mail_search_subargs_to_cmdline(dest, arg->value.subargs, " ");
		return;
	case SEARCH_FLAGS:
	case SEARCH_KEYWORDS: {
		size_t pos = str_len(dest);

		new_arg = *arg;
		new_arg.match_not = FALSE;
		if (!mail_search_arg_to_imap(dest, &new_arg, &error))
			i_unreached();
		if (str_c(dest)[pos] == '(') {
			str_insert(dest, pos+1, " ");
			str_insert(dest, str_len(dest)-1, " ");
		}
		return;
	}
	case SEARCH_INTHREAD:
		str_append(dest, "INTHREAD ");
		imap_append_astring(dest, mail_thread_type_to_str(arg->value.thread_type));
		str_append_c(dest, ' ');
		mail_search_subargs_to_cmdline(dest, arg->value.subargs, " ");
		break;
	case SEARCH_MAILBOX:
	case SEARCH_MAILBOX_GLOB:
		str_append(dest, "MAILBOX ");
		imap_append_astring(dest, arg->value.str);
		return;
	case SEARCH_MAILBOX_GUID:
		str_append(dest, "MAILBOX-GUID ");
		imap_append_astring(dest, arg->value.str);
		return;
	case SEARCH_ALL:
	case SEARCH_SEQSET:
	case SEARCH_UIDSET:
	case SEARCH_BEFORE:
	case SEARCH_ON:
	case SEARCH_SINCE:
	case SEARCH_SMALLER:
	case SEARCH_LARGER:
	case SEARCH_HEADER:
	case SEARCH_HEADER_ADDRESS:
	case SEARCH_HEADER_COMPRESS_LWSP:
	case SEARCH_BODY:
	case SEARCH_TEXT:
	case SEARCH_MODSEQ:
	case SEARCH_GUID:
	case SEARCH_REAL_UID:
	case SEARCH_MIMEPART:
		break;
	}
	new_arg = *arg;
	new_arg.match_not = FALSE;
	if (!mail_search_arg_to_imap(dest, &new_arg, &error))
		i_panic("mail_search_args_to_cmdline(): Missing handler: %s", error);
}
Esempio n. 11
0
static int cmd_filter_operation_execute
(const struct sieve_runtime_env *renv, sieve_size_t *address)
{	
	const struct sieve_extension *this_ext = renv->oprtn->ext;
	unsigned int is_test = 0;
	struct sieve_stringlist *args_list = NULL;
	enum sieve_error error = SIEVE_ERROR_NONE;
	string_t *pname = NULL;
	const char *program_name = NULL;
	const char *const *args = NULL;
	struct istream *newmsg = NULL;
	struct sieve_extprogram *sprog;
	int ret;

	/*
	 * Read operands
	 */

	/* The is_test flag */

	if ( !sieve_binary_read_byte(renv->sblock, address, &is_test) ) {
		sieve_runtime_trace_error(renv, "invalid is_test flag");
		return SIEVE_EXEC_BIN_CORRUPT;
	}

	/* Optional operands */	

	if ( sieve_action_opr_optional_read(renv, address, NULL, &ret, NULL) != 0 ) 
		return ret;

	/* Fixed operands */

	if ( (ret=sieve_extprogram_command_read_operands
		(renv, address, &pname, &args_list)) <= 0 )
		return ret;

	program_name = str_c(pname);
	if ( args_list != NULL &&
		sieve_stringlist_read_all(args_list, pool_datastack_create(), &args) < 0 ) {
		sieve_runtime_trace_error(renv, "failed to read args operand");
		return args_list->exec_status;
	}

	/*
	 * Perform operation
	 */

	/* Trace */

	sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "filter action");
	sieve_runtime_trace_descend(renv);
	sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS,
		"execute program `%s'", str_sanitize(program_name, 128));

	sprog = sieve_extprogram_create
		(this_ext, renv->scriptenv, renv->msgdata, "filter", program_name, args,
			&error);

	if ( sprog != NULL ) {
		struct mail *mail = sieve_message_get_mail(renv->msgctx);

		if ( sieve_extprogram_set_input_mail(sprog, mail) < 0 ) {
			sieve_extprogram_destroy(&sprog);
			return sieve_runtime_mail_error(renv, mail,
				"filter action: failed to read input message");
		}
		sieve_extprogram_set_output_seekable(sprog);
		ret = sieve_extprogram_run(sprog);
	} else {
		ret = -1;
	}

	if ( ret > 0 )
		newmsg = sieve_extprogram_get_output_seekable(sprog);
	if ( sprog != NULL )
		sieve_extprogram_destroy(&sprog);

	if ( ret > 0 && newmsg != NULL ) {
		sieve_runtime_trace(renv,	SIEVE_TRLVL_ACTIONS,
			"executed program successfully");

		i_stream_set_name(newmsg,
			t_strdup_printf("filter %s output", program_name));
		newmsg->blocking = TRUE;
		if ( (ret=sieve_message_substitute(renv->msgctx, newmsg)) >= 0 ) {
			sieve_runtime_trace(renv,	SIEVE_TRLVL_ACTIONS,
				"changed message");
		} else {
			sieve_runtime_critical(renv, NULL, "filter action",
				"filter action: failed to substitute message"); 
		}

		i_stream_unref(&newmsg);

	} else if ( ret < 0 ) {
		if ( error == SIEVE_ERROR_NOT_FOUND ) {
			sieve_runtime_error(renv, NULL,
				"filter action: program `%s' not found",
				str_sanitize(program_name, 80));
		} else {
			sieve_extprogram_exec_error(renv->ehandler,
				sieve_runtime_get_full_command_location(renv),
				"filter action: failed to execute to program `%s'",
				str_sanitize(program_name, 80));
		}

	} else {
		sieve_runtime_trace(renv,	SIEVE_TRLVL_ACTIONS,
			"filter action: program indicated false result");
	}

	if ( is_test > 0 ) {
		sieve_interpreter_set_test_result(renv->interp, ( ret > 0 ));

		return SIEVE_EXEC_OK;
	}

	return ( ret >= 0 ? SIEVE_EXEC_OK : SIEVE_EXEC_FAILURE );
}
Esempio n. 12
0
static void client_connected(struct master_service_connection *conn)
{
	enum mail_storage_service_flags flags =
		MAIL_STORAGE_SERVICE_FLAG_NO_PLUGINS;
	string_t *instr, *keys;
	const char **args, *key, *value, *error, *version_line, *data_line;
	struct mail_storage_service_ctx *service_ctx;
	struct mail_storage_service_input input;
	struct mail_storage_service_user *user;
	char buf[1024];
	unsigned int i, socket_count;
	int fd = -1;
	ssize_t ret;

	alarm(SCRIPT_LOGIN_READ_TIMEOUT_SECS);

	net_set_nonblock(conn->fd, FALSE);
	instr = t_str_new(1024);
	ret = fd_read(conn->fd, buf, sizeof(buf), &fd);
	while (ret > 0) {
		str_append_n(instr, buf, ret);
		if (buf[ret-1] == '\n' &&
		    strchr(str_c(instr), '\n')[1] != '\0') {
			str_truncate(instr, str_len(instr)-1);
			break;
		}

		ret = read(conn->fd, buf, sizeof(buf));
	}

	version_line = str_c(instr);
	data_line = strchr(version_line, '\n');
	if (data_line != NULL)
		version_line = t_strdup_until(version_line, data_line++);
	else
		version_line = NULL;

	if (ret > 0 || version_line != NULL) {
		if (version_line == NULL ||
		    !version_string_verify(version_line, "script-login",
				SCRIPT_LOGIN_PROTOCOL_VERSION_MAJOR)) {
			i_fatal("Client not compatible with this binary "
				"(connecting to wrong socket?)");
		}
	}

	if (ret <= 0) {
		if (ret < 0)
			i_fatal("read() failed: %m");
		else
			i_fatal("read() failed: disconnected");
	}
	if (fd == -1)
		i_fatal("client fd not received");

	/* put everything to environment */
	env_clean();
	keys = t_str_new(256);
	args = t_strsplit(data_line, "\t");

	if (str_array_length(args) < 3)
		i_fatal("Missing input fields");

	i = 0;
	memset(&input, 0, sizeof(input));
	input.module = "mail"; /* need to get mail_uid, mail_gid */
	input.service = "script-login";
	(void)net_addr2ip(args[i++], &input.local_ip);
	(void)net_addr2ip(args[i++], &input.remote_ip);
	input.username = args[i++];
	input.userdb_fields = args + i;

	env_put(t_strconcat("LOCAL_IP=", net_ip2addr(&input.local_ip), NULL));
	env_put(t_strconcat("IP=", net_ip2addr(&input.remote_ip), NULL));
	env_put(t_strconcat("USER="******"%s ", key);
		}
	}
	env_put(t_strconcat(ENV_USERDB_KEYS"=", str_c(keys), NULL));

	master_service_init_log(master_service,
		t_strdup_printf("script-login(%s): ", input.username));

	service_ctx = mail_storage_service_init(master_service, NULL, flags);
	if (mail_storage_service_lookup(service_ctx, &input, &user, &error) <= 0)
		i_fatal("%s", error);
	mail_storage_service_restrict_setenv(service_ctx, user);

	if (drop_privileges)
		restrict_access_by_env(getenv("HOME"), TRUE);

	if (dup2(fd, STDIN_FILENO) < 0)
		i_fatal("dup2() failed: %m");
	if (dup2(fd, STDOUT_FILENO) < 0)
		i_fatal("dup2() failed: %m");
	if (conn->fd != SCRIPT_COMM_FD) {
		if (dup2(conn->fd, SCRIPT_COMM_FD) < 0)
			i_fatal("dup2() failed: %m");
	}

	/* close all listener sockets */
	socket_count = master_service_get_socket_count(master_service);
	for (i = 0; i < socket_count; i++) {
		if (close(MASTER_LISTEN_FD_FIRST + i) < 0)
			i_error("close(listener) failed: %m");
	}
	if (close(MASTER_STATUS_FD) < 0)
		i_error("close(status) failed: %m");

	execvp_const(exec_args[0], exec_args);
}
Esempio n. 13
0
static int uri_parse_host(struct uri_parser *parser, struct uri_authority *auth)
{
	const unsigned char *preserve;
	struct in_addr ip4;
	struct in6_addr ip6;
	string_t *literal = NULL;
	int ret;

	/* RFC 3986:
	 *
	 * host          = IP-literal / IPv4address / reg-name
	 */

	literal = uri_parser_get_tmpbuf(parser, 256);

	/* IP-literal / */
	if (parser->cur < parser->end && *parser->cur == '[') {
#ifdef HAVE_IPV6
		if ((ret=uri_parse_ip_literal(parser, literal, &ip6)) <= 0)
			return -1;

		if (auth != NULL) {
			auth->host_literal = t_strdup(str_c(literal));
			auth->host_ip.family = AF_INET6;
			auth->host_ip.u.ip6 = ip6;
			auth->have_host_ip = TRUE;
		}
		return 1;
#else
		parser->error = "IPv6 host address is not supported";
		return -1;
#endif
	}

	/* IPv4address /
	 *
	 * If it fails to parse, we try to parse it as a reg-name
	 */
	preserve = parser->cur;
	if ((ret = uri_parse_ipv4address(parser, literal, &ip4)) > 0) {
		if (auth != NULL) {
			auth->host_literal = t_strdup(str_c(literal));
			auth->host_ip.family = AF_INET;
			auth->host_ip.u.ip4 = ip4;
			auth->have_host_ip = TRUE;
		}
		return ret;
	}
	parser->cur = preserve;
	str_truncate(literal, 0);

	/* reg-name */
	if ((ret = uri_parse_reg_name(parser, literal)) != 0) {
		if (ret > 0 && auth != NULL) {
			auth->host_literal = t_strdup(str_c(literal));
			auth->have_host_ip = FALSE;
		}
		return ret;
	}
	return 0;
}
Esempio n. 14
0
	net_set_nonblock(fd, FALSE);
	input = i_stream_create_fd(fd, (size_t)-1);

	cmd = t_str_new(10);
	str_append(cmd, "RESET");
/* XXX: Not supported yet.
	for(ptr = items; *ptr; ptr++)
	{
		str_append_c(cmd, '\t');
		str_append(cmd, *ptr);
	}
*/
	str_append_c(cmd, '\n');

	/* send command */
	ret = write_full(fd, str_c(cmd), str_len(cmd));

	if (ret < 0) {
		i_close_fd(&fd);
		i_error("write(%s) failed: %m", path);
		return;
	}

	line = i_stream_read_next_line(input);

	if (line == NULL) {
		i_error("read(%s) failed: %s", path, i_stream_get_error(input));
	} else if (strncmp(line, "OK", 2) != 0) {
		i_error("%s",line);
	} else {
		i_info("Stats reset");
Esempio n. 15
0
static bool cmd_copy_full(struct client_command_context *cmd, bool move)
{
	struct client *client = cmd->client;
	struct mail_storage *dest_storage;
	struct mailbox *destbox;
	struct mailbox_transaction_context *t, *src_trans;
        struct mail_search_args *search_args;
	const char *messageset, *mailbox, *src_uidset;
	enum mailbox_sync_flags sync_flags = 0;
	enum imap_sync_flags imap_flags = 0;
	struct mail_transaction_commit_changes changes;
	unsigned int copy_count;
	string_t *msg;
	int ret;

	/* <message set> <mailbox> */
	if (!client_read_string_args(cmd, 2, &messageset, &mailbox))
		return FALSE;

	if (!client_verify_open_mailbox(cmd))
		return TRUE;

	ret = imap_search_get_seqset(cmd, messageset, cmd->uid, &search_args);
	if (ret <= 0)
		return ret < 0;

	if (client_open_save_dest_box(cmd, mailbox, &destbox) < 0) {
		mail_search_args_unref(&search_args);
		return TRUE;
	}

	t = mailbox_transaction_begin(destbox,
				      MAILBOX_TRANSACTION_FLAG_EXTERNAL |
				      MAILBOX_TRANSACTION_FLAG_ASSIGN_UIDS);
	ret = fetch_and_copy(client, move, t, &src_trans, search_args,
			     &src_uidset, &copy_count);
	mail_search_args_unref(&search_args);

	msg = t_str_new(256);
	if (ret <= 0)
		mailbox_transaction_rollback(&t);
	else if (mailbox_transaction_commit_get_changes(&t, &changes) < 0) {
		if (mailbox_get_last_mail_error(destbox) == MAIL_ERROR_EXPUNGED) {
			/* storage backend didn't notice the expunge until
			   at commit time. */
			ret = 0;
		} else {
			ret = -1;
		}
	} else if (copy_count == 0) {
		str_append(msg, "OK No messages found.");
		pool_unref(&changes.pool);
	} else if (seq_range_count(&changes.saved_uids) == 0 ||
		   changes.no_read_perm) {
		/* not supported by backend (virtual) or no read permissions
		   for mailbox */
		str_append(msg, move ? "OK Move completed." :
			   "OK Copy completed.");
		pool_unref(&changes.pool);
	} else if (move) {
		i_assert(copy_count == seq_range_count(&changes.saved_uids));
		copy_update_trashed(client, destbox, copy_count);

		str_printfa(msg, "* OK [COPYUID %u %s ",
			    changes.uid_validity, src_uidset);
		imap_write_seq_range(msg, &changes.saved_uids);
		str_append(msg, "] Moved UIDs.");
		client_send_line(client, str_c(msg));

		str_truncate(msg, 0);
		str_append(msg, "OK Move completed.");
		pool_unref(&changes.pool);
	} else {
		i_assert(copy_count == seq_range_count(&changes.saved_uids));
		copy_update_trashed(client, destbox, copy_count);

		str_printfa(msg, "OK [COPYUID %u %s ", changes.uid_validity,
			    src_uidset);
		imap_write_seq_range(msg, &changes.saved_uids);
		str_append(msg, "] Copy completed.");
		pool_unref(&changes.pool);
	}

	if (ret <= 0 && move) {
		/* move failed, don't expunge anything */
		mailbox_transaction_rollback(&src_trans);
	} else {
		if (mailbox_transaction_commit(&src_trans) < 0)
			ret = -1;
	}

 	dest_storage = mailbox_get_storage(destbox);
	if (destbox != client->mailbox) {
		if (move)
			sync_flags |= MAILBOX_SYNC_FLAG_EXPUNGE;
		else
			sync_flags |= MAILBOX_SYNC_FLAG_FAST;
		imap_flags |= IMAP_SYNC_FLAG_SAFE;
		mailbox_free(&destbox);
	} else if (move) {
		sync_flags |= MAILBOX_SYNC_FLAG_EXPUNGE;
		imap_flags |= IMAP_SYNC_FLAG_SAFE;
	}

	if (ret > 0)
		return cmd_sync(cmd, sync_flags, imap_flags, str_c(msg));
	else if (ret == 0) {
		/* some messages were expunged, sync them */
		return cmd_sync(cmd, 0, 0,
			"NO ["IMAP_RESP_CODE_EXPUNGEISSUED"] "
			"Some of the requested messages no longer exist.");
	} else {
		client_send_storage_error(cmd, dest_storage);
		return TRUE;
	}
}
Esempio n. 16
0
static int json_parse_string(struct json_parser *parser, bool allow_skip,
			     const char **value_r)
{
	if (*parser->data != '"')
		return -1;
	parser->data++;

	if (parser->skipping && allow_skip) {
		*value_r = NULL;
		return json_skip_string(parser);
	}

	str_truncate(parser->value, 0);
	for (; parser->data != parser->end; parser->data++) {
		if (*parser->data == '"') {
			parser->data++;
			*value_r = str_c(parser->value);
			return 1;
		}
		if (*parser->data != '\\')
			str_append_c(parser->value, *parser->data);
		else {
			if (++parser->data == parser->end)
				return 0;
			switch (*parser->data) {
			case '"':
			case '\\':
			case '/':
				str_append_c(parser->value, *parser->data);
				break;
			case 'b':
				str_append_c(parser->value, '\b');
				break;
			case 'f':
				str_append_c(parser->value, '\f');
				break;
			case 'n':
				str_append_c(parser->value, '\n');
				break;
			case 'r':
				str_append_c(parser->value, '\r');
				break;
			case 't':
				str_append_c(parser->value, '\t');
				break;
			case 'u':
				parser->data++;
				if (parser->end - parser->data < 4) {
					/* wait for more data */
					parser->data = parser->end;
					return 0;
				}
				uni_ucs4_to_utf8_c(hex2dec(parser->data, 4),
						   parser->value);
				parser->data += 3;
				break;
			default:
				return -1;
			}
		}
	}
	return 0;
}
};

bool ext_variables_namespace_argument_activate
(const struct sieve_extension *this_ext, struct sieve_validator *valdtr,
	struct sieve_ast_argument *arg, struct sieve_command *cmd,
	ARRAY_TYPE(sieve_variable_name) *var_name, bool assignment)
{
	pool_t pool = sieve_command_pool(cmd);
	struct sieve_ast *ast = arg->ast;
	const struct sieve_variables_namespace *nspc;
	struct arg_namespace_variable *var;
	const struct sieve_variable_name *name_element = array_idx(var_name, 0);
	void *var_data = NULL;

	nspc = ext_variables_namespace_create_instance
		(this_ext, valdtr, cmd, str_c(name_element->identifier));
	if ( nspc == NULL ) {
		sieve_argument_validate_error(valdtr, arg,
			"referring to variable in unknown namespace '%s'",
			str_c(name_element->identifier));
		return FALSE;
	}

	if ( nspc->def != NULL && nspc->def->validate != NULL &&
		!nspc->def->validate
			(valdtr, nspc, arg, cmd, var_name, &var_data, assignment) ) {
		return FALSE;
	}

	var = p_new(pool, struct arg_namespace_variable, 1);
	var->namespace = nspc;
Esempio n. 18
0
File: qplot.cpp Progetto: beg0/qplot
//----------------------------------------------------------------------------
qplot_xy_t qplot_read_text(
  const std::string file, long start, long size, long step,
  char separator, int xCol, int yCol)
{
  qplot_xy_t data;
  data.size = 0;

  qDebug("qplot_read_text(file='%s')", file.c_str());
  
  long cnt = 0;
  long step_cnt = 0;

  if (xCol < 0 && yCol < 0)
    return data; // stupid mission

  std::ifstream fs(file.c_str());
  std::string line;
  while (std::getline(fs, line))
  {
    if (start != 0)
    {
      start--;
      continue;
    }

    if (step_cnt-- != 0)
      continue;
    step_cnt = step - 1;

    if (size != -1 && cnt >= size)
      break;

    std::stringstream str_stream(line);
    std::string cell;
    std::vector<std::string> cells;
    cells.clear();

    while (std::getline(str_stream, cell, separator))
    { //!!! FIXME (use standart trim algoritm next time)
      str_t str = str_cstr(cell.c_str());
      str_t str_trimmed = str_trim(&str);
      
      if (separator == ' ')
      {
        if (str_size(&str_trimmed))
          cells.push_back(str_c(&str_trimmed));
      }
      else
        cells.push_back(str_c(&str_trimmed));
      
      str_free(&str_trimmed);
      str_free(&str);
    }

    if (yCol < 0)
    { // xCol >= 0 && yCol < 0
      if ((int) cells.size() > xCol)
        if (cells[yCol].size())
        {
          data.x.push_back(atof(cells[xCol].c_str()));
          data.y.push_back((double) cnt);
					cnt++;
        }
    }
    else if (xCol < 0)
    { // xCol < 0 && yCol >= 0
      if ((int) cells.size() > yCol)
        if (cells[yCol].size())
        {
          data.x.push_back((double) cnt);
          data.y.push_back(atof(cells[yCol].c_str()));
					cnt++;
        }
    }
    else
    { // xCol >= 0 && yCol >= 0
      if ((int) cells.size() > xCol && (int) cells.size() > yCol)
        if (cells[xCol].size() && cells[yCol].size())
        {
          data.x.push_back(atof(cells[xCol].c_str()));
          data.y.push_back(atof(cells[yCol].c_str()));
					cnt++;
        }
    }
  } // while (std::getline(fs, line))

  data.size = cnt;
  return data;
}
Esempio n. 19
0
int index_sort_node_cmp_type(struct mail_search_sort_program *program,
			     const enum mail_sort_type *sort_program,
			     uint32_t seq1, uint32_t seq2)
{
	struct mail *mail = program->temp_mail;
	enum mail_sort_type sort_type;
	time_t time1, time2;
	uoff_t size1, size2;
	float float1, float2;
	int tz, ret = 0;

	sort_type = *sort_program & MAIL_SORT_MASK;
	switch (sort_type) {
	case MAIL_SORT_CC:
	case MAIL_SORT_FROM:
	case MAIL_SORT_TO:
	case MAIL_SORT_SUBJECT:
	case MAIL_SORT_DISPLAYFROM:
	case MAIL_SORT_DISPLAYTO:
		T_BEGIN {
			string_t *str1, *str2;

			str1 = t_str_new(256);
			str2 = t_str_new(256);
			if (index_sort_header_get(program, seq1, sort_type, str1) < 0)
				index_sort_program_set_mail_failed(program, mail);
			if (index_sort_header_get(program, seq2, sort_type, str2) < 0)
				index_sort_program_set_mail_failed(program, mail);

			ret = strcmp(str_c(str1), str_c(str2));
		} T_END;
		break;
	case MAIL_SORT_ARRIVAL:
		index_sort_set_seq(program, mail, seq1);
		if (mail_get_received_date(mail, &time1) < 0)
			time1 = index_sort_program_set_date_failed(program, mail);

		index_sort_set_seq(program, mail, seq2);
		if (mail_get_received_date(mail, &time2) < 0)
			time2 = index_sort_program_set_date_failed(program, mail);

		ret = time1 < time2 ? -1 :
			(time1 > time2 ? 1 : 0);
		break;
	case MAIL_SORT_DATE:
		index_sort_set_seq(program, mail, seq1);
		if (mail_get_date(mail, &time1, &tz) < 0)
			time1 = index_sort_program_set_date_failed(program, mail);
		else if (time1 == 0) {
			if (mail_get_received_date(mail, &time1) < 0)
				time1 = index_sort_program_set_date_failed(program, mail);
		}

		index_sort_set_seq(program, mail, seq2);
		if (mail_get_date(mail, &time2, &tz) < 0)
			time2 = index_sort_program_set_date_failed(program, mail);
		else if (time2 == 0) {
			if (mail_get_received_date(mail, &time2) < 0)
				time2 = index_sort_program_set_date_failed(program, mail);
		}

		ret = time1 < time2 ? -1 :
			(time1 > time2 ? 1 : 0);
		break;
	case MAIL_SORT_SIZE:
		index_sort_set_seq(program, mail, seq1);
		if (mail_get_virtual_size(mail, &size1) < 0) {
			index_sort_program_set_mail_failed(program, mail);
			size1 = 0;
		}

		index_sort_set_seq(program, mail, seq2);
		if (mail_get_virtual_size(mail, &size2) < 0) {
			index_sort_program_set_mail_failed(program, mail);
			size2 = 0;
		}

		ret = size1 < size2 ? -1 :
			(size1 > size2 ? 1 : 0);
		break;
	case MAIL_SORT_RELEVANCY:
		index_sort_set_seq(program, mail, seq1);
		if (index_sort_get_relevancy(mail, &float1) < 0)
			index_sort_program_set_mail_failed(program, mail);
		index_sort_set_seq(program, mail, seq2);
		if (index_sort_get_relevancy(mail, &float2) < 0)
			index_sort_program_set_mail_failed(program, mail);

		/* NOTE: higher relevancy is returned first, unlike with all
		   other number based sort keys */
		ret = float1 < float2 ? 1 :
			(float1 > float2 ? -1 : 0);
		break;
	case MAIL_SORT_POP3_ORDER:
		/* 32bit numbers would be enough, but since there is already
		   existing code for uoff_t in sizes, just use them. */
		index_sort_set_seq(program, mail, seq1);
		if (index_sort_get_pop3_order(mail, &size1) < 0)
			index_sort_program_set_mail_failed(program, mail);
		index_sort_set_seq(program, mail, seq2);
		if (index_sort_get_pop3_order(mail, &size2) < 0)
			index_sort_program_set_mail_failed(program, mail);

		ret = size1 < size2 ? -1 :
			(size1 > size2 ? 1 : 0);
		break;
	case MAIL_SORT_END:
		return seq1 < seq2 ? -1 :
			(seq1 > seq2 ? 1 : 0);
	case MAIL_SORT_MASK:
	case MAIL_SORT_FLAG_REVERSE:
		i_unreached();
	}

	if (ret == 0) {
		return index_sort_node_cmp_type(program, sort_program+1,
						seq1, seq2);
	}

	if ((*sort_program & MAIL_SORT_FLAG_REVERSE) != 0)
		ret = ret < 0 ? 1 : -1;
	return ret;
}
Esempio n. 20
0
File: qplot.cpp Progetto: beg0/qplot
//----------------------------------------------------------------------------
// run by mission INI-file
bool qplot_run(
  const char  *mission_file, // имя INI-файла задания
  PlotArea    *pa,           // указатель на PlotArea : QwtPlot widget
  QMainWindow *mw)           // указатель на PlotWin  : QMainWindow
{
  qDebug("qplot_run(mission_file='%s')", mission_file);

  // open mission INI-file
  aclass::aini f(mission_file);

  std::string title = f.read_str("", "title", "");
  if (!title.size())
    title = mission_file;
  mw->setWindowTitle("QPlot - " + _QS(title));

  QSize wsize = mw->size();
  int width = (int) f.read_long("", "width", -1);
  if (width > 0) wsize.setWidth(width);
  int height = (int) f.read_long("", "height", -1);
  if (height > 0) wsize.setHeight(height);
  if (width > 0 || height > 0) mw->resize(wsize);

  // read [area] section
  PlotAreaConf conf = pa->getConf();
  qplot_read_conf(&f, "area", &conf);
  pa->setConf(conf);

  // off all markers
  pa->enableMarker(false);
  pa->enableVLine(false);
  pa->enableHLine(false);

  // read [axis] section
  qplot_read_axis(&f, "axis", pa);

  if (!f.has_section("0") && !f.has_section("1"))
    return false; // no curve section

  // remove all old curves
  pa->clear();

  // read curve description sections [0], [1], [2], ...
  int begin = (int) f.read_long("", "begin", 0);
  int end   = (int) f.read_long("", "end", 100);
  for (int i = begin; i <= end; i++)
  {
    qplot_xy_t data;

    str_t tmp = str_int(i);
    std::string s = str_c(&tmp);
    str_free(&tmp);
    if (!f.has_section(s)) continue;

    std::string file = f.read_str(s, "file", "");
    if (file.size() == 0) continue;

    long start = f.read_long(s, "start", 0);
    long size  = f.read_long(s, "size", -1);
    long step  = f.read_long(s, "step",  1);
    if (step <= 0) step = 1;

    std::string fmt = f.read_str(s, "format", "txt");
    if (_STRCMP(fmt, "bin"   ) == 0 ||
        _STRCMP(fmt, "binary") == 0 ||
        _STRCMP(fmt, "raw"   ) == 0)
    { // binary data file format
      long recordSize = f.read_long(s, "recordSize");
      if (recordSize <= 0)
      {
        qDebug("recordSize = %li, skip [%i] section",
               recordSize, i);
        continue;
      }

      int xOff = (int) f.read_long(s, "xOff", -1);
      int yOff = (int) f.read_long(s, "yOff", -1);

      std::string type = f.read_str(s, "xType", "float");
      int xType = qplot_id_by_type(type);

      type = f.read_str(s, "yType", "float");
      int yType = qplot_id_by_type(type);

      data = qplot_read_binary(file, start, size, step,
                               recordSize, xType, yType, xOff, yOff);
    }
    else
    { // text data file format
      std::string sep = f.read_str(s, "separator", " ");
      char separator = (sep.size() > 0) ? sep[0] : ' ';

      int xCol = (int) f.read_long(s, "xCol", -1);
      int yCol = (int) f.read_long(s, "yCol", -1);

      data = qplot_read_text(file, start, size, step,
                             separator, xCol, yCol);
    }

    if (data.size <= 0)
    {
      qDebug("data.size = %i, skip [%i] section", data.size, i);
      continue;
    }

    CurveConf conf;
    conf.legend = _QS(f.read_str(s, "legend", ""));

    conf.curve = qplot_qwt_curve_by_name(f.read_str(s, "curve", "lines"));

    conf.pen = QPen(
      QColor(f.read_str(s, "color", "black").c_str()),
      f.read_double(s, "width", conf.curve == QwtPlotCurve::Dots ? 3.0 : 1.0),
      qplot_pen_by_name(f.read_str(s, "style", "solid")));

    conf.symStyle = qplot_qwt_symbol_by_name(
      f.read_str(s, "symbol", "no"));

    conf.symPen = QPen(
      QColor(f.read_str(s, "symColor", "blue").c_str()),
      f.read_double(s, "symWidth", 1.0),
      Qt::SolidLine);

    conf.symBrush = QBrush(
      QColor(f.read_str(s, "symBrush", "gray").c_str()));

    conf.symSize = (int) f.read_long(s, "symSize", 7);

    std::string axis = f.read_str(s, "axisX", "Bottom");
    conf.xAxis = !_STRCMP(axis, "Top") ? QwtPlot::xTop : QwtPlot::xBottom;

    axis = f.read_str(s, "axisY", "Left");
    conf.yAxis = !_STRCMP(axis, "Right") ? QwtPlot::yRight : QwtPlot::yLeft;

		if (data.size)
      //pa->addCurve(data.x.data(), data.y.data(), data.size, conf /*, false*/);
      pa->addCurve(&data.x[0], &data.y[0], data.size, conf /*, false*/);
  } // for (int i = 0; i < num; i++)

  pa->redraw();
  return true;
}
Esempio n. 21
0
static bool cmd_putscript_finish_parsing(struct client_command_context *cmd)
{
	struct client *client = cmd->client;
	struct cmd_putscript_context *ctx = cmd->context;
	const struct managesieve_arg *args;
	int ret;

	/* if error occurs, the CRLF is already read. */
	client->input_skip_line = FALSE;

	/* <script literal> */
	ret = managesieve_parser_read_args(ctx->save_parser, 0, 0, &args);
	if (ret == -1 || client->output->closed) {
		if (ctx->storage != NULL)
			client_send_command_error(cmd, NULL);
		cmd_putscript_finish(ctx);
		return TRUE;
	}
	if (ret < 0) {
		/* need more data */
		return FALSE;
	}

	if ( MANAGESIEVE_ARG_IS_EOL(&args[0]) ) {
		struct sieve_script *script;
		bool success = TRUE;

		/* Eat away the trailing CRLF */
		client->input_skip_line = TRUE;

		/* Obtain script object for uploaded script */
		script = sieve_storage_save_get_tempscript(ctx->save_ctx);

		/* Check result */
		if ( script == NULL ) {
			client_send_storage_error(client, ctx->storage);
			cmd_putscript_finish(ctx);
			return TRUE;
		}

		/* If quoted string, the size was not known until now */
		if ( ctx->script_size == 0 ) {
			if (sieve_script_get_size(script, &ctx->script_size) < 0) {
				client_send_storage_error(client, ctx->storage);
				cmd_putscript_finish(ctx);
				return TRUE;
			}
			/* Check quota; max size is already checked */
			if ( ctx->scriptname != NULL && !managesieve_quota_check_all
					(client, ctx->scriptname, ctx->script_size) ) {
				cmd_putscript_finish(ctx);
				return TRUE;
			}
		}

		/* Try to compile script */
		T_BEGIN {
			struct sieve_error_handler *ehandler;
			enum sieve_compile_flags cpflags =
				SIEVE_COMPILE_FLAG_NOGLOBAL | SIEVE_COMPILE_FLAG_UPLOADED;
			struct sieve_binary *sbin;
			enum sieve_error error;
			string_t *errors;

			/* Mark this as an activation when we are replacing the active script */
			if ( sieve_storage_save_will_activate(ctx->save_ctx) ) {
				cpflags |= SIEVE_COMPILE_FLAG_ACTIVATED;
			}

			/* Prepare error handler */
			errors = str_new(default_pool, 1024);
			ehandler = sieve_strbuf_ehandler_create(client->svinst, errors, TRUE,
				client->set->managesieve_max_compile_errors);

			/* Compile */
			if ( (sbin=sieve_compile_script
				(script, ehandler, cpflags, &error)) == NULL ) {
				if ( error != SIEVE_ERROR_NOT_VALID ) {
					const char *errormsg =
						sieve_script_get_last_error(script, &error);
					if ( error != SIEVE_ERROR_NONE )
						client_send_no(client, errormsg);
					else
						client_send_no(client, str_c(errors));
				} else {
					client_send_no(client, str_c(errors));
				}
				success = FALSE;
			} else {
				sieve_close(&sbin);

				/* Commit to save only when this is a putscript command */
				if ( ctx->scriptname != NULL ) {
					ret = sieve_storage_save_commit(&ctx->save_ctx);

					/* Check commit */
					if (ret < 0) {
						client_send_storage_error(client, ctx->storage);
						success = FALSE;
					}
				}
			}

			/* Finish up */
			cmd_putscript_finish(ctx);

			/* Report result to user */
			if ( success ) {
				if ( ctx->scriptname != NULL ) {
					client->put_count++;
					client->put_bytes += ctx->script_size;
				} else {
					client->check_count++;
					client->check_bytes += ctx->script_size;
				}

				if ( sieve_get_warnings(ehandler) > 0 )
					client_send_okresp(client, "WARNINGS", str_c(errors));
				else {
					if ( ctx->scriptname != NULL )
						client_send_ok(client, "PUTSCRIPT completed.");
					else
						client_send_ok(client, "Script checked successfully.");
				}
			}

			sieve_error_handler_unref(&ehandler);
			str_free(&errors);
		} T_END;

		return TRUE;
	}

	client_send_command_error(cmd, "Too many command arguments.");
	cmd_putscript_finish(ctx);
	return TRUE;
}
Esempio n. 22
0
int ext_enotify_runtime_check_operands
(const struct sieve_runtime_env *renv,
	string_t *method_uri, string_t *message, string_t *from,
	struct sieve_stringlist *options,
	const struct sieve_enotify_method **method_r, void **method_context)
{
	const struct sieve_enotify_method *method;
	const char *uri_body;

	/* Get method */
	method = ext_enotify_get_method(renv, method_uri, &uri_body);
	if ( method == NULL ) return SIEVE_EXEC_FAILURE;

	/* Check provided operands */
	if ( method->def != NULL && method->def->runtime_check_operands != NULL ) {
		struct sieve_enotify_env nenv;
		int result = SIEVE_EXEC_OK;

		memset(&nenv, 0, sizeof(nenv));
		nenv.svinst = renv->svinst;
		nenv.method = method;
		nenv.ehandler = sieve_prefix_ehandler_create
			(renv->ehandler, sieve_runtime_get_full_command_location(renv),
				"notify action");

		/* Execute check function */
		if ( method->def->runtime_check_operands
			(&nenv, str_c(method_uri), uri_body, message, from,
				sieve_result_pool(renv->result), method_context) ) {

			/* Check any provided options */
			if ( options != NULL ) {
				string_t *option = NULL;
				int ret;

				/* Iterate through all provided options */
				while ( (ret=sieve_stringlist_next_item(options, &option)) > 0 ) {
					const char *opt_name = NULL, *opt_value = NULL;

					/* Parse option into <optionname> and <value> */
					if ( ext_enotify_option_parse
						(&nenv, str_c(option), FALSE, &opt_name, &opt_value) ) {

						/* Set option */
						if ( method->def->runtime_set_option != NULL ) {
							(void) method->def->runtime_set_option
								(&nenv, *method_context, opt_name, opt_value);
						}
					}
				}

				/* Check for binary corruptions encountered during string list iteration
				 */
				if ( ret >= 0 ) {
					*method_r = method;
				} else {
					/* Binary corrupt */
					sieve_runtime_trace_error
						(renv, "invalid item in options string list");
					result = SIEVE_EXEC_BIN_CORRUPT;
				}

			} else {
				/* No options */
				*method_r = method;
			}

		} else {
			/* Operand check failed */
			result = SIEVE_EXEC_FAILURE;
		}

		sieve_error_handler_unref(&nenv.ehandler);
		return result;
	}

	/* No check function defined: a most unlikely situation */
	*method_context = NULL;
	*method_r = method;
	return SIEVE_EXEC_OK;
}
Esempio n. 23
0
static int client_fetch_url(struct client *client, const char *url,
			    enum imap_urlauth_fetch_flags url_flags)
{
	string_t *response;
	const char *bpstruct, *errormsg;
	bool binary_with_nuls;
	int ret;

	i_assert(client->url == NULL);

	client->msg_part_size = 0;
	client->msg_part_input = NULL;

	if (client->debug)
		i_debug("Fetching URLAUTH %s", url);

	/* fetch URL */
	ret = client_fetch_urlpart(client, url, url_flags, &bpstruct,
				   &binary_with_nuls, &errormsg);
	if (ret <= 0) {
		/* fetch failed */
		if (client->url != NULL)
			imap_msgpart_url_free(&client->url);
		/* don't send error details to anonymous users: just to be sure
		   that no information about the target user account is unduly
		   leaked. */
		if (client->access_anonymous || errormsg == NULL)
			client_send_line(client, "NO");
		else {
			client_send_line(client, "NO\terror=%s",
					 str_tabescape(errormsg));
		}
		if (ret < 0) {
			/* fetch failed badly */
			client_abort(client, "Session aborted: Fatal failure while fetching URL");
		}
		return 0;
	}

	response = t_str_new(256);
	str_append(response, "OK");
	if (binary_with_nuls)
		str_append(response, "\thasnuls");
	if (bpstruct != NULL) {
		str_append(response, "\tbpstruct=");
		str_append(response, str_tabescape(bpstruct));
		if (client->debug) {
			i_debug("Fetched URLAUTH yielded BODYPARTSTRUCTURE (%s)",
				bpstruct);
		}
	}

	/* return content */
	o_stream_cork(client->output);
	if (client->msg_part_size == 0 || client->msg_part_input == NULL) {
		/* empty */
		str_append(response, "\t0");
		client_send_line(client, "%s", str_c(response));

		imap_msgpart_url_free(&client->url);
		client->url = NULL;
		if (client->debug)
			i_debug("Fetched URLAUTH yielded empty result");
	} else {

		/* actual content */
		str_printfa(response, "\t%"PRIuUOFF_T, client->msg_part_size);
		client_send_line(client, "%s", str_c(response));

		if (client->debug) {
			i_debug("Fetched URLAUTH yielded %"PRIuUOFF_T" bytes "
				"of %smessage data", client->msg_part_size,
				(binary_with_nuls ? "binary " : ""));
		}
		if (client_run_url(client) < 0) {
			client_abort(client,
				"Session aborted: Fatal failure while transfering URL");
			return 0;
		}		
	}

	if (client->url != NULL) {
		/* URL not finished */
		o_stream_set_flush_pending(client->output, TRUE);
		client->waiting_input = TRUE;
	}
	o_stream_uncork(client->output);
	return client->url != NULL ? 0 : 1;
}
Esempio n. 24
0
int str_to_int(const str *string, int *result) {
    *result = atoi(str_c(string));
    return 1;
}
Esempio n. 25
0
mkdir_chown_full(const char *path, mode_t mode, uid_t uid,
		 gid_t gid, const char *gid_origin)
{
	string_t *str;
	mode_t old_mask;
	int ret, orig_errno;

	old_mask = umask(0);
	ret = mkdir(path, mode);
	umask(old_mask);

	if (ret < 0) {
		if (errno == EISDIR || errno == ENOSYS) {
			/* EISDIR check is for BSD/OS which returns it if path
			   contains '/' at the end and it exists.

			   ENOSYS check is for NFS mount points. */
			errno = EEXIST;
		}
		return -1;
	}
	if (chown(path, uid, gid) < 0) {
		orig_errno = errno;
		if (rmdir(path) < 0)
			i_error("rmdir(%s) failed: %m", path);
		errno = orig_errno;

		if (errno == EPERM && uid == (uid_t)-1) {
			i_error("%s", eperm_error_get_chgrp("chown", path, gid,
							    gid_origin));
			return -1;
		}

		str = t_str_new(256);
		str_printfa(str, "chown(%s, %ld", path,
			    uid == (uid_t)-1 ? -1L : (long)uid);
		if (uid != (uid_t)-1) {
			struct passwd pw;

			if (i_getpwuid(uid, &pw) > 0)
				str_printfa(str, "(%s)", pw.pw_name);

		}
		str_printfa(str, ", %ld",
			    gid == (gid_t)-1 ? -1L : (long)gid);
		if (gid != (gid_t)-1) {
			struct group gr;

			if (i_getgrgid(uid, &gr) > 0)
				str_printfa(str, "(%s)", gr.gr_name);
		}
		errno = orig_errno;
		i_error("%s) failed: %m", str_c(str));
		return -1;
	}
	if (gid != (gid_t)-1 && (mode & S_ISGID) == 0) {
		/* make sure the directory doesn't have setgid bit enabled
		   (in case its parent had) */
		if (chmod(path, mode) < 0) {
			orig_errno = errno;
			if (rmdir(path) < 0)
				i_error("rmdir(%s) failed: %m", path);
			errno = orig_errno;
			i_error("chmod(%s) failed: %m", path);
			return -1;
		}
	}
	return 0;
}
Esempio n. 26
0
int str_to_float(const str *string, float *result) {
    *result = atof(str_c(string));
    return 1;
}
Esempio n. 27
0
int index_sort_node_cmp_type(struct mail *mail,
			     const enum mail_sort_type *sort_program,
			     uint32_t seq1, uint32_t seq2)
{
	enum mail_sort_type sort_type;
	time_t time1, time2;
	uoff_t size1, size2;
	float float1, float2;
	int ret = 0;

	sort_type = *sort_program & MAIL_SORT_MASK;
	switch (sort_type) {
	case MAIL_SORT_CC:
	case MAIL_SORT_FROM:
	case MAIL_SORT_TO:
	case MAIL_SORT_SUBJECT:
	case MAIL_SORT_DISPLAYFROM:
	case MAIL_SORT_DISPLAYTO:
		T_BEGIN {
			string_t *str1, *str2;

			str1 = t_str_new(256);
			str2 = t_str_new(256);
			index_sort_header_get(mail, seq1, sort_type, str1);
			index_sort_header_get(mail, seq2, sort_type, str2);

			ret = strcmp(str_c(str1), str_c(str2));
		} T_END;
		break;
	case MAIL_SORT_ARRIVAL:
		mail_set_seq(mail, seq1);
		if (mail_get_received_date(mail, &time1) < 0)
			time1 = 0;

		mail_set_seq(mail, seq2);
		if (mail_get_received_date(mail, &time2) < 0)
			time1 = 0;

		ret = time1 < time2 ? -1 :
			(time1 > time2 ? 1 : 0);
		break;
	case MAIL_SORT_DATE:
		mail_set_seq(mail, seq1);
		if (mail_get_date(mail, &time1, NULL) < 0)
			time1 = 0;
		else if (time1 == 0) {
			if (mail_get_received_date(mail, &time1) < 0)
				time1 = 0;
		}

		mail_set_seq(mail, seq2);
		if (mail_get_date(mail, &time2, NULL) < 0)
			time2 = 0;
		else if (time2 == 0) {
			if (mail_get_received_date(mail, &time2) < 0)
				time2 = 0;
		}

		ret = time1 < time2 ? -1 :
			(time1 > time2 ? 1 : 0);
		break;
	case MAIL_SORT_SIZE:
		mail_set_seq(mail, seq1);
		if (mail_get_virtual_size(mail, &size1) < 0)
			size1 = 0;

		mail_set_seq(mail, seq2);
		if (mail_get_virtual_size(mail, &size2) < 0)
			size2 = 0;

		ret = size1 < size2 ? -1 :
			(size1 > size2 ? 1 : 0);
		break;
	case MAIL_SORT_SEARCH_SCORE:
		mail_set_seq(mail, seq1);
		float1 = index_sort_get_score(mail);
		mail_set_seq(mail, seq2);
		float2 = index_sort_get_score(mail);

		ret = float1 < float2 ? -1 :
			(float1 > float2 ? 1 : 0);
		break;
	case MAIL_SORT_END:
		return seq1 < seq2 ? -1 :
			(seq1 > seq2 ? 1 : 0);
	case MAIL_SORT_MASK:
	case MAIL_SORT_FLAG_REVERSE:
		i_unreached();
	}

	if (ret == 0) {
		return index_sort_node_cmp_type(mail, sort_program+1,
						seq1, seq2);
	}

	if ((*sort_program & MAIL_SORT_FLAG_REVERSE) != 0)
		ret = ret < 0 ? 1 : -1;
	return ret;
}
Esempio n. 28
0
int str_to_long(const str *string, long *result) {
    *result = atol(str_c(string));
    return 1;
}
Esempio n. 29
0
void imap_client_auth_result(struct client *client,
			     enum client_auth_result result,
			     const struct client_auth_reply *reply,
			     const char *text)
{
	struct imap_url url;
	string_t *referral;

	switch (result) {
	case CLIENT_AUTH_RESULT_SUCCESS:
		/* nothing to be done for IMAP */
		break;
	case CLIENT_AUTH_RESULT_REFERRAL_SUCCESS:
	case CLIENT_AUTH_RESULT_REFERRAL_NOLOGIN:
		/* IMAP referral

		   [nologin] referral host=.. [port=..] [destuser=..]
		   [reason=..]

		   NO [REFERRAL imap://destuser;AUTH=..@host:port/] Can't login.
		   OK [...] Logged in, but you should use this server instead.
		   .. [REFERRAL ..] (Reason from auth server)
		*/
		referral = t_str_new(128);

		i_zero(&url);
		url.userid = reply->destuser;
		url.auth_type = client->auth_mech_name;
		url.host.name = reply->host;
		if (reply->port != 143)
			url.port = reply->port;
		str_append(referral, "REFERRAL ");
		str_append(referral, imap_url_create(&url));

		if (result == CLIENT_AUTH_RESULT_REFERRAL_SUCCESS) {
			client_send_reply_code(client, IMAP_CMD_REPLY_OK,
					       str_c(referral), text);
		} else {
			client_send_reply_code(client, IMAP_CMD_REPLY_NO,
					       str_c(referral), text);
		}
		break;
	case CLIENT_AUTH_RESULT_INVALID_BASE64:
	case CLIENT_AUTH_RESULT_ABORTED:
		client_send_reply(client, IMAP_CMD_REPLY_BAD, text);
		break;
	case CLIENT_AUTH_RESULT_AUTHFAILED_REASON:
	case CLIENT_AUTH_RESULT_MECH_INVALID:
		if (text[0] == '[')
			client_send_reply(client, IMAP_CMD_REPLY_NO, text);
		else {
			client_send_reply_code(client, IMAP_CMD_REPLY_NO,
					       "ALERT", text);
		}
		break;
	case CLIENT_AUTH_RESULT_AUTHZFAILED:
		client_send_reply_code(client, IMAP_CMD_REPLY_NO,
				       IMAP_RESP_CODE_AUTHZFAILED, text);
		break;
	case CLIENT_AUTH_RESULT_TEMPFAIL:
		client_send_reply_code(client, IMAP_CMD_REPLY_NO,
				       IMAP_RESP_CODE_UNAVAILABLE, text);
		break;
	case CLIENT_AUTH_RESULT_SSL_REQUIRED:
	case CLIENT_AUTH_RESULT_MECH_SSL_REQUIRED:
		client_send_reply_code(client, IMAP_CMD_REPLY_NO,
				       IMAP_RESP_CODE_PRIVACYREQUIRED, text);
		break;
	case CLIENT_AUTH_RESULT_PASS_EXPIRED:
		client_send_reply_code(client, IMAP_CMD_REPLY_NO,
				       IMAP_RESP_CODE_EXPIRED, text);
		break;
	case CLIENT_AUTH_RESULT_LOGIN_DISABLED:
		client_send_reply_code(client, IMAP_CMD_REPLY_NO,
				       IMAP_RESP_CODE_CONTACTADMIN, text);
		break;
	case CLIENT_AUTH_RESULT_AUTHFAILED:
		client_send_reply_code(client, IMAP_CMD_REPLY_NO,
				       IMAP_RESP_CODE_AUTHFAILED, text);
		break;
	}
}
Esempio n. 30
0
static int
imap_master_client_input_args(struct connection *conn, const char *const *args,
			      int fd_client, pool_t pool)
{
	struct imap_master_client *client = (struct imap_master_client *)conn;
	struct client *imap_client;
	struct mail_storage_service_input input;
	struct imap_master_input master_input;
	const char *error;
	int ret;

	if (imap_master_client_parse_input(args, pool, &input, &master_input,
					   &error) < 0) {
		i_error("imap-master: Failed to parse client input: %s", error);
		o_stream_nsend_str(conn->output, t_strdup_printf(
			"-Failed to parse client input: %s\n", error));
		i_close_fd(&fd_client);
		return -1;
	}
	if (imap_master_client_verify(&master_input, fd_client, &error) < 0) {
		i_error("imap-master: Failed to verify client input: %s", error);
		o_stream_nsend_str(conn->output, t_strdup_printf(
			"-Failed to verify client input: %s\n", error));
		i_close_fd(&fd_client);
		return -1;
	}
	/* Send a success notification before we start anything that lasts
	   potentially a long time. imap-hibernate process is waiting for us
	   to answer. Even if we fail later, we log the error anyway. */
	o_stream_nsend_str(conn->output, "+\n");
	(void)o_stream_flush(conn->output);

	/* NOTE: before client_create_from_input() on failures we need to close
	   fd_client, but afterward it gets closed by client_destroy() */
	ret = client_create_from_input(&input, fd_client, fd_client,
				       &imap_client, &error);
	if (ret < 0) {
		i_error("imap-master(%s): Failed to create client: %s",
			input.username, error);
		i_close_fd(&fd_client);
		return -1;
	}
	client->imap_client_created = TRUE;

	if (client_create_finish(imap_client, &error) < 0) {
		i_error("imap-master(%s): %s", input.username, error);
		client_destroy(imap_client, error);
		return -1;
	}
	/* log prefix is set at this point, so we don't need to add the
	   username anymore to the log messages */

	o_stream_nsend(imap_client->output,
		       master_input.client_output->data,
		       master_input.client_output->used);
	if (master_input.client_input->used > 0 &&
	    !i_stream_add_data(imap_client->input,
			       master_input.client_input->data,
			       master_input.client_input->used)) {
		i_error("imap-master: Couldn't add %"PRIuSIZE_T
			" bytes to client's input stream",
			master_input.client_input->used);
		client_destroy(imap_client, "Client initialization failed");
		return -1;
	}
	imap_client->state_import_bad_idle_done =
		master_input.state_import_bad_idle_done;
	imap_client->state_import_idle_continue =
		master_input.state_import_idle_continue;
	if (imap_client->user->mail_debug) {
		if (imap_client->state_import_bad_idle_done)
			i_debug("imap-master: Unhibernated because IDLE was stopped with BAD command");
		else if (imap_client->state_import_idle_continue)
			i_debug("imap-master: Unhibernated to send mailbox changes");
		else
			i_debug("imap-master: Unhibernated because IDLE was stopped with DONE");
	}

	ret = imap_state_import_internal(imap_client, master_input.state->data,
					 master_input.state->used, &error);
	if (ret <= 0) {
		i_error("imap-master: Failed to import client state: %s", error);
		client_destroy(imap_client, "Client state initialization failed");
		return -1;
	}

	if (master_input.tag != NULL)
		imap_state_import_idle_cmd_tag(imap_client, master_input.tag);

	/* make sure all pending input gets handled */
	i_assert(imap_client->to_delayed_input == NULL);
	if (master_input.client_input->used > 0) {
		if (imap_client->user->mail_debug) {
			i_debug("imap-master: Pending client input: '%s'",
				str_sanitize(str_c(master_input.client_input), 128));
		}
		imap_client->to_delayed_input =
			timeout_add(0, client_input, imap_client);
	}

	imap_refresh_proctitle();
	/* we'll always disconnect the client afterwards */
	return -1;
}