From 21aa7d929dca6a8490dc3b8963b9dfdd8d06a300 Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Sat, 3 Jun 2023 10:07:32 -0400 Subject: [PATCH] ID3v2: Pass parsing mode to frame parsing --- src/aac/read.rs | 2 +- src/ape/read.rs | 2 +- src/flac/read.rs | 2 +- src/id3/v2/frame/content.rs | 2 ++ src/id3/v2/frame/read.rs | 18 ++++++++++++------ src/id3/v2/read.rs | 22 ++++++++++++++++------ src/id3/v2/tag.rs | 14 +++++++++----- src/iff/aiff/read.rs | 2 +- src/iff/chunk.rs | 5 +++-- src/iff/wav/read.rs | 2 +- src/mpeg/read.rs | 2 +- 11 files changed, 48 insertions(+), 25 deletions(-) diff --git a/src/aac/read.rs b/src/aac/read.rs index 21a35e28..07955899 100644 --- a/src/aac/read.rs +++ b/src/aac/read.rs @@ -48,7 +48,7 @@ where stream_len -= u64::from(header.size); - let id3v2 = parse_id3v2(reader, header)?; + let id3v2 = parse_id3v2(reader, header, parse_mode)?; if let Some(existing_tag) = &mut file.id3v2_tag { // https://github.com/Serial-ATA/lofty-rs/issues/87 // Duplicate tags should have their frames appended to the previous diff --git a/src/ape/read.rs b/src/ape/read.rs index 7a23225b..dd8cb25e 100644 --- a/src/ape/read.rs +++ b/src/ape/read.rs @@ -40,7 +40,7 @@ where let reader = &mut &*content; - let id3v2 = parse_id3v2(reader, header)?; + let id3v2 = parse_id3v2(reader, header, parse_options.parsing_mode)?; id3v2_tag = Some(id3v2); } diff --git a/src/flac/read.rs b/src/flac/read.rs index b3f378d3..4c350332 100644 --- a/src/flac/read.rs +++ b/src/flac/read.rs @@ -51,7 +51,7 @@ where if let ID3FindResults(Some(header), Some(content)) = find_id3v2(data, true)? { let reader = &mut &*content; - let id3v2 = parse_id3v2(reader, header)?; + let id3v2 = parse_id3v2(reader, header, parse_options.parsing_mode)?; flac_file.id3v2_tag = Some(id3v2); } diff --git a/src/id3/v2/frame/content.rs b/src/id3/v2/frame/content.rs index aa4f8ba0..ebfb15fe 100644 --- a/src/id3/v2/frame/content.rs +++ b/src/id3/v2/frame/content.rs @@ -6,6 +6,7 @@ use crate::id3::v2::items::{ }; use crate::id3::v2::Id3v2Version; use crate::macros::err; +use crate::probe::ParsingMode; use crate::util::text::TextEncoding; use std::io::Read; @@ -15,6 +16,7 @@ pub(super) fn parse_content( reader: &mut R, id: &str, version: Id3v2Version, + parse_mode: ParsingMode, ) -> Result> { Ok(match id { // The ID was previously upgraded, but the content remains unchanged, so version is necessary diff --git a/src/id3/v2/frame/read.rs b/src/id3/v2/frame/read.rs index 0a1da4e1..17569f93 100644 --- a/src/id3/v2/frame/read.rs +++ b/src/id3/v2/frame/read.rs @@ -5,13 +5,18 @@ use crate::id3::v2::frame::content::parse_content; use crate::id3::v2::util::synchsafe::{SynchsafeInteger, UnsynchronizedStream}; use crate::id3::v2::{FrameFlags, FrameId, FrameValue, Id3v2Version}; use crate::macros::try_vec; +use crate::probe::ParsingMode; use std::io::Read; use byteorder::{BigEndian, ReadBytesExt}; impl<'a> Frame<'a> { - pub(crate) fn read(reader: &mut R, version: Id3v2Version) -> Result<(Option, bool)> + pub(crate) fn read( + reader: &mut R, + version: Id3v2Version, + parse_mode: ParsingMode, + ) -> Result<(Option, bool)> where R: Read, { @@ -91,14 +96,14 @@ impl<'a> Frame<'a> { return handle_encryption(&mut compression_reader, size, id, flags); } - return parse_frame(&mut compression_reader, id, flags, version); + return parse_frame(&mut compression_reader, id, flags, version, parse_mode); } if flags.encryption.is_some() { return handle_encryption(&mut unsynchronized_reader, size, id, flags); } - return parse_frame(&mut unsynchronized_reader, id, flags, version); + return parse_frame(&mut unsynchronized_reader, id, flags, version, parse_mode); }, // Possible combinations: // @@ -113,7 +118,7 @@ impl<'a> Frame<'a> { return handle_encryption(&mut compression_reader, size, id, flags); } - return parse_frame(&mut compression_reader, id, flags, version); + return parse_frame(&mut compression_reader, id, flags, version, parse_mode); }, // Possible combinations: // @@ -126,7 +131,7 @@ impl<'a> Frame<'a> { }, // Everything else that doesn't have special flags _ => { - return parse_frame(&mut reader, id, flags, version); + return parse_frame(&mut reader, id, flags, version, parse_mode); }, } } @@ -172,8 +177,9 @@ fn parse_frame( id: FrameId<'static>, flags: FrameFlags, version: Id3v2Version, + parse_mode: ParsingMode, ) -> Result<(Option>, bool)> { - match parse_content(reader, id.as_str(), version)? { + match parse_content(reader, id.as_str(), version, parse_mode)? { Some(value) => Ok((Some(Frame { id, value, flags }), false)), None => Ok((None, false)), } diff --git a/src/id3/v2/read.rs b/src/id3/v2/read.rs index 2bc81698..7253473e 100644 --- a/src/id3/v2/read.rs +++ b/src/id3/v2/read.rs @@ -3,10 +3,15 @@ use super::tag::Id3v2Tag; use super::Id3v2Header; use crate::error::Result; use crate::id3::v2::util::synchsafe::UnsynchronizedStream; +use crate::probe::ParsingMode; use std::io::Read; -pub(crate) fn parse_id3v2(bytes: &mut R, header: Id3v2Header) -> Result +pub(crate) fn parse_id3v2( + bytes: &mut R, + header: Id3v2Header, + parse_mode: ParsingMode, +) -> Result where R: Read, { @@ -16,12 +21,12 @@ where if header.flags.unsynchronisation { // Unsynchronize the entire tag let mut unsyncronized_reader = UnsynchronizedStream::new(tag_bytes); - ret = read_all_frames_into_tag(&mut unsyncronized_reader, header)?; + ret = read_all_frames_into_tag(&mut unsyncronized_reader, header, parse_mode)?; // Get the `Take` back from the `UnsynchronizedStream` tag_bytes = unsyncronized_reader.into_inner(); } else { - ret = read_all_frames_into_tag(&mut tag_bytes, header)?; + ret = read_all_frames_into_tag(&mut tag_bytes, header, parse_mode)?; }; // Throw away the rest of the tag (padding, bad frames) @@ -29,7 +34,11 @@ where Ok(ret) } -fn read_all_frames_into_tag(reader: &mut R, header: Id3v2Header) -> Result +fn read_all_frames_into_tag( + reader: &mut R, + header: Id3v2Header, + parse_mode: ParsingMode, +) -> Result where R: Read, { @@ -38,7 +47,7 @@ where tag.set_flags(header.flags); loop { - match Frame::read(reader, header.version)? { + match Frame::read(reader, header.version, parse_mode)? { // No frame content found, and we can expect there are no more frames (None, true) => break, (Some(f), false) => drop(tag.insert(f)), @@ -53,9 +62,10 @@ where #[test] fn zero_size_id3v2() { use crate::id3::v2::read_id3v2_header; + use crate::ParsingMode; use std::io::Cursor; let mut f = Cursor::new(std::fs::read("tests/tags/assets/id3v2/zero.id3v2").unwrap()); let header = read_id3v2_header(&mut f).unwrap(); - assert!(parse_id3v2(&mut f, header).is_ok()); + assert!(parse_id3v2(&mut f, header, ParsingMode::Strict).is_ok()); } diff --git a/src/id3/v2/tag.rs b/src/id3/v2/tag.rs index c62078be..9f4afb44 100644 --- a/src/id3/v2/tag.rs +++ b/src/id3/v2/tag.rs @@ -1068,6 +1068,7 @@ impl<'a, I: Iterator> + Clone + 'a> Id3v2TagRef<'a, I> { #[cfg(test)] mod tests { + use crate::ParsingMode; use std::borrow::Cow; use crate::id3::v2::frame::MUSICBRAINZ_UFID_OWNER; @@ -1095,7 +1096,7 @@ mod tests { let mut reader = std::io::Cursor::new(&tag_bytes[..]); let header = read_id3v2_header(&mut reader).unwrap(); - crate::id3::v2::read::parse_id3v2(&mut reader, header).unwrap() + crate::id3::v2::read::parse_id3v2(&mut reader, header, ParsingMode::Strict).unwrap() } #[test] @@ -1206,7 +1207,9 @@ mod tests { let temp_reader = &mut &*writer; let temp_header = read_id3v2_header(temp_reader).unwrap(); - let temp_parsed_tag = crate::id3::v2::read::parse_id3v2(temp_reader, temp_header).unwrap(); + let temp_parsed_tag = + crate::id3::v2::read::parse_id3v2(temp_reader, temp_header, ParsingMode::Strict) + .unwrap(); assert_eq!(parsed_tag, temp_parsed_tag); } @@ -1456,7 +1459,7 @@ mod tests { let mut reader = &mut &writer[..]; let header = read_id3v2_header(&mut reader).unwrap(); - assert!(crate::id3::v2::read::parse_id3v2(reader, header).is_ok()); + assert!(crate::id3::v2::read::parse_id3v2(reader, header, ParsingMode::Strict).is_ok()); assert_eq!(writer[3..10], writer[writer.len() - 7..]) } @@ -1481,7 +1484,7 @@ mod tests { let mut reader = &mut &writer[..]; let header = read_id3v2_header(&mut reader).unwrap(); - let tag = crate::id3::v2::read::parse_id3v2(reader, header).unwrap(); + let tag = crate::id3::v2::read::parse_id3v2(reader, header, ParsingMode::Strict).unwrap(); assert_eq!(tag.len(), 1); assert_eq!( @@ -1798,7 +1801,8 @@ mod tests { let mut reader = std::io::Cursor::new(&content[..]); let header = read_id3v2_header(&mut reader).unwrap(); - let reparsed = crate::id3::v2::read::parse_id3v2(&mut reader, header).unwrap(); + let reparsed = + crate::id3::v2::read::parse_id3v2(&mut reader, header, ParsingMode::Strict).unwrap(); assert_eq!(id3v2, reparsed); } diff --git a/src/iff/aiff/read.rs b/src/iff/aiff/read.rs index cd0b6abf..c231023e 100644 --- a/src/iff/aiff/read.rs +++ b/src/iff/aiff/read.rs @@ -52,7 +52,7 @@ where while chunks.next(data).is_ok() { match &chunks.fourcc { b"ID3 " | b"id3 " => { - let tag = chunks.id3_chunk(data)?; + let tag = chunks.id3_chunk(data, parse_options.parsing_mode)?; if let Some(existing_tag) = id3v2_tag.as_mut() { // https://github.com/Serial-ATA/lofty-rs/issues/87 // Duplicate tags should have their frames appended to the previous diff --git a/src/iff/chunk.rs b/src/iff/chunk.rs index e8d9406a..2045864d 100644 --- a/src/iff/chunk.rs +++ b/src/iff/chunk.rs @@ -1,6 +1,7 @@ use crate::error::Result; use crate::id3::v2::tag::Id3v2Tag; use crate::macros::{err, try_vec}; +use crate::probe::ParsingMode; use std::io::{Read, Seek, SeekFrom}; use std::marker::PhantomData; @@ -91,7 +92,7 @@ impl Chunks { Ok(content) } - pub fn id3_chunk(&mut self, data: &mut R) -> Result + pub fn id3_chunk(&mut self, data: &mut R, parse_mode: ParsingMode) -> Result where R: Read + Seek, { @@ -103,7 +104,7 @@ impl Chunks { let reader = &mut &*content; let header = read_id3v2_header(reader)?; - let id3v2 = parse_id3v2(reader, header)?; + let id3v2 = parse_id3v2(reader, header, parse_mode)?; // Skip over the footer if id3v2.flags().footer { diff --git a/src/iff/wav/read.rs b/src/iff/wav/read.rs index 34107f49..03de956e 100644 --- a/src/iff/wav/read.rs +++ b/src/iff/wav/read.rs @@ -88,7 +88,7 @@ where } }, b"ID3 " | b"id3 " => { - let tag = chunks.id3_chunk(data)?; + let tag = chunks.id3_chunk(data, parse_options.parsing_mode)?; if let Some(existing_tag) = id3v2_tag.as_mut() { // https://github.com/Serial-ATA/lofty-rs/issues/87 // Duplicate tags should have their frames appended to the previous diff --git a/src/mpeg/read.rs b/src/mpeg/read.rs index 7591c41e..24b58c32 100644 --- a/src/mpeg/read.rs +++ b/src/mpeg/read.rs @@ -41,7 +41,7 @@ where let header = read_id3v2_header(reader)?; let skip_footer = header.flags.footer; - let id3v2 = parse_id3v2(reader, header)?; + let id3v2 = parse_id3v2(reader, header, parse_options.parsing_mode)?; if let Some(existing_tag) = &mut file.id3v2_tag { // https://github.com/Serial-ATA/lofty-rs/issues/87 // Duplicate tags should have their frames appended to the previous