]> granicus.if.org Git - taglib/commitdiff
Add a hack to read ID2v2.4 frames with v2.3-like sizes, written by iTunes.
authorLukáš Lalinský <lalinsky@gmail.com>
Sat, 1 Dec 2007 09:15:23 +0000 (09:15 +0000)
committerLukáš Lalinský <lalinsky@gmail.com>
Sat, 1 Dec 2007 09:15:23 +0000 (09:15 +0000)
The code is inside a '#ifndef NO_ITUNES_HACKS' block, so I hope it's ok to add it.

git-svn-id: svn://anonsvn.kde.org/home/kde/trunk/kdesupport/taglib@743534 283d02a7-25f6-0310-bc7c-ecb5cbfe19da

taglib/mpeg/id3v2/id3v2frame.cpp
tests/data/005411.id3 [new file with mode: 0644]
tests/test_id3v2.cpp

index c743cafdef7dd4a1cc0385093c4567ae0cc4b113..49e57b9629decbfee1966b97250fe9c467ef5fdb 100644 (file)
@@ -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 (file)
index 0000000..ab2e099
Binary files /dev/null and b/tests/data/005411.id3 differ
index 0cd43546d3800cfe6da49ed8b8bc0191fb070b33..d4566555b17d83ee426b735861bc6b7c9ee4a96c 100644 (file)
@@ -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());
-  }*/
+  }
 
 };