Added basic input verification for sortOrder/refreshInterval

This commit is contained in:
Seednode 2022-11-10 10:09:39 -06:00
parent 28af94cba3
commit ea4b1be5c3
4 changed files with 65 additions and 28 deletions

View File

@ -50,7 +50,7 @@ Note: These patterns require sequentially-numbered files matching the following
## Refresh ## Refresh
If a `refresh=<time in seconds>` query parameter is provided, the page will reload after that interval. If a non-zero `refresh=<time in seconds>` query parameter is provided, the page will reload after that interval.
This can be used to generate a sort of slideshow of images. This can be used to generate a sort of slideshow of images.

View File

@ -15,7 +15,6 @@ import (
"math/rand" "math/rand"
"os" "os"
"path/filepath" "path/filepath"
"regexp"
"runtime" "runtime"
"strconv" "strconv"
"strings" "strings"
@ -212,13 +211,13 @@ func appendPaths(path string, files *Files, filters *Filters, stats *Stats) erro
return nil return nil
} }
func getNewFile(paths []string, filters *Filters, sortOrder string, re regexp.Regexp, fileCache *[]string) (string, error) { func getNewFile(paths []string, filters *Filters, sortOrder string, regexes *Regexes, fileCache *[]string) (string, error) {
filePath, err := pickFile(paths, filters, sortOrder, fileCache) filePath, err := pickFile(paths, filters, sortOrder, fileCache)
if err != nil { if err != nil {
return "", nil return "", nil
} }
path, err := splitPath(filePath, re) path, err := splitPath(filePath, regexes)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -256,8 +255,8 @@ func getNewFile(paths []string, filters *Filters, sortOrder string, re regexp.Re
return filePath, nil return filePath, nil
} }
func getNextFile(filePath, sortOrder string, re regexp.Regexp) (string, error) { func getNextFile(filePath, sortOrder string, regexes *Regexes) (string, error) {
path, err := splitPath(filePath, re) path, err := splitPath(filePath, regexes)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -279,11 +278,11 @@ func getNextFile(filePath, sortOrder string, re regexp.Regexp) (string, error) {
return fileName, err return fileName, err
} }
func splitPath(path string, re regexp.Regexp) (*Path, error) { func splitPath(path string, regexes *Regexes) (*Path, error) {
p := Path{} p := Path{}
var err error var err error
split := re.FindAllStringSubmatch(path, -1) split := regexes.Filename.FindAllStringSubmatch(path, -1)
if len(split) < 1 || len(split[0]) < 3 { if len(split) < 1 || len(split[0]) < 3 {
return &Path{}, nil return &Path{}, nil

View File

@ -10,7 +10,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
var Version = "0.25.2" var Version = "0.25.3"
func init() { func init() {
rootCmd.AddCommand(versionCmd) rootCmd.AddCommand(versionCmd)

View File

@ -28,6 +28,11 @@ const (
RedirectStatusCode int = http.StatusSeeOther RedirectStatusCode int = http.StatusSeeOther
) )
type Regexes struct {
Alphanumeric *regexp.Regexp
Filename *regexp.Regexp
}
type Filters struct { type Filters struct {
Includes []string Includes []string
Excludes []string Excludes []string
@ -81,7 +86,31 @@ func notFound(w http.ResponseWriter, r *http.Request, filePath string) error {
return nil return nil
} }
func splitQueryParams(query string) []string { func getRefreshInterval(r *http.Request) string {
refreshInterval := r.URL.Query().Get("refresh")
if refreshInterval == "" {
refreshInterval = "0"
}
num, err := strconv.Atoi(refreshInterval)
if err != nil || num < 0 {
refreshInterval = "0"
}
return refreshInterval
}
func getSortOrder(r *http.Request) string {
sortOrder := r.URL.Query().Get("sort")
if !(sortOrder == "asc" || sortOrder == "desc") {
sortOrder = ""
}
return sortOrder
}
func splitQueryParams(query string, regexes *Regexes) []string {
if query == "" { if query == "" {
return []string{} return []string{}
} }
@ -89,7 +118,11 @@ func splitQueryParams(query string) []string {
params := strings.Split(query, ",") params := strings.Split(query, ",")
for i := 0; i < len(params); i++ { for i := 0; i < len(params); i++ {
params[i] = strings.ToLower(params[i]) isAlphanumeric := regexes.Alphanumeric.MatchString(params[i])
if isAlphanumeric {
params[i] = strings.ToLower(params[i])
}
} }
return params return params
@ -179,12 +212,11 @@ func serveHtml(w http.ResponseWriter, r *http.Request, filePath string, dimensio
w.Header().Add("Content-Type", "text/html") w.Header().Add("Content-Type", "text/html")
refreshInterval := r.URL.Query().Get("refresh") refreshInterval := getRefreshInterval(r)
if refreshInterval == "" {
refreshInterval = "0"
}
queryParams := generateQueryParams(filters, r.URL.Query().Get("sort"), refreshInterval) sortOrder := getSortOrder(r)
queryParams := generateQueryParams(filters, sortOrder, refreshInterval)
var htmlBody strings.Builder var htmlBody strings.Builder
htmlBody.WriteString(`<!DOCTYPE html><html lang="en"><head>`) htmlBody.WriteString(`<!DOCTYPE html><html lang="en"><head>`)
@ -281,7 +313,7 @@ func serveStaticFileHandler(paths []string) http.HandlerFunc {
} }
} }
func serveHtmlHandler(paths []string, re regexp.Regexp, fileCache *[]string) http.HandlerFunc { func serveHtmlHandler(paths []string, regexes *Regexes, fileCache *[]string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
refererUri, err := stripQueryParams(refererToUri(r.Referer())) refererUri, err := stripQueryParams(refererToUri(r.Referer()))
if err != nil { if err != nil {
@ -289,29 +321,26 @@ func serveHtmlHandler(paths []string, re regexp.Regexp, fileCache *[]string) htt
} }
filters := Filters{} filters := Filters{}
filters.Includes = splitQueryParams(r.URL.Query().Get("include")) filters.Includes = splitQueryParams(r.URL.Query().Get("include"), regexes)
filters.Excludes = splitQueryParams(r.URL.Query().Get("exclude")) filters.Excludes = splitQueryParams(r.URL.Query().Get("exclude"), regexes)
sortOrder := r.URL.Query().Get("sort") sortOrder := getSortOrder(r)
refreshInterval := r.URL.Query().Get("refresh") refreshInterval := getRefreshInterval(r)
if refreshInterval == "" {
refreshInterval = "0"
}
if r.URL.Path == "/" { if r.URL.Path == "/" {
var filePath string var filePath string
var err error var err error
if refererUri != "" { if refererUri != "" {
filePath, err = getNextFile(refererUri, sortOrder, re) filePath, err = getNextFile(refererUri, sortOrder, regexes)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
} }
if filePath == "" { if filePath == "" {
filePath, err = getNewFile(paths, &filters, sortOrder, re, fileCache) filePath, err = getNewFile(paths, &filters, sortOrder, regexes, fileCache)
switch { switch {
case err != nil && err == ErrNoImagesFound: case err != nil && err == ErrNoImagesFound:
notFound(w, r, filePath) notFound(w, r, filePath)
@ -372,6 +401,15 @@ func serveHtmlHandler(paths []string, re regexp.Regexp, fileCache *[]string) htt
func doNothing(http.ResponseWriter, *http.Request) {} func doNothing(http.ResponseWriter, *http.Request) {}
func generateRegularExpressions() *Regexes {
r := Regexes{}
r.Filename = regexp.MustCompile(`(.+)([0-9]{3})(\..+)`)
r.Alphanumeric = regexp.MustCompile(`^[a-zA-Z0-9]*$`)
return &r
}
func ServePage(args []string) error { func ServePage(args []string) error {
fmt.Printf("roulette v%v\n\n", Version) fmt.Printf("roulette v%v\n\n", Version)
@ -380,13 +418,13 @@ func ServePage(args []string) error {
return err return err
} }
re := regexp.MustCompile(`(.+)([0-9]{3})(\..+)`) regexes := generateRegularExpressions()
rand.Seed(time.Now().UnixNano()) rand.Seed(time.Now().UnixNano())
fileCache := []string{} fileCache := []string{}
http.Handle("/", serveHtmlHandler(paths, *re, &fileCache)) http.Handle("/", serveHtmlHandler(paths, regexes, &fileCache))
http.Handle(Prefix+"/", http.StripPrefix(Prefix, serveStaticFileHandler(paths))) http.Handle(Prefix+"/", http.StripPrefix(Prefix, serveStaticFileHandler(paths)))
http.HandleFunc("/favicon.ico", doNothing) http.HandleFunc("/favicon.ico", doNothing)