big fix to allow codec and metadata interface to handle unknown metadata block types correctly
diff --git a/src/libFLAC/metadata_iterators.c b/src/libFLAC/metadata_iterators.c
index e92ebb4..70d56b7 100644
--- a/src/libFLAC/metadata_iterators.c
+++ b/src/libFLAC/metadata_iterators.c
@@ -73,6 +73,7 @@
 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_(FILE *file, FLAC__StreamMetadata_VorbisComment *block);
 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_track_(FILE *file, FLAC__StreamMetadata_CueSheet_Track *track);
 static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_(FILE *file, FLAC__StreamMetadata_CueSheet *block);
+static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_unknown_(FILE *file, FLAC__StreamMetadata_Unknown *block, unsigned block_length);
 
 static FLAC__bool write_metadata_block_header_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block);
 static FLAC__bool write_metadata_block_data_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block);
@@ -82,6 +83,7 @@
 static FLAC__Metadata_SimpleIteratorStatus write_metadata_block_data_seektable_(FILE *file, const FLAC__StreamMetadata_SeekTable *block);
 static FLAC__Metadata_SimpleIteratorStatus write_metadata_block_data_vorbis_comment_(FILE *file, const FLAC__StreamMetadata_VorbisComment *block);
 static FLAC__Metadata_SimpleIteratorStatus write_metadata_block_data_cuesheet_(FILE *file, const FLAC__StreamMetadata_CueSheet *block);
+static FLAC__Metadata_SimpleIteratorStatus write_metadata_block_data_unknown_(FILE *file, const FLAC__StreamMetadata_Unknown *block, unsigned block_length);
 static FLAC__bool write_metadata_block_stationary_(FLAC__Metadata_SimpleIterator *iterator, const FLAC__StreamMetadata *block);
 static FLAC__bool write_metadata_block_stationary_with_padding_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, unsigned padding_length, FLAC__bool padding_is_last);
 static FLAC__bool rewrite_whole_file_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool append);
@@ -1350,11 +1352,10 @@
 	iterator->type = (FLAC__MetadataType)(raw_header[0] & 0x7f);
 	iterator->length = unpack_uint32_(raw_header + 1, 3);
 
-	/* do some checking */
-	if(iterator->type >= FLAC__METADATA_TYPE_UNDEFINED) {
-		iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA;
-		return false;
-	}
+	/* Note that we don't check:
+	 *    if(iterator->type >= FLAC__METADATA_TYPE_UNDEFINED)
+	 * we just will read in an opaque block
+	 */
 
 	return true;
 }
@@ -1384,8 +1385,8 @@
 			iterator->status = read_metadata_block_data_cuesheet_(iterator->file, &block->data.cue_sheet);
 			break;
 		default:
-			FLAC__ASSERT(0);
-			iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR;
+			iterator->status = read_metadata_block_data_unknown_(iterator->file, &block->data.unknown, block->length);
+			break;
 	}
 
 	return (iterator->status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK);
@@ -1662,6 +1663,24 @@
 	return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
 }
 
+FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_unknown_(FILE *file, FLAC__StreamMetadata_Unknown *block, unsigned block_length)
+{
+	FLAC__ASSERT(0 != file);
+
+	if(block_length == 0) {
+		block->data = 0;
+	}
+	else {
+		if(0 == (block->data = (FLAC__byte*)malloc(block_length)))
+			return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
+
+		if(fread(block->data, 1, block_length, file) != block_length)
+			return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
+	}
+
+	return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
+}
+
 FLAC__bool write_metadata_block_header_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block)
 {
 	FLAC__byte buffer[FLAC__STREAM_METADATA_HEADER_LENGTH];
@@ -1706,8 +1725,8 @@
 			*status = write_metadata_block_data_cuesheet_(file, &block->data.cue_sheet);
 			break;
 		default:
-			FLAC__ASSERT(0);
-			*status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR;
+			*status = write_metadata_block_data_unknown_(file, &block->data.unknown, block->length);
+			break;
 	}
 	return (*status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK);
 }
@@ -1927,6 +1946,16 @@
 	return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
 }
 
