<commit_before>/* Copyright (C) 2007-2008 <NAME>, LGPLv2.1 */

#include "lib.h"
#include "array.h"
#include "str.h"
#include "module-context.h"
#include "mail-storage-private.h"
#include "mailbox-list-private.h"
#include "listescape-plugin.h"

#include <stdlib.h>
#include <ctype.h>

#define DEFAULT_ESCAPE_CHAR '\\'

#define LIST_ESCAPE_CONTEXT(obj) \
	MODULE_CONTEXT(obj, listescape_storage_module)
#define LIST_ESCAPE_LIST_CONTEXT(obj) \
	MODULE_CONTEXT(obj, listescape_list_module)

struct listescape_mail_storage {
	union mail_storage_module_context module_ctx;
};

struct listescape_mailbox_list {
	union mailbox_list_module_context module_ctx;
	struct mailbox_info info;
	string_t *list_name;
	char escape_char;
	bool name_escaped;
};

const char *listescape_plugin_version = PACKAGE_VERSION;

static void (*listescape_next_hook_mail_storage_created)
	(struct mail_storage *storage);
static void (*listescape_next_hook_mailbox_list_created)
	(struct mailbox_list *list);
static void (*listescape_next_hook_mail_namespaces_created)
	(struct mail_namespace *namespaces);

static MODULE_CONTEXT_DEFINE_INIT(listescape_storage_module,
				  &mail_storage_module_register);
static MODULE_CONTEXT_DEFINE_INIT(listescape_list_module,
				  &mailbox_list_module_register);

static const char *list_escape(struct mail_namespace *ns,
			       const char *str, bool change_sep)
{
	struct listescape_mailbox_list *mlist =
		LIST_ESCAPE_LIST_CONTEXT(ns->list);
	string_t *esc = t_str_new(64);

	if (*str == '~') {
		str_printfa(esc, "%c%02x", mlist->escape_char, *str);
		str++;
	}
	for (; *str != '\0'; str++) {
		if (*str == ns->sep && change_sep)
			str_append_c(esc, ns->list->hierarchy_sep);
		else if (*str == ns->list->hierarchy_sep ||
			 *str == mlist->escape_char || *str == '/')
			str_printfa(esc, "%c%02x", mlist->escape_char, *str);
		else
			str_append_c(esc, *str);
	}
	return str_c(esc);
}

static void list_unescape_str(struct mail_namespace *ns,
			      const char *str, string_t *dest)
{
	struct listescape_mailbox_list *mlist =
		LIST_ESCAPE_LIST_CONTEXT(ns->list);
	unsigned int num;

	for (; *str != '\0'; str++) {
		if (*str == mlist->escape_char &&
		    i_isxdigit(str[1]) && i_isxdigit(str[2])) {
			if (str[1] >= '0' && str[1] <= '9')
				num = str[1] - '0';
			else
				num = i_toupper(str[1]) - 'A' + 10;
			num *= 16;
			if (str[2] >= '0' && str[2] <= '9')
				num += str[2] - '0';
			else
				num += i_toupper(str[2]) - 'A' + 10;

			str_append_c(dest, num);
			str += 2;
		} else if (*str == ns->list->hierarchy_sep)
			str_append_c(dest, ns->sep);
		else
			str_append_c(dest, *str);
	}
}

static struct mailbox_list_iterate_context *
listescape_mailbox_list_iter_init(struct mailbox_list *list,
				  const char *const *patterns,
				  enum mailbox_list_iter_flags flags)
{
	struct listescape_mailbox_list *mlist = LIST_ESCAPE_LIST_CONTEXT(list);
	struct mailbox_list_iterate_context *ctx;
	const char **escaped_patterns;
	unsigned int i;

	t_push();
	if ((flags & MAILBOX_LIST_ITER_VIRTUAL_NAMES) != 0) {
		escaped_patterns = t_new(const char *,
					 str_array_length(patterns) + 1);
		for (i = 0; patterns[i] != NULL; i++) {
			escaped_patterns[i] =
				list_escape(list->ns, patterns[i], FALSE);
		}
		patterns = escaped_patterns;
	}

	/* Listing breaks if ns->real_sep isn't correct, but with everything
	   else we need real_sep == virtual_sep. maybe some day lib-storage
	   API gets changed so that it sees only virtual mailbox names and
	   convers them internally and we don't have this problem. */
	list->ns->real_sep = list->hierarchy_sep;
	ctx = mlist->module_ctx.super.iter_init(list, patterns, flags);
	list->ns->real_sep = list->ns->sep;
	t_pop();
	return ctx;
}

static const struct mailbox_info *
listescape_mailbox_list_iter_next(struct mailbox_list_iterate_context *ctx)<commit_msg>listescape: Fixed problems with handling mailbox listing.<commit_after>/* Copyright (C) 2007-2008 <NAME>, LGPLv2.1 */

#include "lib.h"
#include "array.h"
#include "str.h"
#include "module-context.h"
#include "mail-storage-private.h"
#include "mailbox-list-private.h"
#include "listescape-plugin.h"

