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