Albirew/nyaa-pantsu
Archivé
1
0
Bifurcation 0
Ce dépôt a été archivé le 2022-05-07. Vous pouvez voir ses fichiers ou le cloner, mais pas ouvrir de ticket ou de demandes d'ajout, ni soumettre de changements.
nyaa-pantsu/util/metainfo/metainfo.go
Jeff Becker c088cb2642 add torrent file parsing for upload form
* vendor bencode library github.com/zeebo/bencode

* add metainfo parsing library from XD

* fix up upload handler so to be less cluttered
2017-05-06 07:43:24 -04:00

143 lignes
3,1 Kio
Go

package metainfo
// this file is from https://github.com/majestrate/XD
import (
"crypto/sha1"
"github.com/zeebo/bencode"
"io"
"os"
"path/filepath"
)
type FilePath []string
// get filepath
func (f FilePath) FilePath() string {
return filepath.Join(f...)
}
/** open file using base path */
func (f FilePath) Open(base string) (*os.File, error) {
return os.OpenFile(filepath.Join(base, f.FilePath()), os.O_RDWR|os.O_CREATE, 0600)
}
type FileInfo struct {
// length of file
Length uint64 `bencode:"length"`
// relative path of file
Path FilePath `bencode:"path"`
// md5sum
Sum []byte `bencode:"md5sum,omitempty"`
}
// info section of torrent file
type Info struct {
// length of pices in bytes
PieceLength uint32 `bencode:"piece length"`
// piece data
Pieces []byte `bencode:"pieces"`
// name of root file
Path string `bencode:"name"`
// file metadata
Files []FileInfo `bencode:"files,omitempty"`
// private torrent
Private *int64 `bencode:"private,omitempty"`
// length of file in signle file mode
Length uint64 `bencode:"length,omitempty"`
// md5sum
Sum []byte `bencode:"md5sum,omitempty"`
}
// get fileinfos from this info section
func (i Info) GetFiles() (infos []FileInfo) {
if i.Length > 0 {
infos = append(infos, FileInfo{
Length: i.Length,
Path: FilePath([]string{i.Path}),
Sum: i.Sum,
})
} else {
infos = append(infos, i.Files...)
}
return
}
func (i Info) NumPieces() uint32 {
return uint32(len(i.Pieces) / 20)
}
// a torrent file
type TorrentFile struct {
Info Info `bencode:"info"`
Announce string `bencode:"announce"`
AnnounceList [][]string `bencode:"announce-list"`
Created uint64 `bencode:"created"`
Comment []byte `bencode:"comment"`
CreatedBy []byte `bencode:"created by"`
Encoding []byte `bencode:"encoding"`
}
// get total size of files from torrent info section
func (tf *TorrentFile) TotalSize() uint64 {
if tf.IsSingleFile() {
return tf.Info.Length
}
total := uint64(0)
for _, f := range tf.Info.Files {
total += f.Length
}
return total
}
func (tf *TorrentFile) GetAllAnnounceURLS() (l []string) {
if len(tf.Announce) > 0 {
l = append(l, tf.Announce)
}
for _, al := range tf.AnnounceList {
for _, a := range al {
if len(a) > 0 {
l = append(l, a)
}
}
}
return
}
func (tf *TorrentFile) TorrentName() string {
return string(tf.Info.Path)
}
// return true if this torrent is private otherwise return false
func (tf *TorrentFile) IsPrivate() bool {
return tf.Info.Private == nil || *tf.Info.Private == 0
}
// calculate infohash
func (tf *TorrentFile) Infohash() (ih [20]byte) {
s := sha1.New()
enc := bencode.NewEncoder(s)
enc.Encode(&tf.Info)
d := s.Sum(nil)
copy(ih[:], d[:])
return
}
// return true if this torrent is for a single file
func (tf *TorrentFile) IsSingleFile() bool {
return tf.Info.Length > 0
}
// bencode this file via an io.Writer
func (tf *TorrentFile) Encode(w io.Writer) (err error) {
enc := bencode.NewEncoder(w)
err = enc.Encode(tf)
return
}
// load from an io.Reader
func (tf *TorrentFile) Decode(r io.Reader) (err error) {
dec := bencode.NewDecoder(r)
err = dec.Decode(tf)
return
}