Example #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
Example #2
0
	bool WriteChunk ( LFA_FileRef inFileRef, long tagID, const char * data, UInt32 len )
	{
		atag ck;
		ck.id = MakeUns32LE ( tagID );
		ck.len = MakeUns32LE ( len );
	
		try {
			LFA_Write ( inFileRef, &ck, 8 );
			LFA_Write ( inFileRef, data, len );
		} catch ( ... ) {
			return false;
		}
	
		return true;
	}
Example #3
0
	bool MarkChunkAsPadding ( LFA_FileRef inFileRef, RiffState & inOutRiffState, long riffType, long tagID, long subtypeID )
	{
		UInt32 len;
		UInt64 pos;
		atag tag;
	
		try {
	
			bool found = FindChunk ( inOutRiffState, tagID, riffType, subtypeID, NULL, &len, &pos );
			if ( ! found ) return false;
	
			if ( subtypeID != 0 ) {
				pos -= 12;
			} else {
				pos -= 8;
			}

			tag.id = MakeUns32LE ( ckidPremierePadding );
			LFA_Seek ( inFileRef, pos, SEEK_SET );
			LFA_Write ( inFileRef, &tag, 4 );
	
			pos += 8;
			AddTag ( inOutRiffState, ckidPremierePadding, len, pos, 0, 0, 0 );
	
		} catch(...) {
	
			return false;	// If a write fails, it throws, so we return false.
	
		}
	
		return true;
	}
Example #4
0
	bool WriteXMPTag ( LFA_FileRef fileRef, XMP_Uns32 len, const char* inBuffer )
	{
		bool ret = false;

		XMP_Uns16 code = MakeUns16LE ( (SWF_TAG_ID_METADATA << 6) | 0x3F );
		XMP_Uns32 length = MakeUns32LE ( len );

		try {
			LFA_Write (fileRef, &code, 2 );
			LFA_Write (fileRef, &length, 4 );
			LFA_Write (fileRef, inBuffer, len );
			ret = true;
		} catch ( ... ) {}

		return ret;

	}	// WriteXMPTag
Example #5
0
	bool PutChunk ( LFA_FileRef inFileRef, RiffState & inOutRiffState, long riffType, long tagID, const char * inBuffer, UInt32 inBufferSize )
	{
		UInt32 len;
		UInt64 pos;
		atag tag;
	
		// Make sure we're writting an even number of bytes. Required by the RIFF specification.
		XMP_Assert ( (inBufferSize & 1) == 0 );
	
		try {

			bool found = FindChunk ( inOutRiffState, tagID, 0, 0, NULL, &len, &pos );
			if ( found ) {

				if ( len == inBufferSize ) {
					LFA_Seek ( inFileRef, pos, SEEK_SET );
					LFA_Write ( inFileRef, inBuffer, inBufferSize );
					return true;
				}
	
				pos -= 8;
				tag.id = MakeUns32LE ( ckidPremierePadding );
				LFA_Seek ( inFileRef, pos, SEEK_SET );
				LFA_Write ( inFileRef, &tag, 4 );
	
				if ( len > inBufferSize ) {
					pos += 8;
					AddTag ( inOutRiffState, ckidPremierePadding, len, pos, 0, 0, 0 );
				}

			}

		} catch ( ... ) {

			// If a write fails, it throws, so we return false
			return false;

		}
	
		bool ok = MakeChunk ( inFileRef, inOutRiffState, riffType, (inBufferSize + 8) );
		if ( ! ok ) return false;
	
		return WriteChunk ( inFileRef, tagID, inBuffer, inBufferSize );
	
	}
Example #6
0
	int FileInfo::Encode ( LFA_FileRef fileRef, LFA_FileRef updateRef, SWF_MODE swfMode, CompressionFnc cmpFnc )
	{

		LFA_Seek ( updateRef, 0, SEEK_SET );
		
		if ( swfMode == CWS ) {
			LFA_Write ( updateRef, SWF_C_SIGNATURE_DATA, SWF_SIGNATURE_LEN );
		} else {
			XMP_Assert ( swfMode == FWS );
			LFA_Write ( updateRef, SWF_F_SIGNATURE_DATA, SWF_SIGNATURE_LEN );
		}

		LFA_Seek ( fileRef, SWF_SIGNATURE_LEN, SEEK_SET );
		LFA_Seek ( updateRef, SWF_SIGNATURE_LEN, SEEK_SET );
		LFA_Copy ( fileRef, updateRef, 5 );

		int ret = cmpFnc ( fileRef, updateRef );
		LFA_Flush ( updateRef );

		return ret;

	}	// FileInfo::Encode
