1
Fork 0

Cleanup media routes and media_name generation

This commit is contained in:
viktorstrate 2020-10-30 17:14:09 +01:00
parent 60e93a8497
commit 74581ee090
7 changed files with 61 additions and 29 deletions

View File

@ -25,9 +25,9 @@ require (
github.com/vektah/gqlparser/v2 v2.1.0
github.com/wsxiaoys/terminal v0.0.0-20160513160801-0940f3fc43a0
github.com/xor-gate/goexif2 v1.1.0
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
golang.org/x/image v0.0.0-20200801110659-972c09e46d76
golang.org/x/net v0.0.0-20200904194848-62affa334b73 // indirect
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5
golang.org/x/net v0.0.0-20201029221708-28c70e62bb1d // indirect
gopkg.in/vansante/go-ffprobe.v2 v2.0.2
gopkg.in/yaml.v2 v2.3.0 // indirect
)

View File

@ -118,9 +118,13 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20200801110659-972c09e46d76 h1:U7GPaoQyQmX+CBRWXKrvRzWTbd+slqeSh8uARsIyhAw=
golang.org/x/image v0.0.0-20200801110659-972c09e46d76/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5 h1:QelT11PB4FXiDEXucrfNckHoFxwt8USGY1ajP1ZF5lM=
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@ -129,6 +133,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwL
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA=
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201029221708-28c70e62bb1d h1:dOiJ2n2cMwGLce/74I/QHMbnpk5GfY7InR8rczoMqRM=
golang.org/x/net v0.0.0-20201029221708-28c70e62bb1d/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -139,7 +145,10 @@ golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtD
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd h1:oMEQDWVXVNpceQoVd1JN3CQ7LYJJzs5qWqZIUcxXHHw=
golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=

View File

