Esempio n. 1
0
static void
dsync_fix_mailbox_name(struct mail_namespace *ns, string_t *vname,
		       char alt_char)
{
	const char *old_vname;
	char *p, list_sep = mailbox_list_get_hierarchy_sep(ns->list);
	guid_128_t guid;

	/* replace control chars */
	for (p = str_c_modifiable(vname); *p != '\0'; p++) {
		if ((unsigned char)*p < ' ')
			*p = alt_char;
	}
	/* make it valid UTF8 */
	if (!uni_utf8_str_is_valid(str_c(vname))) {
		old_vname = t_strdup(str_c(vname));
		str_truncate(vname, 0);
		if (uni_utf8_get_valid_data((const void *)old_vname,
					    strlen(old_vname), vname))
			i_unreached();
	}
	if (dsync_is_valid_name(ns, str_c(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 (p = str_c_modifiable(vname); *p != '\0'; p++) {
			if (*p == list_sep)
				*p = alt_char;
		}
		if (dsync_is_valid_name(ns, str_c(vname)))
			return;
	}
	/* 2) '/' characters aren't valid without listescape */
	if (mail_namespace_get_sep(ns) != '/' && list_sep != '/') {
		for (p = str_c_modifiable(vname); *p != '\0'; p++) {
			if (*p == '/')
				*p = alt_char;
		}
		if (dsync_is_valid_name(ns, str_c(vname)))
			return;
	}
	/* 3) probably some reserved name (e.g. dbox-Mails) */
	str_insert(vname, ns->prefix_len, "_");
	if (dsync_is_valid_name(ns, str_c(vname)))
		return;

	/* 4) name is too long? just give up and generate a unique name */
	guid_128_generate(guid);
	str_truncate(vname, 0);
	str_append(vname, ns->prefix);
	str_append(vname, guid_128_to_string(guid));
	i_assert(dsync_is_valid_name(ns, str_c(vname)));
}
Esempio n. 2
0
static char *i_stream_next_line_finish(struct istream_private *stream, size_t i)
{
	char *ret;
	size_t end;

	if (i > 0 && stream->buffer[i-1] == '\r') {
		end = i - 1;
		stream->line_crlf = TRUE;
	} else {
		end = i;
		stream->line_crlf = FALSE;
	}

	if (stream->w_buffer != NULL) {
		/* modify the buffer directly */
		stream->w_buffer[end] = '\0';
		ret = (char *)stream->w_buffer + stream->skip;
	} else {
		/* use a temporary string to return it */
		if (stream->line_str == NULL)
			stream->line_str = str_new(default_pool, 256);
		str_truncate(stream->line_str, 0);
		str_append_n(stream->line_str, stream->buffer + stream->skip,
			     end - stream->skip);
		ret = str_c_modifiable(stream->line_str);
	}

	if (i < stream->pos)
		i++;
	stream->istream.v_offset += i - stream->skip;
	stream->skip = i;
	return ret;
}
static void stream_data(string_t *str, const unsigned char *data, size_t size)
{
	const char *text;

	str_truncate(str, 0);
	str_append_n(str, data, size);
	text = str_tabunescape(str_c_modifiable(str));
	doveadm_print_stream(text, strlen(text));
}
int rfc822_parse_content_param(struct rfc822_parser_context *ctx,
			       const char **key_r, const char **value_r)
{
	string_t *tmp;
	size_t value_pos;
	int ret;

	/* .. := *(";" parameter)
	   parameter := attribute "=" value
	   attribute := token
	   value := token / quoted-string
	*/
	*key_r = NULL;
	*value_r = NULL;

	if (ctx->data == ctx->end)
		return 0;
	if (*ctx->data != ';')
		return -1;
	ctx->data++;

	if (rfc822_skip_lwsp(ctx) <= 0)
		return -1;

	tmp = t_str_new(64);
	if (rfc822_parse_mime_token(ctx, tmp) <= 0)
		return -1;
	str_append_c(tmp, '\0');
	value_pos = str_len(tmp);

	if (*ctx->data != '=')
		return -1;
	ctx->data++;

	if ((ret = rfc822_skip_lwsp(ctx)) <= 0) {
		/* broken / no value */
	} else if (*ctx->data == '"') {
		ret = rfc822_parse_quoted_string(ctx, tmp);
		(void)str_unescape(str_c_modifiable(tmp) + value_pos);
	} else if (ctx->data != ctx->end && *ctx->data == '=') {
		/* workaround for broken input:
		   name==?utf-8?b?...?= */
		while (ctx->data != ctx->end && *ctx->data != ';' &&
		       *ctx->data != ' ' && *ctx->data != '\t' &&
		       *ctx->data != '\r' && *ctx->data != '\n') {
			str_append_c(tmp, *ctx->data);
			ctx->data++;
		}
	} else {
		ret = rfc822_parse_mime_token(ctx, tmp);
	}

	*key_r = str_c(tmp);
	*value_r = *key_r + value_pos;
	return ret < 0 ? -1 : 1;
}
bool mod_lower_modify(string_t *in, string_t **result)
{
	char *content;

	*result = t_str_new(str_len(in));
	str_append_str(*result, in);

	content = str_c_modifiable(*result);
	(void)str_lcase(content);

	return TRUE;
}
bool mod_lowerfirst_modify(string_t *in, string_t **result)
{
	char *content;

	*result = t_str_new(str_len(in));
	str_append_str(*result, in);

	content = str_c_modifiable(*result);
	content[0] = i_tolower(content[0]);

	return TRUE;
}
void client_auth_parse_response(struct client *client)
{
	if (client_auth_read_line(client) <= 0)
		return;

	if (strcmp(str_c(client->auth_response), "*") == 0) {
		sasl_server_auth_abort(client);
		return;
	}

	client_auth_respond(client, str_c(client->auth_response));
	memset(str_c_modifiable(client->auth_response), 0,
	       str_len(client->auth_response));
}
static void server_flush_field(struct server_connection *conn, string_t *str,
			       const unsigned char *data, size_t size)
{
	if (conn->streaming) {
		conn->streaming = FALSE;
		if (size > 0)
			stream_data(str, data, size);
		doveadm_print_stream("", 0);
	} else {
		const char *text;

		str_truncate(str, 0);
		str_append_n(str, data, size);
		text = str_tabunescape(str_c_modifiable(str));
		doveadm_print(text);
	}
}
Esempio n. 9
0
bool settings_read_i(const char *path, const char *section,
		     settings_callback_t *callback,
		     settings_section_callback_t *sect_callback, void *context,
		     const char **error_r)
{
	/* pretty horrible code, but v2.0 will have this rewritten anyway.. */
	struct input_stack root, *input;
	const char *errormsg, *next_section, *name, *last_section_path = NULL;
	char *line, *key, *p, quote;
	string_t *full_line;
	size_t len;
	int fd, last_section_line = 0, skip, sections, root_section;

	fd = open(path, O_RDONLY);
	if (fd < 0) {
		*error_r = t_strdup_printf(
			"Can't open configuration file %s: %m", path);
		return FALSE;
	}

	if (section == NULL) {
		skip = 0;
                next_section = NULL;
	} else {
		skip = 1;
		next_section = t_strcut(section, '/');
	}

	memset(&root, 0, sizeof(root));
	root.path = path;
	input = &root;

	full_line = t_str_new(512);
	sections = 0; root_section = 0; errormsg = NULL;
	input->input = i_stream_create_fd_autoclose(&fd, (size_t)-1);
	i_stream_set_return_partial_line(input->input, TRUE);
prevfile:
	while ((line = i_stream_read_next_line(input->input)) != NULL) {
		input->linenum++;

		/* @UNSAFE: line is modified */

		/* skip whitespace */
		while (IS_WHITE(*line))
			line++;

		/* ignore comments or empty lines */
		if (*line == '#' || *line == '\0')
			continue;

		/* strip away comments. pretty kludgy way really.. */
		for (p = line; *p != '\0'; p++) {
			if (*p == '\'' || *p == '"') {
				quote = *p;
				for (p++; *p != quote && *p != '\0'; p++) {
					if (*p == '\\' && p[1] != '\0')
						p++;
				}
				if (*p == '\0')
					break;
			} else if (*p == '#') {
				if (!IS_WHITE(p[-1])) {
					i_warning("Configuration file %s line %u: "
						  "Ambiguous '#' character in line, treating it as comment. "
						  "Add a space before it to remove this warning.",
						  input->path, input->linenum);
				}
				*p = '\0';
				break;
			}
		}

		/* remove whitespace from end of line */
		len = strlen(line);
		while (IS_WHITE(line[len-1]))
			len--;
		line[len] = '\0';

		if (len > 0 && line[len-1] == '\\') {
			/* continues in next line */
			len--;
			while (IS_WHITE(line[len-1]))
				len--;
			str_append_n(full_line, line, len);
			str_append_c(full_line, ' ');
			continue;
		}
		if (str_len(full_line) > 0) {
			str_append(full_line, line);
			line = str_c_modifiable(full_line);
		}

		/* a) key = value
		   b) section_type [section_name] {
		   c) } */
		key = line;
		while (!IS_WHITE(*line) && *line != '\0' && *line != '=')
			line++;
		if (IS_WHITE(*line)) {
			*line++ = '\0';
			while (IS_WHITE(*line)) line++;
		}

		if (strcmp(key, "!include_try") == 0 ||
		    strcmp(key, "!include") == 0) {
			if (settings_include(fix_relative_path(line, input),
					     &input,
					     strcmp(key, "!include_try") == 0,
					     &errormsg) == 0)
				goto prevfile;
		} else if (*line == '=') {
			/* a) */
			*line++ = '\0';
			while (IS_WHITE(*line)) line++;

			len = strlen(line);
			if (len > 0 &&
			    ((*line == '"' && line[len-1] == '"') ||
			     (*line == '\'' && line[len-1] == '\''))) {
				line[len-1] = '\0';
				line = str_unescape(line+1);
			}

			errormsg = skip ? NULL :
				callback(key, line, context);
		} else if (strcmp(key, "}") != 0 || *line != '\0') {
			/* b) + errors */
			line[-1] = '\0';

			if (*line == '{')
				name = "";
			else {
				name = line;
				while (!IS_WHITE(*line) && *line != '\0')
					line++;

				if (*line != '\0') {
					*line++ = '\0';
					while (IS_WHITE(*line))
						line++;
				}
			}

			if (*line != '{')
				errormsg = "Expecting '='";
			else {
				sections++;
				if (next_section != NULL &&
				    strcmp(next_section, name) == 0) {
					section += strlen(next_section);
					if (*section == '\0') {
						skip = 0;
						next_section = NULL;
						root_section = sections;
					} else {
						i_assert(*section == '/');
						section++;
						next_section =
							t_strcut(section, '/');
					}
				}

				if (skip > 0)
					skip++;
				else {
					skip = sect_callback == NULL ? 1 :
						!sect_callback(key, name,
							       context,
							       &errormsg);
					if (errormsg != NULL &&
					    last_section_line != 0) {
						errormsg = t_strdup_printf(
							SECTION_ERRORMSG,
							errormsg,
							last_section_path,
							last_section_line);
					}
				}
				last_section_path = input->path;
				last_section_line = input->linenum;
			}
		} else {
			/* c) */
			if (sections == 0)
				errormsg = "Unexpected '}'";
			else {
				if (skip > 0)
					skip--;
				else {
					i_assert(sect_callback != NULL);
					sect_callback(NULL, NULL, context,
						      &errormsg);
					if (root_section == sections &&
					    errormsg == NULL) {
						/* we found the section,
						   now quit */
						break;
					}
				}
				last_section_path = input->path;
				last_section_line = input->linenum;
				sections--;
			}
		}

		if (errormsg != NULL) {
			*error_r = t_strdup_printf(
				"Error in configuration file %s line %d: %s",
				input->path, input->linenum, errormsg);
			break;
		}
		str_truncate(full_line, 0);
	}

	i_stream_destroy(&input->input);
	input = input->prev;
	if (line == NULL && input != NULL)
		goto prevfile;

	return errormsg == NULL;
}