view src/lib-storage/mail-storage.c @ 903:fd8888f6f037 HEAD

Naming style changes, finally got tired of most of the typedefs. Also the previous enum -> macro change reverted so that we don't use the highest bit anymore, that's incompatible with old indexes so they will be rebuilt.
author Timo Sirainen <tss@iki.fi>
date Sun, 05 Jan 2003 15:09:51 +0200
parents 39e0b536e708
children 340dea0150bf
line wrap: on
line source

/* Copyright (C) 2002 Timo Sirainen */

#include "lib.h"
#include "ioloop.h"
#include "mail-storage.h"

#include <time.h>
#include <ctype.h>

/* Message to show to users when critical error occurs */
#define CRITICAL_MSG "Internal error [%Y-%m-%d %H:%M:%S]"

struct mail_storage_list {
	struct mail_storage_list *next;
	struct mail_storage *storage;
};

static struct mail_storage_list *storages = NULL;

void mail_storage_class_register(struct mail_storage *storage_class)
{
	struct mail_storage_list *list, **pos;

	list = i_new(struct mail_storage_list, 1);
	list->storage = storage_class;

	/* append it after the list, so the autodetection order is correct */
	pos = &storages;
	while (*pos != NULL)
		pos = &(*pos)->next;
	*pos = list;
}

void mail_storage_class_unregister(struct mail_storage *storage_class)
{
	struct mail_storage_list **list, *next;

	for (list = &storages; *list != NULL; list = &(*list)->next) {
		if ((*list)->storage == storage_class) {
			next = (*list)->next;

			(*list)->storage->free((*list)->storage);
			i_free(*list);

			*list = next;
		}
	}
}

struct mail_storage *mail_storage_create(const char *name, const char *data,
					 const char *user)
{
	struct mail_storage_list *list;

	i_assert(name != NULL);

	for (list = storages; list != NULL; list = list->next) {
		if (strcasecmp(list->storage->name, name) == 0)
			return list->storage->create(data, user);
	}

	return NULL;
}

struct mail_storage *mail_storage_create_default(const char *user)
{
	struct mail_storage_list *list;
	struct mail_storage *storage;

	for (list = storages; list != NULL; list = list->next) {
		storage = list->storage->create(NULL, user);
		if (storage != NULL)
			return storage;
	}

	return NULL;
}

static struct mail_storage *mail_storage_autodetect(const char *data)
{
	struct mail_storage_list *list;

	for (list = storages; list != NULL; list = list->next) {
		if (list->storage->autodetect(data))
			return list->storage;
	}

	return NULL;
}

struct mail_storage *mail_storage_create_with_data(const char *data,
						   const char *user)
{
	struct mail_storage *storage;
	const char *p, *name;

	if (data == NULL || *data == '\0')
		return mail_storage_create_default(user);

	/* check if we're in the form of mailformat:data
	   (eg. maildir:Maildir) */
	p = data;
	while (i_isalnum(*p)) p++;

	if (*p == ':') {
		name = t_strdup_until(data, p);
		storage = mail_storage_create(name, p+1, user);
	} else {
		storage = mail_storage_autodetect(data);
		if (storage != NULL)
			storage = storage->create(data, user);
	}

	return storage;
}

void mail_storage_destroy(struct mail_storage *storage)
{
	i_assert(storage != NULL);

	i_free(storage->dir);
	i_free(storage);
}

void mail_storage_clear_error(struct mail_storage *storage)
{
	i_free(storage->error);
	storage->error = NULL;

	storage->syntax_error = FALSE;
}

void mail_storage_set_error(struct mail_storage *storage, const char *fmt, ...)
{
	va_list va;

	i_free(storage->error);

	if (fmt == NULL)
		storage->error = NULL;
	else {
		va_start(va, fmt);
		storage->error = i_strdup_vprintf(fmt, va);
		storage->syntax_error = FALSE;
		va_end(va);
	}
}

void mail_storage_set_syntax_error(struct mail_storage *storage,
				   const char *fmt, ...)
{
	va_list va;

	i_free(storage->error);

	if (fmt == NULL)
		storage->error = NULL;
	else {
		va_start(va, fmt);
		storage->error = i_strdup_vprintf(fmt, va);
		storage->syntax_error = TRUE;
		va_end(va);
	}
}

void mail_storage_set_internal_error(struct mail_storage *storage)
{
	struct tm *tm;
	char str[256];

	tm = localtime(&ioloop_time);

	storage->error = strftime(str, sizeof(str), CRITICAL_MSG, tm) > 0 ?
		i_strdup(str) : i_strdup("Internal error");
	storage->syntax_error = FALSE;
}

void mail_storage_set_critical(struct mail_storage *storage,
			       const char *fmt, ...)
{
	va_list va;

	i_free(storage->error);
	if (fmt == NULL)
		storage->error = NULL;
	else {
		va_start(va, fmt);
		i_error("%s", t_strdup_vprintf(fmt, va));
		va_end(va);

		/* critical errors may contain sensitive data, so let user
		   see only "Internal error" with a timestamp to make it
		   easier to look from log files the actual error message. */
		mail_storage_set_internal_error(storage);
	}
}

const char *mail_storage_get_last_error(struct mail_storage *storage,
					int *syntax)
{
	if (syntax != NULL)
		*syntax = storage->syntax_error;
	return storage->error;
}

int mail_storage_is_inconsistency_error(struct mailbox *box)
{
	return box->inconsistent;
}