home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / macfe / utility / xp_file_mac.cp < prev    next >
Encoding:
Text File  |  1998-04-08  |  36.3 KB  |  1,297 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. /* xp_file_mac.h
  20.  * Mac-only xp_file functions
  21.  */
  22.  #include "xp_file_mac.h"
  23.  
  24.     /* macfe */
  25. #include "resgui.h"
  26. #include "ufilemgr.h"
  27. #include "uprefd.h"
  28.  
  29.     /* utilities */
  30. #include "MoreFilesExtras.h"
  31. #include "FSpCompat.h"
  32. #include "FileCopy.h"
  33. #include "PascalString.h"
  34. #include "Files.h"
  35. #include <LString.h>
  36. #include "cstring.h"
  37.  
  38. // validation flags for overloaded ConvertURLToSpec
  39. enum ConvertURLValidationFlags {
  40.     validateValFlag = 0x00000001,
  41.     stripValFlag    = 0x00000002,
  42.     appendValFlag   = 0x00000004,
  43.     stripAndAppendValFlag = (stripValFlag | appendValFlag) };
  44.  
  45. // Prototypes
  46. OSErr ConvertURLToSpec
  47.     (const char* inName,
  48.     FSSpec* outSpec,
  49.     ResIDT resid = 0,
  50.     Boolean validate = false);
  51. OSErr ConvertURLToSpec(
  52.     const char* inName,
  53.     FSSpec* outSpec,
  54.     const char* suffix = nil,
  55.     ConvertURLValidationFlags validate = validateValFlag);
  56.  
  57. /**************************************************************************************
  58.  * See xp_file.h for full documentation.  BE SURE TO READ THAT FILE.
  59.  **************************************************************************************/
  60.    
  61. //-----------------------------------
  62. OSErr ConvertURLToSpec(const char* inName, FSSpec* outSpec, ResIDT resid, Boolean validate)
  63. // Returns a file spec given a name (URL form), and resid of an extension to add.
  64. // If ResID is zero, just convert.
  65. // If resid is nonzero and validate is true, check the input name and return an error
  66. //         if the name does NOT have the suffix.
  67. // If resid is nonzero and validate is false, append the suffix to the input name
  68. //-----------------------------------
  69. {
  70.     if (!inName)
  71.         return bdNamErr;
  72. #ifdef DEBUG
  73.     if (XP_STRCHR(inName, ':'))
  74.         XP_ASSERT(0);    // Are they passing us a Mac path? 
  75. #endif
  76.  
  77.     OSErr err = CFileMgr::FSSpecFromLocalUnixPath(inName, outSpec);
  78.     if (err && err != fnfErr)     /* fnfErr is OK */
  79.         return err;
  80.     if (resid)
  81.     {
  82.         CStr255 extension;
  83.         ::GetIndString(extension, 300, resid);
  84.         if (validate)
  85.         {
  86.             SInt32 suffixPosition = (XP_STRLEN(inName) - XP_STRLEN(extension));
  87.             if (suffixPosition < 0)
  88.                 return bdNamErr;
  89.             if (XP_STRCASECMP(extension, inName + suffixPosition) != 0)
  90.                 return bdNamErr;
  91.         }
  92.         else
  93.             *(CStr63*)(outSpec->name) += extension;
  94.     }
  95.     return noErr;
  96. } // ConvertURLToSpec
  97.     
  98. //-----------------------------------
  99. OSErr ConvertURLToSpec(const char* inName, FSSpec* outSpec, const char* suffix,
  100.             ConvertURLValidationFlags validate) 
  101. // Returns a file spec given a name (URL form), and resid of an extension to add.
  102. // If ResID is zero, just convert.
  103. // If resid is nonzero and validate is true, check the input name and return an error
  104. //         if the name does NOT have the suffix.
  105. // If resid is nonzero and validate is false, append the suffix to the input name
  106. //-----------------------------------
  107. {
  108.     if (!inName)
  109.         return bdNamErr;
  110. #ifdef DEBUG
  111.     if (XP_STRCHR(inName, ':'))
  112.         XP_ASSERT(0);    // Are they passing us a Mac path? 
  113. #endif
  114.  
  115.     if(validate & stripValFlag) {
  116.         char *dot = XP_STRRCHR(inName, '.');
  117.         if(dot) 
  118.         {
  119.             *dot = '\0';
  120.         }
  121.     }
  122.  
  123.     OSErr err = CFileMgr::FSSpecFromLocalUnixPath(inName, outSpec);
  124.     if (err && err != fnfErr)     /* fnfErr is OK */
  125.         return err;
  126.     if (validate & validateValFlag)
  127.     {
  128.         if (suffix)
  129.         {
  130.             CStr255 extension = suffix;
  131.             SInt32 suffixPosition = (XP_STRLEN(inName) - XP_STRLEN(extension));
  132.             if (suffixPosition < 0)
  133.                 return bdNamErr;
  134.             if (XP_STRCASECMP(extension, inName + suffixPosition) != 0)
  135.                 return bdNamErr;
  136.         }
  137.     }
  138.     if(validate & appendValFlag)
  139.     {
  140.         if (suffix)
  141.         {
  142.             CStr31 extension = suffix;
  143.             CStr63& specName = *(CStr63*)(outSpec->name);
  144.             /* If the total length is greater than 31, we want to 
  145.              * truncate the filename on the right-hand side by the 
  146.              * appropriate amount.
  147.              */
  148.             if(specName.Length() + extension.Length() > 31)
  149.             {
  150.                 specName.Length() = 31 - extension.Length();
  151.             }
  152.             specName += extension;
  153.         } else {
  154.             XP_ASSERT(0);
  155.         }
  156.     }
  157.     
  158.     return noErr;
  159. } // ConvertURLToSpec
  160.  
  161. const char* CacheFilePrefix = "cache";
  162.  
  163. extern long    _fcreator, _ftype;    /* Creator and Type for files created by the open function */
  164.  
  165. //-----------------------------------
  166. OSErr XP_FileSpec(const char *inName, XP_FileType type, FSSpec* outSpec)
  167. // For the Mac, get the Mac specs first
  168. //-----------------------------------
  169. {
  170.     CStr255 tempName(inName);
  171.     OSErr err = noErr;
  172.     _fcreator = emSignature;
  173.     switch (type)    {
  174. /* MAIN FOLDER */
  175.         case xpUserPrefs:    /* Ignored by MacFE */
  176.             err = fnfErr;
  177.             break;
  178.         case xpGlobalHistory:    /* Simple */
  179.             _ftype = emGlobalHistory;
  180.             *outSpec = CPrefs::GetFilePrototype( CPrefs::MainFolder );
  181.             GetIndString(outSpec->name, 300, globHistoryName);
  182.             break;
  183.         case xpImapRootDirectory:
  184.             _ftype = emMailSubdirectory;
  185.             *outSpec = CPrefs::GetFilePrototype( CPrefs::MainFolder );
  186.             *(CStr63*)(outSpec->name) = "\pIMAPmail";
  187.             break;
  188.         case xpImapServerDirectory:
  189.             _ftype = emMailSubdirectory;
  190.             *outSpec = CPrefs::GetFilePrototype( CPrefs::MainFolder );
  191.             *(CStr63*)(outSpec->name) = "\pIMAPmail";
  192.             
  193.             CInfoPBRec infoRecord;
  194.             XP_MEMSET(&infoRecord, 0, sizeof(infoRecord));
  195.             infoRecord.dirInfo.ioDrDirID = 0;
  196.             infoRecord.dirInfo.ioVRefNum = outSpec->vRefNum;
  197.             infoRecord.dirInfo.ioNamePtr = (unsigned char *) CFileMgr::PathNameFromFSSpec(*outSpec, TRUE); 
  198.             if (infoRecord.dirInfo.ioNamePtr)
  199.             {
  200.                 c2pstr((char *) infoRecord.dirInfo.ioNamePtr);
  201.             
  202.                 OSErr getInfoErr = PBGetCatInfoSync(&infoRecord);
  203.                 if (getInfoErr == noErr)
  204.                 {
  205.                     /* any error here is handled by the caller */
  206.                     /* fnfErr is in fact ok for XP_Stat */
  207.                     FSMakeFSSpec(
  208.                         outSpec->vRefNum,
  209.                         infoRecord.dirInfo.ioDrDirID,
  210.                         tempName,
  211.                         outSpec);
  212.                 }
  213.             }
  214.             break;
  215.         case xpBookmarks:
  216.             _ftype = emTextType;
  217.             err = ConvertURLToSpec(inName, outSpec, (ResIDT)0);
  218.             break;
  219. /* MISC */
  220.         case xpTemporary:
  221.             _ftype = emTextType;
  222.             XP_ASSERT(tempName[0] != '/');
  223.             *outSpec = CPrefs::GetTempFilePrototype();
  224.             *(CStr63*)(outSpec->name) = tempName;
  225.             break;
  226.         case xpFileToPost:
  227.             _ftype = emTextType;
  228.             err = ConvertURLToSpec(inName, outSpec, (ResIDT)0);
  229.             break;
  230.         case xpURL:
  231.         case xpExtCache:
  232.             // This does not work if file name contains %. 
  233.             // The problem is that netlib hex-decodes the file names before
  234.             // passing them to XP_File, while other libraries do not
  235.             // Windows has the same bug. atotic
  236.             _ftype = emTextType;                
  237.             err = CFileMgr::FSSpecFromLocalUnixPath( inName, outSpec);
  238.             break;
  239.         case xpMimeTypes:
  240.             *outSpec = CPrefs::GetFilePrototype( CPrefs::MainFolder );
  241.             GetIndString(outSpec->name, 300, mimeTypes);
  242.             break;
  243.         case xpHTTPCookie:
  244.             _ftype = emMagicCookie;
  245.             *outSpec = CPrefs::GetFilePrototype( CPrefs::MainFolder );
  246.             GetIndString(outSpec->name, 300, magicCookie);
  247.             break;
  248.         case xpJSCookieFilters:
  249.             _ftype = emTextType;
  250.             *outSpec = CPrefs::GetFilePrototype( CPrefs::MainFolder );
  251.             *(CStr63*)(outSpec->name) = ":cookies.js";    
  252.             break;
  253.         case xpProxyConfig:
  254.             _ftype = emTextType;
  255.             *outSpec = CPrefs::GetFilePrototype( CPrefs::MainFolder );
  256.             GetIndString(outSpec->name, 300, proxyConfig);
  257.             break;
  258.         case xpSocksConfig:
  259.             _ftype = emTextType;
  260.             *outSpec = CPrefs::GetFilePrototype( CPrefs::MainFolder );
  261.             GetIndString(outSpec->name, 300, socksConfig);
  262.             break;        
  263.         case xpSignature:
  264.             _ftype = emTextType;
  265.             *outSpec = CPrefs::GetFolderSpec( CPrefs::SignatureFile );
  266.             break;
  267.         case xpHTMLAddressBook:
  268.             _ftype = emTextType; // irrelevant
  269.             *outSpec = CPrefs::GetFilePrototype( CPrefs::MainFolder );
  270.             GetIndString(outSpec->name, 300, htmlAddressBook);
  271.             break;
  272.         case xpAddrBookNew:
  273.         case xpAddrBook:
  274.             _ftype = emAddressBookDB;
  275.             *outSpec = CPrefs::GetFilePrototype( CPrefs::MainFolder );
  276.             *(CStr63*)(outSpec->name) = tempName;    
  277.             break;        
  278.         case xpRegistry:
  279.             _ftype = emRegistry;
  280.             err = FindFolder( kOnSystemDisk, kPreferencesFolderType, TRUE, &outSpec->vRefNum, &outSpec->parID);
  281.             GetIndString(outSpec->name, 300, theRegistry);
  282.             break;        
  283.  
  284. /* SECURITY */
  285.         case xpKeyChain:    /* Should probably be the default name instead */
  286.             _ftype = emKeyChain;
  287.             *outSpec = CPrefs::GetFilePrototype( CPrefs::SecurityFolder );
  288.             *(CStr63*)(outSpec->name) = tempName;
  289.             break;
  290.         case xpCertDB:
  291.             _ftype = emCertificates;
  292.             *outSpec = CPrefs::GetFilePrototype( CPrefs::SecurityFolder );
  293.             GetIndString(tempName, 300, certDB);
  294.             if (inName != NULL)
  295.                 tempName += inName;
  296.             *(CStr63*)(outSpec->name) = tempName;    
  297.             break;
  298.         case xpCertDBNameIDX:
  299.             _ftype = emCertIndex;
  300.             *outSpec = CPrefs::GetFilePrototype( CPrefs::SecurityFolder );
  301.             GetIndString(outSpec->name, 300, certDBNameIDX);
  302.             break;    
  303.         case xpKeyDB:
  304.             _ftype = emTextType;
  305.             *outSpec = CPrefs::GetFilePrototype( CPrefs::SecurityFolder );
  306.             GetIndString(tempName, 300, keyDb);
  307.             if (inName != NULL)
  308.                 tempName += inName;
  309.             *(CStr63*)(outSpec->name) = tempName;    
  310.             break;    
  311.         case xpSecModuleDB:
  312.             _ftype = emTextType;
  313.             *outSpec = CPrefs::GetFilePrototype( CPrefs::SecurityFolder );
  314.             GetIndString(tempName, 300, secModuleDb);
  315.             break;    
  316.         case xpSignedAppletDB:
  317.             _ftype = emTextType;
  318.             *outSpec = CPrefs::GetFilePrototype( CPrefs::SecurityFolder );
  319.             GetIndString(tempName, 300, signedAppletDb);
  320.             if (inName != NULL)
  321.                 tempName += inName;
  322.             *(CStr63*)(outSpec->name) = tempName;    
  323.             break;
  324.         case xpCryptoPolicy:
  325.             _ftype = emTextType;
  326.             *outSpec = CPrefs::GetFilePrototype( CPrefs::RequiredGutsFolder);
  327.             GetIndString(outSpec->name, 300, cryptoPolicy);
  328.             break;    
  329. /* CACHE */
  330.         case xpCache:
  331.             _ftype = emTextType;
  332.             *outSpec = CPrefs::GetFilePrototype( CPrefs::DiskCacheFolder );
  333.             *(CStr63*)(outSpec->name) = tempName;
  334.             break;
  335.         case xpCacheFAT:
  336.             _ftype = emCacheFat;
  337.             *outSpec = CPrefs::GetFilePrototype( CPrefs::DiskCacheFolder );
  338.             GetIndString(outSpec->name, 300, cacheLog);
  339.             break;
  340.         case xpExtCacheIndex:
  341.             _ftype = emExtCache;            
  342.             *outSpec = CPrefs::GetFilePrototype( CPrefs::MainFolder );
  343.             GetIndString(outSpec->name, 300, extCacheFile);
  344.             break;    
  345.         case xpSARCache:
  346.             _ftype = emTextType;
  347.             *outSpec = CPrefs::GetFilePrototype( CPrefs::SARCacheFolder );
  348.             *(CStr63*)(outSpec->name) = tempName;
  349.             break;
  350.         case xpSARCacheIndex:
  351.             _ftype = emExtCache;            
  352.             *outSpec = CPrefs::GetFilePrototype( CPrefs::SARCacheFolder );
  353.             GetIndString(outSpec->name, 300, sarCacheIndex);
  354.             break;    
  355. /* NEWS */
  356.         case xpNewsRC:
  357.         case xpSNewsRC:
  358.             _ftype = emNewsrcFile;
  359.             *outSpec = CPrefs::GetFilePrototype( CPrefs::NewsFolder );
  360.             if ( (inName == NULL) || (*inName == 0))
  361.             {
  362.                 GetIndString( tempName, 300, newsrc );
  363.                 /* NET_RegisterNewsrcFile( tempName, inName, type == xpSNewsRC, FALSE ); */
  364.             }
  365.             else
  366.             {
  367.                 tempName = NET_MapNewsrcHostToFilename( (char*)inName, type == xpSNewsRC, FALSE );
  368.                 if ( tempName.IsEmpty() )
  369.                 {
  370.                     // 3.0 -> 4.02 conversion hack:
  371.                     // The missing newsrc file from 3.0 probably is "newsrc"
  372.                     // If we're looking for a file that's not there, try it with "newsrc".
  373.                     // That's because if "foo" is the default host for 3.0, then these things
  374.                     // are true:
  375.                     // (1) When 4.0 is first launched, there is no is no entry in the host
  376.                     //        NewsFAT for foo, and hence no entry in the mapping table for foo.
  377.                     // (2) The entry that SHOULD be in the table for foo is "newsrc".
  378.                     // (3) The entry that 4.0 WOULD make, if the user hadn't run 3.0, is
  379.                     //        newsrc-foo.
  380.                     tempName = "newsrc";
  381.                     *(CStr63*)(outSpec->name) = tempName;
  382.                     FInfo fndrInfo;
  383.                     if (::FSpGetFInfo(outSpec, &fndrInfo) == fnfErr)
  384.                     {
  385.                         char * cstr = CStr255(inName);            // when we have <host:port>,
  386.                         char* macptr = XP_STRCHR(cstr, ':');    // ...replace ':' with '.'
  387.                         if (macptr) *macptr = '.';
  388.     
  389.                         CFileMgr::UniqueFileSpec( *outSpec, cstr, *outSpec );
  390.                         tempName = outSpec->name;
  391.                     }
  392.                     NET_RegisterNewsrcFile( tempName, (char*)inName, type == xpSNewsRC, FALSE );
  393.                 }
  394.             }
  395.             *(CStr63*)(outSpec->name) = tempName;
  396.             break;
  397.         case xpNewsgroups:
  398.             _ftype = emTextType;
  399.             *outSpec = CPrefs::GetFilePrototype( CPrefs::NewsFolder );
  400.             tempName = NET_MapNewsrcHostToFilename((char*)inName, FALSE, TRUE );
  401.             if ( tempName.IsEmpty() )
  402.             {
  403.                 CStr63 newName( "groups-" );
  404.                 newName += inName;
  405.                 tempName = newName;
  406.                 CFileMgr::UniqueFileSpec( *outSpec, CStr31( tempName ), *outSpec );
  407.                 tempName = outSpec->name;
  408.                 NET_RegisterNewsrcFile( tempName, (char*)inName, FALSE, TRUE );
  409.             }
  410.             *(CStr63*)(outSpec->name) = tempName;
  411.             break;
  412.         case xpSNewsgroups:
  413.             _ftype = emTextType;
  414.             *outSpec = CPrefs::GetFilePrototype( CPrefs::NewsFolder );
  415.             tempName = NET_MapNewsrcHostToFilename((char*)inName, TRUE, TRUE );
  416.             if ( tempName.IsEmpty() )
  417.             {
  418.                 CStr63 newName( "sgroups-" );
  419.                 newName += inName;
  420.                 tempName = newName;
  421.                 CFileMgr::UniqueFileSpec( *outSpec, CStr31( tempName ), *outSpec );
  422.                 tempName = outSpec->name;
  423.                 NET_RegisterNewsrcFile( tempName, (char*)inName, TRUE, TRUE );
  424.             }
  425.             *(CStr63*)(outSpec->name) = tempName;
  426.             break;
  427.         case xpTemporaryNewsRC:
  428.             _ftype = emNewsrcFile;
  429.             *outSpec = CPrefs::GetFilePrototype( CPrefs::NewsFolder );
  430.             tempName = "temp newsrc";
  431.             *(CStr63*)(outSpec->name) = tempName;
  432.             break;
  433.         case xpNewsrcFileMap:
  434.             _ftype = emNewsrcDatabase;
  435.             *outSpec = CPrefs::GetFilePrototype( CPrefs::NewsFolder );
  436.             GetIndString(outSpec->name, 300, newsFileMap);
  437.             break;
  438.         case xpXoverCache:
  439.             _ftype = emNewsXoverCache;
  440.             *outSpec = CPrefs::GetFilePrototype(CPrefs::NewsFolder);
  441. //            Boolean isDirectory;
  442. //            long dirID;
  443. //            // Convert the outSpec of the news folder to a dir ID
  444. //            err = FSpGetDirectoryID(outSpec, &dirID, &isDirectory);
  445.             if (!err)
  446.             {
  447. //                Assert_(isDirectory);
  448. //                outSpec->parID = dirID;
  449.                 // Name can contain a slash, so be prepared
  450.  
  451.                 err = CFileMgr::FSSpecFromLocalUnixPath(inName, outSpec);
  452.  
  453. //                // name is now a native partial path
  454. //                err = FSMakeFSSpec(
  455. //                        outSpec->vRefNum,
  456. //                        outSpec->parID,
  457. //                        tempName,
  458. //                        outSpec);
  459.                 if (err == fnfErr) err = noErr;
  460.             }
  461.             break;        
  462.         case xpNewsSort:
  463.             _ftype = emMailFilterRules;
  464.             *outSpec = CPrefs::GetFilePrototype(CPrefs::NewsFolder);
  465.             err = CFileMgr::FSSpecFromLocalUnixPath(inName, outSpec);
  466.             if (err == fnfErr) err = noErr;
  467.             break;
  468.         case xpNewsHostDatabase:
  469.             _ftype = emNewsHostDatabase;
  470.             *outSpec = CPrefs::GetFilePrototype(CPrefs::NewsFolder);
  471.             GetIndString(outSpec->name, 300, newsHostDatabase);
  472.             break;
  473.  
  474. /* MAIL */
  475.         case xpJSMailFilters:
  476.             _ftype = emTextType;
  477.             *outSpec = CPrefs::GetFilePrototype(CPrefs::MailFolder);
  478.             if (inName && *inName)
  479.             {
  480.                 // Make sure there are no colons in the server name
  481.                 char* cp = (char*)&tempName[1];
  482.                 for (int i = 1; i < tempName[0]; i++,cp++)
  483.                     if (*cp == ':') *cp = '.';
  484.                 *(CStr63*)(outSpec->name) += (":" + tempName + ".filters.js"); // in parent of mail folder.
  485.             }
  486.             else
  487.                 *(CStr63*)(outSpec->name) = ":filters.js"; // in parent of mail folder.    
  488.             break;
  489.         case xpMailSort: // normal filters
  490.         {
  491.             _ftype = emMailFilterRules;
  492.             *outSpec = CPrefs::GetFilePrototype(CPrefs::MailFolder);
  493.             if (inName && *inName)
  494.             {
  495.                 // In 5.0, there are rules for each server.
  496.                 // Make sure there are no colons in the server name
  497.                 char* cp = (char*)&tempName[1];
  498.                 for (int i = 1; i < tempName[0]; i++,cp++)
  499.                     if (*cp == ':') *cp = '.';
  500.                 *(CStr63*)(outSpec->name) = (":" + tempName + " Rules"); // in parent of mail folder.
  501.             }
  502.             else
  503.                 GetIndString(outSpec->name, 300, mailFilterFile);// in parent of mail folder.
  504.             break;
  505.         }
  506.         case xpMailFilterLog:
  507.             _ftype = emMailFilterLog;
  508.             *outSpec = CPrefs::GetFilePrototype(CPrefs::MailFolder);
  509.             GetIndString(outSpec->name, 300, mailFilterLog);// in parent of mail folder.
  510.             break;
  511.         case xpMailFolder:
  512.             _ftype = emTextType;
  513.             err = ConvertURLToSpec(inName, outSpec, (ResIDT)0);
  514.             break;
  515.         case xpMailFolderSummary:
  516.             _ftype = emMailFolderSummary;
  517.             err = ConvertURLToSpec(inName, outSpec, mailBoxExt);
  518.             break;
  519.         case xpMailPopState:
  520.             _ftype = emTextType;
  521.             *outSpec = CPrefs::GetFilePrototype(CPrefs::MainFolder);
  522.             GetIndString(outSpec->name, 300, mailPopState);
  523.             break;
  524.         case xpMailSubdirectory:
  525.             _ftype = emMailSubdirectory;
  526.             err = ConvertURLToSpec(inName, outSpec, subdirExt);
  527.             break;
  528.         case xpVCardFile:
  529.             _ftype = emTextType;
  530.             // We are required to check for a '.vcf'
  531.             err = ConvertURLToSpec(inName, outSpec, vCardExt, true);
  532.             break;
  533.         case xpLDIFFile:
  534.             _ftype = emTextType;
  535.             // We are required to check for a '.ldi', '.ldif'
  536.             err = ConvertURLToSpec(inName, outSpec, ldifExt1, true);
  537.             if (err == bdNamErr)
  538.                 err = ConvertURLToSpec(inName, outSpec, ldifExt2, true);
  539.             if ( err == bdNamErr )
  540.             {
  541.                 ConvertURLToSpec(inName, outSpec, 0, false);
  542.                 short refNum;
  543.                 err = ::FSpOpenDF( outSpec,  fsRdPerm, &refNum);
  544.                 FSClose( refNum );
  545.                 if (err == fnfErr)
  546.                     err = ConvertURLToSpec(inName, outSpec, ".ldif", stripAndAppendValFlag);
  547.                 else 
  548.                     err = bdNamErr;
  549.             }
  550.             break;
  551.         case xpPKCS12File:
  552.             _ftype = emTextType;
  553.             // We are required to check for a '.ldi', '.ldif'
  554.             err = ConvertURLToSpec(inName, outSpec, ".p12", stripAndAppendValFlag);
  555.             break;
  556.         case xpFolderCache:
  557.             _ftype = emTextType;
  558.             *outSpec = CPrefs::GetFilePrototype(CPrefs::MainFolder);
  559.             GetIndString(outSpec->name, 300, mailFolderCache);
  560.             break;
  561.         case xpLIClientDB:
  562.             _ftype = emTextType;
  563.             *outSpec = CPrefs::GetFilePrototype( CPrefs::MainFolder );
  564.             *(CStr63*)(outSpec->name) = "LIClientdb.dat";
  565.             break;
  566.         default:
  567.             XP_ASSERT( false );        // Whoever added the enum, it is time to implement it on the Mac
  568.             err = bdNamErr;
  569.             break;
  570.     }
  571.     if ( (err == fnfErr)  )
  572.         err = noErr;
  573.     //XP_ASSERT( err == noErr);
  574.     // Don't assert, sometimes normal flow of control involves an err here.
  575.     return err;
  576. } // XP_FileSpec
  577.  
  578. //-----------------------------------
  579. char* xp_FileName( const char* name, XP_FileType type, char* buf, char* /* unixConfigBuf */ )
  580. //-----------------------------------
  581. {
  582.     FSSpec        macSpec;
  583.     OSErr        err = noErr;
  584.     
  585.     if ( ( type == xpCache ) && name)
  586.     {
  587.         char * cachePath = CPrefs::GetCachePath();
  588.         if (cachePath == NULL)
  589.             err = fnfErr;
  590.         else
  591.         {
  592.             XP_STRCPY(buf, cachePath);
  593.             XP_STRCAT(buf, name);
  594.         }
  595.     }
  596.  
  597. #ifdef _XP_TMP_FILENAME_FOR_LDAP_
  598.     /* this is for address book to have a way of getting a temp file
  599.      * name for each ldap server, yet preserve the temp file name for
  600.      * later use on the same ldap server.  we expect name to be unique
  601.      * to each ldap server and the return would be a temp file name 
  602.      * associated with the ldap server - benjie
  603.      */
  604.     else if ( ( type == xpAddrBook ) && name)
  605.     {
  606.         return FE_GetFileName(name, type);
  607.     }
  608. #endif
  609.  
  610.     else
  611.     {
  612.         char*        path = NULL;
  613.     
  614.         err = XP_FileSpec( name, type, &macSpec );
  615.  
  616.         if (err != noErr)
  617.             return NULL;
  618.             
  619.         path = CFileMgr::PathNameFromFSSpec( macSpec, TRUE );
  620.         
  621.         if ( !path )
  622.             return NULL;
  623.  
  624.         if ((strlen(path) > 1000) )
  625.         {
  626.             XP_ASSERT(FALSE);
  627.             XP_FREE( path );
  628.             return NULL;
  629.         }
  630.  
  631.         XP_STRCPY( buf, path );
  632.         XP_FREE( path );
  633.     }
  634.     if ( err != noErr )
  635.         return NULL;
  636.     return buf;
  637. } // XP_FileSpec
  638.  
  639. //-----------------------------------
  640. char* XP_TempDirName(void)
  641. //-----------------------------------
  642. {
  643.     FSSpec spec = CPrefs::GetTempFilePrototype();
  644.     char* path = CFileMgr::PathNameFromFSSpec(spec, TRUE);
  645.     if (strlen(path) > 1000)
  646.     {
  647.         XP_ASSERT(FALSE);
  648.         return NULL;
  649.     }
  650.     return path;
  651. }
  652.  
  653. //-----------------------------------
  654. char * xp_FilePlatformName(const char * name, char* path)
  655. //-----------------------------------
  656. {
  657.     FSSpec spec;
  658.     OSErr err;
  659.     char * fullPath;
  660.  
  661.     if (name == NULL)
  662.         return NULL;
  663.  
  664.     // Initialize spec, because FSSpecFromLocalUnixPath might use it.
  665.     spec.vRefNum = 0;
  666.     spec.parID = 0;
  667.     err = CFileMgr::FSSpecFromLocalUnixPath(name, &spec);
  668.     // ÑÑÑNOTE: rjc, pchen, and pinkerton changed the behavior of this so that it will no
  669.     // longer return NULL when the file does not exist. If this is a problem, come tell us
  670.     // because we need to change other code.
  671.     if (err != noErr && err != fnfErr && err != dirNFErr )
  672.         return NULL;
  673.     fullPath = CFileMgr::PathNameFromFSSpec( spec, TRUE );
  674.     if (fullPath && (XP_STRLEN(fullPath) < 300))
  675.         XP_STRCPY(path, fullPath);
  676.     else
  677.         return NULL;
  678.     if (fullPath)
  679.         XP_FREE(fullPath);
  680.     return path;
  681. }
  682.  
  683.  
  684. //-----------------------------------
  685. char *XP_PlatformFileToURL(const char * inName)
  686. //-----------------------------------
  687. {
  688.     char *retVal = NULL;
  689.     const char *prefix = "file://";
  690.     /* The inName parameter MUST be a native path, ie colons, spaces, etc.
  691.     ** This assert will help us fix all the various "doubly-encoded path"
  692.     ** bugs  - jrm 97/02/10 */
  693. #ifdef DEBUG
  694.     FSSpec tempSpec;
  695.     OSErr err = ::FSMakeFSSpec(0, 0, CStr255(inName), &tempSpec);
  696.     Boolean nativeMacPath = (err == noErr || err == fnfErr || err == dirNFErr);
  697.     Assert_(nativeMacPath);
  698. #endif
  699.     char *duplicatedName = XP_STRDUP(inName);
  700.     if (duplicatedName)
  701.     {        /* YUCK! duplicatedName  deleted by CFileMgr::EncodeMacPath */
  702.         char *xp_path = CFileMgr::EncodeMacPath(duplicatedName);    
  703.         retVal = (char *) XP_ALLOC (XP_STRLEN(xp_path) + XP_STRLEN(prefix) + 1);
  704.         if (retVal)
  705.         {
  706.             XP_STRCPY (retVal, prefix);
  707.             XP_STRCAT (retVal, xp_path);
  708.         }
  709.         if (xp_path)
  710.             XP_FREE(xp_path);
  711.     }
  712.     return retVal;
  713. }
  714.  
  715. char *XP_PlatformPartialPathToXPPartialPath(const char *sourceStringWithSpaces)
  716. {
  717.     // convert spaces back to %20 quote char
  718.     int numberOfSpaces = 0;
  719.     const char *currentSpace   = XP_STRSTR(sourceStringWithSpaces, " ");
  720.     while (currentSpace)
  721.     {
  722.         numberOfSpaces++;
  723.         currentSpace = XP_STRSTR(currentSpace + 1, " ");
  724.     }
  725.     
  726.     char *escapedReturnString = (char *) XP_ALLOC(XP_STRLEN(sourceStringWithSpaces) + (numberOfSpaces*2) + 1);
  727.     if (escapedReturnString)
  728.     {
  729.         XP_STRCPY(escapedReturnString, sourceStringWithSpaces);
  730.         if (numberOfSpaces)
  731.         {
  732.             char *currentSpace   = XP_STRSTR(escapedReturnString, " ");
  733.             while (currentSpace)
  734.             {
  735.                 XP_MEMMOVE(currentSpace+3,currentSpace+1,XP_STRLEN(currentSpace+1) + 1);
  736.                 *currentSpace++ = '%';
  737.                 *currentSpace++ = '2';
  738.                 *currentSpace++ = '0';
  739.                 currentSpace    = XP_STRSTR(currentSpace, " ");
  740.             }
  741.         }
  742.     }
  743.     
  744.     return escapedReturnString;
  745. }
  746.  
  747. /* Needs to deal with both CR, CRLF, and LF end-of-line */
  748. extern char * XP_FileReadLine(char * dest, int32 bufferSize, XP_File file)
  749. {
  750.     char * retBuf = fgets(dest, bufferSize, file);
  751.     if (retBuf == NULL)    /* EOF */
  752.         return NULL;
  753.     char * LFoccurence = (char *)strchr(retBuf, LF);
  754.     if (LFoccurence != NULL)    /* We have hit LF before CR,  */
  755.     {
  756.         fseek(file, -(strlen(retBuf) - (LFoccurence  - retBuf))+1, SEEK_CUR);
  757.         LFoccurence[1] = 0;
  758.     }
  759.     else    /* We have CR, check if the next character is LF */
  760.     {
  761.         int c;
  762.  
  763.         c = fgetc(file);
  764.  
  765.         if (c == EOF)
  766.             ;    /* Do nothing, end of file */
  767.         else if (c == LF)    /* Swallow CR/LF */
  768.         {
  769.             int len = strlen(retBuf);
  770.             if (len < bufferSize)    /* Append LF to our buffer if we can */
  771.             {
  772.                 retBuf[len++] = LF;
  773.                 retBuf[len] = 0;
  774.             }
  775.         }
  776.         else    /* No LF, just clean up the seek */
  777.         {
  778.             fseek(file, -1, SEEK_CUR);
  779.         }
  780.     }
  781.     return retBuf;
  782. }
  783.  
  784. static counter = 1;    /* temporary name suffix */
  785.  
  786. /* Returns a temp name given a path
  787.  */
  788. char * xp_TempName(XP_FileType type, const char * prefix, char* buf, char* /* buf2 */, unsigned int * /* count */)
  789. {
  790.     FSSpec tempSpec;
  791.     CStr255 defaultName(prefix);
  792.     OSErr err = noErr;
  793.  
  794.     switch (type)    {
  795.         case xpTemporaryNewsRC:
  796.             defaultName = "temp newsrc";
  797.             break;
  798.             break;
  799.         case xpCache:
  800.             defaultName = CacheFilePrefix;
  801.             CStr255 dateString;
  802.             ::NumToString (::TickCount(), dateString);
  803.             defaultName += dateString;
  804.             break;
  805.         case xpBookmarks:
  806.             defaultName += ".bak";
  807.             break;
  808.         case xpJPEGFile:
  809.             defaultName += ".jpeg";
  810.             break;
  811.         case xpMailFolder:    /* Ugly. MailFolder callers for temporary names pass in the full path */
  812.         case xpMailFolderSummary:    /* Ugly. MailFolder callers for temporary names pass in the full path */
  813.             {
  814.                 FSSpec temp;
  815.                 err = XP_FileSpec(prefix, xpMailFolder, &temp);
  816.                 if (err == noErr)
  817.                     defaultName = temp.name;
  818.             }
  819.         case xpFileToPost:    /* Temporary files to post return the full path */
  820.             
  821.         case xpTemporary:
  822.         default:
  823.             if ( (type == xpURL) && prefix ) 
  824.             {
  825.                 if ( XP_STRRCHR(prefix, '/') )
  826.                 {
  827.                     XP_StatStruct st;
  828.                     if (XP_Stat (defaultName, &st, xpURL))
  829.                         XP_MakeDirectoryR (defaultName, xpURL);
  830.                     defaultName += "su";
  831.                 }
  832.             }
  833.  
  834.             if (defaultName.IsEmpty())
  835.                 defaultName = "nstemp";
  836.             CStr255 counterS;
  837.             ::NumToString(counter++, counterS);
  838.             defaultName += counterS;    /* Need counter to guarantee uniqueness if called several times in a row */
  839.             break;
  840.     }
  841.     if (type == xpFileToPost || type == xpMailFolder || type == xpMailFolderSummary || ((type == xpURL) && !prefix)) 
  842.     {
  843.         if (defaultName.Length() > 30)    // Someone has passed in something weird as a prefix
  844.         {
  845.             XP_ASSERT(false);
  846.             defaultName.Delete(30, 1000);
  847.         }
  848.         err = XP_FileSpec(defaultName, xpTemporary, &tempSpec);
  849.     }
  850.     else
  851.         err = XP_FileSpec(defaultName, type, &tempSpec);
  852.  
  853.     if (err && err != fnfErr)
  854.         return NULL;
  855.  
  856.     FSSpec finalSpec;
  857.     err = CFileMgr::UniqueFileSpec(tempSpec, tempSpec.name, finalSpec);
  858.     if (err != noErr)
  859.     {
  860.         XP_ASSERT(FALSE);
  861.         return NULL;
  862.     }
  863.     if ((type == xpFileToPost) || 
  864.         (type == xpBookmarks) ||
  865.         (type == xpMailFolder) || 
  866.         (type == xpURL) ||
  867.         (type == xpMailFolderSummary))
  868.     /* These files needs full pathname */
  869.     {
  870.         char* tempPath = CFileMgr::PathNameFromFSSpec( finalSpec, TRUE );
  871.         tempPath = CFileMgr::EncodeMacPath(tempPath);
  872.         if (tempPath == NULL)
  873.             return NULL;
  874.         else if (XP_STRLEN(tempPath) > 500)    /* Buffer overflow check */
  875.         {
  876.             XP_FREE(tempPath);
  877.             return NULL;
  878.         }
  879.             XP_STRCPY(buf, tempPath);
  880.         XP_FREE(tempPath);
  881.     }
  882.     else
  883.         XP_STRCPY(buf, CStr63(finalSpec.name));
  884.     return buf;
  885. } /* xp_TempName */
  886.  
  887.  
  888.  
  889. /* XP_OpenDir is not handling different directories yet. */
  890. XP_Dir XP_OpenDir( const char* name, XP_FileType type )
  891. {
  892.     CInfoPBRec        pb;
  893.     OSErr            err;
  894.     DirInfo*        dipb;
  895.     struct dirstruct *        dir = XP_NEW(struct dirstruct);
  896.  
  897.     if (dir == NULL)
  898.         return NULL;
  899.  
  900.     XP_TRACE(( "opening file: %s", name ));
  901.     dir->type = type;
  902.     
  903.     err = XP_FileSpec( name, type, &dir->dirSpecs );
  904.     if ( err != noErr )
  905.     {
  906.         XP_DELETE(dir);
  907.         return NULL;
  908.     }
  909.  
  910.     dipb = (DirInfo*)&pb;
  911.  
  912.     pb.hFileInfo.ioNamePtr = dir->dirSpecs.name;
  913.     pb.hFileInfo.ioVRefNum = dir->dirSpecs.vRefNum;
  914.     pb.hFileInfo.ioDirID = dir->dirSpecs.parID;
  915.     pb.hFileInfo.ioFDirIndex = 0;    /* use ioNamePtr and ioDirID */
  916.  
  917.     err = PBGetCatInfoSync( &pb );
  918.  
  919.     /* test that we have gotten a directory back, not a file */
  920.     if ( (err != noErr ) || !( dipb->ioFlAttrib & 0x0010 ) )
  921.     {
  922.         XP_DELETE( dir );
  923.         return NULL;
  924.     }
  925.     dir->dirSpecs.parID = pb.hFileInfo.ioDirID;
  926.     dir->index = pb.dirInfo.ioDrNmFls;
  927.  
  928.     return (XP_Dir)dir;
  929. }
  930.  
  931. void XP_CloseDir( XP_Dir dir )
  932. {
  933.     if ( dir )
  934.         XP_DELETE(dir);
  935. }
  936.  
  937. int XP_FileNumberOfFilesInDirectory(const char * dir_name, XP_FileType type)
  938. {
  939.     FSSpec spec;
  940.     OSErr err = XP_FileSpec(dir_name, type, &spec);
  941.     if ((err != noErr) && (err != fnfErr))
  942.         goto loser;
  943.     CInfoPBRec pb;
  944.     pb.hFileInfo.ioNamePtr = spec.name;
  945.     pb.hFileInfo.ioVRefNum = spec.vRefNum;
  946.     pb.hFileInfo.ioDirID = spec.parID;
  947.     pb.hFileInfo.ioFDirIndex = 0;    /* use ioNamePtr and ioDirID */
  948.     err = PBGetCatInfoSync(&pb);
  949.     if (err != noErr)
  950.         goto loser;
  951.     return pb.dirInfo.ioDrNmFls;
  952. loser:
  953.     return 10000;    /* ???? */
  954. }
  955.  
  956. XP_DirEntryStruct * XP_ReadDir(XP_Dir dir)
  957. {
  958. tryagain:
  959.     if (dir->index <= 0)
  960.         return NULL;
  961.     CInfoPBRec cipb;
  962.     DirInfo    *dipb=(DirInfo *)&cipb;
  963.     dipb->ioCompletion = NULL;
  964.     dipb->ioFDirIndex = dir->index;
  965.     dipb->ioVRefNum = dir->dirSpecs.vRefNum; /* Might need to use vRefNum, not sure*/
  966.     dipb->ioDrDirID = dir->dirSpecs.parID;
  967.     dipb->ioNamePtr = (StringPtr)&dir->dirent.d_name;
  968.     OSErr err = PBGetCatInfoSync (&cipb);
  969.     /* We are traversing the directory backwards */
  970.     if (err != noErr)
  971.     {
  972.         if (dir->index > 1)
  973.         {
  974.             dir->index--;
  975.             goto tryagain;
  976.         }
  977.         else
  978.             return NULL;
  979.     }
  980.     p2cstr((StringPtr)&dir->dirent.d_name);
  981.  
  982.     /* Mail folders are treated in a special way */
  983.  
  984.     if ((dir->type == xpMailFolder) ||
  985.         (dir->type == xpMailFolderSummary) ||
  986.         (dir->type == xpMailSubdirectory) ) 
  987.     {
  988.         char * newName = XP_STRDUP(dir->dirent.d_name);
  989.         newName = CFileMgr::EncodeMacPath(newName);
  990.         if (newName)
  991.         {
  992.             XP_STRCPY(dir->dirent.d_name, newName);
  993.             XP_FREE(newName);
  994.         }
  995.     }
  996.  
  997.     dir->index--;
  998.     return &dir->dirent;
  999. }
  1000.  
  1001. int XP_MakeDirectory(const char* name, XP_FileType type)
  1002. {
  1003.     FSSpec spec;
  1004.     OSErr err = XP_FileSpec(name, type, &spec);
  1005.     if ((err != noErr) && (err != fnfErr))    /* Should not happen */
  1006.         return -1;
  1007.     short refNum;
  1008.     long dirID;
  1009.     err = CFileMgr::CreateFolderInFolder(
  1010.                 spec.vRefNum, spec.parID, spec.name, /* Name of the new folder */
  1011.                 &refNum, &dirID);
  1012.     if (err != noErr)
  1013.         return -1;
  1014.     return 0;
  1015. }
  1016.  
  1017. /* Recursively create all the directories
  1018.  */
  1019. int XP_MakeDirectoryR(const char* name, XP_FileType type)
  1020. {
  1021.     char separator;
  1022.     int result = 0;
  1023.     XP_FILE_NATIVE_PATH finalNameNative = NULL;
  1024.     XP_FILE_URL_PATH finalName = NULL;
  1025.     char * dirPath = NULL;
  1026.     separator = '/';
  1027.  
  1028.     if ( type == xpURL)
  1029.         finalNameNative = CFileMgr::MacPathFromUnixPath(name);
  1030.     else
  1031.         finalNameNative = WH_FileName(name, type);
  1032.     
  1033.     if ( finalNameNative == NULL )
  1034.     {
  1035.         result  = -1;
  1036.         goto done;
  1037.     }
  1038.     finalName = XP_PlatformFileToURL(finalNameNative);
  1039.     if ( finalName )
  1040.     {
  1041.         char * currentEnd;
  1042.         int err = 0;
  1043.         XP_StatStruct s;
  1044.         dirPath = XP_STRDUP( &finalName[7] );    // Skip the file://
  1045.         if (dirPath == NULL)
  1046.         {
  1047.             result = -1;
  1048.             goto done;
  1049.         }
  1050.  
  1051.         currentEnd = XP_STRCHR(dirPath, separator);
  1052.         if (currentEnd)
  1053.             currentEnd = XP_STRCHR(¤tEnd[1], separator);
  1054.         /* Loop through every part of the directory path */
  1055.         while (currentEnd != 0)
  1056.         {
  1057.             char savedChar;
  1058.             savedChar = currentEnd[1];
  1059.             currentEnd[1] = 0;
  1060.             if ( XP_Stat(dirPath, &s, xpURL ) != 0)
  1061.                 err = XP_MakeDirectory(dirPath, xpURL);
  1062.             if ( err != 0)
  1063.             {
  1064.                 XP_ASSERT( FALSE );    /* Could not create the directory? */
  1065.                 break;
  1066.             }
  1067.             currentEnd[1] = savedChar;
  1068.             currentEnd = XP_STRCHR( ¤tEnd[1], separator);
  1069.         }
  1070.         if ( err == 0 )
  1071.         /* If the path is not terminated with / */
  1072.         {
  1073.             if ( dirPath[XP_STRLEN( dirPath) - 1] != separator )
  1074.                 if ( XP_Stat(dirPath, &s, xpURL ) != 0)
  1075.                     err = XP_MakeDirectory(dirPath, xpURL);
  1076.         }
  1077.         if ( 0 != err )
  1078.             result = err;
  1079.     }
  1080.     else
  1081.         result = -1;
  1082. done:
  1083.     XP_FREEIF(finalName);
  1084.     XP_FREEIF(finalNameNative);
  1085.     XP_FREEIF(dirPath);
  1086.     XP_ASSERT( result == 0 );    /* For debugging only */
  1087.     return result;
  1088. }
  1089.  
  1090. int XP_RemoveDirectory (const char* name, XP_FileType type)
  1091. {
  1092.     FSSpec spec;
  1093.     OSErr err = XP_FileSpec(name, type, &spec);
  1094.     if ((err != noErr) && (err != fnfErr))
  1095.         return -1;
  1096.     err = ::FSpDelete(&spec);
  1097.     if (err != noErr)
  1098.         return -1;
  1099.     return 0;
  1100. }
  1101.  
  1102. // Removes the directory and its contents.
  1103. int XP_RemoveDirectoryRecursive(const char *name, XP_FileType type)
  1104. {
  1105.     OSErr err;
  1106.     FSSpec dirSpec;
  1107.     
  1108.     err = XP_FileSpec(name, type, &dirSpec);
  1109.     if ((err != noErr) && (err != fnfErr))
  1110.             return -1;
  1111.     err = DeleteDirectory(dirSpec.vRefNum, dirSpec.parID, dirSpec.name);
  1112.     return (err == noErr) ? 0 : -1;
  1113. }
  1114.  
  1115. int XP_FileRename( const char* from, XP_FileType fromtype,
  1116.                    const char* to, XP_FileType totype )
  1117. {
  1118.     OSErr err = noErr;
  1119.     
  1120.     char* fromName = WH_FileName( from, fromtype );
  1121.     char* toName = WH_FileName( to, totype );
  1122.     
  1123.     if ( fromName && toName )
  1124.     {
  1125.         FSSpec toSpec;
  1126.         err = CFileMgr::FSSpecFromPathname( toName, &toSpec );
  1127.         if (err == noErr || err == fnfErr)
  1128.         {
  1129.             FSSpec fromSpec;
  1130.             err = CFileMgr::FSSpecFromPathname( fromName, &fromSpec );
  1131.             if (err == noErr || err == fnfErr)
  1132.             {
  1133.                 
  1134.                 if (fromSpec.vRefNum == toSpec.vRefNum)    
  1135.                 /* Same volume */
  1136.                 {
  1137.                     /* But, er, is it the same file (jrm 97/08/20)? */
  1138.                     if (fromSpec.parID == toSpec.parID
  1139.                     && *(CStr63*)fromSpec.name == *(CStr63*)toSpec.name)
  1140.                         goto Cleanup; // YOW!  Don't delete it!
  1141.     
  1142.                     /* Delete the file */
  1143.                     ::FSpDelete( &toSpec ); /* ignore error if not there */
  1144.                     if (fromSpec.parID == toSpec.parID)
  1145.                     {
  1146.                         /* this is a flat node rename use ::FSpRename */
  1147.                         err = ::FSpRename(&fromSpec, toSpec.name);
  1148.                     }
  1149.                     else
  1150.                     {
  1151.                         /* we are moving a file between dirs so use HMoveRenameCompat */
  1152.                         err = ::HMoveRenameCompat(
  1153.                             fromSpec.vRefNum,
  1154.                             fromSpec.parID, (ConstStr255Param)fromSpec.name,
  1155.                             toSpec.parID, nil, (StringPtr)toSpec.name);
  1156.                     }
  1157.                 }
  1158.                 else    
  1159.                 /* Different volumes */
  1160.                 {
  1161.                     FSSpec toDir;
  1162.                     err = CFileMgr::FolderSpecFromFolderID(toSpec.vRefNum, toSpec.parID, toDir);
  1163.                     if (err == noErr)
  1164.                     {                    
  1165.                         ::FSpDelete( &toSpec );
  1166.                         err = FSpFileCopy( &fromSpec, &toDir, toSpec.name, NULL, 0, true );
  1167.                         if ( err == noErr)
  1168.                             ::FSpDelete( &fromSpec );
  1169.                     }
  1170.                 }
  1171.             }
  1172.         }
  1173.             
  1174.     }
  1175.     else
  1176.         err = -1;
  1177. Cleanup:
  1178.     if ( fromName )
  1179.         XP_FREE( fromName );
  1180.     if ( toName )
  1181.         XP_FREE( toName );
  1182.     if (err != noErr)
  1183.         return -1;
  1184.     return 0;
  1185. }
  1186.  
  1187. int XP_FileRemove( const char* name, XP_FileType type )
  1188. {
  1189.     FSSpec        spec;
  1190.     OSErr        err;
  1191.  
  1192.     err = XP_FileSpec( name, type, &spec);
  1193.  
  1194.     if ( err == noErr )
  1195.     {
  1196.         err = ::FSpDelete( &spec );
  1197.         if ( type == xpNewsRC || type == xpNewsgroups )
  1198.             NET_UnregisterNewsHost( name, FALSE );
  1199.         else if ( type == xpSNewsRC || type == xpSNewsgroups)
  1200.             NET_UnregisterNewsHost( name, TRUE );
  1201.     }
  1202.     
  1203.     if ( err == noErr )
  1204.         return 0;
  1205.     return -1;
  1206. }
  1207.  
  1208. int XP_FileTruncate( const char* name, XP_FileType type, int32 len )
  1209. {
  1210.     FSSpec        spec;
  1211.     OSErr        err, err2;
  1212.     short refNum;
  1213.  
  1214.     if (len < 0)
  1215.         return EINVAL;
  1216.  
  1217.     err = XP_FileSpec( name, type, &spec);
  1218.     if (err != noErr)
  1219.         return EINVAL;
  1220.  
  1221.     err = FSpOpenDF(&spec, fsRdWrPerm, &refNum);
  1222.     if (err != noErr)
  1223.         return EACCES;
  1224.     
  1225.     err = SetEOF(refNum, len);
  1226.     
  1227.     err2 = FSClose(refNum);
  1228.     if ((err != noErr) || (err2 != noErr))
  1229.         return EIO;
  1230.     return 0;
  1231. }
  1232.  
  1233.  
  1234. int XP_FileDuplicateResourceFork( const char* oldFilePath, XP_FileType oldType,
  1235.                                     const char* newFilePath, XP_FileType newType )
  1236. {
  1237.     OSErr err;
  1238.     FSSpec oldfs, newfs;
  1239.     err = XP_FileSpec( oldFilePath, oldType, &oldfs);
  1240.     if (err != noErr)
  1241.         return EINVAL;
  1242.  
  1243.     err = XP_FileSpec( newFilePath, newType, &newfs);
  1244.     if (err != noErr)
  1245.         return EINVAL;
  1246.  
  1247.     short    oldFileRefNum = -1, newFileRefNum = -1;
  1248.     oldFileRefNum = FSpOpenResFileCompat( &oldfs, fsCurPerm );
  1249.     err = ResError();
  1250.     if ( err  || ( oldFileRefNum == -1 ) )
  1251.     {
  1252.         return EACCES;
  1253.     }
  1254.     
  1255.     // assume we need to create the new resource fork 
  1256.     // (may not be valid assumption for other uses of this function)
  1257.     FSpCreateResFileCompat( &newfs, emSignature, emTextType, smSystemScript );
  1258.     err = ResError();
  1259.     
  1260.     newFileRefNum = FSpOpenResFileCompat( &newfs, fsRdWrPerm );
  1261.     err = ResError();
  1262.     if ( err || ( newFileRefNum == -1 ) )
  1263.     {
  1264.         err = FSClose( oldFileRefNum );
  1265.         XP_ASSERT(0);
  1266.         return EACCES;
  1267.     }
  1268.     
  1269.     long buffsize = 1024;
  1270.     char buff[ 1024 ];
  1271.     err = CopyFork( oldFileRefNum, newFileRefNum, buff, buffsize);
  1272.  
  1273.     FSClose( oldFileRefNum );
  1274.     FSClose( newFileRefNum );
  1275.     
  1276.     if ( err )
  1277.         return EIO;
  1278.     
  1279.     return 0;
  1280. }
  1281.  
  1282. //======================================
  1283. // I put these stubs here.  They can go away when we move to MSL.
  1284. //======================================
  1285.  
  1286. PR_EXTERN(char*) PR_GetEnv(const char *var);
  1287. extern "C" {
  1288.     char* PR_GetEnv(const char *var);
  1289.     char* getenv(const char *var);
  1290. }
  1291.  
  1292. char* getenv(const char *var)
  1293. {
  1294.     return PR_GetEnv(var);
  1295. }
  1296.  
  1297.