diff --git a/mozilla/xpinstall/src/Makefile.in b/mozilla/xpinstall/src/Makefile.in index 6c342db237c..804af053e60 100644 --- a/mozilla/xpinstall/src/Makefile.in +++ b/mozilla/xpinstall/src/Makefile.in @@ -109,6 +109,19 @@ CPPSRCS += \ OS_LIBS += $(call EXPAND_LIBNAME,ole32 version uuid) endif +# Support AppleSingle decoding on Mac OS X +ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT))) +REQUIRES += macmorefiles + +CPPSRCS += \ + nsAppleSingleDecoder.cpp \ + $(NULL) + +LIBS += \ + $(DEPTH)/dist/lib/libmacmorefiles_s.a \ + $(NULL) +endif + LOCAL_INCLUDES = -I$(srcdir)/../public EXTRA_DSO_LDOPTS = \ diff --git a/mozilla/xpinstall/src/nsAppleSingleDecoder.cpp b/mozilla/xpinstall/src/nsAppleSingleDecoder.cpp index 2810124d797..344f837496a 100644 --- a/mozilla/xpinstall/src/nsAppleSingleDecoder.cpp +++ b/mozilla/xpinstall/src/nsAppleSingleDecoder.cpp @@ -22,26 +22,31 @@ #ifndef _NS_APPLESINGLEDECODER_H_ - #include "nsAppleSingleDecoder.h" + #include "nsAppleSingleDecoder.h" +#endif + +#include "MoreFilesX.h" + +#ifdef STANDALONE_ASD +#include +using namespace std; +#undef MOZILLA_CLIENT #endif -#include "MoreFilesExtras.h" -#include "MoreDesktopMgr.h" -#include "IterateDirectory.h" #ifdef MOZILLA_CLIENT -#include "nsISupportsUtils.h" + #include "nsISupportsUtils.h" #endif /*----------------------------------------------------------------------* * Constructors/Destructor *----------------------------------------------------------------------*/ #ifdef MOZILLA_CLIENT -MOZ_DECL_CTOR_COUNTER(nsAppleSingleDecoder) + MOZ_DECL_CTOR_COUNTER(nsAppleSingleDecoder) #endif -nsAppleSingleDecoder::nsAppleSingleDecoder(FSSpec *inSpec, FSSpec *outSpec) -: mInSpec(NULL), - mOutSpec(NULL), +nsAppleSingleDecoder::nsAppleSingleDecoder(const FSRef *inRef, FSRef *outRef) +: mInRef(NULL), + mOutRef(NULL), mInRefNum(0), mRenameReqd(false) { @@ -49,30 +54,31 @@ nsAppleSingleDecoder::nsAppleSingleDecoder(FSSpec *inSpec, FSSpec *outSpec) MOZ_COUNT_CTOR(nsAppleSingleDecoder); #endif - if (inSpec && outSpec) - { - /* merely point to FSSpecs, not own 'em */ - mInSpec = inSpec; - mOutSpec = outSpec; - } + if (inRef && outRef) + { + /* merely point to FSRefs, not own 'em */ + mInRef = inRef; + mOutRef = outRef; + } } nsAppleSingleDecoder::nsAppleSingleDecoder() -: mInSpec(NULL), - mOutSpec(NULL), +: mInRef(NULL), + mOutRef(NULL), mInRefNum(0), mRenameReqd(false) { #ifdef MOZILLA_CLIENT - MOZ_COUNT_CTOR(nsAppleSingleDecoder); + MOZ_COUNT_CTOR(nsAppleSingleDecoder); #endif } nsAppleSingleDecoder::~nsAppleSingleDecoder() { - /* not freeing FSSpecs since we don't own 'em */ + /* not freeing FSRefs since we don't own 'em */ + #ifdef MOZILLA_CLIENT - MOZ_COUNT_DTOR(nsAppleSingleDecoder); + MOZ_COUNT_DTOR(nsAppleSingleDecoder); #endif } @@ -84,220 +90,206 @@ nsAppleSingleDecoder::~nsAppleSingleDecoder() OSErr nsAppleSingleDecoder::Decode() { - OSErr err = noErr; - ASHeader header; - long bytesRead = sizeof(header); - - // param check - if (!mInSpec || !mOutSpec) - return paramErr; - - // check for existence - FSSpec tmp; - err = FSMakeFSSpec(mInSpec->vRefNum, mInSpec->parID, mInSpec->name, &tmp); - if (err == fnfErr) - return err; - - MAC_ERR_CHECK(FSpOpenDF( mInSpec, fsRdPerm, &mInRefNum )); - MAC_ERR_CHECK(FSRead( mInRefNum, &bytesRead, &header )); - - if ( (bytesRead != sizeof(header)) || - (header.magicNum != 0x00051600) || - (header.versionNum != 0x00020000) || - (header.numEntries == 0) ) // empty file? - return -1; - - // create the outSpec which we'll rename correctly later - err = FSMakeFSSpec( mInSpec->vRefNum, mInSpec->parID, "\pdecode", mOutSpec ); - if (err!=noErr && err!=fnfErr) - return err; - MAC_ERR_CHECK(FSMakeUnique( mOutSpec )); - MAC_ERR_CHECK(FSpCreate( mOutSpec, 'MOZZ', '????', 0 )); - - - /* Loop through the entries, processing each. - ** Set the time/date stamps last, because otherwise they'll - ** be destroyed when we write. - */ - { - Boolean hasDateEntry = false; - ASEntry dateEntry; - long offset; - ASEntry entry; - - for ( int i=0; i < header.numEntries; i++ ) - { - offset = sizeof( ASHeader ) + sizeof( ASEntry ) * i; - MAC_ERR_CHECK(SetFPos( mInRefNum, fsFromStart, offset )); - - bytesRead = sizeof(entry); - MAC_ERR_CHECK(FSRead( mInRefNum, &bytesRead, &entry )); - if (bytesRead != sizeof(entry)) - return -1; - - if ( entry.entryID == AS_FILEDATES ) - { - hasDateEntry = true; - dateEntry = entry; - } - else - MAC_ERR_CHECK(ProcessASEntry( entry )); - } - if ( hasDateEntry ) - MAC_ERR_CHECK(ProcessASEntry( dateEntry )); - } - - // close the inSpec - FSClose( mInRefNum ); - - // rename if need be - if (mRenameReqd) - { - FSSpec old; // delete old version of target file - - FSMakeFSSpec(mInSpec->vRefNum, mInSpec->parID, mInSpec->name, &old); - MAC_ERR_CHECK(FSpDelete(&old)); - MAC_ERR_CHECK(FSpRename(mOutSpec, mInSpec->name)); - - // reflect change in outSpec - nsAppleSingleDecoder::PLstrncpy( mOutSpec->name, mInSpec->name, mInSpec->name[0] ); - mOutSpec->name[0] = mInSpec->name[0]; - mRenameReqd = false; // XXX redundant reinit? - } - - if (mType == 'APPL') - { - // need to register in desktop database - DTSetAPPL( NULL, - mOutSpec->vRefNum, - mCreator, - mOutSpec->parID, - mOutSpec->name ); - } - - return err; + OSErr err = noErr; + ASHeader header; + UInt32 bytesRead = sizeof(header); + HFSUniStr255 nameInRef; + + // param check + if (!mInRef || !mOutRef) + return paramErr; + + // check for existence (and get leaf name for later renaming of decoded file) + err = FSGetCatalogInfo(mInRef, kFSCatInfoNone, NULL, &nameInRef, NULL, NULL); + if (err == fnfErr) + return err; + + HFSUniStr255 dataForkName; + MAC_ERR_CHECK(FSGetDataForkName( &dataForkName )); + MAC_ERR_CHECK(FSOpenFork( mInRef, dataForkName.length, dataForkName.unicode, + fsRdPerm, &mInRefNum )); + MAC_ERR_CHECK(FSRead( mInRefNum, (long *)&bytesRead, &header )); + + if ( (bytesRead != sizeof(header)) || + (header.magicNum != APPLESINGLE_MAGIC) || + (header.versionNum != APPLESINGLE_VERSION) || + (header.numEntries == 0) ) // empty file? + return -1; + + // create the outSpec which we'll rename correctly later + FSRef parentRef; + MAC_ERR_CHECK(FSGetParentRef( mInRef, &parentRef )); + MAC_ERR_CHECK(FSMakeUnique( &parentRef, mOutRef )); + MAC_ERR_CHECK(FSCreateFork( mOutRef, dataForkName.length, + dataForkName.unicode )); + + /* Loop through the entries, processing each. + ** Set the time/date stamps last, because otherwise they'll + ** be destroyed when we write. + */ + { + Boolean hasDateEntry = false; + ASEntry dateEntry; + long offset; + ASEntry entry; + + for ( int i=0; i < header.numEntries; i++ ) + { + offset = sizeof( ASHeader ) + sizeof( ASEntry ) * i; + MAC_ERR_CHECK(SetFPos( mInRefNum, fsFromStart, offset )); + + bytesRead = sizeof(entry); + MAC_ERR_CHECK(FSRead( mInRefNum, (long *) &bytesRead, &entry )); + if (bytesRead != sizeof(entry)) + return -1; + + if ( entry.entryID == AS_FILEDATES ) + { + hasDateEntry = true; + dateEntry = entry; + } + else + MAC_ERR_CHECK(ProcessASEntry( entry )); + } + if ( hasDateEntry ) + MAC_ERR_CHECK(ProcessASEntry( dateEntry )); + } + + // close the inSpec + FSClose( mInRefNum ); + + // rename if need be + if (mRenameReqd) + { + // delete encoded version of target file + MAC_ERR_CHECK(FSDeleteObject( mInRef )); + MAC_ERR_CHECK(FSRenameUnicode( mOutRef, nameInRef.length, + nameInRef.unicode, kTextEncodingUnknown, mOutRef )); + mRenameReqd = false; + } + + return err; } OSErr -nsAppleSingleDecoder::Decode(FSSpec *inSpec, FSSpec *outSpec) +nsAppleSingleDecoder::Decode(const FSRef *inRef, FSRef *outRef) { - OSErr err = noErr; - - // param check - if (inSpec && outSpec) - { - mInSpec = inSpec; // reinit - mOutSpec = outSpec; - mRenameReqd = false; - } - else - return paramErr; - - err = Decode(); - - return err; + OSErr err = noErr; + + // param check + if (inRef && outRef) + { + mInRef = inRef; // reinit + mOutRef = outRef; + mRenameReqd = false; + } + else + return paramErr; + + err = Decode(); + + return err; } -pascal void -DecodeDirIterateFilter(const CInfoPBRec * const cpbPtr, Boolean *quitFlag, void *yourDataPtr) -{ - OSErr err = noErr; - FSSpec currFSp, outFSp; - nsAppleSingleDecoder* thisObj = NULL; - Boolean isDir = false; - long dummy; - - // param check - if (!yourDataPtr || !cpbPtr || !quitFlag) - return; - - *quitFlag = false; - - // extract 'this' -- an nsAppleSingleDecoder instance - thisObj = (nsAppleSingleDecoder*) yourDataPtr; - - // make an FSSpec from the CInfoPBRec* - err = FSMakeFSSpec(cpbPtr->hFileInfo.ioVRefNum, cpbPtr->hFileInfo.ioFlParID, - cpbPtr->hFileInfo.ioNamePtr, &currFSp); - if (err == noErr) - { - FSpGetDirectoryID(&currFSp, &dummy, &isDir); - - // if current FSSpec is file - if (!isDir) - { - // if file is in AppleSingle format - if (nsAppleSingleDecoder::IsAppleSingleFile(&currFSp)) - { - // decode file - thisObj->Decode(&currFSp, &outFSp); - } - } - else - { - // else if current FSSpec is folder ignore - // XXX never reached? - return; - } - } +Boolean +DecodeDirIterateFilter(Boolean containerChanged, ItemCount currentLevel, + const FSCatalogInfo *catalogInfo, const FSRef *ref, + const FSSpec *spec, const HFSUniStr255 *name, void *yourDataPtr) +{ + FSRef outRef; + nsAppleSingleDecoder *thisObj; + Boolean isDir; + + // param check + if (!yourDataPtr || !ref) + return false; + + // extract 'this' -- an nsAppleSingleDecoder instance + thisObj = (nsAppleSingleDecoder*) yourDataPtr; + + isDir = nsAppleSingleDecoder::IsDirectory(ref); + + // if current FSRef is file + if (!isDir) + { + // if file is in AppleSingle format + if (nsAppleSingleDecoder::IsAppleSingleFile(ref)) + { + // decode file + thisObj->Decode(ref, &outRef); + } + } + + // else current FSRef is folder + else + { + thisObj->DecodeFolder(ref); + } + + return false; // always continue iteration } OSErr -nsAppleSingleDecoder::DecodeFolder(FSSpec *aFolder) +nsAppleSingleDecoder::DecodeFolder(const FSRef *aFolder) { - OSErr err = noErr; - long dummy; - Boolean isDir = false; - - // check that FSSpec is folder - if (aFolder) - { - FSpGetDirectoryID(aFolder, &dummy, &isDir); - if (!isDir) - return dirNFErr; - } - - // recursively enumerate contents of folder (maxLevels=0 means recurse all) - FSpIterateDirectory(aFolder, 0, DecodeDirIterateFilter, (void*)this); - - return err; + OSErr err; + Boolean isDir = false; + + // check that FSSpec is folder + if (aFolder) + { + isDir = IsDirectory((const FSRef *) aFolder); + if (!isDir) + return dirNFErr; + } + + // recursively enumerate contents of folder + // (maxLevels=0 means recurse all) + err = FSIterateContainer(aFolder, 0, kFSCatInfoNone, false, + false, DecodeDirIterateFilter, (void*)this); + + // XXX do we really want to return err? + return err; } Boolean -nsAppleSingleDecoder::IsAppleSingleFile(FSSpec *inSpec) +nsAppleSingleDecoder::IsAppleSingleFile(const FSRef *inRef) { - OSErr err; - Boolean bAppleSingle = false; - short inRefNum; - UInt32 magic; - long bytesRead = sizeof(magic); - - // param checks - if (!inSpec) - return false; - - // check for existence - FSSpec tmp; - err = FSMakeFSSpec(inSpec->vRefNum, inSpec->parID, inSpec->name, &tmp); - if (err!=noErr) - return false; - - // open and read the magic number len bytes - err = FSpOpenDF( inSpec, fsRdPerm, &inRefNum ); - if (err!=noErr) - return false; - - err = FSRead( inRefNum, &bytesRead, &magic ); - if (err!=noErr) - return false; - - FSClose(inRefNum); - if (bytesRead != sizeof(magic)) - return false; + OSErr err; + SInt16 inRefNum; + UInt32 magic; + long bytesRead = sizeof(magic); + + // param checks + if (!inRef) + return false; + + // check for existence + err = FSGetCatalogInfo(inRef, kFSCatInfoNone, NULL, NULL, NULL, NULL); + if (err!=noErr) + return false; + + // open and read the magic number len bytes + HFSUniStr255 dataForkName; + err = FSGetDataForkName( &dataForkName ); + if (err!=noErr) + return false; - // check if bytes read match magic number - bAppleSingle = (magic == 0x00051600); - return bAppleSingle; + err = FSOpenFork( inRef, dataForkName.length, dataForkName.unicode, + fsRdPerm, &inRefNum ); + if (err!=noErr) + return false; + + err = FSRead( inRefNum, &bytesRead, &magic ); + if (err!=noErr) + return false; + + FSClose(inRefNum); + if (bytesRead != sizeof(magic)) + return false; + + // check if bytes read match magic number + return (magic == APPLESINGLE_MAGIC); } #pragma mark - @@ -308,242 +300,215 @@ nsAppleSingleDecoder::IsAppleSingleFile(FSSpec *inSpec) OSErr nsAppleSingleDecoder::ProcessASEntry(ASEntry inEntry) { - switch (inEntry.entryID) - { - case AS_DATA: - return ProcessDataFork( inEntry ); - break; - case AS_RESOURCE: - return ProcessResourceFork( inEntry ); - break; - case AS_REALNAME: - ProcessRealName( inEntry ); - break; - // return 0; // Ignore these errors in ASD <--- XXX remove - case AS_COMMENT: -// return ProcessComment( inEntry ); - break; - case AS_ICONBW: -// return ProcessIconBW( inEntry ); - break; - case AS_ICONCOLOR: -// return ProcessIconColor( inEntry ); - break; - case AS_FILEDATES: - return ProcessFileDates( inEntry ); - break; - case AS_FINDERINFO: - return ProcessFinderInfo( inEntry ); - break; - case AS_MACINFO: - return ProcessMacInfo( inEntry ); - break; - case AS_PRODOSINFO: - case AS_MSDOSINFO: - case AS_AFPNAME: - case AS_AFPINFO: - case AS_AFPDIRID: - default: - return 0; - } - return 0; + switch (inEntry.entryID) + { + case AS_DATA: + return ProcessDataFork( inEntry ); + break; + case AS_RESOURCE: + return ProcessResourceFork( inEntry ); + break; + case AS_REALNAME: + ProcessRealName( inEntry ); + break; + case AS_FILEDATES: + return ProcessFileDates( inEntry ); + break; + case AS_FINDERINFO: + return ProcessFinderInfo( inEntry ); + break; + case AS_MACINFO: + case AS_COMMENT: + case AS_ICONBW: + case AS_ICONCOLOR: + case AS_PRODOSINFO: + case AS_MSDOSINFO: + case AS_AFPNAME: + case AS_AFPINFO: + case AS_AFPDIRID: + default: + return 0; + } + return 0; } OSErr nsAppleSingleDecoder::ProcessDataFork(ASEntry inEntry) { - OSErr err = noErr; - SInt16 refNum; - - /* Setup the files */ - err = FSpOpenDF (mOutSpec, fsWrPerm, &refNum); + OSErr err = noErr; + SInt16 refNum; + + /* Setup the files */ + HFSUniStr255 dataForkName; + err = FSGetDataForkName( &dataForkName ); + if (err != noErr) + return err; - if ( err == noErr ) - err = EntryToMacFile( inEntry, refNum ); - - FSClose( refNum ); - return err; + err = FSOpenFork( mOutRef, dataForkName.length, dataForkName.unicode, + fsWrPerm, &refNum ); + + if ( err == noErr ) + err = EntryToMacFile( inEntry, refNum ); + + FSClose( refNum ); + return err; } OSErr nsAppleSingleDecoder::ProcessResourceFork(ASEntry inEntry) { - OSErr err = noErr; - SInt16 refNum; - - err = FSpOpenRF(mOutSpec, fsWrPerm, &refNum); + OSErr err = noErr; + SInt16 refNum; + + HFSUniStr255 rsrcForkName; + err = FSGetResourceForkName( &rsrcForkName ); + if (err != noErr) + return err; - if ( err == noErr ) - err = EntryToMacFile( inEntry, refNum ); - - FSClose( refNum ); - return err; + err = FSOpenFork( mOutRef, rsrcForkName.length, rsrcForkName.unicode, + fsWrPerm, &refNum ); + + if ( err == noErr ) + err = EntryToMacFile( inEntry, refNum ); + + FSClose( refNum ); + return err; } OSErr nsAppleSingleDecoder::ProcessRealName(ASEntry inEntry) { - OSErr err = noErr; - Str255 newName; - long bytesRead; - - if ( inEntry.entryLength > 32 ) /* Max file name length for the Mac */ - return -1; + OSErr err = noErr; + Str255 newName; + HFSUniStr255 newNameUni; + UInt32 bytesRead; + FSRef parentOfOutRef; + + MAC_ERR_CHECK(SetFPos(mInRefNum, fsFromStart, inEntry.entryOffset)); + + bytesRead = inEntry.entryLength; + MAC_ERR_CHECK(FSRead(mInRefNum, (long *) &bytesRead, &newName[1])); + if (bytesRead != inEntry.entryLength) + return -1; + + newName[0] = inEntry.entryLength; + MAC_ERR_CHECK(FSGetParentRef(mOutRef, &parentOfOutRef)); + MAC_ERR_CHECK(HFSNameGetUnicodeName(newName, kTextEncodingUnknown, + &newNameUni)); + err = FSRenameUnicode(mOutRef, newNameUni.length, newNameUni.unicode, + kTextEncodingUnknown, mOutRef); + if (err == dupFNErr) + { + HFSUniStr255 inRefName; + MAC_ERR_CHECK(FSGetCatalogInfo(mInRef, kFSCatInfoNone, NULL, &inRefName, + NULL, NULL)); - MAC_ERR_CHECK(SetFPos(mInRefNum, fsFromStart, inEntry.entryOffset)); - - bytesRead = inEntry.entryLength; - MAC_ERR_CHECK(FSRead(mInRefNum, &bytesRead, &newName[1])); - if (bytesRead != inEntry.entryLength) - return -1; - - newName[0] = inEntry.entryLength; - err = FSpRename(mOutSpec, newName); - if (err == dupFNErr) - { - // if we are trying to rename temp decode file to src name, rename later - if (nsAppleSingleDecoder::PLstrcmp(newName, mInSpec->name)) - { - mRenameReqd = true; - return noErr; - } - - FSSpec old; // delete old version of target file - - FSMakeFSSpec(mOutSpec->vRefNum, mOutSpec->parID, newName, &old); - MAC_ERR_CHECK(FSpDelete(&old)); - MAC_ERR_CHECK(FSpRename(mOutSpec, newName)); - } - nsAppleSingleDecoder::PLstrncpy( mOutSpec->name, newName, inEntry.entryLength ); - mOutSpec->name[0] = inEntry.entryLength; + // if we are trying to rename temp decode file to src name, rename later + if (nsAppleSingleDecoder::UCstrcmp(&newNameUni, &inRefName)) + { + mRenameReqd = true; + return noErr; + } + + // otherwise replace file in the way + FSRef inTheWayRef; - return err; + // delete file in the way + MAC_ERR_CHECK(FSMakeFSRefUnicode( &parentOfOutRef, newNameUni.length, + newNameUni.unicode, kTextEncodingUnknown, &inTheWayRef )); + MAC_ERR_CHECK(FSDeleteObject( &inTheWayRef )); + + // rename decoded file to ``newName'' + MAC_ERR_CHECK(FSRenameUnicode( mOutRef, newNameUni.length, + newNameUni.unicode, kTextEncodingUnknown, mOutRef )); + } + + return err; } OSErr nsAppleSingleDecoder::ProcessFileDates(ASEntry inEntry) { - OSErr err = noErr; - ASFileDates dates; - long bytesRead; - - if ( inEntry.entryLength != sizeof(dates) ) /* Max file name length for the Mac */ - return -1; - - MAC_ERR_CHECK(SetFPos(mInRefNum, fsFromStart, inEntry.entryOffset)); - - bytesRead = inEntry.entryLength; - MAC_ERR_CHECK(FSRead(mInRefNum, &bytesRead, &dates)); - if (bytesRead != inEntry.entryLength) - return -1; - - Str31 name; - nsAppleSingleDecoder::PLstrncpy(name, mOutSpec->name, mOutSpec->name[0]); - name[0] = mOutSpec->name[0]; - CInfoPBRec pb; - pb.hFileInfo.ioNamePtr = &name[0]; - pb.hFileInfo.ioVRefNum = mOutSpec->vRefNum; - pb.hFileInfo.ioDirID = mOutSpec->parID; - pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ - err = PBGetCatInfoSync(&pb); - if ( err != noErr ) - return -1; + OSErr err = noErr; + ASFileDates dates; + UInt32 bytesRead; + FSCatalogInfo catInfo; + + if ( inEntry.entryLength != sizeof(dates) ) + return -1; + + MAC_ERR_CHECK(SetFPos(mInRefNum, fsFromStart, inEntry.entryOffset)); + + bytesRead = inEntry.entryLength; + MAC_ERR_CHECK(FSRead(mInRefNum, (long *) &bytesRead, &dates)); + if (bytesRead != inEntry.entryLength) + return -1; + #define YR_2000_SECONDS 3029529600 - pb.hFileInfo.ioFlCrDat = dates.create + YR_2000_SECONDS; - pb.hFileInfo.ioFlMdDat = dates.modify + YR_2000_SECONDS; - pb.hFileInfo.ioFlBkDat = dates.backup + YR_2000_SECONDS; - /* Not sure if mac has the last access time */ - - nsAppleSingleDecoder::PLstrncpy(name, mOutSpec->name, mOutSpec->name[0]); - name[0] = mOutSpec->name[0]; - pb.hFileInfo.ioNamePtr = name; - pb.hFileInfo.ioVRefNum = mOutSpec->vRefNum; - pb.hFileInfo.ioDirID = mOutSpec->parID; - pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ - err = PBSetCatInfo(&pb, false); - - return err; + LocalDateTime local = (LocalDateTime) {0, 0, 0}; + + // set creation date + local.lowSeconds = dates.create + YR_2000_SECONDS; + ConvertLocalToUTCDateTime(&local, &catInfo.createDate); + + // set content modification date + local.lowSeconds = dates.modify + YR_2000_SECONDS; + ConvertLocalToUTCDateTime(&local, &catInfo.contentModDate); + + // set last access date + local.lowSeconds = dates.access + YR_2000_SECONDS; + ConvertLocalToUTCDateTime(&local, &catInfo.accessDate); + + // set backup date + local.lowSeconds = dates.backup + YR_2000_SECONDS; + ConvertLocalToUTCDateTime(&local, &catInfo.backupDate); + + // set attribute modification date + GetUTCDateTime(&catInfo.attributeModDate, kUTCDefaultOptions); + + MAC_ERR_CHECK(FSSetCatalogInfo(mOutRef, + kFSCatInfoCreateDate | + kFSCatInfoContentMod | + kFSCatInfoAttrMod | + kFSCatInfoAccessDate | + kFSCatInfoBackupDate, + &catInfo)); + + return err; } OSErr nsAppleSingleDecoder::ProcessFinderInfo(ASEntry inEntry) { - OSErr err = noErr; - ASFinderInfo info; - long bytesRead; - - if (inEntry.entryLength != sizeof( ASFinderInfo )) - return -1; + OSErr err = noErr; + ASFinderInfo info; + UInt32 bytesRead; + FSCatalogInfo catInfo; + + if (inEntry.entryLength != sizeof( ASFinderInfo )) + return -1; - MAC_ERR_CHECK(SetFPos(mInRefNum, fsFromStart, inEntry.entryOffset)); + MAC_ERR_CHECK(SetFPos(mInRefNum, fsFromStart, inEntry.entryOffset)); - bytesRead = sizeof(info); - MAC_ERR_CHECK(FSRead(mInRefNum, &bytesRead, &info)); - if (bytesRead != inEntry.entryLength) - return -1; - - err = FSpSetFInfo(mOutSpec, &info.ioFlFndrInfo); - if (err!=noErr && err!=fnfErr) - return err; - - Str31 name; - nsAppleSingleDecoder::PLstrncpy(name, mOutSpec->name, mOutSpec->name[0]); - name[0] = mOutSpec->name[0]; - CInfoPBRec pb; - pb.hFileInfo.ioNamePtr = name; - pb.hFileInfo.ioVRefNum = mOutSpec->vRefNum; - pb.hFileInfo.ioDirID = mOutSpec->parID; - pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ - MAC_ERR_CHECK(PBGetCatInfoSync(&pb)); - - pb.hFileInfo.ioNamePtr = name; - pb.hFileInfo.ioVRefNum = mOutSpec->vRefNum; - pb.hFileInfo.ioDirID = mOutSpec->parID; - pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ - pb.hFileInfo.ioFlXFndrInfo = info.ioFlXFndrInfo; - err = PBSetCatInfo(&pb, false); + bytesRead = sizeof(info); + MAC_ERR_CHECK(FSRead(mInRefNum, (long *) &bytesRead, &info)); + if (bytesRead != inEntry.entryLength) + return -1; - // save the creator and file type so we can set it on the renamed spec - mCreator = info.ioFlFndrInfo.fdCreator; - mType = info.ioFlFndrInfo.fdType; + MAC_ERR_CHECK(FSGetCatalogInfo(mOutRef, kFSCatInfoGettableInfo, &catInfo, + NULL, NULL, NULL)); - return err; -} + BlockMoveData((const void *) &info.ioFlFndrInfo, + (void *) &catInfo.finderInfo, sizeof(FInfo)); + BlockMoveData((const void *) &info.ioFlXFndrInfo, + (void *) &catInfo.extFinderInfo, sizeof(FXInfo)); -OSErr -nsAppleSingleDecoder::ProcessMacInfo(ASEntry inEntry) -{ - OSErr err = noErr; - ASMacInfo info; - long bytesRead; - - if (inEntry.entryLength != sizeof( ASMacInfo )) - return -1; - - MAC_ERR_CHECK(SetFPos(mInRefNum, fsFromStart, inEntry.entryOffset)); - - bytesRead = sizeof(info); - MAC_ERR_CHECK(FSRead(mInRefNum, &bytesRead, &info)); - if (bytesRead != inEntry.entryLength) - return -1; - - Str31 name; - nsAppleSingleDecoder::PLstrncpy(name, mOutSpec->name, mOutSpec->name[0]); - name[0] = mOutSpec->name[0]; - CInfoPBRec pb; - pb.hFileInfo.ioNamePtr = name; - pb.hFileInfo.ioVRefNum = mOutSpec->vRefNum; - pb.hFileInfo.ioDirID = mOutSpec->parID; - pb.hFileInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ - MAC_ERR_CHECK(PBGetCatInfoSync(&pb)); - - pb.hFileInfo.ioNamePtr = name; - pb.hFileInfo.ioVRefNum = mOutSpec->vRefNum; - pb.hFileInfo.ioDirID = mOutSpec->parID; - pb.hFileInfo.ioFlAttrib = info.ioFlAttrib; - err = PBSetCatInfo(&pb, false); - - return err; + MAC_ERR_CHECK(FSSetCatalogInfo(mOutRef, + kFSCatInfoFinderInfo | + kFSCatInfoFinderXInfo, + &catInfo)); + + return err; } OSErr @@ -551,208 +516,184 @@ nsAppleSingleDecoder::EntryToMacFile(ASEntry inEntry, UInt16 inTargetSpecRefNum) { #define BUFFER_SIZE 8192 - OSErr err = noErr; - char buffer[BUFFER_SIZE]; - long totalRead = 0, bytesRead, bytesToWrite; + OSErr err = noErr; + char buffer[BUFFER_SIZE]; + UInt32 totalRead = 0, bytesRead, bytesToWrite; - MAC_ERR_CHECK(SetFPos( mInRefNum, fsFromStart, inEntry.entryOffset )); + MAC_ERR_CHECK(SetFPos( mInRefNum, fsFromStart, inEntry.entryOffset )); - while ( totalRead < inEntry.entryLength ) - { + while ( totalRead < inEntry.entryLength ) + { // Should we yield in here? - bytesRead = BUFFER_SIZE; - err = FSRead( mInRefNum, &bytesRead, buffer ); - if (err!=noErr && err!=eofErr) - return err; - - if ( bytesRead <= 0 ) - return -1; - bytesToWrite = totalRead + bytesRead > inEntry.entryLength ? - inEntry.entryLength - totalRead : - bytesRead; + bytesRead = BUFFER_SIZE; + err = FSRead( mInRefNum, (long *) &bytesRead, buffer ); + if (err!=noErr && err!=eofErr) + return err; + + if ( bytesRead <= 0 ) + return -1; + bytesToWrite = totalRead + bytesRead > inEntry.entryLength ? + inEntry.entryLength - totalRead : + bytesRead; - totalRead += bytesRead; - MAC_ERR_CHECK(FSWrite(inTargetSpecRefNum, &bytesToWrite, buffer)); - } - - return err; + totalRead += bytesRead; + MAC_ERR_CHECK(FSWrite(inTargetSpecRefNum, (long *) &bytesToWrite, + buffer)); + } + + return err; } #pragma mark - -OSErr -nsAppleSingleDecoder::DTSetAPPL(Str255 volName, short vRefNum, OSType creator, - long applParID, Str255 applName) +Boolean +nsAppleSingleDecoder::IsDirectory(const FSRef *inRef) { - OSErr err; - DTPBRec *pb = NULL; - short dtRefNum; - short realVRefNum; - Boolean newDTDatabase; - - /* get the real vRefnum */ - err = DetermineVRefNum(volName, vRefNum, &realVRefNum); - if (err == noErr) - { - err = DTOpen(volName, vRefNum, &dtRefNum, &newDTDatabase); - if (err == noErr && !newDTDatabase) - { - pb = (DTPBRec*) NewPtrClear( sizeof(DTPBRec) ); - - if (pb==NULL) return -1; + OSErr err; + Boolean isDir; - pb->ioNamePtr = applName; - pb->ioDTRefNum = dtRefNum; - pb->ioDirID = applParID; - pb->ioFileCreator = creator; + if (!inRef) + return false; - err = PBDTAddAPPLSync(pb); - - if (pb) DisposePtr((Ptr)pb); - } - } - - return err; + err = FSGetFinderInfo(inRef, NULL, NULL, &isDir); + if (err != noErr) + return false; + + return isDir; } OSErr -nsAppleSingleDecoder::FSMakeUnique(FSSpec *ioSpec) +nsAppleSingleDecoder::FSMakeUnique(const FSRef *inParentRef, FSRef *outRef) { - OSErr err = noErr; - Boolean bUnique = false; - FSSpec tmp; - long uniqueID = 0; - Str255 name; - short i, j; - unsigned char puniqueID[16]; - char *cuniqueIDPtr; +/* +** This function has descended from Apple Sample Code, but we have +** made changes. Specifically, this function descends from the +** GenerateUniqueHFSUniStr() function in MoreFilesX.c, version 1.0.1. +*/ - // grab suggested name from in-out FSSpec - nsAppleSingleDecoder::PLstrncpy(name, ioSpec->name, ioSpec->name[0]); - name[0] = ioSpec->name[0]; - - for (i=0; i<65536; i++) // prevent infinite loop - { - if (!bUnique) - { - err = FSMakeFSSpec( ioSpec->vRefNum, ioSpec->parID, name, &tmp ); - if (err == fnfErr) - { - bUnique = true; - break; - } - else if (err == noErr) // file already exists - { - // grab suggested name from in-out FSSpec - nsAppleSingleDecoder::PLstrncpy(name, ioSpec->name, ioSpec->name[0]); - name[0] = ioSpec->name[0]; - - // attempt to create a new unique file name - nsAppleSingleDecoder::PLstrncat( name, "\p-", 1 ); - - // tack on digit(s) - cuniqueIDPtr = nsAppleSingleDecoder::ltoa(uniqueID++); - puniqueID[0] = strlen(cuniqueIDPtr); - for (j=0; jname, name, name[0]); - ioSpec->name[0] = name[0]; - - return noErr; -} + OSErr result = noErr; + long i, startSeed = 0x4a696d4c; /* a fine unlikely filename */ + FSRefParam pb; + unsigned char hexStr[17] = "0123456789ABCDEF"; + HFSUniStr255 uniqueName; + + /* set up the parameter block */ + pb.name = uniqueName.unicode; + pb.nameLength = 8; /* always 8 characters */ + pb.textEncodingHint = kTextEncodingUnknown; + pb.newRef = outRef; + pb.ref = inParentRef; + + /* loop until we get fnfErr with a filename in both directories */ + result = noErr; + while ( fnfErr != result ) + { + /* convert startSeed to 8 character Unicode string */ + uniqueName.length = 8; + for ( i = 0; i < 8; ++i ) + { + uniqueName.unicode[i] = hexStr[((startSeed >> ((7-i)*4)) & 0xf)]; + } + + result = PBMakeFSRefUnicodeSync(&pb); + if ( fnfErr == result ) + { + OSErr err; + MAC_ERR_CHECK(FSCreateFileUnicode(inParentRef, uniqueName.length, + uniqueName.unicode, kFSCatInfoNone, NULL, outRef, NULL)); + + return noErr; + } + else if ( noErr != result) + { + /* exit if anything other than noErr or fnfErr */ + return result; + } + + /* increment seed for next pass through loop */ + ++(startSeed); + } + + return result; +} /*----------------------------------------------------------------------* * Utilities *----------------------------------------------------------------------*/ -char * -nsAppleSingleDecoder::ltoa(long n) -{ - char *s; - int i, j, sign, tmp; - - /* check sign and convert to positive to stringify numbers */ - if ( (sign = n) < 0) - n = -n; - i = 0; - s = (char*) malloc(sizeof(char)); - - /* grow string as needed to add numbers from powers of 10 down till none left */ - do - { - s = (char*) realloc(s, (i+1)*sizeof(char)); - s[i++] = n % 10 + '0'; /* '0' or 30 is where ASCII numbers start from */ - s[i] = '\0'; - } - while( (n /= 10) > 0); - - /* tack on minus sign if we found earlier that this was negative */ - if (sign < 0) - { - s = (char*) realloc(s, (i+1)*sizeof(char)); - s[i++] = '-'; - } - s[i] = '\0'; - - /* pop numbers (and sign) off of string to push back into right direction */ - for (i = 0, j = strlen(s) - 1; i < j; i++, j--) - { - tmp = s[i]; - s[i] = s[j]; - s[j] = tmp; - } - - return s; -} - -StringPtr -nsAppleSingleDecoder::PLstrncpy(StringPtr dst, ConstStr255Param src, short max) -{ - int srcLen = src[0]; - if (srcLen > max) - srcLen = max; - dst[0] = srcLen; - memcpy(&dst[1], &src[1], srcLen); - return dst; -} - -StringPtr -nsAppleSingleDecoder::PLstrncat(StringPtr dst, ConstStr255Param src, short max) -{ - int srcLen = src[0], dstLen = dst[0]; - if (srcLen > max) - srcLen = max; - dst[0] += srcLen; - memcpy(&dst[dstLen+1], &src[1], srcLen); - return dst; -} - Boolean -nsAppleSingleDecoder::PLstrcmp(StringPtr str1, StringPtr str2) +nsAppleSingleDecoder::UCstrcmp(const HFSUniStr255 *str1, + const HFSUniStr255 *str2) { - Boolean bEqual = true; - - // check for same length - if (str1[0] == str2[0]) - { - // verify mem blocks match - if (0 != memcmp(&str1[1], &str2[1], str1[0])) - bEqual = false; - } - else - bEqual = false; - - return bEqual; + OSStatus status; + Boolean bEqual; + + status = UCCompareTextDefault(kUCCollateStandardOptions, str1->unicode, + str1->length, str2->unicode, str2->length, + &bEqual, NULL); + if (status != noErr) + return false; + + return bEqual; } +#ifdef STANDALONE_ASD +int +main(int argc, char **argv) +{ + OSErr err; + FSRef encoded, decoded; + nsAppleSingleDecoder *decoder = new nsAppleSingleDecoder; + Boolean isDir; + + if (argc < 2) + { + cout << "usage: " << argv[0] << " " << endl + << "\t\tAppleSingle encoded file path" << endl + << "\t\tor" << endl + << "\t\tfolder path containing AppleSingle encoded files." << endl; + exit(-1); + } + + err = FSPathMakeRef((const UInt8 *)argv[1], &encoded, &isDir); + if (err != noErr) + return 1; + + // handle AppleSingle encoded files + if (!isDir) + { + Boolean isEncoded = nsAppleSingleDecoder::IsAppleSingleFile(&encoded); + cout << "IsAppleSingleFile returned: " << (isEncoded ? "true" : "false") + << endl; + + if (isEncoded) + { + err = decoder->Decode(&encoded, &decoded); + cout << "Decode returned: " << err << endl; + } + } + + // handle folders containing AppleSingle encoded files + else + { + err = decoder->DecodeFolder(&encoded); + cout << "DecodeFolder returned: " << err << endl; + } + + // verify out file (n/a for folders) + if (!isDir) + { + err = FSGetCatalogInfo(&decoded, kFSCatInfoNone, NULL, NULL, NULL, NULL); + if (err == noErr) + { + cout << "Decoded file appears to exist" << endl; + char path[1024]; + FSRefMakePath(&decoded, (UInt8 *)path, 1024); + cout << "Decoded file path: " << path << endl; + } + else + cout << "Decoded file doesn't appear to exist: " << err << endl; + } + + return 0; +} +#endif /* STANDALONE_ASD */ diff --git a/mozilla/xpinstall/src/nsAppleSingleDecoder.h b/mozilla/xpinstall/src/nsAppleSingleDecoder.h index da1d797a206..cfe403ca503 100644 --- a/mozilla/xpinstall/src/nsAppleSingleDecoder.h +++ b/mozilla/xpinstall/src/nsAppleSingleDecoder.h @@ -23,13 +23,9 @@ /*----------------------------------------------------------------------* * Implements a simple AppleSingle decoder, as described in RFC1740 - * http://andrew2.andrew.cmu.edu/rfc/rfc1740.html + * http://andrew2.andrew.cmu.edu/rfc/rfc1740.html *----------------------------------------------------------------------*/ -#ifndef macintosh -#error Sorry! This is Mac only functionality! -#endif - #pragma options align=mac68k #ifndef _NS_APPLESINGLEDECODER_H_ @@ -37,48 +33,50 @@ #include #include -#include -#include +#include /*----------------------------------------------------------------------* * Struct definitions from RFC1740 *----------------------------------------------------------------------*/ +#define APPLESINGLE_MAGIC 0x00051600L +#define APPLESINGLE_VERSION 0x00020000L + typedef struct ASHeader /* header portion of AppleSingle */ { - /* AppleSingle = 0x00051600; AppleDouble = 0x00051607 */ - UInt32 magicNum; /* internal file type tag */ - UInt32 versionNum; /* format version: 2 = 0x00020000 */ - UInt8 filler[16]; /* filler, currently all bits 0 */ - UInt16 numEntries; /* number of entries which follow */ + /* AppleSingle = 0x00051600; AppleDouble = 0x00051607 */ + UInt32 magicNum; /* internal file type tag */ + UInt32 versionNum; /* format version: 2 = 0x00020000 */ + UInt8 filler[16]; /* filler, currently all bits 0 */ + UInt16 numEntries; /* number of entries which follow */ } ASHeader ; /* ASHeader */ typedef struct ASEntry /* one AppleSingle entry descriptor */ { - UInt32 entryID; /* entry type: see list, 0 invalid */ - UInt32 entryOffset; /* offset, in octets, from beginning */ - /* of file to this entry's data */ - UInt32 entryLength; /* length of data in octets */ + UInt32 entryID; /* entry type: see list, 0 invalid */ + UInt32 entryOffset; /* offset, in octets, from beginning */ + /* of file to this entry's data */ + UInt32 entryLength; /* length of data in octets */ } ASEntry; /* ASEntry */ typedef struct ASFinderInfo { - FInfo ioFlFndrInfo; /* PBGetFileInfo() or PBGetCatInfo() */ - FXInfo ioFlXFndrInfo; /* PBGetCatInfo() (HFS only) */ + FInfo ioFlFndrInfo; /* PBGetFileInfo() or PBGetCatInfo() */ + FXInfo ioFlXFndrInfo; /* PBGetCatInfo() (HFS only) */ } ASFinderInfo; /* ASFinderInfo */ -typedef struct ASMacInfo /* entry ID 10, Macintosh file information */ +typedef struct ASMacInfo /* entry ID 10, Macintosh file information */ { - UInt8 filler[3]; /* filler, currently all bits 0 */ - UInt8 ioFlAttrib; /* PBGetFileInfo() or PBGetCatInfo() */ + UInt8 filler[3]; /* filler, currently all bits 0 */ + UInt8 ioFlAttrib; /* PBGetFileInfo() or PBGetCatInfo() */ } ASMacInfo; -typedef struct ASFileDates /* entry ID 8, file dates info */ +typedef struct ASFileDates /* entry ID 8, file dates info */ { - SInt32 create; /* file creation date/time */ - SInt32 modify; /* last modification date/time */ - SInt32 backup; /* last backup date/time */ - SInt32 access; /* last access date/time */ + SInt32 create; /* file creation date/time */ + SInt32 modify; /* last modification date/time */ + SInt32 backup; /* last backup date/time */ + SInt32 access; /* last access date/time */ } ASFileDates; /* ASFileDates */ /* entryID list */ @@ -88,7 +86,7 @@ typedef struct ASFileDates /* entry ID 8, file dates info */ #define AS_COMMENT 4 /* standard Mac comment */ #define AS_ICONBW 5 /* Mac black & white icon */ #define AS_ICONCOLOR 6 /* Mac color icon */ - /* 7 /* not used */ +/* 7 not used */ #define AS_FILEDATES 8 /* file dates; create, modify, etc */ #define AS_FINDERINFO 9 /* Mac Finder info & extended info */ #define AS_MACINFO 10 /* Mac file info, attributes, etc */ @@ -103,118 +101,115 @@ typedef struct ASFileDates /* entry ID 8, file dates info */ /*----------------------------------------------------------------------* * Macros *----------------------------------------------------------------------*/ -#define MAC_ERR_CHECK(_funcCall) \ - err = _funcCall; \ - if (err!=noErr) \ - return err; - - +#define MAC_ERR_CHECK(_funcCall) \ + err = _funcCall; \ + if (err!=noErr) \ + return err; + + class nsAppleSingleDecoder { public: - nsAppleSingleDecoder(FSSpec *inSpec, FSSpec *outSpec); - nsAppleSingleDecoder(); - ~nsAppleSingleDecoder(); - - /** - * Decode - * - * Takes an "in" FSSpec for the source file in AppleSingle - * format to decode and write out to an "out" FSSpec. - * This form is used when the Decode(void) method has already - * been invoked once and this object is reused to decode - * another AppleSingled file: useful in iteration to avoid - * nsAppleSingleDecoder object instantiation per file. - * - * @param inSpec the AppleSingled file to decode - * @param outSpec the destination file in which the decoded - * data was written out (empty when passed in - * and filled on return) - * @return err a standard MacOS OSErr where noErr means OK - */ - OSErr Decode(FSSpec *inSpec, FSSpec *outSpec); - - /** - * Decode - * - * Decodes the AppleSingled file passed in to the constructor - * and writes out the decoded data to the outSpec passed to the - * constructor. - * - * @return err a standard MacOS OSErr where noErr = OK - */ - OSErr Decode(); - - /** - * DecodeFolder - * - * Traverses arbitrarily nested subdirs decoding any files - * in AppleSingle format and leaving other files alone. - * - * @param aFolder the folder whose contents to decode - * @return err a standard MacOS err (dirNFErr if invalid dir, noErr = OK) - */ - OSErr DecodeFolder(FSSpec *aFolder); + nsAppleSingleDecoder(const FSRef *inRef, FSRef *outRef); + nsAppleSingleDecoder(); + ~nsAppleSingleDecoder(); + + /** + * Decode + * + * Takes an "in" FSSpec for the source file in AppleSingle + * format to decode and write out to an "out" FSSpec. + * This form is used when the Decode(void) method has already + * been invoked once and this object is reused to decode + * another AppleSingled file: useful in iteration to avoid + * nsAppleSingleDecoder object instantiation per file. + * + * @param inRef the AppleSingled file to decode + * @param outRef the destination file in which the decoded + * data was written out (empty when passed in + * and filled on return) + * @return err a standard MacOS OSErr where noErr means OK + */ + OSErr Decode(const FSRef *inRef, FSRef *outRef); + + /** + * Decode + * + * Decodes the AppleSingled file passed in to the constructor + * and writes out the decoded data to the outSpec passed to the + * constructor. + * + * @return err a standard MacOS OSErr where noErr = OK + */ + OSErr Decode(); + + /** + * DecodeFolder + * + * Traverses arbitrarily nested subdirs decoding any files + * in AppleSingle format and leaving other files alone. + * + * @param aFolder the folder whose contents to decode + * @return err a standard MacOS err + * (dirNFErr if invalid dir, noErr = OK) + */ + OSErr DecodeFolder(const FSRef *aFolder); - /** - * IsAppleSingleFile - * - * Checks the file header to see whether this is an AppleSingle - * version 2 file by matching the magicNum field in the header. - * - * @param inSpec the file to check - * @return bAppleSingle a Boolean where true indicates this is - * in fact an AppleSingle file - */ - static Boolean IsAppleSingleFile(FSSpec *inSpec); - - /** - * String utilities to ensure building standalone - * since Mozilla doesn't use PLStringFuncs. - */ - static StringPtr PLstrncpy(StringPtr dst, ConstStr255Param src, short max); - static StringPtr PLstrncat(StringPtr dst, ConstStr255Param src, short max); - static Boolean PLstrcmp(StringPtr str1, StringPtr str2); - - /** - * ltoa -- long to ascii - * - * Converts a long to a C string. We allocate - * a string of the appropriate size and the caller - * should assume ownership of the returned pointer. - */ - static char *ltoa(long n); - -private: - FSSpec *mInSpec; - FSSpec *mOutSpec; - short mInRefNum; // cache since it's used through the life of one Decode cycle - Boolean mRenameReqd; - OSType mCreator; - OSType mType; - - OSErr ProcessASEntry(ASEntry inEntry); - OSErr ProcessDataFork(ASEntry inEntry); - OSErr ProcessResourceFork(ASEntry inEntry); - OSErr ProcessRealName(ASEntry inEntry); - OSErr ProcessFileDates(ASEntry inEntry); - OSErr ProcessFinderInfo(ASEntry inEntry); - OSErr ProcessMacInfo(ASEntry inEntry); - OSErr EntryToMacFile(ASEntry inEntry, UInt16 inTargetSpecRefNum); - OSErr DTSetAPPL(Str255 volName, short vRefNum, OSType creator, - long applParID, Str255 applName); + /** + * IsAppleSingleFile + * + * Checks the file header to see whether this is an AppleSingle + * version 2 file by matching the magicNum field in the header. + * + * @param inRef the file to check + * @return bAppleSingle a Boolean where true indicates this is + * in fact an AppleSingle file + */ + static Boolean IsAppleSingleFile(const FSRef *inRef); + + /** + * IsDirectory + * + * Check whether the supplied FSSpec points to a directory. + * + * @param inRef the file/directory spec + * @return bDir true iff this spec is a valid directory + */ + static Boolean IsDirectory(const FSRef *inRef); - OSErr FSMakeUnique(FSSpec *ioSpec); + /** + * String utility wrapper to compare to Unicode filenames. + */ + static Boolean UCstrcmp(const HFSUniStr255 *str1, const HFSUniStr255 *str2); + +private: + const FSRef *mInRef; + FSRef *mOutRef; + // cache since it's used through the life of one Decode cycle: + SInt16 mInRefNum; + Boolean mRenameReqd; + + OSErr ProcessASEntry(ASEntry inEntry); + OSErr ProcessDataFork(ASEntry inEntry); + OSErr ProcessResourceFork(ASEntry inEntry); + OSErr ProcessRealName(ASEntry inEntry); + OSErr ProcessFileDates(ASEntry inEntry); + OSErr ProcessFinderInfo(ASEntry inEntry); + OSErr EntryToMacFile(ASEntry inEntry, UInt16 inTargetSpecRefNum); + + OSErr FSMakeUnique(const FSRef *inParentRef, FSRef *outRef); }; #ifdef __cplusplus extern "C" { #endif -pascal void -DecodeDirIterateFilter(const CInfoPBRec * const cpbPtr, Boolean *quitFlag, void *yourDataPtr); +Boolean +DecodeDirIterateFilter(Boolean containerChanged, ItemCount currentLevel, + const FSCatalogInfo *catalogInfo, const FSRef *ref, + const FSSpec *spec, const HFSUniStr255 *name, void *yourDataPtr); #ifdef __cplusplus } @@ -222,4 +217,4 @@ DecodeDirIterateFilter(const CInfoPBRec * const cpbPtr, Boolean *quitFlag, void #pragma options align=reset -#endif /* _NS_APPLESINGLEDECODER_H_ */ \ No newline at end of file +#endif /* _NS_APPLESINGLEDECODER_H_ */ diff --git a/mozilla/xpinstall/src/nsInstall.cpp b/mozilla/xpinstall/src/nsInstall.cpp index b1870d9299e..33027cc7bf2 100644 --- a/mozilla/xpinstall/src/nsInstall.cpp +++ b/mozilla/xpinstall/src/nsInstall.cpp @@ -23,6 +23,7 @@ * Douglas Turner * Pierre Phaneuf * Sean Su + * Samir Gehani */ @@ -75,8 +76,8 @@ #include "nsInstallFileOpEnums.h" #include "nsInstallFileOpItem.h" -#ifdef XP_MAC -#include "Gestalt.h" +#if defined(XP_MAC) || defined(XP_MACOSX) +#include #include "nsAppleSingleDecoder.h" #include "nsILocalFileMac.h" #endif @@ -328,7 +329,7 @@ nsInstall::GetInstallPlatform(nsCString& aPlatform) mInstallPlatform += ' '; mInstallPlatform += (char*)name.machine; } -#elif defined (XP_MAC) +#elif defined (XP_MAC) || defined (XP_MACOSX) mInstallPlatform += "PPC"; #elif defined(XP_OS2) ULONG os2ver = 0; @@ -902,12 +903,12 @@ nsInstall::FinalizeInstall(PRInt32* aReturn) return NS_OK; } -#ifdef XP_MAC +#if defined(XP_MAC) || defined(XP_MACOSX) #define GESTALT_CHAR_CODE(x) (((unsigned long) ((x[0]) & 0x000000FF)) << 24) \ | (((unsigned long) ((x[1]) & 0x000000FF)) << 16) \ | (((unsigned long) ((x[2]) & 0x000000FF)) << 8) \ | (((unsigned long) ((x[3]) & 0x000000FF))) -#endif /* XP_MAC */ +#endif /* XP_MACOS || XP_MACOSX */ PRInt32 nsInstall::Gestalt(const nsString& aSelector, PRInt32* aReturn) @@ -921,7 +922,7 @@ nsInstall::Gestalt(const nsString& aSelector, PRInt32* aReturn) *aReturn = SaveError( result ); return NS_OK; } -#ifdef XP_MAC +#if defined(XP_MAC) || defined(XP_MACOSX) long response = 0; char selectorChars[4]; @@ -945,7 +946,7 @@ nsInstall::Gestalt(const nsString& aSelector, PRInt32* aReturn) else *aReturn = response; -#endif +#endif /* XP_MAC || XP_MACOSX */ return NS_OK; } @@ -2159,7 +2160,8 @@ nsInstall::FileOpFileMacAlias(nsIFile *aSourceFile, nsIFile *aAliasFile, PRInt32 *aReturn = nsInstall::SUCCESS; -#ifdef XP_MAC +#if defined(XP_MAC) || defined(XP_MACOSX) + nsInstallFileOpItem* ifop = new nsInstallFileOpItem(this, NS_FOP_MAC_ALIAS, aSourceFile, aAliasFile, aReturn); if (!ifop) { @@ -2186,7 +2188,8 @@ nsInstall::FileOpFileMacAlias(nsIFile *aSourceFile, nsIFile *aAliasFile, PRInt32 } SaveError(*aReturn); -#endif + +#endif /* XP_MAC || XP_MACOSX */ return NS_OK; } @@ -2667,16 +2670,17 @@ nsInstall::ExtractFileFromJar(const nsString& aJarfile, nsIFile* aSuggestedName, } } -#ifdef XP_MAC - FSSpec finalSpec, extractedSpec; +#if defined(XP_MAC) || defined(XP_MACOSX) + FSRef finalRef, extractedRef; nsCOMPtr tempExtractHereSpec; tempExtractHereSpec = do_QueryInterface(extractHereSpec, &rv); - tempExtractHereSpec->GetFSSpec(&extractedSpec); + tempExtractHereSpec->GetFSRef(&extractedRef); - if ( nsAppleSingleDecoder::IsAppleSingleFile(&extractedSpec) ) + if ( nsAppleSingleDecoder::IsAppleSingleFile(&extractedRef) ) { - nsAppleSingleDecoder *asd = new nsAppleSingleDecoder(&extractedSpec, &finalSpec); + nsAppleSingleDecoder *asd = + new nsAppleSingleDecoder(&extractedRef, &finalRef); OSErr decodeErr = fnfErr; if (asd) @@ -2689,22 +2693,20 @@ nsInstall::ExtractFileFromJar(const nsString& aJarfile, nsIFile* aSuggestedName, return EXTRACTION_FAILED; } - if ( !(extractedSpec.vRefNum == finalSpec.vRefNum) || - !(extractedSpec.parID == finalSpec.parID) || - !(nsAppleSingleDecoder::PLstrcmp(extractedSpec.name, finalSpec.name)) ) + if (noErr != FSCompareFSRefs(&extractedRef, &finalRef)) { // delete the unique extracted file that got renamed in AS decoding - FSpDelete(&extractedSpec); + FSDeleteObject(&extractedRef); // "real name" in AppleSingle entry may cause file rename - tempExtractHereSpec->InitWithFSSpec(&finalSpec); + tempExtractHereSpec->InitWithFSRef(&finalRef); extractHereSpec = do_QueryInterface(tempExtractHereSpec, &rv); } } -#endif +#endif /* XP_MAC || XP_MACOSX */ extractHereSpec->Clone(aRealName); - + return nsInstall::SUCCESS; } diff --git a/mozilla/xpinstall/src/nsInstallFileOpItem.cpp b/mozilla/xpinstall/src/nsInstallFileOpItem.cpp index a9aa4f76321..da4c89cfd0a 100644 --- a/mozilla/xpinstall/src/nsInstallFileOpItem.cpp +++ b/mozilla/xpinstall/src/nsInstallFileOpItem.cpp @@ -42,6 +42,7 @@ #include "ScheduledTasks.h" #include "nsProcess.h" #include "nsNativeCharsetUtils.h" +#include "nsReadableUtils.h" #include "nsInstallExecute.h" #ifdef _WINDOWS @@ -49,13 +50,12 @@ #include "nsWinShortcut.h" #endif -#ifdef XP_MAC -#include "Aliases.h" -#include "Gestalt.h" -#include "Resources.h" -#include "TextUtils.h" -#include "script.h" -#include "MoreFilesExtras.h" +#if defined(XP_MAC) || defined(XP_MACOSX) +#include +#include +#include +#include +#include "MoreFilesX.h" #include "nsILocalFileMac.h" #endif @@ -1322,7 +1322,7 @@ PRInt32 nsInstallFileOpItem::NativeFileOpMacAliasPrepare() { -#ifdef XP_MAC +#if defined(XP_MAC) || defined(XP_MACOSX) nsCOMPtr targetFile = do_QueryInterface(mTarget); nsCOMPtr sourceFile = do_QueryInterface(mSrc); @@ -1346,7 +1346,7 @@ nsInstallFileOpItem::NativeFileOpMacAliasPrepare() if (NS_FAILED(rv)) return nsInstall::FILENAME_ALREADY_USED; } -#endif /* XP_MAC */ +#endif /* XP_MAC || XP_MACOSX */ return nsInstall::SUCCESS; } @@ -1355,16 +1355,16 @@ PRInt32 nsInstallFileOpItem::NativeFileOpMacAliasComplete() { -#ifdef XP_MAC +#if defined(XP_MAC) || defined(XP_MACOSX) // XXX gestalt to see if alias manager is around nsCOMPtr localFileMacTarget = do_QueryInterface(mTarget); nsCOMPtr localFileMacSrc = do_QueryInterface(mSrc); - FSSpec fsSource, fsAlias; + FSRef sourceRef, aliasRef, aliasParentRef; + HFSUniStr255 aliasName; PRBool exists; AliasHandle aliasH; - FInfo info; OSErr err = noErr; nsresult rv = NS_OK; @@ -1386,23 +1386,43 @@ nsInstallFileOpItem::NativeFileOpMacAliasComplete() return nsInstall::FILENAME_ALREADY_USED; } - rv = localFileMacSrc->GetFSSpec(&fsSource); - if (!NS_SUCCEEDED(rv)) return rv; - rv = localFileMacTarget->GetFSSpec(&fsAlias); - if (!NS_SUCCEEDED(rv)) return rv; + rv = localFileMacSrc->GetFSRef(&sourceRef); + if (NS_FAILED(rv)) return rv; - err = NewAliasMinimal( &fsSource, &aliasH ); + // get alias parent + nsCOMPtr aliasParentIFile; + rv = localFileMacTarget->GetParent(getter_AddRefs(aliasParentIFile)); + if (NS_FAILED(rv)) return rv; + nsCOMPtr macDaddy(do_QueryInterface(aliasParentIFile)); + rv = macDaddy->GetFSRef(&aliasParentRef); + if (NS_FAILED(rv)) return rv; + + // get alias leaf name + nsAutoString leafName; + rv = localFileMacTarget->GetLeafName(leafName); + if (NS_FAILED(rv)) return rv; + aliasName.length = leafName.Length(); + CopyUnicodeTo(leafName, 0, aliasName.unicode, aliasName.length); + + err = FSNewAliasMinimal( &sourceRef, &aliasH ); if (err != noErr) // bubble up Alias Manager error return err; // create the alias file - FSpGetFInfo(&fsSource, &info); - FSpCreateResFile(&fsAlias, info.fdCreator, info.fdType, smRoman); - short refNum = FSpOpenResFile(&fsAlias, fsRdWrPerm); + FSCatalogInfo catInfo; + FSGetCatalogInfo(&sourceRef, kFSCatInfoFinderInfo, &catInfo, + NULL, NULL, NULL); + // mark newly created file as an alias file + FInfo *fInfo = (FInfo *) catInfo.finderInfo; + fInfo->fdFlags |= kIsAlias; + FSCreateResFile(&aliasParentRef, aliasName.length, aliasName.unicode, + kFSCatInfoFinderInfo, &catInfo, &aliasRef, NULL); + + SInt16 refNum = FSOpenResFile(&aliasRef, fsRdWrPerm); if (refNum != -1) { UseResFile(refNum); - AddResource((Handle)aliasH, rAliasType, 0, fsAlias.name); + AddResource((Handle)aliasH, rAliasType, 0, "\pAlias"); ReleaseResource((Handle)aliasH); UpdateResFile(refNum); CloseResFile(refNum); @@ -1410,11 +1430,7 @@ nsInstallFileOpItem::NativeFileOpMacAliasComplete() else return nsInstall::SUCCESS; // non-fatal so prevent internal abort - // mark newly created file as an alias file - FSpGetFInfo(&fsAlias, &info); - info.fdFlags |= kIsAlias; - FSpSetFInfo(&fsAlias, &info); -#endif +#endif /* XP_MAC || XP_MACOSX */ return nsInstall::SUCCESS; } @@ -1422,7 +1438,7 @@ nsInstallFileOpItem::NativeFileOpMacAliasComplete() PRInt32 nsInstallFileOpItem::NativeFileOpMacAliasAbort() { -#ifdef XP_MAC +#if defined(XP_MAC) || defined(XP_MACOSX) NativeFileOpFileDeleteComplete(mTarget); #endif