Пример #1
0
void LFA_Move ( LFA_FileRef srcFile, XMP_Int64 srcOffset,
				LFA_FileRef dstFile, XMP_Int64 dstOffset,
				XMP_Int64 length, XMP_AbortProc abortProc /* = 0 */, void * abortArg /* = 0 */ )
{
	enum { kBufferLen = 64*1024 };
	XMP_Uns8 buffer [kBufferLen];

	const bool checkAbort = (abortProc != 0);

	if ( srcOffset > dstOffset ) {	// avoiding shadow effects

	// move down -> shift lowest packet first !

		while ( length > 0 ) {

			if ( checkAbort && abortProc(abortArg) ) LFA_Throw ( "LFA_Move - User abort", kLFAErr_UserAbort );
			XMP_Int32 ioCount = kBufferLen;
			if ( length < kBufferLen ) ioCount = (XMP_Int32)length; //smartly avoids 32/64 bit issues

			LFA_Seek ( srcFile, srcOffset, SEEK_SET );
			LFA_Read ( srcFile, buffer, ioCount, kLFA_RequireAll );
			LFA_Seek ( dstFile, dstOffset, SEEK_SET );
			LFA_Write ( dstFile, buffer, ioCount );
			length -= ioCount;

			srcOffset += ioCount;
			dstOffset += ioCount;

		}

	} else {	// move up -> shift highest packet first

		srcOffset += length; //move to end
		dstOffset += length;

		while ( length > 0 ) {

			if ( checkAbort && abortProc(abortArg) ) LFA_Throw ( "LFA_Move - User abort", kLFAErr_UserAbort );
			XMP_Int32 ioCount = kBufferLen;
			if ( length < kBufferLen ) ioCount = (XMP_Int32)length; //smartly avoids 32/64 bit issues

			srcOffset -= ioCount;
			dstOffset -= ioCount;

			LFA_Seek ( srcFile, srcOffset, SEEK_SET );
			LFA_Read ( srcFile, buffer, ioCount, kLFA_RequireAll );
			LFA_Seek ( dstFile, dstOffset, SEEK_SET );
			LFA_Write ( dstFile, buffer, ioCount );
			length -= ioCount;

		}

	}

}	// LFA_Move
Пример #2
0
XMP_Uns64 TagTree::digest64u(LFA_FileRef file,const std::string key /* ="" */, bool BigEndian /*=false*/,bool hexDisplay /*=false*/ )
{
	XMP_Uns64 r;
	if (8 != LFA_Read ( file, &r, 8, false)) // require all == false => leave the throwing to this routine
		Log::error("could not read 8-byte value from file (end of file?)");
	if ( ((kBigEndianHost==1) &&  !BigEndian ) ||  ((kBigEndianHost==0) && BigEndian ))  // "XOR"
		Flip8(&r);
	if (!key.empty()) {
		char out[25]; //largets 64 bit no: 18446744073709551616 -1 (20 digits)
		if (!hexDisplay)
		{
			//not working, 0x1244e7780 ==> 609122176 decimal (== 0x244e7780)
			#if WIN_ENV
				snprintf(out , 24 , "%I64u" , r);
			#else 
				// MAC, UNIX
				snprintf(out , 24 , "%llu" , r);
			#endif
		}
		else
		{	
			//not working, upper 32 bit empty:  			
			#if WIN_ENV
				snprintf( out , 24 , "0x%.16I64X" , r );
			#else
				snprintf( out , 24 , "0x%.16llX" , r );
			#endif
		}
		setKeyValue(key,out);
	}
	return r;
}
Пример #3
0
// =================================================================================================
// MP3_CheckFormat
// ===============
// For MP3 we check parts .... See the MP3 spec for offset info.
bool MP3_CheckFormat ( XMP_FileFormat format,
					  XMP_StringPtr  filePath,
					  LFA_FileRef    file,
					  XMPFiles *     parent )
{
	IgnoreParam(filePath); IgnoreParam(parent);	//supress warnings
	XMP_Assert ( format == kXMP_MP3File );		//standard assert
	LFA_Rewind( file );

	XMP_Uns8 header[3];
	LFA_Read( file, header, 3, true );
	if ( !CheckBytes( &header[0], "ID3", 3 ))
		return (parent->format == kXMP_MP3File);	// No ID3 signature -> depend on first call hint.	

	XMP_Uns8 major = LFA_ReadUns8( file );
	XMP_Uns8 minor = LFA_ReadUns8( file );

	if ( (major<3 || major>4) || (minor == 0xFF) )
		return false;	// only support IDv2.3 and ID3v2.4, minor must not be 0xFF

	XMP_Uns8 flags = LFA_ReadUns8( file );

	//TODO
	if ( flags & 0x10 ) 
		XMP_Throw("no support for MP3 with footer",kXMPErr_Unimplemented); //no support for MP3 with footer
	if ( flags & 0x80 )
		return false; //no support for unsynchronized MP3 (as before, also see [1219125])
	if ( flags & 0x0F ) 
		XMP_Throw("illegal header lower bits",kXMPErr_Unimplemented);

	XMP_Uns32 size = LFA_ReadUns32_BE( file );
	if ( size & 0x80808080 ) return false; //if any bit survives -> not a valid synchsafe 32 bit integer

	return true;
}	// MP3_CheckFormat
Пример #4
0
	static bool ReadChunk ( LFA_FileRef inFileRef, UInt64 & pos, UInt32 len, char * outBuffer )
	{
	
		if ( (inFileRef == 0) || (outBuffer == 0) ) return false;
	
		LFA_Seek (inFileRef, pos, SEEK_SET );
		UInt32 bytesRead = LFA_Read ( inFileRef, outBuffer, len );
		if ( bytesRead != len ) return false;
	
		return true;
	
	}
