Decode unsynch-encoded tag (ID3v2.3) and frame (ID3v2.4) data before parsing them.

BUG:138829


git-svn-id: svn://anonsvn.kde.org/home/kde/trunk/kdesupport/taglib@733565 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
This commit is contained in:
Lukáš Lalinský 2007-11-06 18:27:47 +00:00
parent 0d7ed811fe
commit b83bf359fc
7 changed files with 78 additions and 6 deletions

View File

@ -28,6 +28,7 @@
#include <tdebug.h>
#include "id3v2framefactory.h"
#include "id3v2synchdata.h"
#include "frames/attachedpictureframe.h"
#include "frames/commentsframe.h"
@ -71,6 +72,15 @@ Frame *FrameFactory::createFrame(const ByteVector &data, bool synchSafeInts) con
Frame *FrameFactory::createFrame(const ByteVector &data, uint version) const
{
Header tagHeader;
tagHeader.setMajorVersion(version);
return createFrame(data, &tagHeader);
}
Frame *FrameFactory::createFrame(const ByteVector &origData, Header *tagHeader) const
{
ByteVector data = origData;
uint version = tagHeader->majorVersion();
Frame::Header *header = new Frame::Header(data, version);
ByteVector frameID = header->frameID();
@ -78,7 +88,7 @@ Frame *FrameFactory::createFrame(const ByteVector &data, uint version) const
// characters. Also make sure that there is data in the frame.
if(!frameID.size() == (version < 3 ? 3 : 4) ||
header->frameSize() <= 0 ||
header->frameSize() <= (header->dataLengthIndicator() ? 4 : 0) ||
header->frameSize() > data.size())
{
delete header;
@ -92,6 +102,14 @@ Frame *FrameFactory::createFrame(const ByteVector &data, uint version) const
}
}
if(version > 3 && (tagHeader->unsynchronisation() || header->unsynchronisation())) {
// Data lengths are not part of the encoded data, but since they are synch-safe
// integers they will be never actually encoded.
ByteVector frameData = data.mid(Frame::Header::size(version), header->frameSize());
SynchData::decode(frameData);
data = data.mid(0, Frame::Header::size(version)) + frameData;
}
// TagLib doesn't mess with encrypted frames, so just treat them
// as unknown frames.

View File

@ -29,6 +29,7 @@
#include "taglib_export.h"
#include "tbytevector.h"
#include "id3v2frame.h"
#include "id3v2header.h"
namespace TagLib {
@ -64,8 +65,8 @@ namespace TagLib {
* false if we are parsing an old tag (v2.3 or older) that does not support
* synchsafe ints.
*
* \deprecated Please use the method below that accepts an ID3 version
* number in new code.
* \deprecated Please use the method below that accepts a ID3v2::Header
* instance in new code.
*/
Frame *createFrame(const ByteVector &data, bool synchSafeInts) const;
@ -73,9 +74,18 @@ namespace TagLib {
* Create a frame based on \a data. \a version should indicate the ID3v2
* version of the tag. As ID3v2.4 is the most current version of the
* standard 4 is the default.
*
* \deprecated Please use the method below that accepts a ID3v2::Header
* instance in new code.
*/
Frame *createFrame(const ByteVector &data, uint version = 4) const;
/*!
* Create a frame based on \a data. \a tagHeader should be a valid
* ID3v2::Header instance.
*/
// BIC: make virtual
Frame *createFrame(const ByteVector &data, uint version = 4) const;
Frame *createFrame(const ByteVector &data, Header *tagHeader) const;
/*!
* Returns the default text encoding for text frames. If setTextEncoding()

View File

@ -101,6 +101,11 @@ TagLib::uint Header::majorVersion() const
return d->majorVersion;
}
void Header::setMajorVersion(TagLib::uint version)
{
d->majorVersion = version;
}
TagLib::uint Header::revisionNumber() const
{
return d->revisionNumber;

View File

@ -69,6 +69,13 @@ namespace TagLib {
*/
uint majorVersion() const;
/*!
* Set the the major version number to \a version. (Note: This is
* the 4, not the 2 in ID3v2.4.0. The 2 is implied.)
* \see majorVersion()
*/
void setMajorVersion(uint version);
/*!
* Returns the revision number. (Note: This is the 0, not the 4 in
* ID3v2.4.0. The 2 is implied.)

View File

@ -50,3 +50,23 @@ ByteVector SynchData::fromUInt(uint value)
return v;
}
void SynchData::decode(ByteVector &data)
{
char *n = data.data();
const char *o = data.data();
const char *end = o + data.size();
if(data.size() <= 0)
return;
while(o < end - 1) {
*n++ = *o;
if(o[0] == '\xFF' && o[1] == '\x00')
o++;
o++;
}
*n++ = *o;
data.resize(n - data.data());
}

View File

@ -57,6 +57,11 @@ namespace TagLib {
* Returns a 4 byte (32 bit) synchsafe integer based on \a value.
*/
ByteVector fromUInt(uint value);
/*!
* Deunsynchronize the data (in-place).
*/
void decode(ByteVector &data);
}
}

View File

@ -30,6 +30,7 @@
#include "id3v2header.h"
#include "id3v2extendedheader.h"
#include "id3v2footer.h"
#include "id3v2synchdata.h"
#include "id3v1genres.h"
@ -381,8 +382,14 @@ void ID3v2::Tag::read()
}
}
void ID3v2::Tag::parse(const ByteVector &data)
void ID3v2::Tag::parse(const ByteVector &origData)
{
ByteVector data = origData;
if(d->header.unsynchronisation() && d->header.majorVersion() <= 3) {
SynchData::decode(data);
}
uint frameDataPosition = 0;
uint frameDataLength = data.size();
@ -424,7 +431,7 @@ void ID3v2::Tag::parse(const ByteVector &data)
}
Frame *frame = d->factory->createFrame(data.mid(frameDataPosition),
d->header.majorVersion());
&d->header);
if(!frame)
return;