==========================
* Better handling of PCM WAV files with a 'fact' chunk.
-
+ * Better handling of corrupted APE tags.
+
1.11 BETA:
* New API for creating FileRef from IOStream.
class APE::Item::ItemPrivate
{
public:
- ItemPrivate() : type(Text), readOnly(false) {}
+ ItemPrivate() :
+ type(Text),
+ readOnly(false) {}
Item::ItemTypes type;
String key;
d->type = Binary;
d->value = value;
}
- else
+ else {
d->text.append(value);
+ }
}
APE::Item::Item(const Item &item) :
int APE::Item::size() const
{
- // SFB: Why is d->key.size() used when size() returns the length in UniChars and not UTF-8?
- int result = 8 + d->key.size() /* d->key.data(String::UTF8).size() */ + 1;
- switch (d->type) {
+ int result = 8 + d->key.size() + 1;
+ switch(d->type) {
case Text:
if(!d->text.isEmpty()) {
StringList::ConstIterator it = d->text.begin();
const unsigned int valueLength = data.toUInt(0, false);
const unsigned int flags = data.toUInt(4, false);
- d->key = String(data.mid(8), String::UTF8);
+ // An item key can contain ASCII characters from 0x20 up to 0x7E, not UTF-8.
+
+ d->key = String(data.mid(8), String::Latin1);
const ByteVector value = data.mid(8 + d->key.size() + 1, valueLength);
data.append(ByteVector::fromUInt(value.size(), false));
data.append(ByteVector::fromUInt(flags, false));
- data.append(d->key.data(String::UTF8));
+ data.append(d->key.data(String::Latin1));
data.append(ByteVector('\0'));
data.append(value);
using namespace TagLib;
using namespace APE;
+namespace
+{
+ inline bool isValidItemKey(const String &key)
+ {
+ for(String::ConstIterator it = key.begin(); it != key.end(); ++it) {
+ const int c = static_cast<unsigned short>(*it);
+ if(c < 0x20 || 0x7E < c)
+ return false;
+ }
+
+ return true;
+ }
+}
+
class APE::Tag::TagPrivate
{
public:
APE::Item item;
item.parse(data.mid(pos));
- d->itemListMap.insert(item.key().upper(), item);
+ if(isValidItemKey(item.key()))
+ d->itemListMap.insert(item.key().upper(), item);
pos += item.size();
}