Example #7
0
	bool WriteFileAttrFlags ( LFA_FileRef fileRef, const TagData& fileAttrTag, XMP_Uns32  flags )
	{

		try {
			XMP_Uns32 bitMask = MakeUns32LE ( flags );
			LFA_Seek ( fileRef, fileAttrTag.pos + fileAttrTag.offset, SEEK_SET );
			LFA_Write ( fileRef, &bitMask, 4 );
			return true;
		} catch ( ... ) {}

		return false;

	}	// WriteFileAttrFlags
Example #8
0
	bool WriteBuffer ( LFA_FileRef fileRef, XMP_Uns64& pos, XMP_Uns32 len, const char* inBuffer )
	{

		try {
			if ( (fileRef == 0) || (inBuffer == 0) ) return false;
			LFA_Seek ( fileRef, pos, SEEK_SET );
			LFA_Write ( fileRef, inBuffer, len );
			return true;
		}
		catch ( ... ) {}

		return false;

	}	// WriteBuffer
Example #9
0
	bool RewriteChunk ( LFA_FileRef inFileRef, RiffState & inOutRiffState, long tagID, long parentID, const char * inData )
	{
		UInt32 len;
		UInt64 pos;
	
		try {
			if ( FindChunk ( inOutRiffState, tagID, parentID, 0, NULL, &len, &pos ) ) {
				LFA_Seek ( inFileRef, pos, SEEK_SET );
				LFA_Write ( inFileRef, inData, len );
			}
		} catch ( ... ) {
			return false;
		}
	
		return true;
	
	}
Example #10
0
	bool UpdateHeader ( LFA_FileRef fileRef )
	{

		try {

			XMP_Int64 length64 = LFA_Measure ( fileRef );
			if ( (length64 < 8) || (length64 > (XMP_Int64)0xFFFFFFFFULL) ) return false;

			XMP_Uns32 length32 = MakeUns32LE ( (XMP_Uns32)length64 );

			LFA_Seek ( fileRef, 4, SEEK_SET );
			LFA_Write ( fileRef, &length32, 4 );
			
			return true;

		} catch ( ... ) {}
	
		return false;

	}	// UpdateHeader