Пример #5
0
	bool ReadBuffer ( LFA_FileRef fileRef, XMP_Uns64& pos, XMP_Uns32 len, XMP_Uns8* outBuffer )
	{

		try {
			if ( (fileRef == 0) || (outBuffer == 0) ) return false;
			LFA_Seek ( fileRef, pos, SEEK_SET );
			long bytesRead = LFA_Read ( fileRef, outBuffer, len );
			return ( (XMP_Uns32)bytesRead == len );
		} catch ( ... ) {}

		return false;

	}	// ReadBuffer
Пример #6
0
XMP_Int16 TagTree::digest16s(LFA_FileRef file,const std::string key /* ="" */ , bool BigEndian /*=false*/ )
{
	XMP_Int16 r;
	if (2 != LFA_Read ( file, &r, 2, false)) // require all == false => leave the throwing to this routine
		Log::error("could not read 2-byte value from file (end of file?)");
	if ( ((kBigEndianHost==1) &&  !BigEndian ) ||  ((kBigEndianHost==0) && BigEndian ))  // "XOR"
		Flip2(&r);
	if (!key.empty()) {
		char out[10]; //longest signed int is "�768", 6 chars 	
		snprintf(out,9,"%d",r);
		setKeyValue(key,out);
	}
	return r;
}
Пример #7
0
XMP_Int32 TagTree::digest32s(LFA_FileRef file,const std::string key /* ="" */ , bool BigEndian /*=false*/ )
{
	XMP_Int32 r;
	if (4 != LFA_Read ( file, &r, 4, false)) // require all == false => leave the throwing to this routine
		Log::error("could not read 4-byte value from file (end of file?)");
	if ( ((kBigEndianHost==1) &&  !BigEndian ) ||  ((kBigEndianHost==0) && BigEndian ))  // "XOR"
		Flip4(&r);
	if (!key.empty()) {
		char out[15]; //longest signed int is "�47483648", 11 chars 	
		snprintf(out,14,"%d",r); //signed, mind the trailing \0 on Mac btw
		setKeyValue(key,out);
	}
	return r;
}
Пример #8
0
////////////////////////////////////////////////////////////////////////////////////
// numeric digest routines
//
XMP_Int64 TagTree::digest64s(LFA_FileRef file,const std::string key /* ="" */ , bool BigEndian /*=false*/ )
{
	XMP_Int64 r;
	if (8 != LFA_Read ( file, &r, 8, false)) // require all == false => leave the throwing to this routine
		Log::error("could not read 8-byte value from file (end of file?)");
	if ( ((kBigEndianHost==1) &&  !BigEndian ) ||  ((kBigEndianHost==0) && BigEndian ))  // "XOR"
		Flip8(&r);

	if (!key.empty()) {
		char out[25]; //longest is "18446744073709551615", 21 chars ==> 25
		snprintf(out,24,"%lld",r); //signed, mind the trailing \0 on Mac btw
		setKeyValue(key,out);
	}
	return r;
}
Пример #9
0
XMP_Uns16 TagTree::digest16u(LFA_FileRef file,const std::string key /* ="" */, bool BigEndian /*=false*/,bool hexDisplay /*=false*/ )
{
	XMP_Uns16 r;
	if (2 != LFA_Read ( file, &r, 2, false)) // require all == false => leave the throwing to this routine
		Log::error("could not read 2-byte value from file (end of file?)");
	if ( ((kBigEndianHost==1) &&  !BigEndian ) ||  ((kBigEndianHost==0) && BigEndian ))  // "XOR"
		Flip2(&r);
	if (!key.empty()) {
		char out[15]; //longest unsigned int is "65536", 5 chars resp.  0xFFFF = 6 chars
		if (!hexDisplay)
			snprintf(out,14,"%u",r);
		else
			snprintf(out,14,"0x%.4X",r);
		setKeyValue(key,out);
	}
	return r;
}
Пример #10
0
XMP_Uns32 TagTree::digest32u(LFA_FileRef file,const std::string key /* ="" */, bool BigEndian /*=false*/,bool hexDisplay /*=false*/ )
{
	XMP_Uns32 r;
	if (4 != LFA_Read ( file, &r, 4, false)) // require all == false => leave the throwing to this routine
		Log::error("could not read 4-byte value from file (end of file?)");
	if ( ((kBigEndianHost==1) &&  !BigEndian ) ||  ((kBigEndianHost==0) && BigEndian ))  // "XOR"
		Flip4(&r);
	if (!key.empty()) {
		char out[19]; //longest unsigned int is "2147483648", 10 chars resp. 0xFFFFFFFF 10 chars
		if (!hexDisplay)
			snprintf(out,18,"%u",r); //unsigned, mind the trailing \0 on Mac btw
		else
			snprintf(out,18,"0x%.8X",r); //unsigned, mind the trailing \0 on Mac btw
		setKeyValue(key,out);
	}
	return r;
}
Пример #11
0
void TagTree::digest(LFA_FileRef file,const std::string key /*=NULL*/,
					   void* returnValue /*=""*/,
					   XMP_Int32 numOfBytes /*=0*/ )
{
	if (numOfBytes==0) {
		//0-byte requests *are* legitimate, reducing codeforks for the caller
		if ( !key.empty() )
			setKeyValue(key,"(0 bytes)");
		return;
	}

	//do we need own space or will it be provided?
	char* value;
	if (returnValue)
		value=(char*)returnValue;
	else
		value=new char[numOfBytes+1];

										// require all == false => leave the throwing to this routine
	if (numOfBytes != LFA_Read ( file, value, numOfBytes, false))	// saying 1,4 guarantes read as ordered (4,1 would not)
		Log::error("could not read %d number of files (End of File reached?)",numOfBytes);
#if !IOS_ENV
	char* out=new char[2 + numOfBytes*3 + 5]; //'0x12 34 45 78 '   length formula: 2 ("0x") + numOfBytes x 3 + 5 (padding)
	if (!key.empty()) {
		snprintf(out,3,"0x");
		XMP_Int64 i; // *)
		for (i=0; i < numOfBytes; i++)
			snprintf(&out[2+i*3],4,"%.2X ",value[i]); //always must allow that extra 0-byte on mac (overwritten again and again)
		snprintf(&out[2+i*3],1,"%c",'\0'); // *) using i one more time (needed while bug 1613297 regarding snprintf not fixed)
		setKeyValue(key,out);
	}
#else
    char* out=new char[2 + numOfBytes*9 + 5]; //'0x12 34 45 78 '   length formula: 2 ("0x") + numOfBytes x 3 + 5 (padding)
	if (!key.empty()) {
		snprintf(out,3,"0x");
		XMP_Int64 i; // *)
		for (i=0; i < numOfBytes; i++)
			snprintf(&out[2+i*9],10,"%.8X ",value[i]); //always must allow that extra 0-byte on mac (overwritten again and again)
		snprintf(&out[2+i*9],1,"%c",'\0'); // *) using i one more time (needed while bug 1613297 regarding snprintf not fixed)
		setKeyValue(key,out);
	}

#endif
    delete [] out;
	if (!returnValue) delete [] value; //if we own it, we delete it
}
Пример #12
0
	void FileInfo::CheckFormat ( LFA_FileRef fileRef )
	{
		IOBuffer ioBuf;
	
		LFA_Seek ( fileRef, 0, SEEK_SET );

		if ( CheckFileSpace ( fileRef, &ioBuf, SWF_SIGNATURE_LEN ) ) {

			if ( CheckBytes ( ioBuf.ptr, SWF_F_SIGNATURE_DATA, SWF_SIGNATURE_LEN ) ) {
				this->compressedFile = false;
			} else if ( CheckBytes ( ioBuf.ptr, SWF_C_SIGNATURE_DATA, SWF_SIGNATURE_LEN ) ) {
				this->compressedFile = true;
			}

			LFA_Seek ( fileRef, 4, SEEK_SET );
			XMP_Uns8 buffer[4];
			LFA_Read ( fileRef, buffer, 4 );
			iSize = GetUns32LE ( buffer );

		}

		LFA_Seek ( fileRef, 0, SEEK_SET );

	}	// FileInfo::CheckFormat
