From c74c4790b0cd4edd439ee15b73e7098be96289c6 Mon Sep 17 00:00:00 2001 From: YouROK <8yourok8@mail.ru> Date: Thu, 4 Mar 2021 11:11:23 +0300 Subject: [PATCH 1/5] fix auth play --- server/web/api/stream.go | 76 ++++++++++++++++++++++++++++++++++++++++ server/web/auth/auth.go | 66 +++++++++++++++++++++++++++++++++- 2 files changed, 141 insertions(+), 1 deletion(-) diff --git a/server/web/api/stream.go b/server/web/api/stream.go index 1f56fd0..97de8c6 100644 --- a/server/web/api/stream.go +++ b/server/web/api/stream.go @@ -36,6 +36,17 @@ func stream(c *gin.Context) { _, play := c.GetQuery("play") title := c.Query("title") poster := c.Query("poster") + notAuth := c.GetBool("not_auth") + + if notAuth && play { + streamNoAuth(c) + return + } + if notAuth { + c.Header("WWW-Authenticate", "Basic realm=Authorization Required") + c.AbortWithStatus(http.StatusUnauthorized) + return + } if link == "" { c.AbortWithError(http.StatusBadRequest, errors.New("link should not be empty")) @@ -111,3 +122,68 @@ func stream(c *gin.Context) { return } } + +func streamNoAuth(c *gin.Context) { + link := c.Query("link") + indexStr := c.Query("index") + _, preload := c.GetQuery("preload") + title := c.Query("title") + poster := c.Query("poster") + + // c.Header("WWW-Authenticate", "Basic realm=Authorization Required") + // c.AbortWithStatus(http.StatusUnauthorized) + + if link == "" { + c.AbortWithError(http.StatusBadRequest, errors.New("link should not be empty")) + return + } + + if title == "" { + title = c.Param("fname") + title, _ = url.PathUnescape(title) + title = strings.TrimLeft(title, "/") + } else { + title, _ = url.QueryUnescape(title) + } + + link, _ = url.QueryUnescape(link) + poster, _ = url.QueryUnescape(poster) + + spec, err := utils.ParseLink(link) + if err != nil { + c.AbortWithError(http.StatusInternalServerError, err) + return + } + + tor := torr.GetTorrent(spec.InfoHash.HexString()) + if tor == nil { + c.AbortWithError(http.StatusNotFound, errors.New("Torrent not found")) + return + } + + if !tor.GotInfo() { + c.AbortWithError(http.StatusInternalServerError, errors.New("timeout connection torrent")) + return + } + + // find file + index := -1 + if len(tor.Files()) == 1 { + index = 1 + } else { + ind, err := strconv.Atoi(indexStr) + if err == nil { + index = ind + } + } + if index == -1 { // if file index not set and play file exec + c.AbortWithError(http.StatusBadRequest, errors.New("\"index\" is empty or wrong")) + return + } + // preload torrent + if preload { + torr.Preload(tor, index) + } + + tor.Stream(index, c.Request, c.Writer) +} diff --git a/server/web/auth/auth.go b/server/web/auth/auth.go index 9a2b588..4aae796 100644 --- a/server/web/auth/auth.go +++ b/server/web/auth/auth.go @@ -1,9 +1,14 @@ package auth import ( + "encoding/base64" "encoding/json" "io/ioutil" + "net/http" "path/filepath" + "reflect" + "strings" + "unsafe" "github.com/gin-gonic/gin" @@ -19,7 +24,7 @@ func SetupAuth(engine *gin.Engine) *gin.RouterGroup { if accs == nil { return nil } - return engine.Group("/", gin.BasicAuth(accs)) + return engine.Group("/", BasicAuth(accs)) } func getAccounts() gin.Accounts { @@ -34,3 +39,62 @@ func getAccounts() gin.Accounts { } return accs } + +type authPair struct { + value string + user string +} +type authPairs []authPair + +func (a authPairs) searchCredential(authValue string) (string, bool) { + if authValue == "" { + return "", false + } + for _, pair := range a { + if pair.value == authValue { + return pair.user, true + } + } + return "", false +} + +func BasicAuth(accounts gin.Accounts) gin.HandlerFunc { + pairs := processAccounts(accounts) + return func(c *gin.Context) { + user, found := pairs.searchCredential(c.Request.Header.Get("Authorization")) + if !found { + if strings.HasPrefix(c.FullPath(), "/stream") { + c.Set("not_auth", true) + return + } + c.Header("WWW-Authenticate", "Basic realm=Authorization Required") + c.AbortWithStatus(http.StatusUnauthorized) + return + } + c.Set(gin.AuthUserKey, user) + } +} + +func processAccounts(accounts gin.Accounts) authPairs { + pairs := make(authPairs, 0, len(accounts)) + for user, password := range accounts { + value := authorizationHeader(user, password) + pairs = append(pairs, authPair{ + value: value, + user: user, + }) + } + return pairs +} + +func authorizationHeader(user, password string) string { + base := user + ":" + password + return "Basic " + base64.StdEncoding.EncodeToString(StringToBytes(base)) +} + +func StringToBytes(s string) (b []byte) { + sh := *(*reflect.StringHeader)(unsafe.Pointer(&s)) + bh := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + bh.Data, bh.Len, bh.Cap = sh.Data, sh.Len, sh.Len + return b +} From e09a032e843cc40fb2e001684bcb4cd5d40fd8ad Mon Sep 17 00:00:00 2001 From: YouROK <8yourok8@mail.ru> Date: Thu, 4 Mar 2021 11:11:39 +0300 Subject: [PATCH 2/5] remove comments --- server/torr/stream.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/server/torr/stream.go b/server/torr/stream.go index 0766dea..92c5b96 100644 --- a/server/torr/stream.go +++ b/server/torr/stream.go @@ -46,20 +46,6 @@ func (t *Torrent) Stream(fileID int, req *http.Request, resp http.ResponseWriter reader := t.NewReader(file) - //off := int64(0) - //buf := make([]byte, 32*1024) - //for true { - // n, err := reader.Read(buf) - // if err != nil { - // fmt.Println("error read", err) - // break - // } - // off = off + int64(n) - // if off%(200*1024*1024) == 0 { - // time.Sleep(time.Second * 15) - // } - //} - log.Println("Connect client") sets.SetViewed(&sets.Viewed{t.Hash().HexString(), fileID}) From 37aa23337dcb55970a1758ce11b0797e7cdcd3fa Mon Sep 17 00:00:00 2001 From: YouROK <8yourok8@mail.ru> Date: Thu, 4 Mar 2021 11:12:14 +0300 Subject: [PATCH 3/5] remove comments --- server/web/api/stream.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/server/web/api/stream.go b/server/web/api/stream.go index 97de8c6..99de164 100644 --- a/server/web/api/stream.go +++ b/server/web/api/stream.go @@ -130,9 +130,6 @@ func streamNoAuth(c *gin.Context) { title := c.Query("title") poster := c.Query("poster") - // c.Header("WWW-Authenticate", "Basic realm=Authorization Required") - // c.AbortWithStatus(http.StatusUnauthorized) - if link == "" { c.AbortWithError(http.StatusBadRequest, errors.New("link should not be empty")) return From 80a5df7a47f4acc098a92384e5f9cff7e25da251 Mon Sep 17 00:00:00 2001 From: YouROK <8yourok8@mail.ru> Date: Thu, 4 Mar 2021 14:44:47 +0300 Subject: [PATCH 4/5] add data --- server/torr/apihelper.go | 1 + 1 file changed, 1 insertion(+) diff --git a/server/torr/apihelper.go b/server/torr/apihelper.go index 333f6a0..cbd5665 100644 --- a/server/torr/apihelper.go +++ b/server/torr/apihelper.go @@ -73,6 +73,7 @@ func GetTorrent(hashHex string) *Torrent { if tr != nil { tr.Title = tor.Title tr.Poster = tor.Poster + tr.Data = tor.Data tr.Size = tor.Size tr.Timestamp = tor.Timestamp tr.GotInfo() From 740b755f499c20a572fd76c344e7af3d9e3a66c2 Mon Sep 17 00:00:00 2001 From: YouROK <8yourok8@mail.ru> Date: Fri, 5 Mar 2021 11:29:40 +0300 Subject: [PATCH 5/5] add def settings --- server/settings/btsets.go | 4 ++++ server/torr/apihelper.go | 9 +++++++++ server/web/api/settings.go | 9 ++++++--- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/server/settings/btsets.go b/server/settings/btsets.go index e31307a..62b8acd 100644 --- a/server/settings/btsets.go +++ b/server/settings/btsets.go @@ -76,6 +76,10 @@ func loadBTSets() { log.TLogln("Error unmarshal btsets", err) } + SetDefault() +} + +func SetDefault() { sets := new(BTSets) sets.EnableDebug = false sets.DisableUTP = true diff --git a/server/torr/apihelper.go b/server/torr/apihelper.go index cbd5665..d6c4d75 100644 --- a/server/torr/apihelper.go +++ b/server/torr/apihelper.go @@ -129,6 +129,15 @@ func SetSettings(set *sets.BTSets) { bts.Connect() } +func SetDefSettings() { + if sets.ReadOnly { + return + } + bts.Disconnect() + sets.SetDefault() + bts.Connect() +} + func Shutdown() { bts.Disconnect() sets.CloseDB() diff --git a/server/web/api/settings.go b/server/web/api/settings.go index 2d7c3a8..0269dcc 100644 --- a/server/web/api/settings.go +++ b/server/web/api/settings.go @@ -10,7 +10,7 @@ import ( "server/torr" ) -//Action: get, set +//Action: get, set, def type setsReqJS struct { requestI Sets *sets.BTSets `json:"sets,omitempty"` @@ -27,11 +27,14 @@ func settings(c *gin.Context) { if req.Action == "get" { c.JSON(200, sets.BTsets) return - } - if req.Action == "set" { + } else if req.Action == "set" { torr.SetSettings(req.Sets) c.Status(200) return + } else if req.Action == "def" { + torr.SetDefSettings() + c.Status(200) + return } c.AbortWithError(http.StatusBadRequest, errors.New("action is empty")) }