gecko-dev/lib/libmisc/dirprefs.c
1998-03-28 02:44:41 +00:00

2506 lines
66 KiB
C

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/* dirprefs.c -- directory server preferences */
#include "rosetta.h"
#include "xp.h"
#include "xp_mcom.h"
#include "xpgetstr.h"
#include "dirprefs.h"
#include "prefapi.h"
#include "libi18n.h"
#ifdef MOZ_LDAP
#include "ldap.h"
HG82168
#else
#define LDAP_PORT 389
#define LDAPS_PORT 636
#endif /* MOZ_LDAP */
#if !defined(MOZADDRSTANDALONE)
extern int MK_OUT_OF_MEMORY;
extern int MK_ADDR_PAB;
extern int MK_LDAP_COMMON_NAME;
extern int MK_LDAP_GIVEN_NAME;
extern int MK_LDAP_SURNAME;
extern int MK_LDAP_EMAIL_ADDRESS;
extern int MK_LDAP_PHONE_NUMBER;
extern int MK_LDAP_ORGANIZATION;
extern int MK_LDAP_ORG_UNIT;
extern int MK_LDAP_LOCALITY;
extern int MK_LDAP_STREET;
extern int MK_LDAP_CUSTOM1;
extern int MK_LDAP_CUSTOM2;
extern int MK_LDAP_CUSTOM3;
extern int MK_LDAP_CUSTOM4;
extern int MK_LDAP_CUSTOM5;
extern int MK_LDAP_REPL_CANT_SYNC_REPLICA;
#else
#define MK_OUT_OF_MEMORY -1;
#endif /* #if !defined(MOZADDRSTANDALONE) */
/*****************************************************************************
* Private structs and stuff
*/
/* DIR_Server.flags */
#define DIR_AUTO_COMPLETE_ENABLED 0x00000001
#define DIR_ENABLE_AUTH 0x00000002
#define DIR_SAVE_PASSWORD 0x00000004
#define DIR_DEFEAT_UTF8 0x00000008
#define DIR_IS_SECURE 0x00000010
#define DIR_SAVE_RESULTS 0x00000020
#define DIR_EFFICIENT_WILDCARDS 0x00000040
/* DIR_Server.customAttributes is a list of DIR_Attribute structures */
typedef struct DIR_Attribute
{
DIR_AttributeId id;
char *prettyName;
char **attrNames;
} DIR_Attribute;
struct _DIR_ReplicationInfo
{
XP_Bool enabled; /* duh */
char *description; /* human readable description of replica */
char *filter; /* LDAP filter string which constrains the repl search */
int32 lastChangeNumber; /* Last change we saw -- start replicating here */
int32 generation; /* LDAP server's scoping of the lastChangeNumber */
/* this changes when the server's DB gets reloaded from LDIF */
char **excludedAttributes; /* list of attributes we shouldn't replicate */
int excludedAttributesCount; /* duh */
};
/* Our internal view of a default attribute is a resourceId for the pretty
* name and the real attribute name. These are catenated to create a string
* of the form "Pretty Name:attrname"
*/
typedef struct DIR_DefaultAttribute
{
DIR_AttributeId id;
int resourceId;
char *name;
} DIR_DefaultAttribute;
/* DIR_Filter.flags */
#define DIR_F_SUBST_STARS_FOR_SPACES 0x00000001
#define DIR_F_REPEAT_FILTER_FOR_TOKENS 0x00000002
/* DIR_Server.filters is a list of DIR_Filter structures */
typedef struct DIR_Filter
{
char *string;
uint32 flags;
} DIR_Filter;
/* Default settings for site-configurable prefs */
#define kDefaultTokenSeps " ,."
#define kDefaultSubstStarsForSpaces TRUE
#define kDefaultRepeatFilterForTokens TRUE
#define kDefaultEfficientWildcards TRUE
#define kDefaultFilter "(cn=*%s*)"
#define kDefaultEfficientFilter "(|(givenname=%s)(sn=%s))"
#define kDefaultStopOnHit TRUE
#define kDefaultMaxHits 100
#define kDefaultIsOffline TRUE
#define kDefaultEnableAuth FALSE
#define kDefaultSavePassword FALSE
#define kDefaultAutoCompleteEnabled FALSE
#define kDefaultReplicaExcludedAttributes ""
#define kDefaultReplicaEnabled FALSE
#define kDefaultReplicaFilter "(objectclass=*)"
#define kDefaultReplicaChangeNumber 0
#define kDefaultReplicaChangeNumberGeneration 0
#define kDefaultReplicaDescription ""
#define kDefaultUtf8Disabled FALSE
#define kLdapServersPrefName "network.hosts.ldap_servers"
const char *DIR_GetAttributeName (DIR_Server *server, DIR_AttributeId id);
void DIR_SetServerFileName(DIR_Server* pServer, const char* leafName);
static DIR_DefaultAttribute *DIR_GetDefaultAttribute (DIR_AttributeId id);
/*****************************************************************************
* Functions for creating DIR_Servers
*/
int DIR_InitServer (DIR_Server *server)
{
XP_ASSERT(server);
if (server)
{
XP_BZERO(server, sizeof(DIR_Server));
server->saveResults = TRUE;
server->efficientWildcards = kDefaultEfficientWildcards;
server->port = LDAP_PORT;
server->maxHits = kDefaultMaxHits;
server->isOffline = kDefaultIsOffline;
}
return 0;
}
/*****************************************************************************
* Functions for cloning DIR_Servers
*/
static DIR_Attribute *DIR_CopyAttribute (DIR_Attribute *inAttribute)
{
DIR_Attribute *outAttribute = (DIR_Attribute*) XP_ALLOC(sizeof(DIR_Attribute));
if (outAttribute)
{
int count = 0;
outAttribute->id = inAttribute->id;
outAttribute->prettyName = XP_STRDUP(inAttribute->prettyName);
while (inAttribute->attrNames[count])
count++;
outAttribute->attrNames = (char**) XP_ALLOC((count + 1) * sizeof(char*));
if (outAttribute->attrNames)
{
int i;
for (i = 0; i < count; i++)
outAttribute->attrNames[i] = XP_STRDUP(inAttribute->attrNames[i]);
outAttribute->attrNames[i] = NULL;
}
}
return outAttribute;
}
static DIR_Filter *DIR_CopyFilter (DIR_Filter *inFilter)
{
DIR_Filter *outFilter = (DIR_Filter*) XP_ALLOC(sizeof(DIR_Filter));
if (outFilter)
{
outFilter->flags = inFilter->flags;
outFilter->string = XP_STRDUP(inFilter->string);
}
return outFilter;
}
static int dir_CopyTokenList (char **inList, int inCount, char ***outList, int *outCount)
{
int status = 0;
if (0 != inCount && NULL != inList)
{
*outList = (char**) XP_ALLOC(inCount * sizeof(char*));
if (*outList)
{
int i;
for (i = 0; i < inCount; i++)
(*outList)[i] = XP_STRDUP (inList[i]);
*outCount = inCount;
}
else
status = MK_OUT_OF_MEMORY;
}
return status;
}
static DIR_ReplicationInfo *dir_CopyReplicationInfo (DIR_ReplicationInfo *inInfo)
{
DIR_ReplicationInfo *outInfo = (DIR_ReplicationInfo*) XP_CALLOC (sizeof(DIR_ReplicationInfo), 1);
if (outInfo)
{
outInfo->lastChangeNumber = inInfo->lastChangeNumber;
outInfo->generation = inInfo->generation;
outInfo->enabled = inInfo->enabled;
if (inInfo->description)
outInfo->description = XP_STRDUP (inInfo->description);
if (inInfo->filter)
outInfo->filter = XP_STRDUP (inInfo->filter);
dir_CopyTokenList (inInfo->excludedAttributes, inInfo->excludedAttributesCount,
&outInfo->excludedAttributes, &outInfo->excludedAttributesCount);
}
return outInfo;
}
int DIR_CopyServer (DIR_Server *in, DIR_Server **out)
{
int err = 0;
if (in) {
*out = XP_ALLOC(sizeof(DIR_Server));
if (*out)
{
XP_BZERO (*out, sizeof(DIR_Server));
if (in->description)
{
(*out)->description = XP_STRDUP(in->description);
if (!(*out)->description)
err = MK_OUT_OF_MEMORY;
}
if (in->serverName)
{
(*out)->serverName = XP_STRDUP(in->serverName);
if (!(*out)->serverName)
err = MK_OUT_OF_MEMORY;
}
if (in->searchBase)
{
(*out)->searchBase = XP_STRDUP(in->searchBase);
if (!(*out)->searchBase)
err = MK_OUT_OF_MEMORY;
}
if (in->fileName)
{
(*out)->fileName = XP_STRDUP(in->fileName);
if (!(*out)->fileName)
err = MK_OUT_OF_MEMORY;
}
if (in->prefId)
{
(*out)->prefId = XP_STRDUP(in->prefId);
if (!(*out)->prefId)
err = MK_OUT_OF_MEMORY;
}
(*out)->port = in->port;
(*out)->maxHits = in->maxHits;
(*out)->isSecure = in->isSecure;
(*out)->saveResults = in->saveResults;
(*out)->isOffline = in->isOffline;
(*out)->efficientWildcards = in->efficientWildcards;
(*out)->dirType = in->dirType;
(*out)->flags = in->flags;
(*out)->enableAuth = in->enableAuth;
(*out)->savePassword = in->savePassword;
if (in->authDn)
{
(*out)->authDn = XP_STRDUP (in->authDn);
if (!(*out)->authDn)
err = MK_OUT_OF_MEMORY;
}
if (in->password)
{
(*out)->password = XP_STRDUP (in->password);
if (!(*out)->password)
err = MK_OUT_OF_MEMORY;
}
if (in->customAttributes)
{
(*out)->customAttributes = XP_ListNew();
if ((*out)->customAttributes)
{
XP_List *list = in->customAttributes;
DIR_Attribute *attribute = NULL;
while ((attribute = XP_ListNextObject (list)) != NULL)
{
DIR_Attribute *outAttr = DIR_CopyAttribute (attribute);
if (outAttr)
XP_ListAddObject ((*out)->customAttributes, outAttr);
else
err = MK_OUT_OF_MEMORY;
}
}
else
err = MK_OUT_OF_MEMORY;
}
if (in->customFilters)
{
(*out)->customFilters = XP_ListNew();
if ((*out)->customFilters)
{
XP_List *list = in->customFilters;
DIR_Filter *filter = NULL;
while ((filter = XP_ListNextObject (list)) != NULL)
{
DIR_Filter *outFilter = DIR_CopyFilter (filter);
if (outFilter)
XP_ListAddObject ((*out)->customFilters, outFilter);
else
err = MK_OUT_OF_MEMORY;
}
}
else
err = MK_OUT_OF_MEMORY;
}
if (in->replInfo)
(*out)->replInfo = dir_CopyReplicationInfo (in->replInfo);
if (in->basicSearchAttributesCount > 0)
{
int bsaLength = in->basicSearchAttributesCount * sizeof(DIR_AttributeId);
(*out)->basicSearchAttributes = (DIR_AttributeId*) XP_ALLOC(bsaLength);
if ((*out)->basicSearchAttributes)
{
XP_MEMCPY ((*out)->basicSearchAttributes, in->basicSearchAttributes, bsaLength);
(*out)->basicSearchAttributesCount = in->basicSearchAttributesCount;
}
}
dir_CopyTokenList (in->dnAttributes, in->dnAttributesCount,
&(*out)->dnAttributes, &(*out)->dnAttributesCount);
dir_CopyTokenList (in->suppressedAttributes, in->suppressedAttributesCount,
&(*out)->suppressedAttributes, &(*out)->suppressedAttributesCount);
if (in->customDisplayUrl)
(*out)->customDisplayUrl = XP_STRDUP (in->customDisplayUrl);
}
else {
err = MK_OUT_OF_MEMORY;
(*out) = NULL;
}
}
else {
XP_ASSERT (0);
err = -1;
(*out) = NULL;
}
return err;
}
/*****************************************************************************
* Function for comparing DIR_Servers
*/
XP_Bool DIR_AreServersSame (DIR_Server *first, DIR_Server *second)
{
XP_Bool result = FALSE;
if (first && second)
{
/* assume for right now one personal address book type where offline is false */
if ((first->dirType == PABDirectory) && (second->dirType == PABDirectory)) {
if ((first->isOffline == FALSE) && (second->isOffline == FALSE))
return TRUE;
else {
XP_ASSERT (first->serverName && second->serverName);
if (first->serverName && second->serverName)
{
if (XP_STRCASECMP (first->serverName, second->serverName) == 0)
{
if (first->port == second->port)
{
/* allow for a null search base */
if (first->searchBase == NULL && second->searchBase == NULL)
return TRUE;
/* otherwise check the strings */
if (first->searchBase && second->searchBase)
{
if (XP_STRCASECMP (first->searchBase, second->searchBase) == 0)
{
return TRUE;
}
else
return FALSE;
}
else
return FALSE;
}
}
else
return FALSE;
}
}
}
if (first->dirType != second->dirType)
return FALSE;
/* otherwise check for ldap servers */
XP_ASSERT (first->serverName && second->serverName);
if (first->serverName && second->serverName)
{
if (!XP_STRCASECMP (first->serverName, second->serverName))
{
if (first->port == second->port)
{
/* allow for a null search base */
if (first->searchBase == NULL && second->searchBase == NULL)
result = TRUE;
/* otherwise check the strings */
if (first->searchBase && second->searchBase)
{
if (!XP_STRCASECMP (first->searchBase, second->searchBase))
{
result = TRUE;
}
}
}
}
}
}
return result;
}
/*****************************************************************************
* Functions for destroying DIR_Servers
*/
static void dir_DeleteTokenList (char **tokenList, int tokenListCount)
{
int tokenIdx;
for (tokenIdx = 0; tokenIdx < tokenListCount; tokenIdx++)
XP_FREE(tokenList[tokenIdx]);
XP_FREE(tokenList);
}
static int DIR_DeleteFilter (DIR_Filter *filter)
{
if (filter->string)
XP_FREE(filter->string);
XP_FREE(filter);
return 0;
}
static int DIR_DeleteAttribute (DIR_Attribute *attribute)
{
int i = 0;
if (attribute->prettyName)
XP_FREE(attribute->prettyName);
if (attribute->attrNames)
{
while (attribute->attrNames[i])
XP_FREE((char**)attribute->attrNames[i++]);
XP_FREE(attribute->attrNames);
}
XP_FREE(attribute);
return 0;
}
static void dir_DeleteReplicationInfo (DIR_Server *server)
{
DIR_ReplicationInfo *info = NULL;
if (server && (info = server->replInfo) != NULL)
{
dir_DeleteTokenList (info->excludedAttributes, info->excludedAttributesCount);
XP_FREEIF(info->description);
XP_FREEIF(info->filter);
XP_FREE(info);
}
}
int DIR_DeleteServer (DIR_Server *server)
{
if (server)
{
int i;
XP_FREEIF (server->description);
XP_FREEIF (server->serverName);
XP_FREEIF (server->searchBase);
XP_FREEIF (server->fileName);
XP_FREEIF (server->lastSearchString);
XP_FREEIF (server->tokenSeps);
XP_FREEIF (server->authDn);
XP_FREEIF (server->password);
XP_FREEIF (server->prefId);
if (server->customFilters)
{
for (i = 1; i <= XP_ListCount(server->customFilters); i++)
DIR_DeleteFilter ((DIR_Filter*) XP_ListGetObjectNum (server->customFilters, i));
XP_ListDestroy (server->customFilters);
}
if (server->customAttributes)
{
XP_List *list = server->customAttributes;
DIR_Attribute *walkAttrStruct = NULL;
while ((walkAttrStruct = XP_ListNextObject(list)) != NULL)
DIR_DeleteAttribute (walkAttrStruct);
XP_ListDestroy (server->customAttributes);
}
if (server->suppressedAttributes)
dir_DeleteTokenList (server->suppressedAttributes, server->suppressedAttributesCount);
if (server->dnAttributes)
dir_DeleteTokenList (server->dnAttributes, server->dnAttributesCount);
XP_FREEIF (server->basicSearchAttributes);
if (server->replInfo)
dir_DeleteReplicationInfo (server);
XP_FREEIF (server->customDisplayUrl);
XP_FREE (server);
}
return 0;
}
int DIR_DeleteServerList(XP_List *wholeList)
{
int i;
if (wholeList)
{
for (i = 1; i <= XP_ListCount(wholeList); i++)
DIR_DeleteServer(XP_ListGetObjectNum (wholeList, i));
XP_ListDestroy (wholeList);
}
return 0;
}
int DIR_CleanUpServerPreferences(XP_List *deletedList)
{
int i;
if (deletedList)
{
for (i = 1; i <= XP_ListCount(deletedList); i++)
{
DIR_Server *server = (DIR_Server *) (XP_ListGetObjectNum (deletedList, i));
if (server)
{
#if !defined(MOZADDRSTANDALONE)
if (server->fileName)
XP_FileRemove (server->fileName, xpAddrBookNew);
#endif
}
}
DIR_DeleteServerList(deletedList);
}
return 0;
}
/*****************************************************************************
* Functions for retrieving subsets of the DIR_Server list
*/
int DIR_GetHtmlServers (XP_List *wholeList, XP_List *subList)
{
int i;
if (wholeList && subList)
{
for (i = 1; i <= XP_ListCount(wholeList); i++)
{
DIR_Server *s = (DIR_Server*) XP_ListGetObjectNum (wholeList, i);
if (HTMLDirectory == s->dirType)
XP_ListAddObjectToEnd (subList, s);
}
return 0;
}
return -1;
}
int DIR_GetLdapServers (XP_List *wholeList, XP_List *subList)
{
int i;
if (wholeList && subList)
{
for (i = 1; i <= XP_ListCount(wholeList); i++)
{
DIR_Server *s = (DIR_Server*) XP_ListGetObjectNum (wholeList, i);
if (LDAPDirectory == s->dirType)
XP_ListAddObjectToEnd (subList, s);
}
return 0;
}
return -1;
}
int DIR_ReorderLdapServers (XP_List *wholeList)
{
int status = 0;
int length = 0;
DIR_Server *s = NULL;
char *prefValue = NULL;
XP_List *walkList = wholeList;
while (s = (DIR_Server*) XP_ListNextObject (walkList))
{
length += XP_STRLEN (s->prefId) + 2; /* +2 for ", " */
}
prefValue = (char*) XP_ALLOC (length + 1); /* +1 for null term */
if (prefValue)
{
*prefValue = '\0';
walkList = wholeList;
while (s = (DIR_Server*) XP_ListNextObject (walkList))
{
XP_STRCAT (prefValue, s->prefId);
XP_STRCAT (prefValue, ", ");
}
if (PREF_SetCharPref (kLdapServersPrefName, prefValue) < 0)
status = -1; /* not sure how to make a pref error into an mk error */
XP_FREE(prefValue);
}
else
status = MK_OUT_OF_MEMORY;
return status;
}
int DIR_GetPersonalAddressBook (XP_List *wholeList, DIR_Server **pab)
{
int i;
if (wholeList && pab)
{
*pab = NULL;
for (i = 1; i <= XP_ListCount(wholeList); i++)
{
DIR_Server *s = (DIR_Server*) XP_ListGetObjectNum (wholeList, i);
if ((PABDirectory == s->dirType) && (FALSE == s->isOffline))
{
if (s->serverName) {
if (XP_STRLEN (s->serverName) == 0) {
*pab = s;
return 0;
}
}
if (s->serverName == NULL) {
*pab = s;
return 0;
}
}
}
}
return -1;
}
int DIR_GetComposeNameCompletionAddressBook (XP_List *wholeList, DIR_Server **cab)
{
int i;
if (wholeList && cab)
{
*cab = NULL;
for (i = 1; i <= XP_ListCount(wholeList); i++)
{
DIR_Server *s = (DIR_Server*) XP_ListGetObjectNum (wholeList, i);
if (PABDirectory == s->dirType)
{
*cab = s;
return 0;
}
}
}
return -1;
}
/*****************************************************************************
* Functions for managing JavaScript prefs for the DIR_Servers
*/
#if !defined(MOZADDRSTANDALONE)
static char *DIR_GetStringPref (const char *prefRoot, const char *prefLeaf, char *scratch, const char *defaultValue)
{
int valueLength = 0;
char *value = NULL;
XP_STRCPY(scratch, prefRoot);
XP_STRCAT (scratch, prefLeaf);
if (PREF_NOERROR == PREF_CopyCharPref(scratch, &value))
{
/* unfortunately, there may be some prefs out there which look like this */
if (!XP_STRCMP(value, "(null)"))
value = XP_STRDUP(defaultValue);
}
else
value = XP_STRDUP(defaultValue);
return value;
}
static int32 DIR_GetIntPref (const char *prefRoot, const char *prefLeaf, char *scratch, int32 defaultValue)
{
int32 value;
XP_STRCPY(scratch, prefRoot);
if (PREF_NOERROR != PREF_GetIntPref(XP_STRCAT (scratch, prefLeaf), &value))
value = defaultValue;
return value;
}
static XP_Bool DIR_GetBoolPref (const char *prefRoot, const char *prefLeaf, char *scratch, XP_Bool defaultValue)
{
XP_Bool value;
XP_STRCPY(scratch, prefRoot);
if (PREF_NOERROR != PREF_GetBoolPref(XP_STRCAT (scratch, prefLeaf), &value))
value = defaultValue;
return value;
}
int DIR_AttributeNameToId (const char *attrName, DIR_AttributeId *id)
{
int status = 0;
switch (attrName[0])
{
case 'a':
if (!XP_STRCASECMP(attrName, "auth"))
*id = auth;
else
status = -1;
break;
case 'c' :
if (!XP_STRCASECMP(attrName, "cn"))
*id = cn;
else if (!XP_STRNCASECMP(attrName, "custom", 6))
{
switch (attrName[6])
{
case '1': *id = custom1; break;
case '2': *id = custom2; break;
case '3': *id = custom3; break;
case '4': *id = custom4; break;
case '5': *id = custom5; break;
default: status = -1;
}
}
else
status = -1;
break;
case 'g':
if (!XP_STRCASECMP(attrName, "givenname"))
*id = givenname;
else
status = -1;
break;
case 's':
if (!XP_STRCASECMP(attrName, "street"))
*id = street;
else if (!XP_STRCASECMP(attrName, "sn"))
*id = sn;
else
status = -1;
break;
case 'm':
if (!XP_STRCASECMP(attrName, "mail"))
*id = mail;
else
status = -1;
break;
case 'o':
if (!XP_STRCASECMP(attrName, "o"))
*id = o;
else if (!XP_STRCASECMP(attrName, "ou"))
*id = ou;
else
status = -1;
break;
case 'l':
if (!XP_STRCASECMP(attrName, "l"))
*id = l;
else
status = -1;
break;
case 't':
if (!XP_STRCASECMP(attrName, "telephoneNumber"))
*id = telephonenumber;
else
status = -1;
break;
default:
status = -1;
}
return status;
}
static int DIR_AddCustomAttribute (DIR_Server *server, const char *attrName, char *jsAttr)
{
int status = 0;
char *jsCompleteAttr = NULL;
char *jsAttrForTokenizing = jsAttr;
DIR_AttributeId id;
status = DIR_AttributeNameToId (attrName, &id);
/* If the string they gave us doesn't have a ':' in it, assume it's one or more
* attributes without a pretty name. So find the default pretty name, and generate
* a "complete" string to use for tokenizing.
*/
if (status == 0 && !XP_STRCHR(jsAttr, ':'))
{
const char *defaultPrettyName = DIR_GetAttributeName (server, id);
if (defaultPrettyName)
{
jsCompleteAttr = PR_smprintf ("%s:%s", defaultPrettyName, jsAttr);
if (jsCompleteAttr)
jsAttrForTokenizing = jsCompleteAttr;
else
status = MK_OUT_OF_MEMORY;
}
}
if (status == 0)
{
char *scratchAttr = XP_STRDUP(jsAttrForTokenizing);
DIR_Attribute *attrStruct = (DIR_Attribute*) XP_ALLOC(sizeof(DIR_Attribute));
if (!server->customAttributes)
server->customAttributes = XP_ListNew();
if (attrStruct && server->customAttributes && scratchAttr)
{
char *attrToken = NULL;
int attrCount = 0;
XP_BZERO(attrStruct, sizeof(DIR_Attribute));
/* Try to pull out the pretty name into the struct */
attrStruct->id = id;
attrStruct->prettyName = XP_STRDUP(XP_STRTOK(scratchAttr, ":"));
/* Count up the attribute names */
while ((attrToken = XP_STRTOK(NULL, ", ")) != NULL)
attrCount++;
/* Pull the attribute names into the struct */
XP_STRCPY(scratchAttr, jsAttrForTokenizing);
XP_STRTOK(scratchAttr, ":");
attrStruct->attrNames = (char**) XP_ALLOC((attrCount + 1) * sizeof(char*));
if (attrStruct->attrNames)
{
int i = 0;
while ((attrToken = XP_STRTOK(NULL, ", ")) != NULL)
attrStruct->attrNames[i++] = XP_STRDUP(attrToken);
attrStruct->attrNames[i] = NULL; /* null-terminate the array */
}
if (status == 0)
XP_ListAddObject (server->customAttributes, attrStruct);
else
DIR_DeleteAttribute (attrStruct);
XP_FREE(scratchAttr);
}
else
status = MK_OUT_OF_MEMORY;
}
if (jsCompleteAttr)
XP_FREE(jsCompleteAttr);
return status;
}
static int dir_CreateTokenListFromWholePref (const char *pref, char ***outList, int *outCount)
{
int result = 0;
char *commaSeparatedList = NULL;
if (PREF_NOERROR == PREF_CopyCharPref (pref, &commaSeparatedList) && commaSeparatedList)
{
char *tmpList = commaSeparatedList;
*outCount = 1;
while (*tmpList)
if (*tmpList++ == ',')
(*outCount)++;
*outList = (char**) XP_ALLOC (*outCount * sizeof(char*));
if (*outList)
{
int i;
char *token = XP_STRTOK (commaSeparatedList, ", ");
for (i = 0; i < *outCount; i++)
{
(*outList)[i] = XP_STRDUP (token);
token = XP_STRTOK(NULL, ", ");
}
}
else
result = MK_OUT_OF_MEMORY;
XP_FREE (commaSeparatedList);
}
else
result = -1;
return result;
}
static int dir_CreateTokenListFromPref (const char *prefBase, const char *prefLeaf, char *scratch, char ***outList, int *outCount)
{
XP_STRCPY (scratch, prefBase);
XP_STRCAT (scratch, prefLeaf);
return dir_CreateTokenListFromWholePref (scratch, outList, outCount);
}
static int dir_ConvertTokenListToIdList (char **tokenList, int tokenCount, DIR_AttributeId **outList)
{
*outList = (DIR_AttributeId*) XP_ALLOC (sizeof(DIR_AttributeId) * tokenCount);
if (*outList)
{
int i;
for (i = 0; i < tokenCount; i++)
DIR_AttributeNameToId (tokenList[i], &(*outList)[i]);
}
else
return MK_OUT_OF_MEMORY;
return 0;
}
static void dir_GetReplicationInfo (const char *prefName, DIR_Server *server, char *scratch)
{
char *childList = NULL;
XP_STRCPY (scratch, prefName);
if (PREF_NOERROR == PREF_CreateChildList (XP_STRCAT(scratch, "replication"), &childList))
{
XP_ASSERT (server->replInfo == NULL);
if (childList && childList[0])
{
server->replInfo = (DIR_ReplicationInfo *) XP_CALLOC (sizeof (DIR_ReplicationInfo), 1);
if (server->replInfo)
{
char *child = NULL;
int index = 0;
while ((child = PREF_NextChild (childList, &index)) != NULL)
{
char *leaf = XP_STRRCHR (child, '.');
if (leaf)
{
leaf++; /* skip over the '.' */
/* Note: JS prefs are case-sensitive, and so is this code */
switch (leaf[0])
{
case 'd':
if (!XP_STRCMP (leaf, "description"))
PREF_CopyCharPref (child, &server->replInfo->description);
else
XP_ASSERT(FALSE);
break;
case 'e':
if (!XP_STRCMP (leaf, "enabled"))
PREF_GetBoolPref (child, &server->replInfo->enabled);
else if (!XP_STRCMP (leaf, "excludedAttributes"))
dir_CreateTokenListFromWholePref (child, &server->replInfo->excludedAttributes,
&server->replInfo->excludedAttributesCount);
else
XP_ASSERT(FALSE);
break;
case 'f' :
if (!XP_STRCMP (leaf, "filter"))
PREF_CopyCharPref (child, &server->replInfo->filter);
else
XP_ASSERT(FALSE);
break;
case 'g':
if (!XP_STRCMP (leaf, "generation"))
PREF_GetIntPref (child, &server->replInfo->generation);
else
XP_ASSERT(FALSE);
break;
case 'l':
if (!XP_STRCMP (leaf, "lastChangeNumber"))
PREF_GetIntPref (child, &server->replInfo->lastChangeNumber);
else
XP_ASSERT(FALSE);
break;
default:
XP_ASSERT(FALSE);
}
}
}
}
}
XP_FREE(childList);
}
}
/* Called at startup-time to read whatever overrides the LDAP site administrator has
* done to the attribute names
*/
static int DIR_GetCustomAttributePrefs (const char *prefName, DIR_Server *server, char *scratch)
{
char **tokenList = NULL;
char *childList = NULL;
XP_STRCPY(scratch, prefName);
if (PREF_NOERROR == PREF_CreateChildList(XP_STRCAT(scratch, "attributes"), &childList))
{
if (childList && childList[0])
{
char *child = NULL;
int index = 0;
while ((child = PREF_NextChild (childList, &index)) != NULL)
{
char *jsValue = NULL;
if (PREF_NOERROR == PREF_CopyCharPref (child, &jsValue))
{
if (jsValue && jsValue[0])
{
char *attrName = child + XP_STRLEN(scratch) + 1;
DIR_AddCustomAttribute (server, attrName, jsValue);
}
XP_FREEIF(jsValue);
}
}
}
XP_FREEIF(childList);
}
/* The replicated attributes and basic search attributes can only be
* attributes which are in our predefined set (DIR_AttributeId) so
* store those in an array of IDs for more convenient access
*/
dir_GetReplicationInfo (prefName, server, scratch);
if (0 == dir_CreateTokenListFromPref (prefName, "basicSearchAttributes", scratch,
&tokenList, &server->basicSearchAttributesCount))
{
dir_ConvertTokenListToIdList (tokenList, server->basicSearchAttributesCount,
&server->basicSearchAttributes);
dir_DeleteTokenList (tokenList, server->basicSearchAttributesCount);
}
/* The DN attributes and suppressed attributes can be attributes that
* we've never heard of, so they're stored by name, so we can match 'em
* as we get 'em from the server
*/
dir_CreateTokenListFromPref (prefName, "html.dnAttributes", scratch,
&server->dnAttributes, &server->dnAttributesCount);
dir_CreateTokenListFromPref (prefName, "html.excludedAttributes", scratch,
&server->suppressedAttributes, &server->suppressedAttributesCount);
return 0;
}
/* Called at startup-time to read whatever overrides the LDAP site administrator has
* done to the filtering logic
*/
static int DIR_GetCustomFilterPrefs (const char *prefName, DIR_Server *server, char *scratch)
{
int status = 0;
XP_Bool keepGoing = TRUE;
int filterNum = 1;
char *localScratch = XP_ALLOC(128);
if (!localScratch)
return MK_OUT_OF_MEMORY;
while (keepGoing && !status)
{
char *childList = NULL;
PR_snprintf (scratch, 128, "%sfilter%d", prefName, filterNum);
if (PREF_NOERROR == PREF_CreateChildList(scratch, &childList))
{
if ('\0' != childList[0])
{
DIR_Filter *filter = (DIR_Filter*) XP_ALLOC (sizeof(DIR_Filter));
if (filter)
{
XP_Bool tempBool;
XP_BZERO(filter, sizeof(DIR_Filter));
/* Pull per-directory filter preferences out of JS values */
if (1 == filterNum)
{
server->tokenSeps = DIR_GetStringPref (prefName, "wordSeparators", localScratch, kDefaultTokenSeps);
#if 0
/* This is left over from when I thought I'd have time to let the
** admin specify a list of filters, and we'd run them until we got
** a hit. Still a good idea, but probably too late for Dogbert.
*/
server->stopFiltersOnHit = DIR_GetBoolPref (prefName, "stopFiltersOnHit", localScratch, kDefaultStopOnHit);
#endif
XP_STRCAT(scratch, ".");
}
/* Pull per-filter preferences out of JS values */
filter->string = DIR_GetStringPref (scratch, "string", localScratch,
server->efficientWildcards ? kDefaultFilter : kDefaultEfficientFilter);
tempBool = DIR_GetBoolPref (scratch, "repeatFilterForWords", localScratch, kDefaultRepeatFilterForTokens);
if (tempBool)
filter->flags |= DIR_F_REPEAT_FILTER_FOR_TOKENS;
tempBool = DIR_GetBoolPref (scratch, "substituteStarsForSpaces", localScratch, kDefaultSubstStarsForSpaces);
if (tempBool)
filter->flags |= DIR_F_SUBST_STARS_FOR_SPACES;
/* Add resulting DIR_Filter to the list */
if (!server->customFilters)
server->customFilters = XP_ListNew();
if (server->customFilters)
XP_ListAddObject (server->customFilters, filter);
else
status = MK_OUT_OF_MEMORY;
}
else
status = MK_OUT_OF_MEMORY;
filterNum++;
}
else
keepGoing = FALSE;
XP_FREE(childList);
}
else
keepGoing = FALSE;
}
XP_FREE(localScratch);
return status;
}
/* This will convert from the old preference that was a path and filename */
/* to a just a filename */
void DIR_ConvertServerFileName(DIR_Server* pServer)
{
char* leafName = pServer->fileName;
char* newLeafName = NULL;
#if defined(XP_WIN) || defined(XP_OS2)
/* jefft -- bug 73349 This is to allow users share same address book.
* It only works if the user specify a full path filename.
*/
if (! XP_FileIsFullPath(leafName))
newLeafName = XP_STRRCHR (leafName, '\\');
#else
newLeafName = XP_STRRCHR (leafName, '/');
#endif
pServer->fileName = newLeafName ? XP_STRDUP(newLeafName + 1) : XP_STRDUP(leafName);
if (leafName) XP_FREE(leafName);
}
/* This will generate a correct filename and then remove the path */
void DIR_SetServerFileName(DIR_Server* pServer, const char* leafName)
{
char* tempName = WH_TempName(xpAddrBook, leafName);
char* nativeName = WH_FileName(tempName, xpAddrBook);
char* urlName = XP_PlatformFileToURL(nativeName);
#if defined(XP_WIN) || defined(XP_UNIX) || defined(XP_MAC) || defined(XP_OS2)
char* newLeafName = XP_STRRCHR (urlName + XP_STRLEN("file://"), '/');
pServer->fileName = newLeafName ? XP_STRDUP(newLeafName + 1) : XP_STRDUP(urlName + XP_STRLEN("file://"));
#else
pServer->fileName = XP_STRDUP(urlName + XP_STRLEN("file://"));
#endif
if (urlName) XP_FREE(urlName);
if (nativeName) XP_FREE(nativeName);
if (tempName) XP_FREE(tempName);
}
/* This will reconstruct a correct filename including the path */
void DIR_GetServerFileName(char** filename, const char* leafName)
{
#ifdef XP_MAC
char* realLeafName;
char* nativeName;
char* urlName;
if (XP_STRCHR(leafName, ':') != NULL)
realLeafName = XP_STRRCHR(leafName, ':') + 1; // makes sure that leafName is not a fullpath
else
realLeafName = leafName;
nativeName = WH_FileName(realLeafName, xpAddrBookNew);
urlName = XP_PlatformFileToURL(nativeName);
(*filename) = XP_STRDUP(urlName + XP_STRLEN("file://"));
if (urlName) XP_FREE(urlName);
#elif defined(XP_WIN)
/* jefft -- Bug 73349. To allow users share same address book.
* This only works if user sepcified a full path name in his
* prefs.js
*/
char *nativeName = WH_FilePlatformName (leafName);
char *fullnativeName;
if (XP_FileIsFullPath(nativeName)) {
fullnativeName = nativeName;
nativeName = NULL;
}
else {
fullnativeName = WH_FileName(nativeName, xpAddrBookNew);
}
(*filename) = fullnativeName;
#else
char* nativeName = WH_FilePlatformName (leafName);
char* fullnativeName = WH_FileName(nativeName, xpAddrBookNew);
(*filename) = fullnativeName;
#endif
if (nativeName) XP_FREE(nativeName);
}
static int DIR_GetPrefsFromBranch (XP_List **list, const char *pabFile, const char *branch)
{
int32 numDirectories = 0;
int i = 0;
char *prefstring = NULL;
char *tempString = NULL;
int result = 0;
XP_Bool hasPAB = FALSE;
DIR_Server *pNewServer = NULL;
char *newfilename = NULL;
if (*list)
DIR_DeleteServerList(*list);
prefstring = (char *) XP_ALLOC(128);
tempString = (char *) XP_ALLOC(256);
(*list) = XP_ListNew();
/* get the preference for how many directories */
if (prefstring && tempString && (*list) && branch && *branch)
{
char *numberOfDirs = PR_smprintf ("%s.number_of_directories", branch);
if (numberOfDirs)
PREF_GetIntPref(numberOfDirs, &numDirectories);
for (i = 1; i <= numDirectories; i++)
{
pNewServer = (DIR_Server *) XP_ALLOC(sizeof(DIR_Server));
if (pNewServer)
{
XP_Bool prefBool;
XP_BZERO(pNewServer, sizeof(DIR_Server));
XP_SPRINTF(prefstring, "%s.directory%i.", branch, i);
pNewServer->isSecure = DIR_GetBoolPref (prefstring, "isSecure", tempString, FALSE);
pNewServer->saveResults = DIR_GetBoolPref (prefstring, "saveResults", tempString, TRUE);
pNewServer->efficientWildcards = DIR_GetBoolPref (prefstring, "efficientWildcards", tempString, TRUE);
pNewServer->port = DIR_GetIntPref (prefstring, "port", tempString, pNewServer->isSecure ? LDAPS_PORT : LDAP_PORT);
if (pNewServer->port == 0)
pNewServer->port = pNewServer->isSecure ? LDAPS_PORT : LDAP_PORT;
pNewServer->maxHits = DIR_GetIntPref (prefstring, "maxHits", tempString, kDefaultMaxHits);
pNewServer->description = DIR_GetStringPref (prefstring, "description", tempString, "");
pNewServer->serverName = DIR_GetStringPref (prefstring, "serverName", tempString, "");
pNewServer->searchBase = DIR_GetStringPref (prefstring, "searchBase", tempString, "");
if (!XP_STRCASECMP(pNewServer->serverName, "ldap.infospace.com") && !*pNewServer->searchBase)
{
/* 4.0 unfortunately shipped with the wrong searchbase for Infospace, so
* if we find Infospace, and their searchBase hasn't been set, make it right
* It's not legal to do this in all.js unless we rename the LDAP prefs tree (ugh)
*/
pNewServer->searchBase = XP_STRDUP ("c=US");
PREF_SetCharPref (tempString, "c=US");
}
pNewServer->dirType = (DirectoryType)DIR_GetIntPref (prefstring, "dirType", tempString, (int) LDAPDirectory);
if (pNewServer->dirType == PABDirectory)
{
hasPAB = TRUE;
/* make sure there is a true PAB */
if (XP_STRLEN (pNewServer->serverName) == 0)
pNewServer->isOffline = FALSE;
pNewServer->saveResults = TRUE; /* never let someone delete their PAB this way */
}
pNewServer->fileName = DIR_GetStringPref (prefstring, "filename", tempString, "");
if (!pNewServer->fileName || !*(pNewServer->fileName))
{
if (pNewServer->dirType != PABDirectory)
DIR_SetServerFileName (pNewServer, pNewServer->serverName);
else
{
XP_FREEIF(pNewServer->fileName);
pNewServer->fileName = XP_STRDUP (pabFile);
}
}
#if defined(XP_WIN) || defined(XP_UNIX) || defined(XP_MAC) || defined(XP_OS2)
DIR_ConvertServerFileName(pNewServer);
#endif
pNewServer->lastSearchString = DIR_GetStringPref (prefstring, "searchString", tempString, "");
pNewServer->isOffline = DIR_GetBoolPref (prefstring, "isOffline", tempString, kDefaultIsOffline);
/* This is where site-configurable attributes and filters are read from JavaScript */
DIR_GetCustomAttributePrefs (prefstring, pNewServer, tempString);
DIR_GetCustomFilterPrefs (prefstring, pNewServer, tempString);
/* Get authentication prefs */
pNewServer->enableAuth = DIR_GetBoolPref (prefstring, "enableAuth", tempString, kDefaultEnableAuth);
pNewServer->savePassword = DIR_GetBoolPref (prefstring, "savePassword", tempString, kDefaultSavePassword);
if (pNewServer->savePassword)
{
pNewServer->authDn = DIR_GetStringPref (prefstring, "authDn", tempString, "");
pNewServer->password = DIR_GetStringPref (prefstring, "password", tempString, "");
}
prefBool = DIR_GetBoolPref (prefstring, "autoCompleteEnabled", tempString, kDefaultAutoCompleteEnabled);
DIR_ForceFlag (pNewServer, DIR_AUTO_COMPLETE_ENABLED, prefBool);
prefBool = DIR_GetBoolPref (prefstring, "utf8Disabled", tempString, kDefaultUtf8Disabled);
DIR_ForceFlag (pNewServer, DIR_UTF8_DISABLED, prefBool);
pNewServer->customDisplayUrl = DIR_GetStringPref (prefstring, "customDisplayUrl", tempString, "");
XP_ListAddObjectToEnd((*list), pNewServer);
}
}
XP_FREEIF(numberOfDirs);
/* all.js should have filled this stuff in */
XP_ASSERT(hasPAB);
XP_ASSERT(numDirectories != 0);
}
else
result = -1;
XP_FREEIF (prefstring);
XP_FREEIF (tempString);
return result;
}
int DIR_GetServerPreferences (XP_List **list, const char* pabFile)
{
int err = 0;
XP_List *oldList = NULL;
XP_List *newList = NULL;
char *oldChildren = NULL;
int32 listVersion = -1;
XP_Bool userHasOldPrefs = FALSE;
if (PREF_NOERROR == PREF_GetIntPref ("ldapList.version", &listVersion))
userHasOldPrefs = (kCurrentListVersion > listVersion);
else
userHasOldPrefs = TRUE;
/* Look to see if there's an old-style "directories" tree in prefs */
if (PREF_NOERROR == PREF_CreateChildList ("directories", &oldChildren))
{
if (oldChildren)
{
if (userHasOldPrefs)
err = DIR_GetPrefsFromBranch (&oldList, pabFile, "directories");
PREF_DeleteBranch ("directories");
XP_FREEIF(oldChildren);
}
}
/* Look to see if there's an old-style "ldap" tree in prefs */
else if (PREF_NOERROR == PREF_CreateChildList ("ldap", &oldChildren))
{
if (oldChildren)
{
if (userHasOldPrefs)
err = DIR_GetPrefsFromBranch (&oldList, pabFile, "ldap");
PREF_DeleteBranch ("ldap");
XP_FREEIF(oldChildren);
}
}
/* Find the new-style "ldap_1" tree in prefs */
DIR_GetPrefsFromBranch (&newList, pabFile, "ldap_1");
if (oldList && newList)
{
/* Merge the new tree onto the old tree, new on top, unique old at bottom */
DIR_Server *oldServer;
XP_List *walkOldList = oldList;
while (NULL != (oldServer = XP_ListNextObject(walkOldList)))
{
XP_Bool addOldServer = TRUE;
DIR_Server *newServer;
XP_List *walkNewList = newList;
while (NULL != (newServer = XP_ListNextObject(walkNewList)) && addOldServer)
{
if (DIR_AreServersSame (oldServer, newServer))
addOldServer = FALSE; /* don't add servers which are in the new list */
else if (PABDirectory == oldServer->dirType)
addOldServer = FALSE; /* don't need the old PAB; there's already one in ALL.JS */
else if (!XP_STRCMP (oldServer->serverName, "ldap-trace.fedex.com"))
addOldServer = FALSE;
}
if (addOldServer)
{
DIR_Server *copyOfOldServer;
DIR_CopyServer (oldServer, &copyOfOldServer);
XP_ListAddObjectToEnd (newList, copyOfOldServer);
}
}
/* Delete the list of old-style prefs */
DIR_DeleteServerList (oldList);
/* Write the new/merged list so we get it next time we ask */
DIR_SaveServerPreferences (newList);
}
PREF_SetIntPref ("ldapList.version", kCurrentListVersion);
*list = newList;
return err;
}
#define DIR_GOOD_WAY 1
static void DIR_ClearPrefBranch (const char *branch)
{
/* This little function provides a way to delete a prefs object but still
* allow reassignment of that object later.
*/
char *recreateBranch = NULL;
PREF_DeleteBranch (branch);
recreateBranch = PR_smprintf ("pref_inittree(\"%s\")", branch);
if (recreateBranch)
{
PREF_QuietEvaluateJSBuffer (recreateBranch, XP_STRLEN(recreateBranch));
XP_FREE(recreateBranch);
}
}
static void DIR_ClearIntPref (const char *pref)
{
int32 oldDefault;
int prefErr = PREF_GetDefaultIntPref (pref, &oldDefault);
DIR_ClearPrefBranch (pref);
if (prefErr >= 0)
PREF_SetDefaultIntPref (pref, oldDefault);
}
static void DIR_ClearStringPref (const char *pref)
{
char *oldDefault = NULL;
int prefErr = PREF_CopyDefaultCharPref (pref, &oldDefault);
DIR_ClearPrefBranch (pref);
if (prefErr >= 0)
PREF_SetDefaultCharPref (pref, oldDefault);
XP_FREEIF(oldDefault);
}
static void DIR_ClearBoolPref (const char *pref)
{
XP_Bool oldDefault;
int prefErr = PREF_GetDefaultBoolPref (pref, &oldDefault);
DIR_ClearPrefBranch (pref);
if (prefErr >= 0)
PREF_SetDefaultBoolPref (pref, oldDefault);
}
static void DIR_SetStringPref (const char *prefRoot, const char *prefLeaf, char *scratch, const char *value, const char *defaultValue)
{
char *defaultPref = NULL;
int prefErr = PREF_NOERROR;
XP_STRCPY(scratch, prefRoot);
XP_STRCAT (scratch, prefLeaf);
if (PREF_NOERROR == PREF_CopyDefaultCharPref (scratch, &defaultPref))
{
/* If there's a default pref, just set ours in and let libpref worry
* about potential defaults in all.js
*/
prefErr = PREF_SetCharPref (scratch, value);
XP_FREE(defaultPref);
}
else
{
/* If there's no default pref, look for a user pref, and only set our value in
* if the user pref is different than one of them.
*/
char *userPref = NULL;
if (PREF_NOERROR == PREF_CopyCharPref (scratch, &userPref))
{
#if DIR_GOOD_WAY
if (value && XP_STRCASECMP(value, defaultValue))
prefErr = PREF_SetCharPref (scratch, value);
else
DIR_ClearStringPref (scratch);
#else
prefErr = PREF_SetCharPref (scratch, value);
#endif
}
else
{
if (value && XP_STRCASECMP(value, defaultValue))
prefErr = PREF_SetCharPref (scratch, value);
}
}
XP_ASSERT(prefErr >= 0);
}
static void DIR_SetIntPref (const char *prefRoot, const char *prefLeaf, char *scratch, int32 value, int32 defaultValue)
{
int32 defaultPref;
int prefErr = 0;
XP_STRCPY(scratch, prefRoot);
XP_STRCAT (scratch, prefLeaf);
if (PREF_NOERROR == PREF_GetDefaultIntPref (scratch, &defaultPref))
{
/* solve the problem where reordering user prefs must override default prefs */
PREF_SetIntPref (scratch, value);
}
else
{
int32 userPref;
if (PREF_NOERROR == PREF_GetIntPref (scratch, &userPref))
{
#if DIR_GOOD_WAY
if (value != defaultValue)
prefErr = PREF_SetIntPref(scratch, value);
else
DIR_ClearIntPref (scratch);
#else
prefErr = PREF_SetIntPref(scratch, value);
#endif
}
else
{
if (value != defaultValue)
prefErr = PREF_SetIntPref (scratch, value);
}
}
XP_ASSERT(prefErr >= 0);
}
static void DIR_SetBoolPref (const char *prefRoot, const char *prefLeaf, char *scratch, XP_Bool value, XP_Bool defaultValue)
{
XP_Bool defaultPref;
int prefErr = PREF_NOERROR;
XP_STRCPY(scratch, prefRoot);
XP_STRCAT (scratch, prefLeaf);
if (PREF_NOERROR == PREF_GetDefaultBoolPref (scratch, &defaultPref))
{
/* solve the problem where reordering user prefs must override default prefs */
prefErr = PREF_SetBoolPref (scratch, value);
}
else
{
XP_Bool userPref;
if (PREF_NOERROR == PREF_GetBoolPref (scratch, &userPref))
{
#if DIR_GOOD_WAY
if (value != defaultValue)
prefErr = PREF_SetBoolPref(scratch, value);
else
DIR_ClearBoolPref (scratch);
#else
prefErr = PREF_SetBoolPref(scratch, value);
#endif
}
else
{
if (value != defaultValue)
prefErr = PREF_SetBoolPref (scratch, value);
}
}
XP_ASSERT(prefErr >= 0);
}
static int DIR_ConvertAttributeToPrefsString (DIR_Attribute *attrib, char **ppPrefsString)
{
int err = 0;
/* Compute size in bytes req'd for prefs string */
int length = XP_STRLEN(attrib->prettyName);
int i = 0;
while (attrib->attrNames[i])
{
length += XP_STRLEN(attrib->attrNames[i]) + 1; /* +1 for comma separator */
i++;
}
length += 1; /* +1 for colon */
/* Allocate prefs string */
*ppPrefsString = (char*) XP_ALLOC(length + 1); /* +1 for null term */
/* Unravel attrib struct back out into prefs */
if (*ppPrefsString)
{
int j = 0;
XP_STRCPY (*ppPrefsString, attrib->prettyName);
XP_STRCAT (*ppPrefsString, ":");
while (attrib->attrNames[j])
{
XP_STRCAT (*ppPrefsString, attrib->attrNames[j]);
if (j + 1 < i)
XP_STRCAT (*ppPrefsString, ",");
j++;
}
}
else
err = MK_OUT_OF_MEMORY;
return err;
}
static int DIR_SaveOneCustomAttribute (const char *prefRoot, char *scratch, DIR_Server *server, DIR_AttributeId id)
{
int err;
const char *name = DIR_GetDefaultAttribute (id)->name;
err = 0;
if (server->customAttributes)
{
DIR_Attribute *attrib = NULL;
XP_List *walkList = server->customAttributes;
while ((attrib = XP_ListNextObject(walkList)) != NULL)
{
if (attrib->id == id)
{
char *jsString = NULL;
if (0 == DIR_ConvertAttributeToPrefsString(attrib, &jsString))
{
DIR_SetStringPref (prefRoot, name, scratch, jsString, "");
XP_FREE(jsString);
return err;
}
}
}
}
/* This server doesn't have a custom attribute for the requested ID
* so set it to the null string just in case there's an ALL.JS setting
* or had a previous user value
*/
DIR_SetStringPref (prefRoot, name, scratch, "", "");
return err;
}
static int DIR_SaveCustomAttributes (const char *prefRoot, char *scratch, DIR_Server *server)
{
int err;
char *localScratch = (char*) XP_ALLOC(256);
err = 0;
XP_STRCPY (scratch, prefRoot);
XP_STRCAT (scratch, "attributes.");
if (localScratch)
{
DIR_SaveOneCustomAttribute (scratch, localScratch, server, cn);
DIR_SaveOneCustomAttribute (scratch, localScratch, server, givenname);
DIR_SaveOneCustomAttribute (scratch, localScratch, server, sn);
DIR_SaveOneCustomAttribute (scratch, localScratch, server, mail);
DIR_SaveOneCustomAttribute (scratch, localScratch, server, telephonenumber);
DIR_SaveOneCustomAttribute (scratch, localScratch, server, o);
DIR_SaveOneCustomAttribute (scratch, localScratch, server, ou);
DIR_SaveOneCustomAttribute (scratch, localScratch, server, l);
DIR_SaveOneCustomAttribute (scratch, localScratch, server, street);
DIR_SaveOneCustomAttribute (scratch, localScratch, server, custom1);
DIR_SaveOneCustomAttribute (scratch, localScratch, server, custom2);
DIR_SaveOneCustomAttribute (scratch, localScratch, server, custom3);
DIR_SaveOneCustomAttribute (scratch, localScratch, server, custom4);
DIR_SaveOneCustomAttribute (scratch, localScratch, server, custom5);
DIR_SaveOneCustomAttribute (scratch, localScratch, server, auth);
XP_FREE(localScratch);
}
else
err = MK_OUT_OF_MEMORY;
return err;
}
static int DIR_SaveCustomFilters (const char *prefRoot, char *scratch, DIR_Server *server)
{
int err;
char *localScratch = (char*) XP_ALLOC(256);
err = 0;
XP_STRCPY (scratch, prefRoot);
XP_STRCAT (scratch, "filter1.");
if (server->customFilters)
{
/* Save the custom filters into the JS prefs */
DIR_Filter *filter = NULL;
XP_List *walkList = server->customFilters;
if (localScratch)
{
while ((filter = XP_ListNextObject(walkList)) != NULL)
{
DIR_SetBoolPref (scratch, "repeatFilterForWords", localScratch,
(filter->flags & DIR_F_REPEAT_FILTER_FOR_TOKENS) != 0, kDefaultRepeatFilterForTokens);
DIR_SetStringPref (scratch, "string", localScratch, filter->string, kDefaultFilter);
}
XP_FREE(localScratch);
}
else
err = MK_OUT_OF_MEMORY;
}
else
{
/* The DIR_Server object doesn't think it has any custom filters,
* so make sure the prefs settings are empty too
*/
DIR_SetBoolPref (scratch, "repeatFilterForWords", localScratch,
kDefaultRepeatFilterForTokens, kDefaultRepeatFilterForTokens);
DIR_SetStringPref (scratch, "string", localScratch, kDefaultFilter, kDefaultFilter);
}
return err;
}
static int dir_SaveReplicationInfo (const char *prefRoot, char *scratch, DIR_Server *server)
{
int err = 0;
char *localScratch = (char*) XP_ALLOC(256);
if (!localScratch)
return MK_OUT_OF_MEMORY;
XP_STRCPY (scratch, prefRoot);
XP_STRCAT (scratch, "replication.");
if (server->replInfo)
{
char *excludedList = NULL;
int i;
int excludedLength = 0;
for (i = 0; i < server->replInfo->excludedAttributesCount; i++)
excludedLength += XP_STRLEN (server->replInfo->excludedAttributes[i]) + 2; /* +2 for ", " */
if (excludedLength)
{
excludedList = (char*) XP_ALLOC (excludedLength + 1);
if (excludedList)
{
excludedList[0] = '\0';
for (i = 0; i < server->replInfo->excludedAttributesCount; i++)
{
XP_STRCAT (excludedList, server->replInfo->excludedAttributes[i]);
XP_STRCAT (excludedList, ", ");
}
}
else
err = MK_OUT_OF_MEMORY;
}
DIR_SetStringPref (scratch, "excludedAttributes", scratch, excludedList, kDefaultReplicaExcludedAttributes);
DIR_SetBoolPref (scratch, "enabled", localScratch, server->replInfo->enabled, kDefaultReplicaEnabled);
DIR_SetStringPref (scratch, "description", localScratch, server->replInfo->description, kDefaultReplicaDescription);
DIR_SetStringPref (scratch, "filter", localScratch, server->replInfo->filter, kDefaultReplicaFilter);
DIR_SetIntPref (scratch, "lastChangeNumber", localScratch, server->replInfo->lastChangeNumber, kDefaultReplicaChangeNumber);
DIR_SetIntPref (scratch, "generation", localScratch, server->replInfo->generation, kDefaultReplicaChangeNumberGeneration);
}
return err;
}
int DIR_SaveServerPreferences (XP_List *wholeList)
{
int i;
DIR_Server *s;
char * prefstring = NULL;
char * tempString = NULL;
if (wholeList)
{
prefstring = (char *) XP_ALLOC(128);
tempString = (char *) XP_ALLOC(256);
if (prefstring && tempString)
{
PREF_SetIntPref("ldap_1.number_of_directories", XP_ListCount (wholeList));
for (i = 1; i <= XP_ListCount(wholeList); i++)
{
s = (DIR_Server*) XP_ListGetObjectNum (wholeList, i);
if (s)
{
XP_SPRINTF(prefstring, "ldap_1.directory%i.", i);
DIR_SetStringPref (prefstring, "description", tempString, s->description, "");
DIR_SetStringPref (prefstring, "serverName", tempString, s->serverName, "");
DIR_SetStringPref (prefstring, "searchBase", tempString, s->searchBase, "");
DIR_SetStringPref (prefstring, "filename", tempString, s->fileName, "");
if (s->port == 0)
s->port = s->isSecure ? LDAPS_PORT : LDAP_PORT;
DIR_SetIntPref (prefstring, "port", tempString, s->port, s->isSecure ? LDAPS_PORT : LDAP_PORT);
DIR_SetIntPref (prefstring, "maxHits", tempString, s->maxHits, kDefaultMaxHits);
DIR_SetBoolPref (prefstring, "isSecure", tempString, s->isSecure, FALSE);
DIR_SetBoolPref (prefstring, "saveResults", tempString, s->saveResults, TRUE);
DIR_SetBoolPref (prefstring, "efficientWildcards", tempString, s->efficientWildcards, TRUE);
DIR_SetStringPref (prefstring, "searchString", tempString, s->lastSearchString, "");
DIR_SetIntPref (prefstring, "dirType", tempString, s->dirType, (int) LDAPDirectory);
DIR_SetBoolPref (prefstring, "isOffline", tempString, s->isOffline, kDefaultIsOffline);
DIR_SetBoolPref (prefstring, "autoCompleteEnabled", tempString, DIR_TestFlag(s, DIR_AUTO_COMPLETE_ENABLED), kDefaultAutoCompleteEnabled);
DIR_SetBoolPref (prefstring, "utf8Disabled", tempString, DIR_TestFlag(s, DIR_UTF8_DISABLED), kDefaultUtf8Disabled);
DIR_SetBoolPref (prefstring, "enableAuth", tempString, s->enableAuth, kDefaultEnableAuth);
DIR_SetBoolPref (prefstring, "savePassword", tempString, s->savePassword, kDefaultSavePassword);
if (s->savePassword)
{
DIR_SetStringPref (prefstring, "authDn", tempString, s->authDn, "");
DIR_SetStringPref (prefstring, "password", tempString, s->password, "");
}
DIR_SaveCustomAttributes (prefstring, tempString, s);
DIR_SaveCustomFilters (prefstring, tempString, s);
dir_SaveReplicationInfo (prefstring, tempString, s);
DIR_SetStringPref (prefstring, "customDisplayUrl", tempString, s->customDisplayUrl, "");
}
}
XP_SPRINTF(tempString, "%i", tempString);
PREF_SetCharPref("ldap_1.end_of_directories", tempString);
}
XP_FREEIF (prefstring);
XP_FREEIF (tempString);
}
return 0;
}
/*****************************************************************************
* Functions for getting site-configurable preferences, from JavaScript if
* the site admin has provided them, else out of thin air.
*/
static DIR_DefaultAttribute *DIR_GetDefaultAttribute (DIR_AttributeId id)
{
int i = 0;
static DIR_DefaultAttribute defaults[15];
defaults[0].id = cn;
defaults[0].resourceId = MK_LDAP_COMMON_NAME;
defaults[0].name = "cn";
defaults[1].id = givenname;
defaults[1].resourceId = MK_LDAP_GIVEN_NAME;
defaults[1].name = "givenName";
defaults[2].id = sn;
defaults[2].resourceId = MK_LDAP_SURNAME;
defaults[2].name = "sn";
defaults[3].id = mail;
defaults[3].resourceId = MK_LDAP_EMAIL_ADDRESS;
defaults[3].name = "mail";
defaults[4].id = telephonenumber;
defaults[4].resourceId = MK_LDAP_PHONE_NUMBER;
defaults[4].name = "telephoneNumber";
defaults[5].id = o;
defaults[5].resourceId = MK_LDAP_ORGANIZATION;
defaults[5].name = "o";
defaults[6].id = ou;
defaults[6].resourceId = MK_LDAP_ORG_UNIT;
defaults[6].name = "ou";
defaults[7].id = l;
defaults[7].resourceId = MK_LDAP_LOCALITY;
defaults[7].name = "l";
defaults[8].id = street;
defaults[8].resourceId = MK_LDAP_STREET;
defaults[8].name = "street";
defaults[9].id = custom1;
defaults[9].resourceId = MK_LDAP_CUSTOM1;
defaults[9].name = "custom1";
defaults[10].id = custom2;
defaults[10].resourceId = MK_LDAP_CUSTOM2;
defaults[10].name = "custom2";
defaults[11].id = custom3;
defaults[11].resourceId = MK_LDAP_CUSTOM3;
defaults[11].name = "custom3";
defaults[12].id = custom4;
defaults[12].resourceId = MK_LDAP_CUSTOM4;
defaults[12].name = "custom4";
defaults[13].id = custom5;
defaults[13].resourceId = MK_LDAP_CUSTOM5;
defaults[13].name = "custom5";
defaults[14].id = auth;
defaults[14].resourceId = MK_LDAP_EMAIL_ADDRESS;
defaults[14].name = "mail";
defaults[15].id = cn;
defaults[15].resourceId = 0;
defaults[15].name = NULL;
while (defaults[i].name)
{
if (defaults[i].id == id)
return &defaults[i];
i++;
}
return NULL;
}
const char *DIR_GetAttributeName (DIR_Server *server, DIR_AttributeId id)
{
char *result = NULL;
/* First look in the custom attributes in case the attribute is overridden */
XP_List *list = server->customAttributes;
DIR_Attribute *walkList = NULL;
while ((walkList = XP_ListNextObject(list)) != NULL)
{
if (walkList->id == id)
result = walkList->prettyName;
}
/* If we didn't find it, look in our own static list of attributes */
if (!result)
{
DIR_DefaultAttribute *def;
if ((def = DIR_GetDefaultAttribute(id)) != NULL)
result = XP_GetString(def->resourceId);
}
return result;
}
const char **DIR_GetAttributeStrings (DIR_Server *server, DIR_AttributeId id)
{
const char **result = NULL;
/* First look in the custom attributes in case the attribute is overridden */
XP_List *list = server->customAttributes;
DIR_Attribute *walkList = NULL;
while ((walkList = XP_ListNextObject(list)) != NULL)
{
if (walkList->id == id)
result = (const char**)walkList->attrNames;
}
/* If we didn't find it, look in our own static list of attributes */
if (!result)
{
static const char *array[2];
array[0] = DIR_GetDefaultAttribute(id)->name;
array[1] = NULL;
result = (const char**)array;
}
return result;
}
const char *DIR_GetFirstAttributeString (DIR_Server *server, DIR_AttributeId id)
{
const char **array = DIR_GetAttributeStrings (server, id);
return array[0];
}
const char *DIR_GetFilterString (DIR_Server *server)
{
DIR_Filter *filter = XP_ListTopObject (server->customFilters);
if (filter)
return filter->string;
return NULL;
}
static DIR_Filter *DIR_LookupFilter (DIR_Server *server, const char *filter)
{
XP_List *list = server->customFilters;
DIR_Filter *walkFilter = NULL;
while ((walkFilter = XP_ListNextObject(list)) != NULL)
if (!XP_STRCASECMP(filter, walkFilter->string))
return walkFilter;
return NULL;
}
XP_Bool DIR_RepeatFilterForTokens (DIR_Server *server, const char *filter)
{
const DIR_Filter *filterStruct = DIR_LookupFilter (server, filter);
if (filterStruct)
return (filterStruct->flags & DIR_F_REPEAT_FILTER_FOR_TOKENS) != 0;
return kDefaultRepeatFilterForTokens;
}
XP_Bool DIR_SubstStarsForSpaces (DIR_Server *server, const char *filter)
{
const DIR_Filter *filterStruct = DIR_LookupFilter (server, filter);
if (filterStruct)
return (filterStruct->flags & DIR_F_SUBST_STARS_FOR_SPACES) != 0;
return kDefaultSubstStarsForSpaces;
}
const char *DIR_GetTokenSeparators (DIR_Server *server)
{
return server->tokenSeps ? server->tokenSeps : kDefaultTokenSeps;
}
XP_Bool DIR_UseCustomAttribute (DIR_Server *server, DIR_AttributeId id)
{
XP_List *list = server->customAttributes;
DIR_Attribute *walkList = NULL;
while ((walkList = XP_ListNextObject(list)) != NULL)
{
if (walkList->id == id)
return TRUE;
}
return FALSE;
}
XP_Bool DIR_IsDnAttribute (DIR_Server *s, const char *attrib)
{
if (s && s->dnAttributes)
{
/* Look in the server object to see if there are prefs to tell
* us which attributes contain DNs
*/
int i;
for (i = 0; i < s->dnAttributesCount; i++)
{
if (!XP_STRCASECMP(attrib, s->dnAttributes[i]))
return TRUE;
}
}
else
{
/* We have some default guesses about what attributes
* are likely to contain DNs
*/
switch (XP_TO_LOWER(attrib[0]))
{
case 'm':
if (!XP_STRCASECMP(attrib, "manager") ||
!XP_STRCASECMP(attrib, "member"))
return TRUE;
break;
case o:
if (!XP_STRCASECMP(attrib, "owner"))
return TRUE;
break;
case 'u':
if (!XP_STRCASECMP(attrib, "uniquemember"))
return TRUE;
break;
}
}
return FALSE;
}
XP_Bool DIR_IsAttributeExcludedFromHtml (DIR_Server *s, const char *attrib)
{
if (s && s->suppressedAttributes)
{
/* Look in the server object to see if there are prefs to tell
* us which attributes shouldn't be shown in HTML
*/
int i;
for (i = 0; i < s->suppressedAttributesCount; i++)
{
if (!XP_STRCASECMP(attrib, s->suppressedAttributes[i]))
return TRUE;
}
}
/* else don't exclude it. By default we show everything */
return FALSE;
}
static void dir_PushStringToPrefs (DIR_Server *s, char **curVal, const char *newVal, const char *name)
{
XP_List *servers = NULL;
XP_List *walkList = NULL;
DIR_Server *walkServer = NULL;
XP_Bool found = FALSE;
int idx = 0;
/* Don't do anything if we already have a value and it's the same as the new one */
if (curVal && *curVal)
{
if (!XP_STRCMP(*curVal, newVal))
return;
}
/* Find the server in the list so we can get its index.
* Can't use XP_GetNumFromObject because this DIR_Server isn't guaranteed
* to be in the FE's list -- it may be from a copy of the FE's list
*/
walkList = FE_GetDirServers ();
while (!found)
{
walkServer = (DIR_Server*) XP_ListNextObject (walkList);
if (!walkServer)
break;
found = DIR_AreServersSame (walkServer, s);
idx++;
}
if (found)
{
/* Build the name of the prefs string */
char buf[512];
char *prefRoot = PR_smprintf ("ldap_1.directory%d.", idx);
/* Set into the prefs */
if (prefRoot)
{
*curVal = XP_STRDUP(newVal);
DIR_SetStringPref (prefRoot, name, buf, *curVal, "");
XP_FREE(prefRoot);
}
}
}
void DIR_SetAuthDN (DIR_Server *s, const char *dn)
{
dir_PushStringToPrefs (s, &(s->authDn), dn, "authDn");
}
void DIR_SetPassword (DIR_Server *s, const char *password)
{
dir_PushStringToPrefs (s, &(s->password), password, "password");
}
XP_Bool DIR_IsEscapedAttribute (DIR_Server *s, const char *attrib)
{
/* We're not exposing this setting in JS prefs right now, but in case we
* might want to in the future, leave the DIR_Server* in the prototype.
*/
switch (XP_TO_LOWER(attrib[0]))
{
case 'p':
if (!XP_STRCASECMP(attrib, "postaladdress"))
return TRUE;
break;
case 'f':
if (!XP_STRCASECMP(attrib, "facsimiletelephonenumber"))
return TRUE;
break;
case 'o':
if (!XP_STRCASECMP(attrib, "othermail"))
return TRUE;
break;
}
return FALSE;
}
char *DIR_Unescape (const char *src, XP_Bool makeHtml)
{
/* Borrowed from libnet\mkparse.c */
#define UNHEX(C) \
((C >= '0' && C <= '9') ? C - '0' : \
((C >= 'A' && C <= 'F') ? C - 'A' + 10 : \
((C >= 'a' && C <= 'f') ? C - 'a' + 10 : 0)))
char *dest = NULL;
int destLength = 0;
int dollarCount = 0;
int convertedLengthOfDollar = makeHtml ? 4 : 1;
const char *tmpSrc = src;
while (*tmpSrc)
if (*tmpSrc++ == '$')
dollarCount++;
destLength = XP_STRLEN(src) + (dollarCount * convertedLengthOfDollar);
dest = (char*) XP_ALLOC (destLength + 1);
if (dest)
{
char *tmpDst = dest;
*dest = '\0';
tmpSrc = src;
while (*tmpSrc)
{
switch (*tmpSrc)
{
case '$':
/* A dollar sign is a linebreak. This is easy for HTML, but if we're converting
* for the Address Book or something without multiple lines, just put in a space
*/
if (makeHtml)
{
*tmpDst++ = '<';
*tmpDst++ = 'B';
*tmpDst++ = 'R';
*tmpDst++ = '>';
}
else
*tmpDst++ = ' ';
break;
case '\\': {
/* A backslash indicates that two hex digits follow, which we're supposed to
* convert. The spec sez that '$', '#' and '\'' (single quote) must be encoded
* this way.
*/
XP_Bool didEscape = FALSE;
char c1 = *(tmpSrc + 1);
if (c1 && (XP_IS_DIGIT(c1) || XP_IS_ALPHA(c1)))
{
char c2 = *(tmpSrc + 2);
if (c2 && (XP_IS_DIGIT(c2) || XP_IS_ALPHA(c2)))
{
*tmpDst++ = (UNHEX(c1) << 4) | UNHEX(c2);
tmpSrc +=2;
didEscape = TRUE;
}
}
if (!didEscape)
*tmpDst++ = *tmpSrc;
}
break;
default:
/* Just a plain old char -- copy it over */
*tmpDst++ = *tmpSrc;
}
tmpSrc++;
}
*tmpDst = '\0';
}
return dest;
}
/*****************************************************************************
* Functions for building a secure connection to LDAP servers
*
* Use of PR_CALLBACK is required for Win16 because the socket API functions
* ultimately call into MOZOCK, which has DS-resident global variables. Ick.
*/
#ifdef MOZ_LDAP
HG29989
int DIR_ValidateRootDSE (DIR_Server *server, int32 gen, int32 first, int32 last)
{
/* Here we validate the replication info that the server has against the
* state of the local replica as stored in JS prefs.
*/
XP_ASSERT(server && server->replInfo);
if (!server || !server->replInfo)
return -1;
/* The generation of the server's DB is different than when we last
* saw it, which means that the first and last change number we know
* are totally meaningless.
*/
if (gen != server->replInfo->generation)
return MK_LDAP_REPL_CANT_SYNC_REPLICA;
/* Some changes have come and gone on the server since we last
* replicated. Since we have no way to know what those changes were,
* we have no way to get sync'd up with the current server state
*/
if (first > server->replInfo->lastChangeNumber)
return MK_LDAP_REPL_CANT_SYNC_REPLICA;
/* We appear to have already replicated changes that the server
* hasn't made yet. Not likely
*/
if (last < server->replInfo->lastChangeNumber)
return MK_LDAP_REPL_CANT_SYNC_REPLICA;
return 0;
}
#define DIR_AUTO_COMPLETE_ENABLED 0x00000001
#define DIR_ENABLE_AUTH 0x00000002
#define DIR_SAVE_PASSWORD 0x00000004
#define DIR_UTF8_DISABLED 0x00000008
#define DIR_IS_SECURE 0x00000010
#define DIR_SAVE_RESULTS 0x00000020
#define DIR_EFFICIENT_WILDCARDS 0x00000040
void DIR_SetAutoCompleteEnabled (XP_List *list, DIR_Server *server, XP_Bool enabled)
{
XP_ASSERT(server); /*list can be null*/
if (server)
{
DIR_Server *tmp;
if (enabled)
{
while (NULL != (tmp = XP_ListNextObject(list)))
tmp->flags &= ~DIR_AUTO_COMPLETE_ENABLED;
server->flags |= DIR_AUTO_COMPLETE_ENABLED;
}
else
server->flags &= ~DIR_AUTO_COMPLETE_ENABLED;
}
}
XP_Bool DIR_TestFlag (DIR_Server *server, uint32 flag)
{
if (server)
return 0 != (server->flags & flag);
return FALSE;
}
void DIR_SetFlag (DIR_Server *server, uint32 flag)
{
XP_ASSERT(server);
if (server)
server->flags |= flag;
}
void DIR_ClearFlag (DIR_Server *server, uint32 flag)
{
XP_ASSERT(server);
if (server)
server->flags &= ~flag;
}
void DIR_ForceFlag (DIR_Server *server, uint32 flag, XP_Bool setIt)
{
XP_ASSERT(server);
if (server)
{
if (setIt)
server->flags |= flag;
else
server->flags &= ~flag;
}
}
/* Centralize this charset conversion so everyone can do the UTF8 conversion
* in the same way. Also, if someone ever makes us do T.61 or some other silly
* thing, we can use these bottlenecks
*/
char *DIR_ConvertToServerCharSet (DIR_Server *server, char *src, int16 srcCsid)
{
if (server && (server->flags & DIR_UTF8_DISABLED))
return XP_STRDUP (src);
else
return (char*) INTL_ConvertLineWithoutAutoDetect (srcCsid, CS_UTF8, (unsigned char*) src, XP_STRLEN(src));
}
char *DIR_ConvertFromServerCharSet (DIR_Server *server, char *src, int16 destCsid)
{
if (server && (server->flags & DIR_UTF8_DISABLED))
return XP_STRDUP (src);
else
return (char*) INTL_ConvertLineWithoutAutoDetect (CS_UTF8, destCsid, (unsigned char*) src, XP_STRLEN(src));
}
char *DIR_BuildUrl (DIR_Server *server, const char *dn, XP_Bool forAddToAB)
{
char *url = NULL;
char *escapedDn = NET_Escape (dn, URL_XALPHAS);
if (escapedDn)
{
if (!forAddToAB && server->customDisplayUrl && server->customDisplayUrl[0])
{
/* Allow users to customize the URL we run when we open an LDAP entry. This
* is intended to appease the people who want extensive customization of the
* HTML we generate for LDAP. We're sidestepping the issue by allowing them
* to easily plug in DSGW, the LDAP-to-HTTP gateway, which already has
* very extensive template support.
*/
url = PR_smprintf (server->customDisplayUrl, escapedDn);
}
else
{
/* The default case, where we run an LDAP URL in a browser window
*/
char *urlTemplate = "%s//%s/%s";
char *urlPortTemplate = "%s//%s:%d/%s";
char *urlScheme = NULL;
int port = server->port;
int standardPort = server->isSecure ? LDAPS_PORT : LDAP_PORT;
if (server->isSecure)
urlScheme = forAddToAB ? "addbook-ldaps:" : "ldaps:";
else
urlScheme = forAddToAB ? "addbook-ldap:" : "ldap:";
if (port == standardPort)
url = PR_smprintf (urlTemplate, urlScheme, server->serverName, escapedDn);
else
url = PR_smprintf (urlPortTemplate, urlScheme, server->serverName, port, escapedDn);
}
XP_FREE (escapedDn);
}
return url;
}
#endif /* MOZ_LDAP */
#endif /* #if !defined(MOZADDRSTANDALONE) */