1 /*
2 * tags is a support module which provides access to metadata tags (and xing/vbri/lame tags as well)
3 * Copyright (C) 2013-2020 Elio Blanca <eblanca76@users.sourceforge.net>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library 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 GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 #include "mp3g_io_config.h"
21
22 #include <ctype.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "bit_utils.h"
27 #include "mp3guessenc.h"
28
29
30 #define ID3V2_HEADER_LENGTH 10
31 #define ID3V2_FOOTER_LENGTH ID3V2_HEADER_LENGTH
32 #define ID3V2_FLAGS_FOOTER_PRESENT 0x10
33 #define ID3V2_ID_STRING "ID3"
34
35 #define LYRICS3V1_TAG_MAXSIZE 5100
36 #define LYRICS3_BEGIN_SIGNATURE "LYRICSBEGIN"
37 #define LYRICS3_BEGIN_SIGNATURE_LEN 11
38 #define LYRICS3V1_END_SIGNATURE "LYRICSEND"
39 #define LYRICS3V2_END_SIGNATURE "LYRICS200"
40 #define LYRICS3_END_SIGNATURE_LEN 9
41 #define LYRICS3V2_TAGSIZE_LEN 6
42
43 #define APETAGEX_SIGNATURE "APETAGEX"
44 #define APETAGEX_FLAGS_HEADER_PRESENT 0x80000000
45 #define APETAGEX_FLAGS_THIS_IS_HEADER 0x20000000
46
47 #define MMTAG_FOOTER_SIZE 48
48 #define MMTAG_DATA_OFFSETS_SIZE 20
49 #define MMTAG_META_DATA_MINIMUM_SIZE 7868
50 #define MMTAG_VERSION_INFO_SIZE 256
51 #define MMTAG_HEADER_SIZE MMTAG_VERSION_INFO_SIZE
52 /* This `safe search size' is choosen on purpose. A larger buffer may lead to
53 * include the optional mmtag header and searching for the sync bytes will
54 * result in detecting that optional header as the mandatory version info block
55 * (unless one would do a further second search and after that dives into
56 * pointer calculations...)
57 * With this size and the metadata section at its maximum size (8132 bytes), we
58 * can find the mandatory version block at the head of the buffer (at most) */
59 #define MMTAG_SAFE_SEARCH_SIZE 520
60
61 #define MMTAG_HEADER 0
62 #define MMTAG_IMAGE_EXTENSION 1
63 #define MMTAG_IMAGE_BINARY 2
64 #define MMTAG_UNUSED 3
65 #define MMTAG_VERSION_INFO 4
66 #define MMTAG_AUDIO_METADATA 5
67 #define MMTAG_OFFSET_ENTRIES 6
68
69 #define MMTAG_SIGNATURE "Brava Software Inc."
70 #define MMTAG_SIGNATURE_LEN 19
71 #define MMTAG_SIGNATURE_OFFSET 0
72 #define MMTAG_VERSION_LEN 4
73 #define MMTAG_VERSION_OFFSET 32
74
75 #define MMTAG_VERSION_BLOCK_SYNC_STRING "18273645"
76 #define MMTAG_VERSION_BLOCK_SYNC_OFFSET 0
77 #define MMTAG_VERSION_BLOCK_SYNC_LENGTH 8
78 #define MMTAG_VERSION_BLOCK_SUBSECTION_LENGTH 10
79 #define MMTAG_VERSION_BLOCK_XING_VER_OFFSET 10
80 #define MMTAG_VERSION_BLOCK_MM_VER_OFFSET 20
81 #define MMTAG_VERSION_BLOCK_STRING_LEN 4
82
83 #define MMTAG_IMAGE_EXTENSION_LEN 4
84 #define MMTAG_IMAGE_SIZE_LEN 4
85
86 #define WAVE_RIFF_STRUCTURE_ID "RIFF"
87 #define WAVE_RIFF_IDS_LENGTH 4
88 #define WAVE_RIFF_WAVE_ID "WAVE"
89 #define WAVE_RIFF_HEADER_LENGTH 12
90 //#define WAVE_RIFF_FMT_ID "fmt "
91 //#define WAVE_RIFF_FACT_ID "fact"
92 #define WAVE_RIFF_DATA_ID "data"
93
94 #define VBRI_TAG_START_OFFSET 36
95 #define VBRI_TAG_ID_STRING "VBRI"
96 #define LAME_TAG_ID_STRING "Info"
97 #define XING_TAG_ID_STRING "Xing"
98 #define VBR_TAG_ID_STRING_LEN 4
99
100
101 char *genre_list[]={
102 /* Compliant with https://en.wikipedia.org/wiki/List_of_ID3v1_Genres */
103 "Blues" /* 0 */
104 , "Classic Rock" /* 1 */
105 , "Country" /* 2 */
106 , "Dance" /* 3 */
107 , "Disco" /* 4 */
108 , "Funk" /* 5 */
109 , "Grunge" /* 6 */
110 , "Hip-Hop" /* 7 */
111 , "Jazz" /* 8 */
112 , "Metal" /* 9 */
113 , "New Age" /* 10 */
114 , "Oldies" /* 11 */
115 , "Other" /* 12 */
116 , "Pop" /* 13 */
117 , "Rhythm and Blues" /* 14 */
118 , "Rap" /* 15 */
119 , "Reggae" /* 16 */
120 , "Rock" /* 17 */
121 , "Techno" /* 18 */
122 , "Industrial" /* 19 */
123 , "Alternative" /* 20 */
124 , "Ska" /* 21 */
125 , "Death Metal" /* 22 */
126 , "Pranks" /* 23 */
127 , "Soundtrack" /* 24 */
128 , "Euro-Techno" /* 25 */
129 , "Ambient" /* 26 */
130 , "Trip-Hop" /* 27 */
131 , "Vocal" /* 28 */
132 , "Jazz & Funk" /* 29 */
133 , "Fusion" /* 30 */
134 , "Trance" /* 31 */
135 , "Classical" /* 32 */
136 , "Instrumental" /* 33 */
137 , "Acid" /* 34 */
138 , "House" /* 35 */
139 , "Game" /* 36 */
140 , "Sound Clip" /* 37 */
141 , "Gospel" /* 38 */
142 , "Noise" /* 39 */
143 , "Alternative Rock" /* 40 */
144 , "Bass" /* 41 */
145 , "Soul" /* 42 */
146 , "Punk" /* 43 */
147 , "Space" /* 44 */
148 , "Meditative" /* 45 */
149 , "Instrumental Pop" /* 46 */
150 , "Instrumental Rock" /* 47 */
151 , "Ethnic" /* 48 */
152 , "Gothic" /* 49 */
153 , "Darkwave" /* 50 */
154 , "Techno-Industrial" /* 51 */
155 , "Electronic" /* 52 */
156 , "Pop-Folk" /* 53 */
157 , "Eurodance" /* 54 */
158 , "Dream" /* 55 */
159 , "Southern Rock" /* 56 */
160 , "Comedy" /* 57 */
161 , "Cult" /* 58 */
162 , "Gangsta" /* 59 */
163 , "Top 40" /* 60 */
164 , "Christian Rap" /* 61 */
165 , "Pop/Funk" /* 62 */
166 , "Jungle Music" /* 63 */
167 , "Native American" /* 64 */
168 , "Cabaret" /* 65 */
169 , "New Wave" /* 66 */
170 , "Psychedelic" /* 67 */
171 , "Rave" /* 68 */
172 , "Showtunes" /* 69 */
173 , "Trailer" /* 70 */
174 , "Lo-Fi" /* 71 */
175 , "Tribal" /* 72 */
176 , "Acid Punk" /* 73 */
177 , "Acid Jazz" /* 74 */
178 , "Polka" /* 75 */
179 , "Retro" /* 76 */
180 , "Musical" /* 77 */
181 , "Rock & Roll" /* 78 */
182 , "Hard Rock" /* 79 */
183
184 /* Extension by Winamp */
185 , "Folk" /* 80 */
186 , "Folk/Rock" /* 81 */
187 , "National Folk" /* 82 */
188 , "Swing" /* 83 */
189 , "Fast Fusion" /* 84 */
190 , "Bebop" /* 85 */
191 , "Latin" /* 86 */
192 , "Revival" /* 87 */
193 , "Celtic" /* 88 */
194 , "Bluegrass" /* 89 */
195 , "Avantgarde" /* 90 */
196 , "Gothic Rock" /* 91 */
197 , "Progressive Rock" /* 92 */
198 , "Psychedelic Rock" /* 93 */
199 , "Symphonic Rock" /* 94 */
200 , "Slow Rock" /* 95 */
201 , "Big Band" /* 96 */
202 , "Chorus" /* 97 */
203 , "Easy Listening" /* 98 */
204 , "Acoustic" /* 99 */
205 , "Humour" /* 100 */
206 , "Speech" /* 101 */
207 , "Chanson" /* 102 */
208 , "Opera" /* 103 */
209 , "Chamber Music" /* 104 */
210 , "Sonata" /* 105 */
211 , "Symphony" /* 106 */
212 , "Booty Bass" /* 107 */
213 , "Primus" /* 108 */
214 , "Porn Groove" /* 109 */
215 , "Satire" /* 110 */
216 , "Slow Jam" /* 111 */
217 , "Club" /* 112 */
218 , "Tango" /* 113 */
219 , "Samba" /* 114 */
220 , "Folklore" /* 115 */
221 , "Ballad" /* 116 */
222 , "Power Ballad" /* 117 */
223 , "Rhythmic Soul" /* 118 */
224 , "Freestyle" /* 119 */
225 , "Duet" /* 120 */
226 , "Punk Rock" /* 121 */
227 , "Drum Solo" /* 122 */
228 , "A cappella" /* 123 */
229 , "Euro-House" /* 124 */
230 , "Dance Hall" /* 125 */
231 , "Goa Music" /* 126 */
232 , "Drum & Bass" /* 127 */
233 , "Club House" /* 128 */
234 , "Hardcore Techno" /* 129 */
235 , "Terror" /* 130 */
236 , "Indie" /* 131 */
237 , "BritPop" /* 132 */
238 , "Negerpunk" /* 133 */
239 , "Polsk Punk" /* 134 */
240 , "Beat" /* 135 */
241 , "Christian Gangsta Rap" /* 136 */
242 , "Heavy Metal" /* 137 */
243 , "Black Metal" /* 138 */
244 , "Crossover" /* 139 */
245 , "Contemporary Christian" /* 140 */
246 , "Christian Rock" /* 141 */
247
248 /* Winamp 1.91 */
249 , "Merengue" /* 142 */
250 , "Salsa" /* 143 */
251 , "Thrash Metal" /* 144 */
252 , "Anime" /* 145 */
253 , "Jpop" /* 146 */
254 , "Synthpop" /* 147 */
255
256 /* Winamp 5.6 */
257 , "Abstract" /* 148 */
258 , "Art Rock" /* 149 */
259 , "Baroque" /* 150 */
260 , "Bhangra" /* 151 */
261 , "Big beat" /* 152 */
262 , "Breakbeat" /* 153 */
263 , "Chillout" /* 154 */
264 , "Downtempo" /* 155 */
265 , "Dub" /* 156 */
266 , "EBM" /* 157 */
267 , "Eclectic" /* 158 */
268 , "Electro" /* 159 */
269 , "Electroclash" /* 160 */
270 , "Emo" /* 161 */
271 , "Experimental" /* 162 */
272 , "Garage" /* 163 */
273 , "Global" /* 164 */
274 , "IDM" /* 165 */
275 , "Illbient" /* 166 */
276 , "Industro-Goth" /* 167 */
277 , "Jam Band" /* 168 */
278 , "Krautrock" /* 169 */
279 , "Leftfield" /* 170 */
280 , "Lounge" /* 171 */
281 , "Math Rock" /* 172 */
282 , "New Romantic" /* 173 */
283 , "Nu-Breakz" /* 174 */
284 , "Post-Punk" /* 175 */
285 , "Post-Rock" /* 176 */
286 , "Psytrance" /* 177 */
287 , "Shoegaze" /* 178 */
288 , "Space Rock" /* 179 */
289 , "Trop Rock" /* 180 */
290 , "World Music" /* 181 */
291 , "Neoclassical" /* 182 */
292 , "Audiobook" /* 183 */
293 , "Audio Theatre" /* 184 */
294 , "Neue Deutsche Welle" /* 185 */
295 , "Podcast" /* 186 */
296 , "Indie-Rock" /* 187 */
297 , "G-Funk" /* 188 */
298 , "Dubstep" /* 189 */
299 , "Garage Rock" /* 190 */
300 , "Psybient" /* 191 */
301 };
302
303 typedef struct apefooter_t {
304 char preamble[8];
305 unsigned char version[4];
306 unsigned char tag_size[4];
307 unsigned char item_count[4];
308 unsigned char tag_flags[4];
309 char reserved[8];
310 } apefooter_t;
311
312 typedef struct mmtag_tail_infos_t {
313 unsigned char image_extension[4];
314 unsigned char image_binary[4];
315 unsigned char unused[4];
316 unsigned char version_info[4];
317 unsigned char audio_metadata[4];
318 unsigned char footer[MMTAG_FOOTER_SIZE];
319 } mmtag_tail_infos_t;
320
321 #if defined(__WATCOMC__)
322 /* Watcom compiler sets default alignment to 1 byte */
323 typedef struct mmtag_partial_infos_t {
324 #else
325 typedef struct __attribute__((packed)) mmtag_partial_infos_t {
326 #endif
327 unsigned char empty[12];
328 unsigned char sync[MMTAG_VERSION_BLOCK_SUBSECTION_LENGTH];
329 unsigned char xing[MMTAG_VERSION_BLOCK_SUBSECTION_LENGTH];
330 unsigned char musm[MMTAG_VERSION_BLOCK_SUBSECTION_LENGTH];
331 } mmtag_partial_infos_t;
332
333 typedef struct wave_riff_chunk_t {
334 char ckid[WAVE_RIFF_IDS_LENGTH];
335 unsigned char cksize[4];
336 } wave_riff_chunk_t;
337
338 unsigned char sideinfo_tab[2][2] = {{32,17},{17,9}}; /* MPEG1 {2ch,1ch}, MPEG2/2.5 {2ch,1ch} */
339
340
341 /*
342 * memsrch
343 *
344 * this function searches for a character string 'needle' into a raw byte sequence
345 * called 'haystack' which is 'haystack_len' bytes long
346 *
347 * return value: when found, the pointer to the first character of 'needle',
348 * else NULL
349 * Note: memsrch was developed because of unreliability of 'strstr' search algorithm
350 * into a raw byte sequence. Cannot use 'memmem' (which is very similar) because it
351 * is a GNU libc extension
352 */
memsrch(unsigned char * haystack,int haystack_len,char * needle)353 unsigned char *memsrch(unsigned char *haystack, int haystack_len, char *needle)
354 {
355 unsigned char *p, *q;
356 int i, len;
357
358 p = NULL;
359
360 if (haystack != NULL && needle != NULL)
361 {
362 q = haystack;
363 i = 0;
364 len = strlen(needle);
365
366 if (len <= haystack_len)
367 {
368 haystack_len -= len - 1;
369
370 while (i < haystack_len)
371 {
372 q=memchr(&haystack[i], needle[0], haystack_len-i);
373 if (q != NULL)
374 {
375 if (!memcmp(q, needle, len))
376 {
377 p = q;
378 break;
379 }
380 else
381 {
382 i = (int)(q - haystack) + 1;
383 }
384 }
385 else
386 {
387 break;
388 }
389 }
390 }
391 }
392
393 return p;
394 }
395
396
397 /*
398 * get_little_endian_uint
399 *
400 * this function reads a byte buffer with a little endian integer stored
401 * and returns its unsigned integer value (32 bit)
402 * This is often the case with integer/flag fields into metadata tags.
403 *
404 * I think I will need this when running mp3guessenc
405 * on a big-endian architecture
406 */
get_little_endian_uint(unsigned char * pbuff)407 unsigned int get_little_endian_uint(unsigned char *pbuff)
408 {
409 return (unsigned int)pbuff[0] +
410 ((unsigned int)pbuff[1]<< 8)+
411 ((unsigned int)pbuff[2]<<16)+
412 ((unsigned int)pbuff[3]<<24);
413 }
414
415
416 /*
417 * here the search for lame extended version string is performed
418 * lame stores this string into ancillary data since version 3.80b (may 6th 2000 - the previous
419 * lame version 3.70 apr 6 2000 didn't have it)
420 * Return values:
421 * - an integer value, the length of the extracted string (if any)
422 * - lame_string contains the encoder extended version string (it is untouched when not found)
423 * Note: this routine may be called several times since ancillary data may be found in
424 * several frames, expecially in CBR files
425 * it overwrites `lame_string' several times in order to fullfill it with data from the longest
426 * of the strings it finds.
427 */
extract_enc_string(char * lame_string,unsigned char * p,int len)428 int extract_enc_string(char *lame_string, unsigned char *p, int len)
429 {
430 //#define SHOW_LAME_STRINGS /* useful when debugging */
431 int idx,len_before,resultLen=0;
432 unsigned char *q;
433
434 #ifdef SHOW_LAME_STRINGS
435 printf("begin - lame_string=`%s', len=%d\n",lame_string,len);
436 for (idx=0; idx<len; idx++)
437 if (isprint(p[idx])) putchar(p[idx]); else putchar('.');
438 printf("\n");
439 #endif
440
441 q = memsrch(p,len,"LAME");
442 if (q == NULL)
443 {
444 q = memsrch(p,len,"GOGO");
445 if (q != NULL)
446 {
447 strcpy(lame_string,"GOGO");
448 resultLen = 4;
449 }
450 else
451 {
452 #ifdef SHOW_LAME_STRINGS
453 printf("No_lame_string.\n");
454 #endif
455 resultLen = 0;
456 }
457 }
458 else
459 {
460 /* `LAME' string found! */
461 len -= (q-p);
462
463 if (lame_string[0] == '\0')
464 strcpy(lame_string,"LAME"); /* this is likely to be the first call to extract_lame_string */
465 else
466 {
467 if (memcmp(lame_string, "LAME", 4))
468 {
469 /* lame_string is only modified here, it MUST be "" (null string) the first time,
470 or it MUST start with "LAME". In any other case I want to be warned */
471 printf("WARNING: buffer overwrite on lame_string (\"%s\")! RESETTING!\n",lame_string);
472 memset(lame_string, 0, LAME_STRING_LENGTH);
473 strcpy(lame_string,"LAME");
474 }
475 }
476
477 idx=4; /* I'm sure q points to `LAME' so the loop can be shortened */
478 len_before=strlen(lame_string);
479
480 while (idx<len
481 &&
482 idx<LAME_STRING_LENGTH-1
483 &&
484 isprint((int)q[idx])
485 &&
486 q[idx]!='L'
487 &&
488 q[idx]!=0x55
489 &&
490 (unsigned char)q[idx]!=0xAA)
491 /* in recent versions, lame strings may end either with a 0x55 or a 0xAA byte
492 older releases used to put random non-printable bytes.
493 Also, I check for a capital `L' in order to skip string repetitions such as `LAME3LAME3' */
494 {
495 lame_string[idx]=q[idx];
496 idx++;
497 }
498
499 if (idx>=len_before)
500 lame_string[idx]=0;
501 resultLen = idx;
502 }
503 #ifdef SHOW_LAME_STRINGS
504 printf("exiting - lame_string=%s\n",lame_string);
505 #endif
506 return resultLen;
507 }
508
509 ///////////////////////////////////////////////////////
510 // VBR TAG related routines
511
reset_tag_data(vbrtagdata_t * p)512 void reset_tag_data(vbrtagdata_t *p)
513 {
514 memset((void *)p, 0, sizeof(vbrtagdata_t));
515 p->tagId=NULL;
516 p->infoTag=TAG_NOTAG;
517 p->vbr_scale=-1; /* GOGO encoder does not put vbr quality value into its vbr tag, so I need here a flag */
518 p->lameMusicCRC=-1; /* no music crc found */
519 }
520
parse_vbri_tag(vbrtagdata_t * p,unsigned char * buf)521 unsigned int parse_vbri_tag(vbrtagdata_t *p, unsigned char *buf)
522 {
523 unsigned int offset=4*8;
524
525 p->tagId=VBRI_TAG_ID_STRING;
526 p->infoTag=TAG_VBRITAG;
527 p->version=extract_bits(buf, &offset, 16);
528
529 p->encDelay=extract_bits(buf, &offset, 16);
530
531 p->vbr_scale=extract_bits(buf, &offset, 16);
532
533 p->bytes=extract_bits(buf, &offset, 32);
534
535 p->reported_frames=extract_bits(buf, &offset, 32);
536
537 p->tocEntries=extract_bits(buf, &offset, 16);
538
539 offset+=2*8;
540 p->sizePerTocEntry=extract_bits(buf, &offset, 16);
541
542 p->framesPerTocEntry=extract_bits(buf, &offset, 16);
543
544 p->tocSize=(int)p->sizePerTocEntry*(int)p->tocEntries;
545
546 /* switch to byte */
547 offset = offset/8 + p->tocSize;
548
549 return offset;
550 }
551
parse_xing_tag(vbrtagdata_t * p,unsigned char * buffer_start,unsigned int tag_start,char * lame_string)552 unsigned int parse_xing_tag(vbrtagdata_t *p, unsigned char *buffer_start, unsigned int tag_start, char *lame_string)
553 {
554 #define XING_FLAG_FRAMES 0x0001
555 #define XING_FLAG_BYTES 0x0002
556 #define XING_FLAG_TOC 0x0004
557 #define XING_FLAG_VBR_SCALE 0x0008
558
559 unsigned char *buf=buffer_start+tag_start;
560 unsigned int offset=sizeof(unsigned int)*8, flags;
561 unsigned short sum;
562
563 p->tagId = XING_TAG_ID_STRING;
564 if (buf[0]=='I')
565 p->infoTag = TAG_LAMECBRTAG;
566 else
567 p->infoTag = TAG_XINGTAG;
568
569 flags = extract_bits(buf, &offset, 32);
570
571 if (flags & XING_FLAG_FRAMES)
572 {
573 p->reported_frames = extract_bits(buf, &offset, 32);
574 }
575
576 if (flags & XING_FLAG_BYTES)
577 {
578 p->bytes = extract_bits(buf, &offset, 32);
579 }
580
581 /* switch to byte */
582 offset /= 8;
583
584 if (flags & XING_FLAG_TOC)
585 {
586 /* I know the toc entries amount */
587 p->tocEntries = 100;
588 p->sizePerTocEntry = 1;
589 p->tocSize = 100;
590 offset+=100;
591 }
592
593 if (buf[offset] == 'G' && buf[offset+1] == 'O' && buf[offset+2] == 'G' && buf[offset+3] == 'O')
594 {
595 /* gogo seems not to put a vbr quality value into its tag */
596 offset += extract_enc_string(lame_string,buf+offset,4);
597 }
598 else
599 {
600 if (flags & XING_FLAG_VBR_SCALE)
601 {
602 p->vbr_scale = extract_bits(buf+offset, NULL, 32);
603 offset+=4;
604 }
605 }
606
607 /*
608 * Starting with lame-3.99 alpha releases the devs changed the lame tag signature so it didn't
609 * start with the string `LAME', instead it just contained the capital `L' at the beginning and the
610 * following expected characters in the form `Lx.xxyzz', where x is a digit and z is an optional digit.
611 * Anyway the old signature `LAMEx.xxy' (y may be one of a/b/r) was restored with lame 3.99.2 release
612 * in order to keep lame tag readable by old sw/hw players.
613 */
614 if (
615 (buf[offset] == 'L' && buf[offset+1] == 'A' && buf[offset+2] == 'M' && buf[offset+3] == 'E')
616 ||
617 (buf[offset] == 'L' && isdigit((int)buf[offset+1]) && buf[offset+2] == '.' && isdigit((int)buf[offset+3]) && isdigit((int)buf[offset+4]))
618 ||
619 (tolower(buf[offset])=='l' && tolower(buf[offset+1])=='a' && tolower(buf[offset+2])=='v' && tolower(buf[offset+3])=='c')
620 )
621 {
622 /*
623 * maybe we found a lame info tag
624 * warn: a version check has to be done because lame 3.90 was the first
625 * version able to write a real info tag.
626 * previous versions wrote just a string
627 * Updated `if' statement for better handling of upcoming 3.100 release
628 */
629 if (buf[offset+1]=='A' && buf[offset+4]=='3' && buf[offset+5]=='.' && isdigit((int)buf[offset+6]) && buf[offset+6]<'9' && isdigit((int)buf[offset+7]) && !isdigit((int)buf[offset+8]))
630 /* old versions had more room for detailed strings due to lack of info tag */
631 offset += extract_enc_string(lame_string,buf+offset,LAME_STRING_LENGTH);
632 else
633 {
634 memcpy(p->lametag, buf+offset, LAMETAGSIZE);
635 extract_enc_string(lame_string,buf+offset,9);
636 offset += LAMETAGSIZE; /* 'offset' is now at the very end of lame tag! */
637 sum = crc_reflected_update(0, buffer_start, tag_start+offset-2);
638 p->lametagVerified = (sum == (unsigned short)((reflect_byte(buffer_start[tag_start+offset-1])<<8)
639 | reflect_byte(buffer_start[tag_start+offset-2]) ) );
640
641 if (p->lametagVerified)
642 p->lameMusicCRC = ((reflect_byte(buffer_start[tag_start+offset-3])<<8)
643 | reflect_byte(buffer_start[tag_start+offset-4]) );
644 }
645 }
646
647 return offset;
648 }
649
checkvbrinfotag(vbrtagdata_t * pTagData,unsigned char * buf,off_t pos,char * enc_string)650 char checkvbrinfotag(vbrtagdata_t *pTagData, unsigned char *buf, off_t pos, char *enc_string)
651 {
652 /*
653 * Here we detect the info vbr/cbr tag (if any) -- the search is performed inside the buffer
654 * Return values:
655 * 0: no tag
656 * 1: tag found (details into pTagData)
657 */
658 unsigned int temp;
659 unsigned char mono, lsf;
660
661 reset_tag_data(pTagData);
662
663 pTagData->header=extract_bits(buf, NULL, 32); /* store the header */
664 lsf = 1-((pTagData->header&HEADER_FIELD_LSF)>>HEADER_FIELD_LSF_SHIFT);
665 mono =((pTagData->header&HEADER_FIELD_CHANNELS)>>HEADER_FIELD_CHANNELS_SHIFT)/3;
666
667 if (memcmp(buf+VBRI_TAG_START_OFFSET, VBRI_TAG_ID_STRING, VBR_TAG_ID_STRING_LEN) == 0)
668 {
669 parse_vbri_tag(pTagData,buf+VBRI_TAG_START_OFFSET);
670 }
671 else
672 {
673 temp = sizeof(unsigned int)+(int)sideinfo_tab[lsf][mono]; /* placement of xing vbr tag doesn't take into account optional crc16 */
674
675 if (
676 memcmp(&buf[temp], XING_TAG_ID_STRING, VBR_TAG_ID_STRING_LEN) == 0
677 ||
678 memcmp(&buf[temp], LAME_TAG_ID_STRING, VBR_TAG_ID_STRING_LEN) == 0
679 )
680 {
681 parse_xing_tag(pTagData, buf, temp, enc_string);
682
683 if ((pTagData->lame_buggy_vbrheader=(((pTagData->header&HEADER_FIELD_BITRATE)>>HEADER_FIELD_BITRATE_SHIFT)==BITRATE_INDEX_RESERVED)))
684 /* Despite the bitrate field holds a buggy value, I know the header is valid
685 So, save this (in `lame_buggy_vbrheader' field) and set the right freeformat
686 bitrate index - I will need it later */
687 pTagData->header &= ~HEADER_FIELD_BITRATE;
688 }
689 }
690
691 if (pTagData->infoTag!=TAG_NOTAG) /* was any tag found? If so, I am sure I'm dealing with a layerIII stream */
692 pTagData->tagStartsAt=pos; /* offset of the mpeg frame containing this tag */
693
694 return (pTagData->infoTag!=TAG_NOTAG);
695 }
696
show_info_tag(vbrtagdata_t * p)697 void show_info_tag (vbrtagdata_t *p)
698 /*
699 * Here we show the technical details found into the VBRI/XING tag
700 * If a lame tag is found, then it's showed as well.
701 * Any lame tag detail is based upon description at
702 * http://gabriel.mp3-tech.org/mp3infotag.html
703 * Offset are different than those reported by Gabriel
704 * because here I saved the tag only into the lametag byte array,
705 * so here the 'Encoder short VersionString' starts at zero.
706 */
707 {
708 #define LAMETAG_TAGREVISION_VBRDETAIL 9
709 #define LAMETAG_LOWPASSFREQ 10
710 #define LAMETAG_ENCODINGFLAGS 19
711 #define LAMETAG_MINIMALBITRATE 20
712 #define LAMETAG_ENCODERDELAYS 21
713 #define LAMETAG_MISCINFOS 24
714 #define LAMETAG_PRESETINFO 26
715 #define LAMETAG_MUSICLENGTH 28
716
717 char lameTag=(p->lametag[0]!=0);
718
719 printf("%s tag detected into the first frame (%d bytes long).\n",p->tagId,p->frameSize);
720 printf(" Tag offset : %lld (0x%08X)\n",(long long)p->tagStartsAt,(unsigned)p->tagStartsAt);
721 if (p->infoTag==TAG_VBRITAG)
722 {
723 printf(" Tag version : %d\n",p->version);
724 printf(" Encoder delay : %d samples\n",p->encDelay);
725 }
726 printf(" File size : %u bytes\n",p->bytes);
727 printf(" Number of frames : %u\n",p->reported_frames);
728 if (p->vbr_scale!=-1) /* GOGO doesn't add a vbr quality value */
729 {
730 printf(" Quality : %u",p->vbr_scale);
731 if ((lameTag)&&(p->infoTag!=TAG_LAMECBRTAG))
732 { /* sure the file is vbr encoded by lame, I just need to know whether it's abr or vbr */
733 unsigned char lamemode=p->lametag[LAMETAG_TAGREVISION_VBRDETAIL]&0x0f;
734 if ((lamemode>2)&&(lamemode<7))
735 /* it's vbr, so let's print encoder options */
736 printf(" (-q %d -V %d)",(100-p->vbr_scale)%10,(100-p->vbr_scale)/10);
737 }
738 printf("\n");
739 }
740 printf(" TOC : ");
741 if (p->tocSize)
742 printf("%d bytes (%d entries, %d byte%s each)\n",
743 p->tocSize,p->tocEntries,p->sizePerTocEntry,(p->sizePerTocEntry==1)?"":"s");
744 else
745 printf("no\n");
746 if (p->infoTag!=TAG_VBRITAG)
747 {
748 printf(" Lame tag : ");
749 if (lameTag)
750 {
751 unsigned char c,i;
752 unsigned short j;
753 unsigned int delay;
754 printf("yes");
755 if (p->lame_buggy_vbrheader)
756 printf(" (buggy bitrate field)");
757 /* print details from lame tag */
758 printf("\nLame tag details...\n Lame short string : ");
759 for(i=0;i<9;i++)
760 if (isprint((int)p->lametag[i])) putchar(p->lametag[i]); else putchar(' ');
761 c=p->lametag[LAMETAG_TAGREVISION_VBRDETAIL]>>4;
762 printf("\n Tag revision : ");
763 if (c!=15)
764 printf("%d",c);
765 else
766 printf("invalid!");
767 c=p->lametag[LAMETAG_TAGREVISION_VBRDETAIL]&0x0f;
768 printf("\n Bitrate strategy : ");
769 if ((c==2)||(c==9))
770 printf("ABR, "); /* it's abr */
771 else
772 {
773 if ((c==1)||(c==8))
774 printf("CBR, "); /* it's cbr */
775 else
776 if ((c>2)&&(c<7)) /* it's vbr */
777 printf("VBR method %s, min ",(c==3)?"old/rh":(c==4)?"mtrh":/*if lame, c is 5*/"mt");
778 }
779 c=p->lametag[LAMETAG_MINIMALBITRATE];
780 if (c)
781 {
782 printf("%d kbps",c);
783 if (c==255) printf (" or higher");
784 }
785 else
786 printf("unknown");
787 c=p->lametag[LAMETAG_LOWPASSFREQ];
788 printf("\n Lowpass value : ");
789 if (c)
790 printf("%d",c*100);
791 else
792 printf("unknown");
793 c=p->lametag[LAMETAG_ENCODINGFLAGS];
794 printf("\n nspsytune : %s\n",(c&0x10)?"yes":"no");
795 printf(" nssafejoint : %s\n",(c&0x20)?"yes":"no");
796 printf(" nogap continued : %s\n",(c&0x40)?"yes":"no");
797 printf(" nogap continuation : %s\n",(c&0x80)?"yes":"no");
798 printf(" ATH type : %d\n",c&0xf);
799 delay=extract_bits((unsigned char *)p->lametag+LAMETAG_ENCODERDELAYS, NULL, 24);
800 p->encDelay=(short)((delay>>12)&0xfff);
801 p->encPadding=(short)(delay&0xfff);
802 printf(" Encoder delay (start) : %d samples\n",p->encDelay);
803 printf(" Encoder padding (end) : %d samples\n",p->encPadding);
804 printf(" [ Length of original audio : %u samples ]\n",
805 /* length = frames * samples_per_granule * granules_per_frame - delay - padding */
806 (p->reported_frames * 576 * ((p->header&HEADER_FIELD_LSF)?2:1)) - p->encDelay - p->encPadding);
807 c=p->lametag[LAMETAG_MISCINFOS];
808 /* this single byte holds four noticeable fields - here three are shown
809 fields are 2 + 1 + 3 + 2 bit long (msb to lsb) */
810 printf(" Encoding mode : ");
811 switch (c&0x1c)
812 {
813 case 24:
814 printf("intensity stereo");
815 break;
816 case 20:
817 printf("auto");
818 break;
819 case 16:
820 printf("forced MS stereo");
821 break;
822 case 12:
823 printf("joint stereo");
824 break;
825 case 8:
826 printf("dual channel");
827 break;
828 case 4:
829 printf("simple LR stereo");
830 break;
831 case 0:
832 printf("mono");
833 break;
834 default:
835 printf("other");
836 }
837 printf("\n Unwise settings : %sused\n",(c&32)?"":"not ");
838 printf(" Source frequency : ");
839 switch (c&0xc0)
840 {
841 case 128:
842 printf("48 kHz");
843 break;
844 case 64:
845 printf("44.1 kHz");
846 break;
847 case 0:
848 printf("32 kHz or below");
849 break;
850 default:
851 printf("higher than 48 kHz");
852 }
853 j=extract_bits((unsigned char *)p->lametag+LAMETAG_PRESETINFO, NULL, 16)&0x7ff; /* 11 least significant bits are used for preset */
854 printf("\n Preset : ");
855 if (j==0)
856 printf("No preset.");
857 else
858 {
859 if (j<321)
860 printf("%d kbps",j);
861 else
862 {
863 /* using values from lame internal presets */
864 if (j>409 && j<501)
865 printf("V%d / VBR_%d",50-j/10,j-400);
866 else
867 {
868 if (j>999 && j<1008)
869 {
870 switch (j)
871 {
872 case 1000:
873 printf("R3mix.");
874 break;
875 case 1001:
876 printf("Standard.");
877 break;
878 case 1002:
879 printf("Extreme.");
880 break;
881 case 1003:
882 printf("Insane.");
883 break;
884 case 1004:
885 printf("Standard fast.");
886 break;
887 case 1005:
888 printf("Extreme fast.");
889 break;
890 case 1006:
891 printf("Medium.");
892 break;
893 case 1007:
894 printf("Medium fast.");
895 break;
896 }
897 }
898 else
899 printf("Unknown preset.");
900 }
901 }
902 }
903 printf("\n Originally encoded : %u bytes\n",extract_bits((unsigned char *)p->lametag+LAMETAG_MUSICLENGTH, NULL, 32));
904 printf(" Tag verification : %s\n", (p->lametagVerified?"passed":"failed"));
905 }
906 else
907 printf("no\n");
908 }
909 printf("\n");
910 }
911
912 ///////////////////////////////////////////////////////
913
show_id3v1(id3tag * id3)914 void show_id3v1(id3tag *id3)
915 {
916 int n_genres;
917 unsigned char i, id3v11;
918
919 printf(" Title : ");
920 for(i=0;i<30;i++)
921 if (isprint(id3->title[i])) putchar(id3->title[i]); else putchar('.');
922
923 printf("\n Artist : ");
924 for(i=0;i<30;i++)
925 if (isprint(id3->artist[i])) putchar(id3->artist[i]); else putchar('.');
926
927 printf("\n Album : ");
928 for(i=0;i<30;i++)
929 if (isprint(id3->album[i])) putchar(id3->album[i]); else putchar('.');
930
931 printf("\n Year : ");
932 for(i=0;i<4;i++)
933 if (isprint(id3->year[i])) putchar(id3->year[i]); else putchar('.');
934
935 id3v11 = (!id3->comment[28]&&id3->comment[29]);
936 printf("\n Comment : ");
937 if (id3v11)
938 {
939 for(i=0;i<28;i++)
940 if (isprint(id3->comment[i])) putchar(id3->comment[i]); else putchar('.');
941 printf("\n Track # : %u", id3->comment[29]);
942 }
943 else
944 for(i=0;i<30;i++)
945 if (isprint(id3->comment[i])) putchar(id3->comment[i]); else putchar('.');
946
947 n_genres = sizeof(genre_list) / sizeof(char *);
948 printf("\n Genre : ");
949 if (id3->genre < n_genres)
950 printf("%s", genre_list[id3->genre]);
951 else
952 printf("unknown");
953 printf("\n\n");
954 }
955
checkid3v1(FILE * fi,off_t pos,id3tag * id3)956 int checkid3v1(FILE *fi, off_t pos, id3tag *id3)
957 /*
958 * Here the info tag id3v1.x is detected
959 * This function returns either the offset of the tag
960 * or the offset of EOF if no tag is found,
961 * so the main cycle can stop scanning when this value has been reached
962 * Note: the file pointer IS modified and then it IS restored
963 */
964 {
965 off_t filepos;
966 int id3size=0;
967
968 if (pos-(signed)sizeof(id3tag) >= 0)
969 {
970 filepos=ftello(fi);
971 fseeko(fi,pos-sizeof(id3tag),SEEK_SET);
972
973 if (fread(id3,sizeof(id3tag),1,fi)==1)
974 {
975 if ((id3->tag[0] == 'T' && id3->tag[1] == 'A' && id3->tag[2] == 'G')
976 ||
977 (id3->tag[0] == 't' && id3->tag[1] == 'a' && id3->tag[2] == 'g'))
978 id3size = sizeof(id3tag);
979 }
980 fseeko(fi,filepos,SEEK_SET);
981 }
982 return id3size;
983 }
984
985 /*
986 * Since revision 4, ID3v2 may be found at the file tail also.
987 * Here we'll check for its presence seeking its footer,
988 * which is mandatory when the tag is placed at the bitstream end.
989 *
990 * If the tag is not found, return value is 0.
991 * If errors are detected, return value is -1.
992 * Note: this routine DOES read data from the input file
993 * but it DOES restore the file pointer before exiting.
994 */
checkid3v2_footer(FILE * fi,off_t pos,unsigned char * idMaj,unsigned char * idmin)995 int checkid3v2_footer(FILE *fi, off_t pos, unsigned char *idMaj, unsigned char *idmin)
996 {
997 unsigned char footer[ID3V2_FOOTER_LENGTH];
998 int id3v2size=0;
999 off_t filepos=ftello(fi);
1000
1001 if ((pos-ID3V2_FOOTER_LENGTH)>=0)
1002 {
1003 fseeko(fi,pos-ID3V2_FOOTER_LENGTH,SEEK_SET);
1004
1005 if (fread(footer,ID3V2_FOOTER_LENGTH,1,fi)==1)
1006 {
1007 if (footer[0] == '3' && footer[1] == 'D' && footer[2] == 'I')
1008 {
1009 /* footer found! */
1010 *idMaj=footer[3];
1011 *idmin=footer[4];
1012
1013 if (!(footer[6]&0x80) && !(footer[7]&0x80) && !(footer[8]&0x80) && !(footer[9]&0x80) && !(footer[5]&0x0f))
1014 {
1015 id3v2size = footer[6]*2097152+
1016 footer[7]*16384+
1017 footer[8]*128+
1018 footer[9] +ID3V2_HEADER_LENGTH +ID3V2_FOOTER_LENGTH;
1019 }
1020 else
1021 id3v2size=-1;
1022 }
1023 }
1024
1025 fseeko(fi,filepos,SEEK_SET);
1026 }
1027 return id3v2size;
1028 }
1029
1030
checkapetagx(apefooter_t * af)1031 unsigned int checkapetagx(apefooter_t *af)
1032 {
1033 unsigned int ape_len = 0;
1034
1035 if (!memcmp(af->preamble,APETAGEX_SIGNATURE,8))
1036 {
1037 /* ape tag found! */
1038 ape_len=get_little_endian_uint(af->tag_size);
1039 if ((get_little_endian_uint(af->tag_flags)&APETAGEX_FLAGS_HEADER_PRESENT)!=0)
1040 {
1041 /* tag contains a header */
1042 ape_len+=sizeof(apefooter_t);
1043 }
1044 }
1045
1046 return ape_len;
1047
1048 }
1049
1050 /*
1051 * check for ape tag at the end of the file
1052 * when placed at the end of the file (between the very last frame and the id3v1 tag)
1053 * ape tag version can be both 1 and 2. Tag version is returned into `ape_vers', if found.
1054 * search is started at file position `pos' where the end of mpeg stream is expected to be.
1055 * return value is tag length if found, else zero.
1056 * file pointer doesn't get modified
1057 */
checkapetagx_tail(FILE * fi,off_t pos,int * ape_vers,int * ape_items,char * header_present)1058 int checkapetagx_tail(FILE *fi, off_t pos, int *ape_vers, int *ape_items, char *header_present)
1059 {
1060 int ape_len=0;
1061 apefooter_t apefooter;
1062 off_t filepos;
1063
1064 if ((pos-(signed)sizeof(apefooter_t))>=0)
1065 {
1066 filepos=ftello(fi);
1067 fseeko(fi, pos-sizeof(apefooter_t), SEEK_SET);
1068 if (fread((void *)&apefooter,sizeof(apefooter_t),1,fi)==1)
1069 {
1070 if ((ape_len=checkapetagx(&apefooter)) != 0)
1071 {
1072 *ape_vers=get_little_endian_uint(apefooter.version);
1073 *ape_items=get_little_endian_uint(apefooter.item_count);
1074 *header_present=((get_little_endian_uint(apefooter.tag_flags)&APETAGEX_FLAGS_HEADER_PRESENT)!=0);
1075 }
1076 }
1077 fseeko(fi, filepos, SEEK_SET);
1078 }
1079
1080 return ape_len;
1081 }
1082
1083 /*
1084 * check for a LYRICS3 tag ending at file position 'pos'
1085 * the tag ends with the label 'LYRICSEND'
1086 */
checklyrics3v1(FILE * fi,off_t pos)1087 int checklyrics3v1(FILE *fi, off_t pos)
1088 {
1089 int lyr3_len=0;
1090 unsigned char lyrics3v1_tag[LYRICS3V1_TAG_MAXSIZE];
1091 off_t filepos=ftello(fi);
1092 unsigned char sign[LYRICS3_END_SIGNATURE_LEN],*p;
1093
1094 fseeko(fi, pos-LYRICS3_END_SIGNATURE_LEN, SEEK_SET);
1095 if (fread(sign,LYRICS3_END_SIGNATURE_LEN,1,fi)==1)
1096 {
1097 if (!memcmp(sign,LYRICS3V1_END_SIGNATURE,LYRICS3_END_SIGNATURE_LEN))
1098 {
1099 /* label found */
1100 fseeko(fi,pos-LYRICS3V1_TAG_MAXSIZE-LYRICS3_END_SIGNATURE_LEN,SEEK_SET);
1101 if (fread(lyrics3v1_tag,1,LYRICS3V1_TAG_MAXSIZE,fi)==LYRICS3V1_TAG_MAXSIZE)
1102 {
1103 /* the tag has a limited max size, and this comes very handy
1104 since there's no information about tag size anywhere */
1105 if ((p=memsrch(lyrics3v1_tag,LYRICS3V1_TAG_MAXSIZE,LYRICS3_BEGIN_SIGNATURE))!=NULL)
1106 {
1107 /* begin label was found too - we can calculate the tag size */
1108 lyr3_len = LYRICS3V1_TAG_MAXSIZE-(int)(p-lyrics3v1_tag)+LYRICS3_END_SIGNATURE_LEN;
1109 }
1110 }
1111 }
1112 }
1113
1114 fseeko(fi, filepos, SEEK_SET);
1115 return lyr3_len;
1116 }
1117
1118 /*
1119 * check for a Lyrics3 v2.00 tag ending at file position 'pos'
1120 * this new tag has a more complete footer including its size
1121 */
checklyrics3v2(FILE * fi,off_t pos)1122 int checklyrics3v2(FILE *fi, off_t pos)
1123 {
1124 int lyr3_len=0;
1125 off_t filepos=ftello(fi);
1126 unsigned char sign[LYRICS3V2_TAGSIZE_LEN+LYRICS3_END_SIGNATURE_LEN],*p;
1127
1128 fseeko(fi, pos-LYRICS3_END_SIGNATURE_LEN-LYRICS3V2_TAGSIZE_LEN, SEEK_SET);
1129 if (fread(sign,LYRICS3_END_SIGNATURE_LEN+LYRICS3V2_TAGSIZE_LEN,1,fi)==1)
1130 {
1131 if (!memcmp(&sign[LYRICS3V2_TAGSIZE_LEN],LYRICS3V2_END_SIGNATURE,LYRICS3_END_SIGNATURE_LEN))
1132 {
1133 /* we've found the end signature - the 6 bytes at the very beginning
1134 are the tag size in string format */
1135 lyr3_len = strtol((char *)sign, NULL, 10) + LYRICS3_END_SIGNATURE_LEN + LYRICS3V2_TAGSIZE_LEN;
1136 /* seek back where the begin signature is expected to be */
1137 fseeko(fi, -lyr3_len, SEEK_CUR);
1138 if (fread(sign,LYRICS3_BEGIN_SIGNATURE_LEN,1,fi)==1)
1139 {
1140 if ((p=memsrch(sign,LYRICS3V2_TAGSIZE_LEN+LYRICS3_END_SIGNATURE_LEN,LYRICS3_BEGIN_SIGNATURE))!=sign)
1141 {
1142 /* mismatch! - probably the tag is corrupted */
1143 lyr3_len = 0;
1144 }
1145 }
1146 else
1147 {
1148 lyr3_len = 0;
1149 }
1150 }
1151 }
1152
1153 fseeko(fi, filepos, SEEK_SET);
1154 return lyr3_len;
1155 }
1156
1157 /*
1158 * check for the MusicMatch tag
1159 * this search is heavily based upon unofficial documentation at
1160 * https://github.com/dreamindustries/id3lib/blob/master/doc/musicmatch.txt
1161 */
checkmmtag(FILE * fi,off_t pos,mmtag_t * mmtag)1162 void checkmmtag(FILE *fi, off_t pos, mmtag_t *mmtag)
1163 {
1164 mmtag_tail_infos_t mm_tail_infos;
1165 unsigned char search[MMTAG_SAFE_SEARCH_SIZE], *p;
1166 off_t filepos=ftello(fi);
1167 unsigned int section_sizes[MMTAG_OFFSET_ENTRIES];
1168 int j;
1169
1170 fseeko(fi, pos-MMTAG_FOOTER_SIZE-MMTAG_DATA_OFFSETS_SIZE, SEEK_SET);
1171 if (fread((unsigned char *)&mm_tail_infos,sizeof(mmtag_tail_infos_t),1,fi)==1)
1172 {
1173 /* in a single read we got both the 'data offsets' section and the 'footer' */
1174 if (!memcmp(&mm_tail_infos.footer[MMTAG_SIGNATURE_OFFSET], MMTAG_SIGNATURE, MMTAG_SIGNATURE_LEN))
1175 {
1176 /* we found the signature into the footer - store the version string */
1177 memcpy(mmtag->tag_ver, &mm_tail_infos.footer[MMTAG_VERSION_OFFSET], MMTAG_VERSION_LEN);
1178
1179 fseeko(fi, pos-MMTAG_FOOTER_SIZE-MMTAG_DATA_OFFSETS_SIZE-MMTAG_META_DATA_MINIMUM_SIZE-MMTAG_SAFE_SEARCH_SIZE, SEEK_SET);
1180 if (fread(search,MMTAG_SAFE_SEARCH_SIZE,1,fi)==1)
1181 {
1182 /* we've read a whole bunch of bytes including the version block for sure BUT NOT the optional header */
1183 if ((p=memsrch(search, MMTAG_SAFE_SEARCH_SIZE, MMTAG_VERSION_BLOCK_SYNC_STRING))!=NULL)
1184 {
1185 /* version block found! - store both the MusicMatch and the Xing encoder version strings */
1186 memcpy(mmtag->mm_ver, &p[MMTAG_VERSION_BLOCK_MM_VER_OFFSET], MMTAG_VERSION_BLOCK_STRING_LEN);
1187 memcpy(mmtag->enc_ver, &p[MMTAG_VERSION_BLOCK_XING_VER_OFFSET], MMTAG_VERSION_BLOCK_STRING_LEN);
1188
1189 /* calculate the sizes of the different blocks */
1190 section_sizes[MMTAG_HEADER] = MMTAG_HEADER_SIZE;
1191 section_sizes[MMTAG_IMAGE_EXTENSION] = get_little_endian_uint(mm_tail_infos.image_binary)-
1192 get_little_endian_uint(mm_tail_infos.image_extension);
1193 section_sizes[MMTAG_IMAGE_BINARY] = get_little_endian_uint(mm_tail_infos.unused)-
1194 get_little_endian_uint(mm_tail_infos.image_binary);
1195 section_sizes[MMTAG_UNUSED] = get_little_endian_uint(mm_tail_infos.version_info)-
1196 get_little_endian_uint(mm_tail_infos.unused);
1197 section_sizes[MMTAG_VERSION_INFO] = get_little_endian_uint(mm_tail_infos.audio_metadata)-
1198 get_little_endian_uint(mm_tail_infos.version_info);
1199 section_sizes[MMTAG_AUDIO_METADATA] = MMTAG_SAFE_SEARCH_SIZE-(int)(p-search)-MMTAG_VERSION_INFO_SIZE+MMTAG_META_DATA_MINIMUM_SIZE;
1200 mmtag->metadata_size = section_sizes[MMTAG_AUDIO_METADATA];
1201
1202 mmtag->tag_size = MMTAG_DATA_OFFSETS_SIZE + MMTAG_FOOTER_SIZE;
1203 for (j=MMTAG_IMAGE_EXTENSION; j<MMTAG_OFFSET_ENTRIES; j++)
1204 mmtag->tag_size += section_sizes[j];
1205
1206 /* now, seek back to collect further data and check whether the optional header is there */
1207 fseeko(fi, pos-mmtag->tag_size-MMTAG_HEADER_SIZE, SEEK_SET);
1208 if (fread(search,MMTAG_SAFE_SEARCH_SIZE,1,fi)==1)
1209 {
1210 memcpy(mmtag->image_ext, &search[MMTAG_HEADER_SIZE], MMTAG_IMAGE_EXTENSION_LEN);
1211 mmtag->image_size = search[MMTAG_HEADER_SIZE+MMTAG_IMAGE_EXTENSION_LEN]+
1212 search[MMTAG_HEADER_SIZE+MMTAG_IMAGE_EXTENSION_LEN+1]*256+
1213 search[MMTAG_HEADER_SIZE+MMTAG_IMAGE_EXTENSION_LEN+2]*256*256+
1214 search[MMTAG_HEADER_SIZE+MMTAG_IMAGE_EXTENSION_LEN+3]*256*256*256;
1215 mmtag->image_offset = pos-mmtag->tag_size+MMTAG_IMAGE_EXTENSION_LEN+MMTAG_IMAGE_SIZE_LEN;
1216 mmtag->header_present = (memsrch(search, MMTAG_SAFE_SEARCH_SIZE, MMTAG_VERSION_BLOCK_SYNC_STRING)==search);
1217 if (mmtag->header_present)
1218 mmtag->tag_size += MMTAG_HEADER_SIZE;
1219 }
1220 }
1221 }
1222 }
1223 }
1224
1225 fseeko(fi, filepos, SEEK_SET);
1226 }
1227
checkmm_partial_tag(FILE * fi,off_t pos,mmtag_t * mmtag)1228 char checkmm_partial_tag(FILE *fi, off_t pos, mmtag_t *mmtag)
1229 {
1230 mmtag_partial_infos_t mm_infos;
1231 char present=0;
1232
1233 off_t filepos=ftello(fi);
1234
1235 fseeko(fi, pos, SEEK_SET);
1236 if (fread((unsigned char *)&mm_infos,sizeof(mmtag_partial_infos_t),1,fi)==1)
1237 {
1238 if (!memcmp(&mm_infos.sync, MMTAG_VERSION_BLOCK_SYNC_STRING, MMTAG_VERSION_BLOCK_SYNC_LENGTH))
1239 {
1240 memcpy(mmtag->mm_ver, mm_infos.musm, MMTAG_VERSION_BLOCK_STRING_LEN);
1241 memcpy(mmtag->enc_ver, mm_infos.xing, MMTAG_VERSION_BLOCK_STRING_LEN);
1242 present=1;
1243 }
1244 }
1245
1246 fseeko(fi, filepos, SEEK_SET);
1247 return present;
1248 }
1249
1250
1251 /*
1252 * Here the info tag id3v2 is detected
1253 * This function returns the size of the tag (if detected)
1254 * so the main cycle can choose if either show it or skip it.
1255 * Also, idMaj and idmin provide id3V2 major and minor version number.
1256 * If the tag is not found, return value is 0.
1257 * If errors are detected, return value is -1.
1258 */
checkid3v2(unsigned char * buff,int length,int * next_tag,unsigned char * idMaj,unsigned char * idmin)1259 int checkid3v2(unsigned char *buff, int length, int *next_tag, unsigned char *idMaj, unsigned char *idmin)
1260 {
1261 unsigned char *id3header;
1262 int id3v2size=0;
1263
1264 if ((id3header=memsrch(buff, length, ID3V2_ID_STRING)) != NULL)
1265 {
1266 /* has ID3v2 */
1267 *idMaj=id3header[3];
1268 *idmin=id3header[4];
1269 if (!(id3header[6]&0x80) && !(id3header[7]&0x80) && !(id3header[8]&0x80) && !(id3header[9]&0x80) && !(id3header[5]&0x0f))
1270 {
1271 id3v2size = id3header[6]*2097152+id3header[7]*16384+id3header[8]*128+id3header[9] +ID3V2_HEADER_LENGTH;
1272 if (id3header[5]&ID3V2_FLAGS_FOOTER_PRESENT)
1273 id3v2size += ID3V2_FOOTER_LENGTH;
1274 *next_tag = (int)(id3header-buff);
1275 }
1276 else
1277 id3v2size=-1;
1278 }
1279
1280 return id3v2size;
1281 }
1282
checkapetagx_head(unsigned char * buff,int length,int * next_tag,int * ape_vers,int * ape_items,char * header_present)1283 int checkapetagx_head(unsigned char *buff, int length, int *next_tag, int *ape_vers, int *ape_items, char *header_present)
1284 {
1285 int ape_len=0;
1286 unsigned int hflags;
1287 apefooter_t apefooter;
1288 unsigned char *p_apefooter;
1289
1290 if ((p_apefooter=memsrch(buff, length, APETAGEX_SIGNATURE)) != NULL)
1291 {
1292 memcpy((void *)&apefooter, p_apefooter, sizeof(apefooter_t));
1293
1294 if ((ape_len=checkapetagx(&apefooter)) != 0)
1295 {
1296 hflags = get_little_endian_uint(apefooter.tag_flags);
1297 if ((hflags&APETAGEX_FLAGS_HEADER_PRESENT)!=0 && (hflags&APETAGEX_FLAGS_THIS_IS_HEADER)!=0)
1298 {
1299 *ape_vers=get_little_endian_uint(apefooter.version);
1300 *ape_items=get_little_endian_uint(apefooter.item_count);
1301 *header_present=1;
1302 *next_tag = (int)(p_apefooter - buff);
1303 }
1304 else
1305 {
1306 /* very strange tag - header MUST be present when put at the file head! */
1307 /* I will assume this as a data corruption */
1308 ape_len = 0;
1309 }
1310 }
1311 }
1312
1313 return ape_len;
1314 }
1315
checkwaveriff_datachunk(unsigned char * buff,int * next_tag,int * datachunk)1316 int checkwaveriff_datachunk(unsigned char *buff, int *next_tag, int *datachunk)
1317 {
1318 int chunk_len = 0;
1319
1320 if (
1321 isprint(buff[0])
1322 &&
1323 isprint(buff[1])
1324 &&
1325 isprint(buff[2])
1326 &&
1327 isprint(buff[3])
1328 )
1329 {
1330 *next_tag = 0;
1331 if (memcmp(buff, WAVE_RIFF_DATA_ID, WAVE_RIFF_IDS_LENGTH))
1332 {
1333 /* not the `data' chunk */
1334 chunk_len = get_little_endian_uint(&buff[4]) + WAVE_RIFF_IDS_LENGTH + sizeof(unsigned int);
1335 *datachunk = 0;
1336 }
1337 else
1338 {
1339 /* `data' chunk found */
1340 chunk_len = WAVE_RIFF_IDS_LENGTH + sizeof(unsigned int);
1341 *datachunk = get_little_endian_uint(&buff[4]);
1342 }
1343 }
1344
1345 return chunk_len;
1346 }
1347
checkwaveriff(unsigned char * buff,int length,int * next_tag)1348 int checkwaveriff(unsigned char *buff, int length, int *next_tag)
1349 {
1350 int riff_len=0;
1351 unsigned char *waveriff;
1352
1353 if ((waveriff=memsrch(buff, length, WAVE_RIFF_STRUCTURE_ID)) != NULL)
1354 {
1355 /* "RIFF" found */
1356 if (memcmp(&waveriff[8], WAVE_RIFF_WAVE_ID, WAVE_RIFF_IDS_LENGTH)==0)
1357 {
1358 /* "WAVE" found */
1359 riff_len = WAVE_RIFF_HEADER_LENGTH;
1360 *next_tag = (int)(waveriff - buff);
1361 }
1362 }
1363
1364 return riff_len;
1365 }
1366