diff --git a/router/upload.go b/router/upload.go index b8197172..92fa7ce7 100644 --- a/router/upload.go +++ b/router/upload.go @@ -1,7 +1,6 @@ package router import ( - "encoding/hex" "errors" "fmt" "io" @@ -172,12 +171,17 @@ func (f *uploadForm) ExtractInfo(r *http.Request) error { if len(f.Magnet) != 0 { return errTorrentPlusMagnet } - binInfohash, err := torrent.Infohash() - if err != nil { - return err + + _, seekErr = tfile.Seek(0, io.SeekStart) + if seekErr != nil { + return seekErr } - f.Infohash = strings.ToUpper(hex.EncodeToString(binInfohash[:])) - f.Magnet = util.InfoHashToMagnet(f.Infohash, f.Name, trackers...) + infohash, err := metainfo.DecodeInfohash(tfile) + if err != nil { + return metainfo.ErrInvalidTorrentFile + } + f.Infohash = infohash + f.Magnet = util.InfoHashToMagnet(infohash, f.Name, trackers...) // extract filesize f.Filesize = int64(torrent.TotalSize()) diff --git a/service/api/api.go b/service/api/api.go index 7e79cea6..bb1808bc 100644 --- a/service/api/api.go +++ b/service/api/api.go @@ -198,11 +198,15 @@ func (r *TorrentRequest) ValidateMultipartUpload(req *http.Request) (int64, erro r.Name = torrent.TorrentName() } - binInfohash, err := torrent.Infohash() + _, err = tfile.Seek(0, io.SeekStart) if err != nil { return 0, err, http.StatusInternalServerError } - r.Hash = strings.ToUpper(hex.EncodeToString(binInfohash[:])) + infohash, err := metainfo.DecodeInfohash(tfile) + if err != nil { + return 0, err, http.StatusInternalServerError + } + r.Hash = infohash // extract filesize filesize := int64(torrent.TotalSize()) diff --git a/util/metainfo/metainfo.go b/util/metainfo/metainfo.go index d3dfdaf2..ceaa2818 100644 --- a/util/metainfo/metainfo.go +++ b/util/metainfo/metainfo.go @@ -4,9 +4,11 @@ package metainfo import ( "crypto/sha1" + "encoding/hex" "io" "os" "path/filepath" + "strings" "github.com/zeebo/bencode" ) @@ -120,19 +122,6 @@ func (tf *TorrentFile) IsPrivate() bool { return tf.Info.Private != nil && *tf.Info.Private == 1 } -// Infohash : calculate infohash -func (tf *TorrentFile) Infohash() (ih [20]byte, err error) { - s := sha1.New() - enc := bencode.NewEncoder(s) - err = enc.Encode(&tf.Info) - if err != nil { - return - } - d := s.Sum(nil) - copy(ih[:], d[:]) - return -} - // IsSingleFile : return true if this torrent is for a single file func (tf *TorrentFile) IsSingleFile() bool { return tf.Info.Length > 0 @@ -151,3 +140,27 @@ func (tf *TorrentFile) Decode(r io.Reader) (err error) { err = dec.Decode(tf) return } + +type torrentRaw struct { + InfoRaw bencode.RawMessage `bencode:"info"` +} + +// DecodeInfohash : Decode and calculate the info hash +func DecodeInfohash(r io.Reader) (hash string, err error) { + var t torrentRaw + d := bencode.NewDecoder(r) + err = d.Decode(&t) + if err != nil { + return + } + + s := sha1.New() + _, err = s.Write(t.InfoRaw) + if err != nil { + return + } + rawHash := s.Sum(nil) + + hash = strings.ToUpper(hex.EncodeToString(rawHash)) + return +}