Coverage Report

Created: 2025-11-11 06:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mpg123/src/libmpg123/id3.c
Line
Count
Source
1
/*
2
  id3: ID3v2.3 and ID3v2.4 parsing (a relevant subset)
3
4
  copyright 2006-2023 by the mpg123 project - free software under the terms of the LGPL 2.1
5
  see COPYING and AUTHORS files in distribution or http://mpg123.org
6
  initially written by Thomas Orgis
7
8
  WIP: Handling of multiple ID3 tags in a stream.
9
10
  1. With update flag: Add non-unique data, replace unique.
11
  - Only one TALB, TPE1, etc.
12
  - Only one TXXX with a certain description.
13
  - Only one COMM with certain language and description.
14
  - Only one APIC with certain type and description, generally only one
15
    of type 1 and 2 each.
16
  2. Without update flag: wipe whole data and only store new stuff.
17
18
  BIG BAD BUT: How to properly handle seeks in a stream that make
19
  the parser encounter the same tags again in random order? Is
20
  there even a correct way to handle that without storing an
21
  ordered list of all tags? I could simplify the code here and just
22
  communicate that a frame should be an update to previous, and
23
  at which stream position the frame was encountered. But since
24
  libmpg123 is driven by MPEG frames, there could be multiple
25
  ID3v2 tags in direct succession treated by the parser without
26
  the library user being able to interfere.
27
28
  This is severely fucked. All that complexity also doesn't matter
29
  in practice, as streams use ICY and individual files have just one
30
  ID3v2 tag (relevant for libmpg123).  It's an academic problem. But
31
  for seekable files, I could implement some jumping logic to find
32
  and parse all ID3v2 for once and then set a flag that only jumps
33
  the frames on seeks. That covers all local disk playback. For
34
  streams, seeking is no issue (seeking back, at least), so the
35
  update/replace logic works.
36
37
  Look at the standard:
38
39
------
40
5.   Tag location
41
42
   The default location of an ID3v2 tag is prepended to the audio so
43
   that players can benefit from the information when the data is
44
   streamed. It is however possible to append the tag, or make a
45
   prepend/append combination. When deciding upon where an unembedded
46
   tag should be located, the following order of preference SHOULD be
47
   considered.
48
   
49
     1. Prepend the tag.
50
51
     2. Prepend a tag with all vital information and add a second tag at 
52
        the end of the file, before tags from other tagging systems. The
53
        first tag is required to have a SEEK frame.
54
      
55
     3. Add a tag at the end of the file, before tags from other tagging
56
        systems.
57
      
58
   In case 2 and 3 the tag can simply be appended if no other known tags
59
   are present. The suggested method to find ID3v2 tags are:
60
   
61
     1. Look for a prepended tag using the pattern found in section 3.1.
62
63
     2. If a SEEK frame was found, use its values to guide further
64
        searching.
65
66
     3. Look for a tag footer, scanning from the back of the file.
67
68
   For every new tag that is found, the old tag should be discarded
69
   unless the update flag in the extended header (section 3.2) is set.
70
------
71
72
  For seekable streams, I simply need to implement explicit ID3v2 search along
73
  that recommendation and keep the complete information. Streams that continue
74
  growing during playback will not recognize added ID3v2 tags. So be it.
75
  For non-seekable streams, a tag is always parsed when encountered, assuming
76
  the order of update tags always matches.
77
78
  First step for the 1.26 release shall be the implementaton of the update
79
  logic and glossing over the theoretical problem of re-parsing update
80
  frames in the wrong order by ignoring it. They are not that relevant.
81
82
  TODO: Cave in and add the missing frames from the spec. Not that far to go.
83
  But need another data structure to communicate those ...
84
*/
85
86
#include "mpg123lib_intern.h"
87
#include "id3.h"
88
#include "../common/debug.h"
89
90
#ifndef NO_ID3V2 /* Only the main parsing routine will always be there. */
91
92
/* We know the usual text frames plus some specifics. */
93
55.2k
#define KNOWN_FRAMES 5
94
static const char frame_type[KNOWN_FRAMES][5] = { "COMM", "TXXX", "RVA2", "USLT", "APIC" };
95
enum frame_types { unknown = -2, text = -1, comment, extra, rva2, uslt, picture };
96
97
/* UTF support definitions */
98
99
typedef void (*text_converter)(mpg123_string *sb, const unsigned char* source, size_t len, const int noquiet);
100
101
static void convert_latin1  (mpg123_string *sb, const unsigned char* source, size_t len, const int noquiet);
102
static void convert_utf16bom(mpg123_string *sb, const unsigned char* source, size_t len, const int noquiet);
103
static void convert_utf8    (mpg123_string *sb, const unsigned char* source, size_t len, const int noquiet);
104
105
static const text_converter text_converters[4] =
106
{
107
  convert_latin1,
108
  /* We always check for (multiple) BOM in 16bit unicode. Without BOM, UTF16 BE is the default.
109
     Errors in encoding are detected anyway. */
110
  convert_utf16bom,
111
  convert_utf16bom,
112
  convert_utf8
113
};
114
115
static const unsigned int encoding_widths[4] = { 1, 2, 2, 1 };
116
117
/* the code starts here... */
118
119
static void null_id3_links(mpg123_handle *fr)
120
53.0k
{
121
53.0k
  fr->id3v2.title  = NULL;
122
53.0k
  fr->id3v2.artist = NULL;
123
53.0k
  fr->id3v2.album  = NULL;
124
53.0k
  fr->id3v2.year   = NULL;
125
53.0k
  fr->id3v2.genre  = NULL;
126
53.0k
  fr->id3v2.comment = NULL;
127
53.0k
}
128
129
void INT123_init_id3(mpg123_handle *fr)
130
53.0k
{
131
53.0k
  fr->id3v2.version = 0; /* nothing there */
132
53.0k
  null_id3_links(fr);
133
53.0k
  fr->id3v2.comments     = 0;
134
53.0k
  fr->id3v2.comment_list = NULL;
135
53.0k
  fr->id3v2.texts    = 0;
136
53.0k
  fr->id3v2.text     = NULL;
137
53.0k
  fr->id3v2.extras   = 0;
138
53.0k
  fr->id3v2.extra    = NULL;
139
53.0k
  fr->id3v2.pictures   = 0;
140
53.0k
  fr->id3v2.picture    = NULL;
141
53.0k
}
142
143
/* Managing of the text, comment and extra lists. */
144
145
/* Initialize one element. */
146
static void init_mpg123_text(mpg123_text *txt)
147
26.9k
{
148
26.9k
  mpg123_init_string(&txt->text);
149
26.9k
  mpg123_init_string(&txt->description);
150
26.9k
  txt->id[0] = 0;
151
26.9k
  txt->id[1] = 0;
152
26.9k
  txt->id[2] = 0;
153
26.9k
  txt->id[3] = 0;
154
26.9k
  txt->lang[0] = 0;
155
26.9k
  txt->lang[1] = 0;
156
26.9k
  txt->lang[2] = 0;
157
26.9k
}
158
159
static void init_mpg123_picture(mpg123_picture *pic)
160
0
{
161
0
  mpg123_init_string(&pic->mime_type);
162
0
  mpg123_init_string(&pic->description);
163
0
  pic->type = 0;
164
0
  pic->size = 0;
165
0
  pic->data = NULL;
166
0
}
167
168
/* Free memory of one element. */
169
static void free_mpg123_text(mpg123_text *txt)
170
25.5k
{
171
25.5k
  mpg123_free_string(&txt->text);
172
25.5k
  mpg123_free_string(&txt->description);
173
25.5k
}
174
175
static void free_mpg123_picture(mpg123_picture * pic)
176
0
{
177
0
  mpg123_free_string(&pic->mime_type);
178
0
  mpg123_free_string(&pic->description);
179
0
  if (pic->data != NULL)
180
0
    free(pic->data);
181
0
}
182
183
/* Free memory of whole list. */
184
53.0k
#define free_comment(mh) free_id3_text(&((mh)->id3v2.comment_list), &((mh)->id3v2.comments))
185
53.0k
#define free_text(mh)    free_id3_text(&((mh)->id3v2.text),         &((mh)->id3v2.texts))
186
53.0k
#define free_extra(mh)   free_id3_text(&((mh)->id3v2.extra),        &((mh)->id3v2.extras))
187
53.0k
#define free_picture(mh) free_id3_picture(&((mh)->id3v2.picture),   &((mh)->id3v2.pictures))
188
static void free_id3_text(mpg123_text **list, size_t *size)
189
159k
{
190
159k
  size_t i;
191
172k
  for(i=0; i<*size; ++i) free_mpg123_text(&((*list)[i]));
192
193
159k
  free(*list);
194
159k
  *list = NULL;
195
159k
  *size = 0;
196
159k
}
197
static void free_id3_picture(mpg123_picture **list, size_t *size)
198
53.0k
{
199
53.0k
  size_t i;
200
53.0k
  for(i=0; i<*size; ++i) free_mpg123_picture(&((*list)[i]));
201
202
53.0k
  free(*list);
203
53.0k
  *list = NULL;
204
53.0k
  *size = 0;
205
53.0k
}
206
207
/* Add items to the list. */
208
209
8.14k
#define add_comment(mh, l, d) add_id3_text(&((mh)->id3v2.comment_list), &((mh)->id3v2.comments), NULL,    l, d)
210
2.04k
#define add_text(mh, id)      add_id3_text(&((mh)->id3v2.text),         &((mh)->id3v2.texts),      id, NULL, NULL)
211
423
#define add_uslt(mh, l, d)    add_id3_text(&((mh)->id3v2.text),         &((mh)->id3v2.texts),      id, l, d)
212
7.92k
#define add_extra(mh, d)      add_id3_text(&((mh)->id3v2.extra),        &((mh)->id3v2.extras),   NULL, NULL, d)
213
0
#define add_picture(mh, t, d) add_id3_picture(&((mh)->id3v2.picture), &((mh)->id3v2.pictures), t, d)
214
static mpg123_text *add_id3_text( mpg123_text **list, size_t *size
215
, char id[4], char lang[3], mpg123_string *description )
216
14.2k
{
217
14.2k
  mdebug( "add_id3_text id=%s lang=%s, desc=%s"
218
14.2k
  , id ? (char[5]) { id[0], id[1], id[2], id[3], 0 } : "(nil)"
219
14.2k
  , lang ? (char[4]) { lang[0], lang[1], lang[2], 0 }  : "(nil)"
220
14.2k
  , description ? (description->fill ? description->p : "(empty)") : "(nil)" );
221
14.2k
  if(lang && !description)
222
0
    return NULL; // no lone language intended
223
14.2k
  if(id || description)
224
14.2k
  {
225
    // Look through list of existing texts and return an existing entry
226
    // if it should be overwritten.
227
19.1k
    for(size_t i=0; i<*size; ++i)
228
5.84k
    {
229
5.84k
      mpg123_text *entry = *list+i;
230
5.84k
      if(description)
231
4.34k
      { // Overwrite entry with same description and same ID and language.
232
4.34k
        if( (!id || !memcmp(id, entry->id, 4))
233
4.14k
          && (!lang || !memcmp(entry->lang, lang, 3))
234
3.29k
          && mpg123_same_string(&(entry->description), description)
235
4.34k
        )
236
708
        return entry;
237
4.34k
      } else if(id && !memcmp(id, entry->id, 4))
238
260
        return entry; // Just ovewrite because of same ID.
239
4.87k
      mdebug("add_id3_text: entry %zu was no match", i);
240
4.87k
    }
241
14.2k
  }
242
13.2k
  mdebug("add_id3_text: append to list of %zu", *size);
243
  // Nothing found, add new one.
244
13.2k
  mpg123_text *x = INT123_safe_realloc(*list, sizeof(mpg123_text)*(*size+1));
245
13.2k
  if(x == NULL) return NULL; /* bad */
246
247
13.2k
  *list  = x;
248
13.2k
  *size += 1;
249
13.2k
  init_mpg123_text(&((*list)[*size-1]));
250
251
13.2k
  return &((*list)[*size-1]); /* Return pointer to the added text. */
252
13.2k
}
253
254
255
static mpg123_picture *add_id3_picture(mpg123_picture **list, size_t *size, char type, mpg123_string *description)
256
0
{
257
0
  if(!description)
258
0
    return NULL;
259
260
  // Return entry to overwrite, if appropriate.
261
0
  for(size_t i=0; i<*size; ++i)
262
0
  {
263
0
    mpg123_picture *entry = *list+i;
264
0
    if(  type == entry->type
265
0
      && ( type == 1 || type == 2 ||
266
0
        mpg123_same_string(&entry->description, description)
267
0
      )
268
0
    )
269
0
      return entry;
270
0
  }
271
  // Append a new one.
272
0
  mpg123_picture *x = INT123_safe_realloc(*list, sizeof(mpg123_picture)*(*size+1));
273
0
  if(x == NULL) return NULL; /* bad */
274
275
0
  *list  = x;
276
0
  *size += 1;
277
0
  init_mpg123_picture(&((*list)[*size-1]));
278
279
0
  return &((*list)[*size-1]); /* Return pointer to the added picture. */
280
0
}
281
282
/* OK, back to the higher level functions. */
283
284
void INT123_exit_id3(mpg123_handle *fr)
285
53.0k
{
286
53.0k
  free_picture(fr);
287
53.0k
  free_comment(fr);
288
53.0k
  free_extra(fr);
289
53.0k
  free_text(fr);
290
53.0k
}
291
292
void INT123_reset_id3(mpg123_handle *fr)
293
46.3k
{
294
46.3k
  INT123_exit_id3(fr);
295
46.3k
  INT123_init_id3(fr);
296
46.3k
}
297
298
/* Set the id3v2.artist id3v2.title ... links to elements of the array. */
299
void INT123_id3_link(mpg123_handle *fr)
300
0
{
301
0
  size_t i;
302
0
  mpg123_id3v2 *v2 = &fr->id3v2;
303
0
  debug("linking ID3v2");
304
0
  null_id3_links(fr);
305
0
  for(i=0; i<v2->texts; ++i)
306
0
  {
307
0
    mpg123_text *entry = &v2->text[i];
308
0
    if     (!strncmp("TIT2", entry->id, 4)) v2->title  = &entry->text;
309
0
    else if(!strncmp("TALB", entry->id, 4)) v2->album  = &entry->text;
310
0
    else if(!strncmp("TPE1", entry->id, 4)) v2->artist = &entry->text;
311
0
    else if(!strncmp("TYER", entry->id, 4)) v2->year   = &entry->text;
312
0
    else if(!strncmp("TCON", entry->id, 4)) v2->genre  = &entry->text;
313
0
  }
314
0
  for(i=0; i<v2->comments; ++i)
315
0
  {
316
0
    mpg123_text *entry = &v2->comment_list[i];
317
0
    if(entry->description.fill == 0 || entry->description.p[0] == 0)
318
0
    v2->comment = &entry->text;
319
0
  }
320
  /* When no generic comment found, use the last non-generic one. */
321
0
  if(v2->comment == NULL && v2->comments > 0)
322
0
  v2->comment = &v2->comment_list[v2->comments-1].text;
323
0
}
324
325
/*
326
  Store ID3 text data in an mpg123_string; either verbatim copy or
327
  everything translated to UTF-8 encoding.
328
  Preserve the zero string separator (I don't need strlen for the total size).
329
330
  Since we can overwrite strings with ID3 update frames, don't free
331
  memory, just grow strings.
332
*/
333
static void store_id3_text(mpg123_string *sb, unsigned char encoding, unsigned char *source
334
, size_t source_size, const int noquiet, const int notranslate)
335
42.8k
{
336
42.8k
  if(sb) // Always overwrite, even with nothing.
337
42.8k
    sb->fill = 0;
338
42.8k
  if(!source_size)
339
1.25k
  {
340
1.25k
    debug("Empty id3 data!");
341
1.25k
    return;
342
1.25k
  }
343
344
  /* We shall just copy the data. Client wants to decode itself. */
345
41.5k
  if(notranslate)
346
0
  {
347
    /* Future: Add a path for ID3 errors. */
348
0
    if(!mpg123_grow_string(sb, source_size+1))
349
0
    {
350
0
      if(noquiet) error("Cannot resize target string, out of memory?");
351
0
      return;
352
0
    }
353
0
    sb->p[0] = (char)encoding;
354
0
    memcpy(sb->p+1, source, source_size);
355
0
    sb->fill = source_size+1;
356
0
    debug1("stored undecoded ID3 text of size %zu", source_size+1);
357
0
    return;
358
0
  }
359
360
41.5k
  if(encoding > mpg123_id3_enc_max)
361
230
  {
362
230
    if(noquiet)
363
230
      error1("Unknown text encoding %u, I take no chances, sorry!", encoding);
364
230
    return;
365
230
  }
366
41.3k
  INT123_id3_to_utf8(sb, encoding, source, source_size, noquiet);
367
368
41.3k
  if(sb->fill) debug1("UTF-8 string (the first one): %s", sb->p);
369
0
  else if(noquiet) error("unable to convert string to UTF-8 (out of memory, junk input?)!");
370
41.3k
}
371
372
/* On error, sb->size is 0. */
373
/* Also, encoding has been checked already! */
374
void INT123_id3_to_utf8(mpg123_string *sb, unsigned char encoding, const unsigned char *source, size_t source_size, int noquiet)
375
41.3k
{
376
41.3k
  unsigned int bwidth;
377
41.3k
  if(sb)
378
41.3k
    sb->fill = 0;
379
41.3k
  debug1("encoding: %u", encoding);
380
  /* A note: ID3v2.3 uses UCS-2 non-variable 16bit encoding, v2.4 uses UTF16.
381
     UTF-16 uses a reserved/private range in UCS-2 to add the magic, so we just always treat it as UTF. */
382
41.3k
  bwidth = encoding_widths[encoding];
383
  /* Hack! I've seen a stray zero byte before BOM. Is that supposed to happen? */
384
41.3k
  if(encoding != mpg123_id3_utf16be) /* UTF16be _can_ beging with a null byte! */
385
52.7k
  while(source_size > bwidth && source[0] == 0)
386
13.0k
  {
387
13.0k
    --source_size;
388
13.0k
    ++source;
389
13.0k
    debug("skipped leading zero");
390
13.0k
  }
391
41.3k
  if(source_size % bwidth)
392
1.08k
  {
393
    /* When we need two bytes for a character, it's strange to have an uneven bytestream length. */
394
1.08k
    if(noquiet) warning2("Weird tag size %d for encoding %u - I will probably trim too early or something but I think the MP3 is broken.", (int)source_size, encoding);
395
1.08k
    source_size -= source_size % bwidth;
396
1.08k
  }
397
41.3k
  text_converters[encoding](sb, source, source_size, noquiet);
398
41.3k
}
399
400
/* You have checked encoding to be in the range already. */
401
static unsigned char *next_text(unsigned char* prev, unsigned char encoding, size_t limit)
402
13.7k
{
403
13.7k
  unsigned char *text = prev;
404
13.7k
  size_t width = encoding_widths[encoding];
405
406
13.7k
  if(limit > PTRDIFF_MAX)
407
0
    return NULL;
408
409
  /* So I go lengths to find zero or double zero...
410
     Remember bug 2834636: Only check for aligned NULLs! */
411
169k
  while(text-prev < (ptrdiff_t)limit)
412
168k
  {
413
168k
    if(text[0] == 0)
414
14.8k
    {
415
14.8k
      if(width <= limit-(text-prev))
416
14.4k
      {
417
14.4k
        size_t i = 1;
418
15.6k
        for(; i<width; ++i) if(text[i] != 0) break;
419
420
14.4k
        if(i == width) /* found a null wide enough! */
421
12.4k
        {
422
12.4k
          text += width;
423
12.4k
          break;
424
12.4k
        }
425
14.4k
      }
426
391
      else return NULL; /* No full character left? This text is broken */
427
14.8k
    }
428
429
155k
    text += width;
430
155k
  }
431
13.3k
  if((size_t)(text-prev) >= limit) text = NULL;
432
433
13.3k
  return text;
434
13.7k
}
435
436
static const char *enc_name(unsigned char enc)
437
0
{
438
0
  switch(enc)
439
0
  {
440
0
    case 0:  return "Latin 1";
441
0
    case 1:  return "UTF-16 BOM";
442
0
    case 2:  return "UTF-16 BE";
443
0
    case 3:  return "UTF-8";
444
0
    default: return "unknown!";
445
0
  }
446
0
}
447
448
static void process_text(mpg123_handle *fr, unsigned char *realdata, size_t realsize, char *id)
449
2.04k
{
450
  /* Text encoding          $xx */
451
  /* The text (encoded) ... */
452
2.04k
  if(realsize < 1)
453
0
  {
454
0
    if(NOQUIET) error("Not even an encoding byte?");
455
0
    return;
456
0
  }
457
2.04k
  mpg123_text *t = add_text(fr, id);
458
2.04k
  if(VERBOSE4) fprintf(stderr, "Note: Storing text from %s encoding\n", enc_name(realdata[0]));
459
2.04k
  if(t == NULL)
460
0
  {
461
0
    if(NOQUIET) error("Unable to attach new text!");
462
0
    return;
463
0
  }
464
2.04k
  mdebug("process_text: (over)writing entry with ID %s", t->id[0]
465
2.04k
  ? (char[5]) { t->id[0], t->id[1], t->id[2], t->id[3], 0 }
466
2.04k
  : "(nil)" );
467
2.04k
  memcpy(t->id, id, 4);
468
2.04k
  store_id3_text( &t->text, realdata[0], realdata+1, realsize-1
469
2.04k
  , NOQUIET, fr->p.flags & MPG123_PLAIN_ID3TEXT );
470
2.04k
  if(VERBOSE4) // Do not print unsanitized text to terminals!
471
0
    fprintf(stderr, "Note: ID3v2 %c%c%c%c text frame stored\n", id[0], id[1], id[2], id[3]);
472
2.04k
}
473
474
static void process_picture(mpg123_handle *fr, unsigned char *realdata, size_t realsize)
475
0
{
476
0
  unsigned char encoding;
477
0
  mpg123_picture *i = NULL;
478
0
  unsigned char* workpoint = NULL;
479
0
  mpg123_string mime; mpg123_init_string(&mime);
480
0
  unsigned char image_type = 0;
481
0
  mpg123_string description;  mpg123_init_string(&description);
482
0
  unsigned char *image_data = NULL;
483
0
  if(realsize < 1)
484
0
  {
485
0
    debug("Empty id3 data!");
486
0
    return;
487
0
  }
488
0
  encoding = realdata[0];
489
0
  realdata++; realsize--;
490
0
  if(encoding > mpg123_id3_enc_max)
491
0
  {
492
0
    if(NOQUIET)
493
0
      error1("Unknown text encoding %u, I take no chances, sorry!", encoding);
494
0
    return;
495
0
  }
496
0
  if(VERBOSE4) fprintf(stderr, "Note: Storing picture from APIC frame.\n");
497
498
  /* get mime type (encoding is always latin-1) */
499
0
  workpoint = next_text(realdata, 0, realsize);
500
0
  if(!workpoint)
501
0
  {
502
0
    if(NOQUIET)
503
0
      error("Unable to get mime type for picture; skipping picture.");
504
0
    return;
505
0
  }
506
0
  INT123_id3_to_utf8(&mime, 0, realdata, workpoint - realdata, NOQUIET);
507
0
  realsize -= workpoint - realdata;
508
0
  realdata = workpoint;
509
  /* get picture type */
510
0
  image_type = realdata[0];
511
0
  realdata++; realsize--;
512
  /* get description (encoding is encoding) */
513
0
  workpoint = next_text(realdata, encoding, realsize);
514
0
  if(!workpoint)
515
0
  {
516
0
    if(NOQUIET)
517
0
      error("Unable to get description for picture; skipping picture.");
518
0
    mpg123_free_string(&mime);
519
0
    return;
520
0
  }
521
0
  INT123_id3_to_utf8(&description, encoding, realdata, workpoint - realdata, NOQUIET);
522
0
  realsize -= workpoint - realdata;
523
0
  if(realsize)
524
0
    image_data = (unsigned char*)malloc(realsize);
525
0
  if(!realsize || !image_data) {
526
0
    if(NOQUIET)
527
0
      error("No picture data or malloc failure; skipping picture.");
528
0
    mpg123_free_string(&description);
529
0
    mpg123_free_string(&mime);
530
0
    return;
531
0
  }
532
0
  memcpy(image_data, workpoint, realsize);
533
534
  // All data ready now, append to/replace in list.
535
0
  i = add_picture(fr, image_type, &description);
536
0
  if(!i)
537
0
  {
538
0
    if(NOQUIET)
539
0
      error("Unable to attach new picture!");
540
0
    free(image_data);
541
0
    mpg123_free_string(&description);
542
0
    mpg123_free_string(&mime);
543
0
    return;
544
0
  }
545
546
  // Either this is a fresh image, or one to be replaced.
547
  // We hand over memory, so old storage needs to be freed.
548
0
  free_mpg123_picture(i);
549
0
  i->type = image_type;
550
0
  i->size = realsize;
551
0
  i->data = image_data;
552
0
  mpg123_move_string(&mime, &i->mime_type);
553
0
  mpg123_move_string(&description, &i->description);
554
0
  if(VERBOSE4)
555
0
    fprintf(stderr, "Note: ID3v2 APIC picture frame of type: %d\n", i->type);
556
0
}
557
558
/* Store a new comment that perhaps is a RVA / RVA_ALBUM/AUDIOPHILE / RVA_MIX/RADIO one
559
   Special gimmik: It also stores USLT to the texts. Stucture is the same as for comments. */
