diff --git a/algo/kgm/kgm.go b/algo/kgm/kgm.go index fa3cd06..7b5330e 100644 --- a/algo/kgm/kgm.go +++ b/algo/kgm/kgm.go @@ -8,17 +8,20 @@ import ( ) type Decoder struct { - header header - cipher common.StreamDecoder + rd io.ReadSeeker - rd io.ReadSeeker + cipher common.StreamDecoder offset int + + header header } func NewDecoder(rd io.ReadSeeker) common.Decoder { return &Decoder{rd: rd} } +// Validate checks if the file is a valid Kugou (.kgm, .vpr, .kgma) file. +// rd will be seeked to the beginning of the encrypted audio. func (d *Decoder) Validate() (err error) { if err := d.header.FromFile(d.rd); err != nil { return err diff --git a/algo/kwm/kwm.go b/algo/kwm/kwm.go index d5f1f67..5e533c8 100644 --- a/algo/kwm/kwm.go +++ b/algo/kwm/kwm.go @@ -16,9 +16,9 @@ const magicHeader = "yeelion-kuwo-tme" const keyPreDefined = "MoOtOiTvINGwd2E6n0E1i7L5t2IoOoNk" type Decoder struct { - cipher common.StreamDecoder + rd io.ReadSeeker - rd io.ReadSeeker + cipher common.StreamDecoder offset int outputExt string @@ -33,6 +33,8 @@ func NewDecoder(rd io.ReadSeeker) common.Decoder { return &Decoder{rd: rd} } +// Validate checks if the file is a valid Kuwo .kw file. +// rd will be seeked to the beginning of the encrypted audio. func (d *Decoder) Validate() error { header := make([]byte, 0x400) // kwm header is fixed to 1024 bytes _, err := io.ReadFull(d.rd, header) diff --git a/algo/ncm/ncm.go b/algo/ncm/ncm.go index 0e3cf70..dd77835 100644 --- a/algo/ncm/ncm.go +++ b/algo/ncm/ncm.go @@ -36,22 +36,19 @@ func NewDecoder(rd io.ReadSeeker) common.Decoder { } type Decoder struct { - rd io.ReadSeeker + rd io.ReadSeeker // rd is the original file reader + offset int - cipher common.StreamDecoder - key []byte - box []byte - metaRaw []byte metaType string meta RawMeta - - cover []byte - audio []byte + cover []byte } +// Validate checks if the file is a valid Netease .ncm file. +// rd will be seeked to the beginning of the encrypted audio. func (d *Decoder) Validate() error { if err := d.validateMagicHeader(); err != nil { return err diff --git a/algo/qmc/qmc.go b/algo/qmc/qmc.go index 72bc82c..509ad11 100644 --- a/algo/qmc/qmc.go +++ b/algo/qmc/qmc.go @@ -13,14 +13,15 @@ import ( ) type Decoder struct { - raw io.ReadSeeker - audio io.Reader - offset int - audioLen int + raw io.ReadSeeker // raw is the original file reader - cipher common.StreamDecoder + audio io.Reader // audio is the encrypted audio data + audioLen int // audioLen is the audio data length + offset int // offset is the current audio read position + + decodedKey []byte // decodedKey is the decoded key for cipher + cipher common.StreamDecoder - decodedKey []byte rawMetaExtra1 int rawMetaExtra2 int } @@ -100,23 +101,29 @@ func (d *Decoder) searchKey() error { if err != nil { return err } - buf, err := io.ReadAll(io.LimitReader(d.raw, 4)) - if err != nil { + + suffixBuf := make([]byte, 4) + if _, err := io.ReadFull(d.raw, suffixBuf); err != nil { return err } - if string(buf) == "QTag" { + + switch string(suffixBuf) { + case "QTag": return d.readRawMetaQTag() - } else if string(buf) == "STag" { + case "STag": return errors.New("qmc: file with 'STag' suffix doesn't contains media key") - } else { - size := binary.LittleEndian.Uint32(buf) + default: + size := binary.LittleEndian.Uint32(suffixBuf) + if size <= 0xFFFF && size != 0 { // assume size is key len return d.readRawKey(int64(size)) } + // try to use default static cipher d.audioLen = int(fileSizeM4 + 4) return nil } + } func (d *Decoder) readRawKey(rawKeyLen int64) error { diff --git a/algo/tm/tm.go b/algo/tm/tm.go index 16508ac..af7feea 100644 --- a/algo/tm/tm.go +++ b/algo/tm/tm.go @@ -13,9 +13,10 @@ var replaceHeader = []byte{0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70} var magicHeader = []byte{0x51, 0x51, 0x4D, 0x55} //0x15, 0x1D, 0x1A, 0x21 type Decoder struct { - raw io.ReadSeeker + raw io.ReadSeeker // raw is the original file reader + offset int - audio io.Reader + audio io.Reader // audio is the decrypted audio data } func (d *Decoder) Validate() error { diff --git a/algo/xiami/xm.go b/algo/xiami/xm.go index fbffc21..f878175 100644 --- a/algo/xiami/xm.go +++ b/algo/xiami/xm.go @@ -22,13 +22,11 @@ var ( ) type Decoder struct { - rd io.ReadSeeker + rd io.ReadSeeker // rd is the original file reader offset int cipher common.StreamDecoder outputExt string - mask byte - audio []byte } func (d *Decoder) GetAudioExt() string { @@ -43,6 +41,8 @@ func NewDecoder(rd io.ReadSeeker) common.Decoder { return &Decoder{rd: rd} } +// Validate checks if the file is a valid xiami .xm file. +// rd will set to the beginning of the encrypted audio data. func (d *Decoder) Validate() error { header := make([]byte, 16) // xm header is fixed to 16 bytes diff --git a/internal/logging/zap.go b/internal/logging/zap.go index 3c21c37..a62d764 100644 --- a/internal/logging/zap.go +++ b/internal/logging/zap.go @@ -7,6 +7,7 @@ import ( func NewZapLogger() (*zap.Logger, error) { zapCfg := zap.NewDevelopmentConfig() + zapCfg.DisableStacktrace = true zapCfg.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder zapCfg.EncoderConfig.EncodeTime = zapcore.TimeEncoderOfLayout("2006/01/02 15:04:05.000") return zapCfg.Build()