bool MP3_CheckFormat ( XMP_FileFormat format,
                       XMP_StringPtr  filePath,
                       XMP_IO*    file,
                       XMPFiles *     parent )
{
    IgnoreParam(filePath);
    IgnoreParam(parent);	//supress warnings
    XMP_Assert ( format == kXMP_MP3File );		//standard assert

    if ( file->Length() < 10 ) return false;
    file ->Rewind();

    XMP_Uns8 header[3];
    file->ReadAll ( header, 3 );
    if ( ! CheckBytes( &header[0], "ID3", 3 ) ) return (parent->format == kXMP_MP3File);

    XMP_Uns8 major = XIO::ReadUns8( file );
    XMP_Uns8 minor = XIO::ReadUns8( file );

    if ( (major < 2) || (major > 4) || (minor == 0xFF) ) return false;

    XMP_Uns8 flags = XIO::ReadUns8 ( file );

    //TODO
    if ( flags & 0x10 ) XMP_Throw ( "no support for MP3 with footer", kXMPErr_Unimplemented );
    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 = XIO::ReadUns32_BE ( file );
    if ( (size & 0x80808080) != 0 ) return false; //if any bit survives -> not a valid synchsafe 32 bit integer

    return true;

}	// MP3_CheckFormat
예제 #2
0
bool ID3v2Frame::advancePastCOMMDescriptor ( XMP_Int32& pos )
{

		if ( (this->contentSize - pos) <= 3 ) return false; // silent error, no room left behing language tag
		if ( ! CheckBytes ( &this->content[pos], "eng", 3 ) ) return false; // not an error, but leave all non-eng tags alone...

		pos += 3; // skip lang tag
		if ( pos >= this->contentSize ) return false; // silent error

		while ( pos < this->contentSize ) {
			if ( this->content[pos++] == 0x00 ) break;
		}
		if ( (pos < this->contentSize) && (this->content[pos] == 0x00) ) pos++;

		if ( (pos == 5) && (this->contentSize == 6) && (GetUns16BE(&this->content[4]) == 0x0031) ) {
			return false;
		}

		if ( pos > 4 ) {
			std::string descriptor = std::string ( &this->content[4], pos-1 );
			if ( 0 == descriptor.substr(0,4).compare( "iTun" ) ) {	// begins with engiTun ?
				return false; // leave alone, then
			}
		}

		return true; //o.k., descriptor skipped, time for the real thing.

}	// ID3v2Frame::advancePastCOMMDescriptor
예제 #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
	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