560
static void process_comment(mpg123_handle *fr, enum frame_types tt, unsigned char *realdata, size_t realsize, int rva_level, char *id)
561
5.75k
{
562
  /* Text encoding          $xx */
563
  /* Language               $xx xx xx */
564
  /* Short description (encoded!)      <text> $00 (00) */
565
  /* Then the comment text (encoded) ... */
566
5.75k
  unsigned char  encoding = realdata[0];
567
5.75k
  char lang[3]; // realdata + 1
568
5.75k
  unsigned char *descr    = realdata+4;
569
5.75k
  unsigned char *text     = NULL;
570
5.75k
  mpg123_text *xcom = NULL;
571
5.75k
  mpg123_text localcom; // UTF-8 variant for local processing, remember to clean up!
572
5.75k
  init_mpg123_text(&localcom);
573
574
5.75k
  if(realsize < (size_t)(descr-realdata))
575
390
  {
576
390
    if(NOQUIET) error1("Invalid frame size of %zu (too small for anything).", realsize);
577
390
    return;
578
390
  }
579
5.36k
  if(encoding > mpg123_id3_enc_max)
580
378
  {
581
378
    if(NOQUIET)
582
378
      error1("Unknown text encoding %u, I take no chances, sorry!", encoding);
583
378
    return;
584
378
  }
585
4.98k
  memcpy(lang, realdata+1, 3);
586
  /* Be careful with finding the end of description, I have to honor encoding here. */
587
4.98k
  text = next_text(descr, encoding, realsize-(descr-realdata));
588
4.98k
  if(text == NULL)
589
701
  {
590
701
    if(NOQUIET)
591
701
      error("No comment text / valid description?");
592
701
    return;
593
701
  }
594
4.28k
  { // just vor variable scope
595
4.28k
    mpg123_string description;
596
4.28k
    mpg123_init_string(&description);
597
    // Store the text, with desired encoding, but for comments always a local copy in UTF-8.
598
4.28k
    store_id3_text( &description, encoding, descr, text-descr
599
4.28k
    , NOQUIET, fr->p.flags & MPG123_PLAIN_ID3TEXT );
600
4.28k
    if(tt == comment)
601
3.86k
      store_id3_text( &localcom.description, encoding, descr, text-descr
602
3.86k
      , NOQUIET, 0 );
603
4.28k
    if(VERBOSE4)
604
0
      fprintf( stderr, "Note: Storing comment from %s encoding\n"
605
0
      , enc_name(encoding) );
606
4.28k
    xcom = tt == uslt
607
4.28k
    ?  add_uslt(fr, lang, &description)
608
4.28k
    : add_comment(fr, lang, &description);
609
4.28k
    if(xcom == NULL)
610
0
    {
611
0
      if(NOQUIET)
612
0
        error("Unable to attach new comment!");
613
0
      mpg123_free_string(&description);
614
0
      free_mpg123_text(&localcom);
615
0
      return;
616
0
    }
617
4.28k
    memcpy(xcom->id, id, 4);
618
4.28k
    memcpy(xcom->lang, lang, 3);
619
    // That takes over the description allocation.
620
4.28k
    mpg123_move_string(&description, &xcom->description);
621
4.28k
  }
622
623
0
  store_id3_text( &xcom->text, encoding, text, realsize-(text-realdata)
624
4.28k
  , NOQUIET, fr->p.flags & MPG123_PLAIN_ID3TEXT );
625
  /* Remember: I will probably decode the above (again) for rva comment checking. So no messing around, please. */
626
627
4.28k
  if(VERBOSE4) /* Do _not_ print the verbatim text: The encoding might be funny! */
628
0
  {
629
0
    fprintf(stderr, "Note: ID3 comm/uslt desc of length %zu.\n", xcom->description.fill);
630
0
    fprintf(stderr, "Note: ID3 comm/uslt text of length %zu.\n", xcom->text.fill);
631
0
  }
632
  /* Look out for RVA info only when we really deal with a straight comment. */
633
4.28k
  if(tt == comment && localcom.description.fill > 0)
634
3.86k
  {
635
3.86k
    int rva_mode = -1; /* mix / album */
636
3.86k
    if(    !strcasecmp(localcom.description.p, "rva")
637
3.42k
       || !strcasecmp(localcom.description.p, "rva_mix")
638
3.19k
       || !strcasecmp(localcom.description.p, "rva_track")
639
2.80k
       || !strcasecmp(localcom.description.p, "rva_radio") )
640
1.28k
    rva_mode = 0;
641
2.57k
    else if(    !strcasecmp(localcom.description.p, "rva_album")
642
2.37k
             || !strcasecmp(localcom.description.p, "rva_audiophile")
643
2.18k
             || !strcasecmp(localcom.description.p, "rva_user") )
644
797
    rva_mode = 1;
645
3.86k
    if((rva_mode > -1) && (fr->rva.level[rva_mode] <= rva_level))
646
1.79k
    {
647
      /* Only translate the contents in here where we really need them. */
648
1.79k
      store_id3_text( &localcom.text, encoding, text, realsize-(text-realdata)
649
1.79k
      , NOQUIET, 0 );
650
1.79k
      if(localcom.text.fill > 0)
651
1.79k
      {
652
1.79k
        fr->rva.gain[rva_mode] = (float) atof(localcom.text.p);
653
1.79k
        if(VERBOSE3) fprintf(stderr, "Note: RVA value %fdB\n", fr->rva.gain[rva_mode]);
654
1.79k
        fr->rva.peak[rva_mode] = 0;
655
1.79k
        fr->rva.level[rva_mode] = rva_level;
656
1.79k
      }
657
1.79k
    }
658
3.86k
  }
659
  /* Make sure to free the local memory... */
660
4.28k
  free_mpg123_text(&localcom);
661
4.28k
}
662
663
static void process_extra(mpg123_handle *fr, unsigned char* realdata, size_t realsize, int rva_level, char *id)
664
8.99k
{
665
  /* Text encoding          $xx */
666
  /* Description        ... $00 (00) */
667
  /* Text ... */
668
8.99k
  unsigned char encoding = realdata[0];
669
8.99k
  unsigned char *descr   = realdata+1; /* remember, the encoding is descr[-1] */
670
8.99k
  unsigned char *text;
671
8.99k
  mpg123_text *xex;
672
8.99k
  mpg123_text localex;
673
674
8.99k
  if((int)realsize < descr-realdata)
675
0
  {
676
0
    if(NOQUIET) error1("Invalid frame size of %lu (too small for anything).", (unsigned long)realsize);
677
0
    return;
678
0
  }
679
8.99k
  if(encoding > mpg123_id3_enc_max)
680
274
  {
681
274
    if(NOQUIET)
682
274
      error1("Unknown text encoding %u, I take no chances, sorry!", encoding);
683
274
    return;
684
274
  }
685
8.71k
  text = next_text(descr, encoding, realsize-(descr-realdata));
686
8.71k
  if(VERBOSE4) fprintf(stderr, "Note: Storing extra from %s encoding\n", enc_name(realdata[0]));
687
8.71k
  if(text == NULL)
688
788
  {
689
788
    if(NOQUIET) error("No extra frame text / valid description?");
690
788
    return;
691
788
  }
692
7.92k
  { // just vor variable scope
693
7.92k
    mpg123_string description;
694
7.92k
    mpg123_init_string(&description);
695
    /* The outside storage gets reencoded to UTF-8 only if not requested otherwise.
696
       Remember that we really need the -1 here to hand in the encoding byte!*/
697
7.92k
    store_id3_text( &description, encoding, descr, text-descr
698
7.92k
    , NOQUIET, fr->p.flags & MPG123_PLAIN_ID3TEXT );
699
7.92k
    xex = add_extra(fr, &description);
700
7.92k
    if(xex)
701
7.92k
      mpg123_move_string(&description, &xex->description);
702
0
    else
703
0
      mpg123_free_string(&description);
704
7.92k
  }
705
7.92k
  if(xex == NULL)
706
0
  {
707
0
    if(NOQUIET) error("Unable to attach new extra text!");
708
0
    return;
709
0
  }
710
7.92k
  memcpy(xex->id, id, 4);
711
7.92k
  init_mpg123_text(&localex); /* For our local copy. */
712
713
  /* Our local copy is always stored in UTF-8! */
714
7.92k
  store_id3_text(&localex.description, encoding, descr, text-descr, NOQUIET, 0);
715
  /* At first, only store the outside copy of the payload. We may not need the local copy. */
716
7.92k
  store_id3_text( &xex->text, encoding, text, realsize-(text-realdata)
717
7.92k
  , NOQUIET, fr->p.flags & MPG123_PLAIN_ID3TEXT );
718
719
  /* Now check if we would like to interpret this extra info for RVA. */
720
7.92k
  if(localex.description.fill > 0)
721
7.92k
  {
722
7.92k
    int is_peak = 0;
723
7.92k
    int rva_mode = -1; /* mix / album */
724
725
7.92k
    if(!strncasecmp(localex.description.p, "replaygain_track_",17))
726
3.03k
    {
727
3.03k
      if(VERBOSE3) fprintf(stderr, "Note: RVA ReplayGain track gain/peak\n");
728
729
3.03k
      rva_mode = 0;
730
3.03k
      if(!strcasecmp(localex.description.p, "replaygain_track_peak")) is_peak = 1;
731
2.13k
      else if(strcasecmp(localex.description.p, "replaygain_track_gain")) rva_mode = -1;
732
3.03k
    }
733
4.89k
    else
734
4.89k
    if(!strncasecmp(localex.description.p, "replaygain_album_",17))
735
793
    {
736
793
      if(VERBOSE3) fprintf(stderr, "Note: RVA ReplayGain album gain/peak\n");
737
738
793
      rva_mode = 1;
739
793
      if(!strcasecmp(localex.description.p, "replaygain_album_peak")) is_peak = 1;
740
577
      else if(strcasecmp(localex.description.p, "replaygain_album_gain")) rva_mode = -1;
741
793
    }
742
7.92k
    if((rva_mode > -1) && (fr->rva.level[rva_mode] <= rva_level))
743
2.74k
    {
744
      /* Now we need the translated copy of the data. */
745
2.74k
      store_id3_text( &localex.text, encoding, text, realsize-(text-realdata)
746
2.74k
      , NOQUIET, 0 );
747
2.74k
      if(localex.text.fill > 0)
748
2.74k
      {
749
2.74k
        if(is_peak)
750
925
        {
751
925
          fr->rva.peak[rva_mode] = (float) atof(localex.text.p);
752
925
          if(VERBOSE3) fprintf(stderr, "Note: RVA peak %f\n", fr->rva.peak[rva_mode]);
753
925
        }
754
1.82k
        else
755
1.82k
        {
756
1.82k
          fr->rva.gain[rva_mode] = (float) atof(localex.text.p);
757
1.82k
          if(VERBOSE3) fprintf(stderr, "Note: RVA gain %fdB\n", fr->rva.gain[rva_mode]);
758
1.82k
        }
759
2.74k
        fr->rva.level[rva_mode] = rva_level;
760
2.74k
      }
761
2.74k
    }
762
7.92k
  }
763
764
7.92k
  free_mpg123_text(&localex);
765
7.92k
}
766
767
/* Make a ID3v2.3+ 4-byte ID from a ID3v2.2 3-byte ID
768
   Note that not all frames survived to 2.4; the mapping goes to 2.3 .
769
   A notable miss is the old RVA frame, which is very unspecific anyway.
770
   This function returns -1 when a not known 3 char ID was encountered, 0 otherwise. */
