2
* libid3tag - ID3 tag manipulation library
3
* Copyright (C) 2000-2004 Underbit Technologies, Inc.
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
* $Id: frame.c,v 1.15 2004/01/23 09:41:32 rob Exp $
37
# include "frametype.h"
45
int valid_idchar(char c)
47
return (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9');
51
* NAME: frame->validid()
52
* DESCRIPTION: return true if the parameter string is a legal frame ID
54
int id3_frame_validid(char const *id)
57
valid_idchar(id[0]) &&
58
valid_idchar(id[1]) &&
59
valid_idchar(id[2]) &&
65
* DESCRIPTION: allocate and return a new frame
67
struct id3_frame *id3_frame_new(char const *id)
69
struct id3_frametype const *frametype;
70
struct id3_frame *frame;
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]);
127
void 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);
145
* NAME: frame->addref()
146
* DESCRIPTION: add an external reference to a frame
148
void id3_frame_addref(struct id3_frame *frame)
156
* NAME: frame->delref()
157
* DESCRIPTION: remove an external reference to a frame
159
void id3_frame_delref(struct id3_frame *frame)
161
assert(frame && frame->refcount > 0);
167
* NAME: frame->field()
168
* DESCRIPTION: return a pointer to a field in a frame
170
union id3_field *id3_frame_field(struct id3_frame const *frame,
175
return (index < frame->nfields) ? &frame->fields[index] : 0;
179
struct id3_frame *obsolete(char const *id, id3_byte_t const *data,
182
struct id3_frame *frame;
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);
203
struct 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)
208
struct id3_frame *frame = 0;
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;
240
int parse_data(struct id3_frame *frame,
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)
260
* NAME: frame->parse()
261
* DESCRIPTION: parse raw frame data according to the specified ID3 tag version
263
struct id3_frame *id3_frame_parse(id3_byte_t const **ptr, id3_length_t length,
264
unsigned int version)
266
struct id3_frame *frame = 0;
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;
270
struct id3_compat const *compat = 0;
277
if (ID3_TAG_VERSION_MAJOR(version) < 4) {
278
switch (ID3_TAG_VERSION_MAJOR(version)) {
283
compat = id3_compat_lookup(id, 3);
286
size = id3_parse_uint(ptr, 3);
288
if (size > end - *ptr)
299
compat = id3_compat_lookup(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(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);
348
/* canonicalize frame ID for ID3v2.4 */
350
if (compat && compat->equiv)
352
else if (ID3_TAG_VERSION_MAJOR(version) == 2) {
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(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);
412
/* undo frame encodings */
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(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;
445
/* check for obsolescence */
447
if (compat && !compat->equiv) {
448
frame = obsolete(id, data, end - data);
452
/* generate the internal frame structure */
454
frame = id3_frame_new(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);
485
id3_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);
501
* NAME: frame->render()
502
* DESCRIPTION: render a single, complete frame
504
id3_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)))
518
/* a frame must be at least 1 byte big, excluding the header */
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);
598
/* unsynchronisation */
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;
618
/* patch size and flags */
621
id3_render_syncsafe(&size_ptr, size - 10, 4);
623
id3_render_int(&flags_ptr, flags, 2);