1 /*
2  * libid3tag - ID3 tag manipulation library
3  * Copyright (C) 2000-2004 Underbit Technologies, Inc.
4  *
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.
9  *
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.
14  *
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
18  *
19  * $Id: frame.c,v 1.15 2004/01/23 09:41:32 rob Exp $
20  */
21 
22 # ifdef HAVE_CONFIG_H
23 #  include "config.h"
24 # endif
25 
26 # include "global.h"
27 
28 # include <stdlib.h>
29 # include <string.h>
30 
31 # ifdef HAVE_ASSERT_H
32 #  include <assert.h>
33 # endif
34 
35 # include "id3tag.h"
36 # include "frame.h"
37 # include "frametype.h"
38 # include "compat.h"
39 # include "field.h"
40 # include "render.h"
41 # include "parse.h"
42 # include "util.h"
43 
44 static
valid_idchar(char c)45 int valid_idchar(char c)
46 {
47   return (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9');
48 }
49 
50 /*
51  * NAME:	frame->validid()
52  * DESCRIPTION:	return true if the parameter string is a legal frame ID
53  */
id3_frame_validid(char const * id)54 int id3_frame_validid(char const *id)
55 {
56   return id &&
57     valid_idchar(id[0]) &&
58     valid_idchar(id[1]) &&
59     valid_idchar(id[2]) &&
60     valid_idchar(id[3]);
61 }
62 
63 /*
64  * NAME:	frame->new()
65  * DESCRIPTION:	allocate and return a new frame
66  */
id3_frame_new(char const * id)67 struct id3_frame *id3_frame_new(char const *id)
68 {
69   struct id3_frametype const *frametype;
70   struct id3_frame *frame;
71   unsigned int i;
72 
73   if (!id3_frame_validid(id))
74     return 0;
75 
76   frametype = id3_frametype_lookup(id, 4);
77   if (frametype == 0) {
78     switch (id[0]) {
79     case 'T':
80       frametype = &id3_frametype_text;
81       break;
82 
83     case 'W':
84       frametype = &id3_frametype_url;
85       break;
86 
87     case 'X':
88     case 'Y':
89     case 'Z':
90       frametype = &id3_frametype_experimental;
91       break;
92 
93     default:
94       frametype = &id3_frametype_unknown;
95       if (id3_compat_lookup(id, 4))
96 	frametype = &id3_frametype_obsolete;
97       break;
98     }
99   }
100 
101   frame = malloc(sizeof(*frame) + frametype->nfields * sizeof(*frame->fields));
102   if (frame) {
103     frame->id[0] = id[0];
104     frame->id[1] = id[1];
105     frame->id[2] = id[2];
106     frame->id[3] = id[3];
107     frame->id[4] = 0;
108 
109     frame->description       = frametype->description;
110     frame->refcount          = 0;
111     frame->flags             = frametype->defaultflags;
112     frame->group_id          = 0;
113     frame->encryption_method = 0;
114     frame->encoded           = 0;
115     frame->encoded_length    = 0;
116     frame->decoded_length    = 0;
117     frame->nfields           = frametype->nfields;
118     frame->fields            = (union id3_field *) &frame[1];
119 
120     for (i = 0; i < frame->nfields; ++i)
121       id3_field_init(&frame->fields[i], frametype->fields[i]);
122   }
123 
124   return frame;
125 }
126 
id3_frame_delete(struct id3_frame * frame)127 void id3_frame_delete(struct id3_frame *frame)
128 {
129   assert(frame);
130 
131   if (frame->refcount == 0) {
132     unsigned int i;
133 
134     for (i = 0; i < frame->nfields; ++i)
135       id3_field_finish(&frame->fields[i]);
136 
137     if (frame->encoded)
138       free(frame->encoded);
139 
140     free(frame);
141   }
142 }
143 
144 /*
145  * NAME:	frame->addref()
146  * DESCRIPTION:	add an external reference to a frame
147  */
id3_frame_addref(struct id3_frame * frame)148 void id3_frame_addref(struct id3_frame *frame)
149 {
150   assert(frame);
151 
152   ++frame->refcount;
153 }
154 
155 /*
156  * NAME:	frame->delref()
157  * DESCRIPTION:	remove an external reference to a frame
158  */
id3_frame_delref(struct id3_frame * frame)159 void id3_frame_delref(struct id3_frame *frame)
160 {
161   assert(frame && frame->refcount > 0);
162 
163   --frame->refcount;
164 }
165 
166 /*
167  * NAME:	frame->field()
168  * DESCRIPTION:	return a pointer to a field in a frame
169  */
id3_frame_field(struct id3_frame const * frame,unsigned int index)170 union id3_field *id3_frame_field(struct id3_frame const *frame,
171 				 unsigned int index)
172 {
173   assert(frame);
174 
175   return (index < frame->nfields) ? &frame->fields[index] : 0;
176 }
177 
178 static
obsolete(char const * id,id3_byte_t const * data,id3_length_t length)179 struct id3_frame *obsolete(char const *id, id3_byte_t const *data,
180 			   id3_length_t length)
181 {
182   struct id3_frame *frame;
183 
184   frame = id3_frame_new(ID3_FRAME_OBSOLETE);
185   if (frame) {
186     if (id3_field_setframeid(&frame->fields[0], id) == -1 ||
187 	id3_field_setbinarydata(&frame->fields[1], data, length) == -1)
188       goto fail;
189   }
190 
191   if (0) {
192   fail:
193     if (frame) {
194       id3_frame_delete(frame);
195       frame = 0;
196     }
197   }
198 
199   return frame;
200 }
201 
202 static
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)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)
207 {
208   struct id3_frame *frame = 0;
209   id3_byte_t *mem;
210 
211   mem = malloc(length ? length : 1);
212   if (mem == 0)
213     goto fail;
214 
215   frame = id3_frame_new(id);
216   if (frame == 0)
217     free(mem);
218   else {
219     memcpy(mem, *ptr, length);
220 
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;
227   }
228 
229   if (0) {
230   fail:
231     ;
232   }
233 
234   *ptr += length;
235 
236   return frame;
237 }
238 
239 static
parse_data(struct id3_frame * frame,id3_byte_t const * data,id3_length_t length)240 int parse_data(struct id3_frame *frame,
241 	       id3_byte_t const *data, id3_length_t length)
242 {
243   enum id3_field_textencoding encoding;
244   id3_byte_t const *end;
245   unsigned int i;
246 
247   encoding = ID3_FIELD_TEXTENCODING_ISO_8859_1;
248 
249   end = data + length;
250 
251   for (i = 0; i < frame->nfields; ++i) {
252     if (id3_field_parse(&frame->fields[i], &data, end - data, &encoding) == -1)
253       return -1;
254   }
255 
256   return 0;
257 }
258 
259 /*
260  * NAME:	frame->parse()
261  * DESCRIPTION:	parse raw frame data according to the specified ID3 tag version
262  */
id3_frame_parse(id3_byte_t const ** ptr,id3_length_t length,unsigned int version)263 struct id3_frame *id3_frame_parse(id3_byte_t const **ptr, id3_length_t length,
264 				  unsigned int version)
265 {
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;
271   id3_byte_t *mem = 0;
272   char xid[4];
273 
274   id  = *ptr;
275   end = *ptr + length;
276 
277   if (ID3_TAG_VERSION_MAJOR(version) < 4) {
278     switch (ID3_TAG_VERSION_MAJOR(version)) {
279     case 2:
280       if (length < 6)
281 	goto fail;
282 
283       compat = id3_compat_lookup(id, 3);
284 
285       *ptr += 3;
286       size  = id3_parse_uint(ptr, 3);
287 
288       if (size > end - *ptr)
289 	goto fail;
290 
291       end = *ptr + size;
292 
293       break;
294 
295     case 3:
296       if (length < 10)
297 	goto fail;
298 
299       compat = id3_compat_lookup(id, 4);
300 
301       *ptr += 4;
302       size  = id3_parse_uint(ptr, 4);
303       flags = id3_parse_uint(ptr, 2);
304 
305       if (size > end - *ptr)
306 	goto fail;
307 
308       end = *ptr + size;
309 
310       if (flags & (ID3_FRAME_FLAG_FORMATFLAGS & ~0x00e0)) {
311 	frame = unparseable(id, ptr, end - *ptr, 0, 0, 0, 0);
312 	goto done;
313       }
314 
315       flags =
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);
320 
321       if (flags & ID3_FRAME_FLAG_COMPRESSION) {
322 	if (end - *ptr < 4)
323 	  goto fail;
324 
325 	decoded_length = id3_parse_uint(ptr, 4);
326       }
327 
328       if (flags & ID3_FRAME_FLAG_ENCRYPTION) {
329 	if (end - *ptr < 1)
330 	  goto fail;
331 
332 	encryption_method = id3_parse_uint(ptr, 1);
333       }
334 
335       if (flags & ID3_FRAME_FLAG_GROUPINGIDENTITY) {
336 	if (end - *ptr < 1)
337 	  goto fail;
338 
339 	group_id = id3_parse_uint(ptr, 1);
340       }
341 
342       break;
343 
344     default:
345       goto fail;
346     }
347 
348     /* canonicalize frame ID for ID3v2.4 */
349 
350     if (compat && compat->equiv)
351       id = compat->equiv;
352     else if (ID3_TAG_VERSION_MAJOR(version) == 2) {
353       xid[0] = 'Y';
354       xid[1] = id[0];
355       xid[2] = id[1];
356       xid[3] = id[2];
357 
358       id = xid;
359 
360       flags |=
361 	ID3_FRAME_FLAG_TAGALTERPRESERVATION |
362 	ID3_FRAME_FLAG_FILEALTERPRESERVATION;
363     }
364   }
365   else {  /* ID3v2.4 */
366     if (length < 10)
367       goto fail;
368 
369     *ptr += 4;
370     size  = id3_parse_syncsafe(ptr, 4);
371     flags = id3_parse_uint(ptr, 2);
372 
373     if (size > end - *ptr)
374       goto fail;
375 
376     end = *ptr + size;
377 
378     if (flags & (ID3_FRAME_FLAG_FORMATFLAGS & ~ID3_FRAME_FLAG_KNOWNFLAGS)) {
379       frame = unparseable(id, ptr, end - *ptr, flags, 0, 0, 0);
380       goto done;
381     }
382 
383     if (flags & ID3_FRAME_FLAG_GROUPINGIDENTITY) {
384       if (end - *ptr < 1)
385 	goto fail;
386 
387       group_id = id3_parse_uint(ptr, 1);
388     }
389 
390     if ((flags & ID3_FRAME_FLAG_COMPRESSION) &&
391 	!(flags & ID3_FRAME_FLAG_DATALENGTHINDICATOR))
392       goto fail;
393 
394     if (flags & ID3_FRAME_FLAG_ENCRYPTION) {
395       if (end - *ptr < 1)
396 	goto fail;
397 
398       encryption_method = id3_parse_uint(ptr, 1);
399     }
400 
401     if (flags & ID3_FRAME_FLAG_DATALENGTHINDICATOR) {
402       if (end - *ptr < 4)
403 	goto fail;
404 
405       decoded_length = id3_parse_syncsafe(ptr, 4);
406     }
407   }
408 
409   data = *ptr;
410   *ptr = end;
411 
412   /* undo frame encodings */
413 
414   if ((flags & ID3_FRAME_FLAG_UNSYNCHRONISATION) && end - data > 0) {
415     mem = malloc(end - data);
416     if (mem == 0)
417       goto fail;
418 
419     memcpy(mem, data, end - data);
420 
421     end  = mem + id3_util_deunsynchronise(mem, end - data);
422     data = mem;
423   }
424 
425   if (flags & ID3_FRAME_FLAG_ENCRYPTION) {
426     frame = unparseable(id, &data, end - data, flags,
427 			group_id, encryption_method, decoded_length);
428     goto done;
429   }
430 
431   if (flags & ID3_FRAME_FLAG_COMPRESSION) {
432     id3_byte_t *decomp;
433 
434     decomp = id3_util_decompress(data, end - data, decoded_length);
435     if (decomp == 0)
436       goto fail;
437 
438     if (mem)
439       free(mem);
440 
441     data = mem = decomp;
442     end  = data + decoded_length;
443   }
444 
445   /* check for obsolescence */
446 
447   if (compat && !compat->equiv) {
448     frame = obsolete(id, data, end - data);
449     goto done;
450   }
451 
452   /* generate the internal frame structure */
453 
454   frame = id3_frame_new(id);
455   if (frame) {
456     frame->flags    = flags;
457     frame->group_id = group_id;
458 
459     if (compat && compat->translate) {
460       if (compat->translate(frame, compat->id, data, end - data) == -1)
461 	goto fail;
462     }
463     else {
464       if (parse_data(frame, data, end - data) == -1)
465 	goto fail;
466     }
467   }
468 
469   if (0) {
470   fail:
471     if (frame) {
472       id3_frame_delete(frame);
473       frame = 0;
474     }
475   }
476 
477  done:
478   if (mem)
479     free(mem);
480 
481   return frame;
482 }
483 
484 static
render_data(id3_byte_t ** ptr,union id3_field * fields,unsigned int length)485 id3_length_t render_data(id3_byte_t **ptr,
486 			 union id3_field *fields, unsigned int length)
487 {
488   id3_length_t size = 0;
489   enum id3_field_textencoding encoding;
490   unsigned int i;
491 
492   encoding = ID3_FIELD_TEXTENCODING_ISO_8859_1;
493 
494   for (i = 0; i < length; ++i)
495     size += id3_field_render(&fields[i], ptr, &encoding, i < length - 1);
496 
497   return size;
498 }
499 
500 /*
501  * NAME:	frame->render()
502  * DESCRIPTION:	render a single, complete frame
503  */
id3_frame_render(struct id3_frame const * frame,id3_byte_t ** ptr,int options)504 id3_length_t id3_frame_render(struct id3_frame const *frame,
505 			      id3_byte_t **ptr, int options)
506 {
507   id3_length_t size = 0, decoded_length, datalen;
508   id3_byte_t *size_ptr = 0, *flags_ptr = 0, *data = 0;
509   int flags;
510 
511   assert(frame);
512 
513   if ((frame->flags & ID3_FRAME_FLAG_TAGALTERPRESERVATION) ||
514       ((options & ID3_TAG_OPTION_FILEALTERED) &&
515        (frame->flags & ID3_FRAME_FLAG_FILEALTERPRESERVATION)))
516     return 0;
517 
518   /* a frame must be at least 1 byte big, excluding the header */
519 
520   decoded_length = render_data(0, frame->fields, frame->nfields);
521   if (decoded_length == 0 && frame->encoded == 0)
522     return 0;
523 
524   /* header */
525 
526   size += id3_render_immediate(ptr, frame->id, 4);
527 
528   if (ptr)
529     size_ptr = *ptr;
530 
531   size += id3_render_syncsafe(ptr, 0, 4);
532 
533   if (ptr)
534     flags_ptr = *ptr;
535 
536   flags = frame->flags;
537 
538   size += id3_render_int(ptr, flags, 2);
539 
540   if (flags & (ID3_FRAME_FLAG_FORMATFLAGS & ~ID3_FRAME_FLAG_KNOWNFLAGS)) {
541     size += id3_render_binary(ptr, frame->encoded, frame->encoded_length);
542     if (size_ptr)
543       id3_render_syncsafe(&size_ptr, size - 10, 4);
544 
545     return size;
546   }
547 
548   flags &= ID3_FRAME_FLAG_KNOWNFLAGS;
549 
550   flags &= ~ID3_FRAME_FLAG_UNSYNCHRONISATION;
551   if (options & ID3_TAG_OPTION_UNSYNCHRONISATION)
552     flags |= ID3_FRAME_FLAG_UNSYNCHRONISATION;
553 
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;
558   }
559 
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);
568   }
569 
570   if (ptr)
571     data = *ptr;
572 
573   if (flags & ID3_FRAME_FLAG_ENCRYPTION)
574     datalen = id3_render_binary(ptr, frame->encoded, frame->encoded_length);
575   else {
576     if (ptr == 0)
577       datalen = decoded_length;
578     else {
579       datalen = render_data(ptr, frame->fields, frame->nfields);
580 
581       if (flags & ID3_FRAME_FLAG_COMPRESSION) {
582 	id3_byte_t *comp;
583 	id3_length_t complen;
584 
585 	comp = id3_util_compress(data, datalen, &complen);
586 	if (comp == 0)
587 	  flags &= ~ID3_FRAME_FLAG_COMPRESSION;
588 	else {
589 	  *ptr = data;
590 	  datalen = id3_render_binary(ptr, comp, complen);
591 
592 	  free(comp);
593 	}
594       }
595     }
596   }
597 
598   /* unsynchronisation */
599 
600   if (flags & ID3_FRAME_FLAG_UNSYNCHRONISATION) {
601     if (data == 0)
602       datalen *= 2;
603     else {
604       id3_length_t newlen;
605 
606       newlen = id3_util_unsynchronise(data, datalen);
607       if (newlen == datalen)
608 	flags &= ~ID3_FRAME_FLAG_UNSYNCHRONISATION;
609       else {
610 	*ptr   += newlen - datalen;
611 	datalen = newlen;
612       }
613     }
614   }
615 
616   size += datalen;
617 
618   /* patch size and flags */
619 
620   if (size_ptr)
621     id3_render_syncsafe(&size_ptr, size - 10, 4);
622   if (flags_ptr)
623     id3_render_int(&flags_ptr, flags, 2);
624 
625   return size;
626 }
627