diff --git a/router/apiHandler.go b/router/apiHandler.go index 2939ea50..991ae7ac 100644 --- a/router/apiHandler.go +++ b/router/apiHandler.go @@ -6,6 +6,7 @@ import ( "html" "net/http" "strconv" + "strings" "time" "github.com/ewhal/nyaa/config" @@ -100,22 +101,22 @@ func ApiUploadHandler(w http.ResponseWriter, r *http.Request) { return } + token := r.Header.Get("Authorization") + user := model.User{} + db.ORM.Where("api_token = ?", token).First(&user) //i don't like this + if user.ID == 0 { + http.Error(w, apiService.ErrApiKey.Error(), http.StatusForbidden) + return + } + + upload := apiService.TorrentRequest{} + var filesize int64 + contentType := r.Header.Get("Content-Type") if contentType == "application/json" { - token := r.Header.Get("Authorization") - user := model.User{} - db.ORM.Where("api_token = ?", token).First(&user) //i don't like this - if user.ID == 0 { - http.Error(w, apiService.ErrApiKey.Error(), http.StatusForbidden) - return - } defer r.Body.Close() - //verify token - //token := r.Header.Get("Authorization") - - upload := apiService.TorrentRequest{} d := json.NewDecoder(r.Body) if err := d.Decode(&upload); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) @@ -126,27 +127,41 @@ func ApiUploadHandler(w http.ResponseWriter, r *http.Request) { http.Error(w, err.Error(), code) return } + } else if strings.HasPrefix(contentType, "multipart/form-data") { - torrent := model.Torrent{ - Name: upload.Name, - Category: upload.Category, - SubCategory: upload.SubCategory, - Status: 1, - Hash: upload.Hash, - Date: time.Now(), - Filesize: 0, //? - Description: upload.Description, - UploaderID: user.ID, - Uploader: &user, - } + upload.Name = r.FormValue("name") + upload.Category, _ = strconv.Atoi(r.FormValue("category")) + upload.SubCategory, _ = strconv.Atoi(r.FormValue("sub_category")) + upload.Description = r.FormValue("description") - db.ORM.Create(&torrent) + var err error + var code int + + filesize, err, code = upload.ValidateMultipartUpload(r) if err != nil { - util.SendError(w, err, 500) + http.Error(w, err.Error(), code) return } - fmt.Printf("%+v\n", torrent) } + + torrent := model.Torrent{ + Name: upload.Name, + Category: upload.Category, + SubCategory: upload.SubCategory, + Status: 1, + Hash: upload.Hash, + Date: time.Now(), + Filesize: filesize, + Description: upload.Description, + UploaderID: user.ID, + Uploader: &user, + } + /*db.ORM.Create(&torrent) + if err != nil { + util.SendError(w, err, 500) + return + }*/ + fmt.Printf("%+v\n", torrent) } func ApiUpdateHandler(w http.ResponseWriter, r *http.Request) { diff --git a/service/api/api.go b/service/api/api.go index 3c5a3547..9abae7dd 100644 --- a/service/api/api.go +++ b/service/api/api.go @@ -1,6 +1,9 @@ package apiService import ( + "encoding/hex" + "errors" + "io" "net/http" "net/url" "reflect" @@ -9,6 +12,8 @@ import ( "github.com/ewhal/nyaa/model" "github.com/ewhal/nyaa/service" + "github.com/ewhal/nyaa/util/metainfo" + "github.com/zeebo/bencode" ) type torrentsQuery struct { @@ -60,9 +65,9 @@ func (r *TorrentsRequest) ToParams() serviceBase.WhereParams { } func validateName(r *TorrentRequest) (error, int) { - if len(r.Name) < 100 { //isn't this too much? + /*if len(r.Name) < 100 { //isn't this too much? return ErrShortName, http.StatusNotAcceptable - } + }*/ return nil, http.StatusOK } @@ -105,8 +110,6 @@ func validateHash(r *TorrentRequest) (error, int) { return nil, http.StatusOK } -//rewrite validators!!! - func (r *TorrentRequest) ValidateUpload() (err error, code int) { validators := []func(r *TorrentRequest) (error, int){ validateName, @@ -128,6 +131,46 @@ func (r *TorrentRequest) ValidateUpload() (err error, code int) { return err, code } +func (r *TorrentRequest) ValidateMultipartUpload(req *http.Request) (int64, error, int) { + tfile, _, err := req.FormFile("torrent") + if err == nil { + var torrent metainfo.TorrentFile + + // decode torrent + if _, err = tfile.Seek(0, io.SeekStart); err != nil { + return 0, err, http.StatusInternalServerError + } + if err = bencode.NewDecoder(tfile).Decode(&torrent); err != nil { + return 0, err, http.StatusInternalServerError + } + // check a few things + if torrent.IsPrivate() { + return 0, errors.New("private torrents not allowed"), http.StatusBadRequest + } + //import cycle + /*trackers := torrent.GetAllAnnounceURLS() + if !router.CheckTrackers(trackers) { + return 0, errors.New("tracker(s) not allowed"), http.StatusBadRequest + }*/ + + if r.Name == "" { + r.Name = torrent.TorrentName() + } + + binInfohash, err := torrent.Infohash() + if err != nil { + return 0, err, http.StatusInternalServerError + } + r.Hash = strings.ToUpper(hex.EncodeToString(binInfohash[:])) + + // extract filesize + filesize := int64(torrent.TotalSize()) + err, code := r.ValidateUpload() + return filesize, err, code + } + return 0, err, http.StatusInternalServerError +} + func (r *TorrentRequest) ValidateUpdate() (err error, code int) { validators := []func(r *TorrentRequest) (error, int){ validateName, diff --git a/test.torrent b/test.torrent new file mode 100644 index 00000000..5b48d5ae Binary files /dev/null and b/test.torrent differ