/*
 * Copyright (c) 2003-2005 Sendmail, Inc. and its suppliers.
 *	All rights reserved.
 *
 * By using this file, you agree to the terms and conditions set
 * forth in the LICENSE file which can be found at the top level of
 * the sendmail distribution.
 */

#include "sm/generic.h"
SM_RCSID("@(#)$Id: lookupdomain.c,v 1.17 2007/01/22 17:24:21 ca Exp $")

#include "sm/assert.h"
#include "sm/error.h"
#include "sm/memops.h"
#include "sm/heap.h"
#include "sm/rdstr.h"
#include "map.h"
#include "sm/map.h"
#include "sm/maps.h"
#include "sm/mapc.h"

/*
**  Add flags (also for lookup_ip):
**  lookup also .domain
**  lookup only Tag:
**  others?
*/

/*
**  SM_MAP_LOOKUP_DOMAIN -- Lookup domain and subdomains (and . if requested)
**
**	Parameters:
**		map -- map
**		domain -- input string (domain)
**		tag -- tag including delimiter (NULL for no tag)
**		flags -- flags to control lookup
**		rhs -- rhs of matching entry
**
**	Returns:
**		usual sm_error code
*/

sm_ret_T
sm_map_lookup_domain(sm_map_P map, sm_rdstr_P domain, sm_str_P tag, uint32_t flags, sm_str_P rhs)
{
	sm_ret_T ret;
	sm_mapc_P mapc;
	sm_str_P str;
	size_t j, len_domain;
	bool found;

	if (NULL == map)
		return sm_error_perm(SM_EM_MAP, SM_E_NOMAP);
	SM_IS_MAP(map);
	mapc = map->sm_map_class;
	SM_IS_MAPC(mapc);
	if (NULL == mapc->sm_mapc_lookupf)
		return sm_error_perm(SM_EM_MAP, SM_E_NOTIMPL);
	if (!SMMAP_LT_M_CAPS(map, SMMAP_FL_HAS_DOMAIN))
		return sm_error_perm(SM_EM_MAP, ENOENT);	/* XXX */

	len_domain = SM_RDSTR_GETLEN(domain);
	if (0 == len_domain)
		return sm_error_perm(SM_EM_MAP, SM_E_NOTFOUND);	/* XXX */
	if (tag != NULL)
		len_domain += sm_str_getlen(tag);

	str = sm_str_new(NULL, len_domain , len_domain + 2);
	if (NULL == str)
		return sm_error_perm(SM_EM_MAP, ENOMEM);

	ret = sm_error_perm(SM_EM_MAP, SM_E_NOTFOUND);	/* XXX */
	j = 0;
	found = false;
	len_domain = SM_RDSTR_GETLEN(domain) - 1;
	while (j <= len_domain) {
		sm_str_clr(str);
		if (tag != NULL) {
			ret = sm_str_cat(str, tag);
			if (sm_is_err(ret))
				break;
		}

		ret = sm_str_catpart(str, (sm_rdstr_P) domain, j, len_domain);
		if (sm_is_err(ret))
			break;

		ret = mapc->sm_mapc_lookupf(map, SMMAP_FL_LWR_KEY, str, rhs);
		if (SM_MAP_DATA2BIG == ret)
			goto done;
		if (SM_SUCCESS == ret) {
			found = true;
			break;
		}

#if 0
		if (SMMAP_IS_LFL(flags, SMMAP_LFL_DOTSUBDOM))
#endif
			++j;

		/* search for next '.'; domains don't have escaped dots */
		while (j < len_domain && SM_RDSTR_RD_ELEM(domain, j) != '.')
			++j;

#if 0
		if (!SMMAP_IS_LFL(flags, SMMAP_LFL_DOTSUBDOM))
			++j;
#endif

	}

	if (!found && SMMAP_IS_LFL(flags, SMMAP_LFL_TAG) && j > len_domain
	    && tag != NULL)
	{
		/* lookup default: just tag */
		ret = mapc->sm_mapc_lookupf(map, SMMAP_FL_NONE, tag, rhs);
		if (SM_MAP_DATA2BIG == ret)
			goto done;
		if (SM_SUCCESS == ret)
			found = true;
	}

	if (!found && SMMAP_IS_LFL(flags, SMMAP_LFL_DOT) && j > len_domain) {
		/* lookup . */
		sm_str_clr(str);
		ret = sm_str_scat(str, ".");
		if (!sm_is_err(ret)) {
			ret = mapc->sm_mapc_lookupf(map, SMMAP_FL_NONE, str, rhs);
			if (SM_SUCCESS == ret)
				found = true;
		}
	}

 done:
	sm_str_free(str);

	/*
	**  Who "owns" the data?
	**  need some flags that tell us what to do? see BDB.
	*/

	return ret;
}


syntax highlighted by Code2HTML, v. 0.9.1