]> granicus.if.org Git - taglib/commitdiff
Remove the null termination stuff from the ToC frames too
authorScott Wheeler <scott@directededge.com>
Mon, 18 May 2015 16:12:34 +0000 (18:12 +0200)
committerScott Wheeler <scott@directededge.com>
Mon, 18 May 2015 16:17:10 +0000 (18:17 +0200)
taglib/mpeg/id3v2/frames/tableofcontentsframe.cpp
tests/test_id3v2.cpp

index 4c750cc5811904b0929b6f74549d979d93e0f3f8..550df64e53ec9cd703ea72dd0e7f1510a6d864d0 100644 (file)
@@ -50,6 +50,31 @@ public:
   FrameList embeddedFrameList;
 };
 
+namespace {
+
+  // These functions are needed to try to aim for backward compatibility with
+  // an API that previously (unreasonably) required null bytes to be appeneded
+  // at the end of identifiers explicitly by the API user.
+
+  // BIC: remove these
+
+  ByteVector &strip(ByteVector &b)
+  {
+    if(b.endsWith('\0'))
+      b.resize(b.size() - 1);
+    return b;
+  }
+
+  ByteVectorList &strip(ByteVectorList &l)
+  {
+    for(ByteVectorList::Iterator it = l.begin(); it != l.end(); ++it)
+    {
+      strip(*it);
+    }
+    return l;
+  }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // public methods
 ////////////////////////////////////////////////////////////////////////////////
@@ -68,6 +93,7 @@ TableOfContentsFrame::TableOfContentsFrame(const ByteVector &eID, const ByteVect
 {
   d = new TableOfContentsFramePrivate;
   d->elementID = eID;
+  strip(d->elementID);
   d->childElements = ch;
   FrameList l = eF;
   for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it)
@@ -107,8 +133,7 @@ ByteVectorList TableOfContentsFrame::childElements() const
 void TableOfContentsFrame::setElementID(const ByteVector &eID)
 {
   d->elementID = eID;
-  if(eID.at(eID.size() - 1) != char(0))
-    d->elementID.append(char(0));
+  strip(d->elementID);
 }
 
 void TableOfContentsFrame::setIsTopLevel(const bool &t)
@@ -124,16 +149,22 @@ void TableOfContentsFrame::setIsOrdered(const bool &o)
 void TableOfContentsFrame::setChildElements(const ByteVectorList &l)
 {
   d->childElements = l;
+  strip(d->childElements);
 }
 
 void TableOfContentsFrame::addChildElement(const ByteVector &cE)
 {
   d->childElements.append(cE);
+  strip(d->childElements);
 }
 
 void TableOfContentsFrame::removeChildElement(const ByteVector &cE)
 {
   ByteVectorList::Iterator it = d->childElements.find(cE);
+
+  if(it == d->childElements.end())
+    it = d->childElements.find(cE + ByteVector("\0"));
+
   d->childElements.erase(it);
 }
 
@@ -240,17 +271,19 @@ void TableOfContentsFrame::parseFields(const ByteVector &data)
   int pos = 0;
   TagLib::uint embPos = 0;
   d->elementID = readStringField(data, String::Latin1, &pos).data(String::Latin1);
-  d->elementID.append(char(0));
   d->isTopLevel = (data.at(pos) & 2) > 0;
   d->isOrdered = (data.at(pos++) & 1) > 0;
   TagLib::uint entryCount = data.at(pos++);
   for(TagLib::uint i = 0; i < entryCount; i++) {
     ByteVector childElementID = readStringField(data, String::Latin1, &pos).data(String::Latin1);
-    childElementID.append(char(0));
     d->childElements.append(childElementID);
   }
 
   size -= pos;
+
+  if(size < header()->size())
+    return;
+
   while(embPos < size - header()->size()) {
     Frame *frame = FrameFactory::instance()->createFrame(data.mid(pos + embPos), d->tagHeader);
 
@@ -273,6 +306,7 @@ ByteVector TableOfContentsFrame::renderFields() const
   ByteVector data;
 
   data.append(d->elementID);
+  data.append('\0');
   char flags = 0;
   if(d->isTopLevel)
     flags += 2;
@@ -283,6 +317,7 @@ ByteVector TableOfContentsFrame::renderFields() const
   ByteVectorList::ConstIterator it = d->childElements.begin();
   while(it != d->childElements.end()) {
     data.append(*it);
+    data.append('\0');
     it++;
   }
   FrameList l = d->embeddedFrameList;
index be16fd0bf69eab4ac1096a501ed80386c94dc215..c2609cab29cf8c448c03bd037f54c31fc8a25224 100644 (file)
@@ -1001,25 +1001,22 @@ public:
       ByteVector("CTOC"                     // Frame ID
                  "\x00\x00\x00\x16"         // Frame size
                  "\x00\x00"                 // Frame flags
-                 "\x54\x00"                 // Element ID
+                 "\x54\x00"                 // Element ID ("T")
                  "\x01"                     // CTOC flags
                  "\x02"                     // Entry count
-                 "\x43\x00"                 // First entry
-                 "\x44\x00"                 // Second entry
+                 "\x43\x00"                 // First entry ("C")
+                 "\x44\x00"                 // Second entry ("D")
                  "TIT2"                     // Embedded frame ID
                  "\x00\x00\x00\x04"         // Embedded frame size
                  "\x00\x00"                 // Embedded frame flags
                  "\x00"                     // TIT2 frame text encoding
                  "TC1", 32));               // Table of contents title
-    CPPUNIT_ASSERT_EQUAL(ByteVector("\x54\x00", 2),
-                         f.elementID());
+    CPPUNIT_ASSERT_EQUAL(ByteVector("T"), f.elementID());
     CPPUNIT_ASSERT(!f.isTopLevel());
     CPPUNIT_ASSERT(f.isOrdered());
     CPPUNIT_ASSERT((uint)0x02 == f.entryCount());
-    CPPUNIT_ASSERT_EQUAL(ByteVector("\x43\x00", 2),
-                         f.childElements()[0]);
-    CPPUNIT_ASSERT_EQUAL(ByteVector("\x44\x00", 2),
-                         f.childElements()[1]);
+    CPPUNIT_ASSERT_EQUAL(ByteVector("C"), f.childElements()[0]);
+    CPPUNIT_ASSERT_EQUAL(ByteVector("D"), f.childElements()[1]);
     CPPUNIT_ASSERT((uint)0x01 == f.embeddedFrameList().size());
     CPPUNIT_ASSERT(f.embeddedFrameList("TIT2").size() == 1);
     CPPUNIT_ASSERT(f.embeddedFrameList("TIT2")[0]->toString() == "TC1");