From 41f0fe6bb59dea97a6801aecc8db1651630d77d6 Mon Sep 17 00:00:00 2001 From: "ccarlen%netscape.com" Date: Tue, 14 Nov 2000 15:58:54 +0000 Subject: [PATCH] Bug 55891 r=brade, sr=sfraser --- xpcom/io/nsIFileStream.cpp | 20 ++++++- xpcom/io/nsILocalFileMac.h | 9 +++ xpcom/io/nsLocalFileMac.cpp | 113 +++++++++++++++++++++++++++++++++++- xpcom/io/nsLocalFileMac.h | 15 ++++- 4 files changed, 152 insertions(+), 5 deletions(-) diff --git a/xpcom/io/nsIFileStream.cpp b/xpcom/io/nsIFileStream.cpp index 38ae5efda4f..0d9cf958c5b 100644 --- a/xpcom/io/nsIFileStream.cpp +++ b/xpcom/io/nsIFileStream.cpp @@ -228,8 +228,24 @@ NS_IMETHODIMP FileImpl::Open( PRBool ignoredResult; original.ResolveSymlink(ignoredResult); const FSSpec& spec = original.operator const FSSpec&(); - if (nsprMode & PR_CREATE_FILE) - err = FSpCreate(&spec, kCreator, 'TEXT', 0); + if (nsprMode & PR_CREATE_FILE) { + // In order to get the right file type/creator, do it with an nsILocalFileMac + // Don't propagate any errors in doing this. If any error, just use FSpCreate. + FSSpec nonConstSpec = spec; + nsCOMPtr macFile; + nsresult res = NS_NewLocalFileWithFSSpec(&nonConstSpec, PR_FALSE, getter_AddRefs(macFile)); + if (NS_SUCCEEDED(res)) { + nsCOMPtr asFile(do_QueryInterface(macFile, &res)); + if (NS_SUCCEEDED(res)) { + res = asFile->Create(nsIFile::NORMAL_FILE_TYPE, 0); + if (res == NS_ERROR_FILE_ALREADY_EXISTS) + res = NS_OK; + } + } + if (NS_FAILED(res)) + err = FSpCreate(&spec, kCreator, 'TEXT', 0); + } + if (err == dupFNErr) err = noErr; if (err != noErr) diff --git a/xpcom/io/nsILocalFileMac.h b/xpcom/io/nsILocalFileMac.h index 32f3d442e61..8ee5d4725cb 100644 --- a/xpcom/io/nsILocalFileMac.h +++ b/xpcom/io/nsILocalFileMac.h @@ -53,6 +53,9 @@ class nsILocalFileMac : public nsISupports public: NS_DEFINE_STATIC_IID_ACCESSOR(NS_ILOCALFILEMAC_IID) + // Use with SetFileTypeAndCreator to make creator be that of current process + enum { CURRENT_PROCESS_CREATOR = 0x8000000 }; + // We need to be able to determine what init method was used as that // will affect how we clone a nsILocalFileMac NS_IMETHOD GetInitType(nsLocalFileMacInitType *type) = 0; @@ -82,6 +85,12 @@ public: NS_IMETHOD GetFileTypeAndCreator(OSType *type, OSType *creator) = 0; NS_IMETHOD SetFileTypeAndCreator(OSType type, OSType creator) = 0; + // Methods for setting the file type from other means. Just setting the + // type is probably enough. The creator is set to that of the current process + // by default. Failure is likely on these methods - take it lightly. + NS_IMETHOD SetFileTypeFromSuffix(const char *suffix) = 0; + NS_IMETHOD SetFileTypeFromMIMEType(const char *mimetype) = 0; + // Since Mac files can consist of both a data and resource fork we have a // method that will return the combined size of both forks rather than just the // size of the data fork as returned by GetFileSize() diff --git a/xpcom/io/nsLocalFileMac.cpp b/xpcom/io/nsLocalFileMac.cpp index e623320a1e3..d61481a4601 100644 --- a/xpcom/io/nsLocalFileMac.cpp +++ b/xpcom/io/nsLocalFileMac.cpp @@ -26,11 +26,14 @@ #include "nsCOMPtr.h" #include "nsMemory.h" +#include "nsXPIDLString.h" #include "nsLocalFileMac.h" #include "nsISimpleEnumerator.h" #include "nsIComponentManager.h" +#include "nsIInternetConfigService.h" +#include "nsIMIMEInfo.h" #include "prtypes.h" #include "prerror.h" #include "pprio.h" // Include this rather than prio.h so we get def of PR_ImportFile @@ -62,6 +65,10 @@ extern "C" #include } +#pragma mark [Constants] + +const OSType kDefaultCreator = 'MOSS'; + #pragma mark [static util funcs] static inline void ClearFSSpec(FSSpec& aSpec) @@ -772,6 +779,9 @@ class nsDirEnumerator : public nsISimpleEnumerator NS_IMPL_ISUPPORTS(nsDirEnumerator, NS_GET_IID(nsISimpleEnumerator)); #pragma mark - + +OSType nsLocalFile::mgCurrentProcessSignature = 0; + #pragma mark [CTOR/DTOR] nsLocalFile::nsLocalFile() : mInitType(eNotInitialized) @@ -779,12 +789,16 @@ nsLocalFile::nsLocalFile() , mHaveFileInfo(PR_FALSE) , mFollowSymlinks(PR_FALSE) , mType('????') -, mCreator('MOSS') +, mCreator(kDefaultCreator) { NS_INIT_REFCNT(); MakeDirty(); ClearFSSpec(mSpec); + + DetermineCurrentProcessCreator(); + if (mgCurrentProcessSignature != 0) + mCreator = mgCurrentProcessSignature; } nsLocalFile::~nsLocalFile() @@ -1037,7 +1051,10 @@ nsLocalFile::OpenNSPRFileDesc(PRInt32 flags, PRInt32 mode, PRFileDesc **_retval) return MacErrorMapper(err); if (flags & PR_CREATE_FILE) + { + SetOSTypeFromExtension(); err = ::FSpCreate(&spec, mCreator, mType, 0); + } /* If opening with the PR_EXCL flag the existence of the file prior to opening is an error */ if ((flags & PR_EXCL) && (err == dupFNErr)) @@ -1145,6 +1162,7 @@ nsLocalFile::Create(PRUint32 type, PRUint32 attributes) switch (type) { case NORMAL_FILE_TYPE: + SetOSTypeFromExtension(); err = ::FSpCreate(&mResolvedSpec, mCreator, mType, smCurrentScript); return (MacErrorMapper(err)); break; @@ -2605,6 +2623,9 @@ NS_IMETHODIMP nsLocalFile::SetFileTypeAndCreator(OSType type, OSType creator) OSErr err = ::FSpGetFInfo(&mTargetSpec, &info); if (err != noErr) return NS_ERROR_FILE_NOT_FOUND; + + if (creator == CURRENT_PROCESS_CREATOR) + creator = (mgCurrentProcessSignature != 0) ? mgCurrentProcessSignature : kDefaultCreator; // See if the user specified a type or creator before changing from what was read if (type) @@ -2619,6 +2640,33 @@ NS_IMETHODIMP nsLocalFile::SetFileTypeAndCreator(OSType type, OSType creator) return NS_OK; } +NS_IMETHODIMP nsLocalFile::SetFileTypeFromSuffix(const char *suffix) +{ + NS_ENSURE_ARG(suffix); + return SetOSTypeFromExtension(suffix); +} + +NS_IMETHODIMP nsLocalFile::SetFileTypeFromMIMEType(const char *mimetype) +{ + NS_ENSURE_ARG(mimetype); + + nsresult rv; + NS_WITH_SERVICE(nsIInternetConfigService, icService, NS_INTERNETCONFIGSERVICE_CONTRACTID, &rv); + if (NS_SUCCEEDED(rv)) + { + nsCOMPtr mimeInfo; + rv = icService->FillInMIMEInfo(mimetype, nsnull, getter_AddRefs(mimeInfo)); + if (NS_SUCCEEDED(rv)) + { + PRUint32 osType; + rv = mimeInfo->GetMacType(&osType); + if (NS_SUCCEEDED(rv)) + mType = osType; + } + } + return rv; +} + NS_IMETHODIMP nsLocalFile::GetFileSizeWithResFork(PRInt64 *aFileSize) { @@ -2728,6 +2776,69 @@ nsLocalFile::OpenDocWithApp(nsILocalFile* aAppToOpenWith, PRBool aLaunchInBackgr return rv; } +nsresult nsLocalFile::SetOSTypeFromExtension(const char* extension) +{ + nsresult rv; + + nsXPIDLCString localExtBuf; + char *extPtr; + + if (!extension) + { + rv = GetLeafName(getter_Copies(localExtBuf)); + extPtr = strrchr(localExtBuf, '.'); + if (!extPtr) + return NS_ERROR_FAILURE; + ++extPtr; + } + else + { + extPtr = const_cast(extension); // really, we won't touch it + if (*extPtr == '.') + ++extPtr; + } + + NS_WITH_SERVICE(nsIInternetConfigService, icService, NS_INTERNETCONFIGSERVICE_CONTRACTID, &rv); + if (NS_SUCCEEDED(rv)) + { + nsCOMPtr mimeInfo; + rv = icService->GetMIMEInfoFromExtension(extPtr, getter_AddRefs(mimeInfo)); + if (NS_SUCCEEDED(rv)) + { + PRUint32 osType; + rv = mimeInfo->GetMacType(&osType); + if (NS_SUCCEEDED(rv)) + mType = osType; + } + } + return rv; +} + +nsresult nsLocalFile::DetermineCurrentProcessCreator() +{ + nsresult rv = NS_OK; + + if (mgCurrentProcessSignature == 0) + { + OSErr err; + ProcessSerialNumber psn; + ProcessInfoRec info; + + psn.highLongOfPSN = 0; + psn.lowLongOfPSN = kCurrentProcess; + + info.processInfoLength = sizeof(ProcessInfoRec); + info.processName = nil; + info.processAppSpec = nil; + err = ::GetProcessInformation(&psn, &info); + if (err == noErr) + mgCurrentProcessSignature = info.processSignature; + // Try again next time if error + else + rv = MacErrorMapper(err); + } + return NS_OK; +} #pragma mark - diff --git a/xpcom/io/nsLocalFileMac.h b/xpcom/io/nsLocalFileMac.h index 5b11f31b2d4..61824889e27 100644 --- a/xpcom/io/nsLocalFileMac.h +++ b/xpcom/io/nsLocalFileMac.h @@ -71,6 +71,9 @@ public: NS_IMETHOD GetFileTypeAndCreator(OSType *type, OSType *creator); NS_IMETHOD SetFileTypeAndCreator(OSType type, OSType creator); + NS_IMETHOD SetFileTypeFromSuffix(const char *suffix); + NS_IMETHOD SetFileTypeFromMIMEType(const char *mimetype); + NS_IMETHOD GetFileSizeWithResFork(PRInt64 *aFileSize); NS_IMETHOD LaunchAppWithDoc(nsILocalFile* aDocToLoad, PRBool aLaunchInBackground); @@ -91,7 +94,13 @@ protected: nsresult TestFinderFlag(PRUint16 flagMask, PRBool *outFlagSet, PRBool testTargetSpec = PR_TRUE); OSErr GetTargetSpecCatInfo(CInfoPBRec& outInfo); - nsresult MoveCopy( nsIFile* newParentDir, const char* newName, PRBool isCopy ); + nsresult MoveCopy( nsIFile* newParentDir, const char* newName, PRBool isCopy ); + + // Passing nsnull for the extension uses leaf name + nsresult SetOSTypeFromExtension(const char* extension = nsnull); + + static nsresult DetermineCurrentProcessCreator(); + private: // It's important we keep track of how we were initialized @@ -128,7 +137,9 @@ private: CInfoPBRec mTargetFileInfoRec; // cached file info, for the mTargetSpec OSType mType, mCreator; - + + static OSType mgCurrentProcessSignature; + }; #endif