1fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber/*
2fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * Copyright (C) 2010 The Android Open Source Project
3fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *
4fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * you may not use this file except in compliance with the License.
6fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * You may obtain a copy of the License at
7fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *
8fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *
10fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * Unless required by applicable law or agreed to in writing, software
11fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * See the License for the specific language governing permissions and
14fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * limitations under the License.
15fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber */
16fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
17fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber//#define LOG_NDEBUG 0
18fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#define LOG_TAG "ID3"
19fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#include <utils/Log.h>
20fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
21fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#include "../include/ID3.h"
22fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
23d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <media/DataSource.h>
24f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <media/stagefright/foundation/ADebug.h>
25607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang#include <media/stagefright/foundation/ByteUtils.h>
26fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#include <utils/String8.h>
27569e7f1b1444194d1aca5a0b23de154565ba12daMarco Nelissen#include <byteswap.h>
28fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
29fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubernamespace android {
30fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
3165997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huberstatic const size_t kMaxMetadataSize = 3 * 1024 * 1024;
3265997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber
332a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissenstruct MemorySource : public DataSourceBase {
3414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    MemorySource(const uint8_t *data, size_t size)
3514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        : mData(data),
3614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber          mSize(size) {
3714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
3814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
3914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    virtual status_t initCheck() const {
4014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return OK;
4114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
4214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
4314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    virtual ssize_t readAt(off64_t offset, void *data, size_t size) {
44b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross        off64_t available = (offset >= (off64_t)mSize) ? 0ll : mSize - offset;
4514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
46b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross        size_t copy = (available > (off64_t)size) ? size : available;
4714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        memcpy(data, mData + offset, copy);
4814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
4914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        return copy;
5014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
5114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
5214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huberprivate:
5314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    const uint8_t *mData;
5414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    size_t mSize;
5514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
5614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(MemorySource);
5714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber};
5814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
592a243f08193fe9ff1afe018e9953f01c44ced9deMarco NelissenID3::ID3(DataSourceBase *source, bool ignoreV1, off64_t offset)
60fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    : mIsValid(false),
61fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mData(NULL),
62fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mSize(0),
63fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mFirstFrameOffset(0),
6414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mVersion(ID3_UNKNOWN),
6514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mRawSize(0) {
66328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    mIsValid = parseV2(source, offset);
6714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
6814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    if (!mIsValid && !ignoreV1) {
6914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        mIsValid = parseV1(source);
7014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    }
7114f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber}
7214f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
7314f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas HuberID3::ID3(const uint8_t *data, size_t size, bool ignoreV1)
7414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    : mIsValid(false),
7514f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mData(NULL),
7614f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mSize(0),
7714f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mFirstFrameOffset(0),
7814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mVersion(ID3_UNKNOWN),
7914f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber      mRawSize(0) {
802a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen    MemorySource *source = new (std::nothrow) MemorySource(data, size);
81c54432ae4f3627b1003fa251616b0103dad8b5d0Ray Essick
82c54432ae4f3627b1003fa251616b0103dad8b5d0Ray Essick    if (source == NULL)
83c54432ae4f3627b1003fa251616b0103dad8b5d0Ray Essick        return;
8414f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber
85328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    mIsValid = parseV2(source, 0);
8683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
87ffd6ffc5429c45577fd8e9f8fa90e79bb91b8a84Dylan Powers    if (!mIsValid && !ignoreV1) {
8883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mIsValid = parseV1(source);
8983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
902a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen    delete source;
91fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
92fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
93fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::~ID3() {
94fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mData) {
95fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        free(mData);
96fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mData = NULL;
97fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
98fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
99fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
100fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberbool ID3::isValid() const {
101fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return mIsValid;
102fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
103fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
104fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::Version ID3::version() const {
105fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return mVersion;
106fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
107fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
108bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber// static
109bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huberbool ID3::ParseSyncsafeInteger(const uint8_t encoded[4], size_t *x) {
110bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    *x = 0;
111bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    for (int32_t i = 0; i < 4; ++i) {
112bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (encoded[i] & 0x80) {
113bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            return false;
114bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
115bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
116bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        *x = ((*x) << 7) | encoded[i];
117bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    }
118bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
119bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    return true;
120bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber}
121bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
1222a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissenbool ID3::parseV2(DataSourceBase *source, off64_t offset) {
123bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huberstruct id3_header {
124bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    char id[3];
125bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    uint8_t version_major;
126bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    uint8_t version_minor;
127bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    uint8_t flags;
128bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    uint8_t enc_size[4];
129fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    };
130fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
131fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    id3_header header;
132fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (source->readAt(
133328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                offset, &header, sizeof(header)) != (ssize_t)sizeof(header)) {
134fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
135fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
136fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
137fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (memcmp(header.id, "ID3", 3)) {
138fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
139fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
140fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
141fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.version_major == 0xff || header.version_minor == 0xff) {
142fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
143fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
144fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
145fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.version_major == 2) {
146fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (header.flags & 0x3f) {
147fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // We only support the 2 high bits, if any of the lower bits are
148fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // set, we cannot guarantee to understand the tag format.
149fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
150fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
151fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
152fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (header.flags & 0x40) {
153fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // No compression scheme has been decided yet, ignore the
154fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // tag if compression is indicated.
155fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
156fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
157fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
158fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    } else if (header.version_major == 3) {
159fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (header.flags & 0x1f) {
160fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // We only support the 3 high bits, if any of the lower bits are
161fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            // set, we cannot guarantee to understand the tag format.
162fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
163fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
164bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (header.version_major == 4) {
165bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (header.flags & 0x0f) {
166bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            // The lower 4 bits are undefined in this spec.
167bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            return false;
168bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
169fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    } else {
170fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
171fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
172fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
173bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    size_t size;
174bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    if (!ParseSyncsafeInteger(header.enc_size, &size)) {
175bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        return false;
176fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
177fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
17865997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber    if (size > kMaxMetadataSize) {
179b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross        ALOGE("skipping huge ID3 metadata of size %zu", size);
18065997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber        return false;
18165997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber    }
18265997f022fa3f557ba864ecc99a1aa33df54c2dbAndreas Huber
183fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mData = (uint8_t *)malloc(size);
184fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
185fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mData == NULL) {
186fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
187fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
188fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
189fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mSize = size;
19014f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber    mRawSize = mSize + sizeof(header);
191fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
192328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    if (source->readAt(offset + sizeof(header), mData, mSize) != (ssize_t)mSize) {
193ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        free(mData);
194ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        mData = NULL;
195ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
196fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return false;
197fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
198fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
199ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    if (header.version_major == 4) {
200428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        void *copy = malloc(size);
201b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia        if (copy == NULL) {
202b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia            free(mData);
203b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia            mData = NULL;
204b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia            ALOGE("b/24623447, no more memory");
205b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia            return false;
206b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia        }
207b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia
208428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        memcpy(copy, mData, size);
209428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber
210428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        bool success = removeUnsynchronizationV2_4(false /* iTunesHack */);
211428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        if (!success) {
212428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            memcpy(mData, copy, size);
213428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            mSize = size;
214428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber
215428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            success = removeUnsynchronizationV2_4(true /* iTunesHack */);
216428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber
217428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            if (success) {
2183856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("Had to apply the iTunes hack to parse this ID3 tag");
219428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            }
220428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        }
221428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber
222428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        free(copy);
223428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        copy = NULL;
224428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber
225428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        if (!success) {
226ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            free(mData);
227ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            mData = NULL;
228ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
229ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            return false;
230ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
231ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    } else if (header.flags & 0x80) {
2323856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("removing unsynchronization");
233ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
234fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        removeUnsynchronization();
235fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
236fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
237fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mFirstFrameOffset = 0;
238fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.version_major == 3 && (header.flags & 0x40)) {
239fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // Version 2.3 has an optional extended header.
240fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
241fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (mSize < 4) {
24283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            free(mData);
24383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            mData = NULL;
24483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
245fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
246fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
247fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
248b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia        size_t extendedHeaderSize = U32_AT(&mData[0]);
249b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia        if (extendedHeaderSize > SIZE_MAX - 4) {
250b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia            free(mData);
251b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia            mData = NULL;
252b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia            ALOGE("b/24623447, extendedHeaderSize is too large");
253b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia            return false;
254b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia        }
255b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia        extendedHeaderSize += 4;
256fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
257fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (extendedHeaderSize > mSize) {
25883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            free(mData);
25983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            mData = NULL;
26083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
261fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return false;
262fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
263fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
264fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mFirstFrameOffset = extendedHeaderSize;
265fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
266fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        uint16_t extendedFlags = 0;
267fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (extendedHeaderSize >= 6) {
268fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            extendedFlags = U16_AT(&mData[4]);
269fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
270fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (extendedHeaderSize >= 10) {
271fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                size_t paddingSize = U32_AT(&mData[6]);
272fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
273b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia                if (paddingSize > SIZE_MAX - mFirstFrameOffset) {
274b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia                    ALOGE("b/24623447, paddingSize is too large");
275b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia                }
276b3694ff5a5bcecd4b6cedca156f6effb55bbf4caWei Jia                if (paddingSize > mSize - mFirstFrameOffset) {
27783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    free(mData);
27883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mData = NULL;
27983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
280fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                    return false;
281fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                }
282fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
283fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mSize -= paddingSize;
284fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
285fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
286fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (extendedFlags & 0x8000) {
2873856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("have crc");
288fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
289fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
290bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (header.version_major == 4 && (header.flags & 0x40)) {
291bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // Version 2.4 has an optional extended header, that's different
292bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // from Version 2.3's...
293bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
294bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (mSize < 4) {
295bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            free(mData);
296bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            mData = NULL;
297bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
298bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            return false;
299bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
300bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
301bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        size_t ext_size;
302bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (!ParseSyncsafeInteger(mData, &ext_size)) {
303bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            free(mData);
304bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            mData = NULL;
305bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
306bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            return false;
307bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
308bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
309bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (ext_size < 6 || ext_size > mSize) {
310bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            free(mData);
311bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            mData = NULL;
312bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
313bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            return false;
314bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
315bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
316bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        mFirstFrameOffset = ext_size;
317fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
318fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
319fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (header.version_major == 2) {
320fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mVersion = ID3_V2_2;
321bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (header.version_major == 3) {
322fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mVersion = ID3_V2_3;
323bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else {
324bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        CHECK_EQ(header.version_major, 4);
325bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        mVersion = ID3_V2_4;
326fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
327fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
328fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return true;
329fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
330fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
331fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::removeUnsynchronization() {
332f9d87cc850a589b9b0cc3658cf222187822bcc00Robert Shih
333f9d87cc850a589b9b0cc3658cf222187822bcc00Robert Shih    // This file has "unsynchronization", so we have to replace occurrences
334f9d87cc850a589b9b0cc3658cf222187822bcc00Robert Shih    // of 0xff 0x00 with just 0xff in order to get the real data.
335f9d87cc850a589b9b0cc3658cf222187822bcc00Robert Shih
336f9d87cc850a589b9b0cc3658cf222187822bcc00Robert Shih    size_t writeOffset = 1;
337f9d87cc850a589b9b0cc3658cf222187822bcc00Robert Shih    for (size_t readOffset = 1; readOffset < mSize; ++readOffset) {
338f9d87cc850a589b9b0cc3658cf222187822bcc00Robert Shih        if (mData[readOffset - 1] == 0xff && mData[readOffset] == 0x00) {
339f9d87cc850a589b9b0cc3658cf222187822bcc00Robert Shih            continue;
340fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
341f9d87cc850a589b9b0cc3658cf222187822bcc00Robert Shih        // Only move data if there's actually something to move.
342f9d87cc850a589b9b0cc3658cf222187822bcc00Robert Shih        // This handles the special case of the data being only [0xff, 0x00]
343f9d87cc850a589b9b0cc3658cf222187822bcc00Robert Shih        // which should be converted to just 0xff if unsynchronization is on.
344f9d87cc850a589b9b0cc3658cf222187822bcc00Robert Shih        mData[writeOffset++] = mData[readOffset];
345fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
346f9d87cc850a589b9b0cc3658cf222187822bcc00Robert Shih
347f9d87cc850a589b9b0cc3658cf222187822bcc00Robert Shih    if (writeOffset < mSize) {
348f9d87cc850a589b9b0cc3658cf222187822bcc00Robert Shih        mSize = writeOffset;
349f9d87cc850a589b9b0cc3658cf222187822bcc00Robert Shih    }
350f9d87cc850a589b9b0cc3658cf222187822bcc00Robert Shih
351fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
352fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
353ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huberstatic void WriteSyncsafeInteger(uint8_t *dst, size_t x) {
354ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    for (size_t i = 0; i < 4; ++i) {
355ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        dst[3 - i] = (x & 0x7f);
356ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        x >>= 7;
357ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    }
358ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber}
359ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
360428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huberbool ID3::removeUnsynchronizationV2_4(bool iTunesHack) {
361ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    size_t oldSize = mSize;
362ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
363ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    size_t offset = 0;
36409da86913ca97d7a818a8917b6601527e5e18a24Wei Jia    while (mSize >= 10 && offset <= mSize - 10) {
365ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        if (!memcmp(&mData[offset], "\0\0\0\0", 4)) {
366ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            break;
367ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
368ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
369ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        size_t dataSize;
370428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        if (iTunesHack) {
371428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber            dataSize = U32_AT(&mData[offset + 4]);
372428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        } else if (!ParseSyncsafeInteger(&mData[offset + 4], &dataSize)) {
373ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            return false;
374ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
375ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
37609da86913ca97d7a818a8917b6601527e5e18a24Wei Jia        if (dataSize > mSize - 10 - offset) {
377ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            return false;
378ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
379ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
380ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        uint16_t flags = U16_AT(&mData[offset + 8]);
381ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        uint16_t prevFlags = flags;
382ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
383ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        if (flags & 1) {
384ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            // Strip data length indicator
385ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
386c37f7f6fa0cb7f55cdc5b2d4ccbf2c87c3bc6c3bNeel Mehta            if (mSize < 14 || mSize - 14 < offset || dataSize < 4) {
38709da86913ca97d7a818a8917b6601527e5e18a24Wei Jia                return false;
38809da86913ca97d7a818a8917b6601527e5e18a24Wei Jia            }
389ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            memmove(&mData[offset + 10], &mData[offset + 14], mSize - offset - 14);
390ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            mSize -= 4;
391ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            dataSize -= 4;
392ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
393ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            flags &= ~1;
394ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
395ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
396d1c19c57f66d91ea8033c8fa6510a8760a6e663bMarco Nelissen        if ((flags & 2) && (dataSize >= 2)) {
39772a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen            // This file has "unsynchronization", so we have to replace occurrences
39872a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen            // of 0xff 0x00 with just 0xff in order to get the real data.
399ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
40072a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen            size_t readOffset = offset + 11;
40172a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen            size_t writeOffset = offset + 11;
402ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            for (size_t i = 0; i + 1 < dataSize; ++i) {
40372a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen                if (mData[readOffset - 1] == 0xff
40472a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen                        && mData[readOffset] == 0x00) {
40572a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen                    ++readOffset;
406ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                    --mSize;
407ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                    --dataSize;
408ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                }
4093e70296461c5f260988ab21854a6f43fdafea764Marco Nelissen                if (i + 1 < dataSize) {
4103e70296461c5f260988ab21854a6f43fdafea764Marco Nelissen                    // Only move data if there's actually something to move.
4113e70296461c5f260988ab21854a6f43fdafea764Marco Nelissen                    // This handles the special case of the data being only [0xff, 0x00]
4123e70296461c5f260988ab21854a6f43fdafea764Marco Nelissen                    // which should be converted to just 0xff if unsynchronization is on.
4133e70296461c5f260988ab21854a6f43fdafea764Marco Nelissen                    mData[writeOffset++] = mData[readOffset++];
4143e70296461c5f260988ab21854a6f43fdafea764Marco Nelissen                }
415ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            }
41672a43b68da48890273508cb1c9d646b7d75fc101Marco Nelissen            // move the remaining data following this frame
417d1c19c57f66d91ea8033c8fa6510a8760a6e663bMarco Nelissen            if (readOffset <= oldSize) {
418d1c19c57f66d91ea8033c8fa6510a8760a6e663bMarco Nelissen                memmove(&mData[writeOffset], &mData[readOffset], oldSize - readOffset);
419d1c19c57f66d91ea8033c8fa6510a8760a6e663bMarco Nelissen            } else {
420d1c19c57f66d91ea8033c8fa6510a8760a6e663bMarco Nelissen                ALOGE("b/34618607 (%zu %zu %zu %zu)", readOffset, writeOffset, oldSize, mSize);
421d1c19c57f66d91ea8033c8fa6510a8760a6e663bMarco Nelissen                android_errorWriteLog(0x534e4554, "34618607");
422d1c19c57f66d91ea8033c8fa6510a8760a6e663bMarco Nelissen            }
423ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
424ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
425d1c19c57f66d91ea8033c8fa6510a8760a6e663bMarco Nelissen        flags &= ~2;
426428d96d5f882d01acb0abb7e1ceb51d4ccc48efaAndreas Huber        if (flags != prevFlags || iTunesHack) {
427ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            WriteSyncsafeInteger(&mData[offset + 4], dataSize);
428ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            mData[offset + 8] = flags >> 8;
429ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            mData[offset + 9] = flags & 0xff;
430ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        }
431ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
432ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber        offset += 10 + dataSize;
433ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    }
434ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
435ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    memset(&mData[mSize], 0, oldSize - mSize);
436ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
437ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber    return true;
438ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber}
439ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber
440fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::Iterator::Iterator(const ID3 &parent, const char *id)
441fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    : mParent(parent),
442fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mID(NULL),
443fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mOffset(mParent.mFirstFrameOffset),
444fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mFrameData(NULL),
445fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mFrameSize(0) {
446fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (id) {
447fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mID = strdup(id);
448fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
449fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
450fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    findFrame();
451fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
452fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
453fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::Iterator::~Iterator() {
454fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mID) {
455fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        free(mID);
456fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mID = NULL;
457fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
458fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
459fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
460fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberbool ID3::Iterator::done() const {
461fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return mFrameData == NULL;
462fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
463fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
464fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::next() {
465fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mFrameData == NULL) {
466fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
467fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
468fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
469fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mOffset += mFrameSize;
470fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
471fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    findFrame();
472fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
473fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
474fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::getID(String8 *id) const {
475fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    id->setTo("");
476fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
477fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mFrameData == NULL) {
478fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
479fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
480fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
481fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mParent.mVersion == ID3_V2_2) {
482fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        id->setTo((const char *)&mParent.mData[mOffset], 3);
483bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (mParent.mVersion == ID3_V2_3 || mParent.mVersion == ID3_V2_4) {
484fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        id->setTo((const char *)&mParent.mData[mOffset], 4);
48583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    } else {
48683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
48783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
48883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        switch (mOffset) {
48983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 3:
49083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TT2");
49183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
49283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 33:
49383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TP1");
49483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
49583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 63:
49683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TAL");
49783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
49883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 93:
49983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TYE");
50083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
50183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 97:
50283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("COM");
50383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
50483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 126:
50583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TRK");
50683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
50783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            case 127:
50883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                id->setTo("TCO");
50983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
51083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            default:
51183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                CHECK(!"should not be here.");
51283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
51383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        }
514fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
515fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
516fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
517fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
518b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen// the 2nd argument is used to get the data following the \0 in a comment field
519b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissenvoid ID3::Iterator::getString(String8 *id, String8 *comment) const {
520b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    getstring(id, false);
521b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    if (comment != NULL) {
522b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        getstring(comment, true);
523b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    }
524b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen}
525b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen
526b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen// comment fields (COM/COMM) contain an initial short descriptor, followed by \0,
527b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen// followed by more data. The data following the \0 can be retrieved by setting
528b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen// "otherdata" to true.
529b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissenvoid ID3::Iterator::getstring(String8 *id, bool otherdata) const {
530fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    id->setTo("");
531fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
532b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    const uint8_t *frameData = mFrameData;
533b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    if (frameData == NULL) {
534fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return;
535fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
536fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
537b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    uint8_t encoding = *frameData;
538b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen
53983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1) {
54083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        if (mOffset == 126 || mOffset == 127) {
54183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            // Special treatment for the track number and genre.
54283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            char tmp[16];
5432c9cb62d0160fc4353d89fd9d648725794e7995eGeorge Burgess IV            snprintf(tmp, sizeof(tmp), "%d", (int)*frameData);
54483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
54583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            id->setTo(tmp);
54683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            return;
54783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        }
54883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
549544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        // this is supposed to be ISO-8859-1, but pass it up as-is to the caller, who will figure
550544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        // out the real encoding
551544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        id->setTo((const char*)frameData, mFrameSize);
55283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return;
55383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
55483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
5553bf1e0fdf27e1188b8d3574ed073595b8eacb114Wei Jia    if (mFrameSize < getHeaderLength() + 1) {
5563bf1e0fdf27e1188b8d3574ed073595b8eacb114Wei Jia        return;
5573bf1e0fdf27e1188b8d3574ed073595b8eacb114Wei Jia    }
558fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    size_t n = mFrameSize - getHeaderLength() - 1;
559b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    if (otherdata) {
560e1e791727f709c7ab54d47b9cd46d4326a02e913Roger        if (n < 5) {
561e1e791727f709c7ab54d47b9cd46d4326a02e913Roger            return;
562e1e791727f709c7ab54d47b9cd46d4326a02e913Roger        }
563b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        // skip past the encoding, language, and the 0 separator
564b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        frameData += 4;
565b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        int32_t i = n - 4;
566b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        while(--i >= 0 && *++frameData != 0) ;
567b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        int skipped = (frameData - mFrameData);
56814f7672b5d450ed26a06fd3bb3ce045ea78b11b2Andreas Huber        if (skipped >= (int)n) {
569b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen            return;
570b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        }
571b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        n -= skipped;
572b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    }
573fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
574d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick    if (n <= 0) {
575d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick       return;
576d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick    }
577d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick
578b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    if (encoding == 0x00) {
579544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        // supposedly ISO 8859-1
580544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        id->setTo((const char*)frameData + 1, n);
581b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    } else if (encoding == 0x03) {
582544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        // supposedly UTF-8
583b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        id->setTo((const char *)(frameData + 1), n);
584b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen    } else if (encoding == 0x02) {
585544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        // supposedly UTF-16 BE, no byte order mark.
586bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // API wants number of characters, not number of bytes...
587bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        int len = n / 2;
588b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        const char16_t *framedata = (const char16_t *) (frameData + 1);
589bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        char16_t *framedatacopy = NULL;
590bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber#if BYTE_ORDER == LITTLE_ENDIAN
591c54432ae4f3627b1003fa251616b0103dad8b5d0Ray Essick        if (len > 0) {
592c54432ae4f3627b1003fa251616b0103dad8b5d0Ray Essick            framedatacopy = new (std::nothrow) char16_t[len];
593d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            if (framedatacopy == NULL) {
594d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick                return;
595c54432ae4f3627b1003fa251616b0103dad8b5d0Ray Essick            }
596d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            for (int i = 0; i < len; i++) {
597d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick                framedatacopy[i] = bswap_16(framedata[i]);
598d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            }
599d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            framedata = framedatacopy;
600bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
601bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber#endif
602bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        id->setTo(framedata, len);
603bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (framedatacopy != NULL) {
604bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            delete[] framedatacopy;
605bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        }
606544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen    } else if (encoding == 0x01) {
607fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        // UCS-2
60808e7eb983fcb9860a574e964ff905f75aab88d2fAndreas Huber        // API wants number of characters, not number of bytes...
6095a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        int len = n / 2;
6103762e0615273f25b059556d5b5f65102e9c55c35Marco Nelissen        if (len == 0) {
6113762e0615273f25b059556d5b5f65102e9c55c35Marco Nelissen            return;
6123762e0615273f25b059556d5b5f65102e9c55c35Marco Nelissen        }
613b636abde14f2612ea236257846b9ab15d87d4623Marco Nelissen        const char16_t *framedata = (const char16_t *) (frameData + 1);
6145a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        char16_t *framedatacopy = NULL;
6155a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        if (*framedata == 0xfffe) {
616d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            // endianness marker != host endianness, convert & skip
617d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            if (len <= 1) {
618d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick                return;         // nothing after the marker
619d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            }
620d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            framedatacopy = new (std::nothrow) char16_t[len];
621d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            if (framedatacopy == NULL) {
622d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick                return;
623d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            }
624d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            for (int i = 0; i < len; i++) {
625d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick                framedatacopy[i] = bswap_16(framedata[i]);
626d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            }
627d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            framedata = framedatacopy;
628d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            // and skip over the marker
629d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            framedata++;
630d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            len--;
631d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick        } else if (*framedata == 0xfeff) {
632d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            // endianness marker == host endianness, skip it
633d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            if (len <= 1) {
634d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick                return;         // nothing after the marker
6355a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            }
6365a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            framedata++;
6375a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            len--;
6385a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        }
639544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen
640544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        // check if the resulting data consists entirely of 8-bit values
641544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        bool eightBit = true;
642544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        for (int i = 0; i < len; i++) {
643544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen            if (framedata[i] > 0xff) {
644544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen                eightBit = false;
645544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen                break;
646544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen            }
647544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        }
648d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick        if (eightBit) {
649544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen            // collapse to 8 bit, then let the media scanner client figure out the real encoding
650c54432ae4f3627b1003fa251616b0103dad8b5d0Ray Essick            char *frame8 = new (std::nothrow) char[len];
651c54432ae4f3627b1003fa251616b0103dad8b5d0Ray Essick            if (frame8 != NULL) {
652c54432ae4f3627b1003fa251616b0103dad8b5d0Ray Essick                for (int i = 0; i < len; i++) {
653c54432ae4f3627b1003fa251616b0103dad8b5d0Ray Essick                    frame8[i] = framedata[i];
654c54432ae4f3627b1003fa251616b0103dad8b5d0Ray Essick                }
655c54432ae4f3627b1003fa251616b0103dad8b5d0Ray Essick                id->setTo(frame8, len);
656c54432ae4f3627b1003fa251616b0103dad8b5d0Ray Essick                delete [] frame8;
657d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick            } else {
658d2b126291b7cc302ebcef8249bef7813e0dd77dcRay Essick                id->setTo(framedata, len);
659544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen            }
660544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        } else {
661544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen            id->setTo(framedata, len);
662544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen        }
663544ad2be674423238c47650d2c8588ba7dfc9ed2Marco Nelissen
6645a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        if (framedatacopy != NULL) {
6655a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen            delete[] framedatacopy;
6665a2621a64de196cbdb9a2a50357dee1c32fcf11bMarco Nelissen        }
667fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
668fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
669fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
670fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberconst uint8_t *ID3::Iterator::getData(size_t *length) const {
671fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    *length = 0;
672fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
673fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mFrameData == NULL) {
674fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return NULL;
675fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
676fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
677be7b5e253f85132683826f305e5dcdaf83f0b300Joshua J. Drake    // Prevent integer underflow
678be7b5e253f85132683826f305e5dcdaf83f0b300Joshua J. Drake    if (mFrameSize < getHeaderLength()) {
679be7b5e253f85132683826f305e5dcdaf83f0b300Joshua J. Drake        return NULL;
680be7b5e253f85132683826f305e5dcdaf83f0b300Joshua J. Drake    }
681be7b5e253f85132683826f305e5dcdaf83f0b300Joshua J. Drake
682fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    *length = mFrameSize - getHeaderLength();
683fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
684fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return mFrameData;
685fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
686fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
687fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubersize_t ID3::Iterator::getHeaderLength() const {
688fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mParent.mVersion == ID3_V2_2) {
689fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return 6;
690bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    } else if (mParent.mVersion == ID3_V2_3 || mParent.mVersion == ID3_V2_4) {
691fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return 10;
69283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    } else {
69383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
69483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return 0;
695fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
696fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
697fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
698fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid ID3::Iterator::findFrame() {
699fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (;;) {
700fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mFrameData = NULL;
701fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mFrameSize = 0;
702fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
703fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (mParent.mVersion == ID3_V2_2) {
704fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + 6 > mParent.mSize) {
705fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
706fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
707fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
708fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!memcmp(&mParent.mData[mOffset], "\0\0\0", 3)) {
709fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
710fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
711fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
712fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameSize =
713fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                (mParent.mData[mOffset + 3] << 16)
714fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                | (mParent.mData[mOffset + 4] << 8)
715fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                | mParent.mData[mOffset + 5];
716fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
717ba6e982635f11bced34897f4317cbe8ff1c89483Marco Nelissen            if (mFrameSize == 0) {
718ba6e982635f11bced34897f4317cbe8ff1c89483Marco Nelissen                return;
719ba6e982635f11bced34897f4317cbe8ff1c89483Marco Nelissen            }
720ba6e982635f11bced34897f4317cbe8ff1c89483Marco Nelissen            mFrameSize += 6; // add tag id and size field
721fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
722c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            // Prevent integer overflow in validation
723c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            if (SIZE_MAX - mOffset <= mFrameSize) {
724c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake                return;
725c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            }
726c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake
727fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + mFrameSize > mParent.mSize) {
728b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross                ALOGV("partial frame at offset %zu (size = %zu, bytes-remaining = %zu)",
729b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross                    mOffset, mFrameSize, mParent.mSize - mOffset - (size_t)6);
730fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
731fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
732fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
733fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameData = &mParent.mData[mOffset + 6];
734fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
735fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!mID) {
736fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
737fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
738fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
739fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            char id[4];
740fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            memcpy(id, &mParent.mData[mOffset], 3);
741fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            id[3] = '\0';
742fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
743fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!strcmp(id, mID)) {
744fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
745fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
746bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        } else if (mParent.mVersion == ID3_V2_3
747bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                || mParent.mVersion == ID3_V2_4) {
748fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + 10 > mParent.mSize) {
749fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
750fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
751fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
752fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!memcmp(&mParent.mData[mOffset], "\0\0\0\0", 4)) {
753fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
754fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
755fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
756c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            size_t baseSize = 0;
757bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            if (mParent.mVersion == ID3_V2_4) {
758bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                if (!ParseSyncsafeInteger(
759bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                            &mParent.mData[mOffset + 4], &baseSize)) {
760bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                    return;
761bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                }
762bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            } else {
763bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                baseSize = U32_AT(&mParent.mData[mOffset + 4]);
764bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            }
765bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
766ba6e982635f11bced34897f4317cbe8ff1c89483Marco Nelissen            if (baseSize == 0) {
767ba6e982635f11bced34897f4317cbe8ff1c89483Marco Nelissen                return;
768ba6e982635f11bced34897f4317cbe8ff1c89483Marco Nelissen            }
769ba6e982635f11bced34897f4317cbe8ff1c89483Marco Nelissen
770c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            // Prevent integer overflow when adding
771c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            if (SIZE_MAX - 10 <= baseSize) {
772c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake                return;
773c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            }
774c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake
775ba6e982635f11bced34897f4317cbe8ff1c89483Marco Nelissen            mFrameSize = 10 + baseSize; // add tag id, size field and flags
776fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
777c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            // Prevent integer overflow in validation
778c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            if (SIZE_MAX - mOffset <= mFrameSize) {
779c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake                return;
780c580c836c1941fb4912e1dd4e08626caf98a62c7Joshua J. Drake            }
781fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
782fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (mOffset + mFrameSize > mParent.mSize) {
783b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross                ALOGV("partial frame at offset %zu (size = %zu, bytes-remaining = %zu)",
784b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross                    mOffset, mFrameSize, mParent.mSize - mOffset - (size_t)10);
785fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return;
786fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
787fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
788bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            uint16_t flags = U16_AT(&mParent.mData[mOffset + 8]);
789bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
790ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber            if ((mParent.mVersion == ID3_V2_4 && (flags & 0x000c))
791bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                || (mParent.mVersion == ID3_V2_3 && (flags & 0x00c0))) {
792ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                // Compression or encryption are not supported at this time.
793ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                // Per-frame unsynchronization and data-length indicator
794ac994dfb88d414aeedf5998aa1c6015c5b47ec01Andreas Huber                // have already been taken care of.
795bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
7963856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("Skipping unsupported frame (compression, encryption "
797bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                     "or per-frame unsynchronization flagged");
798bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
799bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                mOffset += mFrameSize;
800bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber                continue;
801bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            }
802bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber
803fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mFrameData = &mParent.mData[mOffset + 10];
804fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
805fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!mID) {
806fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
807fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
808fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
809fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            char id[5];
810fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            memcpy(id, &mParent.mData[mOffset], 4);
811fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            id[4] = '\0';
812fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
813fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!strcmp(id, mID)) {
814fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                break;
815fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
81683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        } else {
81783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
81883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
81983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            if (mOffset >= mParent.mSize) {
82083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                return;
82183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
82283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
82383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            mFrameData = &mParent.mData[mOffset];
82483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
82583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            switch (mOffset) {
82683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 3:
82783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 33:
82883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 63:
82983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 30;
83083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
83183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 93:
83283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 4;
83383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
83483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 97:
83583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    if (mParent.mVersion == ID3_V1) {
83683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                        mFrameSize = 30;
83783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    } else {
83883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                        mFrameSize = 29;
83983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    }
84083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
84183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 126:
84283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 1;
84383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
84483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                case 127:
84583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    mFrameSize = 1;
84683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
84783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                default:
84883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    CHECK(!"Should not be here, invalid offset.");
84983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                    break;
85083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
85183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
85283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            if (!mID) {
85383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
85483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
85583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
85683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            String8 id;
85783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            getID(&id);
85883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
85983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            if (id == mID) {
86083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber                break;
86183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            }
862fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
863fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
864fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mOffset += mFrameSize;
865fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
866fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
867fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
868ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick// return includes terminator;  if unterminated, returns > limit
869ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essickstatic size_t StringSize(const uint8_t *start, size_t limit, uint8_t encoding) {
870ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick
871bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    if (encoding == 0x00 || encoding == 0x03) {
872bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        // ISO 8859-1 or UTF-8
873ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick        return strnlen((const char *)start, limit) + 1;
874fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
875fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
876fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    // UCS-2
877fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    size_t n = 0;
878ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick    while ((n+1 < limit) && (start[n] != '\0' || start[n + 1] != '\0')) {
879fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        n += 2;
880fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
881ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick    n += 2;
882ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick    return n;
883fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
884fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
885fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberconst void *
886fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberID3::getAlbumArt(size_t *length, String8 *mime) const {
887fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    *length = 0;
888fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mime->setTo("");
889fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
890bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber    Iterator it(
891bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            *this,
892bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber            (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) ? "APIC" : "PIC");
893fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
894fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    while (!it.done()) {
895fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        size_t size;
896fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        const uint8_t *data = it.getData(&size);
897be7b5e253f85132683826f305e5dcdaf83f0b300Joshua J. Drake        if (!data) {
898be7b5e253f85132683826f305e5dcdaf83f0b300Joshua J. Drake            return NULL;
899be7b5e253f85132683826f305e5dcdaf83f0b300Joshua J. Drake        }
900fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
901bebd11b5a406bc4243cb7bd55f6849841bf911a7Andreas Huber        if (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) {
902fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t encoding = data[0];
903ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            size_t consumed = 1;
904ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick
905ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            // *always* in an 8-bit encoding
906ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            size_t mimeLen = StringSize(&data[consumed], size - consumed, 0x00);
907ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            if (mimeLen > size - consumed) {
908ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick                ALOGW("bogus album art size: mime");
909ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick                return NULL;
910ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            }
911ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            mime->setTo((const char *)&data[consumed]);
912ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            consumed += mimeLen;
913fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
914fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#if 0
915ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            uint8_t picType = data[consumed];
916fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (picType != 0x03) {
917fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                // Front Cover Art
918fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                it.next();
919fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                continue;
920fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
921fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#endif
922fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
923ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            consumed++;
924ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            if (consumed >= size) {
925ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick                ALOGW("bogus album art size: pic type");
926ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick                return NULL;
927ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            }
928ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick
929ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            size_t descLen = StringSize(&data[consumed], size - consumed, encoding);
930ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            consumed += descLen;
931fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
932ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            if (consumed >= size) {
933ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick                ALOGW("bogus album art size: description");
934f26400c9d01a0e2f71690d5ebc644270f098d590Marco Nelissen                return NULL;
935f26400c9d01a0e2f71690d5ebc644270f098d590Marco Nelissen            }
936fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
937ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            *length = size - consumed;
938ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick
939ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            return &data[consumed];
940fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        } else {
941fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t encoding = data[0];
942fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
943ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            if (size <= 5) {
944ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick                return NULL;
945ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            }
946ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick
947fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (!memcmp(&data[1], "PNG", 3)) {
948fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mime->setTo("image/png");
949fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            } else if (!memcmp(&data[1], "JPG", 3)) {
950fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mime->setTo("image/jpeg");
951fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            } else if (!memcmp(&data[1], "-->", 3)) {
952fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                mime->setTo("text/plain");
953fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            } else {
954fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                return NULL;
955fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
956fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
957fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#if 0
958fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            uint8_t picType = data[4];
959fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (picType != 0x03) {
960fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                // Front Cover Art
961fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                it.next();
962fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                continue;
963fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
964fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#endif
965fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
966ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            size_t descLen = StringSize(&data[5], size - 5, encoding);
967ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            if (descLen > size - 5) {
968ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick                return NULL;
969ebb726f940b29174f8dd4bb74d6de39c3f6eb611Ray Essick            }
970fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
971fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *length = size - 5 - descLen;
972fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
973fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return &data[5 + descLen];
974fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
975fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
976fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
977fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return NULL;
978fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
979fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
9802a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissenbool ID3::parseV1(DataSourceBase *source) {
98183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    const size_t V1_TAG_SIZE = 128;
98283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
983c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t size;
984c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    if (source->getSize(&size) != OK || size < (off64_t)V1_TAG_SIZE) {
98583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return false;
98683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
98783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
98883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    mData = (uint8_t *)malloc(V1_TAG_SIZE);
98983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (source->readAt(size - V1_TAG_SIZE, mData, V1_TAG_SIZE)
99083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber            != (ssize_t)V1_TAG_SIZE) {
99183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        free(mData);
99283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mData = NULL;
99383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
99483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return false;
99583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
99683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
99783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (memcmp("TAG", mData, 3)) {
99883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        free(mData);
99983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mData = NULL;
100083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
100183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        return false;
100283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
100383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
100483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    mSize = V1_TAG_SIZE;
100583e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    mFirstFrameOffset = 3;
100683e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
100783e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    if (mData[V1_TAG_SIZE - 3] != 0) {
100883e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mVersion = ID3_V1;
100983e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    } else {
101083e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber        mVersion = ID3_V1_1;
101183e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    }
101283e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber
101383e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber    return true;
101483e5850bdf9c8b5c36c364b367b039674eb827adAndreas Huber}
1015fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
1016fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}  // namespace android
1017