Example #11
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
Example #12
0
XMP_Uns32 PSIR_FileWriter::UpdateFileResources ( LFA_FileRef sourceRef, LFA_FileRef destRef,
												 IOBuffer * ioBuf, XMP_AbortProc abortProc, void * abortArg )
{
	IgnoreParam(ioBuf);
	const XMP_Uns32 zero32 = 0;

	const bool checkAbort = (abortProc != 0);

	struct RsrcHeader {
		XMP_Uns32 type;
		XMP_Uns16 id;
	};
	XMP_Assert ( (offsetof(RsrcHeader,type) == 0) && (offsetof(RsrcHeader,id) == 4) );

	if ( this->memParsed ) XMP_Throw ( "Not file based", kXMPErr_EnforceFailure );

	XMP_Int64 destLenOffset = LFA_Seek ( destRef, 0, SEEK_CUR );
	XMP_Uns32 destLength = 0;

	LFA_Write ( destRef, &destLength, 4 );	// Write a placeholder for the new PSIR section length.

	#if 0
	{
		printf ( "\nPSIR_FileWriter::UpdateFileResources, 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

	// First write all of the '8BIM' resources from the map. Use the internal data if present, else
	// copy the data from the file.

	RsrcHeader outHeader;
	outHeader.type  = MakeUns32BE ( k8BIM );

	InternalRsrcMap::iterator rsrcPos = this->imgRsrcs.begin();
	InternalRsrcMap::iterator rsrcEnd = this->imgRsrcs.end();

	// printf ( "\nPSIR_FileWriter::UpdateFileResources - 8BIM resources\n" );
	for ( ; rsrcPos != rsrcEnd; ++rsrcPos ) {

		InternalRsrcInfo& currRsrc = rsrcPos->second;

		outHeader.id = MakeUns16BE ( currRsrc.id );
		LFA_Write ( destRef, &outHeader, 6 );
		destLength += 6;

		if ( currRsrc.rsrcName == 0 ) {
			LFA_Write ( destRef, &zero32, 2 );
			destLength += 2;
		} else {
			XMP_Assert ( currRsrc.rsrcName[0] != 0 );
			XMP_Uns16 nameLen = currRsrc.rsrcName[0];	// ! Include room for +1.
			XMP_Uns16 paddedLen = (nameLen + 2) & 0xFFFE;	// ! Round up to an even total. Yes, +2!
			LFA_Write ( destRef, currRsrc.rsrcName, paddedLen );
			destLength += paddedLen;
		}

		XMP_Uns32 dataLen = MakeUns32BE ( currRsrc.dataLen );
		LFA_Write ( destRef, &dataLen, 4 );
		// printf ( "  #%d, offset %d (0x%X), dataLen %d\n", currRsrc.id, destLength, destLength, currRsrc.dataLen );

		if ( currRsrc.dataPtr != 0 ) {
			LFA_Write ( destRef, currRsrc.dataPtr, currRsrc.dataLen );
		} else {
			LFA_Seek ( sourceRef, currRsrc.origOffset, SEEK_SET );
			LFA_Copy ( sourceRef, destRef, currRsrc.dataLen );
		}

		destLength += 4 + currRsrc.dataLen;

		if ( (currRsrc.dataLen & 1) != 0 ) {
			LFA_Write ( destRef, &zero32, 1 );	// ! Pad the data to an even length.
			++destLength;
		}

	}

	// Now write all of the non-8BIM resources. Copy the entire resource chunk from the source file.

	// printf ( "\nPSIR_FileWriter::UpdateFileResources - other resources\n" );
	for ( size_t i = 0; i < this->otherRsrcs.size(); ++i ) {
		// printf ( "  offset %d (0x%X), length %d",
		//		 this->otherRsrcs[i].rsrcOffset, this->otherRsrcs[i].rsrcOffset, this->otherRsrcs[i].rsrcLength );
		LFA_Seek ( sourceRef, this->otherRsrcs[i].rsrcOffset, SEEK_SET );
		LFA_Copy ( sourceRef, destRef, this->otherRsrcs[i].rsrcLength );
		destLength += this->otherRsrcs[i].rsrcLength;	// Alignment padding is already included.
	}

	// Write the final PSIR section length, seek back to the end of the file, return the length.

	// printf ( "\nPSIR_FileWriter::UpdateFileResources - final length %d (0x%X)\n", destLength, destLength );
	LFA_Seek ( destRef, destLenOffset, SEEK_SET );
	XMP_Uns32 outLen = MakeUns32BE ( destLength );
	LFA_Write ( destRef, &outLen, 4 );
	LFA_Seek ( destRef, 0, SEEK_END );

	// *** Not rebuilding the internal map - turns out we never want it, why pay for the I/O.
	// *** Should probably add an option for all of these cases, memory and file based.

	return destLength;

}	// PSIR_FileWriter::UpdateFileResources
Example #13
0
// =================================================================================================
// MP3_MetaHandler::UpdateFile
// ===========================
void MP3_MetaHandler::UpdateFile ( bool doSafeUpdate )
{
	if ( doSafeUpdate )
		XMP_Throw ( "UCF_MetaHandler::UpdateFile: Safe update not supported", kXMPErr_Unavailable );

	LFA_FileRef file ( this->parent->fileRef );

	// leave 2.3 resp. 2.4 header, since we want to let alone 
	// and don't know enough about the encoding of unrelated frames...
	XMP_Assert( this->containsXMP );

	tagIsDirty = false;
	mustShift = false;

	// write out native properties:
	// * update existing ones
	// * create new frames as needed
	// * delete frames if property is gone!
	// see what there is to do for us:

	// RECON LOOP START
	for (int r=0; reconProps[r].frameID != 0; r++)
	{
		std::string value;
		bool needDescriptor = false;
		bool need16LE = true;
		bool needEncodingByte = true;

		XMP_Uns32 frameID = GetUns32BE( reconProps[r].frameID ); // the would-be frame
		ID3v2Frame* frame = framesMap[ frameID ];	// the actual frame (if already existing)

		// get XMP property
		//	* honour specific exceptions
		//  * leave value empty() if it doesn't exist ==> frame must be delete/not created
		switch( frameID )
		{
		case 0x54434D50: // TCMP if exists: part of compilation
			need16LE = false;
			if ( xmpObj.GetProperty( kXMP_NS_DM, "partOfCompilation", &value, 0 )
				&& ( 0 == stricmp( value.c_str(), "true" ) ))
				value = "1"; // set a TCMP frame of value 1
			else
				value.erase(); // delete/prevent creation of frame
			break;

		case 0x54495432: // TIT2 -> title["x-default"]
		case 0x54434F50: // TCOP -> rights["x-default"]
			if (! xmpObj.GetLocalizedText( reconProps[r].ns, reconProps[r].prop, "", "x-default", 0, &value, 0 )) //jaja, side effect.
				value.erase(); // if not, erase string.
			break;
		case 0x54434F4E: // TCON -> genre
			{
				if (! xmpObj.GetProperty( reconProps[r].ns, reconProps[r].prop, &value, 0 ))
				{	// nothing found? -> Erase string. (Leads to Unset below)
					value.erase();
					break;
				}
				// genre: we need to get the number back, if possible
				XMP_Int16 iFound = -1; // flag as "not found"
				for ( int i=0; i < 127; ++i ) {
					if ( (value.size() == strlen(Genres[i])) 
					  && (stricmp( value.c_str(), Genres[i] ) == 0) ) //fixing stricmp buggy on PPC
						{
							iFound = i; // Found
							break;
						}
				}
				if ( iFound == -1 ) // not found known numeric genre?
					break; // stick with the literal value (also for v2.3, since this is common practice!)

				need16LE = false; // no unicode need for (##)
				char strGenre[64];
				snprintf ( strGenre, sizeof(strGenre), "(%d)", iFound );	// AUDIT: Using sizeof(strGenre) is safe.
				value.assign(strGenre);
			}
			break;
		case 0x434F4D4D: // COMM
		case 0x55534C54: // USLT, both need descriptor.
			needDescriptor = true;
			if (! xmpObj.GetProperty( reconProps[r].ns, reconProps[r].prop, &value, 0 ))
				value.erase();
			break;
		case 0x54594552: //TYER
		case 0x54444154: //TDAT	
		case 0x54494D45: //TIME			
			{
				if ( majorVersion <= 3 ) // TYER, TIME and TDAT depricated since v. 2.4 -> else use TDRC
				{
					XMP_DateTime dateTime;	
					if (! xmpObj.GetProperty_Date( reconProps[r].ns, reconProps[r].prop, &dateTime, 0 ))
					{	// nothing found? -> Erase string. (Leads to Unset below)
						value.erase();
						break;
					}

					// TYER
					if ( frameID == 0x54594552 )
					{
						XMP_Validate( dateTime.year <= 9999 && dateTime.year > 0 , "Year is out of range", kXMPErr_BadParam);
						// get only Year!
						SXMPUtils::ConvertFromInt( dateTime.year, "", &value );
						break;
					} 
					// TDAT
					else if ( frameID == 0x54444154 && dateTime.hasDate ) // date validation made by "GetProperty_Date"
					{						
						std::string day, month;
						SXMPUtils::ConvertFromInt( dateTime.day, "", &day );
						SXMPUtils::ConvertFromInt( dateTime.month, "", &month );
						if ( dateTime.day < 10 )
							value = "0";
						value += day;
						if ( dateTime.month < 10 )
							value += "0";
						value += month;
						break;
					} 
					// TIME
					else if ( frameID == 0x54494D45 && dateTime.hasTime ) // time validation made by "GetProperty_Date" )
					{
						std::string hour, minute;
						SXMPUtils::ConvertFromInt( dateTime.hour, "", &hour );
						SXMPUtils::ConvertFromInt( dateTime.minute, "", &minute );
						if ( dateTime.hour < 10 )
							value = "0";
						value += hour;
						if ( dateTime.minute < 10 )
							value += "0";
						value += minute;
						break;
					} 
					else
					{
						value.erase();
						break;
					}
				}
				else // v.2.4 --> delete TYER,TIME or TDAT & write into TDRC
				{
					value.erase();
					break;
				}
			}
		case 0x54445243: //TDRC (only v2.4)
			{
				// only export for id3 > v2.4
				if ( majorVersion > 3 ) // (only v2.4)
				{
					if (! xmpObj.GetProperty( reconProps[r].ns, reconProps[r].prop, &value, 0 ))
						value.erase();				
				}
				break;
			}
		break;
		case 0x57434F50: //WCOP
			needEncodingByte = false;
			need16LE = false;
			if (! xmpObj.GetProperty( reconProps[r].ns, reconProps[r].prop, &value, 0 ))
				value.erase(); // if not, erase string
		break;
		case 0x5452434B: // TRCK
		case 0x54504F53: // TPOS
			need16LE = false;
			// no break, go on:
		default:
			if (! xmpObj.GetProperty( reconProps[r].ns, reconProps[r].prop, &value, 0 ))
				value.erase(); // if not, erase string
			break;
		}

		// [XMP exist] x [frame exist] => four cases:
		// 1/4) nothing before, nothing now
		if ( value.empty() && (frame==0))  
			continue; // nothing to do

		// all else means there will be rewrite work to do:
		tagIsDirty = true;

		// 2/4) value before, now gone:
		if ( value.empty() && (frame!=0))
		{
			frame->active = false; //mark for non-use
			continue;
		}
		// 3/4) no old value, create new value
		if ( frame==0)
		{	
			ID3v2Frame* newFrame=new ID3v2Frame( frameID );
			newFrame->setFrameValue( value, needDescriptor,  need16LE, false, needEncodingByte ); //always write as utf16-le incl. BOM
			framesVector.push_back( newFrame );
			framesMap[ frameID ] = newFrame;
			continue;
		}
		// 4/4) change existing value
		else // resp. change frame
		{
			frame->setFrameValue( value, needDescriptor, need16LE, false, needEncodingByte );
		}
	} 	// RECON LOOP END

	/////////////////////////////////////////////////////////////////////////////////
	// (Re)Build XMP frame:
	ID3v2Frame* frame = framesMap[ XMP_FRAME_ID ];
	if ( frame == 0)
	{	
		ID3v2Frame* newFrame=new ID3v2Frame( XMP_FRAME_ID );
		newFrame->setFrameValue( this->xmpPacket, false, false, true );
		framesVector.push_back( newFrame );
		framesMap[ XMP_FRAME_ID ] = newFrame;
	} else
		frame->setFrameValue( this->xmpPacket, false, false, true );

	////////////////////////////////////////////////////////////////////////////////
	// Decision making
	newFramesSize = 0;
	for ( XMP_Uns32 i=0; i < framesVector.size(); i++)
	{
		if (framesVector[i]->active)
			newFramesSize += (10 + framesVector[i]->contentSize );
	}

	mustShift = ( newFramesSize > (oldTagSize - 10)) ||
	//optimization: If more than 8K can be saved by rewriting the MP3, go do it:
				((newFramesSize + 8*1024) < oldTagSize );

	if (!mustShift)	// fill what we got
		newTagSize = oldTagSize;
	else // if need to shift anyway, get some nice 2K padding
		newTagSize = newFramesSize + 2048 + 10;
	newPadding = newTagSize -10 - newFramesSize;

	// shifting needed? -> shift
	if ( mustShift )
	{
		XMP_Int64 filesize = LFA_Measure( file );
		if ( this->hasID3Tag )
			LFA_Move( file, oldTagSize, file, newTagSize , filesize - oldTagSize ); //fix [2338569]
		else
			LFA_Move( file, 0, file, newTagSize, filesize ); // move entire file up.
	}

	// correct size stuff, write out header
	LFA_Rewind( file );
	id3Header.write( file, newTagSize);	

	// write out tags
	for ( XMP_Uns32 i=0; i < framesVector.size(); i++)
	{
		if ( framesVector[i]->active)
			framesVector[i]->write(file, majorVersion);
	}

	// write out padding:
	for ( XMP_Int64 i = newPadding; i > 0;)
	{
		const XMP_Uns64 zero = 0;
		if ( i >= 8 ) // worthwhile optimization
		{
			LFA_Write( file, &zero, 8 );
			i -= 8;
			continue;
		}
		LFA_Write( file, &zero, 1 );
		i--;
	}

	// check end of file for ID3v1 tag
	XMP_Int64 possibleTruncationPoint = LFA_Seek( file, -128, SEEK_END);
	bool alreadyHasID3v1 = (LFA_ReadInt32_BE( file ) & 0xFFFFFF00) == 0x54414700; // "TAG"
	if ( ! alreadyHasID3v1 ) // extend file
		LFA_Extend( file, LFA_Measure( file ) + 128 );
	id3v1Tag.write( file, &this->xmpObj );

	this->needsUpdate = false; //do last for safety reasons
}	// MP3_MetaHandler::UpdateFile
Example #14
0
	bool MakeChunk ( LFA_FileRef inFileRef, RiffState & inOutRiffState, long riffType, UInt32 len )
	{
		long starttag;
		UInt32 taglen;
		UInt32 rifflen, avail;
		UInt64 pos;
	
		/* look for top level Premiere padding chunk */
		starttag = 0;
		while ( FindChunk ( inOutRiffState, ckidPremierePadding, riffType, 0, &starttag, &taglen, &pos ) ) {
	
			pos -= 8;
			taglen += 8;
			long extra = taglen - len;
			if ( extra < 0 ) continue;
	
			RiffIterator iter = inOutRiffState.tags.begin();
			iter += (starttag - 1);
	
			if ( extra == 0 ) {

				iter->len = 0;

			} else {

				atag pad;
				UInt64 padpos;
	
				/*  need 8 bytes extra to be able to split it */
				extra -= 8;
				if ( extra < 0 ) continue;
	
				try{
					padpos = pos + len;
					LFA_Seek ( inFileRef, padpos, SEEK_SET );
					pad.id = MakeUns32LE ( ckidPremierePadding );
					pad.len = MakeUns32LE ( extra );
					LFA_Write ( inFileRef, &pad, sizeof(pad) );
				} catch ( ... ) {
					return false;
				}

				iter->pos = padpos + 8;
				iter->len = extra;

			}
	
			/* seek back to start of original padding chunk */
			LFA_Seek ( inFileRef, pos, SEEK_SET );
	
			return true;

		}
	
		/* can't take padding chunk, so append new chunk to end of file */
	
		rifflen = inOutRiffState.rifflen + 8;
		avail = AVIMAXCHUNKSIZE - rifflen;
	
		LFA_Seek ( inFileRef, 0, SEEK_END );
		pos = GetFilePosition ( inFileRef );

		if ( (pos & 1) == 1 ) {
			// The file length is odd, need a pad byte.
			XMP_Uns8 pad = 0;
			LFA_Write ( inFileRef, &pad, 1 );
			++pos;
		}
	
		if ( avail < len ) {

			/* if needed, create new AVIX chunk */
			ltag avix;
	
			avix.id = MakeUns32LE ( FOURCC_RIFF );
			avix.len = MakeUns32LE ( 4 + len );
			avix.subid = MakeUns32LE ( formtypeAVIX );
			LFA_Write(inFileRef, &avix, sizeof(avix));
	
			pos += 12;
			AddTag ( inOutRiffState, avix.id, len, pos, 0, 0, 0 );

		} else {

			/* otherwise, rewrite length of last RIFF chunk in file */
			pos = inOutRiffState.riffpos + 4;
			rifflen = inOutRiffState.rifflen + len;
			XMP_Uns32 fileLen = MakeUns32LE ( rifflen );
			LFA_Seek ( inFileRef, pos, SEEK_SET );
			LFA_Write ( inFileRef, &fileLen, 4 );
			inOutRiffState.rifflen = rifflen;
	
			/* prepare to write data */
			LFA_Seek ( inFileRef, 0, SEEK_END );

		}
	
		return true;

	}
Example #15
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
Example #16
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