+FLAC__Metadata_SimpleIteratorStatus write_metadata_block_data_unknown_(FILE *file, const FLAC__StreamMetadata_Unknown *block, unsigned block_length)
+{
+	FLAC__ASSERT(0 != file);
+
+	if(local__fwrite(block->data, 1, block_length, file) != block_length)
+		return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR;
+
+	return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
+}
+
 FLAC__bool write_metadata_block_stationary_(FLAC__Metadata_SimpleIterator *iterator, const FLAC__StreamMetadata *block)
 {
 	if(0 != fseek(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) {
diff --git a/src/libFLAC/metadata_object.c b/src/libFLAC/metadata_object.c
index c6de62b..8bf1dd5 100644
--- a/src/libFLAC/metadata_object.c
+++ b/src/libFLAC/metadata_object.c
@@ -332,11 +332,22 @@
 				object->length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
 				break;
 			case FLAC__METADATA_TYPE_PADDING:
+				/* calloc() took care of this for us:
+				object->length = 0;
+				*/
 				break;
 			case FLAC__METADATA_TYPE_APPLICATION:
 				object->length = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8;
+				/* calloc() took care of this for us:
+				object->data.application.data = 0;
+				*/
 				break;
 			case FLAC__METADATA_TYPE_SEEKTABLE:
+				/* calloc() took care of this for us:
+				object->length = 0;
+				object->data.seek_table.num_points = 0;
+				object->data.seek_table.points = 0;
+				*/
 				break;
 			case FLAC__METADATA_TYPE_VORBIS_COMMENT:
 				{
@@ -352,10 +363,11 @@
 				cuesheet_calculate_length_(object);
 				break;
 			default:
-				/* double protection: */
-				FLAC__ASSERT(0);
-				free(object);
-				return 0;
+				/* calloc() took care of this for us:
+				object->length = 0;
+				object->data.unknown.data = 0;
+				*/
+				break;
 		}
 	}
 
@@ -430,10 +442,11 @@
 				}
 				break;
 			default:
-				/* double protection: */
-				FLAC__ASSERT(0);
-				free(to);
-				return 0;
+				if(!copy_bytes_(&to->data.unknown.data, object->data.unknown.data, object->length)) {
+					FLAC__metadata_object_delete(to);
+					return 0;
+				}
+				break;
 		}
 	}
 
@@ -477,7 +490,11 @@
 			}
 			break;
 		default:
-			FLAC__ASSERT(0);
+			if(0 != object->data.unknown.data) {
+				free(object->data.unknown.data);
+				object->data.unknown.data = 0;
+			}
+			break;
 	}
 }
 
@@ -626,6 +643,17 @@
 	return true;
 }
 
+static FLAC__bool compare_block_data_unknown_(const FLAC__StreamMetadata_Unknown *block1, const FLAC__StreamMetadata_Unknown *block2, unsigned block_length)
+{
+	FLAC__ASSERT(0 != block1);
+	FLAC__ASSERT(0 != block2);
+
+	if(0 != block1->data && 0 != block2->data)
+		return 0 == memcmp(block1->data, block2->data, block_length);
+	else
+		return block1->data == block2->data;
+}
+
 FLAC_API FLAC__bool FLAC__metadata_object_is_equal(const FLAC__StreamMetadata *block1, const FLAC__StreamMetadata *block2)
 {
 	FLAC__ASSERT(0 != block1);
@@ -654,8 +682,7 @@
 		case FLAC__METADATA_TYPE_CUESHEET:
 			return compare_block_data_cuesheet_(&block1->data.cue_sheet, &block2->data.cue_sheet);
 		default:
-			FLAC__ASSERT(0);
-			return false;
+			return compare_block_data_unknown_(&block1->data.unknown, &block2->data.unknown, block1->length);
 	}
 }
 
diff --git a/src/libFLAC/stream_decoder.c b/src/libFLAC/stream_decoder.c
index 61a6d22..882bf96 100644
--- a/src/libFLAC/stream_decoder.c
+++ b/src/libFLAC/stream_decoder.c
@@ -100,7 +100,7 @@
 	FLAC__bool has_stream_info, has_seek_table;
 	FLAC__StreamMetadata stream_info;
 	FLAC__StreamMetadata seek_table;
-	FLAC__bool metadata_filter[FLAC__METADATA_TYPE_UNDEFINED];
+	FLAC__bool metadata_filter[128]; /* MAGIC number 128 == total number of metadata block types == 1 << 7 */
 	FLAC__byte *metadata_filter_ids;
 	unsigned metadata_filter_ids_count, metadata_filter_ids_capacity; /* units for both are IDs, not bytes */
 	FLAC__Frame frame;