Пример #13
0
/* note! function does not rewind (LFA_Seek)) */
void LFA_Copy ( LFA_FileRef sourceFile, LFA_FileRef destFile, XMP_Int64 length,
                XMP_AbortProc abortProc /* = 0 */, void * abortArg /* = 0 */ )
{
	enum { kBufferLen = 64*1024 };
	XMP_Uns8 buffer [kBufferLen];

	const bool checkAbort = (abortProc != 0);

	while ( length > 0 ) {

		if ( checkAbort && abortProc(abortArg) ) {
			LFA_Throw ( "LFA_Copy - User abort", kLFAErr_UserAbort );
		}

		XMP_Int32 ioCount = kBufferLen;
		if ( length < kBufferLen ) ioCount = (XMP_Int32)length;

		LFA_Read ( sourceFile, buffer, ioCount, kLFA_RequireAll );
		LFA_Write ( destFile, buffer, ioCount );
		length -= ioCount;

	}

}	// LFA_Copy
Пример #14
0
	int FileInfo::Inf ( LFA_FileRef source, LFA_FileRef dest )
	{
		int ret;
		unsigned have;
		z_stream strm;
		unsigned char in[CHUNK];
		unsigned char out[CHUNK];

		XMP_Uns64 allBytes = 0;

		// allocate inflate state 
		strm.zalloc = Z_NULL;
		strm.zfree = Z_NULL;
		strm.opaque = Z_NULL;
		strm.avail_in = 0;
		strm.next_in = Z_NULL;

		ret = inflateInit ( &strm );

		if ( ret != Z_OK ) return ret;

		// decompress until deflate stream ends or end of file 

		LFA_Seek ( source, SWF_COMPRESSION_BEGIN, SEEK_SET );
		XMP_Uns64 outPos = SWF_COMPRESSION_BEGIN;

		try {

			do { 

				strm.avail_in = LFA_Read ( source, in, CHUNK );
				if ( strm.avail_in == 0 ) {
					ret = Z_STREAM_END;
					break;
				}

				strm.next_in = in;

				// run inflate() on input until output buffer not full 
				do {

					strm.avail_out = CHUNK; 
					strm.next_out = out;
					ret = inflate ( &strm, Z_NO_FLUSH );
					XMP_Assert ( ret != Z_STREAM_ERROR );  // state not clobbered 

					switch ( ret ) {
						case Z_NEED_DICT:	ret = Z_DATA_ERROR;	// and fall through 
						case Z_DATA_ERROR:
						case Z_MEM_ERROR:	inflateEnd ( &strm );
											return ret;
					}

					have = CHUNK - strm.avail_out;
					LFA_Seek ( dest, outPos, SEEK_SET );
					LFA_Write ( dest, out, have );
					
					outPos += have;
					
				} while ( strm.avail_out == 0 );

				// done when inflate() says it's done 

			} while ( ret != Z_STREAM_END );

		} catch ( ... ) {

			inflateEnd ( &strm );
			return Z_ERRNO;

		}

		// clean up and return 
		inflateEnd ( &strm );
		return ( (ret == Z_STREAM_END) ? Z_OK : Z_DATA_ERROR );

	}	// FileInfo::Inf
