123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786 |
- #include "frame.h"
- #include "util.h"
- #ifdef _WIN32
- #include "zlib/zlib.h"
- #else
- #include "zlib/zlib.h"
- #endif
- #include "frames.h"
- #include <string.h>
- #include <stdlib.h>
- #include "nu/ByteReader.h"
- #include "nu/ByteWriter.h"
- #include "foundation/error.h"
- #include "nsid3v2.h"
- /* === ID3v2 common === */
- ID3v2::Frame::Frame()
- {
- data = 0;
- data_size = 0;
- }
- ID3v2::Frame::~Frame()
- {
- free(data);
- }
- int ID3v2::Frame::GetData(const void **_data, size_t *data_len) const
- {
- if (data)
- {
- *_data = data;
- *data_len = data_size;
- return NErr_Success;
- }
- else
- return NErr_NullPointer;
- }
- size_t ID3v2::Frame::GetDataSize() const
- {
- return data_size;
- }
- int ID3v2::Frame::NewData(size_t new_len, void **_data, size_t *_data_len)
- {
- // we DO NOT update the header, as its meant to hold the original data
- void *new_data = realloc(data, new_len);
- if (new_data)
- {
- data = new_data;
- data_size = new_len;
- *_data = data;
- *_data_len = data_size;
- return NErr_Success;
- }
- else
- return NErr_OutOfMemory;
- }
- bool ID3v2::Frame::Encrypted() const
- {
- return false;
- }
- bool ID3v2::Frame::Compressed() const
- {
- return false;
- }
- bool ID3v2::Frame::Grouped() const
- {
- return false;
- }
- bool ID3v2::Frame::ReadOnly() const
- {
- return false;
- }
- bool ID3v2::Frame::FrameUnsynchronised() const
- {
- return false;
- }
- bool ID3v2::Frame::DataLengthIndicated() const
- {
- return false;
- }
- bool ID3v2::Frame::TagAlterPreservation() const
- {
- return false;
- }
- bool ID3v2::Frame::FileAlterPreservation() const
- {
- return false;
- }
- static inline void Advance(const void *&data, size_t &len, size_t amount)
- {
- data = (const uint8_t *)data + amount;
- len -= amount;
- }
- static inline void AdvanceBoth(const void *&data, size_t &len, size_t &len2, size_t amount)
- {
- data = (const uint8_t *)data + amount;
- len -= amount;
- len2 -= amount;
- }
- /* === ID3v2.2 === */
- ID3v2_2::Frame::Frame(const ID3v2::Header &_header, const int8_t *id, int flags) : header(_header, id, flags)
- {
- }
- ID3v2_2::Frame::Frame(const FrameHeader &_header) : header(_header)
- {
- }
- int ID3v2_2::Frame::Parse(const void *_data, size_t len, size_t *read)
- {
- *read = 0;
- data_size = header.FrameSize(); // size of frame AFTER re-synchronization
- /* check to make sure that we have enough input data to read the data */
- if (header.Unsynchronised())
- {
- /* this is tricky, because the stored size reflects after re-synchronization,
- but the incoming data is unsynchronized */
- if (ID3v2::Util::UnsynchronisedInputSize(_data, data_size) > len)
- return 1;
- }
- else if (data_size > len)
- return 1;
- /* allocate memory (real data_size) */
- data = malloc(data_size);
- if (!data)
- return 1;
- /* === Read the data === */
- if (header.Unsynchronised())
- {
- *read += ID3v2::Util::UnsynchroniseTo(data, _data, data_size);
- }
- else // normal data
- {
- memcpy(data, _data, data_size);
- *read += data_size;
- }
- return NErr_Success;
- }
- int ID3v2_2::Frame::SerializedSize(uint32_t *length, const ID3v2::Header &tag_header, int flags) const
- {
- ID3v2_2::FrameHeader new_header(header, tag_header);
- // TODO: for now, we're not going to deal with compression
- new_header.SetSize(data_size);
- uint32_t current_length=0;
- new_header.SerializedSize(¤t_length);
- if (new_header.Unsynchronised())
- {
- current_length += ID3v2::Util::SynchronisedSize(data, data_size);
- }
- else
- {
- current_length += new_header.FrameSize();
- }
- *length = current_length;
- return NErr_Success;
- }
- int ID3v2_2::Frame::Serialize(void *output, uint32_t *written, const ID3v2::Header &tag_header, int flags) const
- {
- size_t current_length = FrameHeader::SIZE;
- uint8_t *data_ptr = (uint8_t *)output;
- ID3v2_2::FrameHeader new_header(header, tag_header);
- new_header.SetSize(data_size);
- // write frame header
- new_header.Serialize(data_ptr);
- data_ptr += FrameHeader::SIZE;
- if (new_header.Unsynchronised())
- {
- current_length += ID3v2::Util::SynchroniseTo(data_ptr, data, data_size);
- }
- else
- {
- memcpy(data_ptr, data, data_size);
- current_length += data_size;
- }
- *written = current_length;
- return NErr_Success;
- }
- const int8_t *ID3v2_2::Frame::GetIdentifier() const
- {
- return header.GetIdentifier();
- }
- /* === ID3v2.3 === */
- ID3v2_3::Frame::Frame(const ID3v2::Header &_header, const int8_t *id, int flags) : header(_header, id, flags)
- {
- }
- ID3v2_3::Frame::Frame(const FrameHeader &_header) : header(_header)
- {
- }
- /* helper function
- reads num_bytes from input into output, dealing with re-synchronization and length checking
- increments input pointer
- increments bytes_read value by number of input bytes read (different from num_bytes when data is unsynchronized
- decrements input_len by bytes read
- decrements output_len by bytes written
- */
- bool ID3v2_3::Frame::ReadData(void *output, const void *&input, size_t &input_len, size_t &frame_len, size_t num_bytes, size_t *bytes_read) const
- {
- /* verify that we have enough data in the frame */
- if (num_bytes > frame_len)
- return false;
- /* verify that we have enough data in the buffer */
- size_t bytes_to_read;
- if (header.Unsynchronised())
- bytes_to_read = ID3v2::Util::UnsynchronisedInputSize(input, num_bytes);
- else
- bytes_to_read = num_bytes;
- if (bytes_to_read > input_len)
- return false;
- /* read data */
- if (header.Unsynchronised())
- {
- *bytes_read += ID3v2::Util::SynchroniseTo(&output, input, num_bytes);
- }
- else
- {
- *bytes_read += num_bytes;
- memcpy(output, input, num_bytes);
- }
- /* increment input pointer */
- input = (const uint8_t *)input + bytes_to_read;
- /* decrement sizes */
- frame_len -= num_bytes;
- input_len -= bytes_to_read;
- return true;
- }
- /* benski> this function is a bit complex
- we have two things to worry about, and can have any combination of the two
- 1) Is the data 'unsynchronized'
- 2) Is the data compressed (zlib)
- we keep track of three sizes:
- len - number of bytes in input buffer
- data_size - number of bytes of output data buffer
- frame_size - number of bytes of data in frame AFTER re-synchronization
- frame_size==data_size when compression is OFF
- */
- int ID3v2_3::Frame::Parse(const void *_data, size_t len, size_t *read)
- {
- *read = 0;
- size_t frame_size = header.FrameSize(); // size of frame AFTER re-synchronization
- if (header.Compressed())
- {
- // read 4 bytes of decompressed size
- uint8_t raw_size[4];
- if (ReadData(raw_size, _data, len, frame_size, 4, read) == false)
- return 1;
- bytereader_value_t byte_reader;
- bytereader_init(&byte_reader, raw_size, 4);
- data_size = bytereader_read_u32_be(&byte_reader);
- }
- /* Check for group identity. If this exists, we'll store it separate from the raw data */
- if (header.Grouped())
- {
- // read 1 byte for group identity
- if (ReadData(&group_identity, _data, len, frame_size, 1, read) == false)
- return 1;
- }
- if (!header.Compressed())
- {
- data_size = frame_size;
- }
- /* check to make sure that we have enough input data to read the data */
- if (!header.Compressed() && header.Unsynchronised())
- {
- /* this is tricky, because the stored size reflects after re-synchronization,
- but the incoming data is unsynchronized */
- if (ID3v2::Util::UnsynchronisedInputSize(_data, data_size) > len)
- return 1;
- }
- else if (frame_size > len)
- return 1;
- /* allocate memory (real data_size) */
- data = malloc(data_size);
- if (!data)
- return NErr_OutOfMemory;
- /* === Read the data === */
- if (header.Compressed())
- {
- if (header.Unsynchronised()) // compressed AND unsynchronized.. what a pain!!
- {
- // TODO: combined re-synchronization + inflation
- void *temp = malloc(frame_size);
- if (!temp)
- return NErr_OutOfMemory;
- *read += ID3v2::Util::UnsynchroniseTo(temp, _data, frame_size);
- uLongf uncompressedSize = data_size;
- int ret = uncompress((Bytef *)data, &uncompressedSize, (const Bytef *)temp, frame_size);
- free(temp);
- if (ret != Z_OK)
- return 1;
- }
- else
- {
- uLongf uncompressedSize = data_size;
- if (uncompress((Bytef *)data, &uncompressedSize, (const Bytef *)_data, frame_size) != Z_OK)
- return 1;
- *read += frame_size;
- }
- }
- else if (header.Unsynchronised())
- {
- *read += ID3v2::Util::UnsynchroniseTo(data, _data, data_size);
- }
- else // normal data
- {
- memcpy(data, _data, data_size);
- *read += data_size;
- }
- return NErr_Success;
- }
- int ID3v2_3::Frame::SerializedSize(uint32_t *length, const ID3v2::Header &tag_header, int flags) const
- {
- ID3v2_3::FrameHeader new_header(header, tag_header);
- // TODO: for now, we're not going to deal with compression
- new_header.ClearCompressed();
- new_header.SetSize(data_size);
- uint32_t current_length=0;
- new_header.SerializedSize(¤t_length);
- if (new_header.Unsynchronised())
- {
- if (new_header.Compressed())
- {
- uint8_t data_length[4];
- bytewriter_s byte_writer;
- bytewriter_init(&byte_writer, data_length, 4);
- bytewriter_write_u32_be(&byte_writer, data_size);
- current_length += ID3v2::Util::SynchronisedSize(&data_length, 4);
- }
- if (new_header.Grouped())
- current_length += ID3v2::Util::SynchronisedSize(&group_identity, 1);
- current_length += ID3v2::Util::SynchronisedSize(data, data_size);
- }
- else
- {
- current_length += new_header.FrameSize();
- }
- *length = current_length;
- return NErr_Success;
- }
- int ID3v2_3::Frame::Serialize(void *output, uint32_t *written, const ID3v2::Header &tag_header, int flags) const
- {
- size_t current_length = FrameHeaderBase::SIZE;
- uint8_t *data_ptr = (uint8_t *)output;
- ID3v2_3::FrameHeader new_header(header, tag_header);
- // TODO: for now, we're not going to deal with compression
- new_header.ClearCompressed();
- new_header.SetSize(data_size);
- // write frame header
- uint32_t header_size;
- new_header.Serialize(data_ptr, &header_size);
- data_ptr += header_size;
- if (new_header.Unsynchronised())
- {
- if (new_header.Compressed())
- {
- uint8_t data_length[4];
- bytewriter_s byte_writer;
- bytewriter_init(&byte_writer, data_length, 4);
- bytewriter_write_u32_be(&byte_writer, data_size);
- current_length += ID3v2::Util::SynchroniseTo(data_ptr, &data_length, 4);
- data_ptr+=4;
- }
- if (new_header.Grouped())
- current_length += ID3v2::Util::SynchroniseTo(data_ptr++, &group_identity, 1);
- current_length += ID3v2::Util::SynchroniseTo(data_ptr, data, data_size);
- }
- else
- {
- if (new_header.Compressed())
- {
- bytewriter_s byte_writer;
- bytewriter_init(&byte_writer, data_ptr, 4);
- bytewriter_write_u32_be(&byte_writer, data_size);
- data_ptr+=4;
- }
- if (new_header.Grouped())
- {
- *data_ptr++ = group_identity;
- current_length++;
- }
- memcpy(data_ptr, data, data_size);
- current_length += data_size;
- }
- *written = current_length;
- return NErr_Success;
- }
- const int8_t *ID3v2_3::Frame::GetIdentifier() const
- {
- return header.GetIdentifier();
- }
- bool ID3v2_3::Frame::Encrypted() const
- {
- return header.Encrypted();
- }
- bool ID3v2_3::Frame::Compressed() const
- {
- return header.Compressed();
- }
- bool ID3v2_3::Frame::Grouped() const
- {
- return header.Grouped();
- }
- bool ID3v2_3::Frame::ReadOnly() const
- {
- return header.ReadOnly();
- }
- bool ID3v2_3::Frame::TagAlterPreservation() const
- {
- return header.TagAlterPreservation();
- }
- bool ID3v2_3::Frame::FileAlterPreservation() const
- {
- return header.FileAlterPreservation();
- }
- /* === ID3v2.4 === */
- ID3v2_4::Frame::Frame(const ID3v2::Header &_header, const int8_t *id, int flags) : header(_header, id, flags)
- {
- }
- ID3v2_4::Frame::Frame(const FrameHeader &_header) : header(_header)
- {
- }
- /* helper function
- reads num_bytes from input into output, dealing with re-synchronization and length checking
- increments input pointer
- increments bytes_read value by number of input bytes read (different from num_bytes when data is unsynchronized
- decrements input_len by bytes read
- decrements output_len by bytes written
- */
- bool ID3v2_4::Frame::ReadData(void *output, const void *&input, size_t &input_len, size_t &frame_len, size_t num_bytes, size_t *bytes_read) const
- {
- /* verify that we have enough data in the frame */
- if (num_bytes > frame_len)
- return false;
- /* verify that we have enough data in the buffer */
- size_t bytes_to_read = num_bytes;
- if (bytes_to_read > input_len)
- return false;
- /* read data */
- *bytes_read += num_bytes;
- memcpy(output, input, num_bytes);
- /* increment input pointer */
- input = (const uint8_t *)input + bytes_to_read;
- /* decrement sizes */
- frame_len -= num_bytes;
- input_len -= bytes_to_read;
- return true;
- }
- /* benski> this function is a bit complex
- we have two things to worry about, and can have any combination of the two
- 1) Is the data 'unsynchronized'
- 2) Is the data compressed (zlib)
- we keep track of three sizes:
- len - number of bytes in input buffer
- data_size - number of bytes of output data buffer
- frame_size - number of bytes of data in frame AFTER re-synchronization
- frame_size==data_size when compression is OFF
- */
- int ID3v2_4::Frame::Parse(const void *_data, size_t len, size_t *read)
- {
- *read = 0;
- size_t frame_size = header.FrameSize();
- // TODO: if frame_size >= 128, verify size. iTunes v2.4 parser bug ...
- /* Check for group identity. If this exists, we'll store it separate from the raw data */
- /* Note: ID3v2.4 puts group identity BEFORE data length indicator, where as v2.3 has it the other way */
- if (header.Grouped())
- {
- // read 1 byte for group identity
- if (ReadData(&group_identity, _data, len, frame_size, 1, read) == false)
- return 1;
- }
- if (header.Compressed() || header.DataLengthIndicated())
- {
- // read 4 bytes of decompressed size
- uint8_t raw_size[4];
- if (ReadData(raw_size, _data, len, frame_size, 4, read) == false)
- return 1;
- bytereader_value_t byte_reader;
- bytereader_init(&byte_reader, raw_size, 4);
- data_size = bytereader_read_u32_be(&byte_reader);
- }
- if (!(header.Compressed() || header.DataLengthIndicated()))
- {
- data_size = frame_size;
- }
- /* check to make sure that we have enough input data to read the data */
- if (frame_size > len)
- return 1;
- if (!header.Compressed() && header.Unsynchronised())
- {
- data_size = ID3v2::Util::UnsynchronisedOutputSize(_data, frame_size);
- }
- /* allocate memory (real data_size) */
- data = malloc(data_size);
- if (!data)
- return NErr_OutOfMemory;
- /* === Read the data === */
- if (header.Compressed())
- {
- if (header.Unsynchronised()) // compressed AND unsynchronized.. what a pain!!
- {
- // TODO: combined re-synchronization + inflation
- size_t sync_size = ID3v2::Util::UnsynchronisedOutputSize(_data, frame_size);
- void *temp = malloc(sync_size);
- if (!temp)
- return NErr_OutOfMemory;
- *read += ID3v2::Util::UnsynchroniseTo(temp, _data, sync_size);
- uLongf uncompressedSize = data_size;
- int ret = uncompress((Bytef *)data, &uncompressedSize, (const Bytef *)temp, sync_size);
- /* TODO: realloc and set data_size to uncompressedSize if uncompressedSize was actually lower */
- free(temp);
- if (ret != Z_OK)
- return 1;
- }
- else
- {
- uLongf uncompressedSize = data_size;
- if (uncompress((Bytef *)data, &uncompressedSize, (const Bytef *)_data, frame_size) != Z_OK)
- return 1;
- /* TODO: realloc and set data_size to uncompressedSize if uncompressedSize was actually lower */
- *read += frame_size;
- }
- }
- else if (header.Unsynchronised())
- {
- *read += ID3v2::Util::UnsynchroniseTo(data, _data, data_size);
- }
- else // normal data
- {
- memcpy(data, _data, data_size);
- *read += data_size;
- }
- return 0;
- }
- int ID3v2_4::Frame::SerializedSize(uint32_t *length, const ID3v2::Header &tag_header, int flags) const
- {
- ID3v2_4::FrameHeader new_header(header, tag_header);
- // TODO: for now, we're not going to deal with compression
- new_header.ClearCompressed();
- switch(flags & Serialize_UnsynchronizeMask)
- {
- case Serialize_Unsynchronize:
- // TODO:
- break;
- case Serialize_NoUnsynchronize:
- new_header.ClearUnsynchronized();
- break;
- }
- // TODO: this doesn't handle compression
- if (new_header.Unsynchronised())
- {
- size_t unsynchronized_data_size = ID3v2::Util::SynchronisedSize(data, data_size);
- new_header.SetSize(unsynchronized_data_size);
- }
- else
- {
- new_header.SetSize(data_size);
- }
- size_t current_length = ID3v2_4::FrameHeader::SIZE;
- if (new_header.Unsynchronised())
- {
- if (new_header.DataLengthIndicated() || new_header.Compressed())
- {
- current_length += 4;
- }
- if (new_header.Grouped())
- current_length += ID3v2::Util::SynchronisedSize(&group_identity, 1);
- current_length += ID3v2::Util::SynchronisedSize(data, data_size);
- }
- else
- {
- current_length += new_header.FrameSize();
- }
- *length = current_length;
- return NErr_Success;
- }
- int ID3v2_4::Frame::Serialize(void *output, uint32_t *written, const ID3v2::Header &tag_header, int flags) const
- {
- size_t current_length = ID3v2_4::FrameHeader::SIZE;
- uint8_t *data_ptr = (uint8_t *)output;
- ID3v2_4::FrameHeader new_header(header, tag_header);
- // TODO: for now, we're not going to deal with compression
- new_header.ClearCompressed();
- switch(flags & Serialize_UnsynchronizeMask)
- {
- case Serialize_Unsynchronize:
- // TODO:
- break;
- case Serialize_NoUnsynchronize:
- new_header.ClearUnsynchronized();
- break;
- }
- // TODO: this doesn't handle compression
- if (new_header.Unsynchronised())
- {
- size_t unsynchronized_data_size = ID3v2::Util::SynchronisedSize(data, data_size);
- new_header.SetSize(unsynchronized_data_size);
- }
- else
- {
- new_header.SetSize(data_size);
- }
- // write frame header
- uint32_t header_size;
- new_header.Serialize(data_ptr, &header_size);
- data_ptr += header_size;
- if (new_header.Compressed() || new_header.DataLengthIndicated())
- {
- bytewriter_s byte_writer;
- bytewriter_init(&byte_writer, data_ptr, 4);
- bytewriter_write_u32_be(&byte_writer, ID3v2::Util::Int32To28(data_size));
- data_ptr+=4;
- current_length+=4;
- }
- if (new_header.Unsynchronised())
- {
- if (Grouped())
- current_length += ID3v2::Util::SynchroniseTo(data_ptr++, &group_identity, 1);
- current_length += ID3v2::Util::SynchroniseTo(data_ptr, data, data_size);
- }
- else
- {
- if (new_header.Grouped())
- {
- *data_ptr++ = group_identity;
- current_length++;
- }
- memcpy(data_ptr, data, data_size);
- current_length += data_size;
- }
- *written = current_length;
- return NErr_Success;
- }
- const int8_t *ID3v2_4::Frame::GetIdentifier() const
- {
- return header.GetIdentifier();
- }
- bool ID3v2_4::Frame::Encrypted() const
- {
- return header.Encrypted();
- }
- bool ID3v2_4::Frame::Compressed() const
- {
- return header.Compressed();
- }
- bool ID3v2_4::Frame::Grouped() const
- {
- return header.Grouped();
- }
- bool ID3v2_4::Frame::ReadOnly() const
- {
- return header.ReadOnly();
- }
- bool ID3v2_4::Frame::FrameUnsynchronised() const
- {
- return header.FrameUnsynchronised();
- }
- bool ID3v2_4::Frame::DataLengthIndicated() const
- {
- return header.DataLengthIndicated();
- }
- bool ID3v2_4::Frame::TagAlterPreservation() const
- {
- return header.TagAlterPreservation();
- }
- bool ID3v2_4::Frame::FileAlterPreservation() const
- {
- return header.FileAlterPreservation();
- }
|