1 /**
2  * Handling of Replay Gain information in ID3v2 tags.
3  *
4  * We store Replay Gain data in RVA2 frames inside the ID3v2.4 tag.
5  * Album and track gain are written as two separate frames.
6  * We use the RVA2 frame as follows:
7  *
8  * Identification string:  either "track" or "album";
9  * Channel number:         always 1 (master volume);
10  * Volume adjustment:      recommended gain relative to 89 dB standard;
11  * Bits representing peak: always 16;
12  * Peak volume:            max absolute sample value relative to full scale
13  *
14  * The meaning of the RVA2 peak volume field is not specified in ID3v2.4.
15  * We follow the interpretation of QuodLibet/mutagen: Peak volume is the
16  * maximum absolute sample value relative to full scale, before application
17  * of the volume adjustment, stored as an unsigned fixed point value with
18  * 1 integer bit and (peakbits-1) fractional bits.
19  *
20  * In addition to standard Replay Gain data, we also store mp3gain-specific
21  * fields in TXXX frames. The description string of such frames starts with
22  * "MP3GAIN_". These frames are only needed when mp3gain updates the encoded
23  * audio volume in MP3 stream (-r and -a command line options).
24  *
25  * We read tag data in ID3v2.2, ID3v2.3 or ID3v2.4 format, from either
26  * the beginning or the end of the file. Extended tag headers are ignored
27  * and removed; compressed frames are ignored but preserved. No workarounds
28  * are attempted for invalid ID3v2.4 tags.
29  *
30  * When writing/updating tag data, we always write a single ID3v2.4 tag
31  * at the beginning of the file, fully unsynchronized. If the original
32  * file had an ID3v2.2 or ID3v2.3 tag, it is upgraded to ID3v2.4. If the
33  * original file had only an appended tag, it is moved to the beginning of
34  * the file. If the original file contained multiple tags, we update only
35  * the first tag and ignore the rest (this is bad, but it's probably a
36  * rare case). If the original file had only an ID3v1 tag, it is copied
37  * to a new ID3v2 tag and the ID3v1 tag is left as it was.
38  *
39  * See: http://www.id3.org/id3v2.4.0-structure
40  *      http://www.id3.org/id3v2.4.0-frames
41  */
42 
43 
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <stdarg.h>
47 #include <string.h>
48 #include "apetag.h"
49 #include "id3tag.h"
50 #include "mp3gain.h"
51 
52 
53 #ifdef WIN32
54 #define strcasecmp(x,y) _stricmp(x,y)
55 #endif
56 
57 #define DBG(x)
58 /*#define DBG(x) (printf x)*/
59 
60 #define TAGFL_UNSYNC		(0x80)
61 #define TAGFL_EXTHDR		(0x40)
62 #define TAGFL_EXPR			(0x20)
63 #define TAGFL_FOOTER		(0x10)
64 #define FRAMEFL_BAD			(0x00f0)
65 #define FRAMEFL_TAGALTER	(0x4000)
66 #define FRAMEFL_GROUP		(0x0040)
67 #define FRAMEFL_COMPR		(0x0008)
68 #define FRAMEFL_CRYPT		(0x0004)
69 #define FRAMEFL_UNSYNC		(0x0002)
70 #define FRAMEFL_DLEN		(0x0001)
71 #define SYNCSAFE_INT_BAD	(0xffffffff)
72 
73 
74 struct ID3v2TagStruct {
75 	unsigned long offset;				/* offset of tag in file */
76 	unsigned long length;				/* total length of ID3v2 tag, including header/footer */
77 	unsigned int version;				/* ID3v2 version */
78 	unsigned int flags;					/* tag flags */
79 	struct ID3v2FrameStruct *frames;	/* linked list of frames */
80 };
81 
82 struct ID3v2FrameStruct {
83 	struct ID3v2FrameStruct *next;		/* pointer to next frame */
84 	char frameid[4];					/* frame ID */
85 	unsigned int flags;					/* frame flags */
86 	unsigned long len;					/* length of frame, excluding header */
87 	unsigned long hskip;				/* length of flag parameters */
88 	unsigned char *data;				/* pointer to data, excluding header */
89 };
90 
91 struct upgrade_id3v22_struct {
92 	char id_v22[3];
93 	char id_new[4];
94 };
95 
96 static const struct upgrade_id3v22_struct upgrade_id3v22_table[] = {
97 	{ "BUF", "RBUF" }, { "CNT", "PCNT" },
98 	{ "COM", "COMM" }, { "CRA", "AENC" },
99 	{ "ETC", "ETCO" }, { "EQU", "EQUA" },
100 	{ "GEO", "GEOB" }, { "IPL", "IPLS" },
101 	{ "LNK", "LINK" }, { "MCI", "MCDI" },
102 	{ "MLL", "MLLT" }, { "PIC", "APIC" /* NOTE: incompatible format */ },
103 	{ "POP", "POPM" }, { "REV", "RVRB" },
104 	{ "RVA", "RVAD" }, { "SLT", "SYLT" },
105 	{ "STC", "SYTC" }, { "TAL", "TALB" },
106 	{ "TBP", "TBPM" }, { "TCM", "TCOM" },
107 	{ "TCO", "TCON" }, { "TCR", "TCOP" },
108 	{ "TDA", "TDAT" }, { "TDY", "TDLY" },
109 	{ "TEN", "TENC" }, { "TFT", "TFLT" },
110 	{ "TIM", "TIME" }, { "TKE", "TKEY" },
111 	{ "TLA", "TLAN" }, { "TLE", "TLEN" },
112 	{ "TMT", "TMED" }, { "TOA", "TOPE" },
113 	{ "TOF", "TOFN" }, { "TOL", "TOLY" },
114 	{ "TOR", "TORY" }, { "TOT", "TOAL" },
115 	{ "TP1", "TPE1" }, { "TP2", "TPE2" },
116 	{ "TP3", "TPE3" }, { "TP4", "TPE4" },
117 	{ "TPA", "TPOS" }, { "TPB", "TPUB" },
118 	{ "TRC", "TSRC" }, { "TRD", "TRDA" },
119 	{ "TRK", "TRCK" }, { "TSI", "TSIZ" },
120 	{ "TSS", "TSSE" }, { "TT1", "TIT1" },
121 	{ "TT2", "TIT2" }, { "TT3", "TIT3" },
122 	{ "TXT", "TEXT" }, { "TXX", "TXXX" },
123 	{ "TYE", "TYER" }, { "UFI", "UFID" },
124 	{ "ULT", "USLT" }, { "WAF", "WOAF" },
125 	{ "WAR", "WOAR" }, { "WAS", "WOAS" },
126 	{ "WCM", "WCOM" }, { "WCP", "WCOP" },
127 	{ "WPB", "WPUB" }, { "WXX", "WXXX" },
128 	{ "\0\0\0", "\0\0\0\0" } };
129 
130 
131 /**
132  * Decode a 4-byte unsigned integer.
133  */
id3_get_int32(const unsigned char * p)134 static __inline unsigned long id3_get_int32(const unsigned char *p)
135 {
136 	return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
137 }
138 
139 
140 /**
141  * Decode a 4-byte unsigned synchsafe integer.
142  */
id3_get_syncsafe_int(const unsigned char * p)143 static __inline unsigned long id3_get_syncsafe_int(const unsigned char *p)
144 {
145 	if ((p[0] | p[1] | p[2] | p[3]) & 0x80)
146 		return SYNCSAFE_INT_BAD;
147 	return (p[0] << 21) | (p[1] << 14) | (p[2] << 7) | p[3];
148 }
149 
150 
151 /**
152  * Write a 4-byte unsigned synchsafe integer.
153  */
id3_put_syncsafe_int(unsigned char * p,unsigned long i)154 static __inline void id3_put_syncsafe_int(unsigned char *p, unsigned long i)
155 {
156 	p[0] = (i >> 21) & 0x7f;
157 	p[1] = (i >> 14) & 0x7f;
158 	p[2] = (i >>  7) & 0x7f;
159 	p[3] = i & 0x7f;
160 }
161 
162 
163 /**
164  * Decode srclen bytes of unsynchronized data from src into dest.
165  * Return the number of bytes written into dest.
166  *
167  * The buffer pointed to by dest must be large enough to hold the decoded data.
168  * The decoded data will never be longer than the unsynchronized data.
169  * Decoding may be performed in-place by specifying dest equal to src.
170  *
171  * If dest == NULL, decoded data are not stored but the decoded length is
172  * still computed and returned.
173  */
id3_get_unsync_data(unsigned char * dest,const unsigned char * src,unsigned long srclen)174 static unsigned long id3_get_unsync_data(unsigned char *dest, const unsigned char *src, unsigned long srclen)
175 {
176 	unsigned long k = 0, i;
177 	for (i = 0; i < srclen; i++) {
178 		if (dest)
179 			dest[k] = src[i];
180 		k++;
181 		if (src[i] == 0xff && i + 1 < srclen && src[i+1] == 0x00)
182 			i++;
183 	}
184 	return k;
185 }
186 
187 
188 /**
189  * Encode srclen bytes of data from src, writing the unsynchronized version
190  * into dest. Return the number of bytes written into dest.
191  *
192  * The buffer pointed to by dest must be large enough to hold the
193  * unsynchronized data.
194  *
195  * If dest == NULL, unsynchronized data are not stored but the unsynchronized
196  * length is still computed and returned.
197  *
198  * If the returned length is equal to srclen, unsynchronization is not
199  * needed for these data.
200  */
id3_put_unsync_data(unsigned char * dest,const unsigned char * src,unsigned long srclen)201 static unsigned long id3_put_unsync_data(unsigned char *dest, const unsigned char *src, unsigned long srclen)
202 {
203 	unsigned long k = 0, i;
204 	for (i = 0; i < srclen; i++) {
205 		if (dest)
206 			dest[k] = src[i];
207 		k++;
208 		if (src[i] == 0xff && (i + 1 == srclen || src[i+1] == 0x00 || (src[i+1] & 0xe0) == 0xe0)) {
209 			if (dest)
210 				dest[k] = 0x00;
211 			k++;
212 		}
213 	}
214 	return k;
215 }
216 
217 
218 /**
219  * Release memory associated with a chain of frame structures.
220  */
id3_release_frames(struct ID3v2FrameStruct * frame)221 static void id3_release_frames(struct ID3v2FrameStruct *frame)
222 {
223 	struct ID3v2FrameStruct *tframe;
224 	while (frame) {
225 		tframe = frame;
226 		frame = frame->next;
227 		free(tframe->data);
228 		free(tframe);
229 	}
230 }
231 
232 
233 /**
234  * Construct an ID3v2 frame according to specified format and parameters.
235  *
236  * The format string contains one character per field in the frame:
237  *   's'  stores a string without null-termination (expects const char *)
238  *   'b'  stores a single byte (expects unsigned int)
239  *   'h'  stores a 16-bit big-endian integer (expects unsigned int)
240  *
241  * Return a newly allocated ID3v2FrameStruct, or NULL if the format
242  * is invalid.
243  */
id3_make_frame(const char * frameid,const char * format,...)244 static struct ID3v2FrameStruct * id3_make_frame(const char *frameid, const char *format, ...)
245 {
246 	va_list ap;
247 	struct ID3v2FrameStruct *frame;
248 	unsigned long j, k;
249 	unsigned int i;
250 	const char *p, *s;
251 
252 	va_start(ap, format);
253 	k = 0;
254 	for (p = format; *p; p++) {
255 		switch (*p) {
256 			case 's':	/* string */
257 				s = va_arg(ap, const char *);
258 				k += strlen(s);
259 				break;
260 			case 'b':	/* byte */
261 				i = va_arg(ap, unsigned int);
262 				k += 1;
263 				break;
264 			case 'h':	/* 16-bit integer */
265 				i = va_arg(ap, unsigned int);
266 				k += 2;
267 				break;
268 			default:
269 				va_end(ap);
270 				return NULL;
271 		}
272 	}
273 	va_end(ap);
274 
275 	frame = malloc(sizeof(struct ID3v2FrameStruct));
276 	frame->next = NULL;
277 	strncpy(frame->frameid, frameid, 4);
278 	frame->flags = 0;
279 	frame->len = k;
280 	frame->hskip = 0;
281 	frame->data = malloc(k);
282 
283 	va_start(ap, format);
284 	k = 0;
285 	for (p = format; *p; p++) {
286 		switch (*p) {
287 			case 's':	/* string */
288 				s = va_arg(ap, const char *);
289 				j = strlen(s);
290 				memcpy(frame->data + k, s, j);
291 				k += j;
292 				break;
293 			case 'b':	/* byte */
294 				i = va_arg(ap, unsigned int);
295 				frame->data[k] = i;
296 				k += 1;
297 				break;
298 			case 'h':	/* 16-bit integer */
299 				i = va_arg(ap, unsigned int);
300 				frame->data[k] = (i >> 8) & 0xff;
301 				frame->data[k+1] = i & 0xff;
302 				k += 2;
303 				break;
304 			default:
305 				va_end(ap);
306 				free(frame->data);
307 				free(frame);
308 				return NULL;
309 		}
310 	}
311 	va_end(ap);
312 
313 	return frame;
314 }
315 
316 
317 /**
318  * Decode an RVA2 frame (only track/album gain, only master channel).
319  *
320  * Store gain information in the info structure, unless info == NULL.
321  * Return 1 if the frame is an RVA2 frame with track/album gain, 0 otherwise.
322  */
id3_decode_rva2_frame(const struct ID3v2FrameStruct * frame,struct MP3GainTagInfo * info)323 static int id3_decode_rva2_frame(const struct ID3v2FrameStruct *frame, struct MP3GainTagInfo *info)
324 {
325 	unsigned long p;
326 	int is_album_gain, channel, peakbits;
327 	double gain, peak;
328 
329 	/* Ignore non-RVA2 frames. */
330 	if (memcmp(frame->frameid, "RVA2", 4) != 0)
331 		return 0;
332 
333 	p = frame->hskip;
334 
335 	/* Check identification string; we understand only "track" and "album". */
336 	if (p + 6 <= frame->len &&
337 	    (memcmp(frame->data + p, "track\0", 6) == 0 ||
338 	     memcmp(frame->data + p, "TRACK\0", 6) == 0)) {
339 		is_album_gain = 0;
340 		p += 6;
341 	} else if (p + 6 <= frame->len &&
342 	           (memcmp(frame->data + p, "album\0", 6) == 0 ||
343 	            memcmp(frame->data + p, "ALBUM\0", 6) == 0)) {
344 		is_album_gain = 1;
345 		p += 6;
346 	} else {
347 		return 0;
348 	}
349 
350 	/* Process per-channel data. */
351 	while (p + 4 <= frame->len) {
352 		/*
353 		 *  p+0 :       channel number
354 		 *  p+1, p+2 :  16-bit signed BE int = adjustment * 512
355 		 *  p+3 :       nr of bits representing peak
356 		 *  p+4 ... :   unsigned multibyte BE int = peak sample * 2**(peakbits-1)
357 		 */
358 		channel = frame->data[p];
359 		gain = (double)(((signed char)(frame->data[p+1]) << 8) | frame->data[p+2]) / 512.0;
360 		peakbits = frame->data[p+3];
361 		if (p + 4 + (peakbits + 7) / 8 > frame->len)
362 			break;
363 		peak = 0;
364 		if (peakbits > 0)  peak += (double)(frame->data[p+4]);
365 		if (peakbits > 8)  peak += (double)(frame->data[p+5]) / 256.0;
366 		if (peakbits > 16) peak += (double)(frame->data[p+6]) / 65536.0;
367 		if (peakbits > 0)  peak = peak / (double)(1 << ((peakbits - 1) & 7));
368 		p += 4 + (peakbits + 7) / 8;
369 		if (channel == 1) { /* channel == master volume channel */
370 			if (info) {
371 				if (is_album_gain) {
372 					info->haveAlbumGain = 1;
373 					info->albumGain = gain;
374 					info->haveAlbumPeak = (peakbits > 0);
375 					info->albumPeak = peak;
376 				} else {
377 					info->haveTrackGain = 1;
378 					info->trackGain = gain;
379 					info->haveTrackPeak = (peakbits > 0);
380 					info->trackPeak = peak;
381 				}
382 			}
383 		}
384 	}
385 
386 	return 1;
387 }
388 
389 
390 /**
391  * Create an RVA2 frame, track or album gain, master channel.
392  * Return a newly allocated ID3v2FrameStruct.
393  */
id3_make_rva2_frame(int is_album_gain,double gain,int have_peak,double peak)394 static struct ID3v2FrameStruct * id3_make_rva2_frame(int is_album_gain, double gain, int have_peak, double peak)
395 {
396 	const char *ident;
397 	int g;
398 	unsigned int p;
399 	/*
400 	 * identification:    string = "track" or "album"
401 	 * channel type:      byte   = 1 (master volume)
402 	 * volume adjustment: int16  = gain * 512
403 	 * peak bits:         byte   = 16 (or 0 if no peak information)
404 	 * peak:              uint16 = peak * 32768
405 	 */
406 	ident = (is_album_gain) ? "album" : "track";
407 	g = (gain <= -64) ? -32768 :
408 	    (gain >=  64) ? 32767 :
409 	    (int)(gain * 512);
410 	if (g < -32768) g = -32768;
411 	if (g >  32767) g = 32767;
412 	if (have_peak) {
413 		p = (peak <= 0) ? 0 :
414 		    (peak >= 2) ? 65535 :
415 		    (unsigned int)(peak * 32768);
416 		if (p > 65535) p = 65535;
417 		return id3_make_frame("RVA2", "sbbhbh", ident, 0, 1, g, 16, p);
418 	} else {
419 		return id3_make_frame("RVA2", "sbbhb", ident, 0, 1, g, 0);
420 	}
421 }
422 
423 
424 /**
425  * Decode an APEv2/Vorbis-style TXXX frame, matching
426  * /REPLAYGAIN_(ALBUM|TRACK)_(GAIN|PEAK)/ case-insensitively.
427  *
428  * Store gain information in the info structure, unless info == NULL.
429  * Return 1 if the frame is one of our TXXX frames, 0 otherwise.
430  */
id3_decode_txxx_frame(const struct ID3v2FrameStruct * frame,struct MP3GainTagInfo * info)431 static int id3_decode_txxx_frame(const struct ID3v2FrameStruct *frame, struct MP3GainTagInfo *info)
432 {
433 	unsigned long p, k;
434 	char buf[64];
435 	const char *value;
436 
437 	/* Ignore non-TXXX frames. */
438 	if (memcmp(frame->frameid, "TXXX", 4) != 0)
439 		return 0;
440 
441 	p = frame->hskip;
442 
443 	/* Check text encoding; we understand only 0 (ISO-8859-1) and 3 (UTF-8). */
444 	if (p >= frame->len || (frame->data[p] != 0 && frame->data[p] != 3))
445 		return 0;
446 	p++;
447 
448 	/* Copy character data to temporary buffer. */
449 	k = (frame->len - p + 1 < sizeof(buf)) ? (frame->len - p) : (sizeof(buf) - 2);
450 	memcpy(buf, frame->data + p, k);
451 	buf[k] = '\0';		/* terminate the value string */
452 	buf[k+1] = '\0';	/* ensure buf contains two terminated strings, even for invalid frame data */
453 	value = buf + strlen(buf) + 1;
454 
455 	/* Check identification string. */
456 	if (strcasecmp(buf, "REPLAYGAIN_ALBUM_GAIN") == 0) {
457                 if (info) {
458 			info->haveAlbumGain = !0;
459 			info->albumGain = atof(value);
460 		}
461 		return 1;
462 	} else if (strcasecmp(buf, "REPLAYGAIN_TRACK_GAIN") == 0) {
463                 if (info) {
464 			info->haveTrackGain = !0;
465 			info->trackGain = atof(value);
466 		}
467 		return 1;
468 	} else if (strcasecmp(buf, "REPLAYGAIN_ALBUM_PEAK") == 0) {
469                 if (info) {
470 			info->haveAlbumPeak = !0;
471 			info->albumPeak = atof(value);
472 		}
473 		return 1;
474 	} else if (strcasecmp(buf, "REPLAYGAIN_TRACK_PEAK") == 0) {
475                 if (info) {
476 			info->haveTrackPeak = !0;
477 			info->trackPeak = atof(value);
478 		}
479 		return 1;
480 	} else if (strcasecmp(buf, "REPLAYGAIN_REFERENCE_LOUDNESS") == 0) {
481 		/* we derive no information from this at the moment, but
482 		 * we do want to delete this frame if re-writing */
483 		return 1;
484 	}
485 
486 	return 0;
487 }
488 
489 /**
490  * Decode a mp3gain-specific TXXX frame, either "MP3GAIN_UNDO" or
491  * "MP3GAIN_MINMAX" or "MP3GAIN_ALBUM_MINMAX".
492  *
493  * Store gain information in the info structure, unless info == NULL.
494  * Return 1 if the frame is a mp3gain-specific TXXX frame, 0 otherwise.
495  */
id3_decode_mp3gain_frame(const struct ID3v2FrameStruct * frame,struct MP3GainTagInfo * info)496 static int id3_decode_mp3gain_frame(const struct ID3v2FrameStruct *frame, struct MP3GainTagInfo *info)
497 {
498 	unsigned long p, k;
499 	char buf[64];
500 	int f1, f2;
501 	char f3;
502 
503 	/* Ignore non-TXXX frames. */
504 	if (memcmp(frame->frameid, "TXXX", 4) != 0)
505 		return 0;
506 
507 	p = frame->hskip;
508 
509 	/* Check text encoding; we understand only 0 (ISO-8859-1) and 3 (UTF-8). */
510 	if (p >= frame->len || (frame->data[p] != 0 && frame->data[p] != 3))
511 		return 0;
512 	p++;
513 
514 	/* Copy character data to temporary buffer. */
515 	k = (frame->len - p + 1 < sizeof(buf)) ? (frame->len - p) : (sizeof(buf) - 2);
516 	memcpy(buf, frame->data + p, k);
517 	buf[k] = '\0';		/* terminate the value string */
518 	buf[k+1] = '\0';	/* ensure buf contains two terminated strings, even for invalid frame data */
519 
520 	/* Check identification string. */
521 	if (strcasecmp(buf, "MP3GAIN_UNDO") == 0) {
522 		/* value should be something like "+003,+003,W" */
523 		if (sscanf(buf + strlen(buf) + 1, "%d,%d,%c", &f1, &f2, &f3) == 3 &&
524 		    info != NULL) {
525 			info->haveUndo = 1;
526 			info->undoLeft = f1;
527 			info->undoRight = f2;
528 			info->undoWrap = (f3 == 'w' || f3 == 'W');
529 		}
530 		return 1;
531 	} else if (strcasecmp(buf, "MP3GAIN_MINMAX") == 0) {
532 		/* value should be something like "001,153" */
533 		if (sscanf(buf + strlen(buf) + 1, "%d,%d", &f1, &f2) == 2 &&
534 		    info != NULL) {
535 			info->haveMinMaxGain = 1;
536 			info->minGain = f1;
537 			info->maxGain = f2;
538 		}
539 		return 1;
540 	} else if (strcasecmp(buf, "MP3GAIN_ALBUM_MINMAX") == 0) {
541 		/* value should be something like "001,153" */
542 		if (sscanf(buf + strlen(buf) + 1, "%d,%d", &f1, &f2) == 2 &&
543 		    info != NULL) {
544 			info->haveAlbumMinMaxGain = 1;
545 			info->albumMinGain = f1;
546 			info->albumMaxGain = f2;
547 		}
548 		return 1;
549 	}
550 
551 	return 0;
552 }
553 
554 
555 /**
556  * Read an ID3v2 tag from the current position in the MP3 file.
557  *
558  * Return 1 on success, 0 if no tag is found, or a negative error code
559  * if the tag can not be processed.
560  */
id3_parse_v2_tag(FILE * f,struct ID3v2TagStruct * tag)561 static int id3_parse_v2_tag(FILE *f, struct ID3v2TagStruct *tag)
562 {
563 	unsigned char buf[12], frameid[4];
564 	unsigned int fflags;
565 	unsigned long dlen, flen, fhskip, p, k;
566 	unsigned char *tagdata;
567 	struct ID3v2FrameStruct *frame, **pframe;
568 
569 	/* Read header */
570 	tag->offset = ftell(f);
571 	if (fread(buf, 1, 10, f) != 10)
572 		return 0;
573 
574 	/* Check 'ID3' signature. */
575 	if (memcmp(buf, "ID3", 3) != 0)
576 		return 0;
577 
578 	DBG(("DEBUG: Found ID3v2 tag at offset %lu\n", tag->offset));
579 
580 	/* Check version and flags. */
581 	switch (buf[3]) {
582 		case 2:	/* ID3v2.2 */
583 			if (buf[5] & (~(TAGFL_UNSYNC)))
584 				return M3G_ERR_TAGFORMAT;	/* unknown flags */
585 			break;
586 		case 3: /* ID3v2.3 */
587 			if (buf[5] & (~(TAGFL_UNSYNC | TAGFL_EXTHDR | TAGFL_EXPR)))
588 				return M3G_ERR_TAGFORMAT;	/* unknown flags */
589 			break;
590 		case 4: /* ID3v2.4 */
591 			if (buf[5] & (~(TAGFL_UNSYNC | TAGFL_EXTHDR | TAGFL_EXPR | TAGFL_FOOTER)))
592 				return M3G_ERR_TAGFORMAT;	/* unknown flags */
593 			break;
594 		default:
595 			return M3G_ERR_TAGFORMAT;		/* unknown version */
596 	}
597 
598 	/* Check length. */
599 	dlen = id3_get_syncsafe_int(buf + 6);
600 	if (dlen == SYNCSAFE_INT_BAD)
601 		return M3G_ERR_TAGFORMAT;
602 
603 	/* Fill tag structure. */
604 	tag->flags   = buf[5];
605 	tag->version = (buf[3] << 8) | buf[4];
606 	tag->length  = 10 + dlen + ((tag->flags & TAGFL_FOOTER) ? 10 : 0);
607 	tag->frames  = NULL;
608 
609 	DBG(("  version=%04x length=%lu flags=%02x\n", tag->version, tag->length, tag->flags));
610 
611 	/* Read rest of the tag. */
612 	tagdata = malloc(dlen);
613 	if (fread(tagdata, 1, dlen, f) != dlen)
614 		goto badtag;
615 
616 	/* If this is an unsynced v2.2 or v2.3 tag, decode it now. */
617 	if ((tag->version >> 8) != 4 && (tag->flags & TAGFL_UNSYNC) != 0) {
618 		dlen = id3_get_unsync_data(tagdata, tagdata, dlen);
619 	}
620 
621 	/* Skip extended header. */
622 	p = 0;
623 	if ((tag->flags & TAGFL_EXTHDR) != 0) {
624 		DBG(("  skip extended header\n"));
625 		if (p + 6 > dlen)
626 			goto badtag;
627 		if ((tag->version >> 8) == 4) {
628 			/* Skip ID3v2.4 extended header */
629 			k = id3_get_syncsafe_int(tagdata + p);
630 			if (k == SYNCSAFE_INT_BAD || k > dlen)
631 				goto badtag;
632 			p += k;
633 		} else if ((tag->version >> 8) == 3) {
634 			/* Skip ID3v2.3 extended header */
635 			k = id3_get_int32(tagdata + p);
636 			if (k > dlen)
637 				goto badtag;
638 			p += 4 + k;
639 		}
640 	}
641 
642 	/* Scan frames. */
643 	pframe = &(tag->frames);
644 	while (p < dlen && tagdata[p] != '\0') {
645 
646 		/* Decode frame header. */
647 		switch (tag->version >> 8) {
648 
649 			case 2: /* ID3v2.2 */
650 				if (p + 5 > dlen)
651 					goto badtag;
652 				memset(frameid, 0, 4);
653 				for (k = 0; upgrade_id3v22_table[k].id_new[0]; k++) {
654 					if (memcmp(tagdata + p, upgrade_id3v22_table[k].id_v22, 3) == 0) {
655 						memcpy(frameid, upgrade_id3v22_table[k].id_new, 4);
656 						break;
657 					}
658 				}
659 				flen   = (tagdata[p+3] << 16) | (tagdata[p+4] << 8) | tagdata[p+5];
660 				fflags = 0;
661 				if (flen > dlen)
662 					goto badtag;
663 				p += 6;
664 				break;
665 
666 			case 3: /* ID3v2.3 */
667 				if (p + 10 > dlen)
668 					goto badtag;
669 				memcpy(frameid, tagdata + p, 4);
670 				flen   = id3_get_int32(tagdata + p + 4);
671 				fflags = (tagdata[p+8] << 7) & 0xff00;
672 				if (tagdata[p+9] & 0x80) fflags |= FRAMEFL_COMPR | FRAMEFL_DLEN;
673 				if (tagdata[p+9] & 0x40) fflags |= FRAMEFL_CRYPT;
674 				if (tagdata[p+9] & 0x20) fflags |= FRAMEFL_GROUP;
675 				if (tagdata[p+9] & 0x1f) fflags |= FRAMEFL_BAD;
676 				if (flen > dlen)
677 					goto badtag;
678 				p += 10;
679 				break;
680 
681 			case 4: /* ID3v2.4 */
682 				if (p + 10 > dlen)
683 					goto badtag;
684 				memcpy(frameid, tagdata + p, 4);
685 				flen   = id3_get_syncsafe_int(tagdata + p + 4);
686 				fflags = (tagdata[p+8] << 8) | tagdata[p+9];
687 				if (flen == SYNCSAFE_INT_BAD || flen > dlen)
688 					goto badtag;
689 				p += 10;
690 				break;
691 
692 			default: /* unreachable */
693 				goto badtag;
694 		}
695 
696 		if (p + flen > dlen)
697 			goto badtag;
698 
699 		DBG(("  got frameid=%.4s fflags=%04x\n", frameid, fflags));
700 
701 		/* Drop unsupported frame types. */
702 		if (frameid[0] == '\0' ||
703 		    memcmp(frameid, "RVAD", 4) == 0 ||
704 		    memcmp(frameid, "RGAD", 4) == 0 ||
705 		    memcmp(frameid, "XRVA", 4) == 0) {
706 			DBG(("  drop unsupported frame\n"));
707 			p += flen;
708 			continue;
709 		}
710 
711 		/* Drop v2.3 frames which we can not upgrade. */
712 		if ((tag->version >> 8) == 3 && (fflags & (FRAMEFL_CRYPT | FRAMEFL_BAD)) != 0) {
713 			DBG(("  drop non-upgradable frame\n"));
714 			p += flen;
715 			continue;
716 		}
717 
718 		/* Drop frames that are too short for their flags. */
719 		fhskip = (fflags & FRAMEFL_GROUP ? 1 : 0) +
720 		         (fflags & FRAMEFL_CRYPT ? 1 : 0) +
721 		         (fflags & FRAMEFL_DLEN  ? 4 : 0);
722 		if (fhskip > flen) {
723 			DBG(("  drop short frame\n"));
724 			p += flen;
725 			continue;
726 		}
727 
728 		/* Drop v2.2 PIC frames that are too short. */
729 		if ((tag->version >> 8) == 2 && memcmp(frameid, "APIC", 4) == 0 && flen < 6) {
730 			DBG(("  drop short PIC frame\n"));
731 			p += flen;
732 			continue;
733 		}
734 
735 		/* Rename TYER (Year) to TDRC (Recording time) */
736 		if (memcmp(frameid, "TYER", 4) == 0)
737 			memcpy(frameid, "TDRC", 4);
738 
739 		/* Drop frames that want to be dropped on tag alteration. */
740 		if (fflags & FRAMEFL_TAGALTER) {
741 			DBG(("  drop FRAMEFL_TAGALTER frame\n"));
742 			p += flen;
743 			continue;
744 		}
745 
746 		/* Allocate frame structure. */
747 		frame = malloc(sizeof(struct ID3v2FrameStruct));
748 		frame->next = NULL;
749 		memcpy(frame->frameid, frameid, 4);
750 		frame->flags = fflags;
751 		frame->hskip = fhskip;
752 		*pframe = frame;
753 		pframe = &(frame->next);
754 
755 		/* Copy frame data. */
756 		if ((tag->version >> 8) == 4 && (fflags & FRAMEFL_UNSYNC) != 0) {
757 			/* This frame is unsynchronized; decode it now. */
758 			frame->data = malloc(flen);
759 			k = id3_get_unsync_data(frame->data, tagdata + p, flen);
760 			frame->len = k;
761 			p += flen;
762 		} else if ((tag->version >> 8) == 2 && memcmp(frameid, "APIC", 4) == 0) {
763 			/* APIC frame format differs from PIC frame format */
764 			frame->data = malloc(flen + 12);
765 			frame->data[0] = tagdata[p];
766 			k = 1;
767 			if (memcmp(tagdata + p + 1, "PNG", 3) == 0) {
768 				memcpy(frame->data + k, "image/png", strlen("image/png") + 1);
769 				k += strlen("image/png") + 1;
770 			} else if (memcmp(tagdata + p + 1, "JPG", 3) == 0) {
771 				memcpy(frame->data + k, "image/jpeg", strlen("image/jpeg") + 1);
772 				k += strlen("image/jpeg") + 1;
773 			} else if (tagdata[p+1] == '\0') {
774 				memcpy(frame->data + k, tagdata + p + 1, 3);
775 				frame->data[k+3] = '\0';
776 				k += 4;
777 			}
778 			memcpy(frame->data + k, tagdata + p + 4, flen - 4);
779 			frame->len = k + flen - 4;
780 			p += flen;
781 		} else {
782 			/* Normal case, just copy the data. */
783 			frame->data = malloc(flen);
784 			memcpy(frame->data, tagdata + p, flen);
785 			frame->len = flen;
786 			p += flen;
787 		}
788 
789 		/* Reorder flag parameters of upgraded v2.3 frames. */
790 		if ((tag->version >> 8) == 3 && (fflags & FRAMEFL_DLEN) != 0) {
791 			k = id3_get_int32(frame->data);
792 			if (fflags & FRAMEFL_GROUP) {
793 				frame->data[0] = frame->data[4];
794 				id3_put_syncsafe_int(frame->data + 1, k);
795 			} else {
796 				id3_put_syncsafe_int(frame->data, k);
797 			}
798 		}
799 
800 	}
801 
802 	if (p > dlen)
803 		goto badtag;
804 
805 	free(tagdata);
806 	return 1;
807 
808 badtag:
809 	free(tagdata);
810 	id3_release_frames(tag->frames);
811 	return M3G_ERR_TAGFORMAT;
812 }
813 
814 
815 /**
816  * Write an ID3v2 tag at the current position in the MP3 file.
817  *
818  * Tags are always written in ID3v2.4 format.
819  * Tags are always written completely unsynchronized,
820  * without extended header, padded up to an integer multiple of 2 KB.
821  * We don't write a tag footer (not supported by QuodLibet).
822  *
823  * Return 1 on success, 0 if the tag contains no frames,
824  * or a negative error code.
825  */
id3_write_tag(FILE * f,struct ID3v2TagStruct * tag)826 static int id3_write_tag(FILE *f, struct ID3v2TagStruct *tag)
827 {
828 	unsigned long dlen, p, k;
829 	unsigned char *tagdata;
830 	struct ID3v2FrameStruct *frame;
831 
832 	DBG(("DEBUG: Writing ID3v2 tag\n"));
833 
834 	/* Do not write a tag with zero frames. */
835 	if (tag->frames == NULL)
836 		return 0;
837 
838 	/* Compute raw total length of tag. */
839 	dlen = 10;				/* tag header */
840 	for (frame = tag->frames; frame; frame = frame->next) {
841 		dlen += 10;
842 		dlen += id3_put_unsync_data(NULL, frame->data, frame->len);
843 	}
844 	dlen = (dlen + 2047) & (~2047);		/* padding */
845 
846 	DBG(("  length=%lu\n", dlen));
847 
848 	/* Allocate buffer and fill with zeros. */
849 	tagdata = calloc(dlen, sizeof(unsigned char));
850 
851 	/* Prepare tag header. */
852 	tagdata[0] = 'I';
853 	tagdata[1] = 'D';
854 	tagdata[2] = '3';
855 	tagdata[3] = 4;
856 	tagdata[4] = 0;
857 	tagdata[5] = TAGFL_UNSYNC | (tag->flags & TAGFL_EXPR);
858 	id3_put_syncsafe_int(tagdata + 6, dlen - 10);
859 	p = 10;
860 
861 	/* Prepare frames. */
862 	for (frame = tag->frames; frame; frame = frame->next) {
863 		unsigned long fflags = frame->flags & (~FRAMEFL_UNSYNC);
864 		memcpy(tagdata + p, frame->frameid, 4);
865 		k = id3_put_unsync_data(tagdata + p + 10, frame->data, frame->len);
866 		id3_put_syncsafe_int(tagdata + p + 4, k);
867 		if (k != frame->len) fflags |= FRAMEFL_UNSYNC;
868 		tagdata[p+8] = (fflags >> 8) & 0xff;
869 		tagdata[p+9] = fflags & 0xff;
870 		p += 10 + k;
871 		DBG(("  write frameid=%.4s length=%lu\n", frame->frameid, 10 + k));
872 	}
873 
874 	/* Write the whole thing. */
875 	if (fwrite(tagdata, 1, dlen, f) != dlen) {
876 		free(tagdata);
877 		return M3G_ERR_WRITE;
878 	}
879 
880 	free(tagdata);
881 	return 1;
882 }
883 
884 
885 /**
886  * Read an ID3v1 tag from the current position in the MP3 file.
887  *
888  * Return 1 on success, 0 if no tag is found.
889  */
id3_parse_v1_tag(FILE * f,struct ID3v2TagStruct * tag)890 static int id3_parse_v1_tag(FILE *f, struct ID3v2TagStruct *tag)
891 {
892 	unsigned char buf[128];
893 	char sbuf[32],*p;
894 
895 	struct ID3v2FrameStruct **pframe;
896 
897 	/* Read tag */
898 	tag->offset = ftell(f);
899 	if (fread(buf, 1, 128, f) != 128)
900 		return 0;
901 
902 	/* Check 'TAG' signature. */
903 	if (memcmp(buf, "TAG", 3) != 0)
904 		return 0;
905 
906 	DBG(("DEBUG: Found ID3v1 tag at offset %lu\n", tag->offset));
907 
908 	/* Convert ID3v1 data to ID3v2.4 */
909 	tag->length = 128;
910 	tag->version = 0;
911 	tag->flags = 0;
912 	tag->frames = NULL;
913 
914 	pframe = &(tag->frames);
915 
916 	/* Add title field (offset 3, len 30). */
917 	if (buf[3] != '\0') {
918 		memcpy(sbuf, buf + 3, 30);
919 		sbuf[30] = '\0';
920 		/* get rid of trailing spaces */
921 		for(p=sbuf+29; *p==' ' && p>=sbuf; *p--='\0');
922 		*pframe = id3_make_frame("TIT2", "bs", 0, sbuf);
923 		pframe = &((*pframe)->next);
924 	}
925 
926 	/* Add artist field (offset 33, len 30). */
927 	if (buf[33] != '\0') {
928 		memcpy(sbuf, buf + 33, 30);
929 		sbuf[30] = '\0';
930 		/* get rid of trailing spaces */
931 		for(p=sbuf+29; *p==' ' && p>=sbuf; *p--='\0');
932 		DBG(("fixed v1 artist: \"%s\"\n",sbuf));
933 		*pframe = id3_make_frame("TPE1", "bs", 0, sbuf);
934 		pframe = &((*pframe)->next);
935 	}
936 
937 	/* Add album field (offset 63, len 30). */
938 	if (buf[63] != '\0') {
939 		memcpy(sbuf, buf + 63, 30);
940 		sbuf[30] = '\0';
941 		/* get rid of trailing spaces */
942 		for(p=sbuf+29; *p==' ' && p>=sbuf; *p--='\0');
943 		*pframe = id3_make_frame("TALB", "bs", 0, sbuf);
944 		pframe = &((*pframe)->next);
945 	}
946 
947 	/* Add release year (offset 93, len 4). */
948 	if (buf[93] >= '0' && buf[93] <= '9' &&
949 	    buf[94] >= '0' && buf[94] <= '9' &&
950 	    buf[95] >= '0' && buf[95] <= '9' &&
951 	    buf[96] >= '0' && buf[96] <= '9') {
952 		memcpy(sbuf, buf + 93, 4);
953 		sbuf[4] = '\0';
954 		*pframe = id3_make_frame("TDRC", "bs", 0, sbuf);
955 		pframe = &((*pframe)->next);
956 	}
957 
958 	/* Add comment (offset 97, len 30). */
959 	if (buf[97] != '\0') {
960 		memcpy(sbuf, buf + 97, 30);
961 		sbuf[30] = '\0';
962 		/* get rid of trailing spaces */
963 		for(p=sbuf+29; *p==' ' && p>=sbuf; *p--='\0');
964 		/* assume ISO-8859-1, unknown language, no description */
965 		*pframe = id3_make_frame("COMM", "bssbs", 0, "XXX", "", 0, sbuf);
966 		pframe = &((*pframe)->next);
967 	}
968 
969 	/* Add track number (offset 126, len 1). */
970 	if (buf[125] == '\0' && buf[126] != 0) {
971 		sprintf(sbuf, "%u", buf[126]);
972 		*pframe = id3_make_frame("TRCK", "bs", 0, sbuf);
973 		pframe = &((*pframe)->next);
974 	}
975 
976 	return 1;
977 }
978 
979 
980 /**
981  * Search for an ID3v2 tag at the beginning and end of the file.
982  * If no ID3v2 tag is found, search for an ID3v1 tag at the end
983  * of the file.
984  *
985  * Return 1 on success, 0 if no tag is found, or a negative error code
986  * if the tag can not be processed.
987  */
id3_search_tag(FILE * f,struct ID3v2TagStruct * tag)988 static int id3_search_tag(FILE *f, struct ID3v2TagStruct *tag)
989 {
990 	unsigned char buf[32];
991 	unsigned long pos, k, id3v1_pos = 0;
992 	int j, ret;
993 
994 	/* Look for ID3v2 at the beginning of the file. */
995 	fseek(f, 0, SEEK_SET);
996 	ret = id3_parse_v2_tag(f, tag);
997 
998 	if (ret == 0) {
999 		/* Look for ID3v2 at the end of the file. */
1000 
1001 		fseek(f, 0, SEEK_END);
1002 		pos = ftell(f);
1003 
1004 		while (pos > 128) {
1005 
1006 			/* Test for ID3v2 footer */
1007 			fseek(f, pos - 10, SEEK_SET);
1008 			if (fread(buf, 1, 10, f) != 10)
1009 				return M3G_ERR_READ;
1010 			if (memcmp(buf, "3DI", 3) == 0 &&
1011 			    buf[3] == 4 &&
1012 			    ((buf[6] | buf[7] | buf[8] | buf[9]) & 0x80) == 0) {
1013 				/* Parse ID3v2.4 tag */
1014 				k = id3_get_syncsafe_int(buf + 6);
1015 				if (20 + k < pos) {
1016 					pos -= 20 + k;
1017 					fseek(f, pos, SEEK_SET);
1018 					ret = id3_parse_v2_tag(f, tag);
1019 					break;
1020 				}
1021 			}
1022 
1023 			/* Test for ID3v1/Lyrics3v2 tag */
1024 			fseek(f, pos - 128, SEEK_SET);
1025 			if (fread(buf, 1, 3, f) != 3)
1026 				return M3G_ERR_READ;
1027 			if (memcmp(buf, "TAG", 3) == 0) {
1028 				/* Skip over ID3v1 tag and continue */
1029 				pos -= 128;
1030 				DBG(("DEBUG: Skipping ID3v1 tag at offset %lu\n", pos));
1031 				id3v1_pos = pos;
1032 				/* Test for Lyrics3v2 tag */
1033 				if (pos > 26) {
1034 					fseek(f, pos - 15, SEEK_SET);
1035 					if (fread(buf, 1, 15, f) != 15)
1036 						return M3G_ERR_READ;
1037 					if (memcmp(buf + 6, "LYRICS200", 9) == 0) {
1038 						/* Skip over Lyrics tag */
1039 						k = 0;
1040 						for (j = 0; j < 6; j++) {
1041 							if (buf[j] < '0' || buf[j] > '9') {
1042 								k = 0;
1043 								break;
1044 							}
1045 							k = 10 * k + (buf[j] - '0');
1046 						}
1047 						if (k >= 11 && k + 15 < pos) {
1048 							pos -= k + 15;
1049 							DBG(("DEBUG: Skipping Lyrics3v2 tag at offset %lu\n", pos));
1050 						}
1051 					}
1052 				}
1053 				continue;
1054 			}
1055 
1056 			/* Test for APE tag */
1057 			fseek(f, pos - 32, SEEK_SET);
1058 			if (fread(buf, 1, 32, f) != 32)
1059 				return M3G_ERR_READ;
1060 			if (memcmp(buf, "APETAGEX", 8) == 0) {
1061 				/* Skip over APE tag and continue */
1062 				k = buf[12] | (buf[13] << 8) | (buf[14] << 16) | (buf[15] << 24); /* tag length */
1063 				if (buf[23] & 0x80)
1064 					k += 32; /* tag header present */
1065 				if (k >= 32 && k < pos) {
1066 					pos -= k;
1067 					DBG(("DEBUG: Skipping APE tag at offset %lu\n", pos));
1068 					continue;
1069 				}
1070 			}
1071 
1072 			/* No more tags to skip. */
1073 			break;
1074 
1075 		}
1076 
1077 	}
1078 
1079 	if (ret == 0 && id3v1_pos != 0) {
1080 		/* Read ID3v1 at the end of the file. */
1081 		fseek(f, id3v1_pos, SEEK_SET);
1082 		ret = id3_parse_v1_tag(f, tag);
1083 	}
1084 
1085 	return ret;
1086 }
1087 
1088 
1089 /**
1090  * Seek to offset in inf and copy count bytes to the current
1091  * position in outf. If count == -1, copy until the end of the file.
1092  *
1093  * Return 1 on success, otherwise a negative error code.
1094  */
id3_copy_data(FILE * inf,FILE * outf,long offset,long count)1095 static int id3_copy_data(FILE *inf, FILE *outf, long offset, long count)
1096 {
1097 	const long bufsize = 65536;
1098 	char *buf;
1099 	size_t k;
1100 	int ret;
1101 
1102 	ret = 1;
1103 	buf = malloc(bufsize);
1104 
1105 	if (fseek(inf, offset, SEEK_SET))
1106 		ret = M3G_ERR_READ;
1107 
1108 	while (ret == 1 && count != 0) {
1109 		k = (count > 0 && count < bufsize) ? count : bufsize;
1110 		k = fread(buf, 1, k, inf);
1111 		if (k == 0) {
1112 			if (!feof(inf) || count > 0)
1113 				ret = M3G_ERR_READ;
1114 			break;
1115 		}
1116 		if (fwrite(buf, 1, k, outf) != k) {
1117 			ret = M3G_ERR_WRITE;
1118 			break;
1119 		}
1120 		if (count > 0)
1121 			count -= k;
1122 	}
1123 
1124 	free(buf);
1125 	return ret;
1126 }
1127 
1128 
1129 /**
1130  * Read gain information from an ID3v2 tag.
1131  */
ReadMP3GainID3Tag(char * filename,struct MP3GainTagInfo * info)1132 int ReadMP3GainID3Tag(char *filename, struct MP3GainTagInfo *info)
1133 {
1134 	FILE *f;
1135 	struct ID3v2TagStruct tag;
1136 	struct ID3v2FrameStruct *frame;
1137 	int ret;
1138 
1139 	f = fopen(filename, "rb");
1140 	if (f == NULL) {
1141 		passError(MP3GAIN_UNSPECIFED_ERROR, 3, "Could not open ", filename, "\n");
1142 		return M3G_ERR_FILEOPEN;
1143 	}
1144 
1145 	ret = id3_search_tag(f, &tag);
1146 	fclose(f);
1147 
1148 	if (ret == M3G_ERR_READ) {
1149 		passError(MP3GAIN_UNSPECIFED_ERROR, 3, "Error reading ", filename, "\n");
1150 	}
1151 
1152 	if (ret == 1) {
1153 		/* Got the tag; extract gain information from the RVA2/TXXX frames. */
1154 		frame = tag.frames;
1155 		while (frame) {
1156 			id3_decode_rva2_frame(frame, info);
1157 			id3_decode_txxx_frame(frame, info);
1158 			id3_decode_mp3gain_frame(frame, info);
1159 			frame = frame->next;
1160 		}
1161 		id3_release_frames(tag.frames);
1162 	}
1163 
1164 	return ret;
1165 }
1166 
1167 
1168 /**
1169  * (Re-)Write gain information to an ID3v2 tag.
1170  *
1171  * Writes or updates an ID3v2.4 tag at the beginning of the file.
1172  * If the file does not yet contain an ID3v2 tag, a new tag is created,
1173  * copying basic fields from an ID3v1 tag if present.
1174  * If the file contains an ID3v2.2 or ID3v2.3 tag, it is rewritten as ID3v2.4.
1175  *
1176  * Since modifications are made at the beginning of the file, the entire
1177  * file is rewritten to a temporary file and then moved in place of the
1178  * old file.
1179  */
WriteMP3GainID3Tag(char * filename,struct MP3GainTagInfo * info,int saveTimeStamp)1180 int WriteMP3GainID3Tag(char *filename, struct MP3GainTagInfo *info, int saveTimeStamp)
1181 {
1182 	char sbuf[32];
1183 	char *tmpfilename;
1184 	FILE *f, *outf;
1185 	struct ID3v2TagStruct tag;
1186 	struct ID3v2FrameStruct *frame, **pframe;
1187 	int ret, need_update;
1188 
1189 	if (saveTimeStamp)
1190 		fileTime(filename, storeTime);
1191 
1192 	f = fopen(filename, "rb");
1193 	if (f == NULL) {
1194 		passError(MP3GAIN_UNSPECIFED_ERROR, 3, "Could not open ", filename, "\n");
1195 		return M3G_ERR_FILEOPEN;
1196 	}
1197 	ret = id3_search_tag(f, &tag);
1198 
1199 	switch (ret) {
1200 		case M3G_ERR_READ:
1201 			passError(MP3GAIN_UNSPECIFED_ERROR, 3, "Error reading ", filename, "\n");
1202 			break;
1203 		case M3G_ERR_TAGFORMAT:
1204 			passError(MP3GAIN_UNSPECIFED_ERROR, 3, "Unsupported ID3v2 tag in ", filename, "\n");
1205 			break;
1206 	}
1207 
1208 	if (ret < 0) {
1209 		/* Error. */
1210 		fclose(f);
1211 		return ret;
1212 	}
1213 
1214 	if (ret == 0) {
1215 		/* No ID3v2 or ID3v1 tag found in the file; create a new tag. */
1216 		tag.offset = 0;
1217 		tag.length = 0;
1218 		tag.version = 0;
1219 		tag.flags = 0;
1220 		tag.frames = NULL;
1221 	}
1222 
1223 	/* Kill existing replaygain frames. */
1224 	need_update = 0;
1225 	pframe = &(tag.frames);
1226 	while ((frame = *pframe)) {
1227 		if (id3_decode_rva2_frame(frame, NULL) == 1 ||
1228 		    id3_decode_txxx_frame(frame, NULL) == 1 ||
1229 		    id3_decode_mp3gain_frame(frame, NULL) == 1) {
1230 			/* This is a ReplayGain frame; kill it. */
1231 			need_update = 1;
1232 			*pframe = frame->next;
1233 			free(frame->data);
1234 			free(frame);
1235 		} else {
1236 			pframe = &((*pframe)->next);
1237 		}
1238 	}
1239 
1240 	/* Append new replaygain frames. The TXXX versions are lower-case,
1241 	 * because that's what Winamp wants... */
1242 
1243 	if (info->haveTrackGain || info->haveTrackPeak ||
1244 	    info->haveAlbumGain || info->haveAlbumPeak) {
1245 		need_update = 1;
1246 		frame = id3_make_frame("TXXX", "bsbs", 0, "replaygain_reference_loudness", 0, "89.0 dB");
1247 		*pframe = frame;
1248 		pframe = &(frame->next);
1249 	}
1250 
1251 	if (info->haveTrackGain) {
1252 		need_update = 1;
1253 		frame = id3_make_rva2_frame(0, info->trackGain, info->haveTrackPeak, info->trackPeak);
1254 		*pframe = frame;
1255 		pframe = &(frame->next);
1256 
1257 		sprintf(sbuf, "%-+9.6f dB", info->trackGain);
1258 		frame = id3_make_frame("TXXX", "bsbs", 0, "replaygain_track_gain", 0, sbuf);
1259 		*pframe = frame;
1260 		pframe = &(frame->next);
1261 	}
1262 	if (info->haveTrackPeak) {
1263 		need_update = 1;
1264 		sprintf(sbuf, "%-8.6f", info->trackPeak);
1265 		frame = id3_make_frame("TXXX", "bsbs", 0, "replaygain_track_peak", 0, sbuf);
1266 		*pframe = frame;
1267 		pframe = &(frame->next);
1268 	}
1269 
1270 	if (info->haveAlbumGain) {
1271 		need_update = 1;
1272 		frame = id3_make_rva2_frame(1, info->albumGain, info->haveAlbumPeak, info->albumPeak);
1273 		*pframe = frame;
1274 		pframe = &(frame->next);
1275 
1276 		sprintf(sbuf, "%-+9.6f dB", info->albumGain);
1277 		frame = id3_make_frame("TXXX", "bsbs", 0, "replaygain_album_gain", 0, sbuf);
1278 		*pframe = frame;
1279 		pframe = &(frame->next);
1280 	}
1281 	if (info->haveAlbumPeak) {
1282 		need_update = 1;
1283 		sprintf(sbuf, "%-8.6f", info->albumPeak);
1284 		frame = id3_make_frame("TXXX", "bsbs", 0, "replaygain_album_peak", 0, sbuf);
1285 		*pframe = frame;
1286 		pframe = &(frame->next);
1287 	}
1288 
1289 	/* Append mp3gain-specific frames. */
1290 	if (info->haveMinMaxGain) {
1291 		need_update = 1;
1292 		sprintf(sbuf, "%03d,%03d", info->minGain, info->maxGain);
1293 		frame = id3_make_frame("TXXX", "bsbs", 0, "MP3GAIN_MINMAX", 0, sbuf);
1294 		*pframe = frame;
1295 		pframe = &(frame->next);
1296 	}
1297 	if (info->haveAlbumMinMaxGain) {
1298 		need_update = 1;
1299 		sprintf(sbuf, "%03d,%03d", info->albumMinGain, info->albumMaxGain);
1300 		frame = id3_make_frame("TXXX", "bsbs", 0, "MP3GAIN_ALBUM_MINMAX", 0, sbuf);
1301 		*pframe = frame;
1302 		pframe = &(frame->next);
1303 	}
1304 	if (info->haveUndo) {
1305 		need_update = 1;
1306 		sprintf(sbuf, "%+04d,%+04d,%c", info->undoLeft, info->undoRight, info->undoWrap ? 'W' : 'N');
1307 		frame = id3_make_frame("TXXX", "bsbs", 0, "MP3GAIN_UNDO", 0, sbuf);
1308 		*pframe = frame;
1309 		pframe = &(frame->next);
1310 	}
1311 
1312 	if (!need_update) {
1313 		/* No need to change MP3 file. */
1314 		fclose(f);
1315 		id3_release_frames(tag.frames);
1316 		return 0;
1317 	}
1318 
1319 	/* Create temporary file. */
1320 	tmpfilename = malloc(strlen(filename) + 5);
1321 	strcpy(tmpfilename, filename);
1322 	strcat(tmpfilename, ".TMP");
1323 	outf = fopen(tmpfilename, "wb");
1324 	if (outf == NULL) {
1325 		passError(MP3GAIN_UNSPECIFED_ERROR, 3, "Can not create temporary file ", tmpfilename, "\n");
1326 		fclose(f);
1327 		free(tmpfilename);
1328 		id3_release_frames(tag.frames);
1329 		return M3G_ERR_CANT_MAKE_TMP;
1330 	}
1331 
1332 	/* Write new ID3v2 tag. */
1333 	ret = id3_write_tag(outf, &tag);
1334 
1335 	/* Write rest of MP3 file. */
1336 	if (ret >= 0) {
1337 		if (tag.version == 0) {
1338 			/* The original file has no ID3v2 tag; copy everything. */
1339 			ret = id3_copy_data(f, outf, 0, -1);
1340 		} else {
1341 			/* The original file has an ID3v2 tag; copy everything
1342 			   except the original tag. */
1343 			ret = id3_copy_data(f, outf, 0, tag.offset);
1344 			if (ret >= 0)
1345 				ret = id3_copy_data(f, outf, tag.offset + tag.length, -1);
1346 		}
1347 	}
1348 
1349 	fclose(outf);
1350 	fclose(f);
1351 	id3_release_frames(tag.frames);
1352 
1353 	switch (ret) {
1354 		case M3G_ERR_READ:
1355 			passError(MP3GAIN_UNSPECIFED_ERROR, 3, "Error reading ", filename, "\n");
1356 			break;
1357 		case M3G_ERR_WRITE:
1358 			passError(MP3GAIN_UNSPECIFED_ERROR, 3, "Error writing ", tmpfilename, "\n");
1359 			break;
1360 	}
1361 
1362 	if (ret < 0) {
1363 		/* Delete temp file after error. */
1364 		remove(tmpfilename);
1365 		free(tmpfilename);
1366 		return ret;
1367 	}
1368 
1369 	/* Replace original file. */
1370 #ifdef WIN32
1371 	/* "rename" function in WIN32 does _not_ replace existing destination file, so
1372 	   we have to manually remove it first */
1373 	if (remove(filename) != 0) {
1374 		passError(MP3GAIN_UNSPECIFED_ERROR, 5, "Can not rename ", tmpfilename, " to ", filename, "\n");
1375 		ret = M3G_ERR_RENAME_TMP;
1376 		/* Do NOT remove the temp file itself, just in case the "remove(filename)" function
1377 		   only _temporarily_ failed, and the original file will disappear soon, such as when
1378 		   all handles on the file are closed. If it does disappear and we also
1379 		   delete the tmp file, then the file is completely gone... */
1380 		free(tmpfilename);
1381 	}
1382 #endif
1383 
1384 	ret = 1;
1385 	if (rename(tmpfilename, filename)) {
1386 		remove(tmpfilename);
1387 		passError(MP3GAIN_UNSPECIFED_ERROR, 5, "Can not rename ", tmpfilename, " to ", filename, "\n");
1388 		ret = M3G_ERR_RENAME_TMP;
1389 	} else {
1390 		if (saveTimeStamp)
1391 			fileTime(filename, setStoredTime);
1392 	}
1393 
1394 	free(tmpfilename);
1395 
1396 	return ret;
1397 }
1398 
1399 
1400 /**
1401  * Remove gain information from the ID3v2 tag.
1402  * Return 1 on success, 0 if no changes are needed, or a negative error code.
1403  */
RemoveMP3GainID3Tag(char * filename,int saveTimeStamp)1404 int RemoveMP3GainID3Tag(char *filename, int saveTimeStamp)
1405 {
1406 	struct MP3GainTagInfo info;
1407 
1408 	info.haveAlbumGain = 0;
1409 	info.haveAlbumPeak = 0;
1410 	info.haveTrackGain = 0;
1411 	info.haveTrackPeak = 0;
1412 	info.haveMinMaxGain = 0;
1413 	info.haveAlbumMinMaxGain = 0;
1414 	info.haveUndo = 0;
1415 
1416 	return WriteMP3GainID3Tag(filename, &info, saveTimeStamp);
1417 }
1418 
1419