@@ -390,7 +390,10 @@
 	FLAC__ASSERT(0 != decoder);
 	FLAC__ASSERT(0 != decoder->private_);
 	FLAC__ASSERT(0 != decoder->protected_);
-	FLAC__ASSERT(type < FLAC__METADATA_TYPE_UNDEFINED);
+	FLAC__ASSERT(type < (1u << FLAC__STREAM_METADATA_TYPE_LEN));
+	/* double protection */
+	if(type >= (1u << FLAC__STREAM_METADATA_TYPE_LEN))
+		return false;
 	if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
 		return false;
 	decoder->private_->metadata_filter[type] = true;
@@ -444,7 +447,10 @@
 	FLAC__ASSERT(0 != decoder);
 	FLAC__ASSERT(0 != decoder->private_);
 	FLAC__ASSERT(0 != decoder->protected_);
-	FLAC__ASSERT(type < FLAC__METADATA_TYPE_UNDEFINED);
+	FLAC__ASSERT(type < (1u << FLAC__STREAM_METADATA_TYPE_LEN));
+	/* double protection */
+	if(type >= (1u << FLAC__STREAM_METADATA_TYPE_LEN))
+		return false;
 	if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
 		return false;
 	decoder->private_->metadata_filter[type] = false;
@@ -904,8 +910,20 @@
 					break;
 				case FLAC__METADATA_TYPE_STREAMINFO:
 				case FLAC__METADATA_TYPE_SEEKTABLE:
+					assert(0);
+					break;
 				default:
-					FLAC__ASSERT(0);
+					if(real_length > 0) {
+						if(0 == (block.data.unknown.data = (FLAC__byte*)malloc(real_length))) {
+							decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
+							return false;
+						}
+						if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.unknown.data, real_length, read_callback_, decoder))
+							return false; /* the read_callback_ sets the state for us */
+					}
+					else
+						block.data.unknown.data = 0;
+					break;
 			}
 			decoder->private_->metadata_callback(decoder, &block, decoder->private_->client_data);
 
@@ -937,8 +955,11 @@
 					break;
 				case FLAC__METADATA_TYPE_STREAMINFO:
 				case FLAC__METADATA_TYPE_SEEKTABLE:
-				default:
 					FLAC__ASSERT(0);
+				default:
+					if(0 != block.data.unknown.data)
+						free(block.data.unknown.data);
+					break;
 			}
 		}
 	}
diff --git a/src/libFLAC/stream_encoder.c b/src/libFLAC/stream_encoder.c
index bf8e60c..f8edc58 100644
--- a/src/libFLAC/stream_encoder.c
+++ b/src/libFLAC/stream_encoder.c
@@ -663,9 +663,7 @@
 	metadata_has_seektable = false;
 	metadata_has_vorbis_comment = false;
 	for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) {
-		if(encoder->protected_->metadata[i]->type >= FLAC__METADATA_TYPE_UNDEFINED)
-			return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
-		else if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_STREAMINFO)
+		if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_STREAMINFO)
 			return encoder->protected_->state = FLAC__STREAM_ENCODER_INVALID_METADATA;
 		else if(encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_SEEKTABLE) {
 			if(metadata_has_seektable) /* only one is allowed */
diff --git a/src/libFLAC/stream_encoder_framing.c b/src/libFLAC/stream_encoder_framing.c
index 6ff9631..f9e7ca6 100644
--- a/src/libFLAC/stream_encoder_framing.c
+++ b/src/libFLAC/stream_encoder_framing.c
@@ -162,7 +162,9 @@
 			}
 			break;
 		default:
-			FLAC__ASSERT(0);
+			if(!FLAC__bitbuffer_write_byte_block(bb, metadata->data.unknown.data, metadata->length))
+				return false;
+			break;
 	}
 
 	FLAC__ASSERT(FLAC__bitbuffer_is_byte_aligned(bb));
diff --git a/src/metaflac/operations.c b/src/metaflac/operations.c
index 592526f..50b9e39 100644
--- a/src/metaflac/operations.c
+++ b/src/metaflac/operations.c
@@ -623,7 +623,9 @@
 			}
 			break;
 		default:
-			PPR; printf("SKIPPING block of unknown type\n");
+			PPR; printf("  data contents:\n");
+			if(0 != block->data.unknown.data)
+				hexdump(filename, block->data.unknown.data, block->length, "    ");
 			break;
 	}
 #undef PPR