Skip to content

Commit

Permalink
Translate text frame nulls to '/' (fixes polyfloyd#82)
Browse files Browse the repository at this point in the history
Null bytes in text frames is an ID3v2.4 feature. A valid substitute is
to use '/' in prior versions. This was always the intended behaviour,
hence this is considered a bug fix.
  • Loading branch information
polyfloyd committed May 10, 2022
1 parent d53c8db commit ce18ca8
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 35 deletions.
43 changes: 8 additions & 35 deletions src/stream/frame/content.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,10 @@ impl<W: io::Write> Encoder<W> {

fn text_content(&mut self, content: &str) -> crate::Result<()> {
self.encoding()?;
self.string(content)
match self.version {
Version::Id3v22 | Version::Id3v23 => self.string(&content.replace('\0', "/")),
Version::Id3v24 => self.string(content),
}
}

fn extended_text_content(&mut self, content: &ExtendedText) -> crate::Result<()> {
Expand Down Expand Up @@ -427,6 +430,10 @@ impl<'a> Decoder<'a> {
},
};
let text = encoding.decode(self.bytes(end)?)?;
let text = match self.version {
Version::Id3v22 | Version::Id3v23 => text.replace('/', "\0"),
Version::Id3v24 => text,
};
Ok(Content::Text(text))
}

Expand Down Expand Up @@ -1075,40 +1082,6 @@ mod tests {
}
}

#[test]
fn test_null_terminated_text_v3() {
assert!(decode("TRCK", Version::Id3v23, &[][..]).is_err());
let text = "text\u{0}test\u{0}";
for encoding in &[
Encoding::Latin1,
Encoding::UTF8,
Encoding::UTF16,
Encoding::UTF16BE,
] {
println!("`{}`, `{:?}`", text, encoding);
let mut data = Vec::new();
data.push(*encoding as u8);
data.extend(bytes_for_encoding(text, *encoding).into_iter());

assert_eq!(
decode("TALB", Version::Id3v23, &data[..])
.unwrap()
.text()
.unwrap(),
"text"
);
let mut data_out = Vec::new();
encode(
&mut data_out,
&Content::Text(text.to_string()),
Version::Id3v23,
*encoding,
)
.unwrap();
assert_eq!(data, data_out);
}
}

#[test]
fn test_null_terminated_text_v4() {
assert!(decode("TRCK", Version::Id3v24, &[][..]).is_err());
Expand Down
4 changes: 4 additions & 0 deletions src/stream/tag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,10 @@ mod tests {
tag.set_title("Title");
tag.set_artist("Artist");
tag.set_genre("Genre");
tag.add_frame(Frame::with_content(
"TPE4",
Content::new_text_values(["artist 1", "artist 2", "artist 3"]),
));
tag.set_duration(1337);
tag.add_frame(EncapsulatedObject {
mime_type: "Some Object".to_string(),
Expand Down
11 changes: 11 additions & 0 deletions src/tag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,17 @@ mod tests {
println!("{}", output);
}

#[test]
fn github_issue_82() {
let mut tag = Tag::new();
tag.set_artist("artist 1\0artist 2\0artist 3");
assert_eq!(tag.artist(), Some("artist 1\0artist 2\0artist 3"));
let mut buf = Vec::new();
tag.write_to(&mut buf, Version::Id3v22).unwrap();
let tag = Tag::read_from(&buf[..]).unwrap();
assert_eq!(tag.artist(), Some("artist 1\0artist 2\0artist 3"));
}

#[test]
fn aiff_read_and_write() {
// Copy
Expand Down

0 comments on commit ce18ca8

Please sign in to comment.