home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / libmisc / dirprefs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  68.5 KB  |  2,506 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. /* dirprefs.c -- directory server preferences */
  20. #include "rosetta.h"
  21. #include "xp.h"
  22.  
  23. #include "xp_mcom.h"
  24. #include "xpgetstr.h"
  25. #include "dirprefs.h"
  26. #include "prefapi.h"
  27. #include "libi18n.h"
  28. #ifdef MOZ_LDAP
  29.     #include "ldap.h"
  30. HG82168
  31. #else
  32.     #define LDAP_PORT 389
  33.     #define LDAPS_PORT 636
  34. #endif /* MOZ_LDAP */
  35.  
  36. #if !defined(MOZADDRSTANDALONE)
  37.  
  38. extern int MK_OUT_OF_MEMORY;
  39. extern int MK_ADDR_PAB;
  40.  
  41. extern int MK_LDAP_COMMON_NAME;
  42. extern int MK_LDAP_GIVEN_NAME;
  43. extern int MK_LDAP_SURNAME;
  44. extern int MK_LDAP_EMAIL_ADDRESS; 
  45. extern int MK_LDAP_PHONE_NUMBER;
  46. extern int MK_LDAP_ORGANIZATION; 
  47. extern int MK_LDAP_ORG_UNIT; 
  48. extern int MK_LDAP_LOCALITY;
  49. extern int MK_LDAP_STREET;
  50. extern int MK_LDAP_CUSTOM1; 
  51. extern int MK_LDAP_CUSTOM2;
  52. extern int MK_LDAP_CUSTOM3; 
  53. extern int MK_LDAP_CUSTOM4;
  54. extern int MK_LDAP_CUSTOM5;
  55. extern int MK_LDAP_REPL_CANT_SYNC_REPLICA;
  56.  
  57. #else
  58.  
  59. #define MK_OUT_OF_MEMORY -1;
  60.  
  61. #endif /* #if !defined(MOZADDRSTANDALONE) */
  62.  
  63.  
  64. /*****************************************************************************
  65.  * Private structs and stuff
  66.  */
  67.  
  68. /* DIR_Server.flags */
  69. #define DIR_AUTO_COMPLETE_ENABLED 0x00000001
  70. #define DIR_ENABLE_AUTH           0x00000002
  71. #define DIR_SAVE_PASSWORD         0x00000004
  72. #define DIR_DEFEAT_UTF8           0x00000008
  73. #define DIR_IS_SECURE             0x00000010
  74. #define DIR_SAVE_RESULTS          0x00000020
  75. #define DIR_EFFICIENT_WILDCARDS   0x00000040
  76.  
  77. /* DIR_Server.customAttributes is a list of DIR_Attribute structures */
  78. typedef struct DIR_Attribute
  79. {
  80.     DIR_AttributeId id;
  81.     char *prettyName;
  82.     char **attrNames;
  83. } DIR_Attribute;
  84.  
  85. struct _DIR_ReplicationInfo
  86. {
  87.     XP_Bool enabled;                    /* duh */
  88.     char *description;                    /* human readable description of replica */
  89.     char *filter;                        /* LDAP filter string which constrains the repl search */
  90.     int32 lastChangeNumber;                /* Last change we saw -- start replicating here */
  91.     int32 generation;    /* LDAP server's scoping of the lastChangeNumber */
  92.                                         /* this changes when the server's DB gets reloaded from LDIF */
  93.     char **excludedAttributes;            /* list of attributes we shouldn't replicate */
  94.     int excludedAttributesCount;        /* duh */
  95.  
  96. };
  97.  
  98. /* Our internal view of a default attribute is a resourceId for the pretty
  99.  * name and the real attribute name. These are catenated to create a string
  100.  * of the form "Pretty Name:attrname"
  101.  */
  102. typedef struct DIR_DefaultAttribute
  103. {
  104.     DIR_AttributeId id;
  105.     int resourceId;
  106.     char *name;
  107. } DIR_DefaultAttribute;
  108.  
  109. /* DIR_Filter.flags */
  110. #define DIR_F_SUBST_STARS_FOR_SPACES   0x00000001
  111. #define DIR_F_REPEAT_FILTER_FOR_TOKENS 0x00000002
  112.  
  113. /* DIR_Server.filters is a list of DIR_Filter structures */
  114. typedef struct DIR_Filter
  115. {
  116.     char *string;
  117.     uint32 flags;
  118. } DIR_Filter;
  119.  
  120. /* Default settings for site-configurable prefs */
  121. #define kDefaultTokenSeps " ,."
  122. #define kDefaultSubstStarsForSpaces TRUE
  123. #define kDefaultRepeatFilterForTokens TRUE
  124. #define kDefaultEfficientWildcards TRUE
  125. #define kDefaultFilter "(cn=*%s*)"
  126. #define kDefaultEfficientFilter "(|(givenname=%s)(sn=%s))"
  127. #define kDefaultStopOnHit TRUE
  128. #define kDefaultMaxHits 100
  129. #define kDefaultIsOffline TRUE
  130. #define kDefaultEnableAuth FALSE
  131. #define kDefaultSavePassword FALSE
  132. #define kDefaultAutoCompleteEnabled FALSE
  133.  
  134. #define kDefaultReplicaExcludedAttributes ""
  135. #define kDefaultReplicaEnabled FALSE
  136. #define kDefaultReplicaFilter "(objectclass=*)"
  137. #define kDefaultReplicaChangeNumber 0
  138. #define kDefaultReplicaChangeNumberGeneration 0
  139. #define kDefaultReplicaDescription ""
  140. #define kDefaultUtf8Disabled FALSE
  141.  
  142. #define kLdapServersPrefName "network.hosts.ldap_servers"
  143.  
  144. const char *DIR_GetAttributeName (DIR_Server *server, DIR_AttributeId id);
  145. void DIR_SetServerFileName(DIR_Server* pServer, const char* leafName);
  146. static DIR_DefaultAttribute *DIR_GetDefaultAttribute (DIR_AttributeId id);
  147.  
  148.  
  149. /*****************************************************************************
  150.  * Functions for creating DIR_Servers
  151.  */
  152.  
  153. int DIR_InitServer (DIR_Server *server)
  154. {
  155.     XP_ASSERT(server);
  156.     if (server)
  157.     {
  158.         XP_BZERO(server, sizeof(DIR_Server));
  159.         server->saveResults = TRUE;
  160.         server->efficientWildcards = kDefaultEfficientWildcards;
  161.         server->port = LDAP_PORT;
  162.         server->maxHits = kDefaultMaxHits;
  163.         server->isOffline = kDefaultIsOffline;
  164.     }
  165.     return 0;
  166. }
  167.  
  168.  
  169. /*****************************************************************************
  170.  * Functions for cloning DIR_Servers
  171.  */
  172.  
  173. static DIR_Attribute *DIR_CopyAttribute (DIR_Attribute *inAttribute)
  174. {
  175.     DIR_Attribute *outAttribute = (DIR_Attribute*) XP_ALLOC(sizeof(DIR_Attribute));
  176.     if (outAttribute)
  177.     {
  178.         int count = 0;
  179.         outAttribute->id = inAttribute->id;
  180.         outAttribute->prettyName = XP_STRDUP(inAttribute->prettyName);
  181.         while (inAttribute->attrNames[count])
  182.             count++;
  183.         outAttribute->attrNames = (char**) XP_ALLOC((count + 1) * sizeof(char*));
  184.         if (outAttribute->attrNames)
  185.         {
  186.             int i;
  187.             for (i = 0; i < count; i++)
  188.                 outAttribute->attrNames[i] = XP_STRDUP(inAttribute->attrNames[i]);
  189.             outAttribute->attrNames[i] = NULL;
  190.         }
  191.     }
  192.     return outAttribute;
  193. }
  194.  
  195.  
  196. static DIR_Filter *DIR_CopyFilter (DIR_Filter *inFilter)
  197. {
  198.     DIR_Filter *outFilter = (DIR_Filter*) XP_ALLOC(sizeof(DIR_Filter));
  199.     if (outFilter)
  200.     {
  201.         outFilter->flags = inFilter->flags;
  202.         outFilter->string = XP_STRDUP(inFilter->string);
  203.     }
  204.     return outFilter;
  205. }
  206.  
  207.  
  208. static int dir_CopyTokenList (char **inList, int inCount, char ***outList, int *outCount)
  209. {
  210.     int status = 0;
  211.     if (0 != inCount && NULL != inList)
  212.     {
  213.         *outList = (char**) XP_ALLOC(inCount * sizeof(char*));
  214.         if (*outList)
  215.         {
  216.             int i;
  217.             for (i = 0; i < inCount; i++)
  218.                 (*outList)[i] = XP_STRDUP (inList[i]);
  219.             *outCount = inCount;
  220.         }
  221.         else
  222.             status = MK_OUT_OF_MEMORY;
  223.     }
  224.     return status;
  225. }
  226.  
  227.  
  228. static DIR_ReplicationInfo *dir_CopyReplicationInfo (DIR_ReplicationInfo *inInfo)
  229. {
  230.     DIR_ReplicationInfo *outInfo = (DIR_ReplicationInfo*) XP_CALLOC (sizeof(DIR_ReplicationInfo), 1);
  231.     if (outInfo)
  232.     {
  233.         outInfo->lastChangeNumber = inInfo->lastChangeNumber;
  234.         outInfo->generation = inInfo->generation;
  235.         outInfo->enabled = inInfo->enabled;
  236.         if (inInfo->description)
  237.             outInfo->description = XP_STRDUP (inInfo->description);
  238.         if (inInfo->filter)
  239.             outInfo->filter = XP_STRDUP (inInfo->filter);
  240.         dir_CopyTokenList (inInfo->excludedAttributes, inInfo->excludedAttributesCount,
  241.             &outInfo->excludedAttributes, &outInfo->excludedAttributesCount);
  242.     }
  243.     return outInfo;
  244. }
  245.  
  246.  
  247. int DIR_CopyServer (DIR_Server *in, DIR_Server **out)
  248. {
  249.     int err = 0;
  250.  
  251.     if (in) {
  252.         *out = XP_ALLOC(sizeof(DIR_Server));
  253.         if (*out)
  254.         {
  255.             XP_BZERO (*out, sizeof(DIR_Server));
  256.  
  257.             if (in->description)
  258.             {
  259.                 (*out)->description = XP_STRDUP(in->description);
  260.                 if (!(*out)->description)
  261.                     err = MK_OUT_OF_MEMORY;
  262.             }
  263.  
  264.             if (in->serverName)
  265.             {
  266.                 (*out)->serverName = XP_STRDUP(in->serverName);
  267.                 if (!(*out)->serverName)
  268.                     err = MK_OUT_OF_MEMORY;
  269.             }
  270.  
  271.             if (in->searchBase)
  272.             {
  273.                 (*out)->searchBase = XP_STRDUP(in->searchBase);
  274.                 if (!(*out)->searchBase)
  275.                     err = MK_OUT_OF_MEMORY;
  276.             }
  277.  
  278.             if (in->fileName)
  279.             {
  280.                 (*out)->fileName = XP_STRDUP(in->fileName);
  281.                 if (!(*out)->fileName)
  282.                     err = MK_OUT_OF_MEMORY;
  283.              }
  284.  
  285.             if (in->prefId)
  286.             {
  287.                 (*out)->prefId = XP_STRDUP(in->prefId);
  288.                 if (!(*out)->prefId)
  289.                     err = MK_OUT_OF_MEMORY;
  290.             }
  291.  
  292.             (*out)->port = in->port;
  293.             (*out)->maxHits = in->maxHits;
  294.             (*out)->isSecure = in->isSecure;
  295.             (*out)->saveResults = in->saveResults;
  296.             (*out)->isOffline = in->isOffline;
  297.             (*out)->efficientWildcards = in->efficientWildcards;
  298.             (*out)->dirType = in->dirType;
  299.  
  300.             (*out)->flags = in->flags;
  301.             
  302.             (*out)->enableAuth = in->enableAuth;
  303.             (*out)->savePassword = in->savePassword;
  304.             if (in->authDn)
  305.             {
  306.                 (*out)->authDn = XP_STRDUP (in->authDn);
  307.                 if (!(*out)->authDn)
  308.                     err = MK_OUT_OF_MEMORY;
  309.             }
  310.             if (in->password)
  311.             {
  312.                 (*out)->password = XP_STRDUP (in->password);
  313.                 if (!(*out)->password)
  314.                     err = MK_OUT_OF_MEMORY;
  315.             }
  316.  
  317.             if (in->customAttributes)
  318.             {
  319.                 (*out)->customAttributes = XP_ListNew();
  320.                 if ((*out)->customAttributes)
  321.                 {
  322.                     XP_List *list = in->customAttributes;
  323.                     DIR_Attribute *attribute = NULL;
  324.  
  325.                     while ((attribute = XP_ListNextObject (list)) != NULL)
  326.                     {
  327.                         DIR_Attribute *outAttr = DIR_CopyAttribute (attribute);
  328.                         if (outAttr)
  329.                             XP_ListAddObject ((*out)->customAttributes, outAttr);
  330.                         else
  331.                             err = MK_OUT_OF_MEMORY;
  332.                      }
  333.                 }
  334.                 else
  335.                     err = MK_OUT_OF_MEMORY;
  336.             }
  337.  
  338.             if (in->customFilters)
  339.             {
  340.                 (*out)->customFilters = XP_ListNew();
  341.                 if ((*out)->customFilters)
  342.                 {
  343.                     XP_List *list = in->customFilters;
  344.                     DIR_Filter *filter = NULL;
  345.  
  346.                     while ((filter = XP_ListNextObject (list)) != NULL)
  347.                     {
  348.                         DIR_Filter *outFilter = DIR_CopyFilter (filter);
  349.                         if (outFilter)
  350.                             XP_ListAddObject ((*out)->customFilters, outFilter);
  351.                         else
  352.                             err = MK_OUT_OF_MEMORY;
  353.                     }
  354.                 }
  355.                 else
  356.                     err = MK_OUT_OF_MEMORY;
  357.             }
  358.  
  359.             if (in->replInfo)
  360.                 (*out)->replInfo = dir_CopyReplicationInfo (in->replInfo);
  361.  
  362.             if (in->basicSearchAttributesCount > 0)
  363.             {
  364.                 int bsaLength = in->basicSearchAttributesCount * sizeof(DIR_AttributeId);
  365.                 (*out)->basicSearchAttributes = (DIR_AttributeId*) XP_ALLOC(bsaLength);
  366.                 if ((*out)->basicSearchAttributes)
  367.                 {
  368.                     XP_MEMCPY ((*out)->basicSearchAttributes, in->basicSearchAttributes, bsaLength);
  369.                     (*out)->basicSearchAttributesCount = in->basicSearchAttributesCount;
  370.                 }
  371.             }
  372.  
  373.             dir_CopyTokenList (in->dnAttributes, in->dnAttributesCount,
  374.                 &(*out)->dnAttributes, &(*out)->dnAttributesCount);
  375.  
  376.             dir_CopyTokenList (in->suppressedAttributes, in->suppressedAttributesCount,
  377.                 &(*out)->suppressedAttributes, &(*out)->suppressedAttributesCount);
  378.  
  379.             if (in->customDisplayUrl)
  380.                 (*out)->customDisplayUrl = XP_STRDUP (in->customDisplayUrl);
  381.         }
  382.         else {
  383.             err = MK_OUT_OF_MEMORY;
  384.             (*out) = NULL;
  385.         }
  386.     }
  387.     else {
  388.         XP_ASSERT (0);
  389.         err = -1;
  390.         (*out) = NULL;
  391.     }
  392.  
  393.     return err;
  394. }
  395.  
  396.  
  397. /*****************************************************************************
  398.  * Function for comparing DIR_Servers 
  399.  */
  400.  
  401. XP_Bool    DIR_AreServersSame (DIR_Server *first, DIR_Server *second)
  402. {
  403.     XP_Bool result = FALSE;
  404.  
  405.     if (first && second) 
  406.     {
  407.         /* assume for right now one personal address book type where offline is false */
  408.         if ((first->dirType == PABDirectory) && (second->dirType == PABDirectory)) {
  409.             if ((first->isOffline == FALSE) && (second->isOffline == FALSE))
  410.                 return TRUE;
  411.             else {
  412.                 XP_ASSERT (first->serverName && second->serverName);
  413.                 if (first->serverName && second->serverName)
  414.                 {
  415.                     if (XP_STRCASECMP (first->serverName, second->serverName) == 0) 
  416.                     {
  417.                         if (first->port == second->port) 
  418.                         {
  419.                             /* allow for a null search base */
  420.                             if (first->searchBase == NULL && second->searchBase == NULL)
  421.                                 return TRUE;
  422.                             /* otherwise check the strings */
  423.                             if (first->searchBase && second->searchBase)
  424.                             {
  425.                                 if (XP_STRCASECMP (first->searchBase, second->searchBase) == 0) 
  426.                                 {
  427.                                         return TRUE;
  428.                                 }
  429.                                 else
  430.                                     return FALSE;
  431.                             }
  432.                             else
  433.                                 return FALSE;
  434.                         }
  435.                     }
  436.                     else
  437.                         return FALSE;
  438.                 }
  439.             }
  440.         }
  441.  
  442.         if (first->dirType != second->dirType)
  443.             return FALSE;
  444.  
  445.         /* otherwise check for ldap servers */
  446.         XP_ASSERT (first->serverName && second->serverName);
  447.         if (first->serverName && second->serverName)
  448.         {
  449.             if (!XP_STRCASECMP (first->serverName, second->serverName)) 
  450.             {
  451.                 if (first->port == second->port) 
  452.                 {
  453.                     /* allow for a null search base */
  454.                     if (first->searchBase == NULL && second->searchBase == NULL)
  455.                         result = TRUE;
  456.                     /* otherwise check the strings */
  457.                     if (first->searchBase && second->searchBase)
  458.                     {
  459.                         if (!XP_STRCASECMP (first->searchBase, second->searchBase)) 
  460.                         {
  461.                                 result = TRUE;
  462.                         }
  463.                     }
  464.                 }
  465.             }
  466.         }
  467.     }
  468.     return result;
  469. }
  470.  
  471.  
  472. /*****************************************************************************
  473.  * Functions for destroying DIR_Servers 
  474.  */
  475.  
  476. static void dir_DeleteTokenList (char **tokenList, int tokenListCount)
  477. {
  478.     int tokenIdx;
  479.     for (tokenIdx = 0; tokenIdx < tokenListCount; tokenIdx++)
  480.         XP_FREE(tokenList[tokenIdx]);
  481.     XP_FREE(tokenList);
  482. }
  483.  
  484.  
  485. static int DIR_DeleteFilter (DIR_Filter *filter)
  486. {
  487.     if (filter->string)
  488.         XP_FREE(filter->string);
  489.     XP_FREE(filter);
  490.     return 0;
  491. }
  492.  
  493.  
  494. static int DIR_DeleteAttribute (DIR_Attribute *attribute)
  495. {
  496.     int i = 0;
  497.     if (attribute->prettyName)
  498.         XP_FREE(attribute->prettyName);
  499.     if (attribute->attrNames)
  500.     {
  501.         while (attribute->attrNames[i])
  502.             XP_FREE((char**)attribute->attrNames[i++]);
  503.         XP_FREE(attribute->attrNames);
  504.     }
  505.     XP_FREE(attribute);
  506.     return 0;
  507. }
  508.  
  509.  
  510. static void dir_DeleteReplicationInfo (DIR_Server *server)
  511. {
  512.     DIR_ReplicationInfo *info = NULL;
  513.     if (server && (info = server->replInfo) != NULL)
  514.     {
  515.         dir_DeleteTokenList (info->excludedAttributes, info->excludedAttributesCount);
  516.         
  517.         XP_FREEIF(info->description);
  518.         XP_FREEIF(info->filter);
  519.         XP_FREE(info);
  520.     }
  521. }
  522.  
  523.  
  524. int DIR_DeleteServer (DIR_Server *server)
  525. {
  526.     if (server)
  527.     {
  528.         int i;
  529.  
  530.         XP_FREEIF (server->description);
  531.         XP_FREEIF (server->serverName);
  532.         XP_FREEIF (server->searchBase);
  533.         XP_FREEIF (server->fileName);
  534.         XP_FREEIF (server->lastSearchString);
  535.         XP_FREEIF (server->tokenSeps);
  536.         XP_FREEIF (server->authDn);
  537.         XP_FREEIF (server->password);
  538.         XP_FREEIF (server->prefId);
  539.  
  540.         if (server->customFilters)
  541.         {
  542.             for (i = 1; i <= XP_ListCount(server->customFilters); i++)
  543.                 DIR_DeleteFilter ((DIR_Filter*) XP_ListGetObjectNum (server->customFilters, i));
  544.             XP_ListDestroy (server->customFilters);
  545.         }
  546.  
  547.         if (server->customAttributes)
  548.         {
  549.             XP_List *list = server->customAttributes;
  550.             DIR_Attribute *walkAttrStruct = NULL;
  551.             while ((walkAttrStruct = XP_ListNextObject(list)) != NULL)
  552.                 DIR_DeleteAttribute (walkAttrStruct);
  553.             XP_ListDestroy (server->customAttributes);
  554.         }
  555.  
  556.         if (server->suppressedAttributes)
  557.             dir_DeleteTokenList (server->suppressedAttributes, server->suppressedAttributesCount);
  558.         if (server->dnAttributes)
  559.             dir_DeleteTokenList (server->dnAttributes, server->dnAttributesCount);
  560.         XP_FREEIF (server->basicSearchAttributes);
  561.         if (server->replInfo)
  562.             dir_DeleteReplicationInfo (server);
  563.  
  564.         XP_FREEIF (server->customDisplayUrl);
  565.  
  566.         XP_FREE (server);
  567.     }
  568.     return 0;
  569. }
  570.  
  571. int DIR_DeleteServerList(XP_List *wholeList)
  572. {
  573.     int i;
  574.     if (wholeList)
  575.     {
  576.         for (i = 1; i <= XP_ListCount(wholeList); i++)
  577.             DIR_DeleteServer(XP_ListGetObjectNum (wholeList, i));
  578.         XP_ListDestroy (wholeList);
  579.     }
  580.     return 0;
  581. }
  582.  
  583.  
  584. int DIR_CleanUpServerPreferences(XP_List *deletedList)
  585. {
  586.     int i;
  587.     if (deletedList)
  588.     {
  589.         for (i = 1; i <= XP_ListCount(deletedList); i++)
  590.         {
  591.             DIR_Server *server = (DIR_Server *) (XP_ListGetObjectNum (deletedList, i));
  592.             if (server)
  593.             {
  594. #if !defined(MOZADDRSTANDALONE)
  595.                 if (server->fileName)
  596.                     XP_FileRemove (server->fileName, xpAddrBookNew);
  597. #endif
  598.             }
  599.         }
  600.         DIR_DeleteServerList(deletedList);
  601.     }
  602.     return 0;
  603. }
  604.  
  605.  
  606. /*****************************************************************************
  607.  * Functions for retrieving subsets of the DIR_Server list 
  608.  */
  609.  
  610. int DIR_GetHtmlServers (XP_List *wholeList, XP_List *subList)
  611. {
  612.     int i;
  613.     if (wholeList && subList)
  614.     {
  615.         for (i = 1; i <= XP_ListCount(wholeList); i++)
  616.         {
  617.             DIR_Server *s = (DIR_Server*) XP_ListGetObjectNum (wholeList, i);
  618.             if (HTMLDirectory == s->dirType)
  619.                 XP_ListAddObjectToEnd (subList, s);
  620.         }
  621.         return 0;
  622.     }
  623.     return -1;
  624. }
  625.  
  626. int DIR_GetLdapServers (XP_List *wholeList, XP_List *subList)
  627. {
  628.     int i;
  629.     if (wholeList && subList)
  630.     {
  631.         for (i = 1; i <= XP_ListCount(wholeList); i++)
  632.         {
  633.             DIR_Server *s = (DIR_Server*) XP_ListGetObjectNum (wholeList, i);
  634.             if (LDAPDirectory == s->dirType)
  635.                 XP_ListAddObjectToEnd (subList, s);
  636.         }
  637.         return 0;
  638.     }
  639.     return -1;
  640. }
  641.  
  642. int    DIR_ReorderLdapServers (XP_List *wholeList)
  643. {
  644.     int status = 0;
  645.     int length = 0;
  646.     DIR_Server *s = NULL;
  647.     char *prefValue = NULL;
  648.  
  649.     XP_List *walkList = wholeList;
  650.     while (s = (DIR_Server*) XP_ListNextObject (walkList))
  651.     {
  652.         length += XP_STRLEN (s->prefId) + 2; /* +2 for ", " */
  653.     }
  654.  
  655.     prefValue = (char*) XP_ALLOC (length + 1); /* +1 for null term */
  656.     if (prefValue)
  657.     {
  658.         *prefValue = '\0';
  659.         walkList = wholeList;
  660.         while (s = (DIR_Server*) XP_ListNextObject (walkList))
  661.         {
  662.             XP_STRCAT (prefValue, s->prefId);
  663.             XP_STRCAT (prefValue, ", ");
  664.         }
  665.         if (PREF_SetCharPref (kLdapServersPrefName, prefValue) < 0)
  666.             status = -1; /* not sure how to make a pref error into an mk error */
  667.         XP_FREE(prefValue);
  668.     }
  669.     else
  670.         status = MK_OUT_OF_MEMORY;
  671.  
  672.     return status;
  673. }
  674.  
  675. int DIR_GetPersonalAddressBook (XP_List *wholeList, DIR_Server **pab)
  676. {
  677.     int i;
  678.     if (wholeList && pab)
  679.     {
  680.         *pab = NULL;
  681.         for (i = 1; i <= XP_ListCount(wholeList); i++)
  682.         {
  683.             DIR_Server *s = (DIR_Server*) XP_ListGetObjectNum (wholeList, i);
  684.             if ((PABDirectory == s->dirType) && (FALSE == s->isOffline))
  685.             {
  686.                 if (s->serverName) {
  687.                     if (XP_STRLEN (s->serverName) == 0) {
  688.                         *pab = s;
  689.                         return 0;
  690.                     }
  691.                 }
  692.                 if (s->serverName == NULL) {
  693.                         *pab = s;
  694.                         return 0;
  695.                 }
  696.             }
  697.         }
  698.     }
  699.     return -1;
  700. }
  701.  
  702. int DIR_GetComposeNameCompletionAddressBook (XP_List *wholeList, DIR_Server **cab)
  703. {
  704.     int i;
  705.     if (wholeList && cab)
  706.     {
  707.         *cab = NULL;
  708.         for (i = 1; i <= XP_ListCount(wholeList); i++)
  709.         {
  710.             DIR_Server *s = (DIR_Server*) XP_ListGetObjectNum (wholeList, i);
  711.             if (PABDirectory == s->dirType)
  712.             {
  713.                 *cab = s;
  714.                 return 0;
  715.             }
  716.         }
  717.     }
  718.     return -1;
  719. }
  720.  
  721.  
  722. /*****************************************************************************
  723.  * Functions for managing JavaScript prefs for the DIR_Servers 
  724.  */
  725.  
  726. #if !defined(MOZADDRSTANDALONE)
  727.  
  728. static char *DIR_GetStringPref (const char *prefRoot, const char *prefLeaf, char *scratch, const char *defaultValue)
  729. {
  730.     int valueLength = 0;
  731.     char *value = NULL;
  732.     XP_STRCPY(scratch, prefRoot);
  733.     XP_STRCAT (scratch, prefLeaf);
  734.  
  735.     if (PREF_NOERROR == PREF_CopyCharPref(scratch, &value))
  736.     {
  737.         /* unfortunately, there may be some prefs out there which look like this */
  738.         if (!XP_STRCMP(value, "(null)")) 
  739.             value = XP_STRDUP(defaultValue);
  740.     }
  741.     else
  742.         value = XP_STRDUP(defaultValue);
  743.     return value;
  744. }
  745.  
  746.  
  747. static int32 DIR_GetIntPref (const char *prefRoot, const char *prefLeaf, char *scratch, int32 defaultValue)
  748. {
  749.     int32 value;
  750.     XP_STRCPY(scratch, prefRoot);
  751.     if (PREF_NOERROR != PREF_GetIntPref(XP_STRCAT (scratch, prefLeaf), &value))
  752.         value = defaultValue;
  753.     return value;
  754. }
  755.  
  756.  
  757. static XP_Bool DIR_GetBoolPref (const char *prefRoot, const char *prefLeaf, char *scratch, XP_Bool defaultValue)
  758. {
  759.     XP_Bool value;
  760.     XP_STRCPY(scratch, prefRoot);
  761.     if (PREF_NOERROR != PREF_GetBoolPref(XP_STRCAT (scratch, prefLeaf), &value))
  762.         value = defaultValue;
  763.     return value;
  764. }
  765.  
  766.  
  767. int DIR_AttributeNameToId (const char *attrName, DIR_AttributeId *id)
  768. {
  769.     int status = 0;
  770.  
  771.     switch (attrName[0])
  772.     {
  773.     case 'a':
  774.         if (!XP_STRCASECMP(attrName, "auth"))
  775.             *id = auth;
  776.         else
  777.             status = -1;
  778.         break;
  779.     case 'c' :
  780.         if (!XP_STRCASECMP(attrName, "cn"))
  781.             *id = cn;
  782.         else if (!XP_STRNCASECMP(attrName, "custom", 6))
  783.         {
  784.             switch (attrName[6])
  785.             {
  786.             case '1': *id = custom1; break;
  787.             case '2': *id = custom2; break;
  788.             case '3': *id = custom3; break;
  789.             case '4': *id = custom4; break;
  790.             case '5': *id = custom5; break;
  791.             default: status = -1; 
  792.             }
  793.         }
  794.         else
  795.             status = -1;
  796.         break;
  797.     case 'g':
  798.         if (!XP_STRCASECMP(attrName, "givenname"))
  799.             *id = givenname; 
  800.         else
  801.             status = -1;
  802.         break;
  803.     case 's': 
  804.         if (!XP_STRCASECMP(attrName, "street"))
  805.             *id = street;
  806.         else if (!XP_STRCASECMP(attrName, "sn"))
  807.             *id = sn;
  808.         else
  809.             status = -1;
  810.         break;
  811.     case 'm':
  812.         if (!XP_STRCASECMP(attrName, "mail"))
  813.             *id = mail;
  814.         else
  815.             status = -1;
  816.         break;
  817.     case 'o':
  818.         if (!XP_STRCASECMP(attrName, "o"))
  819.             *id = o;
  820.         else if (!XP_STRCASECMP(attrName, "ou"))
  821.             *id = ou;
  822.         else
  823.             status = -1;
  824.         break;
  825.     case 'l':
  826.         if (!XP_STRCASECMP(attrName, "l"))
  827.             *id = l;
  828.         else
  829.             status = -1;
  830.         break;
  831.     case 't':
  832.         if (!XP_STRCASECMP(attrName, "telephoneNumber"))
  833.             *id = telephonenumber;
  834.         else
  835.             status = -1;
  836.         break;
  837.     default:
  838.         status = -1;
  839.     }
  840.  
  841.     return status;
  842. }
  843.  
  844.  
  845. static int DIR_AddCustomAttribute (DIR_Server *server, const char *attrName, char *jsAttr)
  846. {
  847.     int status = 0;
  848.     char *jsCompleteAttr = NULL;
  849.     char *jsAttrForTokenizing = jsAttr;
  850.  
  851.     DIR_AttributeId id;
  852.     status = DIR_AttributeNameToId (attrName, &id);
  853.  
  854.     /* If the string they gave us doesn't have a ':' in it, assume it's one or more
  855.      * attributes without a pretty name. So find the default pretty name, and generate
  856.      * a "complete" string to use for tokenizing.
  857.      */
  858.     if (status == 0 && !XP_STRCHR(jsAttr, ':'))
  859.     {
  860.         const char *defaultPrettyName = DIR_GetAttributeName (server, id);
  861.         if (defaultPrettyName)
  862.         {
  863.             jsCompleteAttr = PR_smprintf ("%s:%s", defaultPrettyName, jsAttr);
  864.             if (jsCompleteAttr)
  865.                 jsAttrForTokenizing = jsCompleteAttr;
  866.             else
  867.                 status = MK_OUT_OF_MEMORY;
  868.         }
  869.     }
  870.  
  871.     if (status == 0)
  872.     {
  873.         char *scratchAttr = XP_STRDUP(jsAttrForTokenizing);
  874.         DIR_Attribute *attrStruct = (DIR_Attribute*) XP_ALLOC(sizeof(DIR_Attribute));
  875.         if (!server->customAttributes)
  876.             server->customAttributes = XP_ListNew();
  877.  
  878.         if (attrStruct && server->customAttributes && scratchAttr)
  879.         {
  880.             char *attrToken = NULL;
  881.             int attrCount = 0;
  882.  
  883.             XP_BZERO(attrStruct, sizeof(DIR_Attribute));
  884.  
  885.             /* Try to pull out the pretty name into the struct */
  886.             attrStruct->id = id;
  887.             attrStruct->prettyName = XP_STRDUP(XP_STRTOK(scratchAttr, ":")); 
  888.  
  889.             /* Count up the attribute names */
  890.             while ((attrToken = XP_STRTOK(NULL, ", ")) != NULL)
  891.                 attrCount++;
  892.  
  893.             /* Pull the attribute names into the struct */
  894.             XP_STRCPY(scratchAttr, jsAttrForTokenizing);
  895.             XP_STRTOK(scratchAttr, ":"); 
  896.             attrStruct->attrNames = (char**) XP_ALLOC((attrCount + 1) * sizeof(char*));
  897.             if (attrStruct->attrNames)
  898.             {
  899.                 int i = 0;
  900.                 while ((attrToken = XP_STRTOK(NULL, ", ")) != NULL)
  901.                     attrStruct->attrNames[i++] = XP_STRDUP(attrToken);
  902.                 attrStruct->attrNames[i] = NULL; /* null-terminate the array */
  903.             }
  904.  
  905.             if (status == 0)
  906.                 XP_ListAddObject (server->customAttributes, attrStruct);
  907.             else
  908.                 DIR_DeleteAttribute (attrStruct);
  909.  
  910.             XP_FREE(scratchAttr);
  911.         }
  912.         else 
  913.             status = MK_OUT_OF_MEMORY;
  914.     }
  915.  
  916.     if (jsCompleteAttr)
  917.         XP_FREE(jsCompleteAttr);
  918.  
  919.     return status;
  920. }
  921.  
  922.  
  923. static int dir_CreateTokenListFromWholePref (const char *pref, char ***outList, int *outCount)
  924. {
  925.     int result = 0;
  926.     char *commaSeparatedList = NULL;
  927.  
  928.     if (PREF_NOERROR == PREF_CopyCharPref (pref, &commaSeparatedList) && commaSeparatedList)
  929.     {
  930.         char *tmpList = commaSeparatedList;
  931.         *outCount = 1;
  932.         while (*tmpList)
  933.             if (*tmpList++ == ',')
  934.                 (*outCount)++;
  935.  
  936.         *outList = (char**) XP_ALLOC (*outCount * sizeof(char*));
  937.         if (*outList)
  938.         {
  939.             int i;
  940.             char *token = XP_STRTOK (commaSeparatedList, ", ");
  941.             for (i = 0; i < *outCount; i++)
  942.             {
  943.                 (*outList)[i] = XP_STRDUP (token);
  944.                 token = XP_STRTOK(NULL, ", ");
  945.             }
  946.         }
  947.         else
  948.             result = MK_OUT_OF_MEMORY;
  949.  
  950.         XP_FREE (commaSeparatedList);
  951.     }
  952.     else
  953.         result = -1;
  954.     return result;
  955. }
  956.  
  957.  
  958. static int dir_CreateTokenListFromPref (const char *prefBase, const char *prefLeaf, char *scratch, char ***outList, int *outCount)
  959. {
  960.     XP_STRCPY (scratch, prefBase);
  961.     XP_STRCAT (scratch, prefLeaf);
  962.  
  963.     return dir_CreateTokenListFromWholePref (scratch, outList, outCount);
  964. }
  965.  
  966.  
  967. static int dir_ConvertTokenListToIdList (char **tokenList, int tokenCount, DIR_AttributeId **outList)
  968. {
  969.     *outList = (DIR_AttributeId*) XP_ALLOC (sizeof(DIR_AttributeId) * tokenCount);
  970.     if (*outList)
  971.     {
  972.         int i;
  973.         for (i = 0; i < tokenCount; i++)
  974.             DIR_AttributeNameToId (tokenList[i], &(*outList)[i]);
  975.     }
  976.     else
  977.         return MK_OUT_OF_MEMORY;
  978.     return 0;
  979. }
  980.  
  981.  
  982. static void dir_GetReplicationInfo (const char *prefName, DIR_Server *server, char *scratch)
  983. {
  984.     char *childList = NULL;
  985.     XP_STRCPY (scratch, prefName);
  986.     if (PREF_NOERROR == PREF_CreateChildList (XP_STRCAT(scratch, "replication"), &childList))
  987.     {
  988.         XP_ASSERT (server->replInfo == NULL);
  989.         if (childList && childList[0])
  990.         {
  991.             server->replInfo = (DIR_ReplicationInfo *) XP_CALLOC (sizeof (DIR_ReplicationInfo), 1);
  992.             if (server->replInfo)
  993.             {
  994.                 char *child = NULL;
  995.                 int index = 0;
  996.                 while ((child = PREF_NextChild (childList, &index)) != NULL)
  997.                 {
  998.                     char *leaf = XP_STRRCHR (child, '.');
  999.                     if (leaf)
  1000.                     {
  1001.                         leaf++; /* skip over the '.' */
  1002.  
  1003.                         /* Note: JS prefs are case-sensitive, and so is this code */
  1004.                         switch (leaf[0])
  1005.                         {
  1006.                             case 'd':
  1007.                                 if (!XP_STRCMP (leaf, "description"))
  1008.                                     PREF_CopyCharPref (child, &server->replInfo->description);
  1009.                                 else
  1010.                                     XP_ASSERT(FALSE);
  1011.                                 break;
  1012.                             case 'e':
  1013.                                 if (!XP_STRCMP (leaf, "enabled"))
  1014.                                     PREF_GetBoolPref (child, &server->replInfo->enabled);
  1015.                                 else if (!XP_STRCMP (leaf, "excludedAttributes"))
  1016.                                     dir_CreateTokenListFromWholePref (child, &server->replInfo->excludedAttributes, 
  1017.                                                                     &server->replInfo->excludedAttributesCount);
  1018.                                 else
  1019.                                     XP_ASSERT(FALSE);
  1020.                                 break;
  1021.                             case 'f' :
  1022.                                 if (!XP_STRCMP (leaf, "filter"))
  1023.                                     PREF_CopyCharPref (child, &server->replInfo->filter);
  1024.                                 else
  1025.                                     XP_ASSERT(FALSE);
  1026.                                 break;
  1027.                             case 'g':
  1028.                                 if (!XP_STRCMP (leaf, "generation"))
  1029.                                     PREF_GetIntPref (child, &server->replInfo->generation);
  1030.                                 else
  1031.                                     XP_ASSERT(FALSE);
  1032.                                 break;
  1033.                             case 'l':
  1034.                                 if (!XP_STRCMP (leaf, "lastChangeNumber"))
  1035.                                     PREF_GetIntPref (child, &server->replInfo->lastChangeNumber);
  1036.                                 else
  1037.                                     XP_ASSERT(FALSE);
  1038.                                 break;
  1039.                             default:
  1040.                                 XP_ASSERT(FALSE); 
  1041.                         }
  1042.                     }
  1043.                 }
  1044.             }
  1045.         }
  1046.         XP_FREE(childList);
  1047.     }
  1048. }
  1049.  
  1050.  
  1051. /* Called at startup-time to read whatever overrides the LDAP site administrator has
  1052.  * done to the attribute names
  1053.  */
  1054. static int DIR_GetCustomAttributePrefs (const char *prefName, DIR_Server *server, char *scratch)
  1055. {
  1056.     char **tokenList = NULL;
  1057.     char *childList = NULL;
  1058.     XP_STRCPY(scratch, prefName);
  1059.  
  1060.     if (PREF_NOERROR == PREF_CreateChildList(XP_STRCAT(scratch, "attributes"), &childList))
  1061.     {
  1062.         if (childList && childList[0])
  1063.         {
  1064.             char *child = NULL;
  1065.             int index = 0;
  1066.             while ((child = PREF_NextChild (childList, &index)) != NULL)
  1067.             {
  1068.                 char *jsValue = NULL;
  1069.                 if (PREF_NOERROR == PREF_CopyCharPref (child, &jsValue))
  1070.                 {
  1071.                     if (jsValue && jsValue[0])
  1072.                     {
  1073.                         char *attrName = child + XP_STRLEN(scratch) + 1;
  1074.                         DIR_AddCustomAttribute (server, attrName, jsValue);
  1075.                     }
  1076.                     XP_FREEIF(jsValue);
  1077.                 }
  1078.             }
  1079.         }
  1080.  
  1081.         XP_FREEIF(childList);
  1082.     }
  1083.  
  1084.     /* The replicated attributes and basic search attributes can only be
  1085.      * attributes which are in our predefined set (DIR_AttributeId) so
  1086.      * store those in an array of IDs for more convenient access
  1087.      */
  1088.     dir_GetReplicationInfo (prefName, server, scratch);
  1089.  
  1090.     if (0 == dir_CreateTokenListFromPref (prefName, "basicSearchAttributes", scratch, 
  1091.         &tokenList, &server->basicSearchAttributesCount))
  1092.     {
  1093.         dir_ConvertTokenListToIdList (tokenList, server->basicSearchAttributesCount, 
  1094.             &server->basicSearchAttributes);
  1095.         dir_DeleteTokenList (tokenList, server->basicSearchAttributesCount);
  1096.     }
  1097.  
  1098.     /* The DN attributes and suppressed attributes can be attributes that
  1099.      * we've never heard of, so they're stored by name, so we can match 'em
  1100.      * as we get 'em from the server
  1101.      */
  1102.     dir_CreateTokenListFromPref (prefName, "html.dnAttributes", scratch, 
  1103.         &server->dnAttributes, &server->dnAttributesCount);
  1104.     dir_CreateTokenListFromPref (prefName, "html.excludedAttributes", scratch, 
  1105.         &server->suppressedAttributes, &server->suppressedAttributesCount);
  1106.  
  1107.     return 0;
  1108. }
  1109.  
  1110.  
  1111. /* Called at startup-time to read whatever overrides the LDAP site administrator has
  1112.  * done to the filtering logic
  1113.  */
  1114. static int DIR_GetCustomFilterPrefs (const char *prefName, DIR_Server *server, char *scratch)
  1115. {
  1116.     int status = 0;
  1117.     XP_Bool keepGoing = TRUE;
  1118.     int filterNum = 1;
  1119.     char *localScratch = XP_ALLOC(128);
  1120.     if (!localScratch)
  1121.         return MK_OUT_OF_MEMORY;
  1122.  
  1123.     while (keepGoing && !status)
  1124.     {
  1125.         char *childList = NULL;
  1126.  
  1127.         PR_snprintf (scratch, 128, "%sfilter%d", prefName, filterNum);
  1128.         if (PREF_NOERROR == PREF_CreateChildList(scratch, &childList))
  1129.         {
  1130.             if ('\0' != childList[0])
  1131.             {
  1132.                 DIR_Filter *filter = (DIR_Filter*) XP_ALLOC (sizeof(DIR_Filter));
  1133.                 if (filter)
  1134.                 {
  1135.                     XP_Bool tempBool;
  1136.                     XP_BZERO(filter, sizeof(DIR_Filter));
  1137.  
  1138.                     /* Pull per-directory filter preferences out of JS values */
  1139.                     if (1 == filterNum)
  1140.                     {
  1141.                         server->tokenSeps = DIR_GetStringPref (prefName, "wordSeparators", localScratch, kDefaultTokenSeps);
  1142. #if 0
  1143.                         /* This is left over from when I thought I'd have time to let the
  1144.                         ** admin specify a list of filters, and we'd run them until we got 
  1145.                         ** a hit. Still a good idea, but probably too late for Dogbert.
  1146.                         */
  1147.                         server->stopFiltersOnHit = DIR_GetBoolPref (prefName, "stopFiltersOnHit", localScratch, kDefaultStopOnHit);
  1148. #endif
  1149.                         XP_STRCAT(scratch, ".");
  1150.                     }
  1151.  
  1152.                     /* Pull per-filter preferences out of JS values */
  1153.                     filter->string = DIR_GetStringPref (scratch, "string", localScratch, 
  1154.                         server->efficientWildcards ? kDefaultFilter : kDefaultEfficientFilter);
  1155.                     tempBool = DIR_GetBoolPref (scratch, "repeatFilterForWords", localScratch, kDefaultRepeatFilterForTokens);
  1156.                     if (tempBool)
  1157.                         filter->flags |= DIR_F_REPEAT_FILTER_FOR_TOKENS;
  1158.                     tempBool = DIR_GetBoolPref (scratch, "substituteStarsForSpaces", localScratch, kDefaultSubstStarsForSpaces);
  1159.                     if (tempBool)
  1160.                         filter->flags |= DIR_F_SUBST_STARS_FOR_SPACES;
  1161.  
  1162.                     /* Add resulting DIR_Filter to the list */
  1163.                     if (!server->customFilters)
  1164.                         server->customFilters = XP_ListNew();
  1165.                     if (server->customFilters)
  1166.                         XP_ListAddObject (server->customFilters, filter);
  1167.                     else
  1168.                         status = MK_OUT_OF_MEMORY;
  1169.                 }
  1170.                 else
  1171.                     status = MK_OUT_OF_MEMORY;
  1172.                 filterNum++;
  1173.             }
  1174.             else
  1175.                 keepGoing = FALSE;
  1176.             XP_FREE(childList);
  1177.         }
  1178.         else
  1179.             keepGoing = FALSE;
  1180.     }
  1181.  
  1182.     XP_FREE(localScratch);
  1183.     return status;
  1184. }
  1185.  
  1186. /* This will convert from the old preference that was a path and filename */
  1187. /* to a just a filename */
  1188. void DIR_ConvertServerFileName(DIR_Server* pServer)
  1189. {
  1190.     char* leafName = pServer->fileName;
  1191.     char* newLeafName = NULL;
  1192. #if defined(XP_WIN) || defined(XP_OS2)
  1193.     /* jefft -- bug 73349 This is to allow users share same address book.
  1194.      * It only works if the user specify a full path filename.
  1195.      */
  1196.     if (! XP_FileIsFullPath(leafName))
  1197.         newLeafName = XP_STRRCHR (leafName, '\\');
  1198. #else
  1199.     newLeafName = XP_STRRCHR (leafName, '/');
  1200. #endif
  1201.     pServer->fileName = newLeafName ? XP_STRDUP(newLeafName + 1) : XP_STRDUP(leafName);
  1202.     if (leafName) XP_FREE(leafName);
  1203. }
  1204.  
  1205. /* This will generate a correct filename and then remove the path */
  1206. void DIR_SetServerFileName(DIR_Server* pServer, const char* leafName)
  1207. {
  1208.     char* tempName = WH_TempName(xpAddrBook, leafName);
  1209.     char* nativeName = WH_FileName(tempName, xpAddrBook);
  1210.     char* urlName = XP_PlatformFileToURL(nativeName);
  1211. #if defined(XP_WIN) || defined(XP_UNIX) || defined(XP_MAC) || defined(XP_OS2)
  1212.     char* newLeafName = XP_STRRCHR (urlName + XP_STRLEN("file://"), '/');
  1213.     pServer->fileName = newLeafName ? XP_STRDUP(newLeafName + 1) : XP_STRDUP(urlName + XP_STRLEN("file://"));
  1214. #else
  1215.     pServer->fileName = XP_STRDUP(urlName + XP_STRLEN("file://"));
  1216. #endif
  1217.     if (urlName) XP_FREE(urlName);
  1218.     if (nativeName) XP_FREE(nativeName);
  1219.     if (tempName) XP_FREE(tempName);
  1220. }
  1221.  
  1222. /* This will reconstruct a correct filename including the path */
  1223. void DIR_GetServerFileName(char** filename, const char* leafName)
  1224. {
  1225. #ifdef XP_MAC
  1226.     char* realLeafName;
  1227.     char* nativeName;
  1228.     char* urlName;
  1229.     if (XP_STRCHR(leafName, ':') != NULL)
  1230.         realLeafName = XP_STRRCHR(leafName, ':') + 1;    // makes sure that leafName is not a fullpath
  1231.     else
  1232.         realLeafName = leafName;
  1233.  
  1234.     nativeName = WH_FileName(realLeafName, xpAddrBookNew);
  1235.     urlName = XP_PlatformFileToURL(nativeName);
  1236.     (*filename) = XP_STRDUP(urlName + XP_STRLEN("file://"));
  1237.     if (urlName) XP_FREE(urlName);
  1238. #elif defined(XP_WIN)
  1239.     /* jefft -- Bug 73349. To allow users share same address book.
  1240.      * This only works if user sepcified a full path name in his
  1241.      * prefs.js
  1242.      */ 
  1243.     char *nativeName = WH_FilePlatformName (leafName);
  1244.     char *fullnativeName;
  1245.     if (XP_FileIsFullPath(nativeName)) {
  1246.         fullnativeName = nativeName;
  1247.         nativeName = NULL;
  1248.     }
  1249.     else {
  1250.         fullnativeName = WH_FileName(nativeName, xpAddrBookNew);
  1251.     }
  1252.     (*filename) = fullnativeName;
  1253. #else
  1254.     char* nativeName = WH_FilePlatformName (leafName);
  1255.     char* fullnativeName = WH_FileName(nativeName, xpAddrBookNew);
  1256.     (*filename) = fullnativeName;
  1257. #endif
  1258.     if (nativeName) XP_FREE(nativeName);
  1259. }
  1260.  
  1261. static int DIR_GetPrefsFromBranch (XP_List **list, const char *pabFile, const char *branch)
  1262. {
  1263.     int32 numDirectories = 0;
  1264.     int i = 0;
  1265.     char *prefstring = NULL;
  1266.     char *tempString = NULL;
  1267.     int result = 0;
  1268.     XP_Bool hasPAB = FALSE;
  1269.     DIR_Server *pNewServer = NULL;
  1270.     char *newfilename = NULL;
  1271.  
  1272.     if (*list)
  1273.         DIR_DeleteServerList(*list);
  1274.  
  1275.     prefstring = (char *) XP_ALLOC(128);
  1276.     tempString = (char *) XP_ALLOC(256);
  1277.  
  1278.     (*list) = XP_ListNew();
  1279.     /* get the preference for how many directories */
  1280.     if (prefstring && tempString && (*list) && branch && *branch)
  1281.     {
  1282.         char *numberOfDirs = PR_smprintf ("%s.number_of_directories", branch);
  1283.         if (numberOfDirs)
  1284.             PREF_GetIntPref(numberOfDirs, &numDirectories);    
  1285.         for (i = 1; i <= numDirectories; i++)
  1286.         {
  1287.             pNewServer = (DIR_Server *) XP_ALLOC(sizeof(DIR_Server));
  1288.             if (pNewServer)
  1289.             {
  1290.                 XP_Bool prefBool;
  1291.  
  1292.                 XP_BZERO(pNewServer, sizeof(DIR_Server));
  1293.                 XP_SPRINTF(prefstring, "%s.directory%i.", branch, i);
  1294.  
  1295.                 pNewServer->isSecure = DIR_GetBoolPref (prefstring, "isSecure", tempString, FALSE);
  1296.                 pNewServer->saveResults = DIR_GetBoolPref (prefstring, "saveResults", tempString, TRUE);                
  1297.                 pNewServer->efficientWildcards = DIR_GetBoolPref (prefstring, "efficientWildcards", tempString, TRUE);                
  1298.                 pNewServer->port = DIR_GetIntPref (prefstring, "port", tempString, pNewServer->isSecure ? LDAPS_PORT : LDAP_PORT);
  1299.                 if (pNewServer->port == 0)
  1300.                     pNewServer->port = pNewServer->isSecure ? LDAPS_PORT : LDAP_PORT;
  1301.                 pNewServer->maxHits = DIR_GetIntPref (prefstring, "maxHits", tempString, kDefaultMaxHits);
  1302.                 pNewServer->description = DIR_GetStringPref (prefstring, "description", tempString, "");
  1303.                 pNewServer->serverName = DIR_GetStringPref (prefstring, "serverName", tempString, "");
  1304.                 pNewServer->searchBase = DIR_GetStringPref (prefstring, "searchBase", tempString, "");
  1305.                 if (!XP_STRCASECMP(pNewServer->serverName, "ldap.infospace.com") && !*pNewServer->searchBase)
  1306.                 {
  1307.                     /* 4.0 unfortunately shipped with the wrong searchbase for Infospace, so
  1308.                      * if we find Infospace, and their searchBase hasn't been set, make it right
  1309.                      * It's not legal to do this in all.js unless we rename the LDAP prefs tree (ugh)
  1310.                      */
  1311.                     pNewServer->searchBase = XP_STRDUP ("c=US");
  1312.                     PREF_SetCharPref (tempString, "c=US");
  1313.                 }
  1314.                 
  1315.                 pNewServer->dirType = (DirectoryType)DIR_GetIntPref (prefstring, "dirType", tempString, (int) LDAPDirectory);
  1316.                 if (pNewServer->dirType == PABDirectory)
  1317.                 {
  1318.                     hasPAB = TRUE;
  1319.                     /* make sure there is a true PAB */
  1320.                     if (XP_STRLEN (pNewServer->serverName) == 0)
  1321.                         pNewServer->isOffline = FALSE;
  1322.                     pNewServer->saveResults = TRUE; /* never let someone delete their PAB this way */
  1323.                 }
  1324.  
  1325.                 pNewServer->fileName = DIR_GetStringPref (prefstring, "filename", tempString, "");
  1326.                 if (!pNewServer->fileName || !*(pNewServer->fileName)) 
  1327.                 {
  1328.                     if (pNewServer->dirType != PABDirectory)
  1329.                         DIR_SetServerFileName (pNewServer, pNewServer->serverName);
  1330.                     else
  1331.                     {
  1332.                         XP_FREEIF(pNewServer->fileName);
  1333.                         pNewServer->fileName = XP_STRDUP (pabFile);
  1334.                     }
  1335.                 }
  1336. #if defined(XP_WIN) || defined(XP_UNIX) || defined(XP_MAC) || defined(XP_OS2)
  1337.                 DIR_ConvertServerFileName(pNewServer);
  1338. #endif
  1339.                 pNewServer->lastSearchString = DIR_GetStringPref (prefstring, "searchString", tempString, "");
  1340.                 pNewServer->isOffline = DIR_GetBoolPref (prefstring, "isOffline", tempString, kDefaultIsOffline);
  1341.  
  1342.                 /* This is where site-configurable attributes and filters are read from JavaScript */
  1343.                 DIR_GetCustomAttributePrefs (prefstring, pNewServer, tempString);
  1344.                 DIR_GetCustomFilterPrefs (prefstring, pNewServer, tempString);
  1345.  
  1346.                 /* Get authentication prefs */
  1347.                 pNewServer->enableAuth = DIR_GetBoolPref (prefstring, "enableAuth", tempString, kDefaultEnableAuth);
  1348.                 pNewServer->savePassword = DIR_GetBoolPref (prefstring, "savePassword", tempString, kDefaultSavePassword);
  1349.                 if (pNewServer->savePassword)
  1350.                 {
  1351.                     pNewServer->authDn = DIR_GetStringPref (prefstring, "authDn", tempString, "");
  1352.                     pNewServer->password = DIR_GetStringPref (prefstring, "password", tempString, "");
  1353.                 }
  1354.  
  1355.                 prefBool = DIR_GetBoolPref (prefstring, "autoCompleteEnabled", tempString, kDefaultAutoCompleteEnabled);
  1356.                 DIR_ForceFlag (pNewServer, DIR_AUTO_COMPLETE_ENABLED, prefBool);
  1357.  
  1358.                 prefBool = DIR_GetBoolPref (prefstring, "utf8Disabled", tempString, kDefaultUtf8Disabled);
  1359.                 DIR_ForceFlag (pNewServer, DIR_UTF8_DISABLED, prefBool);
  1360.  
  1361.                 pNewServer->customDisplayUrl = DIR_GetStringPref (prefstring, "customDisplayUrl", tempString, "");
  1362.  
  1363.                 XP_ListAddObjectToEnd((*list), pNewServer);
  1364.             }
  1365.         }
  1366.  
  1367.         XP_FREEIF(numberOfDirs);
  1368.  
  1369.         /* all.js should have filled this stuff in */
  1370.         XP_ASSERT(hasPAB);
  1371.         XP_ASSERT(numDirectories != 0); 
  1372.     }
  1373.     else
  1374.         result = -1;
  1375.  
  1376.     XP_FREEIF (prefstring);
  1377.     XP_FREEIF (tempString);
  1378.  
  1379.     return result;
  1380. }
  1381.  
  1382.  
  1383. int DIR_GetServerPreferences (XP_List **list, const char* pabFile)
  1384. {
  1385.     int err = 0;
  1386.     XP_List *oldList = NULL;
  1387.     XP_List *newList = NULL;
  1388.     char *oldChildren = NULL;
  1389.  
  1390.     int32 listVersion = -1;
  1391.     XP_Bool userHasOldPrefs = FALSE;
  1392.  
  1393.     if (PREF_NOERROR == PREF_GetIntPref ("ldapList.version", &listVersion))
  1394.         userHasOldPrefs = (kCurrentListVersion > listVersion);
  1395.     else
  1396.         userHasOldPrefs = TRUE;
  1397.     
  1398.     /* Look to see if there's an old-style "directories" tree in prefs */
  1399.     if (PREF_NOERROR == PREF_CreateChildList ("directories", &oldChildren))
  1400.     {
  1401.         if (oldChildren)
  1402.         {
  1403.             if (userHasOldPrefs)
  1404.                 err = DIR_GetPrefsFromBranch (&oldList, pabFile, "directories");
  1405.             PREF_DeleteBranch ("directories");
  1406.             XP_FREEIF(oldChildren);
  1407.         }
  1408.     }
  1409.     /* Look to see if there's an old-style "ldap" tree in prefs */
  1410.     else if (PREF_NOERROR == PREF_CreateChildList ("ldap", &oldChildren))
  1411.     {
  1412.         if (oldChildren)
  1413.         {
  1414.             if (userHasOldPrefs)
  1415.                 err = DIR_GetPrefsFromBranch (&oldList, pabFile, "ldap");
  1416.             PREF_DeleteBranch ("ldap");
  1417.             XP_FREEIF(oldChildren);
  1418.         }
  1419.     }
  1420.  
  1421.     /* Find the new-style "ldap_1" tree in prefs */
  1422.     DIR_GetPrefsFromBranch (&newList, pabFile, "ldap_1");
  1423.  
  1424.     if (oldList && newList)
  1425.     {
  1426.         /* Merge the new tree onto the old tree, new on top, unique old at bottom */
  1427.         DIR_Server *oldServer;
  1428.         XP_List *walkOldList = oldList;
  1429.  
  1430.         while (NULL != (oldServer = XP_ListNextObject(walkOldList)))
  1431.         {
  1432.             XP_Bool addOldServer = TRUE;
  1433.             DIR_Server *newServer;
  1434.             XP_List *walkNewList = newList;
  1435.  
  1436.             while (NULL != (newServer = XP_ListNextObject(walkNewList)) && addOldServer)
  1437.             {
  1438.                 if (DIR_AreServersSame (oldServer, newServer))
  1439.                     addOldServer = FALSE; /* don't add servers which are in the new list */
  1440.                 else if (PABDirectory == oldServer->dirType)
  1441.                     addOldServer = FALSE; /* don't need the old PAB; there's already one in ALL.JS */
  1442.                 else if (!XP_STRCMP (oldServer->serverName, "ldap-trace.fedex.com"))
  1443.                     addOldServer = FALSE;
  1444.             }
  1445.  
  1446.             if (addOldServer)
  1447.             {
  1448.                 DIR_Server *copyOfOldServer;
  1449.                 DIR_CopyServer (oldServer, ©OfOldServer);
  1450.                 XP_ListAddObjectToEnd (newList, copyOfOldServer);
  1451.             }
  1452.         }
  1453.  
  1454.         /* Delete the list of old-style prefs */
  1455.         DIR_DeleteServerList (oldList);
  1456.  
  1457.         /* Write the new/merged list so we get it next time we ask */
  1458.         DIR_SaveServerPreferences (newList);
  1459.     }
  1460.  
  1461.     PREF_SetIntPref ("ldapList.version", kCurrentListVersion);
  1462.  
  1463.     *list = newList;
  1464.     return err;
  1465. }
  1466.  
  1467.  
  1468. #define DIR_GOOD_WAY 1
  1469.  
  1470.  
  1471. static void DIR_ClearPrefBranch (const char *branch)
  1472. {
  1473.     /* This little function provides a way to delete a prefs object but still
  1474.      * allow reassignment of that object later. 
  1475.      */
  1476.     char *recreateBranch = NULL;
  1477.  
  1478.     PREF_DeleteBranch (branch);
  1479.     recreateBranch = PR_smprintf ("pref_inittree(\"%s\")", branch);
  1480.     if (recreateBranch)
  1481.     {
  1482.         PREF_QuietEvaluateJSBuffer (recreateBranch, XP_STRLEN(recreateBranch));
  1483.         XP_FREE(recreateBranch);
  1484.     }
  1485. }
  1486.  
  1487.  
  1488. static void DIR_ClearIntPref (const char *pref)
  1489. {
  1490.     int32 oldDefault;
  1491.     int prefErr = PREF_GetDefaultIntPref (pref, &oldDefault);
  1492.     DIR_ClearPrefBranch (pref);
  1493.     if (prefErr >= 0)
  1494.         PREF_SetDefaultIntPref (pref, oldDefault);
  1495. }
  1496.  
  1497.  
  1498. static void DIR_ClearStringPref (const char *pref)
  1499. {
  1500.     char *oldDefault = NULL;
  1501.     int prefErr = PREF_CopyDefaultCharPref (pref, &oldDefault);
  1502.     DIR_ClearPrefBranch (pref);
  1503.     if (prefErr >= 0)
  1504.         PREF_SetDefaultCharPref (pref, oldDefault);
  1505.     XP_FREEIF(oldDefault);
  1506. }
  1507.  
  1508.  
  1509. static void DIR_ClearBoolPref (const char *pref)
  1510. {
  1511.     XP_Bool oldDefault;
  1512.     int prefErr = PREF_GetDefaultBoolPref (pref, &oldDefault);
  1513.     DIR_ClearPrefBranch (pref);
  1514.     if (prefErr >= 0)
  1515.         PREF_SetDefaultBoolPref (pref, oldDefault);
  1516. }
  1517.  
  1518.  
  1519. static void DIR_SetStringPref (const char *prefRoot, const char *prefLeaf, char *scratch, const char *value, const char *defaultValue)
  1520. {
  1521.     char *defaultPref = NULL;
  1522.     int prefErr = PREF_NOERROR;
  1523.  
  1524.     XP_STRCPY(scratch, prefRoot);
  1525.     XP_STRCAT (scratch, prefLeaf);
  1526.  
  1527.     if (PREF_NOERROR == PREF_CopyDefaultCharPref (scratch, &defaultPref))
  1528.     {
  1529.         /* If there's a default pref, just set ours in and let libpref worry 
  1530.          * about potential defaults in all.js
  1531.          */
  1532.         prefErr = PREF_SetCharPref (scratch, value);
  1533.         XP_FREE(defaultPref);
  1534.     }
  1535.     else
  1536.     {
  1537.         /* If there's no default pref, look for a user pref, and only set our value in
  1538.          * if the user pref is different than one of them.
  1539.          */
  1540.         char *userPref = NULL;
  1541.         if (PREF_NOERROR == PREF_CopyCharPref (scratch, &userPref))
  1542.         {
  1543. #if DIR_GOOD_WAY
  1544.             if (value && XP_STRCASECMP(value, defaultValue))
  1545.                 prefErr = PREF_SetCharPref (scratch, value);
  1546.             else
  1547.                 DIR_ClearStringPref (scratch); 
  1548. #else
  1549.                 prefErr = PREF_SetCharPref (scratch, value);
  1550. #endif
  1551.         }
  1552.         else
  1553.         {
  1554.             if (value && XP_STRCASECMP(value, defaultValue))
  1555.                 prefErr = PREF_SetCharPref (scratch, value); 
  1556.         }
  1557.     }
  1558.  
  1559.     XP_ASSERT(prefErr >= 0);
  1560. }
  1561.  
  1562.  
  1563. static void DIR_SetIntPref (const char *prefRoot, const char *prefLeaf, char *scratch, int32 value, int32 defaultValue)
  1564. {
  1565.     int32 defaultPref;
  1566.     int prefErr = 0;
  1567.  
  1568.     XP_STRCPY(scratch, prefRoot);
  1569.     XP_STRCAT (scratch, prefLeaf);
  1570.  
  1571.     if (PREF_NOERROR == PREF_GetDefaultIntPref (scratch, &defaultPref))
  1572.     {
  1573.         /* solve the problem where reordering user prefs must override default prefs */
  1574.         PREF_SetIntPref (scratch, value);
  1575.     }
  1576.     else
  1577.     {
  1578.         int32 userPref;
  1579.         if (PREF_NOERROR == PREF_GetIntPref (scratch, &userPref))
  1580.         {
  1581. #if DIR_GOOD_WAY
  1582.             if (value != defaultValue)
  1583.                 prefErr = PREF_SetIntPref(scratch, value);
  1584.             else
  1585.                 DIR_ClearIntPref (scratch);
  1586. #else
  1587.                 prefErr = PREF_SetIntPref(scratch, value);
  1588. #endif
  1589.         }
  1590.         else
  1591.         {
  1592.             if (value != defaultValue)
  1593.                 prefErr = PREF_SetIntPref (scratch, value); 
  1594.         }
  1595.     }
  1596.  
  1597.     XP_ASSERT(prefErr >= 0);
  1598. }
  1599.  
  1600.  
  1601. static void DIR_SetBoolPref (const char *prefRoot, const char *prefLeaf, char *scratch, XP_Bool value, XP_Bool defaultValue)
  1602. {
  1603.     XP_Bool defaultPref;
  1604.     int prefErr = PREF_NOERROR;
  1605.  
  1606.     XP_STRCPY(scratch, prefRoot);
  1607.     XP_STRCAT (scratch, prefLeaf);
  1608.  
  1609.     if (PREF_NOERROR == PREF_GetDefaultBoolPref (scratch, &defaultPref))
  1610.     {
  1611.         /* solve the problem where reordering user prefs must override default prefs */
  1612.         prefErr = PREF_SetBoolPref (scratch, value);
  1613.     }
  1614.     else
  1615.     {
  1616.         XP_Bool userPref;
  1617.         if (PREF_NOERROR == PREF_GetBoolPref (scratch, &userPref))
  1618.         {
  1619. #if DIR_GOOD_WAY
  1620.             if (value != defaultValue)
  1621.                 prefErr = PREF_SetBoolPref(scratch, value);
  1622.             else
  1623.                 DIR_ClearBoolPref (scratch);
  1624. #else
  1625.                 prefErr = PREF_SetBoolPref(scratch, value);
  1626. #endif
  1627.         }
  1628.         else
  1629.         {
  1630.             if (value != defaultValue)
  1631.                 prefErr = PREF_SetBoolPref (scratch, value);
  1632.         }
  1633.  
  1634.     }
  1635.  
  1636.     XP_ASSERT(prefErr >= 0);
  1637. }
  1638.  
  1639.  
  1640. static int DIR_ConvertAttributeToPrefsString (DIR_Attribute *attrib, char **ppPrefsString)
  1641. {
  1642.     int err = 0;
  1643.  
  1644.     /* Compute size in bytes req'd for prefs string */
  1645.     int length = XP_STRLEN(attrib->prettyName);
  1646.     int i = 0;
  1647.     while (attrib->attrNames[i])
  1648.     {
  1649.         length += XP_STRLEN(attrib->attrNames[i]) + 1; /* +1 for comma separator */
  1650.         i++;
  1651.     }
  1652.     length += 1; /* +1 for colon */
  1653.  
  1654.     /* Allocate prefs string */
  1655.     *ppPrefsString = (char*) XP_ALLOC(length + 1); /* +1 for null term */
  1656.  
  1657.     /* Unravel attrib struct back out into prefs */
  1658.     if (*ppPrefsString)
  1659.     {
  1660.         int j = 0;
  1661.         XP_STRCPY (*ppPrefsString, attrib->prettyName);
  1662.         XP_STRCAT (*ppPrefsString, ":");
  1663.         while (attrib->attrNames[j])
  1664.         {
  1665.             XP_STRCAT (*ppPrefsString, attrib->attrNames[j]);
  1666.             if (j + 1 < i)
  1667.                 XP_STRCAT (*ppPrefsString, ",");
  1668.             j++;
  1669.         }
  1670.     }
  1671.     else
  1672.         err = MK_OUT_OF_MEMORY;
  1673.  
  1674.     return err;
  1675. }
  1676.  
  1677.  
  1678. static int DIR_SaveOneCustomAttribute (const char *prefRoot, char *scratch, DIR_Server *server, DIR_AttributeId id)
  1679. {
  1680.     int err;
  1681.  
  1682.     const char *name = DIR_GetDefaultAttribute (id)->name;
  1683.     err = 0;
  1684.  
  1685.     if (server->customAttributes)
  1686.     {
  1687.         DIR_Attribute *attrib = NULL;
  1688.         XP_List *walkList = server->customAttributes;
  1689.         while ((attrib = XP_ListNextObject(walkList)) != NULL)
  1690.         {
  1691.             if (attrib->id == id)
  1692.             {
  1693.                 char *jsString = NULL;
  1694.                 if (0 == DIR_ConvertAttributeToPrefsString(attrib, &jsString))
  1695.                 {
  1696.                     DIR_SetStringPref (prefRoot, name, scratch, jsString, "");
  1697.                     XP_FREE(jsString);
  1698.                     return err;
  1699.                 }
  1700.             }
  1701.         }
  1702.  
  1703.     }
  1704.  
  1705.     /* This server doesn't have a custom attribute for the requested ID
  1706.      * so set it to the null string just in case there's an ALL.JS setting
  1707.      * or had a previous user value
  1708.      */
  1709.     DIR_SetStringPref (prefRoot, name, scratch, "", "");
  1710.  
  1711.     return err;
  1712. }
  1713.  
  1714.  
  1715. static int DIR_SaveCustomAttributes (const char *prefRoot, char *scratch, DIR_Server *server)
  1716. {
  1717.     int err;
  1718.     char *localScratch = (char*) XP_ALLOC(256);
  1719.     err = 0;
  1720.  
  1721.     XP_STRCPY (scratch, prefRoot);
  1722.     XP_STRCAT (scratch, "attributes.");
  1723.     if (localScratch)
  1724.     {
  1725.         DIR_SaveOneCustomAttribute (scratch, localScratch, server, cn);
  1726.         DIR_SaveOneCustomAttribute (scratch, localScratch, server, givenname);
  1727.         DIR_SaveOneCustomAttribute (scratch, localScratch, server, sn);
  1728.         DIR_SaveOneCustomAttribute (scratch, localScratch, server, mail);
  1729.         DIR_SaveOneCustomAttribute (scratch, localScratch, server, telephonenumber);
  1730.         DIR_SaveOneCustomAttribute (scratch, localScratch, server, o);
  1731.         DIR_SaveOneCustomAttribute (scratch, localScratch, server, ou);
  1732.         DIR_SaveOneCustomAttribute (scratch, localScratch, server, l);
  1733.         DIR_SaveOneCustomAttribute (scratch, localScratch, server, street);
  1734.         DIR_SaveOneCustomAttribute (scratch, localScratch, server, custom1);
  1735.         DIR_SaveOneCustomAttribute (scratch, localScratch, server, custom2);
  1736.         DIR_SaveOneCustomAttribute (scratch, localScratch, server, custom3);
  1737.         DIR_SaveOneCustomAttribute (scratch, localScratch, server, custom4);
  1738.         DIR_SaveOneCustomAttribute (scratch, localScratch, server, custom5);
  1739.         DIR_SaveOneCustomAttribute (scratch, localScratch, server, auth);
  1740.         XP_FREE(localScratch);
  1741.     }
  1742.     else
  1743.         err = MK_OUT_OF_MEMORY;
  1744.  
  1745.     return err;
  1746. }
  1747.  
  1748.  
  1749. static int DIR_SaveCustomFilters (const char *prefRoot, char *scratch, DIR_Server *server)
  1750. {
  1751.     int err;
  1752.     char *localScratch = (char*) XP_ALLOC(256);
  1753.     err = 0;
  1754.  
  1755.     XP_STRCPY (scratch, prefRoot);
  1756.     XP_STRCAT (scratch, "filter1.");
  1757.     if (server->customFilters)
  1758.     {
  1759.         /* Save the custom filters into the JS prefs */
  1760.         DIR_Filter *filter = NULL;
  1761.         XP_List *walkList = server->customFilters;
  1762.         if (localScratch)
  1763.         {
  1764.             while ((filter = XP_ListNextObject(walkList)) != NULL)
  1765.             {
  1766.                 DIR_SetBoolPref (scratch, "repeatFilterForWords", localScratch, 
  1767.                     (filter->flags & DIR_F_REPEAT_FILTER_FOR_TOKENS) != 0, kDefaultRepeatFilterForTokens);
  1768.                 DIR_SetStringPref (scratch, "string", localScratch, filter->string, kDefaultFilter);
  1769.             }
  1770.             XP_FREE(localScratch);
  1771.         }
  1772.         else
  1773.             err = MK_OUT_OF_MEMORY;
  1774.     }
  1775.     else
  1776.     {
  1777.         /* The DIR_Server object doesn't think it has any custom filters,
  1778.          * so make sure the prefs settings are empty too
  1779.          */
  1780.         DIR_SetBoolPref (scratch, "repeatFilterForWords", localScratch, 
  1781.             kDefaultRepeatFilterForTokens, kDefaultRepeatFilterForTokens);
  1782.         DIR_SetStringPref (scratch, "string", localScratch, kDefaultFilter, kDefaultFilter);
  1783.     }
  1784.  
  1785.     return err;
  1786. }
  1787.  
  1788.  
  1789. static int dir_SaveReplicationInfo (const char *prefRoot, char *scratch, DIR_Server *server)
  1790. {
  1791.     int err = 0;
  1792.     char *localScratch = (char*) XP_ALLOC(256);
  1793.     if (!localScratch)
  1794.         return MK_OUT_OF_MEMORY;
  1795.  
  1796.     XP_STRCPY (scratch, prefRoot);
  1797.     XP_STRCAT (scratch, "replication.");
  1798.  
  1799.     if (server->replInfo)
  1800.     {
  1801.         char *excludedList = NULL;
  1802.         int i;
  1803.         int excludedLength = 0;
  1804.         for (i = 0; i < server->replInfo->excludedAttributesCount; i++)
  1805.             excludedLength += XP_STRLEN (server->replInfo->excludedAttributes[i]) + 2; /* +2 for ", " */
  1806.         if (excludedLength)
  1807.         {
  1808.             excludedList = (char*) XP_ALLOC (excludedLength + 1);
  1809.             if (excludedList)
  1810.             {
  1811.                 excludedList[0] = '\0';
  1812.                 for (i = 0; i < server->replInfo->excludedAttributesCount; i++)
  1813.                 {
  1814.                     XP_STRCAT (excludedList, server->replInfo->excludedAttributes[i]);
  1815.                     XP_STRCAT (excludedList, ", ");
  1816.                 }
  1817.             }
  1818.             else
  1819.                 err = MK_OUT_OF_MEMORY;
  1820.         }
  1821.  
  1822.         DIR_SetStringPref (scratch, "excludedAttributes", scratch, excludedList, kDefaultReplicaExcludedAttributes);
  1823.  
  1824.         DIR_SetBoolPref (scratch, "enabled", localScratch, server->replInfo->enabled, kDefaultReplicaEnabled);
  1825.         DIR_SetStringPref (scratch, "description", localScratch, server->replInfo->description, kDefaultReplicaDescription);
  1826.         DIR_SetStringPref (scratch, "filter", localScratch, server->replInfo->filter, kDefaultReplicaFilter);
  1827.         DIR_SetIntPref (scratch, "lastChangeNumber", localScratch, server->replInfo->lastChangeNumber, kDefaultReplicaChangeNumber);
  1828.         DIR_SetIntPref (scratch, "generation", localScratch, server->replInfo->generation, kDefaultReplicaChangeNumberGeneration);
  1829.     }
  1830.  
  1831.     return err;
  1832. }
  1833.  
  1834.  
  1835. int DIR_SaveServerPreferences (XP_List *wholeList)
  1836. {
  1837.     int i;
  1838.     DIR_Server *s;
  1839.     char * prefstring = NULL;
  1840.     char * tempString = NULL;
  1841.  
  1842.     if (wholeList)
  1843.     {
  1844.         prefstring = (char *) XP_ALLOC(128);
  1845.         tempString = (char *) XP_ALLOC(256);
  1846.         if (prefstring && tempString) 
  1847.         {
  1848.             PREF_SetIntPref("ldap_1.number_of_directories", XP_ListCount (wholeList));    
  1849.  
  1850.             for (i = 1; i <= XP_ListCount(wholeList); i++)
  1851.             {
  1852.                 s = (DIR_Server*) XP_ListGetObjectNum (wholeList, i);
  1853.                 if (s)
  1854.                 {
  1855.                     XP_SPRINTF(prefstring, "ldap_1.directory%i.", i);
  1856.  
  1857.                     DIR_SetStringPref (prefstring, "description", tempString, s->description, "");
  1858.                     DIR_SetStringPref (prefstring, "serverName", tempString, s->serverName, "");
  1859.                     DIR_SetStringPref (prefstring, "searchBase", tempString, s->searchBase, "");
  1860.                     DIR_SetStringPref (prefstring, "filename", tempString, s->fileName, "");
  1861.                     if (s->port == 0)
  1862.                         s->port = s->isSecure ? LDAPS_PORT : LDAP_PORT;
  1863.                     DIR_SetIntPref (prefstring, "port", tempString, s->port, s->isSecure ? LDAPS_PORT : LDAP_PORT);
  1864.                     DIR_SetIntPref (prefstring, "maxHits", tempString, s->maxHits, kDefaultMaxHits);
  1865.                     DIR_SetBoolPref (prefstring, "isSecure", tempString, s->isSecure, FALSE);
  1866.                     DIR_SetBoolPref (prefstring, "saveResults", tempString, s->saveResults, TRUE);
  1867.                     DIR_SetBoolPref (prefstring, "efficientWildcards", tempString, s->efficientWildcards, TRUE);
  1868.                     DIR_SetStringPref (prefstring, "searchString", tempString, s->lastSearchString, "");
  1869.                     DIR_SetIntPref (prefstring, "dirType", tempString, s->dirType, (int) LDAPDirectory);
  1870.                     DIR_SetBoolPref (prefstring, "isOffline", tempString, s->isOffline, kDefaultIsOffline);
  1871.  
  1872.                     DIR_SetBoolPref (prefstring, "autoCompleteEnabled", tempString, DIR_TestFlag(s, DIR_AUTO_COMPLETE_ENABLED), kDefaultAutoCompleteEnabled);
  1873.                     DIR_SetBoolPref (prefstring, "utf8Disabled", tempString, DIR_TestFlag(s, DIR_UTF8_DISABLED), kDefaultUtf8Disabled);
  1874.  
  1875.                     DIR_SetBoolPref (prefstring, "enableAuth", tempString, s->enableAuth, kDefaultEnableAuth);
  1876.                     DIR_SetBoolPref (prefstring, "savePassword", tempString, s->savePassword, kDefaultSavePassword);
  1877.                     if (s->savePassword)
  1878.                     {
  1879.                         DIR_SetStringPref (prefstring, "authDn", tempString, s->authDn, "");
  1880.                         DIR_SetStringPref (prefstring, "password", tempString, s->password, "");
  1881.                     }
  1882.  
  1883.                     DIR_SaveCustomAttributes (prefstring, tempString, s);
  1884.                     DIR_SaveCustomFilters (prefstring, tempString, s);
  1885.                     dir_SaveReplicationInfo (prefstring, tempString, s);
  1886.  
  1887.                     DIR_SetStringPref (prefstring, "customDisplayUrl", tempString, s->customDisplayUrl, "");
  1888.                 }
  1889.             }
  1890.             XP_SPRINTF(tempString, "%i", tempString);
  1891.             PREF_SetCharPref("ldap_1.end_of_directories", tempString);
  1892.         } 
  1893.  
  1894.         XP_FREEIF (prefstring);
  1895.         XP_FREEIF (tempString);
  1896.     }
  1897.  
  1898.     return 0;
  1899. }
  1900.  
  1901. /*****************************************************************************
  1902.  * Functions for getting site-configurable preferences, from JavaScript if
  1903.  * the site admin has provided them, else out of thin air.
  1904.  */
  1905.  
  1906. static DIR_DefaultAttribute *DIR_GetDefaultAttribute (DIR_AttributeId id)
  1907. {
  1908.     int i = 0;
  1909.  
  1910.     static DIR_DefaultAttribute defaults[15];
  1911.     defaults[0].id = cn;
  1912.     defaults[0].resourceId = MK_LDAP_COMMON_NAME;
  1913.     defaults[0].name = "cn";
  1914.     
  1915.     defaults[1].id = givenname;
  1916.     defaults[1].resourceId = MK_LDAP_GIVEN_NAME;
  1917.     defaults[1].name = "givenName";
  1918.     
  1919.     defaults[2].id = sn;
  1920.     defaults[2].resourceId = MK_LDAP_SURNAME;
  1921.     defaults[2].name = "sn";
  1922.     
  1923.     defaults[3].id = mail;
  1924.     defaults[3].resourceId = MK_LDAP_EMAIL_ADDRESS;
  1925.     defaults[3].name = "mail";
  1926.     
  1927.     defaults[4].id = telephonenumber;
  1928.     defaults[4].resourceId = MK_LDAP_PHONE_NUMBER;
  1929.     defaults[4].name = "telephoneNumber";
  1930.     
  1931.     defaults[5].id = o;
  1932.     defaults[5].resourceId = MK_LDAP_ORGANIZATION;
  1933.     defaults[5].name = "o";
  1934.     
  1935.     defaults[6].id = ou;
  1936.     defaults[6].resourceId = MK_LDAP_ORG_UNIT;
  1937.     defaults[6].name = "ou";
  1938.     
  1939.     defaults[7].id = l;
  1940.     defaults[7].resourceId = MK_LDAP_LOCALITY;
  1941.     defaults[7].name = "l";
  1942.     
  1943.     defaults[8].id = street;
  1944.     defaults[8].resourceId = MK_LDAP_STREET;
  1945.     defaults[8].name = "street";
  1946.     
  1947.     defaults[9].id = custom1;
  1948.     defaults[9].resourceId = MK_LDAP_CUSTOM1;
  1949.     defaults[9].name = "custom1";
  1950.     
  1951.     defaults[10].id = custom2;
  1952.     defaults[10].resourceId = MK_LDAP_CUSTOM2;
  1953.     defaults[10].name = "custom2";
  1954.     
  1955.     defaults[11].id = custom3;
  1956.     defaults[11].resourceId = MK_LDAP_CUSTOM3;
  1957.     defaults[11].name = "custom3";
  1958.     
  1959.     defaults[12].id = custom4;
  1960.     defaults[12].resourceId = MK_LDAP_CUSTOM4;
  1961.     defaults[12].name = "custom4";
  1962.     
  1963.     defaults[13].id = custom5;
  1964.     defaults[13].resourceId = MK_LDAP_CUSTOM5;
  1965.     defaults[13].name = "custom5";
  1966.  
  1967.     defaults[14].id = auth;
  1968.     defaults[14].resourceId = MK_LDAP_EMAIL_ADDRESS;
  1969.     defaults[14].name = "mail";
  1970.  
  1971.     defaults[15].id = cn;
  1972.     defaults[15].resourceId = 0;
  1973.     defaults[15].name = NULL;
  1974.  
  1975.     while (defaults[i].name)
  1976.     {
  1977.         if (defaults[i].id == id)
  1978.             return &defaults[i];
  1979.         i++;
  1980.     }
  1981.  
  1982.     return NULL;
  1983. }
  1984.  
  1985. const char *DIR_GetAttributeName (DIR_Server *server, DIR_AttributeId id)
  1986. {
  1987.     char *result = NULL;
  1988.  
  1989.     /* First look in the custom attributes in case the attribute is overridden */
  1990.     XP_List *list = server->customAttributes;
  1991.     DIR_Attribute *walkList = NULL;
  1992.  
  1993.     while ((walkList = XP_ListNextObject(list)) != NULL)
  1994.     {
  1995.         if (walkList->id == id)
  1996.             result = walkList->prettyName;
  1997.     }
  1998.  
  1999.     /* If we didn't find it, look in our own static list of attributes */
  2000.     if (!result)
  2001.     {
  2002.         DIR_DefaultAttribute *def;
  2003.         if ((def = DIR_GetDefaultAttribute(id)) != NULL)
  2004.             result = XP_GetString(def->resourceId);
  2005.     }
  2006.  
  2007.     return result;
  2008. }
  2009.  
  2010.  
  2011. const char **DIR_GetAttributeStrings (DIR_Server *server, DIR_AttributeId id)
  2012. {
  2013.     const char **result = NULL;
  2014.  
  2015.     /* First look in the custom attributes in case the attribute is overridden */
  2016.     XP_List *list = server->customAttributes;
  2017.     DIR_Attribute *walkList = NULL;
  2018.  
  2019.     while ((walkList = XP_ListNextObject(list)) != NULL)
  2020.     {
  2021.         if (walkList->id == id)
  2022.             result = (const char**)walkList->attrNames;
  2023.     }
  2024.  
  2025.     /* If we didn't find it, look in our own static list of attributes */
  2026.     if (!result)
  2027.     {
  2028.         static const char *array[2];
  2029.         array[0] = DIR_GetDefaultAttribute(id)->name;
  2030.         array[1] = NULL;
  2031.         result = (const char**)array;
  2032.     }
  2033.     return result;
  2034. }
  2035.  
  2036.  
  2037. const char *DIR_GetFirstAttributeString (DIR_Server *server, DIR_AttributeId id)
  2038. {
  2039.     const char **array = DIR_GetAttributeStrings (server, id);
  2040.     return array[0];
  2041. }
  2042.  
  2043.  
  2044. const char *DIR_GetFilterString (DIR_Server *server)
  2045. {
  2046.     DIR_Filter *filter = XP_ListTopObject (server->customFilters);
  2047.     if (filter)
  2048.         return filter->string;
  2049.     return NULL;
  2050. }
  2051.  
  2052.  
  2053. static DIR_Filter *DIR_LookupFilter (DIR_Server *server, const char *filter)
  2054. {
  2055.     XP_List *list = server->customFilters;
  2056.     DIR_Filter *walkFilter = NULL;
  2057.  
  2058.     while ((walkFilter = XP_ListNextObject(list)) != NULL)
  2059.         if (!XP_STRCASECMP(filter, walkFilter->string))
  2060.             return walkFilter;
  2061.  
  2062.     return NULL;
  2063. }
  2064.  
  2065.  
  2066. XP_Bool DIR_RepeatFilterForTokens (DIR_Server *server, const char *filter)
  2067. {
  2068.     const DIR_Filter *filterStruct = DIR_LookupFilter (server, filter);
  2069.     if (filterStruct)
  2070.         return (filterStruct->flags & DIR_F_REPEAT_FILTER_FOR_TOKENS) != 0;
  2071.  
  2072.     return kDefaultRepeatFilterForTokens;
  2073. }
  2074.  
  2075.  
  2076. XP_Bool DIR_SubstStarsForSpaces (DIR_Server *server, const char *filter)
  2077. {
  2078.     const DIR_Filter *filterStruct = DIR_LookupFilter (server, filter);
  2079.     if (filterStruct)
  2080.         return (filterStruct->flags & DIR_F_SUBST_STARS_FOR_SPACES) != 0;
  2081.  
  2082.     return kDefaultSubstStarsForSpaces;
  2083. }
  2084.  
  2085.  
  2086. const char *DIR_GetTokenSeparators (DIR_Server *server)
  2087. {
  2088.     return server->tokenSeps ? server->tokenSeps : kDefaultTokenSeps;
  2089. }
  2090.  
  2091. XP_Bool DIR_UseCustomAttribute (DIR_Server *server, DIR_AttributeId id)
  2092. {
  2093.     XP_List *list = server->customAttributes;
  2094.     DIR_Attribute *walkList = NULL;
  2095.  
  2096.     while ((walkList = XP_ListNextObject(list)) != NULL)
  2097.     {
  2098.         if (walkList->id == id)
  2099.             return TRUE;
  2100.     }
  2101.     return FALSE;
  2102. }
  2103.  
  2104.  
  2105. XP_Bool DIR_IsDnAttribute (DIR_Server *s, const char *attrib)
  2106. {
  2107.     if (s && s->dnAttributes)
  2108.     {
  2109.         /* Look in the server object to see if there are prefs to tell
  2110.          * us which attributes contain DNs
  2111.          */
  2112.         int i;
  2113.         for (i = 0; i < s->dnAttributesCount; i++)
  2114.         {
  2115.             if (!XP_STRCASECMP(attrib, s->dnAttributes[i]))
  2116.                 return TRUE;
  2117.         }
  2118.     }
  2119.     else
  2120.     {
  2121.         /* We have some default guesses about what attributes 
  2122.          * are likely to contain DNs 
  2123.          */
  2124.         switch (XP_TO_LOWER(attrib[0]))
  2125.         {
  2126.         case 'm':
  2127.             if (!XP_STRCASECMP(attrib, "manager") || 
  2128.                 !XP_STRCASECMP(attrib, "member"))
  2129.                 return TRUE;
  2130.             break;
  2131.         case o:
  2132.             if (!XP_STRCASECMP(attrib, "owner"))
  2133.                 return TRUE;
  2134.             break;
  2135.         case 'u':
  2136.             if (!XP_STRCASECMP(attrib, "uniquemember"))
  2137.                 return TRUE;
  2138.             break;
  2139.         }
  2140.     }
  2141.     return FALSE;
  2142.  
  2143. }
  2144.  
  2145.  
  2146. XP_Bool DIR_IsAttributeExcludedFromHtml (DIR_Server *s, const char *attrib)
  2147. {
  2148.     if (s && s->suppressedAttributes)
  2149.     {
  2150.         /* Look in the server object to see if there are prefs to tell
  2151.          * us which attributes shouldn't be shown in HTML
  2152.          */
  2153.         int i;
  2154.         for (i = 0; i < s->suppressedAttributesCount; i++)
  2155.         {
  2156.             if (!XP_STRCASECMP(attrib, s->suppressedAttributes[i]))
  2157.                 return TRUE;
  2158.         }
  2159.     }
  2160.     /* else don't exclude it. By default we show everything */
  2161.  
  2162.     return FALSE;
  2163. }
  2164.  
  2165.  
  2166. static void dir_PushStringToPrefs (DIR_Server *s, char **curVal, const char *newVal, const char *name)
  2167. {
  2168.     XP_List *servers = NULL;
  2169.     XP_List *walkList = NULL;
  2170.     DIR_Server *walkServer = NULL;
  2171.     XP_Bool found = FALSE;
  2172.     int idx = 0;
  2173.  
  2174.     /* Don't do anything if we already have a value and it's the same as the new one */
  2175.     if (curVal && *curVal)
  2176.     {
  2177.         if (!XP_STRCMP(*curVal, newVal))
  2178.             return;
  2179.     }
  2180.  
  2181.     /* Find the server in the list so we can get its index.
  2182.      * Can't use XP_GetNumFromObject because this DIR_Server isn't guaranteed
  2183.      * to be in the FE's list -- it may be from a copy of the FE's list
  2184.      */
  2185.     walkList = FE_GetDirServers ();
  2186.     while (!found)
  2187.     {
  2188.         walkServer = (DIR_Server*) XP_ListNextObject (walkList);
  2189.         if (!walkServer)
  2190.             break;
  2191.         found = DIR_AreServersSame (walkServer, s);
  2192.         idx++;
  2193.     }
  2194.  
  2195.     if (found)
  2196.     {
  2197.         /* Build the name of the prefs string */
  2198.         char buf[512];
  2199.         char *prefRoot = PR_smprintf ("ldap_1.directory%d.", idx);
  2200.  
  2201.         /* Set into the prefs */
  2202.         if (prefRoot)
  2203.         {
  2204.             *curVal = XP_STRDUP(newVal);
  2205.             DIR_SetStringPref (prefRoot, name, buf, *curVal, "");
  2206.  
  2207.             XP_FREE(prefRoot);
  2208.         }
  2209.     }
  2210.  
  2211. }
  2212.  
  2213.  
  2214. void DIR_SetAuthDN (DIR_Server *s, const char *dn)
  2215. {
  2216.     dir_PushStringToPrefs (s, &(s->authDn), dn, "authDn");
  2217. }
  2218.  
  2219.  
  2220. void DIR_SetPassword (DIR_Server *s, const char *password)
  2221. {
  2222.     dir_PushStringToPrefs (s, &(s->password), password, "password");
  2223. }
  2224.  
  2225.  
  2226. XP_Bool DIR_IsEscapedAttribute (DIR_Server *s, const char *attrib)
  2227. {
  2228.     /* We're not exposing this setting in JS prefs right now, but in case we
  2229.      * might want to in the future, leave the DIR_Server* in the prototype.
  2230.      */
  2231.  
  2232.     switch (XP_TO_LOWER(attrib[0]))
  2233.     {
  2234.     case 'p':
  2235.         if (!XP_STRCASECMP(attrib, "postaladdress"))
  2236.             return TRUE;
  2237.         break;
  2238.     case 'f': 
  2239.         if (!XP_STRCASECMP(attrib, "facsimiletelephonenumber"))
  2240.             return TRUE;
  2241.         break;
  2242.     case 'o':
  2243.         if (!XP_STRCASECMP(attrib, "othermail"))
  2244.             return TRUE;
  2245.         break;
  2246.     }
  2247.     return FALSE;
  2248. }
  2249.  
  2250.  
  2251. char *DIR_Unescape (const char *src, XP_Bool makeHtml)
  2252. {
  2253. /* Borrowed from libnet\mkparse.c */
  2254. #define UNHEX(C) \
  2255.     ((C >= '0' && C <= '9') ? C - '0' : \
  2256.     ((C >= 'A' && C <= 'F') ? C - 'A' + 10 : \
  2257.     ((C >= 'a' && C <= 'f') ? C - 'a' + 10 : 0)))
  2258.  
  2259.     char *dest = NULL;
  2260.     int destLength = 0;
  2261.  
  2262.     int dollarCount = 0;
  2263.     int convertedLengthOfDollar = makeHtml ? 4 : 1;
  2264.  
  2265.     const char *tmpSrc = src;
  2266.  
  2267.     while (*tmpSrc)
  2268.         if (*tmpSrc++ == '$')
  2269.             dollarCount++;
  2270.  
  2271.     destLength = XP_STRLEN(src) + (dollarCount * convertedLengthOfDollar);
  2272.     dest = (char*) XP_ALLOC (destLength + 1);
  2273.     if (dest)
  2274.     {
  2275.         char *tmpDst = dest;
  2276.         *dest = '\0';
  2277.         tmpSrc = src;
  2278.  
  2279.         while (*tmpSrc)
  2280.         {
  2281.             switch (*tmpSrc)
  2282.             {
  2283.             case '$':
  2284.                 /* A dollar sign is a linebreak. This is easy for HTML, but if we're converting
  2285.                  * for the Address Book or something without multiple lines, just put in a space
  2286.                  */
  2287.                 if (makeHtml)
  2288.                 {
  2289.                     *tmpDst++ = '<';
  2290.                     *tmpDst++ = 'B';
  2291.                     *tmpDst++ = 'R';
  2292.                     *tmpDst++ = '>';
  2293.                 }
  2294.                 else
  2295.                     *tmpDst++ = ' ';
  2296.                 break;
  2297.             case '\\': {
  2298.                 /* A backslash indicates that two hex digits follow, which we're supposed to
  2299.                  * convert. The spec sez that '$', '#' and '\'' (single quote) must be encoded
  2300.                  * this way. 
  2301.                  */
  2302.                 XP_Bool didEscape = FALSE;
  2303.                 char c1 = *(tmpSrc + 1);
  2304.                 if (c1 && (XP_IS_DIGIT(c1) || XP_IS_ALPHA(c1)))
  2305.                 {
  2306.                     char c2 = *(tmpSrc + 2);
  2307.                     if (c2 && (XP_IS_DIGIT(c2) || XP_IS_ALPHA(c2)))
  2308.                     {
  2309.                         *tmpDst++ = (UNHEX(c1) << 4) | UNHEX(c2);
  2310.                         tmpSrc +=2;
  2311.                         didEscape = TRUE;
  2312.                     }
  2313.                 }
  2314.                 if (!didEscape)
  2315.                     *tmpDst++ = *tmpSrc;
  2316.             }
  2317.             break;
  2318.             default:
  2319.                 /* Just a plain old char -- copy it over */
  2320.                 *tmpDst++ = *tmpSrc;
  2321.             }
  2322.             tmpSrc++;
  2323.         }
  2324.         *tmpDst = '\0';
  2325.     }
  2326.  
  2327.     return dest;
  2328. }
  2329.  
  2330.  
  2331. /*****************************************************************************
  2332.  * Functions for building a secure connection to LDAP servers
  2333.  *
  2334.  * Use of PR_CALLBACK is required for Win16 because the socket API functions
  2335.  * ultimately call into MOZOCK, which has DS-resident global variables. Ick.
  2336.  */
  2337.  
  2338. #ifdef MOZ_LDAP
  2339.  
  2340. HG29989
  2341.  
  2342. int DIR_ValidateRootDSE (DIR_Server *server, int32 gen, int32 first, int32 last)
  2343. {
  2344.     /* Here we validate the replication info that the server has against the
  2345.      * state of the local replica as stored in JS prefs. 
  2346.      */
  2347.  
  2348.     XP_ASSERT(server && server->replInfo);
  2349.     if (!server || !server->replInfo)
  2350.         return -1;
  2351.  
  2352.     /* The generation of the server's DB is different than when we last
  2353.      * saw it, which means that the first and last change number we know
  2354.      * are totally meaningless.
  2355.      */
  2356.     if (gen != server->replInfo->generation)
  2357.         return MK_LDAP_REPL_CANT_SYNC_REPLICA;
  2358.  
  2359.     /* Some changes have come and gone on the server since we last 
  2360.      * replicated. Since we have no way to know what those changes were,
  2361.      * we have no way to get sync'd up with the current server state
  2362.      */
  2363.     if (first > server->replInfo->lastChangeNumber)
  2364.         return MK_LDAP_REPL_CANT_SYNC_REPLICA;
  2365.  
  2366.     /* We appear to have already replicated changes that the server
  2367.      * hasn't made yet. Not likely
  2368.      */
  2369.     if (last < server->replInfo->lastChangeNumber)
  2370.         return MK_LDAP_REPL_CANT_SYNC_REPLICA;
  2371.  
  2372.     return 0;
  2373. }
  2374.  
  2375.  
  2376. #define DIR_AUTO_COMPLETE_ENABLED 0x00000001
  2377. #define DIR_ENABLE_AUTH           0x00000002
  2378. #define DIR_SAVE_PASSWORD         0x00000004
  2379. #define DIR_UTF8_DISABLED         0x00000008
  2380. #define DIR_IS_SECURE             0x00000010
  2381. #define DIR_SAVE_RESULTS          0x00000020
  2382. #define DIR_EFFICIENT_WILDCARDS   0x00000040
  2383.  
  2384. void DIR_SetAutoCompleteEnabled (XP_List *list, DIR_Server *server, XP_Bool enabled)
  2385. {
  2386.     XP_ASSERT(server); /*list can be null*/
  2387.     if (server)
  2388.     {
  2389.         DIR_Server *tmp;
  2390.  
  2391.         if (enabled)
  2392.         {
  2393.             while (NULL != (tmp = XP_ListNextObject(list)))
  2394.                 tmp->flags &= ~DIR_AUTO_COMPLETE_ENABLED;
  2395.             server->flags |= DIR_AUTO_COMPLETE_ENABLED;
  2396.         }
  2397.         else
  2398.             server->flags &= ~DIR_AUTO_COMPLETE_ENABLED;
  2399.     }
  2400. }
  2401.  
  2402. XP_Bool DIR_TestFlag (DIR_Server *server, uint32 flag)
  2403. {
  2404.     if (server)
  2405.         return 0 != (server->flags & flag);
  2406.     return FALSE;
  2407. }
  2408.  
  2409. void DIR_SetFlag (DIR_Server *server, uint32 flag)
  2410. {
  2411.     XP_ASSERT(server);
  2412.     if (server)
  2413.         server->flags |= flag;
  2414. }
  2415.  
  2416. void DIR_ClearFlag (DIR_Server *server, uint32 flag)
  2417. {
  2418.     XP_ASSERT(server);
  2419.     if (server)
  2420.         server->flags &= ~flag;
  2421. }
  2422.  
  2423.  
  2424. void DIR_ForceFlag (DIR_Server *server, uint32 flag, XP_Bool setIt)
  2425. {
  2426.     XP_ASSERT(server);
  2427.     if (server)
  2428.     {
  2429.         if (setIt)
  2430.             server->flags |= flag;
  2431.         else
  2432.             server->flags &= ~flag;
  2433.     }
  2434. }
  2435.  
  2436.  
  2437. /* Centralize this charset conversion so everyone can do the UTF8 conversion
  2438.  * in the same way. Also, if someone ever makes us do T.61 or some other silly
  2439.  * thing, we can use these bottlenecks
  2440.  */
  2441.  
  2442. char *DIR_ConvertToServerCharSet (DIR_Server *server, char *src, int16 srcCsid)
  2443. {
  2444.     if (server && (server->flags & DIR_UTF8_DISABLED))
  2445.         return XP_STRDUP (src);
  2446.     else
  2447.         return (char*) INTL_ConvertLineWithoutAutoDetect (srcCsid, CS_UTF8, (unsigned char*) src, XP_STRLEN(src));
  2448. }
  2449.  
  2450. char *DIR_ConvertFromServerCharSet (DIR_Server *server, char *src, int16 destCsid)
  2451. {
  2452.     if (server && (server->flags & DIR_UTF8_DISABLED))
  2453.         return XP_STRDUP (src);
  2454.     else
  2455.         return (char*) INTL_ConvertLineWithoutAutoDetect (CS_UTF8, destCsid, (unsigned char*) src, XP_STRLEN(src));
  2456. }
  2457.  
  2458.  
  2459. char *DIR_BuildUrl (DIR_Server *server, const char *dn, XP_Bool forAddToAB)
  2460. {
  2461.     char *url = NULL;
  2462.     char *escapedDn = NET_Escape (dn, URL_XALPHAS);
  2463.     if (escapedDn)
  2464.     {
  2465.         if (!forAddToAB && server->customDisplayUrl && server->customDisplayUrl[0])
  2466.         {
  2467.             /* Allow users to customize the URL we run when we open an LDAP entry. This
  2468.              * is intended to appease the people who want extensive customization of the
  2469.              * HTML we generate for LDAP. We're sidestepping the issue by allowing them
  2470.              * to easily plug in DSGW, the LDAP-to-HTTP gateway, which already has
  2471.              * very extensive template support.
  2472.              */
  2473.             url = PR_smprintf (server->customDisplayUrl, escapedDn);
  2474.         }
  2475.         else
  2476.         {
  2477.             /* The default case, where we run an LDAP URL in a browser window 
  2478.              */
  2479.             char *urlTemplate = "%s//%s/%s";
  2480.             char *urlPortTemplate = "%s//%s:%d/%s";
  2481.             char *urlScheme = NULL;
  2482.             int port = server->port;
  2483.             int standardPort = server->isSecure ? LDAPS_PORT : LDAP_PORT;
  2484.  
  2485.             if (server->isSecure)
  2486.                 urlScheme = forAddToAB ? "addbook-ldaps:" : "ldaps:";
  2487.             else
  2488.                 urlScheme = forAddToAB ? "addbook-ldap:" : "ldap:";
  2489.  
  2490.             if (port == standardPort)
  2491.                 url = PR_smprintf (urlTemplate, urlScheme, server->serverName, escapedDn);
  2492.             else
  2493.                 url = PR_smprintf (urlPortTemplate, urlScheme, server->serverName, port, escapedDn);
  2494.  
  2495.         }
  2496.         XP_FREE (escapedDn);
  2497.     }
  2498.     return url;
  2499. }
  2500.  
  2501.  
  2502. #endif /* MOZ_LDAP */
  2503.  
  2504.  
  2505. #endif /* #if !defined(MOZADDRSTANDALONE) */
  2506.