45int valid_idchar(
char c)
47 return (c >=
'A' && c <=
'Z') || (c >=
'0' && c <=
'9');
54int id3_frame_validid(
char const *
id)
57 valid_idchar(
id[0]) &&
58 valid_idchar(
id[1]) &&
59 valid_idchar(
id[2]) &&
67struct id3_frame *id3_frame_new(
char const *
id)
73 if (!id3_frame_validid(
id))
76 frametype = id3_frametype_lookup(
id, 4);
80 frametype = &id3_frametype_text;
84 frametype = &id3_frametype_url;
90 frametype = &id3_frametype_experimental;
94 frametype = &id3_frametype_unknown;
95 if (id3_compat_lookup(
id, 4))
96 frametype = &id3_frametype_obsolete;
101 frame = malloc(
sizeof(*frame) + frametype->nfields *
sizeof(*frame->fields));
103 frame->id[0] =
id[0];
104 frame->id[1] =
id[1];
105 frame->id[2] =
id[2];
106 frame->id[3] =
id[3];
109 frame->description = frametype->description;
111 frame->flags = frametype->defaultflags;
113 frame->encryption_method = 0;
115 frame->encoded_length = 0;
116 frame->decoded_length = 0;
117 frame->nfields = frametype->nfields;
118 frame->fields = (
union id3_field *) &frame[1];
120 for (i = 0; i < frame->nfields; ++i)
121 id3_field_init(&frame->fields[i], frametype->fields[i]);
127void id3_frame_delete(
struct id3_frame *frame)
131 if (frame->refcount == 0) {
134 for (i = 0; i < frame->nfields; ++i)
135 id3_field_finish(&frame->fields[i]);
138 free(frame->encoded);
148void id3_frame_addref(
struct id3_frame *frame)
159void id3_frame_delref(
struct id3_frame *frame)
161 assert(frame && frame->refcount > 0);
175 return (index < frame->nfields) ? &frame->fields[index] : 0;
179struct id3_frame *obsolete(
char const *
id, id3_byte_t
const *data,
184 frame = id3_frame_new(ID3_FRAME_OBSOLETE);
186 if (id3_field_setframeid(&frame->fields[0],
id) == -1 ||
187 id3_field_setbinarydata(&frame->fields[1], data, length) == -1)
194 id3_frame_delete(frame);
203struct id3_frame *unparseable(
char const *
id, id3_byte_t
const **ptr,
204 id3_length_t length,
int flags,
205 int group_id,
int encryption_method,
206 id3_length_t decoded_length)
211 mem = malloc(length ? length : 1);
215 frame = id3_frame_new(
id);
219 memcpy(mem, *ptr, length);
221 frame->flags = flags;
222 frame->group_id = group_id;
223 frame->encryption_method = encryption_method;
224 frame->encoded = mem;
225 frame->encoded_length = length;
226 frame->decoded_length = decoded_length;
241 id3_byte_t
const *data, id3_length_t length)
243 enum id3_field_textencoding encoding;
244 id3_byte_t
const *end;
247 encoding = ID3_FIELD_TEXTENCODING_ISO_8859_1;
251 for (i = 0; i < frame->nfields; ++i) {
252 if (id3_field_parse(&frame->fields[i], &data, end - data, &encoding) == -1)
263struct id3_frame *id3_frame_parse(id3_byte_t
const **ptr, id3_length_t length,
264 unsigned int version)
267 id3_byte_t
const *id, *end, *data;
268 id3_length_t size, decoded_length = 0;
269 int flags = 0, group_id = 0, encryption_method = 0;
277 if (ID3_TAG_VERSION_MAJOR(version) < 4) {
278 switch (ID3_TAG_VERSION_MAJOR(version)) {
283 compat = id3_compat_lookup((
const char *)
id, 3);
286 size = id3_parse_uint(ptr, 3);
288 if (size > end - *ptr)
299 compat = id3_compat_lookup((
const char *)
id, 4);
302 size = id3_parse_uint(ptr, 4);
303 flags = id3_parse_uint(ptr, 2);
305 if (size > end - *ptr)
310 if (flags & (ID3_FRAME_FLAG_FORMATFLAGS & ~0x00e0)) {
311 frame = unparseable((
const char *)
id, ptr, end - *ptr, 0, 0, 0, 0);
316 ((flags >> 1) & ID3_FRAME_FLAG_STATUSFLAGS) |
317 ((flags >> 4) & (ID3_FRAME_FLAG_COMPRESSION |
318 ID3_FRAME_FLAG_ENCRYPTION)) |
319 ((flags << 1) & ID3_FRAME_FLAG_GROUPINGIDENTITY);
321 if (flags & ID3_FRAME_FLAG_COMPRESSION) {
325 decoded_length = id3_parse_uint(ptr, 4);
328 if (flags & ID3_FRAME_FLAG_ENCRYPTION) {
332 encryption_method = id3_parse_uint(ptr, 1);
335 if (flags & ID3_FRAME_FLAG_GROUPINGIDENTITY) {
339 group_id = id3_parse_uint(ptr, 1);
350 if (compat && compat->equiv)
351 id = (
const id3_byte_t *)compat->equiv;
352 else if (ID3_TAG_VERSION_MAJOR(version) == 2) {
358 id = (
const id3_byte_t *)xid;
361 ID3_FRAME_FLAG_TAGALTERPRESERVATION |
362 ID3_FRAME_FLAG_FILEALTERPRESERVATION;
370 size = id3_parse_syncsafe(ptr, 4);
371 flags = id3_parse_uint(ptr, 2);
373 if (size > end - *ptr)
378 if (flags & (ID3_FRAME_FLAG_FORMATFLAGS & ~ID3_FRAME_FLAG_KNOWNFLAGS)) {
379 frame = unparseable((
const char *)
id, ptr, end - *ptr, flags, 0, 0, 0);
383 if (flags & ID3_FRAME_FLAG_GROUPINGIDENTITY) {
387 group_id = id3_parse_uint(ptr, 1);
390 if ((flags & ID3_FRAME_FLAG_COMPRESSION) &&
391 !(flags & ID3_FRAME_FLAG_DATALENGTHINDICATOR))
394 if (flags & ID3_FRAME_FLAG_ENCRYPTION) {
398 encryption_method = id3_parse_uint(ptr, 1);
401 if (flags & ID3_FRAME_FLAG_DATALENGTHINDICATOR) {
405 decoded_length = id3_parse_syncsafe(ptr, 4);
414 if ((flags & ID3_FRAME_FLAG_UNSYNCHRONISATION) && end - data > 0) {
415 mem = malloc(end - data);
419 memcpy(mem, data, end - data);
421 end = mem + id3_util_deunsynchronise(mem, end - data);
425 if (flags & ID3_FRAME_FLAG_ENCRYPTION) {
426 frame = unparseable((
const char *)
id, &data, end - data, flags,
427 group_id, encryption_method, decoded_length);
431 if (flags & ID3_FRAME_FLAG_COMPRESSION) {
434 decomp = id3_util_decompress(data, end - data, decoded_length);
442 end = data + decoded_length;
447 if (compat && !compat->equiv) {
448 frame = obsolete((
const char *)
id, data, end - data);
454 frame = id3_frame_new((
const char *)
id);
456 frame->flags = flags;
457 frame->group_id = group_id;
459 if (compat && compat->translate) {
460 if (compat->translate(frame, compat->id, data, end - data) == -1)
464 if (parse_data(frame, data, end - data) == -1)
472 id3_frame_delete(frame);
485id3_length_t render_data(id3_byte_t **ptr,
486 union id3_field *fields,
unsigned int length)
488 id3_length_t size = 0;
489 enum id3_field_textencoding encoding;
492 encoding = ID3_FIELD_TEXTENCODING_ISO_8859_1;
494 for (i = 0; i < length; ++i)
495 size += id3_field_render(&fields[i], ptr, &encoding, i < length - 1);
504id3_length_t id3_frame_render(
struct id3_frame const *frame,
505 id3_byte_t **ptr,
int options)
507 id3_length_t size = 0, decoded_length, datalen;
508 id3_byte_t *size_ptr = 0, *flags_ptr = 0, *data = 0;
513 if ((frame->flags & ID3_FRAME_FLAG_TAGALTERPRESERVATION) ||
514 ((options & ID3_TAG_OPTION_FILEALTERED) &&
515 (frame->flags & ID3_FRAME_FLAG_FILEALTERPRESERVATION)))
520 decoded_length = render_data(0, frame->fields, frame->nfields);
521 if (decoded_length == 0 && frame->encoded == 0)
526 size += id3_render_immediate(ptr, frame->id, 4);
531 size += id3_render_syncsafe(ptr, 0, 4);
536 flags = frame->flags;
538 size += id3_render_int(ptr, flags, 2);
540 if (flags & (ID3_FRAME_FLAG_FORMATFLAGS & ~ID3_FRAME_FLAG_KNOWNFLAGS)) {
541 size += id3_render_binary(ptr, frame->encoded, frame->encoded_length);
543 id3_render_syncsafe(&size_ptr, size - 10, 4);
548 flags &= ID3_FRAME_FLAG_KNOWNFLAGS;
550 flags &= ~ID3_FRAME_FLAG_UNSYNCHRONISATION;
551 if (options & ID3_TAG_OPTION_UNSYNCHRONISATION)
552 flags |= ID3_FRAME_FLAG_UNSYNCHRONISATION;
554 if (!(flags & ID3_FRAME_FLAG_ENCRYPTION)) {
555 flags &= ~ID3_FRAME_FLAG_COMPRESSION;
556 if (options & ID3_TAG_OPTION_COMPRESSION)
557 flags |= ID3_FRAME_FLAG_COMPRESSION | ID3_FRAME_FLAG_DATALENGTHINDICATOR;
560 if (flags & ID3_FRAME_FLAG_GROUPINGIDENTITY)
561 size += id3_render_int(ptr, frame->group_id, 1);
562 if (flags & ID3_FRAME_FLAG_ENCRYPTION)
563 size += id3_render_int(ptr, frame->encryption_method, 1);
564 if (flags & ID3_FRAME_FLAG_DATALENGTHINDICATOR) {
565 if (flags & ID3_FRAME_FLAG_ENCRYPTION)
566 decoded_length = frame->decoded_length;
567 size += id3_render_syncsafe(ptr, decoded_length, 4);
573 if (flags & ID3_FRAME_FLAG_ENCRYPTION)
574 datalen = id3_render_binary(ptr, frame->encoded, frame->encoded_length);
577 datalen = decoded_length;
579 datalen = render_data(ptr, frame->fields, frame->nfields);
581 if (flags & ID3_FRAME_FLAG_COMPRESSION) {
583 id3_length_t complen;
585 comp = id3_util_compress(data, datalen, &complen);
587 flags &= ~ID3_FRAME_FLAG_COMPRESSION;
590 datalen = id3_render_binary(ptr, comp, complen);
600 if (flags & ID3_FRAME_FLAG_UNSYNCHRONISATION) {
606 newlen = id3_util_unsynchronise(data, datalen);
607 if (newlen == datalen)
608 flags &= ~ID3_FRAME_FLAG_UNSYNCHRONISATION;
610 *ptr += newlen - datalen;
621 id3_render_syncsafe(&size_ptr, size - 10, 4);
623 id3_render_int(&flags_ptr, flags, 2);