mirror of
https://github.com/taglib/taglib.git
synced 2025-06-03 17:18:11 -04:00
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:
parent
0d7ed811fe
commit
b83bf359fc
@ -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.
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
|
@ -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.)
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user