#include <stdlib.h>
#include <ctype.h>

#define DEFAULT_ESCAPE_CHAR '\\'

#define LIST_ESCAPE_CONTEXT(obj) \
	MODULE_CONTEXT(obj, listescape_storage_module)
#define LIST_ESCAPE_LIST_CONTEXT(obj) \
	MODULE_CONTEXT(obj, listescape_list_module)

struct listescape_mail_storage {
	union mail_storage_module_context module_ctx;
};

struct listescape_mailbox_list {
	union mailbox_list_module_context module_ctx;
	struct mailbox_info info;
	string_t *list_name;
	char escape_char;
	bool name_escaped;
};

const char *listescape_plugin_version = PACKAGE_VERSION;

static void (*listescape_next_hook_mail_storage_created)
	(struct mail_storage *storage);
static void (*listescape_next_hook_mailbox_list_created)
	(struct mailbox_list *list);
static void (*listescape_next_hook_mail_namespaces_created)
	(struct mail_namespace *namespaces);

static MODULE_CONTEXT_DEFINE_INIT(listescape_storage_module,
				  &mail_storage_module_register);
static MODULE_CONTEXT_DEFINE_INIT(listescape_list_module,
				  &mailbox_list_module_register);

static const char *list_escape(struct mail_namespace *ns,
			       const char *str, bool change_sep)
{
	struct listescape_mailbox_list *mlist =
		LIST_ESCAPE_LIST_CONTEXT(ns->list);
	string_t *esc = t_str_new(64);

	if (*str == '~') {
		str_printfa(esc, "%c%02x", mlist->escape_char, *str);
		str++;
	}
	for (; *str != '\0'; str++) {
		if (*str == ns->sep) {
			if (change_sep)
				str_append_c(esc, ns->list->hierarchy_sep);
			else
				str_append_c(esc, *str);
		} else if (*str == ns->list->hierarchy_sep ||
			   *str == mlist->escape_char || *str == '/')
			str_printfa(esc, "%c%02x", mlist->escape_char, *str);
		else
			str_append_c(esc, *str);
	}
	return str_c(esc);
}

static void list_unescape_str(struct mail_namespace *ns,
			      const char *str, string_t *dest)
{
	struct listescape_mailbox_list *mlist =
		LIST_ESCAPE_LIST_CONTEXT(ns->list);
	unsigned int num;

	for (; *str != '\0'; str++) {
		if (*str == mlist->escape_char &&
		    i_isxdigit(str[1]) && i_isxdigit(str[2])) {
			if (str[1] >= '0' && str[1] <= '9')
				num = str[1] - '0';
			else
				num = i_toupper(str[1]) - 'A' + 10;
			num *= 16;
			if (str[2] >= '0' && str[2] <= '9')
				num += str[2] - '0';
			else
				num += i_toupper(str[2]) - 'A' + 10;

			str_append_c(dest, num);
			str += 2;
		} else if (*str == ns->list->hierarchy_sep)
			str_append_c(dest, ns->sep);
		else
			str_append_c(dest, *str);
	}
}

static struct mailbox_list_iterate_context *
listescape_mailbox_list_iter_init(struct mailbox_list *list,
				  const char *const *patterns,
				  enum mailbox_list_iter_flags flags)
{
	struct listescape_mailbox_list *mlist = LIST_ESCAPE_LIST_CONTEXT(list);
	struct mailbox_list_iterate_context *ctx;
	const char **escaped_patterns;
	unsigned int i;
	bool change_sep;

	/* this is kind of kludgy. In ACL code we want to convert patterns,
	   in maildir renaming code we don't. so for now just use the _RAW_LIST
	   flag.. */
	if ((flags & MAILBOX_LIST_ITER_RAW_LIST) == 0) {
		change_sep = (flags & MAILBOX_LIST_ITER_VIRTUAL_NAMES) == 0;
		escaped_patterns = t_new(const char *,
					 str_array_length(patterns) + 1);
		for (i = 0; patterns[i] != NULL; i++) {
			escaped_patterns[i] =
				list_escape(list->ns, patterns[i], change_sep);
		}
		patterns = escaped_patterns;
	}

	/* Listing breaks if ns->real_sep isn't correct, but with everything
	   else we need real_sep == virtual_sep. maybe some day lib-storage
	   API gets changed so that it sees only virtual mailbox names and
	   convers them internally and we don't have this problem. */
	list->ns->real_sep = list->hierarchy_sep;
	ctx = mlist->module_ctx.super.iter_init(list, patterns, flags);
	list->ns->real_sep = list->ns->sep;
	return ctx;
}

static const struct mailbox_info *
listescape_mailbox_list_iter_next(struct mailbox_list_iterate_context *ctx)
{'fraction_non_alphanumeric': 0.1315360501567398, 'fraction_numerical': 0.01115987460815047, 'mean_word_length': 4.713467048710601, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 61, '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': '3859042', 'n_tokens_mistral': 3214, 'n_tokens_neox': 2953, 'n_words': 648}