/*
 * $Id: ldap.h 1012 2008-03-26 00:44:22Z hubert@u.washington.edu $
 *
 * ========================================================================
 * Copyright 2013-2020 Eduardo Chappa
 * Copyright 2006-2008 University of Washington
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * ========================================================================
 */

#ifndef PITH_LDAP_INCLUDED
#define PITH_LDAP_INCLUDED


#include "../pith/state.h"
#include "../pith/adrbklib.h"


#ifdef	ENABLE_LDAP

/*
 * This is used to consolidate related information about a server. This
 * information is all stored in the ldap-servers variable, per server.
 */
typedef struct ldap_serv {
    char	*serv,		/* Server name			*/
		*base,		/* Search base			*/
		*binddn,	/* Bind DN if non-anonymous	*/
		*cust,		/* Custom search filter		*/
		*nick,		/* Nickname			*/
		*mail,		/* Backup email address		*/
		*mailattr,	/* "Mail" attribute name	*/
		*snattr,	/* "Surname" attribute name	*/
		*gnattr,	/* "Givenname" attribute name	*/
		*cnattr;	/* "CommonName" attribute name	*/
    int		 port,		/* Port number			*/
		 time,		/* Time limit			*/
		 size,		/* Size limit			*/
		 impl,		/* Use implicitly feature	*/
		 rhs,		/* Lookup contents feature	*/
		 ref,		/* Save by reference feature	*/
		 nosub,		/* Disable space sub feature	*/
		 tls,		/* Attempt TLS			*/
		 tlsmust,	/* Require TLS			*/
		 ldaps,		/* Require LDAPS		*/
		 type,		/* Search type (surname...)	*/
		 srch,		/* Search rule (contains...)	*/
		 scope;		/* Scope of search (base...)	*/
} LDAP_SERV_S;


/*
 * Structures to control the LDAP address selection screen
 *
 * We may run into the problem of LDAP databases containing non-UTF-8 data
 * because they are old. They should have all UTF-8 data and that is what
 * we are assuming. If we wanted to accommodate these servers we could
 * translate the data when we use it. LDAP data is only used in a few
 * places so it might not be too hard to fix it. There are four calls
 * into the LDAP library that produce character strings which are
 * supposed to be UTF-8. They are
 *                                 ldap_get_dn
 *                                 ldap_first_attribute
 *                                 ldap_next_attribute
 *                                 ldap_get_values_len
 * We call those from a half dozen functions. We could fix it by
 * having a directory-character-set per server and passing that around
 * in the LDAP_SERV_RES_S structure, I think. For now, let's go with
 * the assumption that everything is already UTF-8.
 */
typedef struct ldap_serv_results {
    LDAP                      *ld;		/* LDAP handle */
    LDAPMessage               *res;		/* LDAP search result */
    LDAP_SERV_S               *info_used;
    char                      *serv;
    struct ldap_serv_results  *next;
} LDAP_SERV_RES_S;


typedef struct addr_choose {
    LDAP_SERV_RES_S *res_head;
    char            *title;
    LDAP            *selected_ld;	/* from which ld was entry selected */
    LDAPMessage     *selected_entry;	/* which entry was selected */
    LDAP_SERV_S     *info_used;
    char            *selected_serv;
} ADDR_CHOOSE_S;


/*
 * This is very similar to LDAP_SERV_RES_S, but selected_entry
 * is a single entry instead of a result list.
 */
typedef struct ldap_choose_results {
    LDAP                      *ld;		/* LDAP handle */
    LDAPMessage               *selected_entry;
    LDAP_SERV_S               *info_used;
    char                      *serv;
} LDAP_CHOOSE_S;


/*
 * How the LDAP lookup should work.
 */
typedef	enum {AlwaysDisplay,
	      AlwaysDisplayAndMailRequired,
    	      DisplayIfTwo,
	      DisplayIfOne,
	      DisplayForURL
	      } LDAPLookupStyle;

#define ALPINE_LDAP_can_use_num(X, Y)   		\
		((X) != NULL && (X)[(Y)] != NULL	\
		  && (X)[(Y)]->bv_val != NULL		\
		  && (X)[(Y)]->bv_val[0] != '\0')

#define ALPINE_LDAP_can_use(X)   ALPINE_LDAP_can_use_num((X), 0)
#define ALPINE_LDAP_usable(X, Y) ((Y) < ldap_count_values_len((X)) \
				&& ALPINE_LDAP_can_use_num((X), (Y)))

#define	LDAP_TYPE_CN		0
#define	LDAP_TYPE_SUR		1
#define	LDAP_TYPE_GIVEN		2
#define	LDAP_TYPE_EMAIL		3
#define	LDAP_TYPE_CN_EMAIL	4
#define	LDAP_TYPE_SUR_GIVEN	5
#define	LDAP_TYPE_SEVERAL	6

#define	LDAP_SRCH_CONTAINS	0
#define	LDAP_SRCH_EQUALS	1
#define	LDAP_SRCH_BEGINS	2
#define	LDAP_SRCH_ENDS		3

#define	DEF_LDAP_TYPE		6
#define	DEF_LDAP_SRCH		2
#define	DEF_LDAP_TIME		30
#define	DEF_LDAP_SIZE		0
#define	DEF_LDAP_SCOPE		LDAP_SCOPE_SUBTREE
#define	DEF_LDAP_MAILATTR	"mail"
#define	DEF_LDAP_SNATTR		"sn"
#define	DEF_LDAP_GNATTR		"givenname"
#define	DEF_LDAP_CNATTR		"cn"

#endif	/* ENABLE_LDAP */


/*
 * Error handling argument for white pages lookups.
 */
typedef struct wp_err {
    char	*error;
    int		 wp_err_occurred;
    int		*mangled;
    int		 ldap_errno;
} WP_ERR_S;


extern int wp_exit;
extern int wp_nobail;


/* exported prototypes */
ADDRESS       *wp_lookups(char *, WP_ERR_S *, int);
#ifdef	ENABLE_LDAP
int            ldap_lookup_all(char *, int, int, LDAPLookupStyle, CUSTOM_FILT_S *,
			       LDAP_CHOOSE_S **, WP_ERR_S *, LDAP_SERV_RES_S **);
char	      *ldap_translate(char *, LDAP_SERV_S *);
char	     **berval_to_array(struct berval **);
ADDRESS       *address_from_ldap(LDAP_CHOOSE_S *);
LDAP_SERV_S   *break_up_ldap_server(char *);
void           free_ldap_server_info(LDAP_SERV_S **);
void           free_ldap_result_list(LDAP_SERV_RES_S **);
void           our_ldap_memfree(void *);
void           our_ldap_dn_memfree(void *);
int            our_ldap_set_option(LDAP *, int, void *);
int            ldap_v3_is_supported(LDAP *);
int            ask_user_which_entry(LDAP_SERV_RES_S *, char *,
				    LDAP_CHOOSE_S **, WP_ERR_S *, LDAPLookupStyle);
LDAP_SERV_RES_S *ldap_lookup_all_work(char *, int, int, CUSTOM_FILT_S *, WP_ERR_S *);


/*
 * This must be defined in the application
 */
int         ldap_addr_select(struct pine *, ADDR_CHOOSE_S *, LDAP_CHOOSE_S **,
			     LDAPLookupStyle, WP_ERR_S *, char *);
#endif	/* ENABLE_LDAP */


#endif /* PITH_LDAP_INCLUDED */
