]> granicus.if.org Git - taglib/commitdiff
ID3v2 padding won't increase beyond 1% of the file size.
authorTsuda Kageyu <tsuda.kageyu@gmail.com>
Wed, 15 Oct 2014 22:16:57 +0000 (07:16 +0900)
committerTsuda Kageyu <tsuda.kageyu@gmail.com>
Thu, 23 Oct 2014 03:38:38 +0000 (12:38 +0900)
taglib/mpeg/id3v2/id3v2tag.cpp
tests/test_id3v2.cpp

index c6aa4f930a4dac25bd0c59bbf2dbf4dafa4d4547..e8fa23df8ccd74a78e13c479acb2c73d42827f29 100644 (file)
@@ -81,6 +81,11 @@ public:
 static const Latin1StringHandler defaultStringHandler;
 const ID3v2::Latin1StringHandler *ID3v2::Tag::TagPrivate::stringHandler = &defaultStringHandler;
 
+namespace
+{
+  const uint DefaultPaddingSize = 1024;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // StringHandler implementation
 ////////////////////////////////////////////////////////////////////////////////
@@ -596,15 +601,19 @@ ByteVector ID3v2::Tag::render(int version) const
 
   // Compute the amount of padding, and append that to tagData.
 
-  uint paddingSize = 0;
-  uint originalSize = d->header.tagSize();
+  uint paddingSize = DefaultPaddingSize;
 
-  if(tagData.size() < originalSize)
-    paddingSize = originalSize - tagData.size();
-  else
-    paddingSize = 1024;
+  if(d->file && tagData.size() < d->header.tagSize()) {
+    paddingSize = d->header.tagSize() - tagData.size();
+
+    // Padding won't increase beyond 1% of the file size.
+
+    const uint threshold = d->file->length() / 100; // should be ulonglong in taglib2.
+    if(paddingSize > d->paddingSize && paddingSize > threshold)
+      paddingSize = DefaultPaddingSize;
+  }
 
-  tagData.append(ByteVector(paddingSize, char(0)));
+  tagData.append(ByteVector(paddingSize, '\0'));
 
   // Set the version and data size.
   d->header.setMajorVersion(version);
index ebe86fc398b1e239a2e2d1697c1772361022be35..a0443cd8b12e68439851c3a323a7828589fe43d0 100644 (file)
@@ -91,6 +91,7 @@ class TestID3v2 : public CppUnit::TestFixture
   CPPUNIT_TEST(testRenderChapterFrame);
   CPPUNIT_TEST(testParseTableOfContentsFrame);
   CPPUNIT_TEST(testRenderTableOfContentsFrame);
+  CPPUNIT_TEST(testShrinkPadding);
   CPPUNIT_TEST_SUITE_END();
 
 public:
@@ -1005,6 +1006,39 @@ public:
       f.render());
   }
 
+  void testShrinkPadding()
+  {
+    ScopedFileCopy copy("xing", ".mp3");
+    string newname = copy.fileName();
+
+    {
+      MPEG::File f(newname.c_str());
+      ID3v2::Tag *tag = f.ID3v2Tag(true);
+
+      ID3v2::TextIdentificationFrame *frame1 = new ID3v2::TextIdentificationFrame("TIT2");
+      frame1->setText("Title");
+      tag->addFrame(frame1);
+
+      ID3v2::AttachedPictureFrame *frame2 = new ID3v2::AttachedPictureFrame();
+      frame2->setPicture(ByteVector(100 * 1024, '\xff'));
+      tag->addFrame(frame2);
+
+      f.save();
+      CPPUNIT_ASSERT(f.length() > 100 * 1024);
+    }
+
+    {
+      MPEG::File f(newname.c_str());
+      CPPUNIT_ASSERT_EQUAL(true, f.hasID3v2Tag());
+
+      ID3v2::Tag *tag = f.ID3v2Tag();
+      tag->removeFrames("APIC");
+
+      f.save();
+      CPPUNIT_ASSERT(f.length() < 10 * 1024);
+    }
+  }
+
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(TestID3v2);