diff options
Diffstat (limited to 'libid3tag/frame.c')
-rw-r--r-- | libid3tag/frame.c | 1036 |
1 files changed, 548 insertions, 488 deletions
diff --git a/libid3tag/frame.c b/libid3tag/frame.c index 1c680d9..bf4e7a4 100644 --- a/libid3tag/frame.c +++ b/libid3tag/frame.c @@ -19,608 +19,668 @@ * $Id: frame.c,v 1.15 2004/01/23 09:41:32 rob Exp $ */ -# ifdef HAVE_CONFIG_H -# include "config.h" -# endif - -# include "global.h" - -# include <stdlib.h> -# include <string.h> - -# ifdef HAVE_ASSERT_H -# include <assert.h> -# endif - -# include "id3tag.h" -# include "frame.h" -# include "frametype.h" -# include "compat.h" -# include "field.h" -# include "render.h" -# include "parse.h" -# include "util.h" - -static -int valid_idchar(char c) +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "global.h" + +#include <stdlib.h> +#include <string.h> + +#ifdef HAVE_ASSERT_H +# include <assert.h> +#endif + +#include "id3tag.h" +#include "frame.h" +#include "frametype.h" +#include "compat.h" +#include "field.h" +#include "render.h" +#include "parse.h" +#include "util.h" + +static int +valid_idchar(char c) { - return (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); + return (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); } /* - * NAME: frame->validid() - * DESCRIPTION: return true if the parameter string is a legal frame ID + * NAME: frame->validid() + * DESCRIPTION: return true if the parameter string is a legal frame ID */ -int id3_frame_validid(char const *id) +int +id3_frame_validid(char const *id) { - return id && - valid_idchar(id[0]) && - valid_idchar(id[1]) && - valid_idchar(id[2]) && - valid_idchar(id[3]); + return id && + valid_idchar(id[0]) && + valid_idchar(id[1]) && + valid_idchar(id[2]) && valid_idchar(id[3]); } /* - * NAME: frame->new() - * DESCRIPTION: allocate and return a new frame + * NAME: frame->new() + * DESCRIPTION: allocate and return a new frame */ -struct id3_frame *id3_frame_new(char const *id) +struct id3_frame * +id3_frame_new(char const *id) { - struct id3_frametype const *frametype; - struct id3_frame *frame; - unsigned int i; - - if (!id3_frame_validid(id)) - return 0; - - frametype = id3_frametype_lookup(id, 4); - if (frametype == 0) { - switch (id[0]) { - case 'T': - frametype = &id3_frametype_text; - break; - - case 'W': - frametype = &id3_frametype_url; - break; - - case 'X': - case 'Y': - case 'Z': - frametype = &id3_frametype_experimental; - break; - - default: - frametype = &id3_frametype_unknown; - if (id3_compat_lookup(id, 4)) - frametype = &id3_frametype_obsolete; - break; - } - } - - frame = malloc(sizeof(*frame) + frametype->nfields * sizeof(*frame->fields)); - if (frame) { - frame->id[0] = id[0]; - frame->id[1] = id[1]; - frame->id[2] = id[2]; - frame->id[3] = id[3]; - frame->id[4] = 0; - - frame->description = frametype->description; - frame->refcount = 0; - frame->flags = frametype->defaultflags; - frame->group_id = 0; - frame->encryption_method = 0; - frame->encoded = 0; - frame->encoded_length = 0; - frame->decoded_length = 0; - frame->nfields = frametype->nfields; - frame->fields = (union id3_field *) &frame[1]; - - for (i = 0; i < frame->nfields; ++i) - id3_field_init(&frame->fields[i], frametype->fields[i]); - } - - return frame; + struct id3_frametype const *frametype; + struct id3_frame *frame; + unsigned int i; + + if (!id3_frame_validid(id)) + return 0; + + frametype = id3_frametype_lookup(id, 4); + if (frametype == 0) { + switch (id[0]) { + case 'T': + frametype = &id3_frametype_text; + break; + + case 'W': + frametype = &id3_frametype_url; + break; + + case 'X': + case 'Y': + case 'Z': + frametype = &id3_frametype_experimental; + break; + + default: + frametype = &id3_frametype_unknown; + if (id3_compat_lookup(id, 4)) + frametype = &id3_frametype_obsolete; + break; + } + } + + frame = + malloc(sizeof(*frame) + + frametype->nfields * sizeof(*frame->fields)); + if (frame) { + frame->id[0] = id[0]; + frame->id[1] = id[1]; + frame->id[2] = id[2]; + frame->id[3] = id[3]; + frame->id[4] = 0; + + frame->description = frametype->description; + frame->refcount = 0; + frame->flags = frametype->defaultflags; + frame->group_id = 0; + frame->encryption_method = 0; + frame->encoded = 0; + frame->encoded_length = 0; + frame->decoded_length = 0; + frame->nfields = frametype->nfields; + frame->fields = (union id3_field *) &frame[1]; + + for (i = 0; i < frame->nfields; ++i) + id3_field_init(&frame->fields[i], + frametype->fields[i]); + } + + return frame; } -void id3_frame_delete(struct id3_frame *frame) +void +id3_frame_delete(struct id3_frame *frame) { - assert(frame); + assert(frame); - if (frame->refcount == 0) { - unsigned int i; + if (frame->refcount == 0) { + unsigned int i; - for (i = 0; i < frame->nfields; ++i) - id3_field_finish(&frame->fields[i]); + for (i = 0; i < frame->nfields; ++i) + id3_field_finish(&frame->fields[i]); - if (frame->encoded) - free(frame->encoded); + if (frame->encoded) + free(frame->encoded); - free(frame); - } + free(frame); + } } /* - * NAME: frame->addref() - * DESCRIPTION: add an external reference to a frame + * NAME: frame->addref() + * DESCRIPTION: add an external reference to a frame */ -void id3_frame_addref(struct id3_frame *frame) +void +id3_frame_addref(struct id3_frame *frame) { - assert(frame); + assert(frame); - ++frame->refcount; + ++frame->refcount; } /* - * NAME: frame->delref() - * DESCRIPTION: remove an external reference to a frame + * NAME: frame->delref() + * DESCRIPTION: remove an external reference to a frame */ -void id3_frame_delref(struct id3_frame *frame) +void +id3_frame_delref(struct id3_frame *frame) { - assert(frame && frame->refcount > 0); + assert(frame && frame->refcount > 0); - --frame->refcount; + --frame->refcount; } /* - * NAME: frame->field() - * DESCRIPTION: return a pointer to a field in a frame + * NAME: frame->field() + * DESCRIPTION: return a pointer to a field in a frame */ -union id3_field *id3_frame_field(struct id3_frame const *frame, - unsigned int index) +union id3_field * +id3_frame_field(struct id3_frame const *frame, unsigned int index) { - assert(frame); - - return (index < frame->nfields) ? &frame->fields[index] : 0; -} + assert(frame); -static -struct id3_frame *obsolete(char const *id, id3_byte_t const *data, - id3_length_t length) -{ - struct id3_frame *frame; - - frame = id3_frame_new(ID3_FRAME_OBSOLETE); - if (frame) { - if (id3_field_setframeid(&frame->fields[0], id) == -1 || - id3_field_setbinarydata(&frame->fields[1], data, length) == -1) - goto fail; - } - - if (0) { - fail: - if (frame) { - id3_frame_delete(frame); - frame = 0; - } - } - - return frame; + return (index < frame->nfields) ? &frame->fields[index] : 0; } -static -struct id3_frame *unparseable(char const *id, id3_byte_t const **ptr, - id3_length_t length, int flags, - int group_id, int encryption_method, - id3_length_t decoded_length) +static struct id3_frame * +obsolete(char const *id, id3_byte_t const *data, id3_length_t length) { - struct id3_frame *frame = 0; - id3_byte_t *mem; - - mem = malloc(length ? length : 1); - if (mem == 0) - goto fail; - - frame = id3_frame_new(id); - if (frame == 0) - free(mem); - else { - memcpy(mem, *ptr, length); - - frame->flags = flags; - frame->group_id = group_id; - frame->encryption_method = encryption_method; - frame->encoded = mem; - frame->encoded_length = length; - frame->decoded_length = decoded_length; - } - - if (0) { - fail: - ; - } - - *ptr += length; - - return frame; -} - -static -int parse_data(struct id3_frame *frame, - id3_byte_t const *data, id3_length_t length) -{ - enum id3_field_textencoding encoding; - id3_byte_t const *end; - unsigned int i; - - encoding = ID3_FIELD_TEXTENCODING_ISO_8859_1; - - end = data + length; + struct id3_frame *frame; + + frame = id3_frame_new(ID3_FRAME_OBSOLETE); + if (frame) { + if (id3_field_setframeid(&frame->fields[0], id) == -1 || + id3_field_setbinarydata(&frame->fields[1], data, + length) == -1) + goto fail; + } - for (i = 0; i < frame->nfields; ++i) { - if (id3_field_parse(&frame->fields[i], &data, end - data, &encoding) == -1) - return -1; - } + if (0) { + fail: + if (frame) { + id3_frame_delete(frame); + frame = 0; + } + } - return 0; + return frame; } -/* - * NAME: frame->parse() - * DESCRIPTION: parse raw frame data according to the specified ID3 tag version - */ -struct id3_frame *id3_frame_parse(id3_byte_t const **ptr, id3_length_t length, - unsigned int version) +static struct id3_frame * +unparseable(char const *id, id3_byte_t const **ptr, + id3_length_t length, int flags, + int group_id, int encryption_method, + id3_length_t decoded_length) { - struct id3_frame *frame = 0; - id3_byte_t const *id, *end, *data; - id3_length_t size, decoded_length = 0; - int flags = 0, group_id = 0, encryption_method = 0; - struct id3_compat const *compat = 0; - id3_byte_t *mem = 0; - char xid[4]; - - id = *ptr; - end = *ptr + length; - - if (ID3_TAG_VERSION_MAJOR(version) < 4) { - switch (ID3_TAG_VERSION_MAJOR(version)) { - case 2: - if (length < 6) - goto fail; - - compat = id3_compat_lookup(id, 3); - - *ptr += 3; - size = id3_parse_uint(ptr, 3); - - if (size > end - *ptr) - goto fail; - - end = *ptr + size; - - break; - - case 3: - if (length < 10) - goto fail; - - compat = id3_compat_lookup(id, 4); - - *ptr += 4; - size = id3_parse_uint(ptr, 4); - flags = id3_parse_uint(ptr, 2); - - if (size > end - *ptr) - goto fail; - - end = *ptr + size; - - if (flags & (ID3_FRAME_FLAG_FORMATFLAGS & ~0x00e0)) { - frame = unparseable(id, ptr, end - *ptr, 0, 0, 0, 0); - goto done; - } + struct id3_frame *frame = 0; + id3_byte_t *mem; - flags = - ((flags >> 1) & ID3_FRAME_FLAG_STATUSFLAGS) | - ((flags >> 4) & (ID3_FRAME_FLAG_COMPRESSION | - ID3_FRAME_FLAG_ENCRYPTION)) | - ((flags << 1) & ID3_FRAME_FLAG_GROUPINGIDENTITY); + mem = malloc(length ? length : 1); + if (mem == 0) + goto fail; - if (flags & ID3_FRAME_FLAG_COMPRESSION) { - if (end - *ptr < 4) - goto fail; - - decoded_length = id3_parse_uint(ptr, 4); - } + frame = id3_frame_new(id); + if (frame == 0) + free(mem); + else { + memcpy(mem, *ptr, length); + + frame->flags = flags; + frame->group_id = group_id; + frame->encryption_method = encryption_method; + frame->encoded = mem; + frame->encoded_length = length; + frame->decoded_length = decoded_length; + } - if (flags & ID3_FRAME_FLAG_ENCRYPTION) { - if (end - *ptr < 1) - goto fail; + if (0) { + fail: + ; + } - encryption_method = id3_parse_uint(ptr, 1); - } + *ptr += length; - if (flags & ID3_FRAME_FLAG_GROUPINGIDENTITY) { - if (end - *ptr < 1) - goto fail; + return frame; +} - group_id = id3_parse_uint(ptr, 1); - } +static int +parse_data(struct id3_frame *frame, + id3_byte_t const *data, id3_length_t length) +{ + enum id3_field_textencoding encoding; + id3_byte_t const *end; + unsigned int i; - break; + encoding = ID3_FIELD_TEXTENCODING_ISO_8859_1; - default: - goto fail; - } + end = data + length; - /* canonicalize frame ID for ID3v2.4 */ + for (i = 0; i < frame->nfields; ++i) { + if (id3_field_parse + (&frame->fields[i], &data, end - data, + &encoding) == -1) + return -1; + } - if (compat && compat->equiv) - id = compat->equiv; - else if (ID3_TAG_VERSION_MAJOR(version) == 2) { - xid[0] = 'Y'; - xid[1] = id[0]; - xid[2] = id[1]; - xid[3] = id[2]; + return 0; +} - id = xid; +/* + * NAME: frame->parse() + * DESCRIPTION: parse raw frame data according to the specified ID3 tag version + */ +struct id3_frame * +id3_frame_parse(id3_byte_t const **ptr, id3_length_t length, + unsigned int version) +{ + struct id3_frame *frame = 0; + id3_byte_t const *id, + *end, + *data; + id3_length_t size, + decoded_length = 0; + int flags = 0, + group_id = 0, + encryption_method = 0; + struct id3_compat const *compat = 0; + id3_byte_t *mem = 0; + char xid[4]; + + id = *ptr; + end = *ptr + length; + + if (ID3_TAG_VERSION_MAJOR(version) < 4) { + switch (ID3_TAG_VERSION_MAJOR(version)) { + case 2: + if (length < 6) + goto fail; - flags |= - ID3_FRAME_FLAG_TAGALTERPRESERVATION | - ID3_FRAME_FLAG_FILEALTERPRESERVATION; - } - } - else { /* ID3v2.4 */ - if (length < 10) - goto fail; + compat = id3_compat_lookup(id, 3); + + *ptr += 3; + size = id3_parse_uint(ptr, 3); + + if (size > end - *ptr) + goto fail; + + end = *ptr + size; + + break; + + case 3: + if (length < 10) + goto fail; + + compat = id3_compat_lookup(id, 4); + + *ptr += 4; + size = id3_parse_uint(ptr, 4); + flags = id3_parse_uint(ptr, 2); + + if (size > end - *ptr) + goto fail; + + end = *ptr + size; + + if (flags & (ID3_FRAME_FLAG_FORMATFLAGS & ~0x00e0)) { + frame = + unparseable(id, ptr, end - *ptr, 0, 0, + 0, 0); + goto done; + } + + flags = + ((flags >> 1) & ID3_FRAME_FLAG_STATUSFLAGS) | + ((flags >> 4) & (ID3_FRAME_FLAG_COMPRESSION | + ID3_FRAME_FLAG_ENCRYPTION)) | + ((flags << 1) & + ID3_FRAME_FLAG_GROUPINGIDENTITY); + + if (flags & ID3_FRAME_FLAG_COMPRESSION) { + if (end - *ptr < 4) + goto fail; + + decoded_length = id3_parse_uint(ptr, 4); + } + + if (flags & ID3_FRAME_FLAG_ENCRYPTION) { + if (end - *ptr < 1) + goto fail; + + encryption_method = id3_parse_uint(ptr, 1); + } + + if (flags & ID3_FRAME_FLAG_GROUPINGIDENTITY) { + if (end - *ptr < 1) + goto fail; + + group_id = id3_parse_uint(ptr, 1); + } + + break; + + default: + goto fail; + } + + /* + * canonicalize frame ID for ID3v2.4 + */ + + if (compat && compat->equiv) + id = compat->equiv; + else if (ID3_TAG_VERSION_MAJOR(version) == 2) { + xid[0] = 'Y'; + xid[1] = id[0]; + xid[2] = id[1]; + xid[3] = id[2]; + + id = xid; - *ptr += 4; - size = id3_parse_syncsafe(ptr, 4); - flags = id3_parse_uint(ptr, 2); + flags |= + ID3_FRAME_FLAG_TAGALTERPRESERVATION | + ID3_FRAME_FLAG_FILEALTERPRESERVATION; + } + } else { /* ID3v2.4 */ + if (length < 10) + goto fail; - if (size > end - *ptr) - goto fail; + *ptr += 4; + size = id3_parse_syncsafe(ptr, 4); + flags = id3_parse_uint(ptr, 2); - end = *ptr + size; + if (size > end - *ptr) + goto fail; - if (flags & (ID3_FRAME_FLAG_FORMATFLAGS & ~ID3_FRAME_FLAG_KNOWNFLAGS)) { - frame = unparseable(id, ptr, end - *ptr, flags, 0, 0, 0); - goto done; - } + end = *ptr + size; - if (flags & ID3_FRAME_FLAG_GROUPINGIDENTITY) { - if (end - *ptr < 1) - goto fail; + if (flags & + (ID3_FRAME_FLAG_FORMATFLAGS & + ~ID3_FRAME_FLAG_KNOWNFLAGS)) { + frame = + unparseable(id, ptr, end - *ptr, flags, 0, 0, + 0); + goto done; + } - group_id = id3_parse_uint(ptr, 1); - } + if (flags & ID3_FRAME_FLAG_GROUPINGIDENTITY) { + if (end - *ptr < 1) + goto fail; - if ((flags & ID3_FRAME_FLAG_COMPRESSION) && - !(flags & ID3_FRAME_FLAG_DATALENGTHINDICATOR)) - goto fail; + group_id = id3_parse_uint(ptr, 1); + } - if (flags & ID3_FRAME_FLAG_ENCRYPTION) { - if (end - *ptr < 1) - goto fail; + if ((flags & ID3_FRAME_FLAG_COMPRESSION) && + !(flags & ID3_FRAME_FLAG_DATALENGTHINDICATOR)) + goto fail; + + if (flags & ID3_FRAME_FLAG_ENCRYPTION) { + if (end - *ptr < 1) + goto fail; + + encryption_method = id3_parse_uint(ptr, 1); + } + + if (flags & ID3_FRAME_FLAG_DATALENGTHINDICATOR) { + if (end - *ptr < 4) + goto fail; + + decoded_length = id3_parse_syncsafe(ptr, 4); + } + } - encryption_method = id3_parse_uint(ptr, 1); - } + data = *ptr; + *ptr = end; - if (flags & ID3_FRAME_FLAG_DATALENGTHINDICATOR) { - if (end - *ptr < 4) - goto fail; + /* + * undo frame encodings + */ - decoded_length = id3_parse_syncsafe(ptr, 4); - } - } + if ((flags & ID3_FRAME_FLAG_UNSYNCHRONISATION) && end - data > 0) { + mem = malloc(end - data); + if (mem == 0) + goto fail; - data = *ptr; - *ptr = end; + memcpy(mem, data, end - data); - /* undo frame encodings */ + end = mem + id3_util_deunsynchronise(mem, end - data); + data = mem; + } - if ((flags & ID3_FRAME_FLAG_UNSYNCHRONISATION) && end - data > 0) { - mem = malloc(end - data); - if (mem == 0) - goto fail; + if (flags & ID3_FRAME_FLAG_ENCRYPTION) { + frame = unparseable(id, &data, end - data, flags, + group_id, encryption_method, + decoded_length); + goto done; + } - memcpy(mem, data, end - data); + if (flags & ID3_FRAME_FLAG_COMPRESSION) { + id3_byte_t *decomp; - end = mem + id3_util_deunsynchronise(mem, end - data); - data = mem; - } + decomp = + id3_util_decompress(data, end - data, decoded_length); + if (decomp == 0) + goto fail; - if (flags & ID3_FRAME_FLAG_ENCRYPTION) { - frame = unparseable(id, &data, end - data, flags, - group_id, encryption_method, decoded_length); - goto done; - } + if (mem) + free(mem); - if (flags & ID3_FRAME_FLAG_COMPRESSION) { - id3_byte_t *decomp; + data = mem = decomp; + end = data + decoded_length; + } - decomp = id3_util_decompress(data, end - data, decoded_length); - if (decomp == 0) - goto fail; + /* + * check for obsolescence + */ - if (mem) - free(mem); + if (compat && !compat->equiv) { + frame = obsolete(id, data, end - data); + goto done; + } - data = mem = decomp; - end = data + decoded_length; - } - - /* check for obsolescence */ - - if (compat && !compat->equiv) { - frame = obsolete(id, data, end - data); - goto done; - } - - /* generate the internal frame structure */ - - frame = id3_frame_new(id); - if (frame) { - frame->flags = flags; - frame->group_id = group_id; - - if (compat && compat->translate) { - if (compat->translate(frame, compat->id, data, end - data) == -1) - goto fail; - } - else { - if (parse_data(frame, data, end - data) == -1) - goto fail; - } - } + /* + * generate the internal frame structure + */ + + frame = id3_frame_new(id); + if (frame) { + frame->flags = flags; + frame->group_id = group_id; + + if (compat && compat->translate) { + if (compat->translate(frame, compat->id, data, + end - data) == -1) + goto fail; + } else { + if (parse_data(frame, data, end - data) == -1) + goto fail; + } + } - if (0) { - fail: - if (frame) { - id3_frame_delete(frame); - frame = 0; - } - } + if (0) { + fail: + if (frame) { + id3_frame_delete(frame); + frame = 0; + } + } - done: - if (mem) - free(mem); + done: + if (mem) + free(mem); - return frame; + return frame; } -static -id3_length_t render_data(id3_byte_t **ptr, - union id3_field *fields, unsigned int length) +static id3_length_t +render_data(id3_byte_t ** ptr, + union id3_field *fields, unsigned int length) { - id3_length_t size = 0; - enum id3_field_textencoding encoding; - unsigned int i; + id3_length_t size = 0; + enum id3_field_textencoding encoding; + unsigned int i; - encoding = ID3_FIELD_TEXTENCODING_ISO_8859_1; + encoding = ID3_FIELD_TEXTENCODING_ISO_8859_1; - for (i = 0; i < length; ++i) - size += id3_field_render(&fields[i], ptr, &encoding, i < length - 1); + for (i = 0; i < length; ++i) + size += + id3_field_render(&fields[i], ptr, &encoding, + i < length - 1); - return size; + return size; } /* - * NAME: frame->render() - * DESCRIPTION: render a single, complete frame + * NAME: frame->render() + * DESCRIPTION: render a single, complete frame */ -id3_length_t id3_frame_render(struct id3_frame const *frame, - id3_byte_t **ptr, int options) +id3_length_t +id3_frame_render(struct id3_frame const *frame, + id3_byte_t ** ptr, int options) { - id3_length_t size = 0, decoded_length, datalen; - id3_byte_t *size_ptr = 0, *flags_ptr = 0, *data = 0; - int flags; - - assert(frame); + id3_length_t size = 0, + decoded_length, + datalen; + id3_byte_t *size_ptr = 0, + *flags_ptr = 0, + *data = 0; + int flags; - if ((frame->flags & ID3_FRAME_FLAG_TAGALTERPRESERVATION) || - ((options & ID3_TAG_OPTION_FILEALTERED) && - (frame->flags & ID3_FRAME_FLAG_FILEALTERPRESERVATION))) - return 0; + assert(frame); - /* a frame must be at least 1 byte big, excluding the header */ + if ((frame->flags & ID3_FRAME_FLAG_TAGALTERPRESERVATION) || + ((options & ID3_TAG_OPTION_FILEALTERED) && + (frame->flags & ID3_FRAME_FLAG_FILEALTERPRESERVATION))) + return 0; - decoded_length = render_data(0, frame->fields, frame->nfields); - if (decoded_length == 0 && frame->encoded == 0) - return 0; + /* + * a frame must be at least 1 byte big, excluding the header + */ - /* header */ + decoded_length = render_data(0, frame->fields, frame->nfields); + if (decoded_length == 0 && frame->encoded == 0) + return 0; - size += id3_render_immediate(ptr, frame->id, 4); + /* + * header + */ - if (ptr) - size_ptr = *ptr; + size += id3_render_immediate(ptr, frame->id, 4); - size += id3_render_syncsafe(ptr, 0, 4); + if (ptr) + size_ptr = *ptr; - if (ptr) - flags_ptr = *ptr; + size += id3_render_syncsafe(ptr, 0, 4); - flags = frame->flags; + if (ptr) + flags_ptr = *ptr; - size += id3_render_int(ptr, flags, 2); + flags = frame->flags; - if (flags & (ID3_FRAME_FLAG_FORMATFLAGS & ~ID3_FRAME_FLAG_KNOWNFLAGS)) { - size += id3_render_binary(ptr, frame->encoded, frame->encoded_length); - if (size_ptr) - id3_render_syncsafe(&size_ptr, size - 10, 4); + size += id3_render_int(ptr, flags, 2); - return size; - } + if (flags & + (ID3_FRAME_FLAG_FORMATFLAGS & ~ID3_FRAME_FLAG_KNOWNFLAGS)) { + size += + id3_render_binary(ptr, frame->encoded, + frame->encoded_length); + if (size_ptr) + id3_render_syncsafe(&size_ptr, size - 10, 4); - flags &= ID3_FRAME_FLAG_KNOWNFLAGS; - - flags &= ~ID3_FRAME_FLAG_UNSYNCHRONISATION; - if (options & ID3_TAG_OPTION_UNSYNCHRONISATION) - flags |= ID3_FRAME_FLAG_UNSYNCHRONISATION; - - if (!(flags & ID3_FRAME_FLAG_ENCRYPTION)) { - flags &= ~ID3_FRAME_FLAG_COMPRESSION; - if (options & ID3_TAG_OPTION_COMPRESSION) - flags |= ID3_FRAME_FLAG_COMPRESSION | ID3_FRAME_FLAG_DATALENGTHINDICATOR; - } + return size; + } - if (flags & ID3_FRAME_FLAG_GROUPINGIDENTITY) - size += id3_render_int(ptr, frame->group_id, 1); - if (flags & ID3_FRAME_FLAG_ENCRYPTION) - size += id3_render_int(ptr, frame->encryption_method, 1); - if (flags & ID3_FRAME_FLAG_DATALENGTHINDICATOR) { - if (flags & ID3_FRAME_FLAG_ENCRYPTION) - decoded_length = frame->decoded_length; - size += id3_render_syncsafe(ptr, decoded_length, 4); - } + flags &= ID3_FRAME_FLAG_KNOWNFLAGS; - if (ptr) - data = *ptr; + flags &= ~ID3_FRAME_FLAG_UNSYNCHRONISATION; + if (options & ID3_TAG_OPTION_UNSYNCHRONISATION) + flags |= ID3_FRAME_FLAG_UNSYNCHRONISATION; + + if (!(flags & ID3_FRAME_FLAG_ENCRYPTION)) { + flags &= ~ID3_FRAME_FLAG_COMPRESSION; + if (options & ID3_TAG_OPTION_COMPRESSION) + flags |= + ID3_FRAME_FLAG_COMPRESSION | + ID3_FRAME_FLAG_DATALENGTHINDICATOR; + } - if (flags & ID3_FRAME_FLAG_ENCRYPTION) - datalen = id3_render_binary(ptr, frame->encoded, frame->encoded_length); - else { - if (ptr == 0) - datalen = decoded_length; - else { - datalen = render_data(ptr, frame->fields, frame->nfields); + if (flags & ID3_FRAME_FLAG_GROUPINGIDENTITY) + size += id3_render_int(ptr, frame->group_id, 1); + if (flags & ID3_FRAME_FLAG_ENCRYPTION) + size += id3_render_int(ptr, frame->encryption_method, 1); + if (flags & ID3_FRAME_FLAG_DATALENGTHINDICATOR) { + if (flags & ID3_FRAME_FLAG_ENCRYPTION) + decoded_length = frame->decoded_length; + size += id3_render_syncsafe(ptr, decoded_length, 4); + } - if (flags & ID3_FRAME_FLAG_COMPRESSION) { - id3_byte_t *comp; - id3_length_t complen; + if (ptr) + data = *ptr; - comp = id3_util_compress(data, datalen, &complen); - if (comp == 0) - flags &= ~ID3_FRAME_FLAG_COMPRESSION; + if (flags & ID3_FRAME_FLAG_ENCRYPTION) + datalen = + id3_render_binary(ptr, frame->encoded, + frame->encoded_length); else { - *ptr = data; - datalen = id3_render_binary(ptr, comp, complen); - - free(comp); + if (ptr == 0) + datalen = decoded_length; + else { + datalen = + render_data(ptr, frame->fields, + frame->nfields); + + if (flags & ID3_FRAME_FLAG_COMPRESSION) { + id3_byte_t *comp; + id3_length_t complen; + + comp = + id3_util_compress(data, datalen, + &complen); + if (comp == 0) + flags &= + ~ID3_FRAME_FLAG_COMPRESSION; + else { + *ptr = data; + datalen = + id3_render_binary(ptr, comp, + complen); + + free(comp); + } + } + } } - } - } - } - - /* unsynchronisation */ - if (flags & ID3_FRAME_FLAG_UNSYNCHRONISATION) { - if (data == 0) - datalen *= 2; - else { - id3_length_t newlen; - - newlen = id3_util_unsynchronise(data, datalen); - if (newlen == datalen) - flags &= ~ID3_FRAME_FLAG_UNSYNCHRONISATION; - else { - *ptr += newlen - datalen; - datalen = newlen; - } - } - } + /* + * unsynchronisation + */ + + if (flags & ID3_FRAME_FLAG_UNSYNCHRONISATION) { + if (data == 0) + datalen *= 2; + else { + id3_length_t newlen; + + newlen = id3_util_unsynchronise(data, datalen); + if (newlen == datalen) + flags &= ~ID3_FRAME_FLAG_UNSYNCHRONISATION; + else { + *ptr += newlen - datalen; + datalen = newlen; + } + } + } - size += datalen; + size += datalen; - /* patch size and flags */ + /* + * patch size and flags + */ - if (size_ptr) - id3_render_syncsafe(&size_ptr, size - 10, 4); - if (flags_ptr) - id3_render_int(&flags_ptr, flags, 2); + if (size_ptr) + id3_render_syncsafe(&size_ptr, size - 10, 4); + if (flags_ptr) + id3_render_int(&flags_ptr, flags, 2); - return size; + return size; } |