Back to index

lightning-sunbird  0.9+nobinonly
Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes
nsAppleSingleDecoder Class Reference

#include <nsAppleSingleDecoder.h>

List of all members.

Public Member Functions

 nsAppleSingleDecoder (const FSRef *inRef, FSRef *outRef)
 nsAppleSingleDecoder ()
 ~nsAppleSingleDecoder ()
OSErr Decode (const FSRef *inRef, FSRef *outRef)
 Decode.
OSErr Decode ()
 Decode.
OSErr DecodeFolder (const FSRef *aFolder)
 DecodeFolder.

Static Public Member Functions

static Boolean IsAppleSingleFile (const FSRef *inRef)
 IsAppleSingleFile.
static Boolean IsDirectory (const FSRef *inRef)
 IsDirectory.
static Boolean UCstrcmp (const HFSUniStr255 *str1, const HFSUniStr255 *str2)
 String utility wrapper to compare to Unicode filenames.

Private Member Functions

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)

Private Attributes

const FSRefmInRef
FSRefmOutRef
SInt16 mInRefNum
Boolean mRenameReqd

Detailed Description

Definition at line 128 of file nsAppleSingleDecoder.h.


Constructor & Destructor Documentation

Definition at line 64 of file nsAppleSingleDecoder.cpp.

: mInRef(NULL), 
  mOutRef(NULL),
  mInRefNum(0),
  mRenameReqd(false)
{
#ifdef MOZILLA_CLIENT
    MOZ_COUNT_CTOR(nsAppleSingleDecoder);
#endif

  if (inRef && outRef)
  {
    /* merely point to FSRefs, not own 'em */
    mInRef = inRef;
    mOutRef = outRef;
  }
}

Definition at line 82 of file nsAppleSingleDecoder.cpp.

: mInRef(NULL), 
  mOutRef(NULL),
  mInRefNum(0),
  mRenameReqd(false)
{
#ifdef MOZILLA_CLIENT
  MOZ_COUNT_CTOR(nsAppleSingleDecoder);
#endif
}

Definition at line 93 of file nsAppleSingleDecoder.cpp.

{
  /* not freeing FSRefs since we don't own 'em */

#ifdef MOZILLA_CLIENT
  MOZ_COUNT_DTOR(nsAppleSingleDecoder);
#endif
}

Member Function Documentation

OSErr nsAppleSingleDecoder::Decode ( const FSRef inRef,
FSRef outRef 
)

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.

Parameters:
inRefthe AppleSingled file to decode
outRefthe destination file in which the decoded data was written out (empty when passed in and filled on return)
Returns:
err a standard MacOS OSErr where noErr means OK

Definition at line 192 of file nsAppleSingleDecoder.cpp.

{
  OSErr   err = noErr;
  
  // param check
  if (inRef && outRef)
  {
    mInRef = inRef;    // reinit
    mOutRef = outRef;
    mRenameReqd = false; 
  }
  else
    return paramErr;
    
  err = Decode();
  
  return err;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Decode.

Decodes the AppleSingled file passed in to the constructor and writes out the decoded data to the outSpec passed to the constructor.

Returns:
err a standard MacOS OSErr where noErr = OK

Definition at line 108 of file nsAppleSingleDecoder.cpp.

{
  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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

DecodeFolder.

Traverses arbitrarily nested subdirs decoding any files in AppleSingle format and leaving other files alone.

Parameters:
aFolderthe folder whose contents to decode
Returns:
err a standard MacOS err (dirNFErr if invalid dir, noErr = OK)

Definition at line 250 of file nsAppleSingleDecoder.cpp.

{
  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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

OSErr nsAppleSingleDecoder::EntryToMacFile ( ASEntry  inEntry,
UInt16  inTargetSpecRefNum 
) [private]

Definition at line 532 of file nsAppleSingleDecoder.cpp.

{
#define BUFFER_SIZE 8192

  OSErr  err = noErr;
  char   buffer[BUFFER_SIZE];
  UInt32 totalRead = 0, bytesRead, bytesToWrite;

  MAC_ERR_CHECK(SetFPos( mInRefNum, fsFromStart, inEntry.entryOffset ));

  while ( totalRead < inEntry.entryLength )
  {
// Should we yield in here?
    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, (long *) &bytesToWrite, 
      buffer));
  }  
  
  return err;
}

Here is the caller graph for this function:

OSErr nsAppleSingleDecoder::FSMakeUnique ( const FSRef inParentRef,
FSRef outRef 
) [private]

Definition at line 583 of file nsAppleSingleDecoder.cpp.

{
/*
** 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.
*/

  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;
}    

Here is the caller graph for this function:

IsAppleSingleFile.

Checks the file header to see whether this is an AppleSingle version 2 file by matching the magicNum field in the header.

Parameters:
inRefthe file to check
Returns:
bAppleSingle a Boolean where true indicates this is in fact an AppleSingle file

Definition at line 273 of file nsAppleSingleDecoder.cpp.

{
  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;

  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);
}

