/** BEGIN COPYRIGHT BLOCK
 * Copyright (C) 2001 Sun Microsystems, Inc.  Used by permission.
 * Copyright (C) 2005 Red Hat, Inc.
 * All rights reserved.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation version
 * 2.1 of the License.
 *                                                                                  
 * This library 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
 * Lesser General Public License for more details.
 *                                                                                  
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 * END COPYRIGHT BLOCK **/

/*
 * adminutil.h - prototypes for libadminutil
 *
 * $Id: admutil.h,v 1.10 2008/12/03 17:31:26 rmeggins Exp $
 */

#ifndef __ADMUTIL_H__
#define __ADMUTIL_H__

#include <limits.h>
#include <stdio.h>
#include "prtypes.h"
#include "plstr.h"
#include "prprf.h"
#include "prmem.h"
#include <ldap.h>

/* Copy from #include "base/systems.h"  */
#if defined (XP_WIN32)      /* Windows NT */
 
#include <wtypes.h>
#include <winbase.h>

#ifndef PATH_MAX
#define PATH_MAX MAX_PATH
#endif

#endif /* XP_WIN32 */

#ifndef TO_ADMIN
#define TO_ADMIN "admserv"
#endif

#ifndef BIG_LINE
#define BIG_LINE 1024
#endif

/* This environment variable holds the name of the directory
   containing adm.conf, admpw, and other
   adminutil config files - if this env var is set,
   IT WILL OVERRIDE NETSITE_ROOT AND FUNCTION ARGUMENTS to
   functions such as admGetLocalAdmin and admldapBuildInfo
   This was done to minimize coding changes to other modules.
*/
#define ADMINUTIL_CONFDIR_ENV_VAR "ADMINUTIL_CONF_DIR"

/* safs/cgi.h */

