Store torrent FileList info as bencoded data. (#530)
Use this instead of joining with forward-slashes because it's possible that a torrent uses "foo/bar" as a filename or part of the directory list.
Cette révision appartient à :
Parent
93966299f1
révision
f351c2b047
5 fichiers modifiés avec 54 ajouts et 19 suppressions
|
@ -1,14 +1,34 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"github.com/zeebo/bencode"
|
||||
)
|
||||
|
||||
type File struct {
|
||||
ID uint `gorm:"column:file_id;primary_key"`
|
||||
TorrentID uint `gorm:"column:torrent_id;unique_index:idx_tid_path"`
|
||||
Path string `gorm:"column:path;unique_index:idx_tid_path"`
|
||||
Filesize int64 `gorm:"column:filesize"`
|
||||
ID uint `gorm:"column:file_id;primary_key"`
|
||||
TorrentID uint `gorm:"column:torrent_id;unique_index:idx_tid_path"`
|
||||
// this path is bencode'd, call Path() to obtain
|
||||
BencodedPath string `gorm:"column:path;unique_index:idx_tid_path"`
|
||||
Filesize int64 `gorm:"column:filesize"`
|
||||
}
|
||||
|
||||
// Returns the total size of memory allocated for this struct
|
||||
func (f File) Size() int {
|
||||
return (2 + len(f.Path) + 2) * 8;
|
||||
return (2 + len(f.BencodedPath) + 1) * 8;
|
||||
}
|
||||
|
||||
func (f *File) Path() (out []string) {
|
||||
bencode.DecodeString(f.BencodedPath, &out)
|
||||
return
|
||||
}
|
||||
|
||||
func (f *File) SetPath(path []string) error {
|
||||
encoded, err := bencode.EncodeString(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
f.BencodedPath = encoded
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"fmt"
|
||||
"html/template"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -131,7 +132,10 @@ func (t *Torrent) ToJSON() TorrentJSON {
|
|||
}
|
||||
fileListJSON := make([]FileJSON, 0, len(t.FileList))
|
||||
for _, f := range t.FileList {
|
||||
fileListJSON = append(fileListJSON, FileJSON{Path: f.Path, Filesize: util.FormatFilesize2(f.Filesize)})
|
||||
fileListJSON = append(fileListJSON, FileJSON{
|
||||
Path: filepath.Join(f.Path()...),
|
||||
Filesize: util.FormatFilesize2(f.Filesize),
|
||||
})
|
||||
}
|
||||
uploader := ""
|
||||
if t.Uploader != nil {
|
||||
|
|
|
@ -27,7 +27,7 @@ import (
|
|||
// Use this, because we seem to avoid using models, and we would need
|
||||
// the torrent ID to create the File in the DB
|
||||
type UploadedFile struct {
|
||||
Path string
|
||||
Path []string
|
||||
Filesize int64
|
||||
}
|
||||
|
||||
|
@ -161,10 +161,10 @@ func (f *UploadForm) ExtractInfo(r *http.Request) error {
|
|||
|
||||
// extract filelist
|
||||
fileInfos := torrent.Info.GetFiles()
|
||||
for _, info := range fileInfos {
|
||||
for _, fileInfo := range fileInfos {
|
||||
f.FileList = append(f.FileList, UploadedFile{
|
||||
Path: info.Path.FilePath(),
|
||||
Filesize: int64(info.Length),
|
||||
Path: fileInfo.Path,
|
||||
Filesize: int64(fileInfo.Length),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -64,10 +64,12 @@ func UploadHandler(w http.ResponseWriter, r *http.Request) {
|
|||
// add filelist to files db, if we have one
|
||||
if len(uploadForm.FileList) > 0 {
|
||||
for _, uploadedFile := range uploadForm.FileList {
|
||||
file := model.File{
|
||||
TorrentID: torrent.ID,
|
||||
Path: uploadedFile.Path,
|
||||
Filesize: uploadedFile.Filesize}
|
||||
file := model.File{TorrentID: torrent.ID, Filesize: uploadedFile.Filesize}
|
||||
err := file.SetPath(uploadedFile.Path)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
db.ORM.Create(&file)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,23 +120,32 @@ func (fetcher *MetainfoFetcher) removeFromFailed(tID uint) {
|
|||
|
||||
delete(fetcher.failedOperations, tID)
|
||||
}
|
||||
|
||||
func updateFileList(dbEntry model.Torrent, info *metainfo.Info) error {
|
||||
torrentFiles := info.UpvertedFiles()
|
||||
log.Infof("TID %d has %d files.", dbEntry.ID, len(torrentFiles))
|
||||
|
||||
for _, file := range torrentFiles {
|
||||
path := file.DisplayPath(info)
|
||||
var path []string
|
||||
if file.Path != nil {
|
||||
path = file.Path
|
||||
} else {
|
||||
// If it's nil, use the torrent name (info.Name) as the path (single-file torrent)
|
||||
path = append(path, info.Name)
|
||||
}
|
||||
|
||||
// Can't read FileList from the GetTorrents output, rely on the unique_index
|
||||
// to ensure no files are duplicated.
|
||||
log.Infof("Adding file %s to filelist of TID %d", path, dbEntry.ID)
|
||||
log.Infof("Adding file %s to filelist of TID %d", file.DisplayPath(info), dbEntry.ID)
|
||||
dbFile := model.File{
|
||||
TorrentID: dbEntry.ID,
|
||||
Path: path,
|
||||
Filesize: file.Length,
|
||||
}
|
||||
err := dbFile.SetPath(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err := db.ORM.Create(&dbFile).Error
|
||||
err = db.ORM.Create(&dbFile).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
Référencer dans un nouveau ticket