• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* flac - Command-line FLAC encoder/decoder
2  * Copyright (C) 2000-2009  Josh Coalson
3  * Copyright (C) 2011-2022  Xiph.Org Foundation
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #  include <config.h>
22 #endif
23 
24 #include <stdio.h> /* for FILE etc. */
25 #include <stdlib.h> /* for calloc() etc. */
26 #include <string.h> /* for memcmp() etc. */
27 #include "FLAC/assert.h"
28 #include "FLAC/metadata.h"
29 #include "share/alloc.h"
30 #include "share/compat.h"
31 #include "foreign_metadata.h"
32 
33 #ifdef min
34 #undef min
35 #endif
36 #define min(x,y) ((x)<(y)?(x):(y))
37 
38 const char *FLAC__FOREIGN_METADATA_APPLICATION_ID[FLAC__FOREIGN_METADATA_NUMBER_OF_RECOGNIZED_APPLICATION_IDS] = { "aiff" , "riff", "w64 " };
39 
unpack32be_(const FLAC__byte * b)40 static FLAC__uint32 unpack32be_(const FLAC__byte *b)
41 {
42 	return ((FLAC__uint32)b[0]<<24) + ((FLAC__uint32)b[1]<<16) + ((FLAC__uint32)b[2]<<8) + (FLAC__uint32)b[3];
43 }
44 
unpack32le_(const FLAC__byte * b)45 static FLAC__uint32 unpack32le_(const FLAC__byte *b)
46 {
47 	return (FLAC__uint32)b[0] + ((FLAC__uint32)b[1]<<8) + ((FLAC__uint32)b[2]<<16) + ((FLAC__uint32)b[3]<<24);
48 }
49 
unpack64le_(const FLAC__byte * b)50 static FLAC__uint64 unpack64le_(const FLAC__byte *b)
51 {
52 	return (FLAC__uint64)b[0] + ((FLAC__uint64)b[1]<<8) + ((FLAC__uint64)b[2]<<16) + ((FLAC__uint64)b[3]<<24) + ((FLAC__uint64)b[4]<<32) + ((FLAC__uint64)b[5]<<40) + ((FLAC__uint64)b[6]<<48) + ((FLAC__uint64)b[7]<<56);
53 }
54 
55 /* copies 'size' bytes from file 'fin' to 'fout', filling in *error with 'read_error' or 'write_error' as necessary */
copy_data_(FILE * fin,FILE * fout,size_t size,const char ** error,const char * const read_error,const char * const write_error)56 static 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 	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 
75 /* compare 'size' bytes from file 'fin' to 'fout', filling in *error with 'read_error' or 'write_error' as necessary */
compare_data_(FILE * fin,FILE * fout,size_t size,const char ** error,const char * const read_error,const char * const write_error,const char * const compare_error)76 static FLAC__bool compare_data_(FILE *fin, FILE *fout, size_t size, const char **error, const char * const read_error, const char * const write_error, const char * const compare_error)
77 {
78 	FLAC__byte buffer_in[4096];
79 	FLAC__byte buffer_out[4096]; /* sizes need to be the same */
80 	size_t left;
81 	for(left = size; left > 0; ) {
82 		size_t need = min(sizeof(buffer_in), left);
83 		if(fread(buffer_in, 1, need, fin) < need) {
84 			if(error) *error = read_error;
85 			return false;
86 		}
87 		if(fread(buffer_out, 1, need, fout) < need) {
88 			if(error) *error = write_error;
89 			return false;
90 		}
91 		if(memcmp(buffer_in, buffer_out, need)) {
92 			if(error) *error = compare_error;
93 			return false;
94 		}
95 		left -= need;
96 	}
97 	return true;
98 }
99 
append_block_(foreign_metadata_t * fm,FLAC__off_t offset,FLAC__uint32 size,const char ** error)100 static FLAC__bool append_block_(foreign_metadata_t *fm, FLAC__off_t offset, FLAC__uint32 size, const char **error)
101 {
102 	foreign_block_t *fb = safe_realloc_nofree_muladd2_(fm->blocks, sizeof(foreign_block_t), /*times (*/fm->num_blocks, /*+*/1/*)*/);
103 	if(fb) {
104 		fb[fm->num_blocks].offset = offset;
105 		fb[fm->num_blocks].size = size;
106 		fm->num_blocks++;
107 		fm->blocks = fb;
108 		return true;
109 	}
110 	if(error) *error = "out of memory";
111 	return false;
112 }
113 
read_from_aiff_(foreign_metadata_t * fm,FILE * f,const char ** error)114 static FLAC__bool read_from_aiff_(foreign_metadata_t *fm, FILE *f, const char **error)
115 {
116 	FLAC__byte buffer[12];
117 	FLAC__off_t offset, eof_offset;
118 	if((offset = ftello(f)) < 0) {
119 		if(error) *error = "ftello() error (001)";
120 		return false;
121 	}
122 	if(fread(buffer, 1, 12, f) < 12 || memcmp(buffer, "FORM", 4) || (memcmp(buffer+8, "AIFF", 4) && memcmp(buffer+8, "AIFC", 4))) {
123 		if(error) *error = "unsupported FORM layout (002)";
124 		return false;
125 	}
126 	if(!append_block_(fm, offset, 12, error))
127 		return false;
128 	eof_offset = (FLAC__off_t)8 + (FLAC__off_t)unpack32be_(buffer+4);
129 	while(!feof(f)) {
130 		FLAC__uint32 size;
131 		if((offset = ftello(f)) < 0) {
132 			if(error) *error = "ftello() error (003)";
133 			return false;
134 		}
135 		if((size = fread(buffer, 1, 8, f)) < 8) {
136 			if(size == 0 && feof(f))
137 				break;
138 			if(error) *error = "invalid AIFF file (004)";
139 			return false;
140 		}
141 		size = unpack32be_(buffer+4);
142 		/* check if pad byte needed */
143 		if(size & 1)
144 			size++;
145 		if(!memcmp(buffer, "COMM", 4)) {
146 			if(fm->format_block) {
147 				if(error) *error = "invalid AIFF file: multiple \"COMM\" chunks (005)";
148 				return false;
149 			}
150 			if(fm->audio_block) {
151 				if(error) *error = "invalid AIFF file: \"SSND\" chunk before \"COMM\" chunk (006)";
152 				return false;
153 			}
154 			fm->format_block = fm->num_blocks;
155 		}
156 		else if(!memcmp(buffer, "SSND", 4)) {
157 			if(fm->audio_block) {
158 				if(error) *error = "invalid AIFF file: multiple \"SSND\" chunks (007)";
159 				return false;
160 			}
161 			if(!fm->format_block) {
162 				if(error) *error = "invalid AIFF file: \"SSND\" chunk before \"COMM\" chunk (008)";
163 				return false;
164 			}
165 			fm->audio_block = fm->num_blocks;
166 			/* read #offset bytes */
167 			if(fread(buffer+8, 1, 4, f) < 4) {
168 				if(error) *error = "invalid AIFF file (009)";
169 				return false;
170 			}
171 			fm->ssnd_offset_size = unpack32be_(buffer+8);
172 			if(fseeko(f, -4, SEEK_CUR) < 0) {
173 				if(error) *error = "invalid AIFF file: seek error (010)";
174 				return false;
175 			}
176 			/* WATCHOUT: For SSND we ignore the blockSize and are not saving any
177 			 * unaligned part at the end of the chunk.  In retrospect it is pretty
178 			 * pointless to save the unaligned data before the PCM but now it is
179 			 * done and cast in stone.
180 			 */
181 		}
182 		if(!append_block_(fm, offset, 8 + (memcmp(buffer, "SSND", 4)? size : 8 + fm->ssnd_offset_size), error))
183 			return false;
184 		/* skip to next chunk */
185 		if(fseeko(f, size, SEEK_CUR) < 0) {
186 			if(error) *error = "invalid AIFF file: seek error (011)";
187 			return false;
188 		}
189 	}
190 	if(eof_offset != ftello(f)) {
191 		if(error) *error = "invalid AIFF file: unexpected EOF (012)";
192 		return false;
193 	}
194 	if(!fm->format_block) {
195 		if(error) *error = "invalid AIFF file: missing \"COMM\" chunk (013)";
196 		return false;
197 	}
198 	if(!fm->audio_block) {
199 		if(error) *error = "invalid AIFF file: missing \"SSND\" chunk (014)";
200 		return false;
201 	}
202 	return true;
203 }
204 
read_from_wave_(foreign_metadata_t * fm,FILE * f,const char ** error)205 static FLAC__bool read_from_wave_(foreign_metadata_t *fm, FILE *f, const char **error)
206 {
207 	FLAC__byte buffer[12];
208 	FLAC__off_t offset, eof_offset = -1, ds64_data_size = -1;
209 	if((offset = ftello(f)) < 0) {
210 		if(error) *error = "ftello() error (001)";
211 		return false;
212 	}
213 	if(fread(buffer, 1, 12, f) < 12 || (memcmp(buffer, "RIFF", 4) && memcmp(buffer, "RF64", 4)) || memcmp(buffer+8, "WAVE", 4)) {
214 		if(error) *error = "unsupported RIFF layout (002)";
215 		return false;
216 	}
217 	if(!memcmp(buffer, "RF64", 4))
218 		fm->is_rf64 = true;
219 	if(fm->is_rf64 && sizeof(FLAC__off_t) < 8) {
220 		if(error) *error = "RF64 is not supported on this compile (r00)";
221 		return false;
222 	}
223 	if(!append_block_(fm, offset, 12, error))
224 		return false;
225 	if(!fm->is_rf64 || unpack32le_(buffer+4) != 0xffffffff) {
226 		eof_offset = (FLAC__off_t)8 + (FLAC__off_t)unpack32le_(buffer+4);
227 		if(eof_offset & 1) /* fix odd RIFF size */
228 			eof_offset++;
229 	}
230 	while(!feof(f)) {
231 		FLAC__off_t size;
232 		if((offset = ftello(f)) < 0) {
233 			if(error) *error = "ftello() error (003)";
234 			return false;
235 		}
236 		if((size = fread(buffer, 1, 8, f)) < 8) {
237 			if(size == 0 && feof(f))
238 				break;
239 			if(error) *error = "invalid WAVE file (004)";
240 			return false;
241 		}
242 		size = unpack32le_(buffer+4);
243 		/* check if pad byte needed */
244 		if(size & 1)
245 			size++;
246 		if(!memcmp(buffer, "fmt ", 4)) {
247 			if(fm->format_block) {
248 				if(error) *error = "invalid WAVE file: multiple \"fmt \" chunks (005)";
249 				return false;
250 			}
251 			if(fm->audio_block) {
252 				if(error) *error = "invalid WAVE file: \"data\" chunk before \"fmt \" chunk (006)";
253 				return false;
254 			}
255 			fm->format_block = fm->num_blocks;
256 		}
257 		else if(!memcmp(buffer, "data", 4)) {
258 			if(fm->audio_block) {
259 				if(error) *error = "invalid WAVE file: multiple \"data\" chunks (007)";
260 				return false;
261 			}
262 			if(!fm->format_block) {
263 				if(error) *error = "invalid WAVE file: \"data\" chunk before \"fmt \" chunk (008)";
264 				return false;
265 			}
266 			fm->audio_block = fm->num_blocks;
267 			if(fm->is_rf64 && fm->num_blocks < 2) {
268 				if(error) *error = "invalid RF64 file: \"data\" chunk before \"ds64\" chunk (r01)";
269 				return false;
270 			}
271 		}
272 		if(!append_block_(fm, offset, 8 + (memcmp(buffer, "data", 4)? size : 0), error))
273 			return false;
274 		/* parse ds64 chunk if necessary */
275 		if(fm->is_rf64 && fm->num_blocks == 2) {
276 			FLAC__byte buffer2[7*4];
277 			if(memcmp(buffer, "ds64", 4)) {
278 				if(error) *error = "invalid RF64 file: \"ds64\" chunk does not immediately follow \"WAVE\" marker (r02)";
279 				return false;
280 			}
281 			/* unpack the size again since we don't want the padding byte effect */
282 			size = unpack32le_(buffer+4);
283 			if(size < (FLAC__off_t)sizeof(buffer2)) {
284 				if(error) *error = "invalid RF64 file: \"ds64\" chunk size is < 28 (r03)";
285 				return false;
286 			}
287 			if(size > (FLAC__off_t)sizeof(buffer2)) {
288 				if(error) *error = "RF64 file has \"ds64\" chunk with extra size table, which is not currently supported (r04)";
289 				return false;
290 			}
291 			if(fread(buffer2, 1, sizeof(buffer2), f) < sizeof(buffer2)) {
292 				if(error) *error = "unexpected EOF reading \"ds64\" chunk data in RF64 file (r05)";
293 				return false;
294 			}
295 			ds64_data_size = (FLAC__off_t)unpack64le_(buffer2+8);
296 			if(ds64_data_size == (FLAC__off_t)(-1)) {
297 				if(error) *error = "RF64 file has \"ds64\" chunk with data size == -1 (r08)";
298 				return false;
299 			}
300 			/* check if pad byte needed */
301 			if(ds64_data_size & 1)
302 				ds64_data_size++;
303 			/* @@@ [2^63 limit] */
304 			if(ds64_data_size < 0) {
305 				if(error) *error = "RF64 file too large (r09)";
306 				return false;
307 			}
308 			if(unpack32le_(buffer2+24)) {
309 				if(error) *error = "RF64 file has \"ds64\" chunk with extra size table, which is not currently supported (r06)";
310 				return false;
311 			}
312 			eof_offset = (FLAC__off_t)8 + (FLAC__off_t)unpack64le_(buffer2);
313 			/* @@@ [2^63 limit] */
314 			if((FLAC__off_t)unpack64le_(buffer2) < 0 || eof_offset < 0) {
315 				if(error) *error = "RF64 file too large (r07)";
316 				return false;
317 			}
318 		}
319 		else { /* skip to next chunk */
320 			if(fm->is_rf64 && !memcmp(buffer, "data", 4) && unpack32le_(buffer+4) == 0xffffffff) {
321 				if(fseeko(f, ds64_data_size, SEEK_CUR) < 0) {
322 					if(error) *error = "invalid RF64 file: seek error (r10)";
323 					return false;
324 				}
325 			}
326 			else {
327 				if(fseeko(f, size, SEEK_CUR) < 0) {
328 					if(error) *error = "invalid WAVE file: seek error (009)";
329 					return false;
330 				}
331 			}
332 		}
333 	}
334 	if(fm->is_rf64 && eof_offset == (FLAC__off_t)(-1)) {
335 		if(error) *error = "invalid RF64 file: all RIFF sizes are -1 (r11)";
336 		return false;
337 	}
338 	if(eof_offset != ftello(f)) {
339 		if(error) *error = "invalid WAVE file: unexpected EOF (010)";
340 		return false;
341 	}
342 	if(!fm->format_block) {
343 		if(error) *error = "invalid WAVE file: missing \"fmt \" chunk (011)";
344 		return false;
345 	}
346 	if(!fm->audio_block) {
347 		if(error) *error = "invalid WAVE file: missing \"data\" chunk (012)";
348 		return false;
349 	}
350 	return true;
351 }
352 
read_from_wave64_(foreign_metadata_t * fm,FILE * f,const char ** error)353 static FLAC__bool read_from_wave64_(foreign_metadata_t *fm, FILE *f, const char **error)
354 {
355 	FLAC__byte buffer[40];
356 	FLAC__off_t offset, eof_offset = -1;
357 	if((offset = ftello(f)) < 0) {
358 		if(error) *error = "ftello() error (001)";
359 		return false;
360 	}
361 	if(
362 		fread(buffer, 1, 40, f) < 40 ||
363 		/* RIFF GUID 66666972-912E-11CF-A5D6-28DB04C10000 */
364 		memcmp(buffer, "\x72\x69\x66\x66\x2E\x91\xCF\x11\xA5\xD6\x28\xDB\x04\xC1\x00\x00", 16) ||
365 		/* WAVE GUID 65766177-ACF3-11D3-8CD1-00C04F8EDB8A */
366 		memcmp(buffer+24, "\x77\x61\x76\x65\xF3\xAC\xD3\x11\x8C\xD1\x00\xC0\x4F\x8E\xDB\x8A", 16)
367 	) {
368 		if(error) *error = "unsupported Wave64 layout (002)";
369 		return false;
370 	}
371 	if(sizeof(FLAC__off_t) < 8) {
372 		if(error) *error = "Wave64 is not supported on this compile (r00)";
373 		return false;
374 	}
375 	if(!append_block_(fm, offset, 40, error))
376 		return false;
377 	eof_offset = (FLAC__off_t)unpack64le_(buffer+16); /*@@@ [2^63 limit] */
378 	while(!feof(f)) {
379 		FLAC__uint64 size;
380 		if((offset = ftello(f)) < 0) {
381 			if(error) *error = "ftello() error (003)";
382 			return false;
383 		}
384 		if((size = fread(buffer, 1, 24, f)) < 24) {
385 			if(size == 0 && feof(f))
386 				break;
387 			if(error) *error = "invalid Wave64 file (004)";
388 			return false;
389 		}
390 		size = unpack64le_(buffer+16);
391 		/* check if pad bytes needed */
392 		if(size & 7)
393 			size = (size+7) & (~((FLAC__uint64)7));
394 		/* fmt GUID 20746D66-ACF3-11D3-8CD1-00C04F8EDB8A */
395 		if(!memcmp(buffer, "\x66\x6D\x74\x20\xF3\xAC\xD3\x11\x8C\xD1\x00\xC0\x4F\x8E\xDB\x8A", 16)) {
396 			if(fm->format_block) {
397 				if(error) *error = "invalid Wave64 file: multiple \"fmt \" chunks (005)";
398 				return false;
399 			}
400 			if(fm->audio_block) {
401 				if(error) *error = "invalid Wave64 file: \"data\" chunk before \"fmt \" chunk (006)";
402 				return false;
403 			}
404 			fm->format_block = fm->num_blocks;
405 		}
406 		/* data GUID 61746164-ACF3-11D3-8CD1-00C04F8EDB8A */
407 		else if(!memcmp(buffer, "\x64\x61\x74\x61\xF3\xAC\xD3\x11\x8C\xD1\x00\xC0\x4F\x8E\xDB\x8A", 16)) {
408 			if(fm->audio_block) {
409 				if(error) *error = "invalid Wave64 file: multiple \"data\" chunks (007)";
410 				return false;
411 			}
412 			if(!fm->format_block) {
413 				if(error) *error = "invalid Wave64 file: \"data\" chunk before \"fmt \" chunk (008)";
414 				return false;
415 			}
416 			fm->audio_block = fm->num_blocks;
417 		}
418 		if(!append_block_(fm, offset, memcmp(buffer, "\x64\x61\x74\x61\xF3\xAC\xD3\x11\x8C\xD1\x00\xC0\x4F\x8E\xDB\x8A", 16)? (FLAC__uint32)size : 16+8, error))
419 			return false;
420 		/* skip to next chunk */
421 		if(fseeko(f, size-24, SEEK_CUR) < 0) {
422 			if(error) *error = "invalid Wave64 file: seek error (009)";
423 			return false;
424 		}
425 	}
426 	if(eof_offset != ftello(f)) {
427 		if(error) *error = "invalid Wave64 file: unexpected EOF (010)";
428 		return false;
429 	}
430 	if(!fm->format_block) {
431 		if(error) *error = "invalid Wave64 file: missing \"fmt \" chunk (011)";
432 		return false;
433 	}
434 	if(!fm->audio_block) {
435 		if(error) *error = "invalid Wave64 file: missing \"data\" chunk (012)";
436 		return false;
437 	}
438 	return true;
439 }
440 
write_to_flac_(foreign_metadata_t * fm,FILE * fin,FILE * fout,FLAC__Metadata_SimpleIterator * it,const char ** error)441 static FLAC__bool write_to_flac_(foreign_metadata_t *fm, FILE *fin, FILE *fout, FLAC__Metadata_SimpleIterator *it, const char **error)
442 {
443 	FLAC__byte buffer[4];
444 	const uint32_t ID_LEN = FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8;
445 	size_t block_num = 0;
446 	FLAC__ASSERT(sizeof(buffer) >= ID_LEN);
447 	while(block_num < fm->num_blocks) {
448 		/* find next matching padding block */
449 		do {
450 			/* 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 */
451 			if(!FLAC__metadata_simple_iterator_next(it)) {
452 				if(error) *error = "no matching PADDING block found (004)";
453 				return false;
454 			}
455 		} while(FLAC__metadata_simple_iterator_get_block_type(it) != FLAC__METADATA_TYPE_PADDING);
456 		if(FLAC__metadata_simple_iterator_get_block_length(it) != ID_LEN+fm->blocks[block_num].size) {
457 			if(error) *error = "PADDING block with wrong size found (005)";
458 			return false;
459 		}
460 		/* transfer chunk into APPLICATION block */
461 		/* first set up the file pointers */
462 		if(fseeko(fin, fm->blocks[block_num].offset, SEEK_SET) < 0) {
463 			if(error) *error = "seek failed in WAVE/AIFF file (006)";
464 			return false;
465 		}
466 		if(fseeko(fout, FLAC__metadata_simple_iterator_get_block_offset(it), SEEK_SET) < 0) {
467 			if(error) *error = "seek failed in FLAC file (007)";
468 			return false;
469 		}
470 		/* update the type */
471 		buffer[0] = FLAC__METADATA_TYPE_APPLICATION;
472 		if(FLAC__metadata_simple_iterator_is_last(it))
473 			buffer[0] |= 0x80; /*MAGIC number*/
474 		if(fwrite(buffer, 1, 1, fout) < 1) {
475 			if(error) *error = "write failed in FLAC file (008)";
476 			return false;
477 		}
478 		/* length stays the same so skip over it */
479 		if(fseeko(fout, FLAC__STREAM_METADATA_LENGTH_LEN/8, SEEK_CUR) < 0) {
480 			if(error) *error = "seek failed in FLAC file (009)";
481 			return false;
482 		}
483 		/* write the APPLICATION ID */
484 		memcpy(buffer, FLAC__FOREIGN_METADATA_APPLICATION_ID[fm->type], ID_LEN);
485 		if(fwrite(buffer, 1, ID_LEN, fout) < ID_LEN) {
486 			if(error) *error = "write failed in FLAC file (010)";
487 			return false;
488 		}
489 		/* transfer the foreign metadata */
490 		if(!copy_data_(fin, fout, fm->blocks[block_num].size, error, "read failed in WAVE/AIFF file (011)", "write failed in FLAC file (012)"))
491 			return false;
492 		block_num++;
493 	}
494 	return true;
495 }
496 
read_from_flac_(foreign_metadata_t * fm,FILE * f,FLAC__Metadata_SimpleIterator * it,const char ** error)497 static FLAC__bool read_from_flac_(foreign_metadata_t *fm, FILE *f, FLAC__Metadata_SimpleIterator *it, const char **error)
498 {
499 	FLAC__byte id[4], buffer[32];
500 	FLAC__off_t offset;
501 	FLAC__uint32 length;
502 	FLAC__bool first_block = true, type_found = false, ds64_found = false;
503 
504 	FLAC__ASSERT(FLAC__STREAM_METADATA_APPLICATION_ID_LEN == sizeof(id)*8);
505 
506 	while(FLAC__metadata_simple_iterator_next(it)) {
507 		if(FLAC__metadata_simple_iterator_get_block_type(it) != FLAC__METADATA_TYPE_APPLICATION)
508 			continue;
509 		if(!FLAC__metadata_simple_iterator_get_application_id(it, id)) {
510 			if(error) *error = "FLAC__metadata_simple_iterator_get_application_id() error (002)";
511 			return false;
512 		}
513 		if(first_block) {
514 			uint32_t i;
515 			for(i = 0; i < FLAC__FOREIGN_METADATA_NUMBER_OF_RECOGNIZED_APPLICATION_IDS; i++)
516 				if(memcmp(id, FLAC__FOREIGN_METADATA_APPLICATION_ID[i], sizeof(id)) == 0) {
517 					fm->type = i;
518 					first_block = false;
519 				}
520 			if(first_block) /* means no first foreign metadata block was found yet */
521 				continue;
522 		}
523 		else if(memcmp(id, FLAC__FOREIGN_METADATA_APPLICATION_ID[fm->type], sizeof(id)))
524 			continue;
525 		offset = FLAC__metadata_simple_iterator_get_block_offset(it);
526 		length = FLAC__metadata_simple_iterator_get_block_length(it);
527 		/* skip over header and app ID */
528 		offset += (FLAC__STREAM_METADATA_IS_LAST_LEN + FLAC__STREAM_METADATA_TYPE_LEN + FLAC__STREAM_METADATA_LENGTH_LEN) / 8;
529 		offset += sizeof(id);
530 		/* look for format or audio blocks */
531 		if(fseeko(f, offset, SEEK_SET) < 0) {
532 			if(error) *error = "seek error (003)";
533 			return false;
534 		}
535 		if(fread(buffer, 1, 4, f) != 4) {
536 			if(error) *error = "read error (004)";
537 			return false;
538 		}
539 		if(fm->num_blocks == 0) { /* first block? */
540 			/* Initialize bools */
541 			fm->is_wavefmtex = 0;
542 			fm->is_aifc = 0;
543 			fm->is_sowt = 0;
544 			fm->is_rf64 = 0 == memcmp(buffer, "RF64", 4);
545 
546 			if(fm->type == FOREIGN_BLOCK_TYPE__RIFF && (0 == memcmp(buffer, "RIFF", 4) || fm->is_rf64))
547 				type_found = true;
548 			else if(fm->type == FOREIGN_BLOCK_TYPE__WAVE64 && 0 == memcmp(buffer, "riff", 4)) /* use first 4 bytes instead of whole GUID */
549 				type_found = true;
550 			else if(fm->type == FOREIGN_BLOCK_TYPE__AIFF && 0 == memcmp(buffer, "FORM", 4)) {
551 				type_found = true;
552 				if(fread(buffer+4, 1, 8, f) != 8) {
553 					if(error) *error = "read error (020)";
554 					return false;
555 				}
556 				fm->is_aifc = 0 == memcmp(buffer+8, "AIFC", 4);
557 			}
558 			else {
559 				if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (005)";
560 				return false;
561 			}
562 		}
563 		else if(!type_found) {
564 			FLAC__ASSERT(0);
565 			/* double protection: */
566 			if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (006)";
567 			return false;
568 		}
569 		else if(fm->type == FOREIGN_BLOCK_TYPE__RIFF) {
570 			if(!memcmp(buffer, "fmt ", 4)) {
571 				if(fm->format_block) {
572 					if(error) *error = "invalid WAVE metadata: multiple \"fmt \" chunks (007)";
573 					return false;
574 				}
575 				if(fm->audio_block) {
576 					if(error) *error = "invalid WAVE metadata: \"data\" chunk before \"fmt \" chunk (008)";
577 					return false;
578 				}
579 				fm->format_block = fm->num_blocks;
580 				if(fread(buffer+4, 1, 8, f) != 8) {
581 					if(error) *error = "read error (020)";
582 					return false;
583 				}
584 				fm->is_wavefmtex = 0 == memcmp(buffer+8, "\xfe\xff", 2);
585 			}
586 			else if(!memcmp(buffer, "data", 4)) {
587 				if(fm->audio_block) {
588 					if(error) *error = "invalid WAVE metadata: multiple \"data\" chunks (009)";
589 					return false;
590 				}
591 				if(!fm->format_block) {
592 					if(error) *error = "invalid WAVE metadata: \"data\" chunk before \"fmt \" chunk (010)";
593 					return false;
594 				}
595 				fm->audio_block = fm->num_blocks;
596 			}
597 			else if(fm->is_rf64 && fm->num_blocks == 1) {
598 				if(memcmp(buffer, "ds64", 4)) {
599 					if(error) *error = "invalid RF64 metadata: second chunk is not \"ds64\" (011)";
600 					return false;
601 				}
602 				ds64_found = true;
603 			}
604 		}
605 		else if(fm->type == FOREIGN_BLOCK_TYPE__WAVE64) {
606 			if(!memcmp(buffer, "fmt ", 4)) { /* use first 4 bytes instead of whole GUID */
607 				if(fm->format_block) {
608 					if(error) *error = "invalid Wave64 metadata: multiple \"fmt \" chunks (012)";
609 					return false;
610 				}
611 				if(fm->audio_block) {
612 					if(error) *error = "invalid Wave64 metadata: \"data\" chunk before \"fmt \" chunk (013)";
613 					return false;
614 				}
615 				fm->format_block = fm->num_blocks;
616 			}
617 			else if(!memcmp(buffer, "data", 4)) { /* use first 4 bytes instead of whole GUID */
618 				if(fm->audio_block) {
619 					if(error) *error = "invalid Wave64 metadata: multiple \"data\" chunks (014)";
620 					return false;
621 				}
622 				if(!fm->format_block) {
623 					if(error) *error = "invalid Wave64 metadata: \"data\" chunk before \"fmt \" chunk (015)";
624 					return false;
625 				}
626 				fm->audio_block = fm->num_blocks;
627 			}
628 		}
629 		else if(fm->type == FOREIGN_BLOCK_TYPE__AIFF) {
630 			if(!memcmp(buffer, "COMM", 4)) {
631 				if(fm->format_block) {
632 					if(error) *error = "invalid AIFF metadata: multiple \"COMM\" chunks (016)";
633 					return false;
634 				}
635 				if(fm->audio_block) {
636 					if(error) *error = "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (017)";
637 					return false;
638 				}
639 				fm->format_block = fm->num_blocks;
640 				if(fm->is_aifc) {
641 					if(fread(buffer+4, 1, 26, f) != 26) {
642 						if(error) *error = "read error (020)";
643 						return false;
644 					}
645 					fm->is_sowt = 0 == memcmp(buffer+26, "sowt", 2);
646 					fm->aifc_comm_length = length;
647 				}
648 			}
649 			else if(!memcmp(buffer, "SSND", 4)) {
650 				if(fm->audio_block) {
651 					if(error) *error = "invalid AIFF metadata: multiple \"SSND\" chunks (018)";
652 					return false;
653 				}
654 				if(!fm->format_block) {
655 					if(error) *error = "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (019)";
656 					return false;
657 				}
658 				fm->audio_block = fm->num_blocks;
659 				/* read SSND offset size */
660 				if(fread(buffer+4, 1, 8, f) != 8) {
661 					if(error) *error = "read error (020)";
662 					return false;
663 				}
664 				fm->ssnd_offset_size = unpack32be_(buffer+8);
665 			}
666 		}
667 		else {
668 			FLAC__ASSERT(0);
669 			/* double protection: */
670 			if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (021)";
671 			return false;
672 		}
673 		if(!append_block_(fm, offset, FLAC__metadata_simple_iterator_get_block_length(it)-sizeof(id), error))
674 			return false;
675 	}
676 	if(fm->is_rf64 && !ds64_found) {
677 		if(error) *error = "invalid RF64 file: second chunk is not \"ds64\" (023)";
678 		return false;
679 	}
680 	if(!fm->format_block) {
681 		if(error)
682 			*error =
683 				fm->type==FOREIGN_BLOCK_TYPE__RIFF? "invalid WAVE file: missing \"fmt \" chunk (024)" :
684 				fm->type==FOREIGN_BLOCK_TYPE__WAVE64? "invalid Wave64 file: missing \"fmt \" chunk (025)" :
685 				"invalid AIFF file: missing \"COMM\" chunk (026)";
686 		return false;
687 	}
688 	if(!fm->audio_block) {
689 		if(error)
690 			*error =
691 				fm->type==FOREIGN_BLOCK_TYPE__RIFF? "invalid WAVE file: missing \"data\" chunk (027)" :
692 				fm->type==FOREIGN_BLOCK_TYPE__WAVE64? "invalid Wave64 file: missing \"data\" chunk (028)" :
693 				"invalid AIFF file: missing \"SSND\" chunk (029)";
694 		return false;
695 	}
696 	return true;
697 }
698 
write_to_iff_(foreign_metadata_t * fm,FILE * fin,FILE * fout,FLAC__off_t offset1,FLAC__off_t offset2,FLAC__off_t offset3,const char ** error)699 static FLAC__bool write_to_iff_(foreign_metadata_t *fm, FILE *fin, FILE *fout, FLAC__off_t offset1, FLAC__off_t offset2, FLAC__off_t offset3, const char **error)
700 {
701 	size_t i;
702 	if(fseeko(fout, offset1, SEEK_SET) < 0) {
703 		if(error) *error = "seek failed in WAVE/AIFF file";
704 		return false;
705 	}
706 
707 	/* don't write first (RIFF/RF64/FORM) chunk, or ds64 chunk in the case of RF64 */
708 	for(i = fm->is_rf64?2:1; i < fm->format_block; i++) {
709 		if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) {
710 			if(error) *error = "seek failed in FLAC file";
711 			return false;
712 		}
713 		if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in FLAC file", "write failed in WAVE/AIFF file"))
714 			return false;
715 	}
716 
717 	if(fm->is_aifc) {
718 		/* Need to restore compression type name */
719 		if(fseeko(fout, 30, SEEK_CUR) < 0) {
720 			if(error) *error = "seek failed in AIFF-C file";
721 			return false;
722 		}
723 		if(fseeko(fin, fm->blocks[i].offset+30, SEEK_SET) < 0) {
724 			if(error) *error = "seek failed in FLAC file";
725 			return false;
726 		}
727 		if(!copy_data_(fin, fout, fm->aifc_comm_length-34, error, "read failed in FLAC file", "write failed in WAVE/AIFF file"))
728 			return false;
729 		/* Now seek back */
730 		if(fseeko(fout, ((FLAC__int32)(fm->aifc_comm_length) * -1) + 4, SEEK_CUR) < 0) {
731 			if(error) *error = "seek failed in AIFF-C file";
732 			return false;
733 		}
734 	}
735 	if(fseeko(fout, offset2, SEEK_SET) < 0) {
736 		if(error) *error = "seek failed in WAVE/AIFF file (006)";
737 		return false;
738 	}
739 	for(i = fm->format_block+1; i < fm->audio_block; i++) {
740 		if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) {
741 			if(error) *error = "seek failed in FLAC file";
742 			return false;
743 		}
744 		if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in FLAC file", "write failed in WAVE/AIFF file"))
745 			return false;
746 	}
747 	if(fseeko(fout, offset3, SEEK_SET) < 0) {
748 		if(error) *error = "seek failed in WAVE/AIFF file";
749 		return false;
750 	}
751 	for(i = fm->audio_block+1; i < fm->num_blocks; i++) {
752 		if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) {
753 			if(error) *error = "seek failed in FLAC file";
754 			return false;
755 		}
756 		if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in FLAC file", "write failed in WAVE/AIFF file"))
757 			return false;
758 	}
759 	return true;
760 }
761 
compare_with_iff_(foreign_metadata_t * fm,FILE * fin,FILE * fout,FLAC__off_t offset3,const char ** error)762 static FLAC__bool compare_with_iff_(foreign_metadata_t *fm, FILE *fin, FILE *fout, FLAC__off_t offset3, const char **error)
763 {
764 	size_t i;
765 
766 	/* Compare blocks before audio data */
767 	for(i = 0; i <= (fm->audio_block); i++) {
768 		if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) {
769 			if(error) *error = "seek failed in FLAC file";
770 			return false;
771 		}
772 		if(!compare_data_(fin, fout, fm->blocks[i].size, error, "read failed in FLAC file", "read failed in WAVE/AIFF file",
773 		      i==0?"stored main chunk length differs from written length":(
774 		      i==fm->format_block?"stored foreign format block differs from written block. Perhaps the file is being restored to a different format than that of the original file":(
775 		      i==fm->audio_block?"stored audio length differs from written length. Perhaps the file changed in length after being originally encoded":"restore of foreign metadata failed"))))
776 			return false;
777 	}
778 
779 	/* Seek beyond audio */
780 	if(fseeko(fout, offset3, SEEK_SET) < 0) {
781 		if(error) *error = "seek failed in WAVE/AIFF file";
782 		return false;
783 	}
784 	for(; i < fm->num_blocks; i++) {
785 		if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) {
786 			if(error) *error = "seek failed in FLAC file";
787 			return false;
788 		}
789 		if(!compare_data_(fin, fout, fm->blocks[i].size, error, "read failed in FLAC file", "read failed in WAVE/AIFF file", "restore of foreign metadata failed"))
790 			return false;
791 	}
792 	return true;
793 }
794 
flac__foreign_metadata_new(foreign_block_type_t type)795 foreign_metadata_t *flac__foreign_metadata_new(foreign_block_type_t type)
796 {
797 	/* calloc() to zero all the member variables */
798 	foreign_metadata_t *x = calloc(sizeof(foreign_metadata_t), 1);
799 	if(x) {
800 		x->type = type;
801 		x->is_rf64 = false;
802 	}
803 	return x;
804 }
805 
flac__foreign_metadata_delete(foreign_metadata_t * fm)806 void flac__foreign_metadata_delete(foreign_metadata_t *fm)
807 {
808 	if(fm) {
809 		if(fm->blocks)
810 			free(fm->blocks);
811 		free(fm);
812 	}
813 }
814 
flac__foreign_metadata_read_from_aiff(foreign_metadata_t * fm,const char * filename,const char ** error)815 FLAC__bool flac__foreign_metadata_read_from_aiff(foreign_metadata_t *fm, const char *filename, const char **error)
816 {
817 	FLAC__bool ok;
818 	FILE *f = flac_fopen(filename, "rb");
819 	if(!f) {
820 		if(error) *error = "can't open AIFF file for reading (000)";
821 		return false;
822 	}
823 	ok = read_from_aiff_(fm, f, error);
824 	fclose(f);
825 	return ok;
826 }
827 
flac__foreign_metadata_read_from_wave(foreign_metadata_t * fm,const char * filename,const char ** error)828 FLAC__bool flac__foreign_metadata_read_from_wave(foreign_metadata_t *fm, const char *filename, const char **error)
829 {
830 	FLAC__bool ok;
831 	FILE *f = flac_fopen(filename, "rb");
832 	if(!f) {
833 		if(error) *error = "can't open WAVE file for reading (000)";
834 		return false;
835 	}
836 	ok = read_from_wave_(fm, f, error);
837 	fclose(f);
838 	return ok;
839 }
840 
flac__foreign_metadata_read_from_wave64(foreign_metadata_t * fm,const char * filename,const char ** error)841 FLAC__bool flac__foreign_metadata_read_from_wave64(foreign_metadata_t *fm, const char *filename, const char **error)
842 {
843 	FLAC__bool ok;
844 	FILE *f = flac_fopen(filename, "rb");
845 	if(!f) {
846 		if(error) *error = "can't open Wave64 file for reading (000)";
847 		return false;
848 	}
849 	ok = read_from_wave64_(fm, f, error);
850 	fclose(f);
851 	return ok;
852 }
853 
flac__foreign_metadata_write_to_flac(foreign_metadata_t * fm,const char * infilename,const char * outfilename,const char ** error)854 FLAC__bool flac__foreign_metadata_write_to_flac(foreign_metadata_t *fm, const char *infilename, const char *outfilename, const char **error)
855 {
856 	FLAC__bool ok;
857 	FILE *fin, *fout;
858 	FLAC__Metadata_SimpleIterator *it = FLAC__metadata_simple_iterator_new();
859 	if(!it) {
860 		if(error) *error = "out of memory (000)";
861 		return false;
862 	}
863 	if(!FLAC__metadata_simple_iterator_init(it, outfilename, /*read_only=*/true, /*preserve_file_stats=*/false)) {
864 		if(error) *error = "can't initialize iterator (001)";
865 		FLAC__metadata_simple_iterator_delete(it);
866 		return false;
867 	}
868 	if(0 == (fin = flac_fopen(infilename, "rb"))) {
869 		if(error) *error = "can't open WAVE/AIFF file for reading (002)";
870 		FLAC__metadata_simple_iterator_delete(it);
871 		return false;
872 	}
873 	if(0 == (fout = flac_fopen(outfilename, "r+b"))) {
874 		if(error) *error = "can't open FLAC file for updating (003)";
875 		FLAC__metadata_simple_iterator_delete(it);
876 		fclose(fin);
877 		return false;
878 	}
879 	ok = write_to_flac_(fm, fin, fout, it, error);
880 	FLAC__metadata_simple_iterator_delete(it);
881 	fclose(fin);
882 	fclose(fout);
883 	return ok;
884 }
885 
flac__foreign_metadata_read_from_flac(foreign_metadata_t * fm,const char * filename,const char ** error)886 FLAC__bool flac__foreign_metadata_read_from_flac(foreign_metadata_t *fm, const char *filename, const char **error)
887 {
888 	FLAC__bool ok;
889 	FILE *f;
890 	FLAC__Metadata_SimpleIterator *it = FLAC__metadata_simple_iterator_new();
891 	if(!it) {
892 		if(error) *error = "out of memory (000)";
893 		return false;
894 	}
895 	if(!FLAC__metadata_simple_iterator_init(it, filename, /*read_only=*/true, /*preserve_file_stats=*/false)) {
896 		if(error) *error = "can't initialize iterator (001)";
897 		FLAC__metadata_simple_iterator_delete(it);
898 		return false;
899 	}
900 	if(0 == (f = flac_fopen(filename, "rb"))) {
901 		if(error) *error = "can't open FLAC file for reading (002)";
902 		FLAC__metadata_simple_iterator_delete(it);
903 		return false;
904 	}
905 	ok = read_from_flac_(fm, f, it, error);
906 	FLAC__metadata_simple_iterator_delete(it);
907 	fclose(f);
908 	return ok;
909 }
910 
flac__foreign_metadata_write_to_iff(foreign_metadata_t * fm,const char * infilename,const char * outfilename,FLAC__off_t offset1,FLAC__off_t offset2,FLAC__off_t offset3,const char ** error)911 FLAC__bool flac__foreign_metadata_write_to_iff(foreign_metadata_t *fm, const char *infilename, const char *outfilename, FLAC__off_t offset1, FLAC__off_t offset2, FLAC__off_t offset3, const char **error)
912 {
913 	FLAC__bool ok;
914 	FILE *fin, *fout;
915 	if(0 == (fin = flac_fopen(infilename, "rb"))) {
916 		if(error) *error = "can't open FLAC file for reading (000)";
917 		return false;
918 	}
919 	if(0 == (fout = flac_fopen(outfilename, "r+b"))) {
920 		if(error) *error = "can't open WAVE/AIFF file for updating (001)";
921 		fclose(fin);
922 		return false;
923 	}
924 	ok = write_to_iff_(fm, fin, fout, offset1, offset2, offset3, error);
925 	fclose(fin);
926 	fclose(fout);
927 	return ok;
928 }
929 
flac__foreign_metadata_compare_with_iff(foreign_metadata_t * fm,const char * infilename,const char * outfilename,FLAC__off_t offset3,const char ** error)930 FLAC__bool flac__foreign_metadata_compare_with_iff(foreign_metadata_t *fm, const char *infilename, const char *outfilename, FLAC__off_t offset3, const char **error)
931 {
932 	FLAC__bool ok;
933 	FILE *fin, *fout;
934 	if(0 == (fin = flac_fopen(infilename, "rb"))) {
935 		if(error) *error = "can't open FLAC file for reading";
936 		return false;
937 	}
938 	if(0 == (fout = flac_fopen(outfilename, "rb"))) {
939 		if(error) *error = "can't open WAVE/AIFF file for comparing";
940 		fclose(fin);
941 		return false;
942 	}
943 	ok = compare_with_iff_(fm, fin, fout, offset3, error);
944 	fclose(fin);
945 	fclose(fout);
946 	return ok;
947 }
948