/* * Read an EBML header. */ char *ebml_read_header(stream_t *s, int *version) { uint64_t length, l, num; uint32_t id; char *str = NULL; if (ebml_read_master(s, &length) != EBML_ID_HEADER) return 0; if (version) *version = 1; while (length > 0) { id = ebml_read_id(s, NULL); if (id == EBML_ID_INVALID) return NULL; length -= 2; switch (id) { /* is our read version uptodate? */ case EBML_ID_EBMLREADVERSION: num = ebml_read_uint(s, &l); if (num != EBML_VERSION) return NULL; break; /* we only handle 8 byte lengths at max */ case EBML_ID_EBMLMAXSIZELENGTH: num = ebml_read_uint(s, &l); if (num != sizeof(uint64_t)) return NULL; break; /* we handle 4 byte IDs at max */ case EBML_ID_EBMLMAXIDLENGTH: num = ebml_read_uint(s, &l); if (num != sizeof(uint32_t)) return NULL; break; case EBML_ID_DOCTYPE: str = ebml_read_ascii(s, &l); if (str == NULL) return NULL; break; case EBML_ID_DOCTYPEREADVERSION: num = ebml_read_uint(s, &l); if (num == EBML_UINT_INVALID) return NULL; if (version) *version = num; break; /* we ignore these two, they don't tell us anything we care about */ case EBML_ID_VOID: case EBML_ID_EBMLVERSION: case EBML_ID_DOCTYPEVERSION: default: if (ebml_read_skip(s, &l)) return NULL; break; } length -= l; } return str; }
int ebml_check_header(ebml_parser_t *ebml) { uint32_t next_level; ebml_elem_t master; if (!ebml_read_elem_head(ebml, &master)) { xprintf(ebml->xine, XINE_VERBOSITY_LOG, "ebml: invalid master element\n"); return 0; } if (master.id != EBML_ID_EBML) { xprintf(ebml->xine, XINE_VERBOSITY_LOG, "ebml: invalid master element\n"); return 0; } if (!ebml_read_master (ebml, &master)) return 0; next_level = 1; while (next_level == 1) { ebml_elem_t elem; if (!ebml_read_elem_head(ebml, &elem)) return 0; switch (elem.id) { case EBML_ID_EBMLVERSION: { uint64_t num; if (!ebml_read_uint (ebml, &elem, &num)) return 0; lprintf("ebml_version: %" PRIu64 "\n", num); ebml->version = num; break; } case EBML_ID_EBMLREADVERSION: { uint64_t num; if (!ebml_read_uint (ebml, &elem, &num)) return 0; lprintf("ebml_read_version: %" PRIu64 "\n", num); if (num != EBML_VERSION) return 0; ebml->read_version = num; break; } case EBML_ID_EBMLMAXIDLENGTH: { uint64_t num; if (!ebml_read_uint (ebml, &elem, &num)) return 0; lprintf("ebml_max_id_length: %" PRIu64 "\n", num); ebml->max_id_len = num; break; } case EBML_ID_EBMLMAXSIZELENGTH: { uint64_t num; if (!ebml_read_uint (ebml, &elem, &num)) return 0; lprintf("ebml_max_size_length: %" PRIu64 "\n", num); ebml->max_size_len = num; break; } case EBML_ID_DOCTYPE: { char *text = ebml_alloc_read_ascii (ebml, &elem); if (!text) return 0; lprintf("doctype: %s\n", text); if (ebml->doctype) free (ebml->doctype); ebml->doctype = text; break; } case EBML_ID_DOCTYPEVERSION: { uint64_t num; if (!ebml_read_uint (ebml, &elem, &num)) return 0; lprintf("doctype_version: %" PRIu64 "\n", num); ebml->doctype_version = num; break; } case EBML_ID_DOCTYPEREADVERSION: { uint64_t num; if (!ebml_read_uint (ebml, &elem, &num)) return 0; lprintf("doctype_read_version: %" PRIu64 "\n", num); ebml->doctype_read_version = num; break; } default: xprintf(ebml->xine, XINE_VERBOSITY_LOG, "ebml: Unknown data type 0x%x in EBML header (ignored)\n", elem.id); ebml_skip(ebml, &elem); } next_level = ebml_get_next_level(ebml, &elem); } return 1; }