mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-28 03:18:41 +00:00
1343 lines
36 KiB
C++
1343 lines
36 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||
*
|
||
* The contents of this file are subject to the Netscape Public License
|
||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||
* http://www.mozilla.org/NPL/
|
||
*
|
||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||
* for the specific language governing rights and limitations under the
|
||
* NPL.
|
||
*
|
||
* The Initial Developer of this code under the NPL is Netscape
|
||
* Communications Corporation. Portions created by Netscape are
|
||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||
* Reserved.
|
||
*/
|
||
|
||
/* xp_file_mac.h
|
||
* Mac-only xp_file functions
|
||
*/
|
||
#include "xp_file_mac.h"
|
||
|
||
/* macfe */
|
||
#include "resgui.h"
|
||
#include "ufilemgr.h"
|
||
#include "uprefd.h"
|
||
|
||
/* utilities */
|
||
#include "MoreFilesExtras.h"
|
||
#include "FSpCompat.h"
|
||
#include "FileCopy.h"
|
||
#include "PascalString.h"
|
||
#include <Files.h>
|
||
#include <Folders.h>
|
||
#include <LString.h>
|
||
#include "cstring.h"
|
||
|
||
// validation flags for overloaded ConvertURLToSpec
|
||
enum ConvertURLValidationFlags {
|
||
validateValFlag = 0x00000001,
|
||
stripValFlag = 0x00000002,
|
||
appendValFlag = 0x00000004,
|
||
stripAndAppendValFlag = (stripValFlag | appendValFlag) };
|
||
|
||
// Prototypes
|
||
OSErr ConvertURLToSpec
|
||
(const char* inName,
|
||
FSSpec* outSpec,
|
||
ResIDT resid = 0,
|
||
Boolean validate = false);
|
||
OSErr ConvertURLToSpec(
|
||
const char* inName,
|
||
FSSpec* outSpec,
|
||
const char* suffix = nil,
|
||
ConvertURLValidationFlags validate = validateValFlag);
|
||
|
||
/**************************************************************************************
|
||
* See xp_file.h for full documentation. BE SURE TO READ THAT FILE.
|
||
**************************************************************************************/
|
||
|
||
//-----------------------------------
|
||
OSErr ConvertURLToSpec(const char* inName, FSSpec* outSpec, ResIDT resid, Boolean validate)
|
||
// Returns a file spec given a name (URL form), and resid of an extension to add.
|
||
// If ResID is zero, just convert.
|
||
// If resid is nonzero and validate is true, check the input name and return an error
|
||
// if the name does NOT have the suffix.
|
||
// If resid is nonzero and validate is false, append the suffix to the input name
|
||
//-----------------------------------
|
||
{
|
||
if (!inName)
|
||
return bdNamErr;
|
||
#ifdef DEBUG
|
||
if (XP_STRCHR(inName, ':'))
|
||
XP_ASSERT(0); // Are they passing us a Mac path?
|
||
#endif
|
||
|
||
OSErr err = CFileMgr::FSSpecFromLocalUnixPath(inName, outSpec);
|
||
if (err && err != fnfErr) /* fnfErr is OK */
|
||
return err;
|
||
if (resid)
|
||
{
|
||
CStr255 extension;
|
||
::GetIndString(extension, 300, resid);
|
||
if (validate)
|
||
{
|
||
SInt32 suffixPosition = (XP_STRLEN(inName) - XP_STRLEN(extension));
|
||
if (suffixPosition < 0)
|
||
return bdNamErr;
|
||
if (XP_STRCASECMP(extension, inName + suffixPosition) != 0)
|
||
return bdNamErr;
|
||
}
|
||
else
|
||
*(CStr63*)(outSpec->name) += extension;
|
||
}
|
||
return noErr;
|
||
} // ConvertURLToSpec
|
||
|
||
//-----------------------------------
|
||
OSErr ConvertURLToSpec(const char* inName, FSSpec* outSpec, const char* suffix,
|
||
ConvertURLValidationFlags validate)
|
||
// Returns a file spec given a name (URL form), and resid of an extension to add.
|
||
// If ResID is zero, just convert.
|
||
// If resid is nonzero and validate is true, check the input name and return an error
|
||
// if the name does NOT have the suffix.
|
||
// If resid is nonzero and validate is false, append the suffix to the input name
|
||
//-----------------------------------
|
||
{
|
||
if (!inName)
|
||
return bdNamErr;
|
||
#ifdef DEBUG
|
||
if (XP_STRCHR(inName, ':'))
|
||
XP_ASSERT(0); // Are they passing us a Mac path?
|
||
#endif
|
||
|
||
if(validate & stripValFlag) {
|
||
char *dot = XP_STRRCHR(inName, '.');
|
||
if(dot)
|
||
{
|
||
*dot = '\0';
|
||
}
|
||
}
|
||
|
||
OSErr err = CFileMgr::FSSpecFromLocalUnixPath(inName, outSpec);
|
||
if (err && err != fnfErr) /* fnfErr is OK */
|
||
return err;
|
||
if (validate & validateValFlag)
|
||
{
|
||
if (suffix)
|
||
{
|
||
CStr255 extension = suffix;
|
||
SInt32 suffixPosition = (XP_STRLEN(inName) - XP_STRLEN(extension));
|
||
if (suffixPosition < 0)
|
||
return bdNamErr;
|
||
if (XP_STRCASECMP(extension, inName + suffixPosition) != 0)
|
||
return bdNamErr;
|
||
}
|
||
}
|
||
if(validate & appendValFlag)
|
||
{
|
||
if (suffix)
|
||
{
|
||
CStr31 extension = suffix;
|
||
CStr63& specName = *(CStr63*)(outSpec->name);
|
||
/* If the total length is greater than 31, we want to
|
||
* truncate the filename on the right-hand side by the
|
||
* appropriate amount.
|
||
*/
|
||
if(specName.Length() + extension.Length() > 31)
|
||
{
|
||
specName.Length() = 31 - extension.Length();
|
||
}
|
||
specName += extension;
|
||
} else {
|
||
XP_ASSERT(0);
|
||
}
|
||
}
|
||
|
||
return noErr;
|
||
} // ConvertURLToSpec
|
||
|
||
const char* CacheFilePrefix = "cache";
|
||
|
||
extern long _fcreator, _ftype; /* Creator and Type for files created by the open function */
|
||
|
||
//-----------------------------------
|
||
OSErr XP_FileSpec(const char *inName, XP_FileType type, FSSpec* outSpec)
|
||
// For the Mac, get the Mac specs first
|
||
//-----------------------------------
|
||
{
|
||
CStr255 tempName(inName);
|
||
OSErr err = noErr;
|
||
_fcreator = emSignature;
|
||
switch (type) {
|
||
/* MAIN FOLDER */
|
||
case xpUserPrefs: /* Ignored by MacFE */
|
||
err = fnfErr;
|
||
break;
|
||
case xpGlobalHistory: /* Simple */
|
||
_ftype = emGlobalHistory;
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::MainFolder );
|
||
GetIndString(outSpec->name, 300, globHistoryName);
|
||
break;
|
||
#ifdef MOZ_MAIL_NEWS
|
||
case xpImapRootDirectory:
|
||
_ftype = emMailSubdirectory;
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::MainFolder );
|
||
*(CStr63*)(outSpec->name) = "\pIMAPmail";
|
||
break;
|
||
case xpImapServerDirectory:
|
||
_ftype = emMailSubdirectory;
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::MainFolder );
|
||
*(CStr63*)(outSpec->name) = "\pIMAPmail";
|
||
|
||
FSSpec tempSpec;
|
||
OSErr getInfoErr = FSMakeFSSpec(
|
||
outSpec->vRefNum,
|
||
outSpec->parID,
|
||
outSpec->name,
|
||
&tempSpec);
|
||
if (getInfoErr == fnfErr)
|
||
{
|
||
// We have to make the root imap directory ourselves.
|
||
long ignored;
|
||
err = FSpDirCreate(outSpec, smSystemScript, &ignored);
|
||
if (err)
|
||
break;
|
||
}
|
||
CInfoPBRec infoRecord;
|
||
XP_MEMSET(&infoRecord, 0, sizeof(infoRecord));
|
||
infoRecord.dirInfo.ioDrDirID = outSpec->parID;
|
||
infoRecord.dirInfo.ioVRefNum = outSpec->vRefNum;
|
||
infoRecord.dirInfo.ioNamePtr = outSpec->name;
|
||
getInfoErr = PBGetCatInfoSync(&infoRecord);
|
||
if (getInfoErr == noErr)
|
||
{
|
||
/* any error here is handled by the caller */
|
||
/* fnfErr is in fact ok for XP_Stat */
|
||
FSMakeFSSpec(
|
||
outSpec->vRefNum,
|
||
infoRecord.dirInfo.ioDrDirID,
|
||
tempName,
|
||
outSpec);
|
||
}
|
||
|
||
break;
|
||
#endif
|
||
case xpBookmarks:
|
||
_ftype = emTextType;
|
||
err = ConvertURLToSpec(inName, outSpec, (ResIDT)0);
|
||
break;
|
||
/* MISC */
|
||
case xpTemporary:
|
||
_ftype = emTextType;
|
||
XP_ASSERT(tempName[0] != '/');
|
||
*outSpec = CPrefs::GetTempFilePrototype();
|
||
*(CStr63*)(outSpec->name) = tempName;
|
||
break;
|
||
case xpFileToPost:
|
||
_ftype = emTextType;
|
||
err = ConvertURLToSpec(inName, outSpec, (ResIDT)0);
|
||
break;
|
||
case xpURL:
|
||
case xpExtCache:
|
||
// This does not work if file name contains %.
|
||
// The problem is that netlib hex-decodes the file names before
|
||
// passing them to XP_File, while other libraries do not
|
||
// Windows has the same bug. atotic
|
||
_ftype = emTextType;
|
||
err = CFileMgr::FSSpecFromLocalUnixPath( inName, outSpec);
|
||
break;
|
||
case xpMimeTypes:
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::MainFolder );
|
||
GetIndString(outSpec->name, 300, mimeTypes);
|
||
break;
|
||
case xpHTTPCookie:
|
||
_ftype = emMagicCookie;
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::MainFolder );
|
||
GetIndString(outSpec->name, 300, magicCookie);
|
||
break;
|
||
#ifdef CookieManagement
|
||
case xpHTTPCookiePermission:
|
||
_ftype = emMagicCookie; // is this right?
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::MainFolder );
|
||
GetIndString(outSpec->name, 300, cookiePermissions);
|
||
break;
|
||
#endif
|
||
case xpJSCookieFilters:
|
||
_ftype = emTextType;
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::MainFolder );
|
||
*(CStr63*)(outSpec->name) = ":cookies.js";
|
||
break;
|
||
#ifdef SingleSignon
|
||
case xpHTTPSingleSignon:
|
||
_ftype = emMagicCookie; // is this right?
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::MainFolder );
|
||
GetIndString(outSpec->name, 300, singleSignons);
|
||
break;
|
||
#endif
|
||
case xpProxyConfig:
|
||
_ftype = emTextType;
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::MainFolder );
|
||
GetIndString(outSpec->name, 300, proxyConfig);
|
||
break;
|
||
case xpJSConfig:
|
||
_ftype = emTextType;
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::MainFolder );
|
||
GetIndString(outSpec->name, 300, jsConfig);
|
||
break;
|
||
|
||
|
||
|
||
|
||
case xpSocksConfig:
|
||
_ftype = emTextType;
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::MainFolder );
|
||
GetIndString(outSpec->name, 300, socksConfig);
|
||
break;
|
||
case xpSignature:
|
||
_ftype = emTextType;
|
||
*outSpec = CPrefs::GetFolderSpec( CPrefs::SignatureFile );
|
||
break;
|
||
case xpHTMLAddressBook:
|
||
_ftype = emTextType; // irrelevant
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::MainFolder );
|
||
GetIndString(outSpec->name, 300, htmlAddressBook);
|
||
break;
|
||
#ifdef MOZ_MAIL_NEWS
|
||
case xpAddrBookNew:
|
||
case xpAddrBook:
|
||
_ftype = emAddressBookDB;
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::MainFolder );
|
||
*(CStr63*)(outSpec->name) = tempName;
|
||
break;
|
||
#endif
|
||
case xpRegistry:
|
||
_ftype = emRegistry;
|
||
err = FindFolder( kOnSystemDisk, kPreferencesFolderType, TRUE, &outSpec->vRefNum, &outSpec->parID);
|
||
GetIndString(outSpec->name, 300, theRegistry);
|
||
break;
|
||
|
||
/* SECURITY */
|
||
case xpKeyChain: /* Should probably be the default name instead */
|
||
_ftype = emKeyChain;
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::SecurityFolder );
|
||
*(CStr63*)(outSpec->name) = tempName;
|
||
break;
|
||
case xpCertDB:
|
||
_ftype = emCertificates;
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::SecurityFolder );
|
||
GetIndString(tempName, 300, certDB);
|
||
if (inName != NULL)
|
||
tempName += inName;
|
||
*(CStr63*)(outSpec->name) = tempName;
|
||
break;
|
||
case xpCertDBNameIDX:
|
||
_ftype = emCertIndex;
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::SecurityFolder );
|
||
GetIndString(outSpec->name, 300, certDBNameIDX);
|
||
break;
|
||
case xpKeyDB:
|
||
_ftype = emTextType;
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::SecurityFolder );
|
||
GetIndString(tempName, 300, keyDb);
|
||
if (inName != NULL)
|
||
tempName += inName;
|
||
*(CStr63*)(outSpec->name) = tempName;
|
||
break;
|
||
case xpSecModuleDB:
|
||
_ftype = emTextType;
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::SecurityFolder );
|
||
GetIndString(tempName, 300, secModuleDb);
|
||
break;
|
||
case xpSignedAppletDB:
|
||
_ftype = emTextType;
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::SecurityFolder );
|
||
GetIndString(tempName, 300, signedAppletDb);
|
||
if (inName != NULL)
|
||
tempName += inName;
|
||
*(CStr63*)(outSpec->name) = tempName;
|
||
break;
|
||
case xpCryptoPolicy:
|
||
_ftype = emTextType;
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::RequiredGutsFolder);
|
||
GetIndString(outSpec->name, 300, cryptoPolicy);
|
||
break;
|
||
/* CACHE */
|
||
case xpCache:
|
||
_ftype = emTextType;
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::DiskCacheFolder );
|
||
*(CStr63*)(outSpec->name) = tempName;
|
||
break;
|
||
case xpCacheFAT:
|
||
_ftype = emCacheFat;
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::DiskCacheFolder );
|
||
GetIndString(outSpec->name, 300, cacheLog);
|
||
break;
|
||
case xpExtCacheIndex:
|
||
_ftype = emExtCache;
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::MainFolder );
|
||
GetIndString(outSpec->name, 300, extCacheFile);
|
||
break;
|
||
case xpSARCache:
|
||
_ftype = emTextType;
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::SARCacheFolder );
|
||
*(CStr63*)(outSpec->name) = tempName;
|
||
break;
|
||
case xpSARCacheIndex:
|
||
_ftype = emExtCache;
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::SARCacheFolder );
|
||
GetIndString(outSpec->name, 300, sarCacheIndex);
|
||
break;
|
||
/* NEWS */
|
||
case xpNewsRC:
|
||
case xpSNewsRC:
|
||
#ifdef MOZ_MAIL_NEWS
|
||
_ftype = emNewsrcFile;
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::NewsFolder );
|
||
if ( (inName == NULL) || (*inName == 0))
|
||
{
|
||
GetIndString( tempName, 300, newsrc );
|
||
NET_RegisterNewsrcFile( tempName, inName, type == xpSNewsRC, FALSE );
|
||
}
|
||
else
|
||
{
|
||
tempName = NET_MapNewsrcHostToFilename( (char*)inName, type == xpSNewsRC, FALSE );
|
||
if ( tempName.IsEmpty() )
|
||
{
|
||
// 3.0 -> 4.02 conversion hack:
|
||
// The missing newsrc file from 3.0 probably is "newsrc"
|
||
// If we're looking for a file that's not there, try it with "newsrc".
|
||
// That's because if "foo" is the default host for 3.0, then these things
|
||
// are true:
|
||
// (1) When 4.0 is first launched, there is no is no entry in the host
|
||
// NewsFAT for foo, and hence no entry in the mapping table for foo.
|
||
// (2) The entry that SHOULD be in the table for foo is "newsrc".
|
||
// (3) The entry that 4.0 WOULD make, if the user hadn't run 3.0, is
|
||
// newsrc-foo.
|
||
tempName = "newsrc";
|
||
*(CStr63*)(outSpec->name) = tempName;
|
||
FInfo fndrInfo;
|
||
if (::FSpGetFInfo(outSpec, &fndrInfo) == fnfErr)
|
||
{
|
||
char * cstr = CStr255(inName); // when we have <host:port>,
|
||
char* macptr = XP_STRCHR(cstr, ':'); // ...replace ':' with '.'
|
||
if (macptr) *macptr = '.';
|
||
|
||
CFileMgr::UniqueFileSpec( *outSpec, cstr, *outSpec );
|
||
tempName = outSpec->name;
|
||
}
|
||
NET_RegisterNewsrcFile( tempName, (char*)inName, type == xpSNewsRC, FALSE );
|
||
}
|
||
}
|
||
*(CStr63*)(outSpec->name) = tempName;
|
||
break;
|
||
case xpNewsgroups:
|
||
_ftype = emTextType;
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::NewsFolder );
|
||
tempName = NET_MapNewsrcHostToFilename((char*)inName, FALSE, TRUE );
|
||
if ( tempName.IsEmpty() )
|
||
{
|
||
CStr63 newName( "groups-" );
|
||
newName += inName;
|
||
tempName = newName;
|
||
CFileMgr::UniqueFileSpec( *outSpec, CStr31( tempName ), *outSpec );
|
||
tempName = outSpec->name;
|
||
NET_RegisterNewsrcFile( tempName, (char*)inName, FALSE, TRUE );
|
||
}
|
||
*(CStr63*)(outSpec->name) = tempName;
|
||
break;
|
||
case xpSNewsgroups:
|
||
_ftype = emTextType;
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::NewsFolder );
|
||
tempName = NET_MapNewsrcHostToFilename((char*)inName, TRUE, TRUE );
|
||
if ( tempName.IsEmpty() )
|
||
{
|
||
CStr63 newName( "sgroups-" );
|
||
newName += inName;
|
||
tempName = newName;
|
||
CFileMgr::UniqueFileSpec( *outSpec, CStr31( tempName ), *outSpec );
|
||
tempName = outSpec->name;
|
||
NET_RegisterNewsrcFile( tempName, (char*)inName, TRUE, TRUE );
|
||
}
|
||
*(CStr63*)(outSpec->name) = tempName;
|
||
break;
|
||
case xpTemporaryNewsRC:
|
||
_ftype = emNewsrcFile;
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::NewsFolder );
|
||
tempName = "temp newsrc";
|
||
*(CStr63*)(outSpec->name) = tempName;
|
||
break;
|
||
case xpNewsrcFileMap:
|
||
_ftype = emNewsrcDatabase;
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::NewsFolder );
|
||
GetIndString(outSpec->name, 300, newsFileMap);
|
||
break;
|
||
case xpXoverCache:
|
||
_ftype = emNewsXoverCache;
|
||
*outSpec = CPrefs::GetFilePrototype(CPrefs::NewsFolder);
|
||
// Boolean isDirectory;
|
||
// long dirID;
|
||
// // Convert the outSpec of the news folder to a dir ID
|
||
// err = FSpGetDirectoryID(outSpec, &dirID, &isDirectory);
|
||
if (!err)
|
||
{
|
||
// Assert_(isDirectory);
|
||
// outSpec->parID = dirID;
|
||
// Name can contain a slash, so be prepared
|
||
|
||
err = CFileMgr::FSSpecFromLocalUnixPath(inName, outSpec);
|
||
|
||
// // name is now a native partial path
|
||
// err = FSMakeFSSpec(
|
||
// outSpec->vRefNum,
|
||
// outSpec->parID,
|
||
// tempName,
|
||
// outSpec);
|
||
if (err == fnfErr) err = noErr;
|
||
}
|
||
break;
|
||
case xpNewsSort:
|
||
_ftype = emMailFilterRules;
|
||
*outSpec = CPrefs::GetFilePrototype(CPrefs::NewsFolder);
|
||
err = CFileMgr::FSSpecFromLocalUnixPath(inName, outSpec);
|
||
if (err == fnfErr) err = noErr;
|
||
break;
|
||
case xpNewsHostDatabase:
|
||
_ftype = emNewsHostDatabase;
|
||
*outSpec = CPrefs::GetFilePrototype(CPrefs::NewsFolder);
|
||
GetIndString(outSpec->name, 300, newsHostDatabase);
|
||
break;
|
||
|
||
case xpJSMailFilters:
|
||
_ftype = emTextType;
|
||
*outSpec = CPrefs::GetFilePrototype(CPrefs::MailFolder);
|
||
if (inName && *inName)
|
||
{
|
||
// Make sure there are no colons in the server name
|
||
char* cp = (char*)&tempName[1];
|
||
for (int i = 1; i < tempName[0]; i++,cp++)
|
||
if (*cp == ':') *cp = '.';
|
||
*(CStr63*)(outSpec->name) += (":" + tempName + ".filters.js"); // in parent of mail folder.
|
||
}
|
||
else
|
||
*(CStr63*)(outSpec->name) = ":filters.js"; // in parent of mail folder.
|
||
break;
|
||
case xpMailSort: // normal filters
|
||
{
|
||
_ftype = emMailFilterRules;
|
||
*outSpec = CPrefs::GetFilePrototype(CPrefs::MailFolder);
|
||
if (inName && *inName)
|
||
{
|
||
// In 5.0, there are rules for each server.
|
||
// Make sure there are no colons in the server name
|
||
char* cp = (char*)&tempName[1];
|
||
for (int i = 1; i < tempName[0]; i++,cp++)
|
||
if (*cp == ':') *cp = '.';
|
||
*(CStr63*)(outSpec->name) = (":" + tempName + " Rules"); // in parent of mail folder.
|
||
}
|
||
else
|
||
GetIndString(outSpec->name, 300, mailFilterFile);// in parent of mail folder.
|
||
break;
|
||
}
|
||
case xpMailFilterLog:
|
||
_ftype = emMailFilterLog;
|
||
*outSpec = CPrefs::GetFilePrototype(CPrefs::MailFolder);
|
||
GetIndString(outSpec->name, 300, mailFilterLog);// in parent of mail folder.
|
||
break;
|
||
case xpMailFolder:
|
||
_ftype = emTextType;
|
||
err = ConvertURLToSpec(inName, outSpec, (ResIDT)0);
|
||
break;
|
||
case xpMailFolderSummary:
|
||
_ftype = emMailFolderSummary;
|
||
err = ConvertURLToSpec(inName, outSpec, mailBoxExt);
|
||
break;
|
||
case xpMailPopState:
|
||
_ftype = emTextType;
|
||
*outSpec = CPrefs::GetFilePrototype(CPrefs::MainFolder);
|
||
GetIndString(outSpec->name, 300, mailPopState);
|
||
break;
|
||
case xpMailSubdirectory:
|
||
_ftype = emMailSubdirectory;
|
||
err = ConvertURLToSpec(inName, outSpec, subdirExt);
|
||
break;
|
||
case xpVCardFile:
|
||
_ftype = emTextType;
|
||
// We are required to check for a '.vcf'
|
||
err = ConvertURLToSpec(inName, outSpec, vCardExt, true);
|
||
break;
|
||
case xpLDIFFile:
|
||
_ftype = emTextType;
|
||
// We are required to check for a '.ldi', '.ldif'
|
||
err = ConvertURLToSpec(inName, outSpec, ldifExt1, true);
|
||
if (err == bdNamErr)
|
||
err = ConvertURLToSpec(inName, outSpec, ldifExt2, true);
|
||
if ( err == bdNamErr )
|
||
{
|
||
ConvertURLToSpec(inName, outSpec, 0, false);
|
||
short refNum;
|
||
err = ::FSpOpenDF( outSpec, fsRdPerm, &refNum);
|
||
FSClose( refNum );
|
||
if (err == fnfErr)
|
||
err = ConvertURLToSpec(inName, outSpec, ".ldif", stripAndAppendValFlag);
|
||
else
|
||
err = bdNamErr;
|
||
}
|
||
break;
|
||
case xpPKCS12File:
|
||
_ftype = emTextType;
|
||
// We are required to check for a '.ldi', '.ldif'
|
||
err = ConvertURLToSpec(inName, outSpec, ".p12", stripAndAppendValFlag);
|
||
break;
|
||
case xpFolderCache:
|
||
_ftype = emTextType;
|
||
*outSpec = CPrefs::GetFilePrototype(CPrefs::MainFolder);
|
||
GetIndString(outSpec->name, 300, mailFolderCache);
|
||
break;
|
||
case xpLIClientDB:
|
||
_ftype = emTextType;
|
||
*outSpec = CPrefs::GetFilePrototype( CPrefs::MainFolder );
|
||
*(CStr63*)(outSpec->name) = "LIClientdb.dat";
|
||
break;
|
||
case xpLIPrefs:
|
||
_ftype = emTextType;
|
||
*outSpec = CPrefs::GetFilePrototype(CPrefs::MainFolder);
|
||
*(CStr63*)(outSpec->name) = "liprefs.js";
|
||
break;
|
||
#endif // ifdef MOZ_MAILNEWS
|
||
|
||
default:
|
||
XP_ASSERT( false ); // Whoever added the enum, it is time to implement it on the Mac
|
||
err = bdNamErr;
|
||
break;
|
||
}
|
||
if ( (err == fnfErr) )
|
||
err = noErr;
|
||
//XP_ASSERT( err == noErr);
|
||
// Don't assert, sometimes normal flow of control involves an err here.
|
||
return err;
|
||
} // XP_FileSpec
|
||
|
||
//-----------------------------------
|
||
char* xp_FileName( const char* name, XP_FileType type, char* buf, char* /* unixConfigBuf */ )
|
||
//-----------------------------------
|
||
{
|
||
FSSpec macSpec;
|
||
OSErr err = noErr;
|
||
|
||
if ( ( type == xpCache ) && name)
|
||
{
|
||
char * cachePath = CPrefs::GetCachePath();
|
||
if (cachePath == NULL)
|
||
err = fnfErr;
|
||
else
|
||
{
|
||
XP_STRCPY(buf, cachePath);
|
||
XP_STRCAT(buf, name);
|
||
}
|
||
}
|
||
|
||
#ifdef _XP_TMP_FILENAME_FOR_LDAP_
|
||
/* this is for address book to have a way of getting a temp file
|
||
* name for each ldap server, yet preserve the temp file name for
|
||
* later use on the same ldap server. we expect name to be unique
|
||
* to each ldap server and the return would be a temp file name
|
||
* associated with the ldap server - benjie
|
||
*/
|
||
else if ( ( type == xpAddrBook ) && name)
|
||
{
|
||
return FE_GetFileName(name, type);
|
||
}
|
||
#endif
|
||
|
||
else
|
||
{
|
||
char* path = NULL;
|
||
|
||
err = XP_FileSpec( name, type, &macSpec );
|
||
|
||
if (err != noErr)
|
||
return NULL;
|
||
|
||
path = CFileMgr::PathNameFromFSSpec( macSpec, TRUE );
|
||
|
||
if ( !path )
|
||
return NULL;
|
||
|
||
if ((strlen(path) > 1000) )
|
||
{
|
||
XP_ASSERT(FALSE);
|
||
XP_FREE( path );
|
||
return NULL;
|
||
}
|
||
|
||
XP_STRCPY( buf, path );
|
||
XP_FREE( path );
|
||
}
|
||
if ( err != noErr )
|
||
return NULL;
|
||
return buf;
|
||
} // XP_FileSpec
|
||
|
||
//-----------------------------------
|
||
char* XP_TempDirName(void)
|
||
//-----------------------------------
|
||
{
|
||
FSSpec spec = CPrefs::GetTempFilePrototype();
|
||
char* path = CFileMgr::PathNameFromFSSpec(spec, TRUE);
|
||
if (strlen(path) > 1000)
|
||
{
|
||
XP_ASSERT(FALSE);
|
||
return NULL;
|
||
}
|
||
return path;
|
||
}
|
||
|
||
//-----------------------------------
|
||
char * xp_FilePlatformName(const char * name, char* path)
|
||
//-----------------------------------
|
||
{
|
||
FSSpec spec;
|
||
OSErr err;
|
||
char * fullPath;
|
||
|
||
if (name == NULL)
|
||
return NULL;
|
||
|
||
// Initialize spec, because FSSpecFromLocalUnixPath might use it.
|
||
spec.vRefNum = 0;
|
||
spec.parID = 0;
|
||
err = CFileMgr::FSSpecFromLocalUnixPath(name, &spec);
|
||
// <20><><EFBFBD>NOTE: rjc, pchen, and pinkerton changed the behavior of this so that it will no
|
||
// longer return NULL when the file does not exist. If this is a problem, come tell us
|
||
// because we need to change other code.
|
||
if (err != noErr && err != fnfErr && err != dirNFErr )
|
||
return NULL;
|
||
fullPath = CFileMgr::PathNameFromFSSpec( spec, TRUE );
|
||
if (fullPath && (XP_STRLEN(fullPath) < 300))
|
||
XP_STRCPY(path, fullPath);
|
||
else
|
||
return NULL;
|
||
if (fullPath)
|
||
XP_FREE(fullPath);
|
||
return path;
|
||
}
|
||
|
||
|
||
//-----------------------------------
|
||
char *XP_PlatformFileToURL(const char * inName)
|
||
//-----------------------------------
|
||
{
|
||
char *retVal = NULL;
|
||
const char *prefix = "file://";
|
||
/* The inName parameter MUST be a native path, ie colons, spaces, etc.
|
||
** This assert will help us fix all the various "doubly-encoded path"
|
||
** bugs - jrm 97/02/10 */
|
||
#ifdef DEBUG
|
||
FSSpec tempSpec;
|
||
OSErr err = ::FSMakeFSSpec(0, 0, CStr255(inName), &tempSpec);
|
||
Boolean nativeMacPath = (err == noErr || err == fnfErr || err == dirNFErr);
|
||
Assert_(nativeMacPath);
|
||
#endif
|
||
char *duplicatedName = XP_STRDUP(inName);
|
||
if (duplicatedName)
|
||
{ /* YUCK! duplicatedName deleted by CFileMgr::EncodeMacPath */
|
||
char *xp_path = CFileMgr::EncodeMacPath(duplicatedName);
|
||
retVal = (char *) XP_ALLOC (XP_STRLEN(xp_path) + XP_STRLEN(prefix) + 1);
|
||
if (retVal)
|
||
{
|
||
XP_STRCPY (retVal, prefix);
|
||
XP_STRCAT (retVal, xp_path);
|
||
}
|
||
if (xp_path)
|
||
XP_FREE(xp_path);
|
||
}
|
||
return retVal;
|
||
}
|
||
|
||
char *XP_PlatformPartialPathToXPPartialPath(const char *sourceStringWithSpaces)
|
||
{
|
||
// convert spaces back to %20 quote char
|
||
int numberOfSpaces = 0;
|
||
const char *currentSpace = XP_STRSTR(sourceStringWithSpaces, " ");
|
||
while (currentSpace)
|
||
{
|
||
numberOfSpaces++;
|
||
currentSpace = XP_STRSTR(currentSpace + 1, " ");
|
||
}
|
||
|
||
char *escapedReturnString = (char *) XP_ALLOC(XP_STRLEN(sourceStringWithSpaces) + (numberOfSpaces*2) + 1);
|
||
if (escapedReturnString)
|
||
{
|
||
XP_STRCPY(escapedReturnString, sourceStringWithSpaces);
|
||
if (numberOfSpaces)
|
||
{
|
||
char *currentSpace = XP_STRSTR(escapedReturnString, " ");
|
||
while (currentSpace)
|
||
{
|
||
XP_MEMMOVE(currentSpace+3,currentSpace+1,XP_STRLEN(currentSpace+1) + 1);
|
||
*currentSpace++ = '%';
|
||
*currentSpace++ = '2';
|
||
*currentSpace++ = '0';
|
||
currentSpace = XP_STRSTR(currentSpace, " ");
|
||
}
|
||
}
|
||
}
|
||
|
||
return escapedReturnString;
|
||
}
|
||
|
||
/* Needs to deal with both CR, CRLF, and LF end-of-line */
|
||
extern char * XP_FileReadLine(char * dest, int32 bufferSize, XP_File file)
|
||
{
|
||
char * retBuf = fgets(dest, bufferSize, file);
|
||
if (retBuf == NULL) /* EOF */
|
||
return NULL;
|
||
char * LFoccurence = (char *)strchr(retBuf, LF);
|
||
if (LFoccurence != NULL) /* We have hit LF before CR, */
|
||
{
|
||
fseek(file, -(strlen(retBuf) - (LFoccurence - retBuf))+1, SEEK_CUR);
|
||
LFoccurence[1] = 0;
|
||
}
|
||
else /* We have CR, check if the next character is LF */
|
||
{
|
||
int c;
|
||
|
||
c = fgetc(file);
|
||
|
||
if (c == EOF)
|
||
; /* Do nothing, end of file */
|
||
else if (c == LF) /* Swallow CR/LF */
|
||
{
|
||
int len = strlen(retBuf);
|
||
if (len < bufferSize) /* Append LF to our buffer if we can */
|
||
{
|
||
retBuf[len++] = LF;
|
||
retBuf[len] = 0;
|
||
}
|
||
}
|
||
else /* No LF, just clean up the seek */
|
||
{
|
||
fseek(file, -1, SEEK_CUR);
|
||
}
|
||
}
|
||
return retBuf;
|
||
}
|
||
|
||
static counter = 1; /* temporary name suffix */
|
||
|
||
/* Returns a temp name given a path
|
||
*/
|
||
char * xp_TempName(XP_FileType type, const char * prefix, char* buf, char* /* buf2 */, unsigned int * /* count */)
|
||
{
|
||
FSSpec tempSpec;
|
||
CStr255 defaultName(prefix);
|
||
OSErr err = noErr;
|
||
|
||
switch (type) {
|
||
case xpTemporaryNewsRC:
|
||
defaultName = "temp newsrc";
|
||
break;
|
||
break;
|
||
case xpCache:
|
||
defaultName = CacheFilePrefix;
|
||
CStr255 dateString;
|
||
::NumToString (::TickCount(), dateString);
|
||
defaultName += dateString;
|
||
break;
|
||
case xpBookmarks:
|
||
defaultName += ".bak";
|
||
break;
|
||
case xpJPEGFile:
|
||
defaultName += ".jpeg";
|
||
break;
|
||
case xpMailFolder: /* Ugly. MailFolder callers for temporary names pass in the full path */
|
||
case xpMailFolderSummary: /* Ugly. MailFolder callers for temporary names pass in the full path */
|
||
{
|
||
FSSpec temp;
|
||
err = XP_FileSpec(prefix, xpMailFolder, &temp);
|
||
if (err == noErr)
|
||
defaultName = temp.name;
|
||
}
|
||
case xpFileToPost: /* Temporary files to post return the full path */
|
||
|
||
case xpTemporary:
|
||
default:
|
||
if ( (type == xpURL) && prefix )
|
||
{
|
||
if ( XP_STRRCHR(prefix, '/') )
|
||
{
|
||
XP_StatStruct st;
|
||
if (XP_Stat (defaultName, &st, xpURL))
|
||
XP_MakeDirectoryR (defaultName, xpURL);
|
||
defaultName += "su";
|
||
}
|
||
}
|
||
|
||
if (defaultName.IsEmpty())
|
||
defaultName = "nstemp";
|
||
CStr255 counterS;
|
||
::NumToString(counter++, counterS);
|
||
defaultName += counterS; /* Need counter to guarantee uniqueness if called several times in a row */
|
||
break;
|
||
}
|
||
if (type == xpFileToPost || type == xpMailFolder || type == xpMailFolderSummary || ((type == xpURL) && !prefix))
|
||
{
|
||
if (defaultName.Length() > 30) // Someone has passed in something weird as a prefix
|
||
{
|
||
XP_ASSERT(false);
|
||
defaultName.Delete(30, 1000);
|
||
}
|
||
err = XP_FileSpec(defaultName, xpTemporary, &tempSpec);
|
||
}
|
||
else
|
||
err = XP_FileSpec(defaultName, type, &tempSpec);
|
||
|
||
if (err && err != fnfErr)
|
||
return NULL;
|
||
|
||
FSSpec finalSpec;
|
||
err = CFileMgr::UniqueFileSpec(tempSpec, tempSpec.name, finalSpec);
|
||
if (err != noErr)
|
||
{
|
||
XP_ASSERT(FALSE);
|
||
return NULL;
|
||
}
|
||
if ((type == xpFileToPost) ||
|
||
(type == xpBookmarks) ||
|
||
(type == xpMailFolder) ||
|
||
(type == xpURL) ||
|
||
(type == xpMailFolderSummary))
|
||
/* These files needs full pathname */
|
||
{
|
||
char* tempPath = CFileMgr::PathNameFromFSSpec( finalSpec, TRUE );
|
||
tempPath = CFileMgr::EncodeMacPath(tempPath);
|
||
if (tempPath == NULL)
|
||
return NULL;
|
||
else if (XP_STRLEN(tempPath) > 500) /* Buffer overflow check */
|
||
{
|
||
XP_FREE(tempPath);
|
||
return NULL;
|
||
}
|
||
XP_STRCPY(buf, tempPath);
|
||
XP_FREE(tempPath);
|
||
}
|
||
else
|
||
XP_STRCPY(buf, CStr63(finalSpec.name));
|
||
return buf;
|
||
} /* xp_TempName */
|
||
|
||
|
||
|
||
/* XP_OpenDir is not handling different directories yet. */
|
||
XP_Dir XP_OpenDir( const char* name, XP_FileType type )
|
||
{
|
||
CInfoPBRec pb;
|
||
OSErr err;
|
||
DirInfo* dipb;
|
||
struct dirstruct * dir = XP_NEW(struct dirstruct);
|
||
|
||
if (dir == NULL)
|
||
return NULL;
|
||
|
||
XP_TRACE(( "opening file: %s", name ));
|
||
dir->type = type;
|
||
|
||
err = XP_FileSpec( name, type, &dir->dirSpecs );
|
||
if ( err != noErr )
|
||
{
|
||
XP_DELETE(dir);
|
||
return NULL;
|
||
}
|
||
|
||
dipb = (DirInfo*)&pb;
|
||
|
||
pb.hFileInfo.ioNamePtr = dir->dirSpecs.name;
|
||
pb.hFileInfo.ioVRefNum = dir->dirSpecs.vRefNum;
|
||
pb.hFileInfo.ioDirID = dir->dirSpecs.parID;
|
||
pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */
|
||
|
||
err = PBGetCatInfoSync( &pb );
|
||
|
||
/* test that we have gotten a directory back, not a file */
|
||
if ( (err != noErr ) || !( dipb->ioFlAttrib & 0x0010 ) )
|
||
{
|
||
XP_DELETE( dir );
|
||
return NULL;
|
||
}
|
||
dir->dirSpecs.parID = pb.hFileInfo.ioDirID;
|
||
dir->index = pb.dirInfo.ioDrNmFls;
|
||
|
||
return (XP_Dir)dir;
|
||
}
|
||
|
||
void XP_CloseDir( XP_Dir dir )
|
||
{
|
||
if ( dir )
|
||
XP_DELETE(dir);
|
||
}
|
||
|
||
int XP_FileNumberOfFilesInDirectory(const char * dir_name, XP_FileType type)
|
||
{
|
||
FSSpec spec;
|
||
OSErr err = XP_FileSpec(dir_name, type, &spec);
|
||
if ((err != noErr) && (err != fnfErr))
|
||
goto loser;
|
||
CInfoPBRec pb;
|
||
pb.hFileInfo.ioNamePtr = spec.name;
|
||
pb.hFileInfo.ioVRefNum = spec.vRefNum;
|
||
pb.hFileInfo.ioDirID = spec.parID;
|
||
pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */
|
||
err = PBGetCatInfoSync(&pb);
|
||
if (err != noErr)
|
||
goto loser;
|
||
return pb.dirInfo.ioDrNmFls;
|
||
loser:
|
||
return 10000; /* ???? */
|
||
}
|
||
|
||
XP_DirEntryStruct * XP_ReadDir(XP_Dir dir)
|
||
{
|
||
tryagain:
|
||
if (dir->index <= 0)
|
||
return NULL;
|
||
CInfoPBRec cipb;
|
||
DirInfo *dipb=(DirInfo *)&cipb;
|
||
dipb->ioCompletion = NULL;
|
||
dipb->ioFDirIndex = dir->index;
|
||
dipb->ioVRefNum = dir->dirSpecs.vRefNum; /* Might need to use vRefNum, not sure*/
|
||
dipb->ioDrDirID = dir->dirSpecs.parID;
|
||
dipb->ioNamePtr = (StringPtr)&dir->dirent.d_name;
|
||
OSErr err = PBGetCatInfoSync (&cipb);
|
||
/* We are traversing the directory backwards */
|
||
if (err != noErr)
|
||
{
|
||
if (dir->index > 1)
|
||
{
|
||
dir->index--;
|
||
goto tryagain;
|
||
}
|
||
else
|
||
return NULL;
|
||
}
|
||
p2cstr((StringPtr)&dir->dirent.d_name);
|
||
|
||
/* Mail folders are treated in a special way */
|
||
|
||
if ((dir->type == xpMailFolder) ||
|
||
(dir->type == xpMailFolderSummary) ||
|
||
(dir->type == xpMailSubdirectory) )
|
||
{
|
||
char * newName = XP_STRDUP(dir->dirent.d_name);
|
||
newName = CFileMgr::EncodeMacPath(newName);
|
||
if (newName)
|
||
{
|
||
XP_STRCPY(dir->dirent.d_name, newName);
|
||
XP_FREE(newName);
|
||
}
|
||
}
|
||
|
||
dir->index--;
|
||
return &dir->dirent;
|
||
}
|
||
|
||
int XP_MakeDirectory(const char* name, XP_FileType type)
|
||
{
|
||
FSSpec spec;
|
||
OSErr err = XP_FileSpec(name, type, &spec);
|
||
if ((err != noErr) && (err != fnfErr)) /* Should not happen */
|
||
return -1;
|
||
short refNum;
|
||
long dirID;
|
||
err = CFileMgr::CreateFolderInFolder(
|
||
spec.vRefNum, spec.parID, spec.name, /* Name of the new folder */
|
||
&refNum, &dirID);
|
||
if (err != noErr)
|
||
return -1;
|
||
return 0;
|
||
}
|
||
|
||
/* Recursively create all the directories
|
||
*/
|
||
int XP_MakeDirectoryR(const char* name, XP_FileType type)
|
||
{
|
||
char separator;
|
||
int result = 0;
|
||
XP_FILE_NATIVE_PATH finalNameNative = NULL;
|
||
XP_FILE_URL_PATH finalName = NULL;
|
||
char * dirPath = NULL;
|
||
separator = '/';
|
||
|
||
if ( type == xpURL)
|
||
finalNameNative = CFileMgr::MacPathFromUnixPath(name);
|
||
else
|
||
finalNameNative = WH_FileName(name, type);
|
||
|
||
if ( finalNameNative == NULL )
|
||
{
|
||
result = -1;
|
||
goto done;
|
||
}
|
||
finalName = XP_PlatformFileToURL(finalNameNative);
|
||
if ( finalName )
|
||
{
|
||
char * currentEnd;
|
||
int err = 0;
|
||
XP_StatStruct s;
|
||
dirPath = XP_STRDUP( &finalName[7] ); // Skip the file://
|
||
if (dirPath == NULL)
|
||
{
|
||
result = -1;
|
||
goto done;
|
||
}
|
||
|
||
currentEnd = XP_STRCHR(dirPath, separator);
|
||
if (currentEnd)
|
||
currentEnd = XP_STRCHR(¤tEnd[1], separator);
|
||
/* Loop through every part of the directory path */
|
||
while (currentEnd != 0)
|
||
{
|
||
char savedChar;
|
||
savedChar = currentEnd[1];
|
||
currentEnd[1] = 0;
|
||
if ( XP_Stat(dirPath, &s, xpURL ) != 0)
|
||
err = XP_MakeDirectory(dirPath, xpURL);
|
||
if ( err != 0)
|
||
{
|
||
XP_ASSERT( FALSE ); /* Could not create the directory? */
|
||
break;
|
||
}
|
||
currentEnd[1] = savedChar;
|
||
currentEnd = XP_STRCHR( ¤tEnd[1], separator);
|
||
}
|
||
if ( err == 0 )
|
||
/* If the path is not terminated with / */
|
||
{
|
||
if ( dirPath[XP_STRLEN( dirPath) - 1] != separator )
|
||
if ( XP_Stat(dirPath, &s, xpURL ) != 0)
|
||
err = XP_MakeDirectory(dirPath, xpURL);
|
||
}
|
||
if ( 0 != err )
|
||
result = err;
|
||
}
|
||
else
|
||
result = -1;
|
||
done:
|
||
XP_FREEIF(finalName);
|
||
XP_FREEIF(finalNameNative);
|
||
XP_FREEIF(dirPath);
|
||
XP_ASSERT( result == 0 ); /* For debugging only */
|
||
return result;
|
||
}
|
||
|
||
int XP_RemoveDirectory (const char* name, XP_FileType type)
|
||
{
|
||
FSSpec spec;
|
||
OSErr err = XP_FileSpec(name, type, &spec);
|
||
if ((err != noErr) && (err != fnfErr))
|
||
return -1;
|
||
err = ::FSpDelete(&spec);
|
||
if (err != noErr)
|
||
return -1;
|
||
return 0;
|
||
}
|
||
|
||
// Removes the directory and its contents.
|
||
int XP_RemoveDirectoryRecursive(const char *name, XP_FileType type)
|
||
{
|
||
OSErr err;
|
||
FSSpec dirSpec;
|
||
|
||
err = XP_FileSpec(name, type, &dirSpec);
|
||
if ((err != noErr) && (err != fnfErr))
|
||
return -1;
|
||
err = DeleteDirectory(dirSpec.vRefNum, dirSpec.parID, dirSpec.name);
|
||
return (err == noErr) ? 0 : -1;
|
||
}
|
||
|
||
int XP_FileRename( const char* from, XP_FileType fromtype,
|
||
const char* to, XP_FileType totype )
|
||
{
|
||
OSErr err = noErr;
|
||
|
||
char* fromName = WH_FileName( from, fromtype );
|
||
char* toName = WH_FileName( to, totype );
|
||
|
||
if ( fromName && toName )
|
||
{
|
||
FSSpec toSpec;
|
||
err = CFileMgr::FSSpecFromPathname( toName, &toSpec );
|
||
if (err == noErr || err == fnfErr)
|
||
{
|
||
FSSpec fromSpec;
|
||
err = CFileMgr::FSSpecFromPathname( fromName, &fromSpec );
|
||
if (err == noErr || err == fnfErr)
|
||
{
|
||
|
||
if (fromSpec.vRefNum == toSpec.vRefNum)
|
||
/* Same volume */
|
||
{
|
||
/* But, er, is it the same file (jrm 97/08/20)? */
|
||
if (fromSpec.parID == toSpec.parID
|
||
&& *(CStr63*)fromSpec.name == *(CStr63*)toSpec.name)
|
||
goto Cleanup; // YOW! Don't delete it!
|
||
|
||
/* Delete the file */
|
||
::FSpDelete( &toSpec ); /* ignore error if not there */
|
||
if (fromSpec.parID == toSpec.parID)
|
||
{
|
||
/* this is a flat node rename use ::FSpRename */
|
||
err = ::FSpRename(&fromSpec, toSpec.name);
|
||
}
|
||
else
|
||
{
|
||
/* we are moving a file between dirs so use HMoveRenameCompat */
|
||
err = ::HMoveRenameCompat(
|
||
fromSpec.vRefNum,
|
||
fromSpec.parID, (ConstStr255Param)fromSpec.name,
|
||
toSpec.parID, nil, (StringPtr)toSpec.name);
|
||
}
|
||
}
|
||
else
|
||
/* Different volumes */
|
||
{
|
||
FSSpec toDir;
|
||
err = CFileMgr::FolderSpecFromFolderID(toSpec.vRefNum, toSpec.parID, toDir);
|
||
if (err == noErr)
|
||
{
|
||
::FSpDelete( &toSpec );
|
||
err = FSpFileCopy( &fromSpec, &toDir, toSpec.name, NULL, 0, true );
|
||
if ( err == noErr)
|
||
::FSpDelete( &fromSpec );
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
else
|
||
err = -1;
|
||
Cleanup:
|
||
if ( fromName )
|
||
XP_FREE( fromName );
|
||
if ( toName )
|
||
XP_FREE( toName );
|
||
if (err != noErr)
|
||
return -1;
|
||
return 0;
|
||
}
|
||
|
||
int XP_FileRemove( const char* name, XP_FileType type )
|
||
{
|
||
FSSpec spec;
|
||
OSErr err;
|
||
|
||
err = XP_FileSpec( name, type, &spec);
|
||
|
||
if ( err == noErr )
|
||
{
|
||
err = ::FSpDelete( &spec );
|
||
#ifdef MOZ_MAIL_NEWS
|
||
if ( type == xpNewsRC || type == xpNewsgroups )
|
||
NET_UnregisterNewsHost( name, FALSE );
|
||
else if ( type == xpSNewsRC || type == xpSNewsgroups)
|
||
NET_UnregisterNewsHost( name, TRUE );
|
||
#endif
|
||
}
|
||
|
||
if ( err == noErr )
|
||
return 0;
|
||
return -1;
|
||
}
|
||
|
||
int XP_FileTruncate( const char* name, XP_FileType type, int32 len )
|
||
{
|
||
FSSpec spec;
|
||
OSErr err, err2;
|
||
short refNum;
|
||
|
||
if (len < 0)
|
||
return EINVAL;
|
||
|
||
err = XP_FileSpec( name, type, &spec);
|
||
if (err != noErr)
|
||
return EINVAL;
|
||
|
||
err = FSpOpenDF(&spec, fsRdWrPerm, &refNum);
|
||
if (err != noErr)
|
||
return EACCES;
|
||
|
||
err = SetEOF(refNum, len);
|
||
|
||
err2 = FSClose(refNum);
|
||
if ((err != noErr) || (err2 != noErr))
|
||
return EIO;
|
||
return 0;
|
||
}
|
||
|
||
|
||
int XP_FileDuplicateResourceFork( const char* oldFilePath, XP_FileType oldType,
|
||
const char* newFilePath, XP_FileType newType )
|
||
{
|
||
OSErr err;
|
||
FSSpec oldfs, newfs;
|
||
err = XP_FileSpec( oldFilePath, oldType, &oldfs);
|
||
if (err != noErr)
|
||
return EINVAL;
|
||
|
||
err = XP_FileSpec( newFilePath, newType, &newfs);
|
||
if (err != noErr)
|
||
return EINVAL;
|
||
|
||
short oldFileRefNum = -1, newFileRefNum = -1;
|
||
oldFileRefNum = FSpOpenResFileCompat( &oldfs, fsCurPerm );
|
||
err = ResError();
|
||
if ( err || ( oldFileRefNum == -1 ) )
|
||
{
|
||
return EACCES;
|
||
}
|
||
|
||
// assume we need to create the new resource fork
|
||
// (may not be valid assumption for other uses of this function)
|
||
FSpCreateResFileCompat( &newfs, emSignature, emTextType, smSystemScript );
|
||
err = ResError();
|
||
|
||
newFileRefNum = FSpOpenResFileCompat( &newfs, fsRdWrPerm );
|
||
err = ResError();
|
||
if ( err || ( newFileRefNum == -1 ) )
|
||
{
|
||
err = FSClose( oldFileRefNum );
|
||
XP_ASSERT(0);
|
||
return EACCES;
|
||
}
|
||
|
||
long buffsize = 1024;
|
||
char buff[ 1024 ];
|
||
err = CopyFork( oldFileRefNum, newFileRefNum, buff, buffsize);
|
||
|
||
FSClose( oldFileRefNum );
|
||
FSClose( newFileRefNum );
|
||
|
||
if ( err )
|
||
return EIO;
|
||
|
||
return 0;
|
||
}
|
||
|
||
//======================================
|
||
// I put these stubs here. They can go away when we move to MSL.
|
||
//======================================
|
||
|
||
#include "prenv.h" /* For PR_GetEnv */
|
||
extern "C" {
|
||
char* getenv(const char *var);
|
||
}
|
||
|
||
char* getenv(const char *var)
|
||
{
|
||
return PR_GetEnv(var);
|
||
}
|
||
|