#ifdef __cplusplus
extern "C" {
#endif

typedef char* NameType;
typedef char** ValueType;

#define ADMUTIL_OP_OK 0
#define ADMUTIL_OP_FAIL 1
#define ADMUTIL_SYSTEM_ERR 2
#define ADMUTIL_ENV_ERR 3
#define ADMUTIL_LDAP_ERR 4
#define ADMUTIL_NO_SSL_SUPPORT 5

typedef struct _Attribute {
  NameType  attrName;
  ValueType attrVal;
} Attribute, *AttributePtr;

struct ldap;   /* Just a opqueue handle */

/* The following are the convient utility functions to create/delete 
   attributeNameList  and attributeList, it does NOT check out-of-bound
   condition when you add element */

typedef char** AttrNameList;
PR_IMPLEMENT(AttrNameList)
createAttrNameList(int entries);
PR_IMPLEMENT(int)
addName(AttrNameList nl, int index, NameType name);
PR_IMPLEMENT(void)
deleteAttrNameList(AttrNameList nl);

PR_IMPLEMENT(void)
deleteValue(ValueType val);

typedef AttributePtr* AttributeList;
PR_IMPLEMENT(AttributeList)
createAttributeList(int entries);
PR_IMPLEMENT(int)
addAttribute(AttributeList nvl, int index, NameType name, ValueType val);
PR_IMPLEMENT(int)
addSingleValueAttribute(AttributeList nvl, int index, NameType name, char* val);
PR_IMPLEMENT(void)
deleteAttributeList(AttributeList nvl);

/*
 * Utility function for reading a line
 * DBDB changed the name of this function because it collides with
 * a function of the same name in recent glibc versions.
*/
#define MAX_LEN 512
PR_IMPLEMENT(int)
admutil_getline(FILE *fstream, int maxlen, int lineno, char* buf);

/* Utility function to get ldap Information  */

typedef void* AdmldapInfo;

PR_IMPLEMENT(int)
admldapWriteInfoFile(AdmldapInfo info);

/*
 * Just read the ldap information from the file, without also opening a connection
 */
PR_IMPLEMENT(AdmldapInfo)
admldapBuildInfoOnly(char* configRoot, int *errorcode);

/*
 * Read the ldap info, open a connection, and bind, and specify a callback function
 * that returns the ldap password
 */
PR_IMPLEMENT(AdmldapInfo)
admldapBuildInfoCbk(char* configRoot, char* (*cbk)(),  int *errorcode);

/*
 * Read the ldap info, open a connection, and bind
 */
PR_IMPLEMENT(AdmldapInfo)
admldapBuildInfo(char* configRoot, int *errorcode);

PR_IMPLEMENT(void)
destroyAdmldap(AdmldapInfo info);

PR_IMPLEMENT(int)
admldapGetSSLMin(AdmldapInfo info);

PR_IMPLEMENT(int)
admldapGetSSLMax(AdmldapInfo info);

PR_IMPLEMENT(char*)
admldapGetHost(AdmldapInfo info);

PR_IMPLEMENT(int)
admldapGetPort(AdmldapInfo info);

PR_IMPLEMENT(int)
admldapGetSecurity(AdmldapInfo info);

PR_IMPLEMENT(char*)
admldapGetSecurityDir(AdmldapInfo info);

PR_IMPLEMENT(int)
admldapSetSecurityDir(AdmldapInfo info, const char *securityDir);

PR_IMPLEMENT(char*)
admldapGetBaseDN(AdmldapInfo info);

PR_IMPLEMENT(char*)
admldapGetISIEDN(AdmldapInfo info);

PR_IMPLEMENT(char*)
admldapGetSIEDN(AdmldapInfo info);

PR_IMPLEMENT(char*)
admldapGetSIEPWD(AdmldapInfo info);

PR_IMPLEMENT(LDAP *)
admldapGetLDAPHndl(AdmldapInfo info);

PR_IMPLEMENT(char *)
admldapGetDirectoryURL(AdmldapInfo info);

PR_IMPLEMENT(int)
admldapSetDirectoryURL(AdmldapInfo info, const char *ldapurl);

PR_IMPLEMENT(int)
admldapSetSIEDN(AdmldapInfo info, const char *sieDN);

PR_IMPLEMENT(int)
admldapSetISIEDN(AdmldapInfo info, const char *isieDN);

PR_IMPLEMENT(char *)
admldapGetUserDN(AdmldapInfo info, char *uid);

PR_IMPLEMENT(char *)
admldapGetSysUser(AdmldapInfo info);

PR_IMPLEMENT(char *)
admldapGetSysGroup(AdmldapInfo info);

PR_IMPLEMENT(char*)
admldapGetAdminDomain(AdmldapInfo info);

PR_IMPLEMENT(char*)
admldapGetExpressRefreshRate(AdmldapInfo info);

PR_IMPLEMENT(char*)
admldapGetExpressCGITimeout(AdmldapInfo info);

PR_IMPLEMENT(char*)
admldapGetLdapStart(AdmldapInfo info);

PR_IMPLEMENT(char*)
admldapGetAuthPasswd(AdmldapInfo info);

PR_IMPLEMENT(char*)
admldapGetAuthDN(AdmldapInfo info);

PR_IMPLEMENT(char*)
admldapGetConfigFileName(AdmldapInfo info);

PR_IMPLEMENT(char*)
admldapGetAdmpwFilePath(AdmldapInfo info);

PR_IMPLEMENT(char*)
admldapGetLocalAdminName(AdmldapInfo info);

#define UG_OP_OK  0
#define UG_NO_SSL_SUPPORT 1
#define UG_AUTH_FAIL 2
#define UG_ACCESS_FAIL 3
#define UG_EMPTY_LDAPINFO 4
#define UG_NO_TARGETDN 5
#define UG_NULL_LDAP 6
#define UG_NULL_DN 7
#define UG_BAD_DN 8
#define UG_SIE_ENTRY_NOT_EXIST 9
#define UG_REF_ENTRY_NOT_EXIST 10
#define UG_ENTRY_NOT_EXIST 11
#define UG_NO_DATA 12
#define UG_SET_CONFLICT 13
#define UG_LDAP_SYSTEM_ERR 14
#define UG_OP_FAIL 15

PR_IMPLEMENT(int)
admldapGetUserDirectoryReal(struct ldap *ld, char* targetDN, char** directoryURL,
			char** bindDN, char** bindPassword,
			char** directoryInfoRef, int* error_code);

PR_IMPLEMENT(int)
admldapSetUserDirectoryReal(struct ldap *ld, char* targetDN, char* directoryURL,
			    char* bindDN, char* bindPassword,
			    char* directoryInfoRef, int* error_code);

PR_IMPLEMENT(int)
admldapGetUserDirectory(AdmldapInfo info, char* targetDN, char** directoryURL,
			char** bindDN, char** bindPassword,
			char** directoryInfoRef, int* error_code);

PR_IMPLEMENT(int)
admldapSetUserDirectory(AdmldapInfo info, char* targetDN, char* directoryURL,
			char* bindDN, char* bindPassword,
			char* directoryInfoRef, int* error_code);

PR_IMPLEMENT(int)
admldapGetLocalUserDirectory(AdmldapInfo info, char** directoryURL,
			char** bindDN, char** bindPassword,
			char** directoryInfoRef, int* error_code);

PR_IMPLEMENT(int)
admldapSetLocalUserDirectory(AdmldapInfo info, char* directoryURL,
			char* bindDN, char* bindPassword,
			char* directoryInfoRef, int* error_code);

PR_IMPLEMENT(int)
admldapGetAdmGrpUserDirectory(AdmldapInfo info, char** directoryURL,
			char** bindDN, char** bindPassword,
			char** directoryInfoRef, int* error_code);

PR_IMPLEMENT(int)
admldapSetAdmGrpUserDirectory(AdmldapInfo info, char* directoryURL,
			char* bindDN, char* bindPassword,
			char* directoryInfoRef, int* error_code);

PR_IMPLEMENT(int)
admldapGetDomainUserDirectory(AdmldapInfo info, char** directoryURL,
			char** bindDN, char** bindPassword,
			char** directoryInfoRef, int* error_code);

PR_IMPLEMENT(int)
admldapSetDomainUserDirectory(AdmldapInfo info, char* directoryURL,
			char* bindDN, char* bindPassword,
			char* directoryInfoRef, int* error_code);
PR_IMPLEMENT(void)
admldapSetLDAPHndl(AdmldapInfo info, struct ldap *ld);

PR_IMPLEMENT(char*)
admGetLocalAdmin(char* configRoot, int *errorcode);

/*
 * admSetCachedSIEPWD - set the cached copy of the SIE (admin) password.
 *   This is used to save the password during server startup, or in
 *   a CGI program that recieves the password through the CGI pipe.
 */
PR_IMPLEMENT(void)
admSetCachedSIEPWD(const char *pwd);

/*
 * admGetCachedSIEPWD - get the cached copy of the SIE (admin) password.
 *   If no password has been saved, this routine returns NULL.
 *
 *   The caller must free the result
 */
PR_IMPLEMENT(char *)
admGetCachedSIEPWD();

/* Some symbol definition from libadmin.h */
#ifdef XP_UNIX
#define FILE_PATHSEP '/'
#define OPEN_MODE "r"
#define QUOTE ""
#define CONVERT_TO_NATIVE_FS(Filename)
#define CONVERT_TO_HTTP_FORMAT(Filename)
#define WSACleanup()

#define GET_QUERY_STRING() (getenv("QUERY_STRING"))
#define NOT_ABSOLUTE_PATH(str) (str[0] != '/')
#define CREATE_DIRECTORY(Directory)
#define FILE_LOCK_PATH (get_flock_path())

#else /* XP_WIN32 */
#define verify_adm_dbm
#define add_user_dbm
#define find_user_dbm
#define list_users_dbm
#define modify_user_dbm
#define remove_user_dbm
#define dbm_open
#define dbm_close
#define dbm_store
#define lstat stat
#define popen _popen
#define pclose _pclose

#define CONVERT_TO_NATIVE_FS(Filename) 	   \
{									   	   \
	register char *s;				   	   \
	if (Filename)						   \
		for (s = Filename; *s; s++) 	   \
			if ( *s	== '/')				   \
				*s = '\\';				   \
}									 
#define CONVERT_TO_HTTP_FORMAT(Filename) 	\
{									   		\
	register char *s;					   	\
	if (Filename)				   			\
	for (s = Filename; *s; s++) 	   		\
		if ( *s	== '\\')				   	\
			*s = '/';				   		\
}									 
#define FILE_PATHSEP '/'
#define OPEN_MODE "r+b"
#define QUOTE "\""


/* Defined in util.c */
PR_IMPLEMENT(char) *Get_QueryNT(void);
#define GET_QUERY_STRING() (Get_QueryNT())

#define NOT_ABSOLUTE_PATH(str) \
  ((str[0] != '/') && (str[0] != '\\') && (str[2] != '/') && (str[2] != '\\'))

#define CREATE_DIRECTORY(Directory) CreateDirectory(Directory, NULL)
#define FILE_LOCK_PATH (get_flock_path()) 

#endif /* XP_WIN32 */

/* Maintain what amounts to a handle to a list of strings */
/* strlist.c */
PR_IMPLEMENT(char) **new_strlist(int size);
PR_IMPLEMENT(char) **grow_strlist(char **strlist, int newsize);
PR_IMPLEMENT(void) free_strlist(char **strlist);

PR_IMPLEMENT(char) *new_str(int size);
PR_IMPLEMENT(void) free_str(char *str);

 /* Report an error.  Takes 3 args: 1. Category of error 
 *                                 2. Some more specific category info (opt)
 *                                 3. A short explanation of the error. 
 * 
 * rpt_warning: same thing except doesn't exit when done whining
 *
 * This is tempory for error reporting. will be changed later!!!
 */
/* error.c */

/* CGI Task Status (NMC_Status) */
#define NMC_SUCCESS 0
#define NMC_FAILURE 1
#define NMC_WARNING 2
#define NMC_UNKNOWN 3

/* error types */
#define FILE_ERROR 0
#define MEMORY_ERROR 1
#define SYSTEM_ERROR 2
#define INCORRECT_USAGE 3
#define ELEM_MISSING 4
#define REGISTRY_DATABASE_ERROR 5
#define NETWORK_ERROR 6
#define GENERAL_FAILURE 7
#define WARNING 8
#define APP_ERROR 9

/* The upper bound on error types */
#define NMC_MAX_ERROR 10

/* The default error type (in case something goes wrong */
#define DEFAULT_ERROR 3

PR_IMPLEMENT(void) rpt_success(const char *description);
PR_IMPLEMENT(void) rpt_err(int type, const char *info, const char *details, const char *extra);
PR_IMPLEMENT(void) rpt_warning(int type, const char *info, const char *details, const char *extra);
PR_IMPLEMENT(void) rpt_unknown(const char *description);
#define WORD_WRAP_WIDTH 80
PR_IMPLEMENT(char) *alert_wrd_wrap(char *str, int width, char *linefeed);

/*
 * If the UTF8 string "s" contains any HTML special characters, make a
 * duplicate where the appropriate HTML "entities" have been substituted
 * for the special chars.  For example, "<mcs@ace.com>" will be translated
 * to "&lt;mcs@ace.com&gt;".
 * 
 * If "s" does not contain any special characters, it is returned and
 *	*madecopyp is set to 0.
 * Otherwise a malloc'd string is returned and *madecopyp is set to 1.
 */
PR_IMPLEMENT(char *) strdup_escape_entities(char *s, int *madecopyp);

/* this will convert a string with escaped entities ("&amp;")
   back to the original unescaped string ("&")
   This is necessary for converting URLs and other values which would normally
   have entities in them (e.g. search?context=foo&amp;dn=bar)
   for use in javascript (e.g. window.href = 'search?context=foo&dn=bar')
   since javascript must use the unescaped version
   This converts the string in place since the entities "&amp;"
   take up much more room than the single character represented
   If you need to work on a copy then make a copy with strdup first.
*/
PR_IMPLEMENT(void) unescape_entities(char *s);

/* Get internal variable info data structure */
/* This is hack, should be removed later - YJH */
/* form_post.c */
PR_IMPLEMENT(char) **get_input_ptr(void);
 
/* Unescape an %-encoded form variable. */
/* form_post.c */
PR_IMPLEMENT(void) form_unescape(char *str);
 
/* Unescape an %-encoded form variable; escape <, >, &, ", ' */
/* form_post.c */
PR_IMPLEMENT(char *) form_unescape_url_escape_html(char *str);

/* Initialize a form "post" using the GET method.  Send this fn the QS
 * directly.*/
/* form_post.c */
PR_IMPLEMENT(void) get_begin(char *qs);
 
/* Initialize a form "post" using the POST method.  Send this fn "stdin". */
/* form_post.c */
PR_IMPLEMENT(int) post_begin(FILE *in);
 
/* Turn a variable string into a vars vector. */
/* form_post.c */
PR_IMPLEMENT(char) **string_to_vec(char *in);
 
/* Get a cgi variable from the variable list.  NOTE:  Must be initialized
 * with get_begin or post_begin!!!! */
/* form_post.c */

PR_IMPLEMENT(char) *get_cgi_var(char *varname, char *elem_id, char *bongmsg);
 
/* Get an int cgi variable (calls get_cgi_var()). */
/* form_post.c */
PR_IMPLEMENT(int) get_cgi_int(char *varname);
 
/* Get a long int cgi variable (calls get_cgi_var()). */
/* form_post.c */
PR_IMPLEMENT(long) get_cgi_long(char *varname);
 
/* Get a bool cgi variable (true iff value is not "" nor "0") */
/* form_post.c */
PR_IMPLEMENT(int) get_cgi_bool(char *varname);
 
/* Get all multiple values for a cgi variable from the variable list.
 * Note: Must be initialized with get_begin or post_begin!!!! */
/* form_post.c */
PR_IMPLEMENT(char) **get_cgi_multiple(char *varname, char *elem_id, char *bongmsg
);
 
/* Get rid of trailing slashes on strings. */
/* form_post.c */
PR_IMPLEMENT(void) rm_trail_slash(char *target);
 
/* Compresses spaces in place on a string */
/* form_post.c */
PR_IMPLEMENT(void) compress_spaces(char *source);
 
/* Compresses spaces and replaces commas with an or list */
/* form_post.c */
PR_IMPLEMENT(char) * compress_and_replace(char *source);

#ifdef __cplusplus
}
#endif

#endif /* __ADMUTIL_H__ */