Here is the caller graph for this function:

IsDirectory.

Check whether the supplied FSSpec points to a directory.

Parameters:
inRefthe file/directory spec
Returns:
bDir true iff this spec is a valid directory

Definition at line 567 of file nsAppleSingleDecoder.cpp.

{
  OSErr err;
  Boolean isDir;

  if (!inRef)
    return false;

  err = FSGetFinderInfo(inRef, NULL, NULL, &isDir);
  if (err != noErr)
    return false;
  
  return isDir;
}

Here is the call graph for this function:

Here is the caller graph for this function:

OSErr nsAppleSingleDecoder::ProcessASEntry ( ASEntry  inEntry) [private]

Definition at line 318 of file nsAppleSingleDecoder.cpp.

{
  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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

OSErr nsAppleSingleDecoder::ProcessDataFork ( ASEntry  inEntry) [private]

Definition at line 353 of file nsAppleSingleDecoder.cpp.

{
  OSErr  err = noErr;
  SInt16  refNum;
  
  /* Setup the files */
  HFSUniStr255 dataForkName;
  err = FSGetDataForkName( &dataForkName );
  if (err != noErr) 
    return err;

  err = FSOpenFork( mOutRef, dataForkName.length, dataForkName.unicode, 
          fsWrPerm, &refNum );

  if ( err == noErr )
    err = EntryToMacFile( inEntry, refNum );
  
  FSClose( refNum );
  return err;
}

Here is the call graph for this function:

Here is the caller graph for this function:

OSErr nsAppleSingleDecoder::ProcessFileDates ( ASEntry  inEntry) [private]

Definition at line 447 of file nsAppleSingleDecoder.cpp.

{
  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
  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;
}

Here is the caller graph for this function:

OSErr nsAppleSingleDecoder::ProcessFinderInfo ( ASEntry  inEntry) [private]

Definition at line 498 of file nsAppleSingleDecoder.cpp.

{
  OSErr         err = noErr;
  ASFinderInfo  info;
  UInt32        bytesRead;
  FSCatalogInfo catInfo;
  
  if (inEntry.entryLength != sizeof( ASFinderInfo ))
    return -1;

  MAC_ERR_CHECK(SetFPos(mInRefNum, fsFromStart, inEntry.entryOffset));

  bytesRead = sizeof(info);
  MAC_ERR_CHECK(FSRead(mInRefNum, (long *) &bytesRead, &info));
  if (bytesRead != inEntry.entryLength)
    return -1;
    
  MAC_ERR_CHECK(FSGetCatalogInfo(mOutRef, kFSCatInfoGettableInfo, &catInfo, 
    NULL, NULL, NULL));

  BlockMoveData((const void *) &info.ioFlFndrInfo, 
    (void *) &catInfo.finderInfo, sizeof(FInfo));
  BlockMoveData((const void *) &info.ioFlXFndrInfo, 
    (void *) &catInfo.extFinderInfo, sizeof(FXInfo));

  MAC_ERR_CHECK(FSSetCatalogInfo(mOutRef, 
    kFSCatInfoFinderInfo |
    kFSCatInfoFinderXInfo,
    &catInfo));
    
  return err;
}

Here is the caller graph for this function:

OSErr nsAppleSingleDecoder::ProcessRealName ( ASEntry  inEntry) [private]

Definition at line 396 of file nsAppleSingleDecoder.cpp.

{
  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));

    // 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;

    // 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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

OSErr nsAppleSingleDecoder::ProcessResourceFork ( ASEntry  inEntry) [private]

Definition at line 375 of file nsAppleSingleDecoder.cpp.

{
  OSErr  err = noErr;
  SInt16  refNum;
    
  HFSUniStr255 rsrcForkName;
  err = FSGetResourceForkName( &rsrcForkName );
  if (err != noErr) 
    return err;

  err = FSOpenFork( mOutRef, rsrcForkName.length, rsrcForkName.unicode, 
          fsWrPerm, &refNum );

  if ( err == noErr )
    err = EntryToMacFile( inEntry, refNum );
  
  FSClose( refNum );
  return err;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Boolean nsAppleSingleDecoder::UCstrcmp ( const HFSUniStr255 *  str1,
const HFSUniStr255 *  str2 
) [static]

String utility wrapper to compare to Unicode filenames.

Definition at line 641 of file nsAppleSingleDecoder.cpp.

{
  OSStatus          status;
  Boolean           bEqual; 

  status = UCCompareTextDefault(kUCCollateStandardOptions, str1->unicode, 
                                 str1->length, str2->unicode, str2->length, 
                                 &bEqual, NULL);
  if (status != noErr)
    return false;

  return bEqual;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

Definition at line 205 of file nsAppleSingleDecoder.h.

Definition at line 208 of file nsAppleSingleDecoder.h.

Definition at line 206 of file nsAppleSingleDecoder.h.

Definition at line 209 of file nsAppleSingleDecoder.h.


The documentation for this class was generated from the following files: