mirror of
https://github.com/taglib/taglib.git
synced 2025-07-21 22:44:28 -04:00
Fix writing of new RIFF chunks at even positions
If the last chunk had an odd size, the new chunk would have been written at odd position, which is incorrect. This is based on the patch by Jens Dyffort, but I ended up changing the implementation to correctly handle subsequential updates to the file. The whole RIFF code really needs to be rewritten in a different way... BUG:243954 git-svn-id: svn://anonsvn.kde.org/home/kde/trunk/kdesupport/taglib@1220223 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
This commit is contained in:
@ -74,6 +74,11 @@ RIFF::File::File(FileName file, Endianness endianness) : TagLib::File(file)
|
||||
read();
|
||||
}
|
||||
|
||||
TagLib::uint RIFF::File::riffSize() const
|
||||
{
|
||||
return d->size;
|
||||
}
|
||||
|
||||
TagLib::uint RIFF::File::chunkCount() const
|
||||
{
|
||||
return d->chunkNames.size();
|
||||
@ -89,6 +94,11 @@ TagLib::uint RIFF::File::chunkOffset(uint i) const
|
||||
return d->chunkOffsets[i];
|
||||
}
|
||||
|
||||
TagLib::uint RIFF::File::chunkPadding(uint i) const
|
||||
{
|
||||
return d->chunkPadding[i];
|
||||
}
|
||||
|
||||
ByteVector RIFF::File::chunkName(uint i) const
|
||||
{
|
||||
if(i >= chunkCount())
|
||||
@ -116,8 +126,7 @@ ByteVector RIFF::File::chunkData(uint i)
|
||||
|
||||
void RIFF::File::setChunkData(const ByteVector &name, const ByteVector &data)
|
||||
{
|
||||
if(d->chunkNames.size() == 0)
|
||||
{
|
||||
if(d->chunkNames.size() == 0) {
|
||||
debug("RIFF::File::setChunkData - No valid chunks found.");
|
||||
return;
|
||||
}
|
||||
@ -125,12 +134,10 @@ void RIFF::File::setChunkData(const ByteVector &name, const ByteVector &data)
|
||||
for(uint i = 0; i < d->chunkNames.size(); i++) {
|
||||
if(d->chunkNames[i] == name) {
|
||||
|
||||
int sizeDifference = data.size() - d->chunkSizes[i];
|
||||
|
||||
// First we update the global size
|
||||
|
||||
insert(ByteVector::fromUInt(d->size + sizeDifference,
|
||||
d->endianness == BigEndian), 4, 4);
|
||||
d->size += ((data.size() + 1) & ~1) - (d->chunkSizes[i] + d->chunkPadding[i]);
|
||||
insert(ByteVector::fromUInt(d->size, d->endianness == BigEndian), 4, 4);
|
||||
|
||||
// Now update the specific chunk
|
||||
|
||||
@ -148,11 +155,30 @@ void RIFF::File::setChunkData(const ByteVector &name, const ByteVector &data)
|
||||
}
|
||||
}
|
||||
|
||||
// Couldn't find an existing chunk, so let's create a new one. First update
|
||||
// the global size:
|
||||
// Couldn't find an existing chunk, so let's create a new one.
|
||||
|
||||
insert(ByteVector::fromUInt(d->size + data.size() + 8, d->endianness == BigEndian), 4, 4);
|
||||
writeChunk(name, data, d->chunkOffsets.back() + d->chunkSizes.back());
|
||||
uint i = d->chunkNames.size() - 1;
|
||||
ulong offset = d->chunkOffsets[i] + d->chunkSizes[i];
|
||||
|
||||
// First we update the global size
|
||||
|
||||
d->size += (offset & 1) + data.size() + 8;
|
||||
insert(ByteVector::fromUInt(d->size, d->endianness == BigEndian), 4, 4);
|
||||
|
||||
// Now add the chunk to the file
|
||||
|
||||
writeChunk(name, data, offset, std::max(ulong(0), length() - offset), (offset & 1) ? 1 : 0);
|
||||
|
||||
// And update our internal structure
|
||||
|
||||
if (offset & 1) {
|
||||
d->chunkPadding[i] = 1;
|
||||
offset++;
|
||||
}
|
||||
d->chunkNames.push_back(name);
|
||||
d->chunkSizes.push_back(data.size());
|
||||
d->chunkOffsets.push_back(offset + 8);
|
||||
d->chunkPadding.push_back((data.size() & 0x01) ? 1 : 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -203,13 +229,16 @@ void RIFF::File::read()
|
||||
}
|
||||
|
||||
void RIFF::File::writeChunk(const ByteVector &name, const ByteVector &data,
|
||||
ulong offset, ulong replace)
|
||||
ulong offset, ulong replace, uint leadingPadding)
|
||||
{
|
||||
ByteVector combined = name;
|
||||
ByteVector combined;
|
||||
if(leadingPadding) {
|
||||
combined.append(ByteVector(leadingPadding, '\x00'));
|
||||
}
|
||||
combined.append(name);
|
||||
combined.append(ByteVector::fromUInt(data.size(), d->endianness == BigEndian));
|
||||
combined.append(data);
|
||||
if((data.size() & 0x01) != 0) {
|
||||
// padding
|
||||
combined.append('\x00');
|
||||
}
|
||||
insert(combined, offset, replace);
|
||||
|
@ -57,6 +57,11 @@ namespace TagLib {
|
||||
|
||||
File(FileName file, Endianness endianness);
|
||||
|
||||
/*!
|
||||
* \return The size of the main RIFF chunk.
|
||||
*/
|
||||
uint riffSize() const;
|
||||
|
||||
/*!
|
||||
* \return The number of chunks in the file.
|
||||
*/
|
||||
@ -72,6 +77,11 @@ namespace TagLib {
|
||||
*/
|
||||
uint chunkDataSize(uint i) const;
|
||||
|
||||
/*!
|
||||
* \return The size of the padding after the chunk (can be either 0 or 1).
|
||||
*/
|
||||
uint chunkPadding(uint i) const;
|
||||
|
||||
/*!
|
||||
* \return The name of the specified chunk, for instance, "COMM" or "ID3 "
|
||||
*/
|
||||
@ -99,7 +109,8 @@ namespace TagLib {
|
||||
|
||||
void read();
|
||||
void writeChunk(const ByteVector &name, const ByteVector &data,
|
||||
ulong offset, ulong replace = 0);
|
||||
ulong offset, ulong replace = 0,
|
||||
uint leadingPadding = 0);
|
||||
|
||||
class FilePrivate;
|
||||
FilePrivate *d;
|
||||
|
Reference in New Issue
Block a user