From d80c4c96c38d8b66529e7cb845c8704d60b33f64 Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Thu, 16 Oct 2014 07:16:57 +0900 Subject: [PATCH] ID3v2 padding won't increase beyond 1% of the file size. --- taglib/mpeg/id3v2/id3v2tag.cpp | 23 ++++++++++++++++------- tests/test_id3v2.cpp | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/taglib/mpeg/id3v2/id3v2tag.cpp b/taglib/mpeg/id3v2/id3v2tag.cpp index c6aa4f93..e8fa23df 100644 --- a/taglib/mpeg/id3v2/id3v2tag.cpp +++ b/taglib/mpeg/id3v2/id3v2tag.cpp @@ -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(); - tagData.append(ByteVector(paddingSize, char(0))); + // 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, '\0')); // Set the version and data size. d->header.setMajorVersion(version); diff --git a/tests/test_id3v2.cpp b/tests/test_id3v2.cpp index ebe86fc3..a0443cd8 100644 --- a/tests/test_id3v2.cpp +++ b/tests/test_id3v2.cpp @@ -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);