771
static int promote_framename(mpg123_handle *fr, char *id) /* fr because of VERBOSE macros */
772
14.8k
{
773
14.8k
  size_t i;
774
14.8k
  char *old[] =
775
14.8k
  {
776
14.8k
    "COM",  "TAL",  "TBP",  "TCM",  "TCO",  "TCR",  "TDA",  "TDY",  "TEN",  "TFT",
777
14.8k
    "TIM",  "TKE",  "TLA",  "TLE",  "TMT",  "TOA",  "TOF",  "TOL",  "TOR",  "TOT",
778
14.8k
    "TP1",  "TP2",  "TP3",  "TP4",  "TPA",  "TPB",  "TRC",  "TDA",  "TRK",  "TSI",
779
14.8k
    "TSS",  "TT1",  "TT2",  "TT3",  "TXT",  "TXX",  "TYE"
780
14.8k
  };
781
14.8k
  char *new[] =
782
14.8k
  {
783
14.8k
    "COMM", "TALB", "TBPM", "TCOM", "TCON", "TCOP", "TDAT", "TDLY", "TENC", "TFLT",
784
14.8k
    "TIME", "TKEY", "TLAN", "TLEN", "TMED", "TOPE", "TOFN", "TOLY", "TORY", "TOAL",
785
14.8k
    "TPE1", "TPE2", "TPE3", "TPE4", "TPOS", "TPUB", "TSRC", "TRDA", "TRCK", "TSIZ",
786
14.8k
    "TSSE", "TIT1", "TIT2", "TIT3", "TEXT", "TXXX", "TYER"
787
14.8k
  };
788
343k
  for(i=0; i<sizeof(old)/sizeof(char*); ++i)
789
342k
  {
790
342k
    if(!strncmp(id, old[i], 3))
791
14.3k
    {
792
14.3k
      memcpy(id, new[i], 4);
793
14.3k
      if(VERBOSE3) fprintf(stderr, "Translated ID3v2.2 frame %s to %s\n", old[i], new[i]);
794
14.3k
      return 0;
795
14.3k
    }
796
342k
  }
797
487
  if(VERBOSE3) fprintf(stderr, "Ignoring untranslated ID3v2.2 frame %c%c%c\n", id[0], id[1], id[2]);
798
487
  return -1;
799
14.8k
}
800
801
#endif /* NO_ID3V2 */
802
803
static int store_id3v2( mpg123_handle *fr
804
, unsigned long first4bytes, unsigned char buf[6], unsigned long length )
805
33.6k
{
806
33.6k
  int ret = 1;
807
33.6k
  int64_t ret2;
808
33.6k
  unsigned long fullen = 10+length;
809
33.6k
  if(fr->id3v2_raw)
810
0
    free(fr->id3v2_raw);
811
33.6k
  fr->id3v2_size = 0;
812
  /* Allocate one byte more for a closing zero as safety catch for strlen(). */
813
33.6k
  fr->id3v2_raw = malloc(fullen+1);
814
33.6k
  if(!fr->id3v2_raw)
815
0
  {
816
0
    fr->err = MPG123_OUT_OF_MEM;
817
0
    if(NOQUIET)
818
0
      error1("ID3v2: Arrg! Unable to allocate %lu bytes"
819
0
        " for ID3v2 data - trying to skip instead.", length+1);
820
0
    if((ret2=fr->rd->skip_bytes(fr,length)) < 0)
821
0
      ret = ret2;
822
0
    else
823
0
      ret = 0;
824
0
  }
825
33.6k
  else
826
33.6k
  {
827
33.6k
    fr->id3v2_raw[0] = (first4bytes>>24) & 0xff;
828
33.6k
    fr->id3v2_raw[1] = (first4bytes>>16) & 0xff;
829
33.6k
    fr->id3v2_raw[2] = (first4bytes>>8)  & 0xff;
830
33.6k
    fr->id3v2_raw[3] =  first4bytes      & 0xff;
831
33.6k
    memcpy(fr->id3v2_raw+4, buf, 6);
832
33.6k
    if((ret2=fr->rd->read_frame_body(fr, fr->id3v2_raw+10, length)) < 0)
833
14.0k
    {
834
14.0k
      ret=ret2;
835
14.0k
      free(fr->id3v2_raw);
836
14.0k
      fr->id3v2_raw = NULL;
837
14.0k
    }
838
19.6k
    else
839
19.6k
    { /* Closing with a zero for paranoia. */
840
19.6k
      fr->id3v2_raw[fullen] = 0;
841
19.6k
      fr->id3v2_size = fullen;
842
19.6k
    }
843
33.6k
  }
844
33.6k
  return ret;
845
33.6k
}
846
847
/*
848
  trying to parse ID3v2.3 and ID3v2.4 tags...
849
850
  returns:  0: bad or just unparseable tag
851
            1: good, (possibly) new tag info
852
           <0: reader error (may need more data feed, try again)
853
*/
854
int INT123_parse_new_id3(mpg123_handle *fr, unsigned long first4bytes)
855
42.9k
{
856
42.9k
  #define UNSYNC_FLAG 128
857
42.9k
  #define EXTHEAD_FLAG 64  /* ID3v2.3+ */
858
42.9k
  #define COMPRESS_FLAG 64 /* ID3v2.2 */
859
42.9k
  #define EXP_FLAG 32
860
42.9k
  #define FOOTER_FLAG 16
861
42.9k
  #define EXT_UPDATE_FLAG 64 /* ID3v2.4 only: extended header update flag */
862
42.9k
  #define UNKNOWN_FLAGS 15 /* 00001111*/
863
42.9k
  unsigned char buf[6];
864
42.9k
  unsigned long length=0;
865
42.9k
  unsigned char flags = 0;
866
42.9k
  int ret = 1;
867
42.9k
  int64_t ret2;
868
42.9k
  int storetag = 0;
869
42.9k
  unsigned int footlen = 0;
870
42.9k
#ifndef NO_ID3V2
871
42.9k
  int skiptag = 0;
872
42.9k
#endif
873
42.9k
  unsigned char major = first4bytes & 0xff;
874
42.9k
  debug1("ID3v2: major tag version: %i", major);
875
876
42.9k
  if(major == 0xff) return 0; /* Invalid... */
877
42.4k
  if((ret2 = fr->rd->read_frame_body(fr, buf, 6)) < 0) /* read more header information */
878
479
  return ret2;
879
880
41.9k
  if(buf[0] == 0xff) return 0; /* Revision, will never be 0xff. */
881
882
41.1k
  if(fr->p.flags & MPG123_STORE_RAW_ID3)
883
0
    storetag = 1;
884
  /* second new byte are some nice flags, if these are invalid skip the whole thing */
885
41.1k
  flags = buf[1];
886
41.1k
  debug1("ID3v2: flags 0x%08x", flags);
887
  /* use 4 bytes from buf to construct 28bit uint value and return 1; return 0 if bytes are not synchsafe */
888
41.1k
  #define synchsafe_to_long(buf,res) \
889
51.0k
  ( \
890
51.0k
    (((buf)[0]|(buf)[1]|(buf)[2]|(buf)[3]) & 0x80) ? 0 : \
891
51.0k
    (res =  (((unsigned long) (buf)[0]) << 21) \
892
48.5k
         | (((unsigned long) (buf)[1]) << 14) \
893
48.5k
         | (((unsigned long) (buf)[2]) << 7) \
894
48.5k
         |  ((unsigned long) (buf)[3]) \
895
48.5k
    ,1) \
896
51.0k
  )
897
  /* id3v2.3 does not store synchsafe frame sizes, but synchsafe tag size - doh! */
898
  /* Remember: bytes_to_long() can yield ULONG_MAX on 32 bit platforms! */
899
41.1k
  #define bytes_to_long(buf,res) \
900
41.1k
  ( \
901
15.4k
    major == 3 ? \
902
15.4k
    (res =  (((unsigned long) (buf)[0]) << 24) \
903
1.68k
         | (((unsigned long) (buf)[1]) << 16) \
904
1.68k
         | (((unsigned long) (buf)[2]) << 8) \
905
1.68k
         |  ((unsigned long) (buf)[3]) \
906
9.95k
    ,1) : synchsafe_to_long(buf,res) \
907
15.4k
  )
908
  /* for id3v2.2 only */
909
41.1k
  #define threebytes_to_long(buf,res) \
910
41.1k
  ( \
911
15.3k
    res =  (((unsigned long) (buf)[0]) << 16) \
912
15.3k
         | (((unsigned long) (buf)[1]) << 8) \
913
15.3k
         |  ((unsigned long) (buf)[2]) \
914
15.3k
  )
915
916
  /* length-10 or length-20 (footer present); 4 synchsafe integers == 28 bit number  */
917
  /* we have already read 10 bytes, so left are length or length+10 bytes belonging to tag */
918
  /* Note: This is an 28 bit value in 32 bit storage, plenty of space for */
919
  /* length+x for reasonable x. */
920
41.1k
  if(!synchsafe_to_long(buf+2,length))
921
1.59k
  {
922
1.59k
    if(NOQUIET) error4("Bad tag length (not synchsafe): 0x%02x%02x%02x%02x; You got a bad ID3 tag here.", buf[2],buf[3],buf[4],buf[5]);
923
1.59k
    return 0;
924
1.59k
  }
925
39.5k
  if(flags & FOOTER_FLAG)
926
602
    footlen = 10;
927
39.5k
  debug1("ID3v2: tag data length %lu", length);
928
39.5k
#ifndef NO_ID3V2
929
39.5k
  if(VERBOSE2) fprintf(stderr,"Note: ID3v2.%i rev %i tag of %lu bytes\n", major, buf[0], length);
930
  /* skip if unknown version/scary flags, parse otherwise */
931
39.5k
  if(fr->p.flags & MPG123_SKIP_ID3V2)
932
0
  {
933
0
    if(VERBOSE3)
934
0
      fprintf(stderr, "Note: Skipping ID3v2 tag per user request.\n");
935
0
    skiptag = 1;
936
0
  }
937
39.5k
  if((flags & UNKNOWN_FLAGS) || (major > 4) || (major < 2))
938
4.30k
  {
939
4.30k
    if(NOQUIET)
940
4.30k
      warning2( "ID3v2: Won't parse the ID3v2 tag with major version"
941
4.30k
        " %u and flags 0x%xu - some extra code may be needed"
942
4.30k
      , major, flags );
943
4.30k
    skiptag = 1;
944
4.30k
  }
945
  // Standard says that compressed tags should be ignored as there isn't an agreed
946
  // compressoion scheme.
947
39.5k
  if(major == 2 && flags & COMPRESS_FLAG)
948
423
  {
949
423
    if(NOQUIET)
950
423
      warning("ID3v2: ignoring compressed ID3v2.2 tag");
951
423
    skiptag = 1;
952
423
  }
953
39.5k
  if(length < 10)
954
4.19k
  {
955
4.19k
    if(NOQUIET)
956
4.19k
      warning1("ID3v2: unrealistic small tag lengh %lu, skipping", length);
957
4.19k
    skiptag = 1;
958
4.19k
  }
959
39.5k
  if(!skiptag)
960
33.6k
    storetag = 1;
961
39.5k
#endif
962
39.5k
  if(storetag)
963
33.6k
  {
964
    /* Stores whole tag with footer and an additonal trailing zero. */
965
33.6k
    if((ret2 = store_id3v2(fr, first4bytes, buf, length+footlen)) <= 0)
966
14.0k
      return ret2;
967
33.6k
  }
968
25.5k
#ifndef NO_ID3V2
969
25.5k
  if(skiptag)
970
5.84k
  {
971
5.84k
    if(VERBOSE3)
972
0
      fprintf(stderr, "Note: skipped tag clearing possibly existing ID3v2 data");
973
5.84k
    INT123_reset_id3(fr); // Old data is invalid.
974
5.84k
#endif
975
5.84k
    if(!storetag && (ret2=fr->rd->skip_bytes(fr,length+footlen))<0)
976
1.80k
      ret=ret2;
977
5.84k
#ifndef NO_ID3V2
978
5.84k
  }
979
19.6k
  else
980
19.6k
  {
981
19.6k
    unsigned char* tagdata = fr->id3v2_raw+10;
982
    /* try to interpret that beast */
983
19.6k
    debug("ID3v2: analysing frames...");
984
19.6k
    if(length > 0)
985
19.6k
    {
986
19.6k
      unsigned char extflags = 0;
987
19.6k
      unsigned long tagpos = 0;
988
      /* bytes of frame title and of framesize value */
989
19.6k
      unsigned int head_part = major > 2 ? 4 : 3;
990
19.6k
      unsigned int flag_part = major > 2 ? 2 : 0;
991
      /* The amount of bytes that are unconditionally read for each frame: */
992
      /* ID, size, flags. */
993
19.6k
      unsigned int framebegin = head_part+head_part+flag_part;
994
19.6k
      debug1("ID3v2: have read at all %lu bytes for the tag now", (unsigned long)length+6);
995
19.6k
      if(flags & EXTHEAD_FLAG)
996
1.55k
      {
997
1.55k
        debug("ID3v2: extended header");
998
1.55k
        if(!bytes_to_long(tagdata, tagpos) || tagpos >= length)
999
612
        {
1000
612
          ret = 0;
1001
612
          if(NOQUIET)
1002
612
            error4( "Bad (non-synchsafe/too large) tag offset from extended header:"
1003
612
              "0x%02x%02x%02x%02x"
1004
612
            , tagdata[0], tagdata[1], tagdata[2], tagdata[3] );
1005
945
        } else if(tagpos < 6)
1006
340
        {
1007
340
          ret = 0;
1008
340
          if(NOQUIET)
1009
340
            merror("Extended header too small (%lu).", tagpos);
1010
340
        }
1011
1.55k
        if(major == 3)
1012
460
        {
1013
460
          tagpos += 4; // The size itself is not included.
1014
460
          if(tagpos >= length)
1015
256
          {
1016
256
            ret = 0;
1017
256
            if(NOQUIET)
1018
256
              error("Too much extended v2.3 header.");
1019
256
          }
1020
1.09k
        } else if(ret) // v2.4 and at least got my 6 bytes of ext header
1021
592
        {
1022
          // Only v4 knows update frames, check for that.
1023
          // Need to step back. Header is 4 bytes length, one byte flag size,
1024
          // one byte flags. Flag size has to be 1!
1025
592
          if(tagdata[4] == 1 && tagdata[5] & EXT_UPDATE_FLAG)
1026
194
          {
1027
194
            if(VERBOSE3)
1028
0
              fprintf(stderr, "Note: ID3v2.4 update tag\n");
1029
194
            extflags |= EXT_UPDATE_FLAG;
1030
194
          }
1031
592
        }
1032
1.55k
      }
1033
19.6k
      if(!(extflags & EXT_UPDATE_FLAG))
1034
19.4k
      {
1035
19.4k
        if(VERBOSE3)
1036
0
          fprintf(stderr, "Note: non-update tag replacing existing ID3v2 data\n");
1037
19.4k
        INT123_reset_id3(fr);
1038
19.4k
      }
1039
19.6k
      if(ret > 0)
1040
18.7k
      {
1041
18.7k
        char id[5];
1042
18.7k
        unsigned long framesize;
1043
18.7k
        unsigned long fflags; /* need 16 bits, actually */
1044
18.7k
        id[4] = 0;
1045
18.7k
        fr->id3v2.version = major;
1046
        /* Pos now advanced after ext head, now a frame has to follow. */
1047
        /* Note: tagpos <= length, which is 28 bit integer, so both */
1048
        /* far away from overflow for adding known small values. */
1049
        /* I want to read at least one full header now. */
1050
40.8k
        while(length >= tagpos+framebegin)
1051
26.4k
        {
1052
26.4k
          int i = 0;
1053
26.4k
          unsigned long pos = tagpos;
1054
          /* level 1,2,3 - 0 is info from lame/info tag! */
1055
          /* rva tags with ascending significance, then general frames */
1056
26.4k
          enum frame_types tt = unknown;
1057
          /* we may have entered the padding zone or any other strangeness: check if we have valid frame id characters */
1058
105k
          for(i=0; i< head_part; ++i)
1059
82.0k
          if( !( ((tagdata[tagpos+i] > 47) && (tagdata[tagpos+i] < 58))
1060
75.8k
             || ((tagdata[tagpos+i] > 64) && (tagdata[tagpos+i] < 91)) ) )
1061
3.27k
          {
1062
3.27k
            debug5("ID3v2: real tag data apparently ended after %lu bytes with 0x%02x%02x%02x%02x", tagpos, tagdata[tagpos], tagdata[tagpos+1], tagdata[tagpos+2], tagdata[tagpos+3]);
1063
            /* This is no hard error... let's just hope that we got something meaningful already (ret==1 in that case). */
1064
3.27k
            goto tagparse_cleanup; /* Need to escape two loops here. */
1065
3.27k
          }
1066
23.1k
          if(ret > 0)
1067
23.1k
          {
1068
            /* 4 or 3 bytes id */
1069
23.1k
            strncpy(id, (char*) tagdata+pos, head_part);
1070
23.1k
            id[head_part] = 0; /* terminate for 3 or 4 bytes */
1071
23.1k
            pos += head_part;
1072
23.1k
            tagpos += head_part;
1073
            /* size as 32 bits or 28 bits */
1074
23.1k
            if(fr->id3v2.version == 2) threebytes_to_long(tagdata+pos, framesize);
1075
7.83k
            else
1076
7.83k
            if(!bytes_to_long(tagdata+pos, framesize))
1077
284
            {
1078
              /* Just assume that up to now there was some good data. */
1079
284
              if(NOQUIET) error1("ID3v2: non-syncsafe size of %s frame, skipping the remainder of tag", id);
1080
284
              break;
1081
284
            }
1082
22.8k
            if(VERBOSE3) fprintf(stderr, "Note: ID3v2 %s frame of size %lu\n", id, framesize);
1083
22.8k
            tagpos += head_part;
1084
22.8k
            pos += head_part;
1085
22.8k
            if(fr->id3v2.version > 2)
1086
7.54k
            {
1087
7.54k
              fflags  = (((unsigned long) tagdata[pos]) << 8) | ((unsigned long) tagdata[pos+1]);
1088
7.54k
              pos    += 2;
1089
7.54k
              tagpos += 2;
1090
7.54k
            }
1091
15.3k
            else fflags = 0;
1092
1093
22.8k
            if(length - tagpos < framesize)
1094
706
            {
1095
706
              if(NOQUIET) error("Whoa! ID3v2 frame claims to be larger than the whole rest of the tag.");
1096
706
              break;
1097
706
            }
1098
22.1k
            tagpos += framesize; /* the important advancement in whole tag */
1099
            /* for sanity, after full parsing tagpos should be == pos */
1100
            /* debug4("ID3v2: found %s frame, size %lu (as bytes: 0x%08lx), flags 0x%016lx", id, framesize, framesize, fflags); */
1101
            /* v2.4: %0abc0000 %0h00kmnp */
1102
            /* v2.3: %abc00000 %ijk00000 */
1103
            /* v2.2: just zero */
1104
118k
            #define V3 (major == 3)
1105
22.1k
            #define BAD_FFLAGS      (unsigned long) (V3 ? 7967 : 36784)
1106
22.1k
            #define PRES_TAG_FFLAG  (unsigned long) (V3 ? 32768 : 16384)
1107
22.1k
            #define PRES_FILE_FFLAG (unsigned long) (V3 ? 16384 : 8192)
1108
22.1k
            #define READ_ONLY_FFLAG (unsigned long) (V3 ? 8192 : 4096)
1109
22.1k
            #define GROUP_FFLAG     (unsigned long) (V3 ? 32 : 64)
1110
22.1k
            #define COMPR_FFLAG     (unsigned long) (V3 ? 128 : 8)
1111
22.1k
            #define ENCR_FFLAG      (unsigned long) (V3 ? 64 : 4)
1112
22.1k
            #define UNSYNC_FFLAG    (unsigned long) (V3 ? 0 : 2)
1113
22.1k
            #define DATLEN_FFLAG    (unsigned long) (V3 ? 0 : 1)
1114
22.1k
            if(head_part < 4 && promote_framename(fr, id) != 0) continue;
1115
1116
            /* shall not or want not handle these */
1117
21.6k
            if(fflags & (BAD_FFLAGS | COMPR_FFLAG | ENCR_FFLAG))
1118
326
            {
1119
326
              if(NOQUIET) warning("ID3v2: skipping invalid/unsupported frame");
1120
326
              continue;
1121
326
            }
1122
1123
55.2k
            for(i = 0; i < KNOWN_FRAMES; ++i)
1124
52.1k
            if(!strncmp(frame_type[i], id, 4)){ tt = i; break; }
1125
1126
21.3k
            if(id[0] == 'T' && tt != extra) tt = text;
1127
1128
21.3k
            if(tt != unknown)
1129
21.0k
            {
1130
21.0k
              int rva_mode = -1; /* mix / album */
1131
21.0k
              unsigned long realsize = framesize;
1132
21.0k
              unsigned char* realdata = tagdata+pos;
1133
21.0k
              unsigned char* unsyncbuffer = NULL;
1134
21.0k
              if(((flags & UNSYNC_FLAG) || (fflags & UNSYNC_FFLAG)) && framesize > 0)
1135
9.49k
              {
1136
9.49k
                unsigned long ipos = 0;
1137
9.49k
                unsigned long opos = 0;
1138
9.49k
                debug("Id3v2: going to de-unsync the frame data");
1139
                /* de-unsync: FF00 -> FF; real FF00 is simply represented as FF0000 ... */
1140
                /* damn, that means I have to delete bytes from withing the data block... thus need temporal storage */
1141
                /* standard mandates that de-unsync should always be safe if flag is set */
1142
9.49k
                realdata = unsyncbuffer = malloc(framesize+1); /* will need <= bytes, plus a safety zero */
1143
9.49k
                if(realdata == NULL)
1144
0
                {
1145
0
                  if(NOQUIET) error("ID3v2: unable to allocate working buffer for de-unsync");
1146
0
                  continue;
1147
0
                }
1148
                /* now going byte per byte through the data... */
1149
9.49k
                realdata[0] = tagdata[pos];
1150
9.49k
                opos = 1;
1151
33.6M
                for(ipos = pos+1; ipos < pos+framesize; ++ipos)
1152
33.5M
                {
1153
33.5M
                  if(!((tagdata[ipos] == 0) && (tagdata[ipos-1] == 0xff)))
1154
33.3M
                  {
1155
33.3M
                    realdata[opos++] = tagdata[ipos];
1156
33.3M
                  }
1157
33.5M
                }
1158
9.49k
                realsize = opos;
1159
                /* Append a zero to keep strlen() safe. */
1160
9.49k
                realdata[realsize] = 0;
1161
9.49k
                debug2("ID3v2: de-unsync made %lu out of %lu bytes", realsize, framesize);
1162
9.49k
              }
1163
              // The spec says there is a group byte, without explicitly saying that it is
1164
              // the first thing following the header. I just assume so, because of the
1165
              // ordering of the flags.
1166
21.0k
              if(fflags & GROUP_FFLAG)
1167
1.48k
              { // Just skip group byte.
1168
1.48k
                if(realsize)
1169
1.13k
                {
1170
1.13k
                  if(VERBOSE3)
1171
0
                    fprintf(stderr, "Note: frame of group %d\n", realdata[0]);
1172
1.13k
                  --realsize;
1173
1.13k
                  ++realdata;
1174
1.13k
                } else if(NOQUIET)
1175
0
                  error("Grouped frame without group byte, even.");
1176
1.48k
              }
1177
21.0k
              if(fflags & DATLEN_FFLAG)
1178
2.89k
              {
1179
                // Spec says the original (without compression or unsync) data length follows,
1180
                // so it should match de-unsynced data now.
1181
2.89k
                if(realsize >= 4)
1182
2.25k
                {
1183
2.25k
                  unsigned long datlen;
1184
2.25k
                  if(bytes_to_long(realdata, datlen) && datlen == realsize-4)
1185
1.11k
                  {
1186
1.11k
                    realsize  -= 4;
1187
1.11k
                    realdata  += 4;
1188
1.11k
                  } else
1189
1.14k
                  {
1190
1.14k
                    if(NOQUIET)
1191
1.14k
                      error("frame data length bad, skipping");
1192
1.14k
                    realsize = 0;
1193
1.14k
                  }
1194
2.25k
                } else
1195
642
                {
1196
642
                  realsize = 0;
1197
642
                  if(NOQUIET)
1198
642
                    error("frame truncated at frame data length, skipping");
1199
642
                }
1200
2.89k
              }
1201
21.0k
              pos = 0; /* now at the beginning again... */
1202
              /* Avoid reading over boundary, even if there is a */
1203
              /* zero byte of padding for safety. */
1204
21.0k
              if(realsize) switch(tt)
1205
18.7k
              {
1206
5.13k
                case comment:
1207
5.75k
                case uslt:
1208
5.75k
                  process_comment(fr, tt, realdata, realsize, comment+1, id);
1209
5.75k
                break;
1210
8.99k
                case extra: /* perhaps foobar2000's work */
1211
8.99k
                  process_extra(fr, realdata, realsize, extra+1, id);
1212
8.99k
                break;
1213
1.74k
                case rva2: /* "the" RVA tag */
1214
1.74k
                {
1215
                  /* starts with null-terminated identification */
1216
1.74k
                  if(VERBOSE3) fprintf(stderr, "Note: RVA2 identification \"%s\"\n", realdata);
1217
                  /* default: some individual value, mix mode */
1218
1.74k
                  rva_mode = 0;
1219
1.74k
                  if( !strncasecmp((char*)realdata, "album", 5)
1220
1.47k
                     || !strncasecmp((char*)realdata, "audiophile", 10)
1221
1.15k
                     || !strncasecmp((char*)realdata, "user", 4))
1222
784
                  rva_mode = 1;
1223
1.74k
                  if(fr->rva.level[rva_mode] <= rva2+1)
1224
1.74k
                  {
1225
1.74k
                    pos += strlen((char*) realdata) + 1;
1226
1.74k
                    debug2("got my pos: %lu - %lu", realsize, pos);
1227
                    // channel and two bytes for RVA value
1228
                    // pos possibly just past the safety zero, so one more than realsize
1229
1.74k
                    if(pos > realsize || realsize-pos < 3)
1230
1.08k
                    {
1231
1.08k
                      if(NOQUIET)
1232
1.08k
                        error("bad RVA2 tag (truncated?)");
1233
1.08k
                    }
1234
654
                    else if(realdata[pos] == 1)
1235
212
                    {
1236
212
                      ++pos;
1237
                      /* only handle master channel */
1238
212
                      debug("ID3v2: it is for the master channel");
1239
                      /* two bytes adjustment, one byte for bits representing peak - n bytes, eh bits, for peak */
1240
                      /* 16 bit signed integer = dB * 512. Do not shift signed integers! Multiply instead.
1241
                         Also no implementation-defined casting. Reinterpret the pointer to signed char, then do
1242
                         proper casting. */
1243
212
                      fr->rva.gain[rva_mode] = (float) (
1244
212
                        ((short)((signed char*)realdata)[pos]) * 256 + (short)realdata[pos+1] ) / 512;
1245
212
                      pos += 2;
1246
212
                      if(VERBOSE3) fprintf(stderr, "Note: RVA value %fdB\n", fr->rva.gain[rva_mode]);
1247
                      /* heh, the peak value is represented by a number of bits - but in what manner? Skipping that part */
1248
212
                      fr->rva.peak[rva_mode] = 0;
1249
212
                      fr->rva.level[rva_mode] = rva2+1;
1250
212
                    }
1251
1.74k
                  }
1252
1.74k
                }
1253
1.74k
                break;
1254
                /* non-rva metainfo, simply store... */
1255
2.04k
                case text:
1256
2.04k
                  process_text(fr, realdata, realsize, id);
1257
2.04k
                break;
1258
195
                case picture:
1259
195
                  if (fr->p.flags & MPG123_PICTURE)
1260
0
                  process_picture(fr, realdata, realsize);
1261
1262
195
                  break;
1263
0
                default: if(NOQUIET) error1("ID3v2: unknown frame type %i", tt);
1264
18.7k
              }
1265
21.0k
              if(unsyncbuffer)
1266
9.49k
                free(unsyncbuffer);
1267
21.0k
            }
1268
21.3k
            #undef V3
1269
21.3k
            #undef BAD_FFLAGS
1270
21.3k
            #undef PRES_TAG_FFLAG
1271
21.3k
            #undef PRES_FILE_FFLAG
1272
21.3k
            #undef READ_ONLY_FFLAG
1273
21.3k
            #undef GROUP_FFLAG
1274
21.3k
            #undef COMPR_FFLAG
1275
21.3k
            #undef ENCR_FFLAG
1276
21.3k
            #undef UNSYNC_FFLAG
1277
21.3k
            #undef DATLEN_FFLAG
1278
21.3k
          }
1279
0
          else break;
1280
23.1k
          #undef KNOWN_FRAMES
1281
23.1k
        }
1282
18.7k
      } else
1283
956
      {
1284
956
        if(VERBOSE3)
1285
0
          fprintf(stderr, "Note: faulty ID3v2 tag still clearing old data\n");
1286
956
        INT123_reset_id3(fr);
1287
956
      }
1288
19.6k
    } else // No new data, but still there was a tag that invalidates old data.
1289
0
    {
1290
0
      if(VERBOSE3)
1291
0
        fprintf(stderr, "Note: empty ID3v2 clearing old data\n");
1292
0
      INT123_reset_id3(fr);
1293
0
    }
1294
19.6k
tagparse_cleanup:
1295
    /* Get rid of stored raw data that should not be kept. */
1296
19.6k
    if(!(fr->p.flags & MPG123_STORE_RAW_ID3))
1297
19.6k
    {
1298
19.6k
      free(fr->id3v2_raw);
1299
19.6k
      fr->id3v2_raw = NULL;
1300
19.6k
      fr->id3v2_size = 0;
1301
19.6k
    }
1302
19.6k
  }
1303
25.5k
#endif /* NO_ID3V2 */
1304
25.5k
  return ret;
1305
25.5k
  #undef UNSYNC_FLAG
1306
25.5k
  #undef EXTHEAD_FLAG
1307
25.5k
  #undef COMPRESS_FLAG
1308
25.5k
  #undef EXP_FLAG
1309
25.5k
  #undef FOOTER_FLAG
1310
25.5k
  #undef EXT_UPDATE_FLAG
1311
25.5k
  #undef UNKOWN_FLAGS
1312
25.5k
}
1313
1314
#ifndef NO_ID3V2 /* Disabling all the rest... */
1315
1316
static void convert_latin1(mpg123_string *sb, const unsigned char* s, size_t l, const int noquiet)
1317
33.2k
{
1318
33.2k
  size_t length = l;
1319
33.2k
  size_t i;
1320
33.2k
  unsigned char *p;
1321
  /* determine real length, a latin1 character can at most take 2  in UTF8 */
1322
22.2M
  for(i=0; i<l; ++i)
1323
22.2M
  if(s[i] >= 0x80) ++length;
1324
1325
33.2k
  debug1("UTF-8 length: %lu", (unsigned long)length);
1326
  /* one extra zero byte for paranoia */
1327
33.2k
  if(!mpg123_grow_string(sb, length+1))
1328
0
    return;
1329
1330
33.2k
  p = (unsigned char*) sb->p; /* Signedness doesn't matter but it shows I thought about the non-issue */
1331
22.2M
  for(i=0; i<l; ++i)
1332
22.2M
  if(s[i] < 0x80){ *p = s[i]; ++p; }
1333
7.69M
  else /* two-byte encoding */
1334
7.69M
  {
1335
7.69M
    *p     = 0xc0 | (s[i]>>6);
1336
7.69M
    *(p+1) = 0x80 | (s[i] & 0x3f);
1337
7.69M
    p+=2;
1338
7.69M
  }
1339
1340
33.2k
  sb->p[length] = 0;
1341
33.2k
  sb->fill = length+1;
1342
33.2k
}
1343
1344
/*
1345
  Check if we have a byte oder mark(s) there, return:
1346
  -1: little endian
1347
   0: no BOM
1348
   1: big endian
1349
1350
  This modifies source and len to indicate the data _after_ the BOM(s).
1351
  Note on nasty data: The last encountered BOM determines the endianness.
1352
  I have seen data with multiple BOMS, namely from "the" id3v2 program.
1353
  Not nice, but what should I do?
1354
*/
1355
static int check_bom(const unsigned char** source, size_t *len)
1356
4.05k
{
1357
4.05k
  int last_bom = 0;
1358
1359
4.95k
  while(*len >= 2)
1360
4.38k
  {
1361
4.38k
    int this_bom = 0;
1362
4.38k
    if((*source)[0] == 0xff && (*source)[1] == 0xfe)
1363
577
      this_bom = -1;
1364
4.38k
    if((*source)[0] == 0xfe && (*source)[1] == 0xff)
1365
318
      this_bom = 1;
1366
4.38k
    if(this_bom == 0)
1367
3.48k
      break;
1368
    /* Skip the detected BOM. */
1369
895
    last_bom = this_bom;
1370
895
    *source += 2;
1371
895
    *len    -= 2;
1372
895
  }
1373
4.05k
  return last_bom;
1374
4.05k
}
1375
1376
910
#define FULLPOINT(f,s) ( (((f)&0x3ff)<<10) + ((s)&0x3ff) + 0x10000 )
1377
/* Remember: There's a limit at 0x1ffff. */
1378
304k
#define UTF8LEN(x) ( (x)<0x80 ? 1 : ((x)<0x800 ? 2 : ((x)<0x10000 ? 3 : 4)))
1379
static void convert_utf16bom(mpg123_string *sb, const unsigned char* s, size_t l, const int noquiet)
1380
4.05k
{
1381
4.05k
  size_t i;
1382
4.05k
  size_t n; /* number bytes that make up full pairs */
1383
4.05k
  unsigned char *p;
1384
4.05k
  size_t length = 0; /* the resulting UTF-8 length */
1385
  /* Determine real length... extreme case can be more than utf-16 length. */
1386
4.05k
  size_t high = 0;
1387
4.05k
  size_t low  = 1;
1388
4.05k
  int bom_endian;
1389
1390
4.05k
  debug1("convert_utf16 with length %lu", (unsigned long)l);
1391
1392
4.05k
  bom_endian = check_bom(&s, &l);
1393
4.05k
  debug1("UTF16 endianness check: %i", bom_endian);
1394
1395
4.05k
  if(bom_endian == -1) /* little-endian */
1396
296
  {
1397
296
    high = 1; /* The second byte is the high byte. */
1398
296
    low  = 0; /* The first byte is the low byte. */
1399
296
  }
1400
1401
4.05k
  n = (l/2)*2; /* number bytes that make up full pairs */
1402
1403
  /* first: get length, check for errors -- stop at first one */
1404
308k
  for(i=0; i < n; i+=2)
1405
304k
  {
1406
304k
    unsigned long point = ((unsigned long) s[i+high]<<8) + s[i+low];
1407
304k
    if((point & 0xfc00) == 0xd800) /* lead surrogate */
1408
865
    {
1409
865
      unsigned short second = (i+3 < l) ? (s[i+2+high]<<8) + s[i+2+low] : 0;
1410
865
      if((second & 0xfc00) == 0xdc00) /* good... */
1411
455
      {
1412
455
        point = FULLPOINT(point,second);
1413
455
        length += UTF8LEN(point); /* possibly 4 bytes */
1414
455
        i+=2; /* We overstepped one word. */
1415
455
      }
1416
410
      else /* if no valid pair, break here */
1417
410
      {
1418
410
        if(noquiet) error2("Invalid UTF16 surrogate pair at %li (0x%04lx).", (unsigned long)i, point);
1419
410
        n = i; /* Forget the half pair, END! */
1420
410
        break;
1421
410
      }
1422
865
    }
1423
303k
    else length += UTF8LEN(point); /* 1,2 or 3 bytes */
1424
304k
  }
1425
1426
4.05k
  if(!mpg123_grow_string(sb, length+1))
1427
0
    return;
1428
1429
  /* Now really convert, skip checks as these have been done just before. */
1430
4.05k
  p = (unsigned char*) sb->p; /* Signedness doesn't matter but it shows I thought about the non-issue */
1431
308k
  for(i=0; i < n; i+=2)
1432
304k
  {
1433
304k
    unsigned long codepoint = ((unsigned long) s[i+high]<<8) + s[i+low];
1434
304k
    if((codepoint & 0xfc00) == 0xd800) /* lead surrogate */
1435
455
    {
1436
455
      unsigned short second = (s[i+2+high]<<8) + s[i+2+low];
1437
455
      codepoint = FULLPOINT(codepoint,second);
1438
455
      i+=2; /* We overstepped one word. */
1439
455
    }
1440
304k
    if(codepoint < 0x80) *p++ = (unsigned char) codepoint;
1441
255k
    else if(codepoint < 0x800)
1442
28.3k
    {
1443
28.3k
      *p++ = (unsigned char) (0xc0 | (codepoint>>6));
1444
28.3k
      *p++ = (unsigned char) (0x80 | (codepoint & 0x3f));
1445
28.3k
    }
1446
227k
    else if(codepoint < 0x10000)
1447
226k
    {
1448
226k
      *p++ = (unsigned char) (0xe0 | (codepoint>>12));
1449
226k
      *p++ = 0x80 | ((codepoint>>6) & 0x3f);
1450
226k
      *p++ = 0x80 | (codepoint & 0x3f);
1451
226k
    }
1452
455
    else if (codepoint < 0x200000)
1453
455
    {
1454
455
      *p++ = (unsigned char) (0xf0 | codepoint>>18);
1455
455
      *p++ = (unsigned char) (0x80 | ((codepoint>>12) & 0x3f));
1456
455
      *p++ = (unsigned char) (0x80 | ((codepoint>>6) & 0x3f));
1457
455
      *p++ = (unsigned char) (0x80 | (codepoint & 0x3f));
1458
455
    } /* ignore bigger ones (that are not possible here anyway) */
1459
304k
  }
1460
4.05k
  sb->p[sb->size-1] = 0; /* paranoia... */
1461
4.05k
  sb->fill = sb->size;
1462
4.05k
}
1463
#undef UTF8LEN
1464
#undef FULLPOINT
1465
1466
static void convert_utf8(mpg123_string *sb, const unsigned char* source, size_t len, const int noquiet)
1467
4.02k
{
1468
4.02k
  if(mpg123_grow_string(sb, len+1))
1469
4.02k
  {
1470
4.02k
    memcpy(sb->p, source, len);
1471
4.02k
    sb->p[len] = 0;
1472
4.02k
    sb->fill = len+1;
1473
4.02k
  }
1474
4.02k
}
1475
1476
#endif