Пример #15
0
void PSIR_FileWriter::ParseFileResources ( LFA_FileRef fileRef, XMP_Uns32 length )
{
	bool ok;

	this->DeleteExistingInfo();
	this->fileParsed = true;
	if ( length == 0 ) return;

	// Parse the image resource block.

	IOBuffer ioBuf;
	ioBuf.filePos = LFA_Seek ( fileRef, 0, SEEK_CUR );

	XMP_Int64 psirOrigin = ioBuf.filePos;	// Need this to determine the resource data offsets.
	XMP_Int64 fileEnd = ioBuf.filePos + length;

	std::string rsrcPName;

	while ( (ioBuf.filePos + (ioBuf.ptr - ioBuf.data)) < fileEnd ) {

		ok = CheckFileSpace ( fileRef, &ioBuf, 12 );	// The minimal image resource takes 12 bytes.
		if ( ! ok ) break;	// Bad image resource. Throw instead?

		XMP_Int64 thisRsrcPos = ioBuf.filePos + (ioBuf.ptr - ioBuf.data);

		XMP_Uns32 type = GetUns32BE(ioBuf.ptr);
		XMP_Uns16 id   = GetUns16BE(ioBuf.ptr+4);
		ioBuf.ptr += 6;	// Advance to the resource name.

		XMP_Uns16 nameLen = ioBuf.ptr[0];	// ! The length for the Pascal string.
		XMP_Uns16 paddedLen = (nameLen + 2) & 0xFFFE;	// ! Round up to an even total. Yes, +2!
		ok = CheckFileSpace ( fileRef, &ioBuf, paddedLen+4 );	// Get the name text and the data length.
		if ( ! ok ) break;	// Bad image resource. Throw instead?

		if ( nameLen > 0 ) rsrcPName.assign ( (char*)(ioBuf.ptr), paddedLen );	// ! Include the length byte and pad.

		ioBuf.ptr += paddedLen;	// Move to the data length.
		XMP_Uns32 dataLen   = GetUns32BE(ioBuf.ptr);
		XMP_Uns32 dataTotal = ((dataLen + 1) & 0xFFFFFFFEUL);	// Round up to an even total.
		ioBuf.ptr += 4;	// Advance to the resource data.

		XMP_Int64 thisDataPos = ioBuf.filePos + (ioBuf.ptr - ioBuf.data);
		XMP_Int64 nextRsrcPos = thisDataPos + dataTotal;

		if ( type != k8BIM ) {
			XMP_Uns32 fullRsrcLen = (XMP_Uns32) (nextRsrcPos - thisRsrcPos);
			this->otherRsrcs.push_back ( OtherRsrcInfo ( (XMP_Uns32)thisRsrcPos, fullRsrcLen ) );
			MoveToOffset ( fileRef, nextRsrcPos, &ioBuf );
			continue;
		}

		InternalRsrcMap::value_type mapValue ( id, InternalRsrcInfo ( id, dataLen, kIsFileBased ) );
		InternalRsrcMap::iterator newRsrc = this->imgRsrcs.insert ( this->imgRsrcs.end(), mapValue );
		InternalRsrcInfo* rsrcPtr = &newRsrc->second;

		rsrcPtr->origOffset = (XMP_Uns32)thisDataPos;

		if ( nameLen > 0 ) {
			rsrcPtr->rsrcName = (XMP_Uns8*) malloc ( paddedLen );
			if ( rsrcPtr->rsrcName == 0 ) XMP_Throw ( "Out of memory", kXMPErr_NoMemory );
			memcpy ( (void*)rsrcPtr->rsrcName, rsrcPName.c_str(), paddedLen );	// AUDIT: Safe, allocated enough bytes above.
		}

		if ( ! IsMetadataImgRsrc ( id ) ) {
			MoveToOffset ( fileRef, nextRsrcPos, &ioBuf );
			continue;
		}

		rsrcPtr->dataPtr = malloc ( dataLen );	// ! Allocate after the IsMetadataImgRsrc check.
		if ( rsrcPtr->dataPtr == 0 ) XMP_Throw ( "Out of memory", kXMPErr_NoMemory );

		if ( dataTotal <= kIOBufferSize ) {
			// The image resource data fits within the I/O buffer.
			ok = CheckFileSpace ( fileRef, &ioBuf, dataTotal );
			if ( ! ok ) break;	// Bad image resource. Throw instead?
			memcpy ( (void*)rsrcPtr->dataPtr, ioBuf.ptr, dataLen );	// AUDIT: Safe, malloc'ed dataLen bytes above.
			ioBuf.ptr += dataTotal;	// ! Add the rounded length.
		} else {
			// The image resource data is bigger than the I/O buffer.
			LFA_Seek ( fileRef, (ioBuf.filePos + (ioBuf.ptr - ioBuf.data)), SEEK_SET );
			LFA_Read ( fileRef, (void*)rsrcPtr->dataPtr, dataLen );
			FillBuffer ( fileRef, nextRsrcPos, &ioBuf );
		}

	}

	#if 0
	{
		printf ( "\nPSIR_FileWriter::ParseFileResources, count = %d\n", this->imgRsrcs.size() );
		InternalRsrcMap::iterator irPos = this->imgRsrcs.begin();
		InternalRsrcMap::iterator irEnd = this->imgRsrcs.end();
		for ( ; irPos != irEnd; ++irPos ) {
			InternalRsrcInfo& thisRsrc = irPos->second;
			printf ( "  #%d, dataLen %d, origOffset %d (0x%X)%s\n",
					 thisRsrc.id, thisRsrc.dataLen, thisRsrc.origOffset, thisRsrc.origOffset,
					 (thisRsrc.changed ? ", changed" : "") );
		}
	}
	#endif

}	// PSIR_FileWriter::ParseFileResources
Пример #16
0
	int FileInfo::Def ( LFA_FileRef source, LFA_FileRef dest )
	{
		int ret, flush;
		unsigned have;
		z_stream strm;
		unsigned char in[CHUNK];
		unsigned char out[CHUNK];

		// allocate deflate state
		strm.zalloc = Z_NULL;
		strm.zfree = Z_NULL;
		strm.opaque = Z_NULL;
		ret = deflateInit ( &strm, SWF_DEFAULT_COMPRESSION_LEVEL );
		if ( ret != Z_OK ) return ret;

		// compress until end of file

		LFA_Seek ( source, SWF_COMPRESSION_BEGIN, SEEK_SET );
		XMP_Uns64 outPos = SWF_COMPRESSION_BEGIN;

		try {

			do {

				strm.avail_in = LFA_Read ( source, in, CHUNK );

				flush = ( (strm.avail_in < CHUNK) ? Z_FINISH : Z_NO_FLUSH );
				
				strm.next_in = in;

				// run deflate() on input until output buffer not full, finish
				// compression if all of source has been read in
				do {

					strm.avail_out = CHUNK;
					strm.next_out = out;
					ret = deflate ( &strm, flush );    // no bad return value
					XMP_Assert ( ret != Z_STREAM_ERROR );  // state not clobbered
					have = CHUNK - strm.avail_out;
					
					LFA_Seek ( dest, outPos, SEEK_SET );
					LFA_Write ( dest, out, have );
					outPos += have;

				} while ( strm.avail_out == 0 );
				XMP_Assert ( strm.avail_in == 0 );	// all input will be used

				// done when last data in file processed

			} while ( flush != Z_FINISH );
			XMP_Assert ( ret == Z_STREAM_END );	// stream will be complete

		} catch ( ... ) {

			deflateEnd ( &strm );
			return Z_ERRNO;

		}
		
		/* clean up and return */
		deflateEnd ( &strm );
		return Z_OK;

	}	// FileInfo::Def
