/*
 * $Id: 7d004848c5c3d50ccb9d8607b0ee11461393249b $
 *
 * This file is part of nsmtp.
 *
 * Copyright (c) 2007, 2008 Niklas Olmes <niklas@noxa.de>
 *                          http://www.nevm.de/nsmtp/
 *                          NEVM-RIPE
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License Version 2
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */

#include <stdio.h>
#include <stdlib.h>

#include <ldap.h>

#include "ntl.h"
#include "alloc.h"
#include "log.h"
#include "maildir.h"
#include "config.h"

static const char rcsid[] = "$Id: 7d004848c5c3d50ccb9d8607b0ee11461393249b $";

/*
 * return codes:
 * -1 - temp fail
 * 0  - okay
 * 1  - error
 */
int
get_maildir_and_uid(const char *email, char **maildir, unsigned int *uid)
{
	const char *attrs[] = { "mailMessageStore", "uidNumber", NULL };
	char buf[1024];
	const char **tmp;
	int e;
	LDAP *ld;
	LDAPMessage *res, *entry;
	NTL_ATTR *a;

	DEBUG(("get_maildir_and_uid() => mail address <%s>", email));

	if (nsmc_ldap_cfgs == NULL || nsmc_ldap_cfgs[0] == NULL || nsmc_ldap_cfgs[1] == NULL) {
		xfatal("fatal: internal error: get_maildir_and_uid() => no suitable LDAP configs loaded, unable to retrieve");
		return -1;
	}

	if ((ld = ntl_connect(nsmc_ldap_cfgs[0])) == NULL
	    && (ld = ntl_connect(nsmc_ldap_cfgs[1])) == NULL) {
		xwarn("warn: get_maildir_and_uid() => unable to connect to any LDAP server");
		return -1;
	}

	e = 0;
	(void)snprintf(buf, sizeof(buf), "(|(mail=%s)(mailAlternateAddress=%s))", email, email);
	if ((res = ntl_search(ld, nsmc_mail_basedn, LDAP_SCOPE_SUBTREE, buf, attrs)) != NULL
	    && (entry = ldap_first_entry(ld, res)) != NULL) {
		a = ntl_entry(ld, entry);
		if (*(tmp = ntl_lookup(a, attrs[0])) != NULL) {
			*maildir = nsm_strdup(*tmp);
			*uid = nsmc_default_maildir_uid;
			if (*(tmp = ntl_lookup(a, attrs[1])) != NULL) {
				*uid = atoi(*tmp);
				if (!is_sane_uid(*uid)) {
					xwarn("warn: get_maildir_and_uid() => %s=(%d) in LDAP out of valid range", attrs[1], *uid);
					e = -1;
				}
			}
		} else
			e = 1;
		ntl_entry_free(a);
	} else {
		xwarn("warn: get_maildir_and_uid() => mail address <%s> not found in LDAP", email);
		e = 1;
	}

	(void)ldap_msgfree(res);
	(void)ldap_unbind(ld);

	DEBUG(("get_maildir_and_uid() => result for mail address <%s>:  maildir=<%s> uid=(%d)", email, *maildir, *uid));

	return e;
}

int
is_sane_uid(uid_t uid)
{

	if (uid < nsmc_maildir_uid_range_low || uid >= nsmc_maildir_uid_range_high) {
		xwarn("warn: is_sane_uid() => uid (%d) out of range: %d < x <= %d", uid, nsmc_maildir_uid_range_low, nsmc_maildir_uid_range_high);
		return 0;
	}
	return 1;
}
