• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* flac - Command-line FLAC encoder/decoder
2  * Copyright (C) 2000-2009  Josh Coalson
3  * Copyright (C) 2011-2016  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 
39 static const char *FLAC__FOREIGN_METADATA_APPLICATION_ID[3] = { "aiff" , "riff", "w64 " };
40 
unpack32be_(const FLAC__byte * b)41 static FLAC__uint32 unpack32be_(const FLAC__byte *b)
42 {
43 	return ((FLAC__uint32)b[0]<<24) + ((FLAC__uint32)b[1]<<16) + ((FLAC__uint32)b[2]<<8) + (FLAC__uint32)b[3];
44 }
45 
unpack32le_(const FLAC__byte * b)46 static FLAC__uint32 unpack32le_(const FLAC__byte *b)
47 {
48 	return (FLAC__uint32)b[0] + ((FLAC__uint32)b[1]<<8) + ((FLAC__uint32)b[2]<<16) + ((FLAC__uint32)b[3]<<24);
49 }
50 
unpack64le_(const FLAC__byte * b)51 static FLAC__uint64 unpack64le_(const FLAC__byte *b)
52 {
53 	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);
54 }
55 
56 /* 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)57 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)
58 {
59 	FLAC__byte buffer[4096];
60 	size_t left;
61 	for(left = size; left > 0; ) {
62 		size_t need = min(sizeof(buffer), left);
63 		if(fread(buffer, 1, need, fin) < need) {
64 			if(error) *error = read_error;
65 			return false;
66 		}
67 		if(fwrite(buffer, 1, need, fout) < need) {
68 			if(error) *error = write_error;
69 			return false;
70 		}
71 		left -= need;
72 	}
73 	return true;
74 }
75 
append_block_(foreign_metadata_t * fm,FLAC__off_t offset,FLAC__uint32 size,const char ** error)76 static FLAC__bool append_block_(foreign_metadata_t *fm, FLAC__off_t offset, FLAC__uint32 size, const char **error)
77 {
78 	foreign_block_t *fb = safe_realloc_muladd2_(fm->blocks, sizeof(foreign_block_t), /*times (*/fm->num_blocks, /*+*/1/*)*/);
79 	if(fb) {
80 		fb[fm->num_blocks].offset = offset;
81 		fb[fm->num_blocks].size = size;
82 		fm->num_blocks++;
83 		fm->blocks = fb;
84 		return true;
85 	}
86 	if(error) *error = "out of memory";
87 	return false;
88 }
89 
read_from_aiff_(foreign_metadata_t * fm,FILE * f,const char ** error)90 static FLAC__bool read_from_aiff_(foreign_metadata_t *fm, FILE *f, const char **error)
91 {
92 	FLAC__byte buffer[12];
93 	FLAC__off_t offset, eof_offset;
94 	if((offset = ftello(f)) < 0) {
95 		if(error) *error = "ftello() error (001)";
96 		return false;
97 	}
98 	if(fread(buffer, 1, 12, f) < 12 || memcmp(buffer, "FORM", 4) || (memcmp(buffer+8, "AIFF", 4) && memcmp(buffer+8, "AIFC", 4))) {
99 		if(error) *error = "unsupported FORM layout (002)";
100 		return false;
101 	}
102 	if(!append_block_(fm, offset, 12, error))
103 		return false;
104 	eof_offset = (FLAC__off_t)8 + (FLAC__off_t)unpack32be_(buffer+4);
105 	while(!feof(f)) {
106 		FLAC__uint32 size;
107 		if((offset = ftello(f)) < 0) {
108 			if(error) *error = "ftello() error (003)";
109 			return false;
110 		}
111 		if((size = fread(buffer, 1, 8, f)) < 8) {
112 			if(size == 0 && feof(f))
113 				break;
114 			if(error) *error = "invalid AIFF file (004)";
115 			return false;
116 		}
117 		size = unpack32be_(buffer+4);
118 		/* check if pad byte needed */
119 		if(size & 1)
120 			size++;
121 		if(!memcmp(buffer, "COMM", 4)) {
122 			if(fm->format_block) {
123 				if(error) *error = "invalid AIFF file: multiple \"COMM\" chunks (005)";
124 				return false;
125 			}
126 			if(fm->audio_block) {
127 				if(error) *error = "invalid AIFF file: \"SSND\" chunk before \"COMM\" chunk (006)";
128 				return false;
129 			}
130 			fm->format_block = fm->num_blocks;
131 		}
132 		else if(!memcmp(buffer, "SSND", 4)) {
133 			if(fm->audio_block) {
134 				if(error) *error = "invalid AIFF file: multiple \"SSND\" chunks (007)";
135 				return false;
136 			}
137 			if(!fm->format_block) {
138 				if(error) *error = "invalid AIFF file: \"SSND\" chunk before \"COMM\" chunk (008)";
139 				return false;
140 			}
141 			fm->audio_block = fm->num_blocks;
142 			/* read #offset bytes */
143 			if(fread(buffer+8, 1, 4, f) < 4) {
144 				if(error) *error = "invalid AIFF file (009)";
145 				return false;
146 			}
147 			fm->ssnd_offset_size = unpack32be_(buffer+8);
148 			if(fseeko(f, -4, SEEK_CUR) < 0) {
149 				if(error) *error = "invalid AIFF file: seek error (010)";
150 				return false;
151 			}
152 			/* WATCHOUT: For SSND we ignore the blockSize and are not saving any
153 			 * unaligned part at the end of the chunk.  In retrospect it is pretty
154 			 * pointless to save the unaligned data before the PCM but now it is
155 			 * done and cast in stone.
156 			 */
157 		}
158 		if(!append_block_(fm, offset, 8 + (memcmp(buffer, "SSND", 4)? size : 8 + fm->ssnd_offset_size), error))
159 			return false;
160 		/* skip to next chunk */
161 		if(fseeko(f, size, SEEK_CUR) < 0) {
162 			if(error) *error = "invalid AIFF file: seek error (011)";
163 			return false;
164 		}
165 	}
166 	if(eof_offset != ftello(f)) {
167 		if(error) *error = "invalid AIFF file: unexpected EOF (012)";
168 		return false;
169 	}
170 	if(!fm->format_block) {
171 		if(error) *error = "invalid AIFF file: missing \"COMM\" chunk (013)";
172 		return false;
173 	}
174 	if(!fm->audio_block) {
175 		if(error) *error = "invalid AIFF file: missing \"SSND\" chunk (014)";
176 		return false;
177 	}
178 	return true;
179 }
180 
read_from_wave_(foreign_metadata_t * fm,FILE * f,const char ** error)181 static FLAC__bool read_from_wave_(foreign_metadata_t *fm, FILE *f, const char **error)
182 {
183 	FLAC__byte buffer[12];
184 	FLAC__off_t offset, eof_offset = -1, ds64_data_size = -1;
185 	if((offset = ftello(f)) < 0) {
186 		if(error) *error = "ftello() error (001)";
187 		return false;
188 	}
189 	if(fread(buffer, 1, 12, f) < 12 || (memcmp(buffer, "RIFF", 4) && memcmp(buffer, "RF64", 4)) || memcmp(buffer+8, "WAVE", 4)) {
190 		if(error) *error = "unsupported RIFF layout (002)";
191 		return false;
192 	}
193 	if(!memcmp(buffer, "RF64", 4))
194 		fm->is_rf64 = true;
195 	if(fm->is_rf64 && sizeof(FLAC__off_t) < 8) {
196 		if(error) *error = "RF64 is not supported on this compile (r00)";
197 		return false;
198 	}
199 	if(!append_block_(fm, offset, 12, error))
200 		return false;
201 	if(!fm->is_rf64 || unpack32le_(buffer+4) != 0xffffffff) {
202 		eof_offset = (FLAC__off_t)8 + (FLAC__off_t)unpack32le_(buffer+4);
203 		if(eof_offset & 1) /* fix odd RIFF size */
204 			eof_offset++;
205 	}
206 	while(!feof(f)) {
207 		FLAC__uint32 size;
208 		if((offset = ftello(f)) < 0) {
209 			if(error) *error = "ftello() error (003)";
210 			return false;
211 		}
212 		if((size = fread(buffer, 1, 8, f)) < 8) {
213 			if(size == 0 && feof(f))
214 				break;
215 			if(error) *error = "invalid WAVE file (004)";
216 			return false;
217 		}
218 		size = unpack32le_(buffer+4);
219 		/* check if pad byte needed */
220 		if(size & 1)
221 			size++;
222 		if(!memcmp(buffer, "fmt ", 4)) {
223 			if(fm->format_block) {
224 				if(error) *error = "invalid WAVE file: multiple \"fmt \" chunks (005)";
225 				return false;
226 			}
227 			if(fm->audio_block) {
228 				if(error) *error = "invalid WAVE file: \"data\" chunk before \"fmt \" chunk (006)";
229 				return false;
230 			}
231 			fm->format_block = fm->num_blocks;
232 		}
233 		else if(!memcmp(buffer, "data", 4)) {
234 			if(fm->audio_block) {
235 				if(error) *error = "invalid WAVE file: multiple \"data\" chunks (007)";
236 				return false;
237 			}
238 			if(!fm->format_block) {
239 				if(error) *error = "invalid WAVE file: \"data\" chunk before \"fmt \" chunk (008)";
240 				return false;
241 			}
242 			fm->audio_block = fm->num_blocks;
243 			if(fm->is_rf64 && fm->num_blocks < 2) {
244 				if(error) *error = "invalid RF64 file: \"data\" chunk before \"ds64\" chunk (r01)";
245 				return false;
246 			}
247 		}
248 		if(!append_block_(fm, offset, 8 + (memcmp(buffer, "data", 4)? size : 0), error))
249 			return false;
250 		/* parse ds64 chunk if necessary */
251 		if(fm->is_rf64 && fm->num_blocks == 2) {
252 			FLAC__byte buffer2[7*4];
253 			if(memcmp(buffer, "ds64", 4)) {
254 				if(error) *error = "invalid RF64 file: \"ds64\" chunk does not immediately follow \"WAVE\" marker (r02)";
255 				return false;
256 			}
257 			/* unpack the size again since we don't want the padding byte effect */
258 			size = unpack32le_(buffer+4);
259 			if(size < sizeof(buffer2)) {
260 				if(error) *error = "invalid RF64 file: \"ds64\" chunk size is < 28 (r03)";
261 				return false;
262 			}
263 			if(size > sizeof(buffer2)) {
264 				if(error) *error = "RF64 file has \"ds64\" chunk with extra size table, which is not currently supported (r04)";
265 				return false;
266 			}
267 			if(fread(buffer2, 1, sizeof(buffer2), f) < sizeof(buffer2)) {
268 				if(error) *error = "unexpected EOF reading \"ds64\" chunk data in RF64 file (r05)";
269 				return false;
270 			}
271 			ds64_data_size = (FLAC__off_t)unpack64le_(buffer2+8);
272 			if(ds64_data_size == (FLAC__off_t)(-1)) {
273 				if(error) *error = "RF64 file has \"ds64\" chunk with data size == -1 (r08)";
274 				return false;
275 			}
276 			/* check if pad byte needed */
277 			if(ds64_data_size & 1)
278 				ds64_data_size++;
279 			/* @@@ [2^63 limit] */
280 			if(ds64_data_size < 0) {
281 				if(error) *error = "RF64 file too large (r09)";
282 				return false;
283 			}
284 			if(unpack32le_(buffer2+24)) {
285 				if(error) *error = "RF64 file has \"ds64\" chunk with extra size table, which is not currently supported (r06)";
286 				return false;
287 			}
288 			eof_offset = (FLAC__off_t)8 + (FLAC__off_t)unpack64le_(buffer2);
289 			/* @@@ [2^63 limit] */
290 			if((FLAC__off_t)unpack64le_(buffer2) < 0 || eof_offset < 0) {
291 				if(error) *error = "RF64 file too large (r07)";
292 				return false;
293 			}
294 		}
295 		else { /* skip to next chunk */
296 			if(fm->is_rf64 && !memcmp(buffer, "data", 4) && unpack32le_(buffer+4) == 0xffffffff) {
297 				if(fseeko(f, ds64_data_size, SEEK_CUR) < 0) {
298 					if(error) *error = "invalid RF64 file: seek error (r10)";
299 					return false;
300 				}
301 			}
302 			else {
303 				if(fseeko(f, size, SEEK_CUR) < 0) {
304 					if(error) *error = "invalid WAVE file: seek error (009)";
305 					return false;
306 				}
307 			}
308 		}
309 	}
310 	if(fm->is_rf64 && eof_offset == (FLAC__off_t)(-1)) {
311 		if(error) *error = "invalid RF64 file: all RIFF sizes are -1 (r11)";
312 		return false;
313 	}
314 	if(eof_offset != ftello(f)) {
315 		if(error) *error = "invalid WAVE file: unexpected EOF (010)";
316 		return false;
317 	}
318 	if(!fm->format_block) {
319 		if(error) *error = "invalid WAVE file: missing \"fmt \" chunk (011)";
320 		return false;
321 	}
322 	if(!fm->audio_block) {
323 		if(error) *error = "invalid WAVE file: missing \"data\" chunk (012)";
324 		return false;
325 	}
326 	return true;
327 }
328 
read_from_wave64_(foreign_metadata_t * fm,FILE * f,const char ** error)329 static FLAC__bool read_from_wave64_(foreign_metadata_t *fm, FILE *f, const char **error)
330 {
331 	FLAC__byte buffer[40];
332 	FLAC__off_t offset, eof_offset = -1;
333 	if((offset = ftello(f)) < 0) {
334 		if(error) *error = "ftello() error (001)";
335 		return false;
336 	}
337 	if(
338 		fread(buffer, 1, 40, f) < 40 ||
339 		/* RIFF GUID 66666972-912E-11CF-A5D6-28DB04C10000 */
340 		memcmp(buffer, "\x72\x69\x66\x66\x2E\x91\xCF\x11\xA5\xD6\x28\xDB\x04\xC1\x00\x00", 16) ||
341 		/* WAVE GUID 65766177-ACF3-11D3-8CD1-00C04F8EDB8A */
342 		memcmp(buffer+24, "\x77\x61\x76\x65\xF3\xAC\xD3\x11\x8C\xD1\x00\xC0\x4F\x8E\xDB\x8A", 16)
343 	) {
344 		if(error) *error = "unsupported Wave64 layout (002)";
345 		return false;
346 	}
347 	if(sizeof(FLAC__off_t) < 8) {
348 		if(error) *error = "Wave64 is not supported on this compile (r00)";
349 		return false;
350 	}
351 	if(!append_block_(fm, offset, 40, error))
352 		return false;
353 	eof_offset = (FLAC__off_t)unpack64le_(buffer+16); /*@@@ [2^63 limit] */
354 	while(!feof(f)) {
355 		FLAC__uint64 size;
356 		if((offset = ftello(f)) < 0) {
357 			if(error) *error = "ftello() error (003)";
358 			return false;
359 		}
360 		if((size = fread(buffer, 1, 24, f)) < 24) {
361 			if(size == 0 && feof(f))
362 				break;
363 			if(error) *error = "invalid Wave64 file (004)";
364 			return false;
365 		}
366 		size = unpack64le_(buffer+16);
367 		/* check if pad bytes needed */
368 		if(size & 7)
369 			size = (size+7) & (~((FLAC__uint64)7));
370 		/* fmt GUID 20746D66-ACF3-11D3-8CD1-00C04F8EDB8A */
371 		if(!memcmp(buffer, "\x66\x6D\x74\x20\xF3\xAC\xD3\x11\x8C\xD1\x00\xC0\x4F\x8E\xDB\x8A", 16)) {
372 			if(fm->format_block) {
373 				if(error) *error = "invalid Wave64 file: multiple \"fmt \" chunks (005)";
374 				return false;
375 			}
376 			if(fm->audio_block) {
377 				if(error) *error = "invalid Wave64 file: \"data\" chunk before \"fmt \" chunk (006)";
378 				return false;
379 			}
380 			fm->format_block = fm->num_blocks;
381 		}
382 		/* data GUID 61746164-ACF3-11D3-8CD1-00C04F8EDB8A */
383 		else if(!memcmp(buffer, "\x64\x61\x74\x61\xF3\xAC\xD3\x11\x8C\xD1\x00\xC0\x4F\x8E\xDB\x8A", 16)) {
384 			if(fm->audio_block) {
385 				if(error) *error = "invalid Wave64 file: multiple \"data\" chunks (007)";
386 				return false;
387 			}
388 			if(!fm->format_block) {
389 				if(error) *error = "invalid Wave64 file: \"data\" chunk before \"fmt \" chunk (008)";
390 				return false;
391 			}
392 			fm->audio_block = fm->num_blocks;
393 		}
394 		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))
395 			return false;
396 		/* skip to next chunk */
397 		if(fseeko(f, size-24, SEEK_CUR) < 0) {
398 			if(error) *error = "invalid Wave64 file: seek error (009)";
399 			return false;
400 		}
401 	}
402 	if(eof_offset != ftello(f)) {
403 		if(error) *error = "invalid Wave64 file: unexpected EOF (010)";
404 		return false;
405 	}
406 	if(!fm->format_block) {
407 		if(error) *error = "invalid Wave64 file: missing \"fmt \" chunk (011)";
408 		return false;
409 	}
410 	if(!fm->audio_block) {
411 		if(error) *error = "invalid Wave64 file: missing \"data\" chunk (012)";
412 		return false;
413 	}
414 	return true;
415 }
416 
write_to_flac_(foreign_metadata_t * fm,FILE * fin,FILE * fout,FLAC__Metadata_SimpleIterator * it,const char ** error)417 static FLAC__bool write_to_flac_(foreign_metadata_t *fm, FILE *fin, FILE *fout, FLAC__Metadata_SimpleIterator *it, const char **error)
418 {
419 	FLAC__byte buffer[4];
420 	const uint32_t ID_LEN = FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8;
421 	size_t block_num = 0;
422 	FLAC__ASSERT(sizeof(buffer) >= ID_LEN);
423 	while(block_num < fm->num_blocks) {
424 		/* find next matching padding block */
425 		do {
426 			/* 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 */
427 			if(!FLAC__metadata_simple_iterator_next(it)) {
428 				if(error) *error = "no matching PADDING block found (004)";
429 				return false;
430 			}
431 		} while(FLAC__metadata_simple_iterator_get_block_type(it) != FLAC__METADATA_TYPE_PADDING);
432 		if(FLAC__metadata_simple_iterator_get_block_length(it) != ID_LEN+fm->blocks[block_num].size) {
433 			if(error) *error = "PADDING block with wrong size found (005)";
434 			return false;
435 		}
436 		/* transfer chunk into APPLICATION block */
437 		/* first set up the file pointers */
438 		if(fseeko(fin, fm->blocks[block_num].offset, SEEK_SET) < 0) {
439 			if(error) *error = "seek failed in WAVE/AIFF file (006)";
440 			return false;
441 		}
442 		if(fseeko(fout, FLAC__metadata_simple_iterator_get_block_offset(it), SEEK_SET) < 0) {
443 			if(error) *error = "seek failed in FLAC file (007)";
444 			return false;
445 		}
446 		/* update the type */
447 		buffer[0] = FLAC__METADATA_TYPE_APPLICATION;
448 		if(FLAC__metadata_simple_iterator_is_last(it))
449 			buffer[0] |= 0x80; /*MAGIC number*/
450 		if(fwrite(buffer, 1, 1, fout) < 1) {
451 			if(error) *error = "write failed in FLAC file (008)";
452 			return false;
453 		}
454 		/* length stays the same so skip over it */
455 		if(fseeko(fout, FLAC__STREAM_METADATA_LENGTH_LEN/8, SEEK_CUR) < 0) {
456 			if(error) *error = "seek failed in FLAC file (009)";
457 			return false;
458 		}
459 		/* write the APPLICATION ID */
460 		memcpy(buffer, FLAC__FOREIGN_METADATA_APPLICATION_ID[fm->type], ID_LEN);
461 		if(fwrite(buffer, 1, ID_LEN, fout) < ID_LEN) {
462 			if(error) *error = "write failed in FLAC file (010)";
463 			return false;
464 		}
465 		/* transfer the foreign metadata */
466 		if(!copy_data_(fin, fout, fm->blocks[block_num].size, error, "read failed in WAVE/AIFF file (011)", "write failed in FLAC file (012)"))
467 			return false;
468 		block_num++;
469 	}
470 	return true;
471 }
472 
read_from_flac_(foreign_metadata_t * fm,FILE * f,FLAC__Metadata_SimpleIterator * it,const char ** error)473 static FLAC__bool read_from_flac_(foreign_metadata_t *fm, FILE *f, FLAC__Metadata_SimpleIterator *it, const char **error)
474 {
475 	FLAC__byte id[4], buffer[12];
476 	FLAC__off_t offset;
477 	FLAC__bool type_found = false, ds64_found = false;
478 
479 	FLAC__ASSERT(FLAC__STREAM_METADATA_APPLICATION_ID_LEN == sizeof(id)*8);
480 
481 	while(FLAC__metadata_simple_iterator_next(it)) {
482 		if(FLAC__metadata_simple_iterator_get_block_type(it) != FLAC__METADATA_TYPE_APPLICATION)
483 			continue;
484 		if(!FLAC__metadata_simple_iterator_get_application_id(it, id)) {
485 			if(error) *error = "FLAC__metadata_simple_iterator_get_application_id() error (002)";
486 			return false;
487 		}
488 		if(memcmp(id, FLAC__FOREIGN_METADATA_APPLICATION_ID[fm->type], sizeof(id)))
489 			continue;
490 		offset = FLAC__metadata_simple_iterator_get_block_offset(it);
491 		/* skip over header and app ID */
492 		offset += (FLAC__STREAM_METADATA_IS_LAST_LEN + FLAC__STREAM_METADATA_TYPE_LEN + FLAC__STREAM_METADATA_LENGTH_LEN) / 8;
493 		offset += sizeof(id);
494 		/* look for format or audio blocks */
495 		if(fseeko(f, offset, SEEK_SET) < 0) {
496 			if(error) *error = "seek error (003)";
497 			return false;
498 		}
499 		if(fread(buffer, 1, 4, f) != 4) {
500 			if(error) *error = "read error (004)";
501 			return false;
502 		}
503 		if(fm->num_blocks == 0) { /* first block? */
504 			fm->is_rf64 = 0 == memcmp(buffer, "RF64", 4);
505 			if(fm->type == FOREIGN_BLOCK_TYPE__RIFF && (0 == memcmp(buffer, "RIFF", 4) || fm->is_rf64))
506 				type_found = true;
507 			else if(fm->type == FOREIGN_BLOCK_TYPE__WAVE64 && 0 == memcmp(buffer, "riff", 4)) /* use first 4 bytes instead of whole GUID */
508 				type_found = true;
509 			else if(fm->type == FOREIGN_BLOCK_TYPE__AIFF && 0 == memcmp(buffer, "FORM", 4))
510 				type_found = true;
511 			else {
512 				if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (005)";
513 				return false;
514 			}
515 		}
516 		else if(!type_found) {
517 			FLAC__ASSERT(0);
518 			/* double protection: */
519 			if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (006)";
520 			return false;
521 		}
522 		else if(fm->type == FOREIGN_BLOCK_TYPE__RIFF) {
523 			if(!memcmp(buffer, "fmt ", 4)) {
524 				if(fm->format_block) {
525 					if(error) *error = "invalid WAVE metadata: multiple \"fmt \" chunks (007)";
526 					return false;
527 				}
528 				if(fm->audio_block) {
529 					if(error) *error = "invalid WAVE metadata: \"data\" chunk before \"fmt \" chunk (008)";
530 					return false;
531 				}
532 				fm->format_block = fm->num_blocks;
533 			}
534 			else if(!memcmp(buffer, "data", 4)) {
535 				if(fm->audio_block) {
536 					if(error) *error = "invalid WAVE metadata: multiple \"data\" chunks (009)";
537 					return false;
538 				}
539 				if(!fm->format_block) {
540 					if(error) *error = "invalid WAVE metadata: \"data\" chunk before \"fmt \" chunk (010)";
541 					return false;
542 				}
543 				fm->audio_block = fm->num_blocks;
544 			}
545 			else if(fm->is_rf64 && fm->num_blocks == 1) {
546 				if(memcmp(buffer, "ds64", 4)) {
547 					if(error) *error = "invalid RF64 metadata: second chunk is not \"ds64\" (011)";
548 					return false;
549 				}
550 				ds64_found = true;
551 			}
552 		}
553 		else if(fm->type == FOREIGN_BLOCK_TYPE__WAVE64) {
554 			if(!memcmp(buffer, "fmt ", 4)) { /* use first 4 bytes instead of whole GUID */
555 				if(fm->format_block) {
556 					if(error) *error = "invalid Wave64 metadata: multiple \"fmt \" chunks (012)";
557 					return false;
558 				}
559 				if(fm->audio_block) {
560 					if(error) *error = "invalid Wave64 metadata: \"data\" chunk before \"fmt \" chunk (013)";
561 					return false;
562 				}
563 				fm->format_block = fm->num_blocks;
564 			}
565 			else if(!memcmp(buffer, "data", 4)) { /* use first 4 bytes instead of whole GUID */
566 				if(fm->audio_block) {
567 					if(error) *error = "invalid Wave64 metadata: multiple \"data\" chunks (014)";
568 					return false;
569 				}
570 				if(!fm->format_block) {
571 					if(error) *error = "invalid Wave64 metadata: \"data\" chunk before \"fmt \" chunk (015)";
572 					return false;
573 				}
574 				fm->audio_block = fm->num_blocks;
575 			}
576 		}
577 		else if(fm->type == FOREIGN_BLOCK_TYPE__AIFF) {
578 			if(!memcmp(buffer, "COMM", 4)) {
579 				if(fm->format_block) {
580 					if(error) *error = "invalid AIFF metadata: multiple \"COMM\" chunks (016)";
581 					return false;
582 				}
583 				if(fm->audio_block) {
584 					if(error) *error = "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (017)";
585 					return false;
586 				}
587 				fm->format_block = fm->num_blocks;
588 			}
589 			else if(!memcmp(buffer, "SSND", 4)) {
590 				if(fm->audio_block) {
591 					if(error) *error = "invalid AIFF metadata: multiple \"SSND\" chunks (018)";
592 					return false;
593 				}
594 				if(!fm->format_block) {
595 					if(error) *error = "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (019)";
596 					return false;
597 				}
598 				fm->audio_block = fm->num_blocks;
599 				/* read SSND offset size */
600 				if(fread(buffer+4, 1, 8, f) != 8) {
601 					if(error) *error = "read error (020)";
602 					return false;
603 				}
604 				fm->ssnd_offset_size = unpack32be_(buffer+8);
605 			}
606 		}
607 		else {
608 			FLAC__ASSERT(0);
609 			/* double protection: */
610 			if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (021)";
611 			return false;
612 		}
613 		if(!append_block_(fm, offset, FLAC__metadata_simple_iterator_get_block_length(it)-sizeof(id), error))
614 			return false;
615 	}
616 	if(!type_found) {
617 		if(error) *error = "no foreign metadata found (022)";
618 		return false;
619 	}
620 	if(fm->is_rf64 && !ds64_found) {
621 		if(error) *error = "invalid RF64 file: second chunk is not \"ds64\" (023)";
622 		return false;
623 	}
624 	if(!fm->format_block) {
625 		if(error)
626 			*error =
627 				fm->type==FOREIGN_BLOCK_TYPE__RIFF? "invalid WAVE file: missing \"fmt \" chunk (024)" :
628 				fm->type==FOREIGN_BLOCK_TYPE__WAVE64? "invalid Wave64 file: missing \"fmt \" chunk (025)" :
629 				"invalid AIFF file: missing \"COMM\" chunk (026)";
630 		return false;
631 	}
632 	if(!fm->audio_block) {
633 		if(error)
634 			*error =
635 				fm->type==FOREIGN_BLOCK_TYPE__RIFF? "invalid WAVE file: missing \"data\" chunk (027)" :
636 				fm->type==FOREIGN_BLOCK_TYPE__WAVE64? "invalid Wave64 file: missing \"data\" chunk (028)" :
637 				"invalid AIFF file: missing \"SSND\" chunk (029)";
638 		return false;
639 	}
640 	return true;
641 }
642 
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)643 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)
644 {
645 	size_t i;
646 	if(fseeko(fout, offset1, SEEK_SET) < 0) {
647 		if(error) *error = "seek failed in WAVE/AIFF file (002)";
648 		return false;
649 	}
650 	/* don't write first (RIFF/RF64/FORM) chunk, or ds64 chunk in the case of RF64 */
651 	for(i = fm->is_rf64?2:1; i < fm->format_block; i++) {
652 		if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) {
653 			if(error) *error = "seek failed in FLAC file (003)";
654 			return false;
655 		}
656 		if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in WAVE/AIFF file (004)", "write failed in FLAC file (005)"))
657 			return false;
658 	}
659 	if(fseeko(fout, offset2, SEEK_SET) < 0) {
660 		if(error) *error = "seek failed in WAVE/AIFF file (006)";
661 		return false;
662 	}
663 	for(i = fm->format_block+1; i < fm->audio_block; i++) {
664 		if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) {
665 			if(error) *error = "seek failed in FLAC file (007)";
666 			return false;
667 		}
668 		if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in WAVE/AIFF file (008)", "write failed in FLAC file (009)"))
669 			return false;
670 	}
671 	if(fseeko(fout, offset3, SEEK_SET) < 0) {
672 		if(error) *error = "seek failed in WAVE/AIFF file (010)";
673 		return false;
674 	}
675 	for(i = fm->audio_block+1; i < fm->num_blocks; i++) {
676 		if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) {
677 			if(error) *error = "seek failed in FLAC file (011)";
678 			return false;
679 		}
680 		if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in WAVE/AIFF file (012)", "write failed in FLAC file (013)"))
681 			return false;
682 	}
683 	return true;
684 }
685 
flac__foreign_metadata_new(foreign_block_type_t type)686 foreign_metadata_t *flac__foreign_metadata_new(foreign_block_type_t type)
687 {
688 	/* calloc() to zero all the member variables */
689 	foreign_metadata_t *x = calloc(sizeof(foreign_metadata_t), 1);
690 	if(x) {
691 		x->type = type;
692 		x->is_rf64 = false;
693 	}
694 	return x;
695 }
696 
flac__foreign_metadata_delete(foreign_metadata_t * fm)697 void flac__foreign_metadata_delete(foreign_metadata_t *fm)
698 {
699 	if(fm) {
700 		if(fm->blocks)
701 			free(fm->blocks);
702 		free(fm);
703 	}
704 }
705 
flac__foreign_metadata_read_from_aiff(foreign_metadata_t * fm,const char * filename,const char ** error)706 FLAC__bool flac__foreign_metadata_read_from_aiff(foreign_metadata_t *fm, const char *filename, const char **error)
707 {
708 	FLAC__bool ok;
709 	FILE *f = flac_fopen(filename, "rb");
710 	if(!f) {
711 		if(error) *error = "can't open AIFF file for reading (000)";
712 		return false;
713 	}
714 	ok = read_from_aiff_(fm, f, error);
715 	fclose(f);
716 	return ok;
717 }
718 
flac__foreign_metadata_read_from_wave(foreign_metadata_t * fm,const char * filename,const char ** error)719 FLAC__bool flac__foreign_metadata_read_from_wave(foreign_metadata_t *fm, const char *filename, const char **error)
720 {
721 	FLAC__bool ok;
722 	FILE *f = flac_fopen(filename, "rb");
723 	if(!f) {
724 		if(error) *error = "can't open WAVE file for reading (000)";
725 		return false;
726 	}
727 	ok = read_from_wave_(fm, f, error);
728 	fclose(f);
729 	return ok;
730 }
731 
flac__foreign_metadata_read_from_wave64(foreign_metadata_t * fm,const char * filename,const char ** error)732 FLAC__bool flac__foreign_metadata_read_from_wave64(foreign_metadata_t *fm, const char *filename, const char **error)
733 {
734 	FLAC__bool ok;
735 	FILE *f = flac_fopen(filename, "rb");
736 	if(!f) {
737 		if(error) *error = "can't open Wave64 file for reading (000)";
738 		return false;
739 	}
740 	ok = read_from_wave64_(fm, f, error);
741 	fclose(f);
742 	return ok;
743 }
744 
flac__foreign_metadata_write_to_flac(foreign_metadata_t * fm,const char * infilename,const char * outfilename,const char ** error)745 FLAC__bool flac__foreign_metadata_write_to_flac(foreign_metadata_t *fm, const char *infilename, const char *outfilename, const char **error)
746 {
747 	FLAC__bool ok;
748 	FILE *fin, *fout;
749 	FLAC__Metadata_SimpleIterator *it = FLAC__metadata_simple_iterator_new();
750 	if(!it) {
751 		if(error) *error = "out of memory (000)";
752 		return false;
753 	}
754 	if(!FLAC__metadata_simple_iterator_init(it, outfilename, /*read_only=*/true, /*preserve_file_stats=*/false)) {
755 		if(error) *error = "can't initialize iterator (001)";
756 		FLAC__metadata_simple_iterator_delete(it);
757 		return false;
758 	}
759 	if(0 == (fin = flac_fopen(infilename, "rb"))) {
760 		if(error) *error = "can't open WAVE/AIFF file for reading (002)";
761 		FLAC__metadata_simple_iterator_delete(it);
762 		return false;
763 	}
764 	if(0 == (fout = flac_fopen(outfilename, "r+b"))) {
765 		if(error) *error = "can't open FLAC file for updating (003)";
766 		FLAC__metadata_simple_iterator_delete(it);
767 		fclose(fin);
768 		return false;
769 	}
770 	ok = write_to_flac_(fm, fin, fout, it, error);
771 	FLAC__metadata_simple_iterator_delete(it);
772 	fclose(fin);
773 	fclose(fout);
774 	return ok;
775 }
776 
flac__foreign_metadata_read_from_flac(foreign_metadata_t * fm,const char * filename,const char ** error)777 FLAC__bool flac__foreign_metadata_read_from_flac(foreign_metadata_t *fm, const char *filename, const char **error)
778 {
779 	FLAC__bool ok;
780 	FILE *f;
781 	FLAC__Metadata_SimpleIterator *it = FLAC__metadata_simple_iterator_new();
782 	if(!it) {
783 		if(error) *error = "out of memory (000)";
784 		return false;
785 	}
786 	if(!FLAC__metadata_simple_iterator_init(it, filename, /*read_only=*/true, /*preserve_file_stats=*/false)) {
787 		if(error) *error = "can't initialize iterator (001)";
788 		FLAC__metadata_simple_iterator_delete(it);
789 		return false;
790 	}
791 	if(0 == (f = flac_fopen(filename, "rb"))) {
792 		if(error) *error = "can't open FLAC file for reading (002)";
793 		FLAC__metadata_simple_iterator_delete(it);
794 		return false;
795 	}
796 	ok = read_from_flac_(fm, f, it, error);
797 	FLAC__metadata_simple_iterator_delete(it);
798 	fclose(f);
799 	return ok;
800 }
801 
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)802 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)
803 {
804 	FLAC__bool ok;
805 	FILE *fin, *fout;
806 	if(0 == (fin = flac_fopen(infilename, "rb"))) {
807 		if(error) *error = "can't open FLAC file for reading (000)";
808 		return false;
809 	}
810 	if(0 == (fout = flac_fopen(outfilename, "r+b"))) {
811 		if(error) *error = "can't open WAVE/AIFF file for updating (001)";
812 		fclose(fin);
813 		return false;
814 	}
815 	ok = write_to_iff_(fm, fin, fout, offset1, offset2, offset3, error);
816 	fclose(fin);
817 	fclose(fout);
818 	return ok;
819 }
820