예제 #5
0
bool GIF_CheckFormat ( XMP_FileFormat format,
					   XMP_StringPtr  filePath,
                       XMP_IO*        fileRef,
                       XMPFiles *     parent )
{
	IgnoreParam(format); IgnoreParam(filePath); IgnoreParam(parent);
	XMP_Assert ( format == kXMP_GIFFile );

	if ( fileRef->Length() < GIF_89_Header_LEN ) return false;
	XMP_Uns8 buffer[ GIF_89_Header_LEN ];

	fileRef->Rewind();
	fileRef->Read( buffer, GIF_89_Header_LEN );
	if ( !CheckBytes( buffer, GIF_89_Header_DATA, GIF_89_Header_LEN ) ) return false;

	return true;

}	// GIF_CheckFormat
예제 #6
0
bool ID3Header::read ( XMP_IO* file )
{

	XMP_Assert ( sizeof(fields) == kID3_TagHeaderSize );
	file->ReadAll ( this->fields, kID3_TagHeaderSize );

	if ( ! CheckBytes ( &this->fields[ID3Header::o_id], "ID3", 3 ) ) {
		// chuck in default contents:
		const static char defaultHeader[kID3_TagHeaderSize] = { 'I', 'D', '3', 3, 0, 0, 0, 0, 0, 0 };
		memcpy ( this->fields, defaultHeader, kID3_TagHeaderSize );
		return false; // no header found (o.k.) thus stick with new, default header constructed above
	}

	XMP_Uns8 major = this->fields[o_vMajor];
	XMP_Uns8 minor = this->fields[o_vMinor];
	XMP_Validate ( ((2 <= major) && (major <= 4)), "Invalid ID3 major version", kXMPErr_BadFileFormat );

	return true;

}
예제 #7
0
// =================================================================================================
// MP3_MetaHandler::CacheFileData
// ==============================
void MP3_MetaHandler::CacheFileData()
{
	//*** abort procedures
	this->containsXMP = false;		//assume no XMP for now

	LFA_FileRef file = this->parent->fileRef;
	XMP_PacketInfo &packetInfo = this->packetInfo;

	LFA_Rewind(file);

	hasID3Tag = id3Header.read( file );
	majorVersion = id3Header.fields[ID3Header::o_version_major];
	minorVersion = id3Header.fields[ID3Header::o_version_minor];
	hasExtHeader = (0 != ( 0x40 & id3Header.fields[ID3Header::o_flags])); //'naturally' false if no ID3Tag
	hasFooter = ( 0 != ( 0x10 & id3Header.fields[ID3Header::o_flags])); //'naturally' false if no ID3Tag

	// stored size is w/o initial header (thus adding 10)
	// + but extended header (if existing)
	// + padding + frames after unsynchronisation (?)
	// (if no ID3 tag existing, constructed default correctly sets size to 10.)
	oldTagSize = 10 + synchToInt32(GetUns32BE( &id3Header.fields[ID3Header::o_size] ));

	if (hasExtHeader)
	{
		extHeaderSize = synchToInt32( LFA_ReadInt32_BE( file));
		XMP_Uns8 extHeaderNumFlagBytes = LFA_ReadUns8( file );

		// v2.3 doesn't include the size, while v2.4 does
		if ( majorVersion < 4 ) extHeaderSize += 4; 
		XMP_Validate( extHeaderSize >= 6, "extHeader size too small", kXMPErr_BadFileFormat );

		bool ok;
		LFA_Seek(file, extHeaderSize - 6, SEEK_CUR , &ok);
		XMP_Assert(ok);
	}
	else
	{
		extHeaderSize = 0; // := there is no such header.
	}

	this->framesVector.clear(); //mac precaution
	ID3v2Frame* curFrame = 0; // reusable

	////////////////////////////////////////////////////
	// read frames
	while ( LFA_Tell(file) < oldTagSize )
	{
		curFrame = new ID3v2Frame();

		try {
			XMP_Int64 frameSize = curFrame->read( file, majorVersion );
			if (frameSize == 0) // no more frames coming => proceed to padding
			{
				delete curFrame; // ..since not becoming part of vector for latter delete.
				break;			 // not a throw. There's nothing wrong with padding.
			}
			this->containsXMP = true;
		} catch( XMP_Error e)
		{
			delete curFrame;
			XMP_Throw( e.GetErrMsg(), e.GetID()); // rethrow
		}

		// these are both pointer assignments, no (copy) construction
		// (MemLeak Note: for all things pushed, memory cleanup is taken care of in destructor.)
		this->framesVector.push_back( curFrame );

		//remember XMP-Frame, if it occurs:
		if ( CheckBytes( &curFrame->fields[ID3v2Frame::o_id], "PRIV", 4 ))
			if( curFrame->contentSize > 8 ) // to avoid adress violation on very small non-XMP PRIV frames
				if( CheckBytes( &curFrame->content[0], "XMP\0", 4 ))
				{
					// be sure that this is the first packet (all else would be illegal format)
					XMP_Validate( framesMap[ XMP_FRAME_ID] == 0, "two XMP packets in one file", kXMPErr_BadFileFormat );
					//add this to map, needed on reconciliation
					framesMap[ XMP_FRAME_ID ] = curFrame;

					this->packetInfo.length = curFrame->contentSize - 4; // content minus "XMP\0"
					this->packetInfo.offset = ( LFA_Tell(file) - this->packetInfo.length );

					this->xmpPacket.erase(); //safety
					this->xmpPacket.assign( &curFrame->content[4], curFrame->contentSize - 4 );
					this->containsXMP = true; // do this last, after all possible failure
				}

				// No space for another frame? => assume into ID3v2.4 padding.
				if ( LFA_Tell(file) + 10 >= oldTagSize )
					break;
	}

	////////////////////////////////////////////////////
	// padding
	oldPadding = oldTagSize - LFA_Tell( file );
	oldFramesSize = oldTagSize - 10 - oldPadding;

	XMP_Validate( oldPadding >= 0, "illegal oldTagSize or padding value", kXMPErr_BadFileFormat );

	for ( XMP_Int64 i = oldPadding; i > 0;)
	{
		if ( i >= 8 ) // worthwhile optimization
		{
			if ( LFA_ReadInt64_BE(file) != 0 )
				XMP_Throw ( "padding not nulled out.", kXMPErr_BadFileFormat );
			i -= 8;
			continue;
		}
		if ( LFA_ReadUns8(file) != 0)
			XMP_Throw ( "padding(2) not nulled out.", kXMPErr_BadFileFormat );
		i--;
	}

	//// read ID3v1 tag
	if ( ! this->containsXMP ) // all else has priority
	{
		this->containsXMP = id3v1Tag.read( file, &this->xmpObj );
	}

}	// MP3_MetaHandler::CacheFileData
예제 #8
0
파일: player.cpp 프로젝트: list-man/osp
HRESULT COSPServiceMgr::DoAddSourceFilter(IGraphBuilder* pGb, LPCWSTR aFile, IOSPGraphBuilderCallback* aCallback, LPVOID aPrivate)
{
    if (!aFile) return E_INVALIDARG;

    URL_COMPONENTS url;
    memset(&url, 0, sizeof(URL_COMPONENTS));
    url.dwStructSize = sizeof(URL_COMPONENTS);
    url.dwSchemeLength = 1;
    url.dwUrlPathLength = 1;
    url.dwExtraInfoLength = 1;
    if (!InternetCrackUrl(aFile, 0, 0, &url))
    {
        memset(&url, 0, sizeof(URL_COMPONENTS));
        url.dwStructSize = sizeof(URL_COMPONENTS);
        url.nScheme = INTERNET_SCHEME_FILE;

        url.lpszUrlPath = (LPWSTR)aFile;
        url.dwUrlPathLength = wcslen(aFile);
    }

    HRESULT hRes = VFW_E_UNSUPPORTED_STREAM;
    CString strScheme(url.lpszScheme, url.dwSchemeLength);
    CString strExtension = CPathW(CString(url.lpszUrlPath, url.dwUrlPathLength)).GetExtension();
    strExtension.Trim(L'.');

    if (strScheme.GetLength() > 1 && strScheme.CompareNoCase(L"file") != 0)
    {

    }
    else	//local file.
    {
        std::map<wstring, std::multimap<long, long, std::greater<long> > >::iterator itr = m_extensionSource.find((LPCTSTR)strExtension);
        if (itr != m_extensionSource.end())
        {
            std::multimap<long, long, std::greater<long> >::iterator itr2 = itr->second.begin();
            for (; itr2 != itr->second.end(); itr2++)
            {
                if (SUCCEEDED(hRes = DoAddSourceFilter(pGb, aFile, m_allFilters[itr2->second], aCallback, aPrivate)))
                {
                    return hRes;
                }
            }
        }

        HANDLE hFile = ::CreateFile(aFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
        if (INVALID_HANDLE_VALUE == hFile)
        {
            return VFW_E_NOT_FOUND;
        }

        {
            vector<SourceFilter*>::iterator itr = m_sourceFilters.begin();
            for (; itr != m_sourceFilters.end(); itr++)
            {
                if (CheckBytes(*itr, hFile))
                {
                    if (SUCCEEDED(hRes = DoAddSourceFilter(pGb, aFile, &(*itr)->filterBase, aCallback, aPrivate)))
                    {
                        CloseHandle(hFile);
                        return hRes;
                    }
                }
            }

            CloseHandle(hFile);
        }
    }

    return hRes;
}
void MP3_MetaHandler::CacheFileData()
{

    //*** abort procedures
    this->containsXMP = false;		//assume no XMP for now

    XMP_IO* file = this->parent->ioRef;
    XMP_PacketInfo &packetInfo = this->packetInfo;

    file->Rewind();

    this->hasID3Tag = this->id3Header.read( file );
    this->majorVersion = this->id3Header.fields[ID3Header::o_vMajor];
    this->minorVersion = this->id3Header.fields[ID3Header::o_vMinor];
    this->hasExtHeader = (0 != ( 0x40 & this->id3Header.fields[ID3Header::o_flags])); //'naturally' false if no ID3Tag
    this->hasFooter = ( 0 != ( 0x10 & this->id3Header.fields[ID3Header::o_flags])); //'naturally' false if no ID3Tag

    // stored size is w/o initial header (thus adding 10)
    // + but extended header (if existing)
    // + padding + frames after unsynchronisation (?)
    // (if no ID3 tag existing, constructed default correctly sets size to 10.)
    this->oldTagSize = ID3Header::kID3_TagHeaderSize + synchToInt32(GetUns32BE( &id3Header.fields[ID3Header::o_size] ));

    if ( ! hasExtHeader ) {

        this->extHeaderSize = 0; // := there is no such header.

    } else {

        this->extHeaderSize = synchToInt32( XIO::ReadInt32_BE( file));
        XMP_Uns8 extHeaderNumFlagBytes = XIO::ReadUns8( file );

        // v2.3 doesn't include the size, while v2.4 does
        if ( this->majorVersion < 4 ) this->extHeaderSize += 4;
        XMP_Validate( this->extHeaderSize >= 6, "extHeader size too small", kXMPErr_BadFileFormat );

        file->Seek ( this->extHeaderSize - 6, kXMP_SeekFromCurrent );

    }

    this->framesVector.clear(); //mac precaution
    ID3v2Frame* curFrame = 0; // reusable

    ////////////////////////////////////////////////////
    // read frames

    XMP_Uns32 xmpID = XMP_V23_ID;
    if ( this->majorVersion == 2 ) xmpID = XMP_V22_ID;

    while ( file->Offset() < this->oldTagSize ) {

        curFrame = new ID3v2Frame();

        try {
            XMP_Int64 frameSize = curFrame->read ( file, this->majorVersion );
            if ( frameSize == 0 ) {
                delete curFrame; // ..since not becoming part of vector for latter delete.
                break;			 // not a throw. There's nothing wrong with padding.
            }
            this->containsXMP = true;
        } catch ( ... ) {
            delete curFrame;
            throw;
        }

        // these are both pointer assignments, no (copy) construction
        // (MemLeak Note: for all things pushed, memory cleanup is taken care of in destructor.)
        this->framesVector.push_back ( curFrame );

        //remember XMP-Frame, if it occurs:
        if ( (curFrame->id ==xmpID) &&
                (curFrame->contentSize > 8) && CheckBytes ( &curFrame->content[0], "XMP\0", 4 ) ) {

            // be sure that this is the first packet (all else would be illegal format)
            XMP_Validate ( this->framesMap[xmpID] == 0, "two XMP packets in one file", kXMPErr_BadFileFormat );
            //add this to map, needed on reconciliation
            this->framesMap[xmpID] = curFrame;

            this->packetInfo.length = curFrame->contentSize - 4; // content minus "XMP\0"
            this->packetInfo.offset = ( file->Offset() - this->packetInfo.length );

            this->xmpPacket.erase(); //safety
            this->xmpPacket.assign( &curFrame->content[4], curFrame->contentSize - 4 );
            this->containsXMP = true; // do this last, after all possible failure

        }

        // No space for another frame? => assume into ID3v2.4 padding.
        XMP_Int64 newPos = file->Offset();
        XMP_Int64 spaceLeft = this->oldTagSize - newPos;	// Depends on first check below!
        if ( (newPos > this->oldTagSize) || (spaceLeft < (XMP_Int64)ID3Header::kID3_TagHeaderSize) ) break;

    }

    ////////////////////////////////////////////////////
    // padding

    this->oldPadding = this->oldTagSize - file->Offset();
    this->oldFramesSize = this->oldTagSize - ID3Header::kID3_TagHeaderSize - this->oldPadding;

    XMP_Validate ( (this->oldPadding >= 0), "illegal oldTagSize or padding value", kXMPErr_BadFileFormat );

    for ( XMP_Int64 i = this->oldPadding; i > 0; ) {
        if ( i >= 8 ) {
            if ( XIO::ReadInt64_BE(file) != 0 ) XMP_Throw ( "padding not nulled out", kXMPErr_BadFileFormat );
            i -= 8;
            continue;
        }
        if ( XIO::ReadUns8(file) != 0) XMP_Throw ( "padding(2) not nulled out", kXMPErr_BadFileFormat );
        i--;
    }

    //// read ID3v1 tag
    if ( ! this->containsXMP ) this->containsXMP = id3v1Tag.read ( file, &this->xmpObj );

}	// MP3_MetaHandler::CacheFileData