You've already forked filebrowser
mirror of
https://github.com/filebrowser/filebrowser.git
synced 2025-11-26 14:25:26 +08:00
Fixes the error where File Browser would fail when the DB existed with size 0. This closes #628. @1138-4EB I decided not to check the version for now since it's the first time we're adding that info. Only the next time we change the DB structure we'll use that value as reference to know how to upgrade. I did not check it because the users running rc1 would have some issues with it.
178 lines
3.6 KiB
Go
178 lines
3.6 KiB
Go
package cmd
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/asdine/storm"
|
|
"github.com/filebrowser/filebrowser/v2/storage"
|
|
"github.com/filebrowser/filebrowser/v2/storage/bolt"
|
|
"github.com/spf13/cobra"
|
|
"github.com/spf13/pflag"
|
|
yaml "gopkg.in/yaml.v2"
|
|
)
|
|
|
|
func checkErr(err error) {
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func mustGetString(flags *pflag.FlagSet, flag string) string {
|
|
s, err := flags.GetString(flag)
|
|
checkErr(err)
|
|
return s
|
|
}
|
|
|
|
func mustGetBool(flags *pflag.FlagSet, flag string) bool {
|
|
b, err := flags.GetBool(flag)
|
|
checkErr(err)
|
|
return b
|
|
}
|
|
|
|
func mustGetUint(flags *pflag.FlagSet, flag string) uint {
|
|
b, err := flags.GetUint(flag)
|
|
checkErr(err)
|
|
return b
|
|
}
|
|
|
|
func generateRandomBytes(n int) []byte {
|
|
b := make([]byte, n)
|
|
_, err := rand.Read(b)
|
|
checkErr(err)
|
|
// Note that err == nil only if we read len(b) bytes.
|
|
return b
|
|
}
|
|
|
|
type cobraFunc func(cmd *cobra.Command, args []string)
|
|
type pythonFunc func(cmd *cobra.Command, args []string, data pythonData)
|
|
|
|
type pythonConfig struct {
|
|
noDB bool
|
|
allowNoDB bool
|
|
}
|
|
|
|
type pythonData struct {
|
|
hadDB bool
|
|
store *storage.Storage
|
|
}
|
|
|
|
func dbExists(path string) (bool, error) {
|
|
stat, err := os.Stat(path)
|
|
|
|
if os.IsNotExist(err) {
|
|
return false, nil
|
|
} else if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
if stat.Size() == 0 {
|
|
return false, nil
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
func python(fn pythonFunc, cfg pythonConfig) cobraFunc {
|
|
return func(cmd *cobra.Command, args []string) {
|
|
data := pythonData{hadDB: true}
|
|
|
|
path := getParam(cmd.Flags(), "database")
|
|
exists, err := dbExists(path)
|
|
|
|
if err != nil {
|
|
panic(err)
|
|
} else if exists && cfg.noDB {
|
|
log.Fatal(path + " already exists")
|
|
} else if !exists && !cfg.noDB && !cfg.allowNoDB {
|
|
log.Fatal(path + " does not exist. Please run 'filebrowser config init' first.")
|
|
}
|
|
|
|
data.hadDB = exists
|
|
db, err := storm.Open(path)
|
|
checkErr(err)
|
|
defer db.Close()
|
|
data.store, err = bolt.NewStorage(db)
|
|
checkErr(err)
|
|
fn(cmd, args, data)
|
|
}
|
|
}
|
|
|
|
func marshal(filename string, data interface{}) error {
|
|
fd, err := os.Create(filename)
|
|
checkErr(err)
|
|
defer fd.Close()
|
|
|
|
switch ext := filepath.Ext(filename); ext {
|
|
case ".json":
|
|
encoder := json.NewEncoder(fd)
|
|
encoder.SetIndent("", " ")
|
|
return encoder.Encode(data)
|
|
case ".yml", ".yaml":
|
|
encoder := yaml.NewEncoder(fd)
|
|
return encoder.Encode(data)
|
|
default:
|
|
return errors.New("invalid format: " + ext)
|
|
}
|
|
}
|
|
|
|
func unmarshal(filename string, data interface{}) error {
|
|
fd, err := os.Open(filename)
|
|
checkErr(err)
|
|
defer fd.Close()
|
|
|
|
switch ext := filepath.Ext(filename); ext {
|
|
case ".json":
|
|
return json.NewDecoder(fd).Decode(data)
|
|
case ".yml", ".yaml":
|
|
return yaml.NewDecoder(fd).Decode(data)
|
|
default:
|
|
return errors.New("invalid format: " + ext)
|
|
}
|
|
}
|
|
|
|
func jsonYamlArg(cmd *cobra.Command, args []string) error {
|
|
if err := cobra.ExactArgs(1)(cmd, args); err != nil {
|
|
return err
|
|
}
|
|
|
|
switch ext := filepath.Ext(args[0]); ext {
|
|
case ".json", ".yml", ".yaml":
|
|
return nil
|
|
default:
|
|
return errors.New("invalid format: " + ext)
|
|
}
|
|
}
|
|
|
|
func cleanUpInterfaceMap(in map[interface{}]interface{}) map[string]interface{} {
|
|
result := make(map[string]interface{})
|
|
for k, v := range in {
|
|
result[fmt.Sprintf("%v", k)] = cleanUpMapValue(v)
|
|
}
|
|
return result
|
|
}
|
|
|
|
func cleanUpInterfaceArray(in []interface{}) []interface{} {
|
|
result := make([]interface{}, len(in))
|
|
for i, v := range in {
|
|
result[i] = cleanUpMapValue(v)
|
|
}
|
|
return result
|
|
}
|
|
|
|
func cleanUpMapValue(v interface{}) interface{} {
|
|
switch v := v.(type) {
|
|
case []interface{}:
|
|
return cleanUpInterfaceArray(v)
|
|
case map[interface{}]interface{}:
|
|
return cleanUpInterfaceMap(v)
|
|
default:
|
|
return v
|
|
}
|
|
}
|