Compare commits
3 Commits
9b6d9464e6
...
ebb5e48d9a
Author | SHA1 | Date |
---|---|---|
Seednode | ebb5e48d9a | |
Seednode | 9e458aa0bb | |
Seednode | d568d10e78 |
50
cmd/files.go
50
cmd/files.go
|
@ -24,10 +24,9 @@ import (
|
||||||
"seedno.de/seednode/roulette/types"
|
"seedno.de/seednode/roulette/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type regexes struct {
|
var (
|
||||||
alphanumeric *regexp.Regexp
|
filename = regexp.MustCompile(`(.+?)([0-9]*)(\..+)`)
|
||||||
filename *regexp.Regexp
|
)
|
||||||
}
|
|
||||||
|
|
||||||
type scanStats struct {
|
type scanStats struct {
|
||||||
filesMatched chan int
|
filesMatched chan int
|
||||||
|
@ -79,14 +78,14 @@ func kill(path string, index *fileIndex) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newFile(list []string, sortOrder string, regexes *regexes, formats types.Types) (string, error) {
|
func newFile(list []string, sortOrder string, formats types.Types) (string, error) {
|
||||||
path, err := pickFile(list)
|
path, err := pickFile(list)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
if sortOrder == "asc" || sortOrder == "desc" {
|
if sortOrder == "asc" || sortOrder == "desc" {
|
||||||
splitPath, err := split(path, regexes)
|
splitPath, err := split(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -125,8 +124,8 @@ func newFile(list []string, sortOrder string, regexes *regexes, formats types.Ty
|
||||||
return path, nil
|
return path, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func nextFile(filePath, sortOrder string, regexes *regexes, formats types.Types) (string, error) {
|
func nextFile(filePath, sortOrder string, formats types.Types) (string, error) {
|
||||||
splitPath, err := split(filePath, regexes)
|
splitPath, err := split(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -241,10 +240,6 @@ func hasSupportedFiles(path string, formats types.Types) (bool, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func walkPath(path string, fileChannel chan<- string, wg1 *sync.WaitGroup, stats *scanStats, limit chan struct{}, formats types.Types, errorChannel chan<- error) {
|
func walkPath(path string, fileChannel chan<- string, wg1 *sync.WaitGroup, stats *scanStats, limit chan struct{}, formats types.Types, errorChannel chan<- error) {
|
||||||
defer func() {
|
|
||||||
wg1.Done()
|
|
||||||
}()
|
|
||||||
|
|
||||||
limit <- struct{}{}
|
limit <- struct{}{}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
@ -265,11 +260,13 @@ func walkPath(path string, fileChannel chan<- string, wg1 *sync.WaitGroup, stats
|
||||||
var skipDir = false
|
var skipDir = false
|
||||||
|
|
||||||
for _, node := range nodes {
|
for _, node := range nodes {
|
||||||
if Ignore && !node.IsDir() && node.Name() == IgnoreFile {
|
if !node.IsDir() {
|
||||||
skipDir = true
|
files++
|
||||||
}
|
|
||||||
|
|
||||||
files++
|
if Ignore && node.Name() == IgnoreFile {
|
||||||
|
skipDir = true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var skipFiles = false
|
var skipFiles = false
|
||||||
|
@ -297,18 +294,19 @@ func walkPath(path string, fileChannel chan<- string, wg1 *sync.WaitGroup, stats
|
||||||
case node.IsDir() && Recursive:
|
case node.IsDir() && Recursive:
|
||||||
wg1.Add(1)
|
wg1.Add(1)
|
||||||
|
|
||||||
walkPath(fullPath, fileChannel, wg1, stats, limit, formats, errorChannel)
|
go func() {
|
||||||
|
defer wg1.Done()
|
||||||
|
|
||||||
|
walkPath(fullPath, fileChannel, wg1, stats, limit, formats, errorChannel)
|
||||||
|
}()
|
||||||
|
|
||||||
case !node.IsDir() && !skipFiles:
|
case !node.IsDir() && !skipFiles:
|
||||||
path, err := normalizePath(fullPath)
|
path, err := normalizePath(fullPath)
|
||||||
if err != nil {
|
|
||||||
|
switch {
|
||||||
|
case err != nil:
|
||||||
errorChannel <- err
|
errorChannel <- err
|
||||||
|
case formats.Validate(path) || Fallback:
|
||||||
stats.filesSkipped <- 1
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if formats.Validate(path) || Fallback {
|
|
||||||
fileChannel <- path
|
fileChannel <- path
|
||||||
|
|
||||||
stats.filesMatched <- 1
|
stats.filesMatched <- 1
|
||||||
|
@ -421,6 +419,8 @@ func scanPaths(paths []string, sort string, index *fileIndex, formats types.Type
|
||||||
wg1.Add(1)
|
wg1.Add(1)
|
||||||
|
|
||||||
go func(i int) {
|
go func(i int) {
|
||||||
|
defer wg1.Done()
|
||||||
|
|
||||||
walkPath(paths[i], fileChannel, &wg1, stats, limit, formats, errorChannel)
|
walkPath(paths[i], fileChannel, &wg1, stats, limit, formats, errorChannel)
|
||||||
}(i)
|
}(i)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
@ -17,7 +18,7 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
AllowedCharacters string = `^[A-z0-9.\-_]+$`
|
AllowedCharacters string = `^[A-z0-9.\-_]+$`
|
||||||
ReleaseVersion string = "5.0.2"
|
ReleaseVersion string = "5.0.4"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -167,8 +168,6 @@ func init() {
|
||||||
|
|
||||||
rootCmd.Flags().SetInterspersed(true)
|
rootCmd.Flags().SetInterspersed(true)
|
||||||
|
|
||||||
rootCmd.MarkFlagsMutuallyExclusive("debug", "exit-on-error")
|
|
||||||
|
|
||||||
rootCmd.MarkFlagsOneRequired(RequiredArgs...)
|
rootCmd.MarkFlagsOneRequired(RequiredArgs...)
|
||||||
|
|
||||||
rootCmd.SetHelpCommand(&cobra.Command{
|
rootCmd.SetHelpCommand(&cobra.Command{
|
||||||
|
@ -180,4 +179,6 @@ func init() {
|
||||||
rootCmd.SilenceErrors = true
|
rootCmd.SilenceErrors = true
|
||||||
|
|
||||||
rootCmd.Version = ReleaseVersion
|
rootCmd.Version = ReleaseVersion
|
||||||
|
|
||||||
|
log.SetFlags(0)
|
||||||
}
|
}
|
||||||
|
|
14
cmd/sort.go
14
cmd/sort.go
|
@ -38,8 +38,8 @@ func (splitPath *splitPath) decrement() string {
|
||||||
return fmt.Sprintf("%0*d", len(splitPath.number), asInt-1)
|
return fmt.Sprintf("%0*d", len(splitPath.number), asInt-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func split(path string, regexes *regexes) (*splitPath, error) {
|
func split(path string) (*splitPath, error) {
|
||||||
split := regexes.filename.FindAllStringSubmatch(path, -1)
|
split := filename.FindAllStringSubmatch(path, -1)
|
||||||
|
|
||||||
if len(split) < 1 || len(split[0]) < 3 {
|
if len(split) < 1 || len(split[0]) < 3 {
|
||||||
return &splitPath{}, nil
|
return &splitPath{}, nil
|
||||||
|
@ -54,8 +54,8 @@ func split(path string, regexes *regexes) (*splitPath, error) {
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRange(path string, regexes *regexes, index *fileIndex) (string, string, error) {
|
func getRange(path string, index *fileIndex) (string, string, error) {
|
||||||
splitPath, err := split(path, regexes)
|
splitPath, err := split(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ func getRange(path string, regexes *regexes, index *fileIndex) (string, string,
|
||||||
|
|
||||||
Loop:
|
Loop:
|
||||||
for _, val := range list {
|
for _, val := range list {
|
||||||
splitVal, err := split(val, regexes)
|
splitVal, err := split(val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
@ -94,8 +94,8 @@ func pathUrlEscape(path string) string {
|
||||||
return strings.Replace(path, `'`, `%27`, -1)
|
return strings.Replace(path, `'`, `%27`, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func paginateSorted(path, first, last, queryParams string, regexes *regexes, formats types.Types) (string, error) {
|
func paginateSorted(path, first, last, queryParams string, formats types.Types) (string, error) {
|
||||||
split, err := split(path, regexes)
|
split, err := split(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ func sortOrder(r *http.Request) string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func splitQueryParams(query string, regexes *regexes) []string {
|
func splitQueryParams(query string) []string {
|
||||||
results := []string{}
|
results := []string{}
|
||||||
|
|
||||||
if query == "" {
|
if query == "" {
|
||||||
|
|
58
cmd/web.go
58
cmd/web.go
|
@ -6,16 +6,13 @@ package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -171,7 +168,7 @@ func serveStaticFile(paths []string, index *fileIndex, errorChannel chan<- error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func serveRoot(paths []string, regexes *regexes, index *fileIndex, formats types.Types, errorChannel chan<- error) httprouter.Handle {
|
func serveRoot(paths []string, index *fileIndex, formats types.Types, errorChannel chan<- error) httprouter.Handle {
|
||||||
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||||
refererUri, err := stripQueryParams(refererToUri(r.Referer()))
|
refererUri, err := stripQueryParams(refererToUri(r.Referer()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -185,8 +182,8 @@ func serveRoot(paths []string, regexes *regexes, index *fileIndex, formats types
|
||||||
strippedRefererUri := strings.TrimPrefix(refererUri, Prefix+mediaPrefix)
|
strippedRefererUri := strings.TrimPrefix(refererUri, Prefix+mediaPrefix)
|
||||||
|
|
||||||
filters := &filters{
|
filters := &filters{
|
||||||
included: splitQueryParams(r.URL.Query().Get("include"), regexes),
|
included: splitQueryParams(r.URL.Query().Get("include")),
|
||||||
excluded: splitQueryParams(r.URL.Query().Get("exclude"), regexes),
|
excluded: splitQueryParams(r.URL.Query().Get("exclude")),
|
||||||
}
|
}
|
||||||
|
|
||||||
sortOrder := sortOrder(r)
|
sortOrder := sortOrder(r)
|
||||||
|
@ -196,7 +193,7 @@ func serveRoot(paths []string, regexes *regexes, index *fileIndex, formats types
|
||||||
var path string
|
var path string
|
||||||
|
|
||||||
if refererUri != "" {
|
if refererUri != "" {
|
||||||
path, err = nextFile(strippedRefererUri, sortOrder, regexes, formats)
|
path, err = nextFile(strippedRefererUri, sortOrder, formats)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorChannel <- err
|
errorChannel <- err
|
||||||
|
|
||||||
|
@ -220,7 +217,7 @@ func serveRoot(paths []string, regexes *regexes, index *fileIndex, formats types
|
||||||
break loop
|
break loop
|
||||||
}
|
}
|
||||||
|
|
||||||
path, err = newFile(list, sortOrder, regexes, formats)
|
path, err = newFile(list, sortOrder, formats)
|
||||||
switch {
|
switch {
|
||||||
case path == "":
|
case path == "":
|
||||||
noFiles(w, r)
|
noFiles(w, r)
|
||||||
|
@ -251,13 +248,13 @@ func serveRoot(paths []string, regexes *regexes, index *fileIndex, formats types
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func serveMedia(paths []string, regexes *regexes, index *fileIndex, formats types.Types, errorChannel chan<- error) httprouter.Handle {
|
func serveMedia(paths []string, index *fileIndex, formats types.Types, errorChannel chan<- error) httprouter.Handle {
|
||||||
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
|
|
||||||
filters := &filters{
|
filters := &filters{
|
||||||
included: splitQueryParams(r.URL.Query().Get("include"), regexes),
|
included: splitQueryParams(r.URL.Query().Get("include")),
|
||||||
excluded: splitQueryParams(r.URL.Query().Get("exclude"), regexes),
|
excluded: splitQueryParams(r.URL.Query().Get("exclude")),
|
||||||
}
|
}
|
||||||
|
|
||||||
sortOrder := sortOrder(r)
|
sortOrder := sortOrder(r)
|
||||||
|
@ -347,7 +344,7 @@ func serveMedia(paths []string, regexes *regexes, index *fileIndex, formats type
|
||||||
var first, last string
|
var first, last string
|
||||||
|
|
||||||
if Index && sortOrder != "" {
|
if Index && sortOrder != "" {
|
||||||
first, last, err = getRange(path, regexes, index)
|
first, last, err = getRange(path, index)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorChannel <- err
|
errorChannel <- err
|
||||||
|
|
||||||
|
@ -358,7 +355,7 @@ func serveMedia(paths []string, regexes *regexes, index *fileIndex, formats type
|
||||||
}
|
}
|
||||||
|
|
||||||
if Index && !DisableButtons && sortOrder != "" {
|
if Index && !DisableButtons && sortOrder != "" {
|
||||||
paginate, err := paginateSorted(path, first, last, queryParams, regexes, formats)
|
paginate, err := paginateSorted(path, first, last, queryParams, formats)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorChannel <- err
|
errorChannel <- err
|
||||||
|
|
||||||
|
@ -478,8 +475,6 @@ func redirectRoot() httprouter.Handle {
|
||||||
}
|
}
|
||||||
|
|
||||||
func ServePage(args []string) error {
|
func ServePage(args []string) error {
|
||||||
log.SetFlags(0)
|
|
||||||
|
|
||||||
timeZone := os.Getenv("TZ")
|
timeZone := os.Getenv("TZ")
|
||||||
if timeZone != "" {
|
if timeZone != "" {
|
||||||
var err error
|
var err error
|
||||||
|
@ -541,11 +536,6 @@ func ServePage(args []string) error {
|
||||||
return ErrNoMediaFound
|
return ErrNoMediaFound
|
||||||
}
|
}
|
||||||
|
|
||||||
regexes := ®exes{
|
|
||||||
filename: regexp.MustCompile(`(.+?)([0-9]*)(\..+)`),
|
|
||||||
alphanumeric: regexp.MustCompile(`^[A-z0-9]*$`),
|
|
||||||
}
|
|
||||||
|
|
||||||
if !strings.HasSuffix(Prefix, "/") {
|
if !strings.HasSuffix(Prefix, "/") {
|
||||||
Prefix = Prefix + "/"
|
Prefix = Prefix + "/"
|
||||||
}
|
}
|
||||||
|
@ -573,30 +563,20 @@ func ServePage(args []string) error {
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for err := range errorChannel {
|
for err := range errorChannel {
|
||||||
prefix := "ERROR"
|
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case errors.Is(err, os.ErrNotExist) && Debug:
|
case ExitOnError:
|
||||||
prefix = "DEBUG"
|
fmt.Printf("%s | FATAL: %v\n", time.Now().Format(logDate), err)
|
||||||
case errors.Is(err, os.ErrNotExist):
|
case Debug && errors.Is(err, os.ErrNotExist) || errors.Is(err, os.ErrPermission):
|
||||||
|
fmt.Printf("%s | DEBUG: %v\n", time.Now().Format(logDate), err)
|
||||||
|
case errors.Is(err, os.ErrNotExist) || errors.Is(err, os.ErrPermission):
|
||||||
continue
|
continue
|
||||||
case errors.Is(err, os.ErrPermission) && Debug:
|
default:
|
||||||
prefix = "DEBUG"
|
fmt.Printf("%s | ERROR: %v\n", time.Now().Format(logDate), err)
|
||||||
case errors.Is(err, os.ErrPermission):
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("%s | %s: %v\n", time.Now().Format(logDate), prefix, err)
|
|
||||||
|
|
||||||
if ExitOnError {
|
|
||||||
fmt.Printf("%s | %s: Shutting down...\n", time.Now().Format(logDate), prefix)
|
|
||||||
|
|
||||||
srv.Shutdown(context.Background())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
registerHandler(mux, Prefix, serveRoot(paths, regexes, index, formats, errorChannel))
|
registerHandler(mux, Prefix, serveRoot(paths, index, formats, errorChannel))
|
||||||
|
|
||||||
Prefix = strings.TrimSuffix(Prefix, "/")
|
Prefix = strings.TrimSuffix(Prefix, "/")
|
||||||
|
|
||||||
|
@ -608,7 +588,7 @@ func ServePage(args []string) error {
|
||||||
|
|
||||||
registerHandler(mux, Prefix+"/favicon.ico", serveFavicons(errorChannel))
|
registerHandler(mux, Prefix+"/favicon.ico", serveFavicons(errorChannel))
|
||||||
|
|
||||||
registerHandler(mux, Prefix+mediaPrefix+"/*media", serveMedia(paths, regexes, index, formats, errorChannel))
|
registerHandler(mux, Prefix+mediaPrefix+"/*media", serveMedia(paths, index, formats, errorChannel))
|
||||||
|
|
||||||
registerHandler(mux, Prefix+sourcePrefix+"/*static", serveStaticFile(paths, index, errorChannel))
|
registerHandler(mux, Prefix+sourcePrefix+"/*static", serveStaticFile(paths, index, errorChannel))
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue