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

  1. /* -*- Mode: C++; tab-width: 8; 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.  
  20. #include "xp.h"
  21. #include "prmon.h"
  22.  
  23. #ifdef NSPR20
  24. #ifdef XP_MAC
  25. #include "prpriv.h"
  26. #else
  27. #include "private/prpriv.h"
  28. #endif
  29. #endif
  30.  
  31. #ifdef XP_UNIX
  32. #include <fcntl.h>
  33. #include "prefapi.h"
  34. #endif
  35.  
  36. #ifdef XP_MAC
  37. #include "xp_file_mac.h"
  38. #endif
  39. /* for ldap filenames - benjie
  40. #define _XP_TMP_FILENAME_FOR_LDAP_ 
  41. */
  42.  
  43. XP_BEGIN_PROTOS
  44.  
  45.  
  46. #if defined (XP_MAC) || defined(XP_UNIX)
  47. /* Now that Mac is using stdio, we can share some of this.  Yay.
  48.    Presumably Windows can share this too, but they keep these
  49.    functions in the FE, so I don't know.
  50.  */
  51.  
  52.  
  53. int XP_Stat( const char* name, XP_StatStruct * outStat,  XP_FileType type )
  54. {
  55.     int        result = 0;
  56.     
  57.     char* newName = WH_FileName( name, type );
  58.     if (!newName) return -1;
  59.     result = stat( newName, outStat );
  60.     XP_FREE(newName);
  61.     return result;
  62. }
  63.  
  64. XP_File XP_FileOpen( const char* name, XP_FileType type,
  65.                      const XP_FilePerm permissions )
  66. {
  67.   char* newName = WH_FileName(name, type);
  68.   XP_File result;
  69. #ifdef XP_UNIX
  70.   XP_StatStruct st;
  71.   XP_Bool make_private_p = FALSE;
  72. #endif
  73.  
  74.   /* One should never open newsrc for output directly. */
  75.   XP_ASSERT (type != xpNewsRC || type != xpSNewsRC ||
  76.              !strchr (permissions, 'w'));
  77.  
  78.   if (newName == NULL)
  79.     return NULL;
  80.  
  81. #ifdef XP_UNIX
  82.   switch (type)
  83.     {
  84.       /* These files are always private: if the user chmods them, we
  85.          make them -rw------ again the next time we use them, because
  86.          it's really important.
  87.        */
  88.     case xpHTTPCookie:
  89.     case xpKeyChain:
  90.     case xpSignedAppletDB:
  91.     case xpSARCache:
  92.     case xpSARCacheIndex:        
  93.     case xpCertDB:
  94.     case xpCertDBNameIDX:
  95.     case xpKeyDB:
  96.     case xpSecModuleDB:
  97.       /* Always make tmp files private, because of their short lifetime. */
  98.     case xpTemporary:
  99.     case xpTemporaryNewsRC:
  100.     case xpFileToPost:
  101.     case xpPKCS12File:
  102.       if (strchr (permissions, 'w'))     /* opening for output */
  103.         make_private_p = TRUE;
  104.       break;
  105.  
  106.       /* These files are created private, but if the user then goes and
  107.          chmods them, we let their changes stick, because it's reasonable
  108.          for a user to decide to give away read permission on these
  109.          (though by default, it makes sense for them to be more private
  110.          than the user's other files.)
  111.        */
  112.     case xpCacheFAT:
  113.     case xpCache:
  114.     case xpRegistry:
  115.     case xpGlobalHistory:
  116.     case xpHotlist:
  117.     case xpBookmarks:
  118.     case xpMailFolder:
  119.       if (strchr (permissions, 'w') &&   /* opening for output */
  120.           XP_Stat (newName, &st, type))  /* and it doesn't exist yet */
  121.         make_private_p = TRUE;
  122.       break;
  123.  
  124.  
  125.     case xpProxyConfig:
  126.     case xpSocksConfig:
  127.     case xpNewsRC:
  128.     case xpSNewsRC:
  129.     case xpNewsgroups:
  130.     case xpSNewsgroups:
  131.     case xpURL:
  132.     case xpMimeTypes:
  133.     case xpSignature:
  134.     case xpMailFolderSummary:
  135.     case xpFolderCache:
  136.     case xpJSMailFilters:
  137.     case xpJSHTMLFilters:
  138.     case xpMailSort:
  139.     case xpNewsSort:
  140.     case xpMailPopState:
  141.     case xpMailFilterLog:
  142.     case xpNewsFilterLog:
  143.     case xpExtCache:
  144.     case xpExtCacheIndex:
  145.     case xpXoverCache:
  146.     case xpMailSubdirectory:
  147.  
  148.     case xpVCardFile:
  149.     case xpLDIFFile:
  150.     case xpAddrBook:
  151.     case xpAddrBookNew:
  152.     case xpJSCookieFilters:
  153.       /* These files need not be more private than any other, so we
  154.          always create them with the default umask. */
  155.       break;
  156.     default:
  157.       XP_ASSERT(0);
  158.     }
  159. #endif /* XP_UNIX */
  160.  
  161. #ifndef MCC_PROXY
  162.   /* At this point, we'd better have an absolute path, because passing a
  163.      relative path to fopen() is undefined.  (For the client, at least -
  164.      I gather the proxy is different?) */
  165. #endif/* !MCC_PROXY */
  166.  
  167.   result = fopen(newName, permissions);
  168.   
  169. #ifdef XP_MAC
  170.      if (result != 0)
  171.      {
  172.          int err;
  173.          
  174.          err = setvbuf(    result,         /* file to buffer */
  175.                          NULL,            /* allocate the buffer for us */
  176.                          _IOFBF,         /* fully buffer */
  177.                          8 * 1024);        /* 8k buffer */
  178.                          
  179.         XP_ASSERT(err == 0);                         
  180.      }
  181. #endif  
  182.  
  183. #ifdef XP_UNIX
  184.   if (make_private_p && result)
  185. #ifdef SCO_SV
  186.     chmod (newName, S_IRUSR | S_IWUSR); /* rw only by owner */
  187. #else
  188.     fchmod (fileno (result), S_IRUSR | S_IWUSR); /* rw only by owner */
  189. #endif
  190. #endif /* XP_UNIX */
  191.  
  192.   XP_FREE(newName);
  193.   return result; 
  194. }
  195.  
  196. extern XP_Bool XP_FileNameContainsBadChars (const char *name)
  197. {
  198. #ifdef XP_MAC
  199.     char *badChars = ":";
  200. #else /*XP_UNIX*/
  201.     char *badChars = "/";
  202. #endif
  203.     int i, j;
  204.     for (i = 0; i < XP_STRLEN(name); i++)
  205.         for (j = 0; j < XP_STRLEN(badChars); j++)
  206.             if (name[i] == badChars[j])
  207.                 return TRUE;
  208.     return FALSE;
  209. }
  210.  
  211. #endif /* XP_MAC || XP_UNIX */
  212.  
  213. #ifdef XP_UNIX
  214.  
  215. /* This is just like fclose(), except that it does fflush() and fsync() first,
  216.    to ensure that the bits have made it to the disk before we return.
  217.  */
  218. int XP_FileClose(XP_File file)
  219. {
  220.   int filedes;
  221.  
  222.   /* This busniess with `status' and `err' is an attempt to preserve the
  223.      very first non-0 errno we get, while still proceeding to close the file
  224.      if the fflush/fsync failed for some (weird?) reason. */
  225.   int status, err = 0;
  226.   XP_ASSERT(file);
  227.   if (!file) return -1;
  228.   status = fflush(file);              /* Push the stdio buffer to the disk. */
  229.   if (status != 0) err = errno;
  230.  
  231.   filedes = XP_Fileno (file);
  232.   /*
  233.    * Only fsync when the file is not read-only, otherwise
  234.    * HPUX and IRIX return an error, and Linux syncs the disk anyway.
  235.    */
  236.   if (fcntl(filedes, F_GETFL) != O_RDONLY) {
  237.     status = fsync(filedes);   /* Wait for disk buffers to go out. */
  238.     if (status != 0 && err == 0) err = errno;
  239.   }
  240.  
  241.   status = fclose(file);              /* Now close it. */
  242.   if (status != 0 && err == 0) err = errno;
  243.  
  244.   errno = err;
  245.   return status ? status : err ? -1 : 0;
  246. }
  247.  
  248. #endif /* XP_UNIX */
  249.  
  250.  
  251. XP_END_PROTOS
  252.  
  253. #ifdef XP_UNIX
  254.  
  255. #include <unistd.h>        /* for getpid */
  256.  
  257. #ifdef TRACE
  258. #define Debug 1
  259. #define DO_TRACE(x) if (xp_file_debug) XP_TRACE(x)
  260.  
  261.  
  262. int xp_file_debug = 0;
  263. #else
  264. #define DO_TRACE(x)
  265. #endif
  266.  
  267. int XP_FileRemove(const char * name, XP_FileType type)
  268. {
  269.     char * newName = WH_FileName(name, type);
  270.     int result;
  271.     if (!newName) return -1;
  272.     result = remove(newName);
  273.     XP_FREE(newName);
  274.     if (result != 0)
  275.     {
  276.       /* #### Uh, what is this doing?  Of course errno is set! */
  277.         int err = errno;
  278.         if (err != 0)
  279.             return -1;
  280.     }
  281.     
  282.     return result;
  283. }
  284.  
  285.  
  286. int XP_FileRename(const char * from, XP_FileType fromtype,
  287.                   const char * to, XP_FileType totype)
  288. {
  289.     char * fromName = WH_FileName(from, fromtype);
  290.     char * toName = WH_FileName(to, totype);
  291.     int res = 0;
  292.     if (fromName && toName)
  293.         res = rename(fromName, toName);
  294.     else
  295.         res = -1;
  296.     if (fromName)
  297.         XP_FREE(fromName);
  298.     if (toName)
  299.         XP_FREE(toName);
  300.     return res;
  301. }
  302.  
  303.  
  304. /* Create a new directory */
  305.  
  306. int XP_MakeDirectory(const char* name, XP_FileType type)
  307. {
  308.   int result;
  309.   static XP_Bool madeXoverDir = FALSE;
  310.   mode_t mode;
  311.   switch (type) {
  312.   case xpMailFolder:
  313.     mode = 0700;
  314.     break;
  315.   default:
  316.     mode = 0755;
  317.     break;
  318.   }
  319.   if (type == xpXoverCache) {
  320.     /* Once per session, we'll check that the xovercache directory is
  321.        created before trying to make any subdirectories of it.  Sigh. ###*/
  322.     if (!madeXoverDir) {
  323.       madeXoverDir = TRUE;
  324.       XP_MakeDirectory("", type);
  325.     }
  326.   }
  327. #ifdef __linux
  328.   {
  329.     /* Linux is a chokes if the parent of the
  330.        named directory is a symbolic link. */
  331.     char rp[MAXPATHLEN];
  332.     char *s, *s0 = WH_FileName (name, type);
  333.     if (!s0) return -1;
  334.  
  335.     /* realpath is advertised to return a char* (rp) on success, and on
  336.        failure, return 0, set errno, and leave a partial path in rp.
  337.        But on Linux 1.2.3, it doesn't -- it returns 0, leaves the result
  338.        in rp, and doesn't set errno.  So, if errno is unset, assume all
  339.        is well.
  340.      */
  341.     rp[0] = 0;
  342.     errno = 0;
  343.     s = realpath (s0, rp);
  344.     XP_FREE(s0);
  345.     /* WTF??? if (errno) return -1; */
  346.     if (!s) s = rp;
  347.     if (!*s) return -1;
  348.     result = mkdir (s, mode);
  349.   }
  350. #elif defined(SUNOS4)
  351.   {
  352.     char rp[MAXPATHLEN];
  353.     char *s = WH_FileName (name, type);
  354.     char *tmp;
  355.     if (!s) return -1;
  356.  
  357.     /* Take off all trailing slashes, because some systems (SunOS 4.1.2)
  358.        don't think mkdir("/tmp/x/") means mkdir("/tmp/x"), sigh... */
  359.     PR_snprintf (rp, MAXPATHLEN-1, "%s", s);
  360.     XP_FREE(s);
  361.     while ((tmp = XP_STRRCHR(rp, '/')) && tmp[1] == '\0')
  362.       *tmp = '\0';
  363.  
  364.     result = mkdir (rp, mode);
  365.   }
  366. #else /* !__linux && !SUNOS4 */
  367.   DO_TRACE(("XP_MakeDirectory called: creating: %s", name));
  368.   {
  369.       char* filename = WH_FileName(name, type);
  370.       if (!filename) return -1;
  371.       result = mkdir(filename, mode);
  372.       XP_FREE(filename);
  373.   }
  374. #endif
  375.   return result;
  376. }
  377.  
  378. int XP_RemoveDirectory (const char *name, XP_FileType type)
  379. {
  380.   char *tmp = WH_FileName(name, type);
  381.   int ret;
  382.   if (!tmp) return -1;
  383.   ret = rmdir(tmp);
  384.   XP_FREE(tmp);
  385.   return ret;
  386. }
  387.  
  388. /*
  389. ** This function deletes a directory and everything under it.
  390. ** Deleting directories with "non-file" files, such as links,
  391. ** will produce behavior of XP_RemoveFile, since that's what is
  392. ** ultimately called.
  393. **
  394. ** Return values: zero on failure, non-zero for success.
  395. */
  396. int XP_RemoveDirectoryRecursive(const char *name, XP_FileType type)
  397. {
  398.     XP_DirEntryStruct *entry;
  399.     XP_StatStruct     statbuf;
  400.     int            status;
  401.     char*        child;
  402.     char*         dot    = ".";
  403.     char*         dotdot = "..";
  404.     int            ret = 1;
  405.  
  406.     XP_Dir dir = XP_OpenDir(name, type);  
  407.     if (!dir) return 0;
  408.  
  409.     /*
  410.     ** Go through the directory entries and delete appropriately
  411.     */
  412.     while ((entry = XP_ReadDir(dir)))
  413.     {
  414.         /*
  415.         ** Allocate space for current name + path separator + directory name  + NULL
  416.         */
  417.         child = XP_ALLOC( strlen(name) + 2 + strlen(entry->d_name) );
  418.  
  419.         XP_STRCAT(child,"/");
  420.         XP_STRCAT(child,entry->d_name);
  421.  
  422.         if (!(status = XP_Stat(child, &statbuf, type)))
  423.         {
  424.             if (entry->d_name == dot || entry->d_name == dotdot)
  425.             {
  426.                 /* Do nothing, rmdir will clean these up */
  427.             }
  428.             else
  429.                 if (S_ISDIR(statbuf.st_mode))
  430.                 {
  431.                     /* Recursive call to clean out subdirectory */
  432.                     if (!XP_RemoveDirectoryRecursive(child, type))
  433.                         ret = 0;
  434.                 }
  435.                     else
  436.                     {
  437.                         /* Everything that's not a directory is a file! */
  438.                         if (XP_FileRemove(child, type) != 0)
  439.                             ret = 0;
  440.                     }
  441.         }
  442.  
  443.         XP_FREE(child);
  444.     }
  445.  
  446.     /* OK, remove the top-level directory if we can */
  447.     if (XP_RemoveDirectory(name, type) != 0)
  448.         ret = 0;
  449.  
  450.     XP_CloseDir(dir);
  451.  
  452.     return ret;
  453. }
  454.  
  455.  
  456. int XP_FileTruncate(const char* name, XP_FileType type, int32 length)
  457. {
  458.   char* filename = WH_FileName(name, type);
  459.   int result = 0;
  460.   if (!filename) return -1;
  461.   result = truncate(filename, length);
  462.   XP_FREE(filename);
  463.   return result;
  464. }
  465.  
  466.  
  467.  
  468. /* Writes to a file
  469.  */
  470. int XP_FileWrite (const void* source, int32 count, XP_File file)
  471. {
  472.     int32        realCount;
  473.  
  474.     if ( count < 0 )
  475.         realCount = XP_STRLEN( source );
  476.     else
  477.         realCount = count;
  478.  
  479.     return( fwrite( source, 1, realCount, file ) );
  480. }
  481.  
  482. /* The user can set these on the preferences dialogs; the front end
  483.    informs us of them by setting these variables.  We do "something
  484.    sensible" if 0...
  485.    */
  486. PUBLIC char *FE_UserNewsHost = 0;    /* clone of NET_NewsHost, mostly... */
  487. PUBLIC char *FE_UserNewsRC = 0;
  488. PUBLIC char *FE_TempDir = 0;
  489. PUBLIC char *FE_CacheDir = 0;
  490. PUBLIC char *FE_SARCacheDir = 0;
  491. PUBLIC char *FE_GlobalHist = 0;
  492.  
  493.  
  494. static const char *
  495. xp_unix_config_directory(char* buf)
  496. {
  497.   static XP_Bool initted = FALSE;
  498.   const char *dir = ".netscape";
  499.   char *home;
  500.   if (initted)
  501.     return buf;
  502.  
  503.   home = getenv ("HOME");
  504.   if (!home)
  505.     home = "";
  506.  
  507. #ifdef OLD_UNIX_FILES
  508.  
  509.   sprintf (buf, "%.900s", home);
  510.   if (buf[strlen(buf)-1] == '/')
  511.     buf[strlen(buf)-1] = 0;
  512.  
  513. #else  /* !OLD_UNIX_FILES */
  514.  
  515.   if (*home && home[strlen(home)-1] == '/')
  516.     sprintf (buf, "%.900s%s", home, dir);
  517.   else
  518.     sprintf (buf, "%.900s/%s", home, dir);
  519.  
  520. #endif /* !OLD_UNIX_FILES */
  521.  
  522.   return buf;
  523. }
  524.  
  525. static int
  526. xp_unix_sprintf_stat( char * buf,
  527.                       const char * dirName,
  528.                       const char * lang,
  529.                       const char * fileName)
  530. {
  531.     int               result;
  532.     int               len;
  533.     XP_StatStruct     outStat;
  534.  
  535.     if (dirName == NULL || 0 == (len = strlen(dirName)) || len > 900)
  536.     return -1;
  537.  
  538.     while (--len > 0 && dirName[len] == '/')
  539.     /* do nothing */;        /* strip trailing slashes */
  540.     strncpy(buf, dirName, ++len);
  541.     buf[len++] = '/';
  542.     buf[len]   =  0;
  543.     if (lang != NULL && *lang == 0)
  544.     lang  = NULL;
  545.     if (lang != NULL) 
  546.     sprintf(buf+len, "%.100s/%s", lang, fileName);
  547.     else
  548.     strcpy(buf+len, fileName);
  549.     result = stat( buf, &outStat );
  550.     if (result >= 0 && !S_ISREG(outStat.st_mode))
  551.     result = -1;
  552.     if (result < 0 && lang != NULL)
  553.     result = xp_unix_sprintf_stat(buf, dirName, NULL, fileName);
  554.     return result;
  555. }
  556.  
  557. /* returns a unmalloced static string 
  558.  * that is only available for temporary use.
  559.  */
  560. PUBLIC char *
  561. xp_FileName (const char *name, XP_FileType type, char* buf, char* configBuf)
  562. {
  563.   const char *conf_dir = xp_unix_config_directory(configBuf);
  564.  
  565.   switch (type)
  566.     {
  567.     case xpSARCacheIndex:
  568.       {
  569.           const char *sar_cache_dir = FE_SARCacheDir;
  570.         if (!sar_cache_dir || !*sar_cache_dir)
  571.           sar_cache_dir = conf_dir;
  572.         if (sar_cache_dir [strlen (sar_cache_dir) - 1] == '/')
  573.           sprintf (buf, "%.900sarchive.fat", sar_cache_dir);
  574.         else
  575.           sprintf (buf, "%.900s/archive.fat", sar_cache_dir);
  576.  
  577.         name = buf;
  578.         break;
  579.       }
  580.     case xpSARCache:
  581.       {
  582.         /* WH_TempName() returns relative pathnames for the cache files,
  583.            so that relative paths get written into the cacheFAT database.
  584.            WH_FileName() converts them to absolute if they aren't already
  585.            so that the logic of XP_FileOpen() and XP_FileRename() and who
  586.            knows what else is simpler.
  587.          */
  588.                 if (name != NULL && *name == '/')
  589.                   break ;
  590.  
  591.                 {
  592.             char *tmp = FE_SARCacheDir;
  593.             if (!tmp || !*tmp) tmp = "/tmp";
  594.             if (tmp [strlen (tmp) - 1] == '/')
  595.               sprintf (buf, "%.500s%.500s", tmp, name);
  596.             else
  597.               sprintf (buf, "%.500s/%.500s", tmp, name);
  598.             name = buf;
  599.           }
  600.         break;
  601.       }
  602.     case xpCacheFAT:
  603.       {
  604.           const char *cache_dir = FE_CacheDir;
  605.         if (!cache_dir || !*cache_dir)
  606.           cache_dir = conf_dir;
  607.         if (cache_dir [strlen (cache_dir) - 1] == '/')
  608.           sprintf (buf, "%.900sindex.db", cache_dir);
  609.         else
  610.           sprintf (buf, "%.900s/index.db", cache_dir);
  611.  
  612.         name = buf;
  613.         break;
  614.       }
  615.     case xpCache:
  616.       {
  617.         /* WH_TempName() returns relative pathnames for the cache files,
  618.            so that relative paths get written into the cacheFAT database.
  619.            WH_FileName() converts them to absolute if they aren't already
  620.            so that the logic of XP_FileOpen() and XP_FileRename() and who
  621.            knows what else is simpler.
  622.          */
  623.         if (*name != '/')
  624.           {
  625.             char *tmp = FE_CacheDir;
  626.             if (!tmp || !*tmp) tmp = "/tmp";
  627.             if (tmp [strlen (tmp) - 1] == '/')
  628.               sprintf (buf, "%.500s%.500s", tmp, name);
  629.             else
  630.               sprintf (buf, "%.500s/%.500s", tmp, name);
  631.             name = buf;
  632.           }
  633.         break;
  634.       }
  635.  
  636.     case xpHTTPCookie:
  637.       {
  638. #ifndef OLD_UNIX_FILES
  639.         sprintf (buf, "%.900s/cookies", conf_dir);
  640. #else  /* OLD_UNIX_FILES */
  641.         sprintf (buf, "%.900s/.netscape-cookies", conf_dir);
  642. #endif /* OLD_UNIX_FILES */
  643.         name = buf;
  644.         break;
  645.       }
  646.     case xpRegistry:
  647.       {
  648.         if ( name == NULL || *name == '\0' ) {
  649. #ifndef OLD_UNIX_FILES
  650.             sprintf (buf, "%.900s/registry", conf_dir);
  651. #else  /* OLD_UNIX_FILES */
  652.             sprintf (buf, "%.900s/.netscape-registry", conf_dir);
  653. #endif /* OLD_UNIX_FILES */
  654.             name = buf;
  655.         }
  656.         else {
  657.             XP_ASSERT( name[0] == '/' );
  658.         }
  659.         break;
  660.       }
  661.     case xpProxyConfig:
  662.       {
  663.         sprintf(buf, "%.900s/proxyconf", conf_dir);
  664.         name = buf;
  665.         break;
  666.       }
  667.     case xpTemporary:
  668.       {
  669.         if (*name != '/')
  670.           {
  671.             char *tmp = FE_TempDir;
  672.             if (!tmp || !*tmp) tmp = "/tmp";
  673.             if (tmp [strlen (tmp) - 1] == '/')
  674.               sprintf (buf, "%.500s%.500s", tmp, name);
  675.             else
  676.               sprintf (buf, "%.500s/%.500s", tmp, name);
  677.             name = buf;
  678.           }
  679.         break;
  680.       }
  681.     case xpNewsRC:
  682.     case xpSNewsRC:
  683.     case xpTemporaryNewsRC:
  684.       {
  685.         /* In this case, `name' is "" or "host" or "host:port". */
  686.  
  687.         char *home = getenv ("HOME");
  688.         const char *newsrc_dir = ((FE_UserNewsRC && *FE_UserNewsRC)
  689.                                   ? FE_UserNewsRC
  690.                                   : (home ? home : ""));
  691.         const char *basename = (type == xpSNewsRC ? ".snewsrc" : ".newsrc");
  692.         const char *suffix = (type == xpTemporaryNewsRC ? ".tmp" : "");
  693.         if (*name)
  694.           sprintf (buf, "%.800s%.1s%.8s-%.128s%.4s",
  695.                    newsrc_dir,
  696.                    (newsrc_dir[XP_STRLEN(newsrc_dir)-1] == '/' ? "" : "/"),
  697.                    basename, name, suffix);
  698.         else
  699.           sprintf (buf, "%.800s%.1s%.128s%.4s",
  700.                    newsrc_dir,
  701.                    (newsrc_dir[XP_STRLEN(newsrc_dir)-1] == '/' ? "" : "/"),
  702.                    basename, suffix);
  703.  
  704.         name = buf;
  705.         break;
  706.       }
  707.     case xpNewsgroups:
  708.     case xpSNewsgroups:
  709.       {
  710. #ifndef OLD_UNIX_FILES
  711.         sprintf (buf, "%.800s/%snewsgroups-%.128s", 
  712.                  conf_dir, 
  713.                  type == xpSNewsgroups ? "s" : "", 
  714.                  name);
  715. #else  /* OLD_UNIX_FILES */
  716.         sprintf (buf, "%.800s/.netscape-%snewsgroups-%.128s", 
  717.                  conf_dir, 
  718.                  type == xpSNewsgroups ? "s" : "", 
  719.                  name);
  720. #endif /* OLD_UNIX_FILES */
  721.         name = buf;
  722.         break;
  723.       }
  724.  
  725.     case xpExtCacheIndex:
  726. #ifndef OLD_UNIX_FILES
  727.         sprintf (buf, "%.900s/cachelist", conf_dir);
  728. #else  /* OLD_UNIX_FILES */
  729.         sprintf (buf, "%.900s/.netscape-cache-list", conf_dir);
  730. #endif /* OLD_UNIX_FILES */
  731.         name = buf;
  732.         break;
  733.  
  734.     case xpGlobalHistory:
  735.         name = FE_GlobalHist;
  736.         break;
  737.  
  738.     case xpCertDB:
  739. #ifndef OLD_UNIX_FILES
  740.         if ( name ) {
  741.             sprintf (buf, "%.900s/cert%s.db", conf_dir, name);
  742.         } else {
  743.             sprintf (buf, "%.900s/cert.db", conf_dir);
  744.         }
  745. #else  /* OLD_UNIX_FILES */
  746.         sprintf (buf, "%.900s/.netscape-certdb", conf_dir);
  747. #endif /* OLD_UNIX_FILES */
  748.         name = buf;
  749.         break;
  750.     case xpCertDBNameIDX:
  751. #ifndef OLD_UNIX_FILES
  752.         sprintf (buf, "%.900s/cert-nameidx.db", conf_dir);
  753. #else  /* OLD_UNIX_FILES */
  754.         sprintf (buf, "%.900s/.netscape-certdb-nameidx", conf_dir);
  755. #endif /* OLD_UNIX_FILES */
  756.         name = buf;
  757.         break;
  758.     case xpKeyDB:
  759. #ifndef OLD_UNIX_FILES
  760.         if ( name ) {
  761.             sprintf (buf, "%.900s/key%s.db", conf_dir, name);
  762.         } else {
  763.             sprintf (buf, "%.900s/key.db", conf_dir);
  764.         }
  765. #else  /* OLD_UNIX_FILES */
  766.         sprintf (buf, "%.900s/.netscape-keydb", conf_dir);
  767. #endif /* OLD_UNIX_FILES */
  768.         name = buf;
  769.         break;
  770.     case xpSecModuleDB:
  771.         sprintf (buf, "%.900s/secmodule.db", conf_dir);
  772.         name = buf;
  773.         break;
  774.  
  775.     case xpSignedAppletDB:
  776.       {
  777. #ifndef OLD_UNIX_FILES
  778.         if ( name ) {
  779.             sprintf (buf, "%.900s/signedapplet%s.db", conf_dir, name);
  780.         } else {
  781.             sprintf (buf, "%.900s./signedapplet.db", conf_dir);
  782.         }
  783. #else  /* OLD_UNIX_FILES */
  784.         sprintf (buf, "%.900s/.netscape-signedappletdb", conf_dir);
  785. #endif /* OLD_UNIX_FILES */
  786.         name = buf;
  787.         break;
  788.       }
  789.  
  790.     case xpFileToPost:
  791.     case xpSignature:
  792.           /* These are always absolute pathnames. 
  793.          * BUT, the user can type in whatever so
  794.          * we can't assert if it doesn't begin
  795.          * with a slash
  796.          */
  797.         break;
  798.  
  799.     case xpExtCache:
  800.     case xpKeyChain:
  801.     case xpURL:
  802.     case xpHotlist:
  803.     case xpBookmarks:
  804.     case xpMimeTypes:
  805.     case xpSocksConfig:
  806.     case xpMailFolder:
  807. #ifdef BSDI
  808.         /* In bsdi, mkdir fails if the directory name is terminated
  809.          * with a '/'. - dp
  810.          */
  811.         if (name[strlen(name)-1] == '/') {
  812.         strcpy(buf, name);
  813.         buf[strlen(buf)-1] = '\0';
  814.         name = buf;
  815.         }
  816. #endif
  817. #ifndef MCC_PROXY
  818.       /*
  819.        * These are always absolute pathnames for the Navigator.
  820.        * Only the proxy (servers) may have pathnames relative
  821.        * to their current working directory (the servers chdir
  822.        * to their admin/config directory on startup.
  823.        *
  824.        */
  825.       if (name) XP_ASSERT (name[0] == '/');
  826. #endif    /* ! MCC_PROXY */
  827.  
  828.       break;
  829.  
  830.     case xpMailFolderSummary:
  831.       /* Convert /a/b/c/foo to /a/b/c/.foo.summary (note leading dot) */
  832.       {
  833.         const char *slash;
  834.         slash = strrchr (name, '/');
  835.         if (name) XP_ASSERT (name[0] == '/');
  836.         XP_ASSERT (slash);
  837.         if (!slash) return 0;
  838.         XP_MEMCPY (buf, name, slash - name + 1);
  839.         buf [slash - name + 1] = '.';
  840.         XP_STRCPY (buf + (slash - name) + 2, slash + 1);
  841.         XP_STRCAT (buf, ".summary");
  842.         name = buf;
  843.         break;
  844.       }
  845.  
  846.     case xpAddrBookNew:
  847.       /* Convert foo.db to /a/b/c/foo.db */
  848.       {
  849.         if ( name ) {
  850.             sprintf (buf, "%.900s/%s", conf_dir, name);
  851.         } else {
  852.             sprintf (buf, "%.900s/abook.nab", conf_dir);
  853.         }
  854. #if defined(DEBUG_tao)
  855.         printf("\n  xpAddrBookNew, xp_FileName, buf=%s\n", buf);
  856. #endif
  857.         name = buf;
  858.  
  859.         break;
  860.       }
  861.  
  862.     case xpAddrBook:
  863.       /* Convert /a/b/c/foo to /a/b/c/foo.db (note leading dot) */
  864.       {
  865.           /* Tao_27jan97
  866.            */
  867.           char *dot = NULL;
  868.           int len = 0;
  869.           const char *base = NULL;
  870.  
  871.           if (name) 
  872.               XP_ASSERT (name[0] == '/');
  873.  
  874.           dot = XP_STRRCHR(name, '.');
  875.           if (dot) {
  876.  
  877.               len = dot - name + 1;
  878.               XP_STRNCPY_SAFE(buf, name, len);
  879.           }/* if */
  880.  
  881.           XP_STRCAT (buf, ".nab");
  882.  
  883.  
  884.           /* Tao_02jun97 don't convert addrbook.db
  885.            * reuse len, dot
  886.            */
  887.           base = XP_STRRCHR(name, '/');
  888.           if (base && *base == '/')
  889.               base++;              
  890.  
  891. #if defined(DEBUG_tao)
  892.           printf("\n++++  xpAddrBook, before xp_FileName=%s\n", name);
  893. #endif
  894.  
  895.           if (!base || XP_STRCMP(base, "addrbook.db"))
  896.               /* not old addrbook.db file
  897.                */
  898.               name = buf;
  899. #if defined(DEBUG_tao)
  900.           printf("\n  xpAddrBook, xp_FileName=%s\n", name);
  901. #endif
  902.         break;
  903.       }
  904.  
  905.     case xpVCardFile:
  906.       /* Convert /a/b/c/foo to /a/b/c/foo.vcf (note leading dot) */
  907.       {
  908. #if 1
  909.           /* Tao_27jan97
  910.            */
  911.           char *dot = NULL;
  912.           int len = 0;
  913.  
  914.           if (name) 
  915.               XP_ASSERT (name[0] == '/');
  916.  
  917.           dot = XP_STRRCHR(name, '.');
  918.           if (dot) {
  919.               len = dot - name + 1;
  920.               XP_STRNCPY_SAFE(buf, name, len);
  921.           }/* if */
  922.  
  923.           XP_STRCAT (buf, ".vcf");
  924.           name = buf;
  925. #if defined(DEBUG_tao_)
  926.           printf("\n  xp_FileName=%s\n", name);
  927. #endif
  928. #else
  929.         const char *slash;
  930.         slash = strrchr (name, '/');
  931.         if (name) XP_ASSERT (name[0] == '/');
  932.         XP_ASSERT (slash);
  933.         if (!slash) return 0;
  934.         XP_MEMCPY (buf, name, slash - name + 1);
  935.         XP_STRCAT (buf, ".vcf");
  936.         name = buf;
  937. #endif
  938.         break;
  939.       }
  940.  
  941.     case xpLDIFFile:
  942.       /* Convert /a/b/c/foo to /a/b/c/foo.ldif (note leading dot) */
  943.       {
  944. #if 1
  945.           /* Tao_27jan97
  946.            */
  947.           char *dot = NULL;
  948.           int len = 0;
  949.  
  950.           if (name) 
  951.               XP_ASSERT (name[0] == '/');
  952.  
  953.           dot = XP_STRRCHR(name, '.');
  954.           if (dot) {
  955.               len = dot - name + 1;
  956.               XP_STRNCPY_SAFE(buf, name, len);
  957.           }/* if */
  958.  
  959.           XP_STRCAT (buf, ".ldif");
  960.           name = buf;
  961. #if defined(DEBUG_tao_)
  962.           printf("\n  xp_FileName=%s\n", name);
  963. #endif
  964.  
  965. #else
  966.         const char *slash;
  967.         slash = strrchr (name, '/');
  968.         if (name) XP_ASSERT (name[0] == '/');
  969.         XP_ASSERT (slash);
  970.         if (!slash) return 0;
  971.         XP_MEMCPY (buf, name, slash - name + 1);
  972.         XP_STRCAT (buf, ".ldif");
  973.         name = buf;
  974. #endif
  975.         break;
  976.       }
  977.  
  978.     case xpJSMailFilters:
  979.       sprintf(buf, "%.900s/filters.js", conf_dir);
  980.       name = buf;
  981.       break;
  982.  
  983.     case xpJSHTMLFilters:
  984.       sprintf(buf, "%.900s/hook.js", conf_dir);
  985.       name = buf;
  986.       break;
  987.  
  988.     case xpNewsSort:
  989.         sprintf(buf, "%.800s/xover-cache/%.128snetscape-newsrule", conf_dir, name);
  990.         break;
  991.     case xpMailSort:
  992. #ifndef OLD_UNIX_FILES
  993.       sprintf(buf, "%.900s/mailrule", conf_dir);
  994. #else  /* OLD_UNIX_FILES */
  995.       sprintf(buf, "%.900s/.netscape-mailrule", conf_dir);
  996. #endif /* OLD_UNIX_FILES */
  997.       name = buf;
  998.       break;
  999.     case xpMailPopState:
  1000. #ifndef OLD_UNIX_FILES
  1001.       sprintf(buf, "%.900s/popstate", conf_dir);
  1002. #else  /* OLD_UNIX_FILES */
  1003.       sprintf(buf, "%.900s/.netscape-popstate", conf_dir);
  1004. #endif /* OLD_UNIX_FILES */
  1005.       name = buf;
  1006.       break;
  1007.     case xpMailFilterLog:
  1008.       sprintf(buf, "%.900s/.netscape-mailfilterlog", conf_dir);
  1009.       name = buf;
  1010.       break;
  1011.     case xpNewsFilterLog:
  1012.       sprintf(buf, "%.900s/.netscape-newsfilterlog", conf_dir);
  1013.       name = buf;
  1014.       break;
  1015.     case xpMailSubdirectory:
  1016.     {
  1017.      char * pEnd = strrchr(name, '/');
  1018.      strcpy(buf, name);
  1019.  
  1020.       /* strip off the extension */
  1021.        if(!pEnd)
  1022.         pEnd = buf;
  1023.  
  1024.       pEnd = strchr(pEnd, '.');
  1025.       if(pEnd)
  1026.         *pEnd = '\0';
  1027.       strcat(buf, ".sbd/");
  1028.       name = buf;
  1029.     }
  1030.     break;
  1031.     case xpXoverCache:
  1032.       sprintf(buf, "%.800s/xover-cache/%.128s", conf_dir, name);
  1033.       name = buf;
  1034.       break;
  1035.  
  1036.     case xpNewsHostDatabase:
  1037.       sprintf(buf, "%.800s/newsdb", conf_dir);
  1038.       name = buf;
  1039.       break;
  1040.  
  1041.     case xpImapRootDirectory:
  1042.     {
  1043.         char prefbuf[1024];
  1044.         int len = sizeof prefbuf / sizeof *prefbuf;
  1045.         if ((PREF_GetCharPref("mail.imap.root_dir",
  1046.                               prefbuf, &len) == PREF_NOERROR)
  1047.             && *prefbuf == '/')
  1048.                 /* guard against assert: line 806, file xp_file.c */
  1049.             XP_STRNCPY_SAFE(buf, prefbuf, len);
  1050.             /* Copy back to the buffer that was passed in.
  1051.              * We couldn't have PREF_GetCharPref() just put it there
  1052.              * initially because the size of buf wasn't passed in
  1053.              * (it happens to be 1024) and PREF_GetCharPref() insists
  1054.              * on having a size. Sigh.
  1055.              */
  1056.         else
  1057.         {
  1058.             char *home = getenv ("HOME");
  1059.             sprintf(buf, "%s/ns_imap", (home ? home : ""));
  1060.         }
  1061.         name = buf;
  1062.         break;
  1063.     }
  1064.  
  1065.     case xpImapServerDirectory:
  1066.     {
  1067.         char prefbuf[1024];
  1068.         int len = sizeof prefbuf / sizeof *prefbuf;
  1069.         if ((PREF_GetCharPref("mail.imap.root_dir",
  1070.                               prefbuf, &len) == PREF_NOERROR)
  1071.             && *prefbuf == '/')
  1072.                 /* guard against assert: line 806, file xp_file.c */
  1073.             sprintf(buf, "%s/%s", prefbuf, name);
  1074.         else
  1075.         {
  1076.             char *home = getenv ("HOME");
  1077.             sprintf(buf, "%s/ns_imap/%s", (home ? home : ""), name);
  1078.         }
  1079.         name = buf;
  1080.         break;
  1081.     }
  1082.  
  1083.     case xpFolderCache:
  1084.         sprintf (buf, "%s/summary.dat", conf_dir);
  1085.         name = buf;
  1086.         break;
  1087.  
  1088.      case xpCryptoPolicy:
  1089.      {
  1090.          extern void fe_GetProgramDirectory(char *path, int len);
  1091.          char *policyFN = "moz40p3";
  1092.          char *mozHome  = getenv("MOZILLA_HOME");
  1093.          char *lang     = getenv("LANG");
  1094.          int   result;
  1095.          char  dirName[1024];
  1096.  
  1097.          name = buf;
  1098.          if (!xp_unix_sprintf_stat(buf, conf_dir, lang, policyFN))
  1099.              break;
  1100.          if (!xp_unix_sprintf_stat(buf, mozHome, lang, policyFN))
  1101.              break;
  1102.          fe_GetProgramDirectory(dirName, sizeof dirName);
  1103.          if (!xp_unix_sprintf_stat(buf, dirName, lang, policyFN))
  1104.              break;
  1105.  
  1106.          /* couldn't find it, but must leave a valid file name in buf */
  1107.          sprintf(buf, "%.900s/%s", conf_dir, policyFN);
  1108.          break;
  1109.      }
  1110.  
  1111.     case xpPKCS12File:
  1112.       /* Convert /a/b/c/foo to /a/b/c/foo.p12 (note leading dot) */
  1113.       {
  1114.           int len = 0;
  1115.  
  1116.           if(name) {
  1117.             XP_ASSERT(name[0] == '/');
  1118.  
  1119.             /* only append if there is enough space in the buffer */    
  1120.             /* this should be changed if the size of the buf changes */
  1121.             if((XP_STRLEN(name) + 4) <= 1020) {
  1122.  
  1123.                 /* include NULL in length */
  1124.                 len = XP_STRLEN(name) + 1;
  1125.                 XP_STRNCPY_SAFE(buf, name, len);
  1126.  
  1127.                 /* we want to concatenate ".p12" if it is not the
  1128.                  * last 4 characters of the name already.  
  1129.                  * If len is less than 5 (including the terminating
  1130.                  * NULL), it is not ".p12".  
  1131.                  * If the len is > 5 it may have the .p12, so we want
  1132.                  * to check and only append .p12 if the name 
  1133.                  * specified does not end in .p12.
  1134.                  * only side effect -- this allows for the filename
  1135.                  * ".p12" which is fine.
  1136.                  */
  1137.                 if((len >= 5) && XP_STRCASECMP(&(name[len-4-1]), ".p12")) {
  1138.                     XP_STRCAT(buf, ".p12");
  1139.                 } else if(len < 5) {
  1140.                     /* can't be ".p12", so we append ".p12" */
  1141.                     XP_STRCAT(buf, ".p12");
  1142.                 }
  1143.                 name = buf;
  1144.             }
  1145.            }
  1146.         
  1147.            break;
  1148.       }
  1149.  
  1150.     case xpJSCookieFilters:
  1151.         {
  1152.             sprintf(buf, "%.900s/cookies.js", conf_dir);
  1153.             name = buf;
  1154.             break;
  1155.         }
  1156.  
  1157.     case xpLIPrefs:
  1158.         {
  1159.             sprintf(buf, "%.900s/liprefs.js", conf_dir);
  1160.             name = buf;
  1161.             break;
  1162.         }
  1163.  
  1164.     default:
  1165.       abort ();
  1166.     }
  1167.  
  1168.   return (char *) name;
  1169. }
  1170.  
  1171. char * xp_FilePlatformName(const char * name, char* path)
  1172. {
  1173.     if ((name == NULL) || (XP_STRLEN(name) > 1000))
  1174.         return NULL;
  1175.     XP_STRCPY(path, name);
  1176.     return path;
  1177. }
  1178.  
  1179. char * XP_PlatformFileToURL (const char *name)
  1180. {
  1181.     char *prefix = "file://";
  1182.     char *retVal = XP_ALLOC (XP_STRLEN(name) + XP_STRLEN(prefix) + 1);
  1183.     if (retVal)
  1184.     {
  1185.         XP_STRCPY (retVal, "file://");
  1186.         XP_STRCAT (retVal, name);
  1187.     }
  1188.     return retVal;
  1189. }
  1190.  
  1191. char *XP_PlatformPartialPathToXPPartialPath(const char *platformPath)
  1192. {
  1193.     /* using the unix XP_PlatformFileToURL, there is no escaping! */
  1194.     return XP_STRDUP(platformPath);
  1195. }
  1196.  
  1197.  
  1198. #define CACHE_SUBDIRS
  1199.  
  1200. char*
  1201. XP_TempDirName(void)
  1202. {
  1203.     char *tmp = FE_TempDir;
  1204.     if (!tmp || !*tmp) tmp = "/tmp";
  1205.     return XP_STRDUP(tmp);
  1206. }
  1207.  
  1208. char *
  1209. xp_TempName (XP_FileType type, const char * prefix, char* buf, char* buf2, unsigned int *count)
  1210. {
  1211. #define NS_BUFFER_SIZE    1024
  1212.   char *value = buf;
  1213.   time_t now;
  1214.  
  1215.   *buf = 0;
  1216.   XP_ASSERT (type != xpTemporaryNewsRC);
  1217.  
  1218.   if (type == xpCache || type == xpSARCache)
  1219.     {
  1220.       /* WH_TempName() must return relative pathnames for the cache files,
  1221.          so that relative paths get written into the cacheFAT database,
  1222.          making the directory relocatable.
  1223.        */
  1224.       *buf = 0;
  1225.     }
  1226.   else  if ( (type == xpURL) && prefix )
  1227.     {
  1228.        if ( XP_STRRCHR(prefix, '/') )
  1229.            {
  1230.           XP_StatStruct st;
  1231.  
  1232.           XP_SPRINTF (buf, "%.500s", prefix);
  1233.           if (XP_Stat (buf, &st, xpURL))
  1234.             XP_MakeDirectoryR (buf, xpURL);
  1235.           prefix = "su"; 
  1236.            }
  1237.     }
  1238.     else
  1239.     {
  1240.       char *tmp = FE_TempDir;
  1241.       if (!tmp || !*tmp) tmp = "/tmp";
  1242.       XP_SPRINTF (buf, "%.500s", tmp);
  1243.  
  1244.       if (!prefix || !*prefix)
  1245.         prefix = "tmp";
  1246.     }
  1247.  
  1248.   XP_ASSERT (!XP_STRCHR (prefix, '/'));
  1249.   if (*buf && buf[XP_STRLEN (buf)-1] != '/')
  1250.     XP_STRCAT (buf, "/");
  1251.  
  1252.   /* It's good to have the cache file names be pretty long, with a bunch of
  1253.      inputs; this makes the variant part be 15 chars long, consisting of the
  1254.      current time (in seconds) followed by a counter (to differentiate
  1255.      documents opened in the same second) followed by the current pid (to
  1256.      differentiate simultanious processes.)  This organization of the bits
  1257.      has the effect that they are ordered the same lexicographically as by
  1258.      creation time.
  1259.  
  1260.      If name length was an issue we could cut the character count a lot by
  1261.      printing them in base 72 [A-Za-z0-9@%-_=+.,~:].
  1262.    */
  1263.   now = time ((time_t *) 0);
  1264.   sprintf (buf2,
  1265.            "%08X%03X%04X",
  1266.            (unsigned int) now,
  1267.            (unsigned int) *count,
  1268.            (unsigned int) (getpid () & 0xFFFF));
  1269.  
  1270.   if (++(*count) > 4095) (*count) = 0; /* keep it 3 hex digits */
  1271.  
  1272. #ifdef CACHE_SUBDIRS
  1273.   if (type == xpCache || type == xpSARCache)
  1274.     {
  1275.       XP_StatStruct st;
  1276.       char *s;
  1277.       char *tmp = (type == xpCache) ? FE_CacheDir : FE_SARCacheDir;
  1278.       if (!tmp || !*tmp) tmp = "/tmp";
  1279.       sprintf (buf, "%.500s", tmp);
  1280.       if (buf [XP_STRLEN(buf)-1] != '/')
  1281.         XP_STRCAT (buf, "/");
  1282.  
  1283.       s = buf + XP_STRLEN (buf);
  1284.  
  1285.       value = s;        /* return a relative path! */
  1286.  
  1287.       /* The name of the subdirectory is the bottom 5 bits of the time part,
  1288.          in hex (giving a total of 32 directories.) */
  1289.       sprintf (s, "%02X", (now & 0x1F));
  1290.  
  1291.       if (XP_Stat (buf, &st, xpURL))        /* create the dir if necessary */
  1292.         XP_MakeDirectory (buf, type);
  1293.  
  1294.       s[2] = '/';
  1295.       s[3] = 0;
  1296.     }
  1297. #endif /* !CACHE_SUBDIRS */
  1298.  
  1299.   XP_STRNCAT (value, prefix, NS_BUFFER_SIZE - XP_STRLEN(value));
  1300.   XP_STRNCAT (value, buf2, NS_BUFFER_SIZE - XP_STRLEN(value));
  1301.  
  1302.   /* Tao
  1303.    */
  1304.   if (type == xpAddrBook) {
  1305.       XP_STRNCAT (value, ".nab", NS_BUFFER_SIZE - XP_STRLEN(value));
  1306.   }/* if */
  1307.  
  1308.   value[NS_BUFFER_SIZE - 1] = '\0'; /* just in case */
  1309.  
  1310.   DO_TRACE(("WH_TempName called: returning: %s", value));
  1311.  
  1312.   return(value);
  1313. }
  1314.  
  1315.  
  1316. /* XP_GetNewsRCFiles returns a null terminated array
  1317.  * of pointers to malloc'd filename's.  Each filename
  1318.  * represents a different newsrc file.
  1319.  *
  1320.  * return only the filename since the path is not needed
  1321.  * or wanted.
  1322.  *
  1323.  * Netlib is expecting a string of the form:
  1324.  *  [s]newsrc-host.name.domain[:port]
  1325.  *
  1326.  * examples:
  1327.  *    newsrc-news.mcom.com
  1328.  *    snewsrc-flop.mcom.com
  1329.  *    newsrc-news.mcom.com:118
  1330.  *    snewsrc-flop.mcom.com:1191
  1331.  *
  1332.  * the port number is optional and should only be
  1333.  * there when different from the default.
  1334.  * the "s" in front of newsrc signifies that
  1335.  * security is to be used.
  1336.  *
  1337.  * return NULL on critical error or no files
  1338.  */
  1339.  
  1340. #define NEWSRC_PREFIX ".newsrc"
  1341. #define SNEWSRC_PREFIX ".snewsrc"
  1342.  
  1343. #include "nslocks.h"
  1344. #include "prnetdb.h"
  1345.  
  1346. PUBLIC char **
  1347. XP_GetNewsRCFiles(void)
  1348. {
  1349.     XP_Dir dir_ptr;
  1350.     XP_DirEntryStruct *dir_entry;
  1351.     char **array;
  1352.     int count=0;
  1353.     char * dirname;
  1354.     char * name;
  1355.     int len, len2;
  1356.     
  1357.     /* assume that there will never be more than 256 hosts
  1358.      */
  1359. #define MAX_NEWSRCS 256
  1360.     array = (char **) XP_ALLOC(sizeof(char *) * (MAX_NEWSRCS+1));
  1361.  
  1362.     if(!array)
  1363.         return(NULL);
  1364.  
  1365.     XP_MEMSET(array, 0, sizeof(char *) * (MAX_NEWSRCS+1));
  1366.  
  1367.     name = WH_FileName ("", xpNewsRC);
  1368.  
  1369.     /* truncate the last slash */
  1370.     dirname = XP_STRRCHR(name, '/');
  1371.     if(dirname)
  1372.         *dirname = '\0';
  1373.     dirname = name;
  1374.  
  1375.     if(!dirname)
  1376.         dirname = "";
  1377.  
  1378.     dir_ptr = XP_OpenDir(dirname, xpNewsRC);
  1379.     XP_FREE(name);
  1380.     if(dir_ptr == NULL)
  1381.       {
  1382.         XP_FREE(array);
  1383.         return(NULL);
  1384.       }
  1385.  
  1386.     len = XP_STRLEN(NEWSRC_PREFIX);
  1387.     len2 = XP_STRLEN(SNEWSRC_PREFIX);
  1388.  
  1389.     while((dir_entry = XP_ReadDir(dir_ptr)) != NULL
  1390.             && count < MAX_NEWSRCS)
  1391.       {
  1392.         char *name = dir_entry->d_name;
  1393.         char *suffix, *port;
  1394.         if (!XP_STRNCMP (name, NEWSRC_PREFIX, len))
  1395.           suffix = name + len;
  1396.         else if (!XP_STRNCMP (name, SNEWSRC_PREFIX, len2))
  1397.           suffix = name + len2;
  1398.         else
  1399.           continue;
  1400.  
  1401.         if (suffix [strlen (suffix) - 1] == '~' ||
  1402.             suffix [strlen (suffix) - 1] == '#')
  1403.           continue;
  1404.  
  1405.         if (*suffix != 0 && *suffix != '-')
  1406.           /* accept ".newsrc" and ".newsrc-foo" but ignore
  1407.              .newsrcSomethingElse" */
  1408.           continue;
  1409.  
  1410.         if (*suffix &&
  1411.             (suffix[1] == 0 || suffix[1] == ':'))  /* reject ".newsrc-" */
  1412.           continue;
  1413.  
  1414.         port = XP_STRCHR (suffix, ':');
  1415.         if (!port)
  1416.           port = suffix + strlen (suffix);
  1417.  
  1418.         if (*port)
  1419.           {
  1420.             /* If there is a "port" part, reject this file if it contains
  1421.                non-numeric characters (meaning reject ".newsrc-host:99.tmp")
  1422.              */
  1423.             char *s;
  1424.             for (s = port+1; *s; s++)
  1425.               if (*s < '0' || *s > '9')
  1426.                 break;
  1427.             if (*s)
  1428.               continue;
  1429.           }
  1430.  
  1431.         if (suffix != port)
  1432.           {
  1433.             /* If there's a host name in the file, check that it is a
  1434.                resolvable host name.
  1435.  
  1436.                If this turns out to be a bad idea because of socks or
  1437.                some other reason, then we should at least check that
  1438.                it looks vaguely like a host name - no non-hostname
  1439.                characters, and so on.
  1440.              */
  1441.             char host [255];
  1442.             PRHostEnt *ok, hpbuf;
  1443.             char dbbuf[PR_NETDB_BUF_SIZE];
  1444.             if (port - suffix >= sizeof (host))
  1445.               continue;
  1446.             strncpy (host, suffix + 1, port - suffix - 1);
  1447.             host [port - suffix - 1] = 0;
  1448. #ifndef NSPR20
  1449.             ok = PR_gethostbyname (host, &hpbuf, dbbuf, sizeof(dbbuf), 0);
  1450. #else
  1451.                         if (PR_GetHostByName (host, dbbuf, sizeof(dbbuf), &hpbuf) == PR_SUCCESS)
  1452.                 ok = &hpbuf;
  1453.             else
  1454.                 ok = NULL;
  1455. #endif
  1456.             if (!ok)
  1457.               continue;
  1458.           }
  1459.  
  1460.         StrAllocCopy(array[count++], dir_entry->d_name+1);
  1461.       }
  1462.  
  1463.     XP_CloseDir (dir_ptr);
  1464.     return(array);
  1465. }
  1466.  
  1467. XP_Dir XP_OpenDir(const char * name, XP_FileType type)
  1468. {
  1469.     XP_Dir dir = NULL;
  1470.     char *pathName = NULL;
  1471.     switch (type)
  1472.     {
  1473.     case xpMailSubdirectory:
  1474.         pathName = PR_smprintf ("%s%s", name, ".sbd");
  1475.         if (pathName)
  1476.         {
  1477.             dir = opendir (pathName);
  1478.             XP_FREEIF(pathName);
  1479.         }
  1480.         else
  1481.             dir = NULL;
  1482.         break;
  1483.     default:
  1484.         dir = opendir (name);
  1485.     }
  1486.     return dir;
  1487. }
  1488.  
  1489. #endif /* XP_UNIX */
  1490.  
  1491. #if defined(XP_UNIX) || defined(XP_WIN) || defined(XP_OS2)
  1492.  
  1493. /*
  1494.  * Make all the directories specified in the path
  1495.  */
  1496. int XP_MakeDirectoryR(const char* name, XP_FileType type)
  1497. {
  1498.     char separator;
  1499.     int result = 0;
  1500.     char * finalName;
  1501.     
  1502. #if defined(XP_WIN) || defined(XP_OS2)
  1503.     separator = '\\';
  1504. #elif defined XP_UNIX
  1505.     separator = '/';
  1506. #endif
  1507.     finalName = WH_FileName(name, type);
  1508.     if ( finalName )
  1509.     {
  1510.         char * dirPath;
  1511.         char * currentEnd;
  1512.         int err = 0;
  1513.         XP_StatStruct s;
  1514.         dirPath = XP_STRDUP( finalName );
  1515.         if (dirPath == NULL)
  1516.             return -1;
  1517.  
  1518.         currentEnd = XP_STRCHR(dirPath, separator);
  1519.         /* Loop through every part of the directory path */
  1520.         while (currentEnd != 0)
  1521.         {
  1522.             char savedChar;
  1523.             savedChar = currentEnd[1];
  1524.             currentEnd[1] = 0;
  1525.             if ( XP_Stat(dirPath, &s, xpURL ) != 0)
  1526.                 err = XP_MakeDirectory(dirPath, xpURL);
  1527.             if ( err != 0)
  1528.             {
  1529.                 XP_ASSERT( FALSE );    /* Could not create the directory? */
  1530.                 break;
  1531.             }
  1532.             currentEnd[1] = savedChar;
  1533.             currentEnd = XP_STRCHR( ¤tEnd[1], separator);
  1534.         }
  1535.         if ( err == 0 )
  1536.         /* If the path is not terminated with / */
  1537.         {
  1538.             if ( dirPath[XP_STRLEN( dirPath) - 1] != separator )
  1539.                 if ( XP_Stat(dirPath, &s, xpURL ) != 0)
  1540.                     err = XP_MakeDirectory(dirPath, xpURL);
  1541.         }
  1542.         if ( 0 != err )
  1543.             result = err;
  1544.         if ( dirPath )
  1545.             XP_FREE( dirPath );
  1546.     }
  1547.     else
  1548.         result = -1;
  1549.     if ( finalName )
  1550.         XP_FREE( finalName );
  1551.     XP_ASSERT( result == 0 );    /* For debugging only */
  1552.     return result;
  1553. }
  1554.  
  1555. #endif /* XP_WIN || XP_UNIX || XP_OS2 */
  1556. /*
  1557.     If we go to some sort of system-wide canonical format, routines like this make sense.
  1558.     This is intended to work on our (mail's) canonical internal file name format.
  1559.     Currently, this looks like Unix format, e.g., "/directory/subdir".
  1560.     It is NOT intended to be used on native file name formats.
  1561.     The only current use is in spool.c, to determine if a rule folder
  1562.     is an absolute or relative path (relative to mail folder directory),
  1563.     so if this gets yanked, please fix spool.c  DMB 2/13/96
  1564.  
  1565.     spool.c has been retired. This routine has been adopted by lib/libmisc/dirprefs.c.
  1566.     This is only used for windows platform for now. jefft 7-24-97
  1567. */
  1568. XP_Bool XP_FileIsFullPath(const char * name)
  1569. {
  1570. #ifdef XP_WIN
  1571.     char drive[_MAX_DRIVE];
  1572.     char dir[_MAX_DIR];
  1573.     if (NULL == name) return FALSE;
  1574.     _splitpath(name, drive, dir, NULL, NULL);
  1575.     if (*drive != 0 || *dir == '\\') return TRUE;
  1576.     return FALSE;
  1577. #else
  1578.     XP_ASSERT(FALSE);
  1579.     /* return (*name == '/'); */
  1580.     return FALSE;
  1581. #endif
  1582. }
  1583.  
  1584. /******************************************************************************/
  1585. /* Thread-safe entry points: */
  1586.  
  1587. #if !defined(XP_WIN) && !defined(XP_OS2)
  1588.  
  1589. #ifdef NSPR
  1590. #ifndef NSPR20
  1591. extern PRMonitor* _pr_TempName_lock;
  1592. #else
  1593. PRMonitor* _pr_TempName_lock = NULL;
  1594. #endif /* NSPR20 */
  1595. #endif
  1596.  
  1597. PUBLIC char *
  1598. WH_FileName (const char *name, XP_FileType type)
  1599. {
  1600.     static char buf [1024];                /* protected by _pr_TempName_lock */
  1601.     static char configBuf [1024];        /* protected by _pr_TempName_lock */
  1602.     char* result;
  1603. #ifdef NSPR
  1604. #ifndef NSPR20
  1605.     XP_ASSERT(_pr_TempName_lock);
  1606.     PR_EnterMonitor(_pr_TempName_lock);
  1607. #else
  1608.     if (_pr_TempName_lock == NULL) {
  1609.         _pr_TempName_lock = PR_NewNamedMonitor("TempName-lock");
  1610.     }
  1611.     PR_EnterMonitor(_pr_TempName_lock);
  1612. #endif /* NSPR20 */
  1613. #endif
  1614.     /* reset
  1615.      */
  1616.     buf[0] = '\0';
  1617.     result = xp_FileName(name, type, buf, configBuf);
  1618.     if (result)
  1619.         result = XP_STRDUP(result);
  1620. #ifdef NSPR
  1621.     PR_ExitMonitor(_pr_TempName_lock);
  1622. #endif
  1623.     return result;
  1624. }
  1625.  
  1626. char * 
  1627. WH_FilePlatformName(const char * name)
  1628. {
  1629.     char* result;
  1630.     static char path[300];    /* Names longer than 300 are not dealt with in our stdio */
  1631. #ifdef NSPR
  1632. #ifndef NSPR20
  1633.     XP_ASSERT(_pr_TempName_lock);
  1634.     PR_EnterMonitor(_pr_TempName_lock);
  1635. #else
  1636.     if (_pr_TempName_lock == NULL) {
  1637.         _pr_TempName_lock = PR_NewNamedMonitor("TempName-lock");
  1638.     }
  1639.     PR_EnterMonitor(_pr_TempName_lock);
  1640. #endif /* NSPR20 */
  1641. #endif
  1642.     result = xp_FilePlatformName(name, path);
  1643. #ifdef NSPR
  1644.     PR_ExitMonitor(_pr_TempName_lock);
  1645. #endif
  1646.     if (result)
  1647.         result = XP_STRDUP(result);
  1648.         
  1649.     return result;
  1650. }
  1651.  
  1652. char * 
  1653. WH_TempName(XP_FileType type, const char * prefix)
  1654. {
  1655. #define NS_BUFFER_SIZE    1024
  1656.     static char buf [NS_BUFFER_SIZE];    /* protected by _pr_TempName_lock */
  1657.     static char buf2 [100];
  1658.     static unsigned int count = 0;
  1659.     char* result;
  1660. #ifdef NSPR
  1661. #ifndef NSPR20
  1662.     XP_ASSERT(_pr_TempName_lock);
  1663.     PR_EnterMonitor(_pr_TempName_lock);
  1664. #else
  1665.     if (_pr_TempName_lock == NULL) {
  1666.         _pr_TempName_lock = PR_NewNamedMonitor("TempName-lock");
  1667.     }
  1668.     PR_EnterMonitor(_pr_TempName_lock);
  1669. #endif /* NSPR20 */
  1670. #endif
  1671.     result = xp_TempName(type, prefix, buf, buf2, &count);
  1672.     if (result)
  1673.         result = XP_STRDUP(result);
  1674. #ifdef NSPR
  1675.     PR_ExitMonitor(_pr_TempName_lock);
  1676. #endif
  1677.     return result;
  1678. }
  1679.  
  1680. #endif /* !XP_WIN && !XP_OS2 */
  1681.  
  1682. /******************************************************************************/
  1683.