|
|
|
@ -107,20 +107,6 @@ ID3::ID3(DataSourceHelper *sourcehelper, bool ignoreV1, off64_t offset)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ID3::ID3(DataSourceBase *source, bool ignoreV1, off64_t offset)
|
|
|
|
|
: mIsValid(false),
|
|
|
|
|
mData(NULL),
|
|
|
|
|
mSize(0),
|
|
|
|
|
mFirstFrameOffset(0),
|
|
|
|
|
mVersion(ID3_UNKNOWN),
|
|
|
|
|
mRawSize(0) {
|
|
|
|
|
mIsValid = parseV2(source, offset);
|
|
|
|
|
|
|
|
|
|
if (!mIsValid && !ignoreV1) {
|
|
|
|
|
mIsValid = parseV1(source);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ID3::ID3(const uint8_t *data, size_t size, bool ignoreV1)
|
|
|
|
|
: mIsValid(false),
|
|
|
|
|
mData(NULL),
|
|
|
|
@ -247,44 +233,14 @@ struct id3_header {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (header.version_major == 4) {
|
|
|
|
|
void *copy = malloc(size);
|
|
|
|
|
if (copy == NULL) {
|
|
|
|
|
free(mData);
|
|
|
|
|
mData = NULL;
|
|
|
|
|
ALOGE("b/24623447, no more memory");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memcpy(copy, mData, size);
|
|
|
|
|
|
|
|
|
|
bool success = removeUnsynchronizationV2_4(false /* iTunesHack */);
|
|
|
|
|
if (!success) {
|
|
|
|
|
memcpy(mData, copy, size);
|
|
|
|
|
mSize = size;
|
|
|
|
|
|
|
|
|
|
success = removeUnsynchronizationV2_4(true /* iTunesHack */);
|
|
|
|
|
|
|
|
|
|
if (success) {
|
|
|
|
|
ALOGV("Had to apply the iTunes hack to parse this ID3 tag");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(copy);
|
|
|
|
|
copy = NULL;
|
|
|
|
|
|
|
|
|
|
if (!success) {
|
|
|
|
|
free(mData);
|
|
|
|
|
mData = NULL;
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
} else if (header.flags & 0x80) {
|
|
|
|
|
// first handle global unsynchronization
|
|
|
|
|
if (header.flags & 0x80) {
|
|
|
|
|
ALOGV("removing unsynchronization");
|
|
|
|
|
|
|
|
|
|
removeUnsynchronization();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// handle extended header, if present
|
|
|
|
|
mFirstFrameOffset = 0;
|
|
|
|
|
if (header.version_major == 3 && (header.flags & 0x40)) {
|
|
|
|
|
// Version 2.3 has an optional extended header.
|
|
|
|
@ -296,6 +252,7 @@ struct id3_header {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// v2.3 does not have syncsafe integers
|
|
|
|
|
size_t extendedHeaderSize = U32_AT(&mData[0]);
|
|
|
|
|
if (extendedHeaderSize > SIZE_MAX - 4) {
|
|
|
|
|
free(mData);
|
|
|
|
@ -367,6 +324,48 @@ struct id3_header {
|
|
|
|
|
mFirstFrameOffset = ext_size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Handle any v2.4 per-frame unsynchronization
|
|
|
|
|
// The id3 spec isn't clear about what should happen if the global
|
|
|
|
|
// unsynchronization flag is combined with per-frame unsynchronization,
|
|
|
|
|
// or whether that's even allowed, so this code assumes id3 writing
|
|
|
|
|
// tools do the right thing and not apply double-unsynchronization,
|
|
|
|
|
// but will honor the flags if they are set.
|
|
|
|
|
if (header.version_major == 4) {
|
|
|
|
|
void *copy = malloc(size);
|
|
|
|
|
if (copy == NULL) {
|
|
|
|
|
free(mData);
|
|
|
|
|
mData = NULL;
|
|
|
|
|
ALOGE("b/24623447, no more memory");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memcpy(copy, mData, size);
|
|
|
|
|
|
|
|
|
|
bool success = removeUnsynchronizationV2_4(false /* iTunesHack */);
|
|
|
|
|
if (!success) {
|
|
|
|
|
memcpy(mData, copy, size);
|
|
|
|
|
mSize = size;
|
|
|
|
|
|
|
|
|
|
success = removeUnsynchronizationV2_4(true /* iTunesHack */);
|
|
|
|
|
|
|
|
|
|
if (success) {
|
|
|
|
|
ALOGV("Had to apply the iTunes hack to parse this ID3 tag");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(copy);
|
|
|
|
|
copy = NULL;
|
|
|
|
|
|
|
|
|
|
if (!success) {
|
|
|
|
|
free(mData);
|
|
|
|
|
mData = NULL;
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (header.version_major == 2) {
|
|
|
|
|
mVersion = ID3_V2_2;
|
|
|
|
|
} else if (header.version_major == 3) {
|
|
|
|
@ -411,7 +410,7 @@ static void WriteSyncsafeInteger(uint8_t *dst, size_t x) {
|
|
|
|
|
bool ID3::removeUnsynchronizationV2_4(bool iTunesHack) {
|
|
|
|
|
size_t oldSize = mSize;
|
|
|
|
|
|
|
|
|
|
size_t offset = 0;
|
|
|
|
|
size_t offset = mFirstFrameOffset;
|
|
|
|
|
while (mSize >= 10 && offset <= mSize - 10) {
|
|
|
|
|
if (!memcmp(&mData[offset], "\0\0\0\0", 4)) {
|
|
|
|
|
break;
|
|
|
|
@ -445,7 +444,7 @@ bool ID3::removeUnsynchronizationV2_4(bool iTunesHack) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((flags & 2) && (dataSize >= 2)) {
|
|
|
|
|
// This file has "unsynchronization", so we have to replace occurrences
|
|
|
|
|
// This frame has "unsynchronization", so we have to replace occurrences
|
|
|
|
|
// of 0xff 0x00 with just 0xff in order to get the real data.
|
|
|
|
|
|
|
|
|
|
size_t readOffset = offset + 11;
|
|
|
|
|