📄 pgpmacbinary.c
字号:
/*____________________________________________________________________________
Copyright (C) 1997 Network Associates Inc. and affiliated companies.
All rights reserved.
$Id: pgpMacBinary.c,v 1.21 1999/03/10 02:52:58 heller Exp $
____________________________________________________________________________*/
#include "pgpConfig.h"
#include <string.h>
#include "pgpMem.h"
#include "pgpErrors.h"
#include "pgpIO.h"
#include "pgpLineEndIO.h"
#include "pgpIOUtilities.h"
#include "pgpFileUtilities.h"
#include "pgpMacBinary.h"
#include "pgpMacFileMapping.h"
#include "pgpStrings.h"
#include "pgpEndianConversion.h"
#define RawToUInt16( data ) PGPEndianToUInt16( kPGPBigEndian, data )
#define RawToUInt32( data ) PGPEndianToUInt32( kPGPBigEndian, data )
/*____________________________________________________________________________
Convert the raw bytes of the header into an in-memory structure. Fields
in the structure use the approprite endian-ness.
For example, the file type will be big-endian on a Mac and little-endian
on a PC.
____________________________________________________________________________*/
static void
sRawDataToHeader(
PGPByte const * rawData,
MacBinaryHeader * header
)
{
pgpClearMemory( header, sizeof( *header ) );
header->oldVersion = rawData[ kMacBinaryOffset_Version ];
pgpCopyMemory( &rawData[ kMacBinaryOffset_NameLength ], header->name, 64 );
header->info1.fdType =
RawToUInt32( &rawData[ kMacBinaryOffset_FileType ] );
header->info1.fdCreator =
RawToUInt32( &rawData[ kMacBinaryOffset_FileCreator ] );
header->info1.fdFlags =
RawToUInt16( &rawData[ kMacBinaryOffset_FinderFlags ] );
header->info1.fdLocation.v =
RawToUInt16( &rawData[ kMacBinaryOffset_VPos ] );
header->info1.fdLocation.h =
RawToUInt16( &rawData[ kMacBinaryOffset_HPos ] );
header->info1.fdFldr =
RawToUInt16( &rawData[ kMacBinaryOffset_Folder ] );
header->protectedBit = rawData[ kMacBinaryOffset_ProtectedBit ];
header->zero1 = rawData[ kMacBinaryOffset_Zero1 ];
header->dLength =
RawToUInt32( &rawData[ kMacBinaryOffset_DataForkLength ] );
header->rLength =
RawToUInt32( &rawData[ kMacBinaryOffset_ResForkLength ] );
header->creationDate =
RawToUInt32( &rawData[ kMacBinaryOffset_CreationDate ] );
header->modificationDate =
RawToUInt32( &rawData[ kMacBinaryOffset_ModificationDate ] );
header->crc1 = rawData[ kMacBinaryOffset_crc1 ];
header->crc2 = rawData[ kMacBinaryOffset_crc2 ];
}
static PGPUInt16
sCalcCRC16Continue(
PGPUInt16 crc,
const void * data,
PGPInt32 len)
{
const char * dp = (const char *)data;
while(len--)
{
PGPInt16 i;
crc ^= (PGPUInt16)(*dp++) << 8;
for (i = 0; i < 8; ++i)
{
if (crc & 0x8000)
crc = (crc << 1) ^ 0x1021;
else
crc <<= 1;
}
}
return(crc);
}
static PGPUInt16
sCalcCRC16(
const void *data, PGPInt32 len)
{
return sCalcCRC16Continue( 0, data, len);
}
/*____________________________________________________________________________
Return TRUE if the raw header bytes are valid (CRC matches)
____________________________________________________________________________*/
static PGPBoolean
sHeaderIsValid(
const PGPByte *rawBytes )
{
PGPUInt16 crc;
PGPBoolean isValid = FALSE;
/* CRCs don't include themselves */
#define kLengthOfDataToCRC ( kPGPMacBinaryHeaderSize - (2+2) )
crc = sCalcCRC16( rawBytes, kLengthOfDataToCRC );
isValid = ( ( crc >> 8) == rawBytes[ kMacBinaryOffset_crc1 ] &&
(crc & 0xFF) == rawBytes[ kMacBinaryOffset_crc2 ] );
if ( ! isValid )
{
/* we can be more liberal, but our code always sets the CRC */
/* so we may as well require that the CRC be valid */
}
return( isValid );
}
/*____________________________________________________________________________
Read the header into a structure. The struct
produced is an in-memory representation; not necessarily the exact
byte order on disk (primarily for big/little endian reasons, but also
because different compilers on different platforms may pad structures
differently).
____________________________________________________________________________*/
static PGPError
sReadMacBinaryHeader(
PFLFileSpecRef spec,
MacBinaryHeader * header,
PGPBoolean * isValid
)
{
PGPError err = kPGPError_NoErr;
PGPIORef io;
*isValid = FALSE;
err = PGPOpenFileSpec( spec,
kPFLFileOpenFlags_ReadOnly, (PGPFileIORef *)&io );
if ( IsntPGPError( err ) )
{
PGPByte buffer[ kPGPMacBinaryHeaderSize ];
err = PGPIORead( io, sizeof( buffer ), buffer, NULL );
if ( IsntPGPError( err ) )
{
*isValid = sHeaderIsValid( buffer );
/* convert, even if not valid */
sRawDataToHeader( buffer, header );
}
PGPFreeIO( io );
io = NULL;
}
return( err );
}
#if PGP_MACINTOSH /* PGP_MACINTOSH [ */
#include <Script.h>
#include "pgpFileSpecMac.h"
#include "MacFiles.h"
#include "MacErrors.h"
#include "MacStrings.h"
/*____________________________________________________________________________
Mac Version
Create a file from the MacBinary original
____________________________________________________________________________*/
static OSStatus
sCreateFromMacBinary(
PGPMemoryMgrRef memoryMgr,
short fileRef,
MacBinaryHeader const * header,
const FSSpec * tempSpec )
{
OSStatus err;
CInfoPBRec cpb;
err = FSpCreate( tempSpec,
header->info1.fdCreator, header->info1.fdType,
smSystemScript );
if ( IsntErr( err ) && header->dLength != 0 )
{
short outRef;
err = FSpOpenDF( tempSpec, fsRdWrPerm, &outRef );
if ( IsntErr( err ) )
{
err = FSCopyBytes( memoryMgr, fileRef, kPGPMacBinaryHeaderSize,
outRef, 0, header->dLength );
FSClose( outRef );
}
}
if ( IsntErr( err ) && header->rLength != 0 )
{
short outRef;
err = FSpOpenRF( tempSpec, fsRdWrPerm, &outRef );
if ( IsntErr( err ) )
{
err = FSCopyBytes( memoryMgr, fileRef,
kPGPMacBinaryHeaderSize + header->dLength,
outRef, 0, header->rLength );
FSClose( outRef );
}
}
/* set file meta information */
if ( IsntErr( err ) )
{
err = FSpGetCatInfo( tempSpec, &cpb );
if ( IsntErr( err ))
{
#define kFinderFlagsIgnoreMask \
( kHasBeenInited | kNameLocked | kIsInvisible | kIsOnDesk )
cpbFInfo( &cpb ).fdFlags =
header->info1.fdFlags & ~kFinderFlagsIgnoreMask;
cpbFInfo( &cpb ).fdLocation = header->info1.fdLocation;
cpbModificationDate( &cpb ) = header->modificationDate;
cpbCreationDate( &cpb ) = header->creationDate;
err = FSpSetCatInfo( tempSpec, &cpb );
}
}
/* cleanup if error */
if ( IsErr( err ) )
{
(void)FSpDelete( tempSpec );
}
return( err );
}
/*____________________________________________________________________________
Mac Version
____________________________________________________________________________*/
static PGPError
sDeMacBinarize(
PFLFileSpecRef inSpec,
MacBinaryHeader const * header,
PFLFileSpecRef * outSpec )
{
PGPError err = kPGPError_NoErr;
FSSpec fsSpec;
*outSpec = kInvalidPFLFileSpecRef;
err = PFLGetFSSpecFromFileSpec( inSpec, &fsSpec );
if ( IsntPGPError( err ) )
{
short fileRef;
OSStatus macErr;
macErr = FSpOpenDF( &fsSpec, fsRdPerm, &fileRef );
if ( IsntErr( macErr ) )
{
FSSpec tempSpec;
macErr = FSpGetUniqueSpec( &fsSpec, &tempSpec );
if ( IsntErr( macErr ) )
{
macErr = sCreateFromMacBinary(
PFLGetFileSpecMemoryMgr( inSpec ), fileRef,
header, &tempSpec );
}
FSClose( fileRef );
fileRef = 0;
if ( IsntErr( macErr ) )
{
const unsigned char kBinExtension[] = "\p.bin";
/* delete original and move output into its place */
(void)FSpDelete( &fsSpec );
if ( PStringHasSuffix( fsSpec.name, kBinExtension, FALSE ) )
{
fsSpec.name[ 0 ] -= StrLength( kBinExtension );
macErr = FSpGetUniqueSpec( &fsSpec, &fsSpec );
}
if ( IsntErr( macErr ) )
macErr = FSpRename( &tempSpec, fsSpec.name );
}
}
err = MacErrorToPGPError( macErr );
}
if ( IsntPGPError( err ) )
{
err = PFLNewFileSpecFromFSSpec(
PFLGetFileSpecMemoryMgr( inSpec ), &fsSpec, outSpec );
}
return( err );
}
#else /* ] PGP_MACINTOSH [ */
/*____________________________________________________________________________
Non-Mac Version
Copy from input to output, converting mac line endings to PC line endings.
____________________________________________________________________________*/
static PGPError
sCopyAndLineEndConvert(
PGPIORef inRef,
PGPSize requestCount,
PGPIORef outRef)
{
PGPLineEndIORef convertIO = NULL;
PGPError err = kPGPError_NoErr;
ConvertLineEndType toType;
/* wrap a PGPLineEndIO around the given IO */
#if PGP_UNIX
toType = kLFLineEndType;
#elif PGP_WIN32
toType = kCRLFLineEndType;
#else
#error unknown platform
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -