summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md35
-rw-r--r--app/app.go58
-rw-r--r--app/config.go32
-rw-r--r--config.json4
-rw-r--r--go.mod1
-rw-r--r--go.sum2
-rw-r--r--media/path.go5
7 files changed, 111 insertions, 26 deletions
diff --git a/README.md b/README.md
index 8124ae4..5aeca5f 100644
--- a/README.md
+++ b/README.md
@@ -96,14 +96,37 @@ Here are some documentation on key configuration items:
"library": [
{
"path": "videos",
- "prefix": ""
+ "prefix": "",
+ "preserve_upload_filename": false
}
],
}
```
-Set `path` to the value of the path where you want to store videos and where
-`tube` will look for new videos.
+- Set `path` to the value of the path where you want to store videos
+and where `tube` will watch for new video files to show up.
+- Set `prefix` to add a directory component in the video URL.
+- Set the (optional) `preserve_upload_filename` parameter to `true`,
+to to preserve the name of files that are uploaded to this location.
+
+You can add more than one location for video files.
+```#!json
+{
+ "library": [
+ {
+ "path": "/path/to/cat/videos",
+ "prefix": "cats",
+ "preserve_upload_filename": true
+ },
+ {
+ "path": "relative/dog/directory/",
+ "prefix": "dogs"
+ },
+ ],
+}
+```
+The path will be visible on the upload page and clients can select a
+destination for their uploads. Both `prefix` and `path` need to be unique.
### Server Options / Upload Path and Max Upload Size
@@ -114,6 +137,7 @@ Set `path` to the value of the path where you want to store videos and where
"port": 8000,
"store_path": "tube.db",
"upload_path": "uploads",
+ "preserve_upload_filename": false,
"max_upload_size": 104857600
}
}
@@ -129,6 +153,11 @@ Set `path` to the value of the path where you want to store videos and where
- Set `upload_path` to a directory that you wish to use as a temporary working
space for `tube` to store uploaded videos and process them. This can be a
tmpfs file system for example for faster I/O.
+- Set `preserve_upload_filename` parameter to `true` and tube will try to
+ preserve the filename that was transmitted by the client. The default is
+ to give random filenames to uploaded files.
+ If you set it to `true` in the "server" node, it will be active for all
+ library locations.
- Set `max_upload_size` to the maximum number of bytes you wish to impose on
uploaded and imported videos. Upload(s)/Import(s) that exceed this size will
by denied by the server. This is a saftey measure so as to not DoS the
diff --git a/app/app.go b/app/app.go
index f2d729a..9d0828b 100644
--- a/app/app.go
+++ b/app/app.go
@@ -21,6 +21,7 @@ import (
"git.mills.io/prologic/tube/templates"
"git.mills.io/prologic/tube/utils"
+ "github.com/cyphar/filepath-securejoin"
"github.com/dustin/go-humanize"
"github.com/fsnotify/fsnotify"
"github.com/gorilla/handlers"
@@ -148,8 +149,9 @@ func (a *App) Run() error {
for _, pc := range a.Config.Library {
pc.Path = filepath.Clean(pc.Path)
p := &media.Path{
- Path: pc.Path,
- Prefix: pc.Prefix,
+ Path: pc.Path,
+ Prefix: pc.Prefix,
+ PreserveUploadFilename: pc.PreserveUploadFilename,
}
err := a.Library.AddPath(p)
if err != nil {
@@ -215,6 +217,11 @@ func (a *App) indexHandler(w http.ResponseWriter, r *http.Request) {
}
}
+func filenameWithoutExtension(path string) (stem string) {
+ var basename string = filepath.Base(path)
+ return basename[0:len(basename)-len(filepath.Ext(basename))]
+}
+
// HTTP handler for /upload
func (a *App) uploadHandler(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
@@ -278,10 +285,49 @@ func (a *App) uploadHandler(w http.ResponseWriter, r *http.Request) {
return
}
- vf := filepath.Join(
- a.Library.Paths[targetLibraryPath].Path,
- fmt.Sprintf("%s.mp4", shortuuid.New()),
- )
+ // Here we set the final filename for the video file after transcoding.
+ var vf string
+ if a.Config.Server.PreserveUploadFilename ||
+ a.Library.Paths[targetLibraryPath].PreserveUploadFilename {
+ vf, err = securejoin.SecureJoin(
+ a.Library.Paths[targetLibraryPath].Path,
+ fmt.Sprintf("%s.mp4", filenameWithoutExtension(handler.Filename)),
+ )
+ } else {
+ vf, err = securejoin.SecureJoin(
+ a.Library.Paths[targetLibraryPath].Path,
+ fmt.Sprintf("%s.mp4", shortuuid.New()),
+ )
+ }
+ if err != nil {
+ err := fmt.Errorf("error creating file name in target library: %w", err)
+ log.Error(err)
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ // If the (sanitized) original filename collides with an existing file,
+ // we try to add a shortuuid() to it until we find one that doesn't exist.
+ for _, err := os.Stat(vf) ; ! os.IsNotExist(err) ; _, err = os.Stat(vf) {
+ if err != nil {
+ log.Error(err)
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ log.Warn("File '"+ vf + "' already exists.");
+ vf, err = securejoin.SecureJoin(
+ a.Library.Paths[targetLibraryPath].Path,
+ fmt.Sprintf("%s_%s.mp4", filenameWithoutExtension(vf), shortuuid.New()),
+ )
+ if err != nil {
+ err := fmt.Errorf("error creating file name in target library: %w", err)
+ log.Error(err)
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ log.Warn("Using filename '" + vf + "' instead.");
+ }
+
+
thumbFn1 := fmt.Sprintf("%s.jpg", strings.TrimSuffix(tf.Name(), filepath.Ext(tf.Name())))
thumbFn2 := fmt.Sprintf("%s.jpg", strings.TrimSuffix(vf, filepath.Ext(vf)))
diff --git a/app/config.go b/app/config.go
index 2b11688..7d886c0 100644
--- a/app/config.go
+++ b/app/config.go
@@ -17,17 +17,19 @@ type Config struct {
// PathConfig settings for media library path.
type PathConfig struct {
- Path string `json:"path"`
- Prefix string `json:"prefix"`
+ Path string `json:"path"`
+ Prefix string `json:"prefix"`
+ PreserveUploadFilename bool `json:"preserve_upload_filename,omitempty"`
}
// ServerConfig settings for App Server.
type ServerConfig struct {
- Host string `json:"host"`
- Port int `json:"port"`
- StorePath string `json:"store_path"`
- UploadPath string `json:"upload_path"`
- MaxUploadSize int64 `json:"max_upload_size"`
+ Host string `json:"host"`
+ Port int `json:"port"`
+ StorePath string `json:"store_path"`
+ UploadPath string `json:"upload_path"`
+ PreserveUploadFilename bool `json:"preserve_upload_filename,omitempty"`
+ MaxUploadSize int64 `json:"max_upload_size"`
}
// ThumbnailerConfig settings for Transcoder
@@ -68,16 +70,18 @@ func DefaultConfig() *Config {
return &Config{
Library: []*PathConfig{
&PathConfig{
- Path: "videos",
- Prefix: "",
+ Path: "videos",
+ Prefix: "",
+ PreserveUploadFilename: false,
},
},
Server: &ServerConfig{
- Host: "0.0.0.0",
- Port: 8000,
- StorePath: "tube.db",
- UploadPath: "uploads",
- MaxUploadSize: 104857600,
+ Host: "0.0.0.0",
+ Port: 8000,
+ StorePath: "tube.db",
+ UploadPath: "uploads",
+ PreserveUploadFilename: false,
+ MaxUploadSize: 104857600,
},
Thumbnailer: &ThumbnailerConfig{
Timeout: 60,
diff --git a/config.json b/config.json
index eb43aac..bb764f4 100644
--- a/config.json
+++ b/config.json
@@ -2,7 +2,8 @@
"library": [
{
"path": "videos",
- "prefix": ""
+ "prefix": "",
+ "preserve_upload_filename": false
}
],
"server": {
@@ -10,6 +11,7 @@
"port": 8000,
"store_path": "tube.db",
"upload_path": "uploads",
+ "preserve_upload_filename": false,
"max_upload_size": 104857600
},
"thumbnailer": {
diff --git a/go.mod b/go.mod
index 1d9352f..879b5b6 100644
--- a/go.mod
+++ b/go.mod
@@ -22,6 +22,7 @@ require (
github.com/abcum/lcp v0.0.0-20201209214815-7a3f3840be81 // indirect
github.com/antchfx/jsonquery v1.3.0 // indirect
github.com/antchfx/xpath v1.2.1 // indirect
+ github.com/cyphar/filepath-securejoin v0.2.3 // indirect
github.com/felixge/httpsnoop v1.0.3 // indirect
github.com/gofrs/flock v0.8.1 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
diff --git a/go.sum b/go.sum
index 4a3c321..29bd1ac 100644
--- a/go.sum
+++ b/go.sum
@@ -85,6 +85,8 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI=
+github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
diff --git a/media/path.go b/media/path.go
index 1248ed5..bc40b37 100644
--- a/media/path.go
+++ b/media/path.go
@@ -2,6 +2,7 @@ package media
// Path represents a media library path.
type Path struct {
- Path string
- Prefix string
+ Path string
+ Prefix string
+ PreserveUploadFilename bool
}