mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-24 02:02:36 -04:00
For now, disabled all audios variants since it's handling will be entierly different. Found out that audio and video segments don't need to lineup. (same number/duration). As long as the whole file stays long enough it's fine. Video handling now fails when there are too many keyfranmes close enough (like 0.01, 0.3, 0.4, 2, 4). It would only output 3 segments instead of the 5 we would want. We might get arround using fragments containing more than 1 keyframe if we handle things right
99 lines
2.7 KiB
Go
99 lines
2.7 KiB
Go
package main
|
|
|
|
import (
|
|
"crypto/sha1"
|
|
"encoding/base64"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/labstack/echo/v4"
|
|
"github.com/zoriya/kyoo/transcoder/src"
|
|
)
|
|
|
|
// Encode the version in the hash path to update cached values.
|
|
// Older versions won't be deleted (needed to allow multiples versions of the transcoder to run at the same time)
|
|
// If the version changes a lot, we might want to automatically delete older versions.
|
|
var version = "v3-"
|
|
|
|
func GetPath(c echo.Context) (string, string, error) {
|
|
key := c.Param("path")
|
|
if key == "" {
|
|
return "", "", echo.NewHTTPError(http.StatusBadRequest, "Missing resouce path.")
|
|
}
|
|
pathb, err := base64.RawURLEncoding.DecodeString(key)
|
|
if err != nil {
|
|
return "", "", echo.NewHTTPError(http.StatusBadRequest, "Invalid path. Should be base64url (without padding) encoded.")
|
|
}
|
|
path := filepath.Clean(string(pathb))
|
|
if !filepath.IsAbs(path) {
|
|
return "", "", echo.NewHTTPError(http.StatusBadRequest, "Absolute path required.")
|
|
}
|
|
if !strings.HasPrefix(path, src.Settings.SafePath) {
|
|
return "", "", echo.NewHTTPError(http.StatusBadRequest, "Selected path is not marked as safe.")
|
|
}
|
|
hash, err := getHash(path)
|
|
if err != nil {
|
|
return "", "", echo.NewHTTPError(http.StatusNotFound, "File does not exist")
|
|
}
|
|
|
|
return path, hash, nil
|
|
}
|
|
|
|
func getHash(path string) (string, error) {
|
|
info, err := os.Stat(path)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
h := sha1.New()
|
|
h.Write([]byte(path))
|
|
h.Write([]byte(info.ModTime().String()))
|
|
sha := hex.EncodeToString(h.Sum(nil))
|
|
return version + sha, nil
|
|
}
|
|
|
|
func SanitizePath(path string) error {
|
|
if strings.Contains(path, "/") || strings.Contains(path, "..") {
|
|
return echo.NewHTTPError(http.StatusBadRequest, "Invalid parameter. Can't contains path delimiters or ..")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func GetClientId(c echo.Context) (string, error) {
|
|
key := c.Request().Header.Get("X-CLIENT-ID")
|
|
if key == "" {
|
|
return "", echo.NewHTTPError(http.StatusBadRequest, "missing client id. Please specify the X-CLIENT-ID header to a guid constant for the lifetime of the player (but unique per instance)")
|
|
}
|
|
return key, nil
|
|
}
|
|
|
|
func ParseSegment(segment string) (int32, error) {
|
|
if segment == "init.mp4" {
|
|
return -1, nil
|
|
}
|
|
var ret int32
|
|
_, err := fmt.Sscanf(segment, "segment-%d.m4s", &ret)
|
|
if err != nil {
|
|
return 0, echo.NewHTTPError(http.StatusBadRequest, "Could not parse segment.")
|
|
}
|
|
return ret, nil
|
|
}
|
|
|
|
func ErrorHandler(err error, c echo.Context) {
|
|
code := http.StatusInternalServerError
|
|
var message string
|
|
if he, ok := err.(*echo.HTTPError); ok {
|
|
code = he.Code
|
|
message = fmt.Sprint(he.Message)
|
|
} else {
|
|
c.Logger().Error(err)
|
|
message = "Internal server error"
|
|
}
|
|
c.JSON(code, struct {
|
|
Errors []string `json:"errors"`
|
|
}{Errors: []string{message}})
|
|
}
|