@ -3,6 +3,7 @@ package models
import (
"database/sql"
"path"
"strings"
"time"
"github.com/viktorstrate/photoview/api/utils"
@ -85,6 +86,15 @@ func (p *MediaURL) URL() string {
return imageUrl.String()
}
func SanitizeMediaName(mediaName string) string {
result := mediaName
result = strings.ReplaceAll(result, "/", "")
result = strings.ReplaceAll(result, "\\", "")
result = strings.ReplaceAll(result, " ", "_")
result = strings.ReplaceAll(result, ".", "_")
return result
}
func NewMediaURLFromRow(row *sql.Row) (*MediaURL, error) {
url := MediaURL{}

View File

@ -0,0 +1,20 @@
package models
import (
"testing"
)
func TestSanitizeMediaName(t *testing.T) {
tests := [][2]string{
{"filename.png", "filename_png"},
{"../..\\escape", "____escape"},
{"..", "__"},
{"..\\/", "__"},
}
for i, test := range tests {
if SanitizeMediaName(test[0]) != test[1] {
t.Errorf("SanitizeMediaName test %d failed: got '%s', expected '%s'", i, test[1], SanitizeMediaName(test[0]))
}
}
}

View File

@ -21,19 +21,17 @@ func RegisterPhotoRoutes(db *sql.DB, router *mux.Router) {
router.HandleFunc("/{name}", func(w http.ResponseWriter, r *http.Request) {
media_name := mux.Vars(r)["name"]
row := db.QueryRow("SELECT media_url.purpose, media_url.content_type, media_url.media_id FROM media_url, media WHERE media_url.media_name = ? AND media_url.media_id = media.media_id", media_name)
row := db.QueryRow("SELECT media_url.* FROM media_url JOIN media ON media_url.media_id = media.media_id WHERE media_url.media_name = ?", media_name)
var purpose models.MediaPurpose
var content_type string
var media_id int
mediaUrl, err := models.NewMediaURLFromRow(row)
if err := row.Scan(&purpose, &content_type, &media_id); err != nil {
if err != nil {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("404"))
return
}
row = db.QueryRow("SELECT * FROM media WHERE media_id = ?", media_id)
row = db.QueryRow("SELECT * FROM media WHERE media_id = ?", mediaUrl.MediaId)
media, err := models.NewMediaFromRow(row)
if err != nil {
log.Printf("WARN: %s", err)
@ -53,12 +51,12 @@ func RegisterPhotoRoutes(db *sql.DB, router *mux.Router) {
var cachedPath string
var file *os.File = nil
if purpose == models.PhotoThumbnail || purpose == models.PhotoHighRes || purpose == models.VideoThumbnail {
cachedPath = path.Join(scanner.PhotoCache(), strconv.Itoa(media.AlbumId), strconv.Itoa(media_id), media_name)
} else if purpose == models.MediaOriginal {
if mediaUrl.Purpose == models.PhotoThumbnail || mediaUrl.Purpose == models.PhotoHighRes || mediaUrl.Purpose == models.VideoThumbnail {
cachedPath = path.Join(scanner.PhotoCache(), strconv.Itoa(media.AlbumId), strconv.Itoa(mediaUrl.MediaId), mediaUrl.MediaName)
} else if mediaUrl.Purpose == models.MediaOriginal {
cachedPath = media.Path
} else {
log.Printf("ERROR: Can not handle media_purpose for photo: %s\n", purpose)
log.Printf("ERROR: Can not handle media_purpose for photo: %s\n", mediaUrl.Purpose)
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("internal server error"))
return
@ -98,7 +96,7 @@ func RegisterPhotoRoutes(db *sql.DB, router *mux.Router) {
}
}
w.Header().Set("Content-Type", content_type)
w.Header().Set("Content-Type", mediaUrl.ContentType)
if stats, err := file.Stat(); err == nil {
w.Header().Set("Content-Length", fmt.Sprintf("%d", stats.Size()))
}

View File

@ -18,18 +18,16 @@ func RegisterVideoRoutes(db *sql.DB, router *mux.Router) {
router.HandleFunc("/{name}", func(w http.ResponseWriter, r *http.Request) {
media_name := mux.Vars(r)["name"]
row := db.QueryRow("SELECT media_url.purpose, media_url.media_id FROM media_url, media WHERE media_url.media_name = ? AND media_url.media_id = media.media_id", media_name)
row := db.QueryRow("SELECT media_url.* FROM media_url JOIN media ON media_url.media_id = media.media_id WHERE media_url.media_name = ?", media_name)
mediaURL, err := models.NewMediaURLFromRow(row)
var purpose models.MediaPurpose
var media_id int
if err := row.Scan(&purpose, &media_id); err != nil {
if err != nil {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("404"))
return
}
row = db.QueryRow("SELECT * FROM media WHERE media_id = ?", media_id)
row = db.QueryRow("SELECT * FROM media WHERE media_id = ?", mediaURL.MediaId)
media, err := models.NewMediaFromRow(row)
if err != nil {
log.Printf("WARN: %s", err)
@ -48,10 +46,10 @@ func RegisterVideoRoutes(db *sql.DB, router *mux.Router) {
var cachedPath string
if purpose == models.VideoWeb {
cachedPath = path.Join(scanner.PhotoCache(), strconv.Itoa(media.AlbumId), strconv.Itoa(media_id), media_name)
if mediaURL.Purpose == models.VideoWeb {
cachedPath = path.Join(scanner.PhotoCache(), strconv.Itoa(media.AlbumId), strconv.Itoa(mediaURL.MediaId), mediaURL.MediaName)
} else {
log.Printf("ERROR: Can not handle media_purpose for video: %s\n", purpose)
log.Printf("ERROR: Can not handle media_purpose for video: %s\n", mediaURL.Purpose)
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("internal server error"))
return

View File

@ -7,7 +7,6 @@ import (
"os"
"path"
"strconv"
"strings"
"github.com/pkg/errors"
"github.com/viktorstrate/photoview/api/graphql/models"
@ -112,8 +111,7 @@ func processPhoto(tx *sql.Tx, imageData *EncodeMediaData, photoCachePath *string
didProcess = true
highres_name := fmt.Sprintf("highres_%s_%s", path.Base(photo.Path), utils.GenerateToken())
highres_name = strings.ReplaceAll(highres_name, ".", "_")
highres_name = strings.ReplaceAll(highres_name, " ", "_")
highres_name = models.SanitizeMediaName(highres_name)
highres_name = highres_name + ".jpg"
baseImagePath = path.Join(*photoCachePath, highres_name)
@ -176,8 +174,7 @@ func processPhoto(tx *sql.Tx, imageData *EncodeMediaData, photoCachePath *string
didProcess = true
thumbnail_name := fmt.Sprintf("thumbnail_%s_%s", path.Base(photo.Path), utils.GenerateToken())
thumbnail_name = strings.ReplaceAll(thumbnail_name, ".", "_")
thumbnail_name = strings.ReplaceAll(thumbnail_name, " ", "_")
thumbnail_name = models.SanitizeMediaName(thumbnail_name)
thumbnail_name = thumbnail_name + ".jpg"
// thumbnailImage, err := imageData.ThumbnailImage(tx)
@ -253,7 +250,7 @@ func saveOriginalPhotoToDB(tx *sql.Tx, photo *models.Media, imageData *EncodeMed
photoBaseExt := path.Ext(photoName)
original_image_name := fmt.Sprintf("%s_%s", photoBaseName, utils.GenerateToken())
original_image_name = strings.ReplaceAll(original_image_name, " ", "_") + photoBaseExt
original_image_name = models.SanitizeMediaName(original_image_name) + photoBaseExt
contentType, err := imageData.ContentType()
if err != nil {