<commit_before>/* Copyright (c) 2002-2012 Dovecot authors, see the included COPYING file */

#include "lib.h"
#include "str.h"
#include "imap-quote.h"

void imap_quote_append(string_t *str, const unsigned char *value,
		       size_t value_len, bool fix_text)
{
	size_t i, extra = 0;
	bool last_lwsp = TRUE, literal = FALSE, modify = FALSE;

	if (value == NULL) {
		str_append(str, "NIL");
		return;
	}

	if (value_len == (size_t)-1)
		value_len = strlen((const char *) value);

	for (i = 0; i < value_len; i++) {
		switch (value[i]) {
		case 0:
			/* it's converted to 8bit char */
			literal = TRUE;
			last_lwsp = FALSE;
			modify = TRUE;
			break;
		case '\t':
			modify = TRUE;
			/* fall through */
		case ' ':
			if (last_lwsp && fix_text) {
				modify = TRUE;
				extra++;
			}
			last_lwsp = TRUE;
			break;
		case 13:
		case 10:
			if (!fix_text)
				literal = TRUE;
			extra++;
			modify = TRUE;
			break;
		default:
			if ((value[i] & 0x80) != 0 ||
			    value[i] == '"' || value[i] == '\\')
				literal = TRUE;
			last_lwsp = FALSE;
		}
	}

	if (!fix_text) {
		extra = 0;
		modify = FALSE;
	}

	if (!literal) {
		/* no 8bit chars or imapspecials, return as "string" */
		str_append_c(str, '"');
	} else {
		/* return as literal */
		str_printfa(str, "{%"PRIuSIZE_T"}\r\n", value_len - extra);
	}

	if (!modify)
		str_append_n(str, value, value_len);
	else {
		last_lwsp = TRUE;
		for (i = 0; i < value_len; i++) {
			switch (value[i]) {
			case 0:
				str_append_c(str, 128);
				last_lwsp = FALSE;
				break;
			case ' ':
			case '\t':
				if (!last_lwsp)
					str_append_c(str, ' ');
				last_lwsp = TRUE;
				break;
			case 13:
			case 10:
				break;
			default:
				last_lwsp = FALSE;
				str_append_c(str, value[i]);
				break;
			}
		}
	}

	if (!literal)
		str_append_c(str, '"');
}

static const char *
imap_quote_internal(pool_t pool, const unsigned char *value,
		    size_t value_len, bool fix_text)
{
	string_t *str;

	str = t_str_new(value_len + MAX_INT_STRLEN + 5);
	imap_quote_append(str, value, value_len, fix_text);
	return pool->datastack_pool ? str_c(str) :
		p_strndup(pool, str_data(str), str_len(str));
}

const char *imap_quote(pool_t pool, const unsigned char *value,
		       size_t value_len, bool fix_text)
{
	const char *ret;

	if (value == NULL)
		return "NIL";

	if (!pool->datastack_pool)
		ret = imap_quote_internal(pool, value, value_len, fix_text);
	else T_BEGIN {
		ret = imap_quote_internal(pool, value, value_len, fix_text);
	} T_END;
	return ret;
}

void imap_dquote_append(string_t *dest, const char *src)
{
	str_append_c(dest, '"');
	for (; *src != '\0'; src++) {
		switch (*src) {
		case '\r':
		case '\n':
			/* not allowed */
			break;
		case '"':
		case '\\':
			str_append_c(dest, '\\');
			str_append_c(dest, *src);
			break;
		default:
			if ((unsigned char)*src >= 0x80) {
				/* 8bit input not allowed in dquotes */
				break;
			}

			str_append_c(dest, *src);
			break;
		}
	}
	str_append_c(dest, '"');
}
<commit_msg>lib-imap: imap_quote() was broken when called with a datastack pool.<commit_after>/* Copyright (c) 2002-2012 Dovecot authors, see the included COPYING file */

#include "lib.h"
#include "str.h"
#include "imap-quote.h"

void imap_quote_append(string_t *str, const unsigned char *value,
		       size_t value_len, bool fix_text)
{
	size_t i, extra = 0;
	bool last_lwsp = TRUE, literal = FALSE, modify = FALSE;

	if (value == NULL) {
		str_append(str, "NIL");
		return;
	}

	if (value_len == (size_t)-1)
		value_len = strlen((const char *) value);

	for (i = 0; i < value_len; i++) {
		switch (value[i]) {
		case 0:
			/* it's converted to 8bit char */
			literal = TRUE;
			last_lwsp = FALSE;
			modify = TRUE;
			break;
		case '\t':
			modify = TRUE;
			/* fall through */
		case ' ':
			if (last_lwsp && fix_text) {
				modify = TRUE;
				extra++;
			}
			last_lwsp = TRUE;
			break;
		case 13:
		case 10:
			if (!fix_text)
				literal = TRUE;
			extra++;
			modify = TRUE;
			break;
		default:
			if ((value[i] & 0x80) != 0 ||
			    value[i] == '"' || value[i] == '\\')
				literal = TRUE;
			last_lwsp = FALSE;
		}
	}

	if (!fix_text) {
		extra = 0;
		modify = FALSE;
	}

	if (!literal) {
		/* no 8bit chars or imapspecials, return as "string" */
		str_append_c(str, '"');
	} else {
		/* return as literal */
		str_printfa(str, "{%"PRIuSIZE_T"}\r\n", value_len - extra);
	}

	if (!modify)
		str_append_n(str, value, value_len);
	else {
		last_lwsp = TRUE;
		for (i = 0; i < value_len; i++) {
			switch (value[i]) {
			case 0:
				str_append_c(str, 128);
				last_lwsp = FALSE;
				break;
			case ' ':
			case '\t':
				if (!last_lwsp)
					str_append_c(str, ' ');
				last_lwsp = TRUE;
				break;
			case 13:
			case 10:
				break;
			default:
				last_lwsp = FALSE;
				str_append_c(str, value[i]);
				break;
			}
		}
	}

	if (!literal)
		str_append_c(str, '"');
}

static const char *
imap_quote_internal(pool_t pool, const unsigned char *value,
		    size_t value_len, bool fix_text)
{
	string_t *str;

	str = t_str_new(value_len + MAX_INT_STRLEN + 5);
	imap_quote_append(str, value, value_len, fix_text);
	return pool->datastack_pool ? str_c(str) :
		p_strndup(pool, str_data(str), str_len(str));
}

const char *imap_quote(pool_t pool, const unsigned char *value,
		       size_t value_len, bool fix_text)
{
	const char *ret;

	if (value == NULL)
		return "NIL";

	if (pool->datastack_pool)
		ret = imap_quote_internal(pool, value, value_len, fix_text);
	else T_BEGIN {
		ret = imap_quote_internal(pool, value, value_len, fix_text);
	} T_END;
	return ret;
}

void imap_dquote_append(string_t *dest, const char *src)
{
	str_append_c(dest, '"');
	for (; *src != '\0'; src++) {
		switch (*src) {
		case '\r':
		case '\n':
			/* not allowed */
			break;
		case '"':
		case '\\':
			str_append_c(dest, '\\');
			str_append_c(dest, *src);
			break;
		default:
			if ((unsigned char)*src >= 0x80) {
				/* 8bit input not allowed in dquotes */
				break;
			}

			str_append_c(dest, *src);
			break;
		}
	}
	str_append_c(dest, '"');
}

{'fraction_non_alphanumeric': 0.15824468085106383, 'fraction_numerical': 0.012632978723404254, 'mean_word_length': 2.9585526315789474, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1043340', 'n_tokens_mistral': 2860, 'n_tokens_neox': 2437, 'n_words': 593}