diff --git a/taglib/mpeg/id3v2/id3v2frame.cpp b/taglib/mpeg/id3v2/id3v2frame.cpp index c743cafd..49e57b96 100644 --- a/taglib/mpeg/id3v2/id3v2frame.cpp +++ b/taglib/mpeg/id3v2/id3v2frame.cpp @@ -54,6 +54,19 @@ public: Frame::Header *header; }; +bool isValidFrameID(const ByteVector &frameID) +{ + if(frameID.size() != 4) { + return false; + } + for(ByteVector::ConstIterator it = frameID.begin(); it != frameID.end(); it++) { + if( (*it < 'A' || *it > 'Z') && (*it < '1' || *it > '9') ) { + return false; + } + } + return true; +} + //////////////////////////////////////////////////////////////////////////////// // static methods //////////////////////////////////////////////////////////////////////////////// @@ -394,6 +407,17 @@ void Frame::Header::setData(const ByteVector &data, uint version) // the frame header (structure 4) d->frameSize = SynchData::toUInt(data.mid(4, 4)); +#ifndef NO_ITUNES_HACKS + // iTunes writes v2.4 tags with v2.3-like frame sizes + if(d->frameSize > 127) { + if(!isValidFrameID(data.mid(d->frameSize + 10, 4))) { + unsigned int uintSize = data.mid(4, 4).toUInt(); + if(isValidFrameID(data.mid(uintSize + 10, 4))) { + d->frameSize = uintSize; + } + } + } +#endif { // read the first byte of flags std::bitset<8> flags(data[8]); diff --git a/tests/data/005411.id3 b/tests/data/005411.id3 new file mode 100644 index 00000000..ab2e0997 Binary files /dev/null and b/tests/data/005411.id3 differ diff --git a/tests/test_id3v2.cpp b/tests/test_id3v2.cpp index 0cd43546..d4566555 100644 --- a/tests/test_id3v2.cpp +++ b/tests/test_id3v2.cpp @@ -39,7 +39,7 @@ class TestID3v2 : public CppUnit::TestFixture CPPUNIT_TEST(testParseUniqueFileIdentifierFrame); CPPUNIT_TEST(testParseEmptyUniqueFileIdentifierFrame); CPPUNIT_TEST(testBrokenFrame1); - //CPPUNIT_TEST(testItunes24FrameSize); + CPPUNIT_TEST(testItunes24FrameSize); CPPUNIT_TEST(testParseUrlLinkFrame); CPPUNIT_TEST(testRenderUrlLinkFrame); CPPUNIT_TEST(testParseUserUrlLinkFrame); @@ -221,13 +221,13 @@ public: f.render()); } - /*void testItunes24FrameSize() + void testItunes24FrameSize() { MPEG::File f("data/005411.id3", false); CPPUNIT_ASSERT(f.tag()); CPPUNIT_ASSERT(f.ID3v2Tag()->frameListMap().contains("TIT2")); CPPUNIT_ASSERT_EQUAL(String("Sunshine Superman"), f.ID3v2Tag()->frameListMap()["TIT2"].front()->toString()); - }*/ + } };