Пример #17
0
	static bool  ReadTag ( LFA_FileRef inFileRef, long * outTag, UInt32 * outLength, long * subtype, UInt64 & inOutPosition, UInt64 maxOffset )
	{
		UInt32	realLength;
	
		long bytesRead;
		bytesRead = LFA_Read ( inFileRef, outTag, 4 );
		if ( bytesRead != 4 ) return false;
		*outTag = GetUns32LE ( outTag );
		
		bytesRead = LFA_Read ( inFileRef, outLength, 4 );
		if ( bytesRead != 4 ) return false;
		*outLength = GetUns32LE ( outLength );

		realLength = *outLength;
		realLength += (realLength & 1);		// Round up to an even value.

		inOutPosition = GetFilePosition ( inFileRef );	// The file offset of the data portion.
		UInt64 maxLength = maxOffset - inOutPosition;

		if ( (inOutPosition > maxOffset) || ((UInt64)(*outLength) > maxLength) ) {

			bool ignoreLastPad = true;	// Ignore cases where a final pad byte is missing.
			UInt64 fileLen = LFA_Measure ( inFileRef );
			if ( inOutPosition > (maxOffset + 1) ) ignoreLastPad = false;
			if ( (UInt64)(*outLength) > (maxLength + 1) ) ignoreLastPad = false;

			if ( ! ignoreLastPad ) {

				// Workaround for bad files in the field that have a bad size in the outermost RIFF
				// chunk. Do a "runtime repair" of cases where the length is too long (beyond EOF).
				// This handles read-only usage, update usage is repaired (or not) in the handler.

				bool oversizeRIFF = (inOutPosition == 8) &&	// Is this the initial 'RIFF' chunk?
									(fileLen >= 8);			// Is the file at least of the minimal size?
								 
				if ( ! oversizeRIFF ) {
					XMP_Throw ( "RIFF tag exceeds maximum length", kXMPErr_BadValue );
				} else {
					*outLength = (UInt32)(fileLen) - 8;
					realLength = *outLength;
					realLength += (realLength & 1);		// Round up to an even value.
				}

			}

		}
		
		*subtype = 0;

		if ( (*outTag != FOURCC_LIST) && (*outTag != FOURCC_RIFF) ) {

			UInt64 tempPos = inOutPosition + realLength;
			if ( tempPos <= maxOffset ) {
				LFA_Seek ( inFileRef, tempPos, SEEK_SET );
			} else if ( (tempPos == (maxOffset + 1)) && (maxOffset == (UInt64)LFA_Measure(inFileRef)) ) {
				LFA_Seek ( inFileRef, 0, SEEK_END );	// Hack to tolerate a missing final pad byte.
			} else {
				XMP_Throw ( "Bad RIFF offset", kXMPErr_BadValue );
			}

		} else  {

			bytesRead = LFA_Read ( inFileRef, subtype, 4 );
			if ( bytesRead != 4 ) return false;
			*subtype = GetUns32LE ( subtype );

			*outLength -= 4;
			realLength -= 4;

			// Special case:
			// Since the 'movi' chunk can contain billions of subchunks, skip over the 'movi' subchunk.
			//
			// The 'movi' subtype is added to the list as the TAG.
			// The subtype is returned empty so nobody will try to parse the subchunks.

			if ( *subtype == listtypeAVIMOVIE ) {
				inOutPosition = GetFilePosition ( inFileRef );
				UInt64 tempPos = inOutPosition + realLength;
				if ( tempPos <= maxOffset ) {
					LFA_Seek ( inFileRef, tempPos, SEEK_SET );
				} else if ( (tempPos == (maxOffset + 1)) && (maxOffset == (UInt64)LFA_Measure(inFileRef)) ) {
					LFA_Seek ( inFileRef, 0, SEEK_END );	// Hack to tolerate a missing final pad byte.
				} else {
					XMP_Throw ( "Bad RIFF offset", kXMPErr_BadValue );
				}
				*outLength += 4;
				*outTag = *subtype;
				*subtype = 0;
			}

			inOutPosition = GetFilePosition ( inFileRef );

		}
	
		return true;

	}
Пример #18
0
// TOTEST
char LFA_GetChar( LFA_FileRef file )
{
	XMP_Uns8 c;
	LFA_Read( file, &c, 1, true);
	return c;
}