From d730be2ce4580e65a871a2666d5f8802f9640fe7 Mon Sep 17 00:00:00 2001 From: Unbewohnte Date: Sat, 3 Jul 2021 20:10:57 +0300 Subject: [PATCH] =?UTF-8?q?=E2=9D=AE=20Looks=20like=20it=20can=20read=20Fr?= =?UTF-8?q?ames=20now.=20Also=20utils=20are=20looking=20neat!=20=E2=9D=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- testData/testwritev1.mp3 | Bin 3999 -> 5535 bytes util/{etc.go => conversion.go} | 26 +++++----- util/conversion_test.go | 13 +++++ util/maps.go | 12 +++++ util/read.go | 26 ++-------- v1/id3v10.go | 10 ++-- v1/id3v11.go | 10 ++-- v2/frame.go | 88 ++++++++++++++++++++++++++------- v2/frame_test.go | 23 ++++++++- 9 files changed, 144 insertions(+), 64 deletions(-) rename util/{etc.go => conversion.go} (72%) create mode 100644 util/conversion_test.go create mode 100644 util/maps.go diff --git a/testData/testwritev1.mp3 b/testData/testwritev1.mp3 index 8c78a564e2df8ed084f7b4a2a06f897bad62edf4..7b827e28e8a1f152e48cd5bc1c2761fb2232f0ec 100644 GIT binary patch delta 11 ScmbO)KVN&peE!Ar8QB0FO9U_g delta 7 OcmbQQJzsvqe0~57Rs!b$ diff --git a/util/etc.go b/util/conversion.go similarity index 72% rename from util/etc.go rename to util/conversion.go index 8739463..1a0ca95 100644 --- a/util/etc.go +++ b/util/conversion.go @@ -5,19 +5,9 @@ import ( "encoding/binary" "fmt" "strconv" + "strings" ) -// Returns found key (int) in provided map by value (string); -// If key does not exist in map - returns -1 -func GetKey(mp map[int]string, givenValue string) int { - for key, value := range mp { - if value == givenValue { - return key - } - } - return -1 -} - // Decodes given integer bytes into integer func BytesToInt(gBytes []byte) (int64, error) { buff := bytes.NewBuffer(gBytes) @@ -49,3 +39,17 @@ func BytesToIntIgnoreFirstBit(gBytes []byte) (int64, error) { return integer, nil } + +// Converts given bytes into string, ignoring the first 31 non-printable ASCII characters. +// (LOSSY, if given bytes contain some nasty ones) +func ToString(gBytes []byte) string { + var filteredBytes []byte + for _, b := range gBytes { + if b <= 31 { + continue + } + filteredBytes = append(filteredBytes, b) + } + + return strings.ToValidUTF8(string(filteredBytes), "") +} diff --git a/util/conversion_test.go b/util/conversion_test.go new file mode 100644 index 0000000..3772765 --- /dev/null +++ b/util/conversion_test.go @@ -0,0 +1,13 @@ +package util + +import "testing" + +func TestToString(t *testing.T) { + someVeryNastyBytes := []byte{0, 1, 2, 3, 4, 5, 6, 50, 7, 8, 9, 10, 11, 50, 50} + + gString := ToString(someVeryNastyBytes) + + if gString != "222" { + t.Errorf("ToString failed: expected output: %s; got %s", "222", gString) + } +} diff --git a/util/maps.go b/util/maps.go new file mode 100644 index 0000000..2e03650 --- /dev/null +++ b/util/maps.go @@ -0,0 +1,12 @@ +package util + +// Returns found key (int) in provided map by value (string); +// If key does not exist in map - returns -1 +func GetKey(mp map[int]string, givenValue string) int { + for key, value := range mp { + if value == givenValue { + return key + } + } + return -1 +} diff --git a/util/read.go b/util/read.go index c0cec46..474471e 100644 --- a/util/read.go +++ b/util/read.go @@ -16,33 +16,13 @@ func Read(rs io.Reader, n uint64) ([]byte, error) { return read, nil } -// Shortcut function to read n bytes and convert them into string. -// If encountered zero-byte - converts to string only previously read bytes -func ReadToStringIgnoreNullB(rs io.Reader, n uint64) (string, error) { - read := make([]byte, n) - _, err := rs.Read(read) - if err != nil { - return "", fmt.Errorf("could not read from reader: %s", err) - } - - var readString string - for _, b := range read { - if b == 0 { - break - } - readString += string(b) - } - - return readString, nil -} - -// Reads from rs and conversts read []byte into string +// Reads from rs and conversts read []byte into string, ignoring all non-printable or +// invalid characters. func ReadToString(rs io.Reader, n uint64) (string, error) { read := make([]byte, n) _, err := rs.Read(read) if err != nil { return "", fmt.Errorf("could not read from reader: %s", err) } - - return string(read), nil + return ToString(read), nil } diff --git a/v1/id3v10.go b/v1/id3v10.go index 84c3ee5..a50802b 100644 --- a/v1/id3v10.go +++ b/v1/id3v10.go @@ -40,22 +40,22 @@ func Getv1Tags(rs io.ReadSeeker) (*ID3v1Tags, error) { return nil, fmt.Errorf("does not use ID3v1: expected %s; got %s", ID3v1IDENTIFIER, tag) } - songname, err := util.ReadToStringIgnoreNullB(rs, 30) + songname, err := util.ReadToString(rs, 30) if err != nil { return nil, err } - artist, err := util.ReadToStringIgnoreNullB(rs, 30) + artist, err := util.ReadToString(rs, 30) if err != nil { return nil, err } - album, err := util.ReadToStringIgnoreNullB(rs, 30) + album, err := util.ReadToString(rs, 30) if err != nil { return nil, err } - yearStr, err := util.ReadToStringIgnoreNullB(rs, 4) + yearStr, err := util.ReadToString(rs, 4) if err != nil { return nil, err } @@ -64,7 +64,7 @@ func Getv1Tags(rs io.ReadSeeker) (*ID3v1Tags, error) { return nil, fmt.Errorf("could not convert yearbytes into int: %s", err) } - comment, err := util.ReadToStringIgnoreNullB(rs, 30) + comment, err := util.ReadToString(rs, 30) if err != nil { return nil, err } diff --git a/v1/id3v11.go b/v1/id3v11.go index 9204eab..a05b23f 100644 --- a/v1/id3v11.go +++ b/v1/id3v11.go @@ -39,22 +39,22 @@ func Getv11Tags(rs io.ReadSeeker) (*ID3v11Tags, error) { return nil, fmt.Errorf("does not use ID3v1: expected %s; got %s", ID3v1IDENTIFIER, tag) } - songname, err := util.ReadToStringIgnoreNullB(rs, 30) + songname, err := util.ReadToString(rs, 30) if err != nil { return nil, err } - artist, err := util.ReadToStringIgnoreNullB(rs, 30) + artist, err := util.ReadToString(rs, 30) if err != nil { return nil, err } - album, err := util.ReadToStringIgnoreNullB(rs, 30) + album, err := util.ReadToString(rs, 30) if err != nil { return nil, err } - yearStr, err := util.ReadToStringIgnoreNullB(rs, 4) + yearStr, err := util.ReadToString(rs, 4) if err != nil { return nil, err } @@ -63,7 +63,7 @@ func Getv11Tags(rs io.ReadSeeker) (*ID3v11Tags, error) { return nil, fmt.Errorf("could not convert yearbytes into int: %s", err) } - comment, err := util.ReadToStringIgnoreNullB(rs, 28) + comment, err := util.ReadToString(rs, 28) if err != nil { return nil, err } diff --git a/v2/frame.go b/v2/frame.go index 5f31f63..ba84f84 100644 --- a/v2/frame.go +++ b/v2/frame.go @@ -1,29 +1,31 @@ package v2 import ( + "fmt" "io" "github.com/Unbewohnte/id3ed/util" ) -//////////////////////////////////////////////////////////////////////////// -//(ᗜˬᗜ)~⭐//Under construction//Please don`t use it in this verison//(ᗜ‸ᗜ)/// -//////////////////////////////////////////////////////////////////////////// - -type FrameHeader struct { - ID string - FrameSize int64 - Flags int +type FrameFlags struct { + TagAlterPreservation bool + FileAlterPreservation bool + ReadOnly bool + Compressed bool + Encrypted bool + InGroup bool } type Frame struct { - Header FrameHeader - Contents string + ID string + Size int64 + Flags FrameFlags + GroupByte byte + Contents []byte } // Reads ID3v2.3.0 or ID3v2.4.0 frame func ReadFrame(rs io.Reader, version uint) (*Frame, error) { - var frameHeader FrameHeader var frame Frame // ID @@ -31,7 +33,7 @@ func ReadFrame(rs io.Reader, version uint) (*Frame, error) { if err != nil { return nil, err } - frameHeader.ID = identifier + frame.ID = identifier // Size framesizeBytes, err := util.Read(rs, 4) @@ -44,20 +46,67 @@ func ReadFrame(rs io.Reader, version uint) (*Frame, error) { return nil, err } - frameHeader.FrameSize = framesize + frame.Size = framesize // Flags - frameFlagsBytes, err := util.Read(rs, 2) + + frameFlagsByte1, err := util.Read(rs, 1) if err != nil { return nil, err } - frameFlags, err := util.BytesToInt(frameFlagsBytes) + frameFlagsByte2, err := util.Read(rs, 1) if err != nil { return nil, err } - frameHeader.Flags = int(frameFlags) + // I don`t have enough knowledge to handle this more elegantly + // Any pointers ? + + flagsByte1Bits := fmt.Sprintf("%08b", frameFlagsByte1) + flagsByte2Bits := fmt.Sprintf("%08b", frameFlagsByte2) + var flags FrameFlags + + if flagsByte1Bits[0] == 1 { + flags.TagAlterPreservation = true + } else { + flags.TagAlterPreservation = false + } + if flagsByte1Bits[1] == 1 { + flags.FileAlterPreservation = true + } else { + flags.FileAlterPreservation = false + } + if flagsByte1Bits[2] == 1 { + flags.ReadOnly = true + } else { + flags.ReadOnly = false + } + if flagsByte2Bits[0] == 1 { + flags.Compressed = true + } else { + flags.Compressed = false + } + if flagsByte2Bits[1] == 1 { + flags.Encrypted = true + } else { + flags.Encrypted = false + } + if flagsByte2Bits[2] == 1 { + flags.InGroup = true + } else { + flags.InGroup = false + } + + frame.Flags = flags + + if flags.InGroup { + groupByte, err := util.Read(rs, 1) + if err != nil { + return nil, err + } + frame.GroupByte = groupByte[0] + } // Body frameContents, err := util.Read(rs, uint64(framesize)) @@ -65,8 +114,11 @@ func ReadFrame(rs io.Reader, version uint) (*Frame, error) { return nil, err } - frame.Header = frameHeader - frame.Contents = string(frameContents) + frame.Contents = frameContents return &frame, nil } + +func WriteFlag() { + +} diff --git a/v2/frame_test.go b/v2/frame_test.go index 25d9167..9e7fa3d 100644 --- a/v2/frame_test.go +++ b/v2/frame_test.go @@ -5,6 +5,8 @@ import ( "os" "path/filepath" "testing" + + "github.com/Unbewohnte/id3ed/util" ) func TestReadFrame(t *testing.T) { @@ -21,7 +23,24 @@ func TestReadFrame(t *testing.T) { t.Errorf("ReadFrame failed: %s", err) } - if firstFrame.Header.ID != "TRCK" { - t.Errorf("ReadFrame failed: expected ID %s; got %s", "TRCK", firstFrame.Header.ID) + if firstFrame.ID != "TRCK" { + t.Errorf("ReadFrame failed: expected ID %s; got %s", "TRCK", firstFrame.ID) + } + + if firstFrame.Flags.Encrypted != false { + t.Errorf("ReadFrame failed: expected compressed flag to be %v; got %v", false, firstFrame.Flags.Encrypted) + } + + secondFrame, err := ReadFrame(f, 24) + if err != nil { + t.Errorf("ReadFrame failed: %s", err) + } + + if secondFrame.ID != "TDRC" { + t.Errorf("ReadFrame failed: expected ID %s; got %s", "TDRC", secondFrame.ID) + } + + if util.ToString(secondFrame.Contents) != "2006" { + t.Errorf("ReadFrame failed: expected contents to be %s; got %s", "2006", util.ToString(secondFrame.Contents)) } }