1/* flac - Command-line FLAC encoder/decoder
2 * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007  Josh Coalson
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17 */
18
19#if HAVE_CONFIG_H
20#  include <config.h>
21#endif
22
23#if defined _MSC_VER || defined __MINGW32__
24#include <sys/types.h> /* for off_t */
25#if _MSC_VER <= 1600 /* @@@ [2G limit] */
26#define fseeko fseek
27#define ftello ftell
28#endif
29#endif
30#include <stdio.h> /* for FILE etc. */
31#include <stdlib.h> /* for calloc() etc. */
32#include <string.h> /* for memcmp() etc. */
33#include "FLAC/assert.h"
34#include "FLAC/metadata.h"
35#include "share/alloc.h"
36#include "foreign_metadata.h"
37
38#ifdef min
39#undef min
40#endif
41#define min(x,y) ((x)<(y)?(x):(y))
42
43
44static const char *FLAC__FOREIGN_METADATA_APPLICATION_ID[2] = { "aiff" , "riff" };
45
46static FLAC__uint32 unpack32be_(const FLAC__byte *b)
47{
48	return ((FLAC__uint32)b[0]<<24) + ((FLAC__uint32)b[1]<<16) + ((FLAC__uint32)b[2]<<8) + (FLAC__uint32)b[3];
49}
50
51static FLAC__uint32 unpack32le_(const FLAC__byte *b)
52{
53	return (FLAC__uint32)b[0] + ((FLAC__uint32)b[1]<<8) + ((FLAC__uint32)b[2]<<16) + ((FLAC__uint32)b[3]<<24);
54}
55
56static FLAC__bool copy_data_(FILE *fin, FILE *fout, size_t size, const char **error, const char * const read_error, const char * const write_error)
57{
58	static FLAC__byte buffer[4096];
59	size_t left;
60	for(left = size; left > 0; ) {
61		size_t need = min(sizeof(buffer), left);
62		if(fread(buffer, 1, need, fin) < need) {
63			if(error) *error = read_error;
64			return false;
65		}
66		if(fwrite(buffer, 1, need, fout) < need) {
67			if(error) *error = write_error;
68			return false;
69		}
70		left -= need;
71	}
72	return true;
73}
74
75static FLAC__bool append_block_(foreign_metadata_t *fm, off_t offset, FLAC__uint32 size, const char **error)
76{
77	foreign_block_t *fb = safe_realloc_muladd2_(fm->blocks, sizeof(foreign_block_t), /*times (*/fm->num_blocks, /*+*/1/*)*/);
78	if(fb) {
79		fb[fm->num_blocks].offset = offset;
80		fb[fm->num_blocks].size = size;
81		fm->num_blocks++;
82		fm->blocks = fb;
83		return true;
84	}
85	if(error) *error = "out of memory";
86	return false;
87}
88
89static FLAC__bool read_from_aiff_(foreign_metadata_t *fm, FILE *f, const char **error)
90{
91	FLAC__byte buffer[12];
92	off_t offset, eof_offset;
93	if((offset = ftello(f)) < 0) {
94		if(error) *error = "ftello() error (001)";
95		return false;
96	}
97	if(fread(buffer, 1, 12, f) < 12 || memcmp(buffer, "FORM", 4) || (memcmp(buffer+8, "AIFF", 4) && memcmp(buffer+8, "AIFC", 4))) {
98		if(error) *error = "unsupported FORM layout (002)";
99		return false;
100	}
101	if(!append_block_(fm, offset, 12, error))
102		return false;
103	eof_offset = 8 + unpack32be_(buffer+4);
104	while(!feof(f)) {
105		FLAC__uint32 size;
106		if((offset = ftello(f)) < 0) {
107			if(error) *error = "ftello() error (003)";
108			return false;
109		}
110		if((size = fread(buffer, 1, 8, f)) < 8) {
111			if(size == 0 && feof(f))
112				break;
113			if(error) *error = "invalid AIFF file (004)";
114			return false;
115		}
116		size = unpack32be_(buffer+4);
117		/* check if pad byte needed */
118		if(size & 1)
119			size++;
120		if(!memcmp(buffer, "COMM", 4)) {
121			if(fm->format_block) {
122				if(error) *error = "invalid AIFF file: multiple \"COMM\" chunks (005)";
123				return false;
124			}
125			if(fm->audio_block) {
126				if(error) *error = "invalid AIFF file: \"SSND\" chunk before \"COMM\" chunk (006)";
127				return false;
128			}
129			fm->format_block = fm->num_blocks;
130		}
131		else if(!memcmp(buffer, "SSND", 4)) {
132			if(fm->audio_block) {
133				if(error) *error = "invalid AIFF file: multiple \"SSND\" chunks (007)";
134				return false;
135			}
136			if(!fm->format_block) {
137				if(error) *error = "invalid AIFF file: \"SSND\" chunk before \"COMM\" chunk (008)";
138				return false;
139			}
140			fm->audio_block = fm->num_blocks;
141			/* read #offset bytes */
142			if(fread(buffer+8, 1, 4, f) < 4) {
143				if(error) *error = "invalid AIFF file (009)";
144				return false;
145			}
146			fm->ssnd_offset_size = unpack32be_(buffer+8);
147			if(fseeko(f, -4, SEEK_CUR) < 0) {
148				if(error) *error = "invalid AIFF file: seek error (010)";
149				return false;
150			}
151		}
152		if(!append_block_(fm, offset, 8 + (memcmp(buffer, "SSND", 4)? size : 8 + fm->ssnd_offset_size), error))
153			return false;
154		if(fseeko(f, size, SEEK_CUR) < 0) {
155			if(error) *error = "invalid AIFF file: seek error (011)";
156			return false;
157		}
158	}
159	if(eof_offset != ftello(f)) {
160		if(error) *error = "invalid AIFF file: unexpected EOF (012)";
161		return false;
162	}
163	if(!fm->format_block) {
164		if(error) *error = "invalid AIFF file: missing \"COMM\" chunk (013)";
165		return false;
166	}
167	if(!fm->audio_block) {
168		if(error) *error = "invalid AIFF file: missing \"SSND\" chunk (014)";
169		return false;
170	}
171	return true;
172}
173
174static FLAC__bool read_from_wave_(foreign_metadata_t *fm, FILE *f, const char **error)
175{
176	FLAC__byte buffer[12];
177	off_t offset, eof_offset;
178	if((offset = ftello(f)) < 0) {
179		if(error) *error = "ftello() error (001)";
180		return false;
181	}
182	if(fread(buffer, 1, 12, f) < 12 || memcmp(buffer, "RIFF", 4) || memcmp(buffer+8, "WAVE", 4)) {
183		if(error) *error = "unsupported RIFF layout (002)";
184		return false;
185	}
186	if(!append_block_(fm, offset, 12, error))
187		return false;
188	eof_offset = 8 + unpack32le_(buffer+4);
189	while(!feof(f)) {
190		FLAC__uint32 size;
191		if((offset = ftello(f)) < 0) {
192			if(error) *error = "ftello() error (003)";
193			return false;
194		}
195		if((size = fread(buffer, 1, 8, f)) < 8) {
196			if(size == 0 && feof(f))
197				break;
198			if(error) *error = "invalid WAVE file (004)";
199			return false;
200		}
201		size = unpack32le_(buffer+4);
202		/* check if pad byte needed */
203		if(size & 1)
204			size++;
205		if(!memcmp(buffer, "fmt ", 4)) {
206			if(fm->format_block) {
207				if(error) *error = "invalid WAVE file: multiple \"fmt \" chunks (005)";
208				return false;
209			}
210			if(fm->audio_block) {
211				if(error) *error = "invalid WAVE file: \"data\" chunk before \"fmt \" chunk (006)";
212				return false;
213			}
214			fm->format_block = fm->num_blocks;
215		}
216		else if(!memcmp(buffer, "data", 4)) {
217			if(fm->audio_block) {
218				if(error) *error = "invalid WAVE file: multiple \"data\" chunks (007)";
219				return false;
220			}
221			if(!fm->format_block) {
222				if(error) *error = "invalid WAVE file: \"data\" chunk before \"fmt \" chunk (008)";
223				return false;
224			}
225			fm->audio_block = fm->num_blocks;
226		}
227		if(!append_block_(fm, offset, 8 + (memcmp(buffer, "data", 4)? size : 0), error))
228			return false;
229		if(fseeko(f, size, SEEK_CUR) < 0) {
230			if(error) *error = "invalid WAVE file: seek error (009)";
231			return false;
232		}
233	}
234	if(eof_offset != ftello(f)) {
235		if(error) *error = "invalid WAVE file: unexpected EOF (010)";
236		return false;
237	}
238	if(!fm->format_block) {
239		if(error) *error = "invalid WAVE file: missing \"fmt \" chunk (011)";
240		return false;
241	}
242	if(!fm->audio_block) {
243		if(error) *error = "invalid WAVE file: missing \"data\" chunk (012)";
244		return false;
245	}
246	return true;
247}
248
249static FLAC__bool write_to_flac_(foreign_metadata_t *fm, FILE *fin, FILE *fout, FLAC__Metadata_SimpleIterator *it, const char **error)
250{
251	FLAC__byte buffer[4];
252	const unsigned ID_LEN = FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8;
253	size_t block_num = 0;
254	FLAC__ASSERT(sizeof(buffer) >= ID_LEN);
255	while(block_num < fm->num_blocks) {
256		/* find next matching padding block */
257		do {
258			/* even on the first chunk's loop there will be a skippable STREAMINFO block, on subsequent loops we are first moving past the PADDING we just used */
259			if(!FLAC__metadata_simple_iterator_next(it)) {
260				if(error) *error = "no matching PADDING block found (004)";
261				return false;
262			}
263		} while(FLAC__metadata_simple_iterator_get_block_type(it) != FLAC__METADATA_TYPE_PADDING);
264		if(FLAC__metadata_simple_iterator_get_block_length(it) != ID_LEN+fm->blocks[block_num].size) {
265			if(error) *error = "PADDING block with wrong size found (005)";
266			return false;
267		}
268		/* transfer chunk into APPLICATION block */
269		/* first set up the file pointers */
270		if(fseeko(fin, fm->blocks[block_num].offset, SEEK_SET) < 0) {
271			if(error) *error = "seek failed in WAVE/AIFF file (006)";
272			return false;
273		}
274		if(fseeko(fout, FLAC__metadata_simple_iterator_get_block_offset(it), SEEK_SET) < 0) {
275			if(error) *error = "seek failed in FLAC file (007)";
276			return false;
277		}
278		/* update the type */
279		buffer[0] = FLAC__METADATA_TYPE_APPLICATION;
280		if(FLAC__metadata_simple_iterator_is_last(it))
281			buffer[0] |= 0x80; /*MAGIC number*/
282		if(fwrite(buffer, 1, 1, fout) < 1) {
283			if(error) *error = "write failed in FLAC file (008)";
284			return false;
285		}
286		/* length stays the same so skip over it */
287		if(fseeko(fout, FLAC__STREAM_METADATA_LENGTH_LEN/8, SEEK_CUR) < 0) {
288			if(error) *error = "seek failed in FLAC file (009)";
289			return false;
290		}
291		/* write the APPLICATION ID */
292		memcpy(buffer, FLAC__FOREIGN_METADATA_APPLICATION_ID[fm->type], ID_LEN);
293		if(fwrite(buffer, 1, ID_LEN, fout) < ID_LEN) {
294			if(error) *error = "write failed in FLAC file (010)";
295			return false;
296		}
297		/* transfer the foreign metadata */
298		if(!copy_data_(fin, fout, fm->blocks[block_num].size, error, "read failed in WAVE/AIFF file (011)", "write failed in FLAC file (012)"))
299			return false;
300		block_num++;
301	}
302	return true;
303}
304
305static FLAC__bool read_from_flac_(foreign_metadata_t *fm, FILE *f, FLAC__Metadata_SimpleIterator *it, const char **error)
306{
307	FLAC__byte id[4], buffer[12];
308	off_t offset;
309	FLAC__bool type_found = false;
310
311	FLAC__ASSERT(FLAC__STREAM_METADATA_APPLICATION_ID_LEN == sizeof(id)*8);
312
313	while(FLAC__metadata_simple_iterator_next(it)) {
314		if(FLAC__metadata_simple_iterator_get_block_type(it) != FLAC__METADATA_TYPE_APPLICATION)
315			continue;
316		if(!FLAC__metadata_simple_iterator_get_application_id(it, id)) {
317			if(error) *error = "FLAC__metadata_simple_iterator_get_application_id() error (003)";
318			return false;
319		}
320		if(memcmp(id, FLAC__FOREIGN_METADATA_APPLICATION_ID[fm->type], sizeof(id)))
321			continue;
322		offset = FLAC__metadata_simple_iterator_get_block_offset(it);
323		/* skip over header and app ID */
324		offset += (FLAC__STREAM_METADATA_IS_LAST_LEN + FLAC__STREAM_METADATA_TYPE_LEN + FLAC__STREAM_METADATA_LENGTH_LEN) / 8;
325		offset += sizeof(id);
326		/* look for format or audio blocks */
327		if(fseek(f, offset, SEEK_SET) < 0) {
328			if(error) *error = "seek error (004)";
329			return false;
330		}
331		if(fread(buffer, 1, 4, f) != 4) {
332			if(error) *error = "read error (005)";
333			return false;
334		}
335		if(fm->num_blocks == 0) {
336			if(fm->type == FOREIGN_BLOCK_TYPE__RIFF && 0 == memcmp(buffer, "RIFF", 4))
337				type_found = true;
338			else if(fm->type == FOREIGN_BLOCK_TYPE__AIFF && 0 == memcmp(buffer, "FORM", 4))
339				type_found = true;
340			else {
341				if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (005)";
342				return false;
343			}
344		}
345		else if(!type_found) {
346			FLAC__ASSERT(0);
347			/* double protection: */
348			if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (006)";
349			return false;
350		}
351		else if(fm->type == FOREIGN_BLOCK_TYPE__RIFF) {
352			if(!memcmp(buffer, "fmt ", 4)) {
353				if(fm->format_block) {
354					if(error) *error = "invalid WAVE metadata: multiple \"fmt \" chunks (007)";
355					return false;
356				}
357				if(fm->audio_block) {
358					if(error) *error = "invalid WAVE metadata: \"data\" chunk before \"fmt \" chunk (008)";
359					return false;
360				}
361				fm->format_block = fm->num_blocks;
362			}
363			else if(!memcmp(buffer, "data", 4)) {
364				if(fm->audio_block) {
365					if(error) *error = "invalid WAVE metadata: multiple \"data\" chunks (009)";
366					return false;
367				}
368				if(!fm->format_block) {
369					if(error) *error = "invalid WAVE metadata: \"data\" chunk before \"fmt \" chunk (010)";
370					return false;
371				}
372				fm->audio_block = fm->num_blocks;
373			}
374		}
375		else if(fm->type == FOREIGN_BLOCK_TYPE__AIFF) {
376			if(!memcmp(buffer, "COMM", 4)) {
377				if(fm->format_block) {
378					if(error) *error = "invalid AIFF metadata: multiple \"COMM\" chunks (011)";
379					return false;
380				}
381				if(fm->audio_block) {
382					if(error) *error = "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (012)";
383					return false;
384				}
385				fm->format_block = fm->num_blocks;
386			}
387			else if(!memcmp(buffer, "SSND", 4)) {
388				if(fm->audio_block) {
389					if(error) *error = "invalid AIFF metadata: multiple \"SSND\" chunks (013)";
390					return false;
391				}
392				if(!fm->format_block) {
393					if(error) *error = "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (014)";
394					return false;
395				}
396				fm->audio_block = fm->num_blocks;
397				/* read SSND offset size */
398				if(fread(buffer+4, 1, 8, f) != 8) {
399					if(error) *error = "read error (015)";
400					return false;
401				}
402				fm->ssnd_offset_size = unpack32be_(buffer+8);
403			}
404		}
405		else {
406			FLAC__ASSERT(0);
407			/* double protection: */
408			if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (016)";
409			return false;
410		}
411		if(!append_block_(fm, offset, FLAC__metadata_simple_iterator_get_block_length(it)-sizeof(id), error))
412			return false;
413	}
414	if(!type_found) {
415		if(error) *error = "no foreign metadata found (017)";
416		return false;
417	}
418	if(!fm->format_block) {
419		if(error) *error = fm->type==FOREIGN_BLOCK_TYPE__RIFF? "invalid WAVE file: missing \"fmt \" chunk (018)" : "invalid AIFF file: missing \"COMM\" chunk (018)";
420		return false;
421	}
422	if(!fm->audio_block) {
423		if(error) *error = fm->type==FOREIGN_BLOCK_TYPE__RIFF? "invalid WAVE file: missing \"data\" chunk (019)" : "invalid AIFF file: missing \"SSND\" chunk (019)";
424		return false;
425	}
426	return true;
427}
428
429static FLAC__bool write_to_iff_(foreign_metadata_t *fm, FILE *fin, FILE *fout, off_t offset1, off_t offset2, off_t offset3, const char **error)
430{
431	size_t i;
432	if(fseeko(fout, offset1, SEEK_SET) < 0) {
433		if(error) *error = "seek failed in WAVE/AIFF file (002)";
434		return false;
435	}
436	for(i = 1; i < fm->format_block; i++) {
437		if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) {
438			if(error) *error = "seek failed in FLAC file (003)";
439			return false;
440		}
441		if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in WAVE/AIFF file (004)", "write failed in FLAC file (005)"))
442			return false;
443	}
444	if(fseeko(fout, offset2, SEEK_SET) < 0) {
445		if(error) *error = "seek failed in WAVE/AIFF file (006)";
446		return false;
447	}
448	for(i = fm->format_block+1; i < fm->audio_block; i++) {
449		if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) {
450			if(error) *error = "seek failed in FLAC file (007)";
451			return false;
452		}
453		if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in WAVE/AIFF file (008)", "write failed in FLAC file (009)"))
454			return false;
455	}
456	if(fseeko(fout, offset3, SEEK_SET) < 0) {
457		if(error) *error = "seek failed in WAVE/AIFF file (010)";
458		return false;
459	}
460	for(i = fm->audio_block+1; i < fm->num_blocks; i++) {
461		if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) {
462			if(error) *error = "seek failed in FLAC file (011)";
463			return false;
464		}
465		if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in WAVE/AIFF file (012)", "write failed in FLAC file (013)"))
466			return false;
467	}
468	return true;
469}
470
471foreign_metadata_t *flac__foreign_metadata_new(foreign_block_type_t type)
472{
473	foreign_metadata_t *x = (foreign_metadata_t*)calloc(sizeof(foreign_metadata_t), 1);
474	if(x)
475		x->type = type;
476	return x;
477}
478
479void flac__foreign_metadata_delete(foreign_metadata_t *fm)
480{
481	if(fm) {
482		if(fm->blocks)
483			free(fm->blocks);
484		free(fm);
485	}
486}
487
488FLAC__bool flac__foreign_metadata_read_from_aiff(foreign_metadata_t *fm, const char *filename, const char **error)
489{
490	FLAC__bool ok;
491	FILE *f = fopen(filename, "rb");
492	if(!f) {
493		if(error) *error = "can't open AIFF file for reading (000)";
494		return false;
495	}
496	ok = read_from_aiff_(fm, f, error);
497	fclose(f);
498	return ok;
499}
500
501FLAC__bool flac__foreign_metadata_read_from_wave(foreign_metadata_t *fm, const char *filename, const char **error)
502{
503	FLAC__bool ok;
504	FILE *f = fopen(filename, "rb");
505	if(!f) {
506		if(error) *error = "can't open WAVE file for reading (000)";
507		return false;
508	}
509	ok = read_from_wave_(fm, f, error);
510	fclose(f);
511	return ok;
512}
513
514FLAC__bool flac__foreign_metadata_write_to_flac(foreign_metadata_t *fm, const char *infilename, const char *outfilename, const char **error)
515{
516	FLAC__bool ok;
517	FILE *fin, *fout;
518	FLAC__Metadata_SimpleIterator *it = FLAC__metadata_simple_iterator_new();
519	if(!it) {
520		if(error) *error = "out of memory (000)";
521		return false;
522	}
523	if(!FLAC__metadata_simple_iterator_init(it, outfilename, /*read_only=*/true, /*preserve_file_stats=*/false)) {
524		if(error) *error = "can't initialize iterator (001)";
525		FLAC__metadata_simple_iterator_delete(it);
526		return false;
527	}
528	if(0 == (fin = fopen(infilename, "rb"))) {
529		if(error) *error = "can't open WAVE/AIFF file for reading (002)";
530		FLAC__metadata_simple_iterator_delete(it);
531		return false;
532	}
533	if(0 == (fout = fopen(outfilename, "r+b"))) {
534		if(error) *error = "can't open FLAC file for updating (003)";
535		FLAC__metadata_simple_iterator_delete(it);
536		fclose(fin);
537		return false;
538	}
539	ok = write_to_flac_(fm, fin, fout, it, error);
540	FLAC__metadata_simple_iterator_delete(it);
541	fclose(fin);
542	fclose(fout);
543	return ok;
544}
545
546FLAC__bool flac__foreign_metadata_read_from_flac(foreign_metadata_t *fm, const char *filename, const char **error)
547{
548	FLAC__bool ok;
549	FILE *f;
550	FLAC__Metadata_SimpleIterator *it = FLAC__metadata_simple_iterator_new();
551	if(!it) {
552		if(error) *error = "out of memory (000)";
553		return false;
554	}
555	if(!FLAC__metadata_simple_iterator_init(it, filename, /*read_only=*/true, /*preserve_file_stats=*/false)) {
556		if(error) *error = "can't initialize iterator (001)";
557		FLAC__metadata_simple_iterator_delete(it);
558		return false;
559	}
560	if(0 == (f = fopen(filename, "rb"))) {
561		if(error) *error = "can't open FLAC file for reading (002)";
562		FLAC__metadata_simple_iterator_delete(it);
563		return false;
564	}
565	ok = read_from_flac_(fm, f, it, error);
566	FLAC__metadata_simple_iterator_delete(it);
567	fclose(f);
568	return ok;
569}
570
571FLAC__bool flac__foreign_metadata_write_to_iff(foreign_metadata_t *fm, const char *infilename, const char *outfilename, off_t offset1, off_t offset2, off_t offset3, const char **error)
572{
573	FLAC__bool ok;
574	FILE *fin, *fout;
575	if(0 == (fin = fopen(infilename, "rb"))) {
576		if(error) *error = "can't open FLAC file for reading (000)";
577		return false;
578	}
579	if(0 == (fout = fopen(outfilename, "r+b"))) {
580		if(error) *error = "can't open WAVE/AIFF file for updating (001)";
581		fclose(fin);
582		return false;
583	}
584	ok = write_to_iff_(fm, fin, fout, offset1, offset2, offset3, error);
585	fclose(fin);
586	fclose(fout);
587	return ok;
588}
589