From 61e74c29645459c59b29fa8c8efdeb5faeab8b95 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Thu, 12 Aug 2021 19:32:51 +0200 Subject: [PATCH] mp4: Simplify parse_tag(). paraslash fundamentally cares only about five metatags. So remove all code from parse_tag() which handles the tags we don't care about. --- mp4.c | 141 ++++++++++------------------------------------------------ 1 file changed, 23 insertions(+), 118 deletions(-) diff --git a/mp4.c b/mp4.c index c97fa477..deb05747 100644 --- a/mp4.c +++ b/mp4.c @@ -97,7 +97,6 @@ static bool atom_compare(int8_t a1, int8_t b1, int8_t c1, int8_t d1, { return a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2; } - enum atoms { /* atoms with subatoms */ ATOM_MOOV = 1, @@ -648,15 +647,6 @@ static const char *ID3v1GenreList[] = { "Anime", "JPop", "SynthPop", }; -static const char *meta_index_to_genre(uint32_t idx) -{ - if (idx > 0 && idx <= sizeof (ID3v1GenreList) / sizeof (ID3v1GenreList[0])) { - return ID3v1GenreList[idx - 1]; - } else { - return 0; - } -} - static char *read_string(struct mp4 *f, uint32_t length) { char *str = para_malloc(length + 1); @@ -673,69 +663,18 @@ static const char *get_metadata_name(uint8_t atom_type) switch (atom_type) { case ATOM_TITLE: return "title"; case ATOM_ARTIST: return "artist"; - case ATOM_WRITER: return "writer"; case ATOM_ALBUM: return "album"; case ATOM_DATE: return "date"; - case ATOM_TOOL: return "tool"; case ATOM_COMMENT: return "comment"; - case ATOM_GENRE1: return "genre"; - case ATOM_TRACK: return "track"; - case ATOM_DISC: return "disc"; - case ATOM_COMPILATION: return "compilation"; - case ATOM_GENRE2: return "genre"; - case ATOM_TEMPO: return "tempo"; - case ATOM_COVER: return "cover"; - case ATOM_ALBUM_ARTIST: return "album_artist"; - case ATOM_CONTENTGROUP: return "contentgroup"; - case ATOM_LYRICS: return "lyrics"; - case ATOM_DESCRIPTION: return "description"; - case ATOM_NETWORK: return "network"; - case ATOM_SHOW: return "show"; - case ATOM_EPISODENAME: return "episodename"; - case ATOM_SORTTITLE: return "sorttitle"; - case ATOM_SORTALBUM: return "sortalbum"; - case ATOM_SORTARTIST: return "sortartist"; - case ATOM_SORTALBUMARTIST: return "sortalbumartist"; - case ATOM_SORTWRITER: return "sortwriter"; - case ATOM_SORTSHOW: return "sortshow"; - case ATOM_SEASON: return "season"; - case ATOM_EPISODE: return "episode"; - case ATOM_PODCAST: return "podcast"; default: return "unknown"; } } -static uint32_t min_body_size(uint8_t atom_type) -{ - switch(atom_type) { - case ATOM_GENRE2: - case ATOM_TEMPO: - return 10; - case ATOM_TRACK: - return sizeof (char) /* version */ - + sizeof(uint8_t) * 3 /* flags */ - + sizeof(uint32_t) /* reserved */ - + sizeof(uint16_t) /* leading uint16_t */ - + sizeof(uint16_t) /* track */ - + sizeof(uint16_t); /* totaltracks */ - case ATOM_DISC: - return sizeof (char) /* version */ - + sizeof(uint8_t) * 3 /* flags */ - + sizeof(uint32_t) /* reserved */ - + sizeof(uint16_t) /* disc */ - + sizeof(uint16_t); /* totaldiscs */ - default: assert(false); - } -} - -static int32_t parse_tag(struct mp4 *f, uint8_t parent, int32_t size) +static void parse_tag(struct mp4 *f, uint8_t parent, int32_t size) { - uint8_t atom_type; - uint8_t header_size = 0; uint64_t subsize, sumsize; char *name = NULL; char *data = NULL; - uint32_t done = 0; uint32_t len = 0; uint64_t destpos; @@ -744,10 +683,10 @@ static int32_t parse_tag(struct mp4 *f, uint8_t parent, int32_t size) sumsize < size && !f->read_error; /* CVE-2017-9222 */ set_position(f, destpos), sumsize += subsize ) { + uint8_t atom_type; + uint8_t header_size = 0; subsize = atom_read_header(f, &atom_type, &header_size); destpos = get_position(f) + subsize - header_size; - if (done) - continue; if (atom_type == ATOM_NAME) { read_char(f); /* version */ read_int24(f); /* flags */ @@ -760,61 +699,17 @@ static int32_t parse_tag(struct mp4 *f, uint8_t parent, int32_t size) read_char(f); /* version */ read_int24(f); /* flags */ read_int32(f); /* reserved */ - - /* some need special attention */ - if (parent == ATOM_GENRE2 || parent == ATOM_TEMPO) { - uint16_t val; - if (subsize - header_size < min_body_size(parent)) - continue; - val = read_int16(f); - if (parent == ATOM_TEMPO) { - char temp[16]; - sprintf(temp, "%.5u BPM", val); - tag_add_field(&(f-> tags), "tempo", - temp, -1); - } else { - const char *tmp = meta_index_to_genre(val); - if (tmp) - tag_add_field (&(f->tags), - "genre", tmp, -1); - } - done = 1; - } else if (parent == ATOM_TRACK || parent == ATOM_DISC) { - uint16_t index, total; - char temp[32]; - if (subsize - header_size < min_body_size(parent)) - continue; - read_int16(f); - index = read_int16(f); - total = read_int16(f); - if (parent == ATOM_TRACK) - read_int16(f); - sprintf(temp, "%d", index); - tag_add_field(&(f->tags), parent == ATOM_TRACK? - "track" : "disc", temp, -1); - if (total > 0) { - sprintf(temp, "%d", total); - tag_add_field(& (f-> tags), - parent == ATOM_TRACK? - "totaltracks" : "totaldiscs", temp, -1); - } - done = 1; - } else { - free(data); - data = read_string(f, subsize - (header_size + 8)); - len = subsize - (header_size + 8); - } + free(data); + data = read_string(f, subsize - (header_size + 8)); + len = subsize - (header_size + 8); } if (data) { - if (!done) { - if (!name) - name = para_strdup(get_metadata_name(parent)); - tag_add_field(&(f->tags), name, data, len); - } + if (!name) + name = para_strdup(get_metadata_name(parent)); + tag_add_field(&(f->tags), name, data, len); free(data); } free(name); - return 1; } static int32_t read_mdhd(struct mp4 *f) @@ -850,15 +745,25 @@ static int32_t read_mdhd(struct mp4 *f) static int32_t parse_metadata(struct mp4 *f, int32_t size) { - uint64_t subsize, sumsize = 0; - uint8_t atom_type; - uint8_t header_size = 0; + uint64_t sumsize = 0; while (sumsize < size) { + uint8_t atom_type; + uint64_t subsize, destpos; + uint8_t header_size = 0; subsize = atom_read_header(f, &atom_type, &header_size); if (subsize == 0) break; - parse_tag(f, atom_type, (uint32_t)(subsize - header_size)); + destpos = get_position(f) + subsize - header_size; + switch (atom_type) { + case ATOM_ARTIST: + case ATOM_TITLE: + case ATOM_ALBUM: + case ATOM_COMMENT: + case ATOM_DATE: + parse_tag(f, atom_type, subsize - header_size); + } + set_position(f, destpos); sumsize += subsize; } -- 2.39.5