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