diff --git a/cmd/config.go b/cmd/config.go index 9a2ae3f8..255caf3c 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -34,13 +34,6 @@ func addConfigFlags(cmd *cobra.Command) { cmd.Flags().StringP("baseURL", "b", "/", "base url of this installation") cmd.Flags().BoolP("signup", "s", false, "allow users to signup") cmd.Flags().String("shell", "", "shell command to which other commands should be appended") - cmd.Flags().String("scope", "", "scope to prepend to a user's scope when it is relative (default is current working directory)") - - cmd.Flags().StringP("address", "a", "127.0.0.1", "default address to listen to") - cmd.Flags().StringP("log", "l", "stderr", "log output") - cmd.Flags().IntP("port", "p", 0, "default port to listen to") - cmd.Flags().String("tls.cert", "", "tls certificate path") - cmd.Flags().String("tls.key", "", "tls key path") cmd.Flags().String("auth.method", string(auth.MethodJSONAuth), "authentication type") cmd.Flags().String("auth.header", "", "HTTP header for auth.method=proxy") @@ -102,13 +95,6 @@ func printSettings(s *settings.Settings, auther auth.Auther) { fmt.Fprintf(w, "Sign up:\t%t\n", s.Signup) fmt.Fprintf(w, "Auth method:\t%s\n", s.AuthMethod) fmt.Fprintf(w, "Shell:\t%s\t\n", strings.Join(s.Shell, " ")) - fmt.Fprintf(w, "Log:\t%s\t\n", s.Log) - fmt.Fprintf(w, "Scope:\t%s\t\n", s.Scope) - fmt.Fprintln(w, "\nServer:") - fmt.Fprintf(w, "\tAddress:\t%s\n", s.Server.Address) - fmt.Fprintf(w, "\tPort:\t%d\n", s.Server.Port) - fmt.Fprintf(w, "\tTLS Cert:\t%s\n", s.Server.TLSCert) - fmt.Fprintf(w, "\tTLS Key:\t%s\n", s.Server.TLSKey) fmt.Fprintln(w, "\nBranding:") fmt.Fprintf(w, "\tName:\t%s\n", s.Branding.Name) fmt.Fprintf(w, "\tFiles override:\t%s\n", s.Branding.Files) diff --git a/cmd/config_init.go b/cmd/config_init.go index e53b74af..79200bb7 100644 --- a/cmd/config_init.go +++ b/cmd/config_init.go @@ -49,18 +49,11 @@ override the options.`, s := &settings.Settings{ Key: generateRandomBytes(64), // 256 bit BaseURL: mustGetString(cmd, "baseURL"), - Log: mustGetString(cmd, "log"), Signup: mustGetBool(cmd, "signup"), Scope: scope, Shell: strings.Split(strings.TrimSpace(mustGetString(cmd, "shell")), " "), AuthMethod: authMethod, Defaults: defaults, - Server: settings.Server{ - Address: mustGetString(cmd, "address"), - Port: mustGetInt(cmd, "port"), - TLSCert: mustGetString(cmd, "tls.cert"), - TLSKey: mustGetString(cmd, "tls.key"), - }, Branding: settings.Branding{ Name: mustGetString(cmd, "branding.name"), DisableExternal: mustGetBool(cmd, "branding.disableExternal"), diff --git a/cmd/config_set.go b/cmd/config_set.go index 8b8e3a2d..7c66b378 100644 --- a/cmd/config_set.go +++ b/cmd/config_set.go @@ -44,16 +44,6 @@ you want to change.`, s.Branding.DisableExternal = mustGetBool(cmd, flag.Name) case "branding.files": s.Branding.Files = mustGetString(cmd, flag.Name) - case "log": - s.Log = mustGetString(cmd, flag.Name) - case "address": - s.Server.Address = mustGetString(cmd, flag.Name) - case "port": - s.Server.Port = mustGetInt(cmd, flag.Name) - case "tls.cert": - s.Server.TLSCert = mustGetString(cmd, flag.Name) - case "tls.key": - s.Server.TLSKey = mustGetString(cmd, flag.Name) } }) diff --git a/cmd/root.go b/cmd/root.go index 8eb551d5..d15ab5bd 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,7 +1,7 @@ package cmd import ( - "crypto/rand" + "path/filepath" "crypto/tls" "io/ioutil" "log" @@ -13,12 +13,10 @@ import ( "github.com/asdine/storm" "github.com/filebrowser/filebrowser/v2/auth" "github.com/filebrowser/filebrowser/v2/settings" - "github.com/filebrowser/filebrowser/v2/storage" "github.com/filebrowser/filebrowser/v2/users" fbhttp "github.com/filebrowser/filebrowser/v2/http" "github.com/spf13/cobra" - "github.com/spf13/pflag" lumberjack "gopkg.in/natefinch/lumberjack.v2" ) @@ -29,12 +27,12 @@ var ( func init() { rootCmd.PersistentFlags().StringVarP(&databasePath, "database", "d", "./filebrowser.db", "path to the database") - rootCmd.Flags().StringP("address", "a", "", "address to listen on (default comes from database)") - rootCmd.Flags().StringP("log", "l", "", "log output (default comes from database)") - rootCmd.Flags().IntP("port", "p", 0, "port to listen on (default comes from database)") - rootCmd.Flags().StringP("cert", "c", "", "tls certificate (default comes from database)") - rootCmd.Flags().StringP("key", "k", "", "tls key (default comes from database)") - rootCmd.Flags().StringP("scope", "s", "", "scope to prepend to a user's scope when it is relative (default comes from database)") + rootCmd.Flags().StringP("address", "a", "127.0.0.1", "address to listen on") + rootCmd.Flags().StringP("log", "l", "stdout", "log output") + rootCmd.Flags().IntP("port", "p", 80, "port to listen on") + rootCmd.Flags().StringP("cert", "c", "", "tls certificate") + rootCmd.Flags().StringP("key", "k", "", "tls key") + rootCmd.Flags().StringP("scope", "s", ".", "scope to prepend to a user's scope when it is relative") } var rootCmd = &cobra.Command{ @@ -45,29 +43,12 @@ manage your user and all the configurations without accessing the web interface. If you've never run File Browser, you will need to create the database. -See 'filebrowser help config init' for more information. - -This command is used to start up the server. By default it starts listening -on localhost on a random port unless specified otherwise in the database or -via flags. - -Use the available flags to override the database/default options. These flags -values won't be persisted to the database. To persist configuration to the database -use the command 'filebrowser config set'.`, - Run: func(cmd *cobra.Command, args []string) { - if _, err := os.Stat(databasePath); os.IsNotExist(err) { - quickSetup(cmd) - } - - db := getDB() - defer db.Close() - st := getStorage(db) - startServer(cmd, st) - }, +See 'filebrowser help config init' for more information.`, + Run: serveAndListen, } -func setupLogger(s *settings.Settings) { - switch s.Log { +func serveAndListen(cmd *cobra.Command, args []string) { + switch logMethod := mustGetString(cmd, "log"); logMethod { case "stdout": log.SetOutput(os.Stdout) case "stderr": @@ -76,29 +57,58 @@ func setupLogger(s *settings.Settings) { log.SetOutput(ioutil.Discard) default: log.SetOutput(&lumberjack.Logger{ - Filename: s.Log, + Filename: logMethod, MaxSize: 100, MaxAge: 14, MaxBackups: 10, }) } -} -func serverVisitAndReplace(cmd *cobra.Command, s *settings.Settings) { - cmd.Flags().Visit(func(flag *pflag.Flag) { - switch flag.Name { - case "log": - s.Log = mustGetString(cmd, flag.Name) - case "address": - s.Server.Address = mustGetString(cmd, flag.Name) - case "port": - s.Server.Port = mustGetInt(cmd, flag.Name) - case "cert": - s.Server.TLSCert = mustGetString(cmd, flag.Name) - case "key": - s.Server.TLSKey = mustGetString(cmd, flag.Name) - } - }) + if _, err := os.Stat(databasePath); os.IsNotExist(err) { + quickSetup(cmd) + } + + db := getDB() + defer db.Close() + st := getStorage(db) + + port := mustGetInt(cmd, "port") + address := mustGetString(cmd, "address") + cert := mustGetString(cmd, "cert") + key := mustGetString(cmd, "key") + scope := mustGetString(cmd, "scope") + + if scope != "." { + var err error + scope, err = filepath.Abs(scope) + checkErr(err) + settings, err := st.Settings.Get() + checkErr(err) + settings.Scope = scope + err = st.Settings.Save(settings) + checkErr(err) + } + + handler, err := fbhttp.NewHandler(st) + checkErr(err) + + var listener net.Listener + + if key != "" && cert != "" { + cer, err := tls.LoadX509KeyPair(cert, key) + checkErr(err) + config := &tls.Config{Certificates: []tls.Certificate{cer}} + listener, err = tls.Listen("tcp", address+":"+strconv.Itoa(port), config) + checkErr(err) + } else { + listener, err = net.Listen("tcp", address+":"+strconv.Itoa(port)) + checkErr(err) + } + + log.Println("Listening on", listener.Addr().String()) + if err := http.Serve(listener, handler); err != nil { + log.Fatal(err) + } } func quickSetup(cmd *cobra.Command) { @@ -116,16 +126,8 @@ func quickSetup(cmd *cobra.Command) { set := &settings.Settings{ Key: generateRandomBytes(64), // 256 bit BaseURL: "", - Scope: scope, - Log: "stderr", Signup: false, AuthMethod: auth.MethodJSONAuth, - Server: settings.Server{ - Port: 0, - Address: "127.0.0.1", - TLSCert: mustGetString(cmd, "cert"), - TLSKey: mustGetString(cmd, "key"), - }, Defaults: settings.UserDefaults{ Scope: ".", Locale: "en", @@ -142,7 +144,6 @@ func quickSetup(cmd *cobra.Command) { }, } - serverVisitAndReplace(cmd, set) st := getStorage(db) err = st.Settings.Save(set) @@ -166,47 +167,3 @@ func quickSetup(cmd *cobra.Command) { err = st.Users.Save(user) checkErr(err) } - -func startServer(cmd *cobra.Command, st *storage.Storage) { - settings, err := st.Settings.Get() - checkErr(err) - - scope := mustGetString(cmd, "scope") - if scope != "" { - settings.Scope = scope - err = st.Settings.Save(settings) - checkErr(err) - } - - serverVisitAndReplace(cmd, settings) - setupLogger(settings) - - handler, err := fbhttp.NewHandler(st) - checkErr(err) - - var listener net.Listener - - if settings.Server.TLSKey != "" && settings.Server.TLSCert != "" { - cer, err := tls.LoadX509KeyPair(settings.Server.TLSCert, settings.Server.TLSKey) - checkErr(err) - config := &tls.Config{Certificates: []tls.Certificate{cer}} - listener, err = tls.Listen("tcp", settings.Server.Address+":"+strconv.Itoa(settings.Server.Port), config) - checkErr(err) - } else { - listener, err = net.Listen("tcp", settings.Server.Address+":"+strconv.Itoa(settings.Server.Port)) - checkErr(err) - } - - log.Println("Listening on", listener.Addr().String()) - if err := http.Serve(listener, handler); err != nil { - log.Fatal(err) - } -} - -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 -} diff --git a/cmd/utils.go b/cmd/utils.go index 8b2520dd..70e63413 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -1,6 +1,7 @@ package cmd import ( + "crypto/rand" "errors" "os" @@ -53,3 +54,11 @@ func getDB() *storm.DB { func getStorage(db *storm.DB) *storage.Storage { return bolt.NewStorage(db) } + +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 +} diff --git a/files/file.go b/files/file.go index b50dc929..3dbb092a 100644 --- a/files/file.go +++ b/files/file.go @@ -76,7 +76,7 @@ func NewFileInfo(opts FileOptions) (*FileInfo, error) { return file, file.readListing(opts.Checker) } - err = file.detectType(opts.Modify) + err = file.detectType(opts.Modify, true) if err != nil { return nil, err } @@ -126,7 +126,7 @@ func (i *FileInfo) Checksum(algo string) error { return nil } -func (i *FileInfo) detectType(modify bool) error { +func (i *FileInfo) detectType(modify, saveContent bool) error { reader, err := i.Fs.Open(i.Path) if err != nil { return err @@ -160,17 +160,20 @@ func (i *FileInfo) detectType(modify bool) error { return nil default: i.Type = "text" - afs := &afero.Afero{Fs: i.Fs} - content, err := afs.ReadFile(i.Path) - if err != nil { - return err - } if !modify { i.Type = "textImmutable" } - i.Content = string(content) + if saveContent { + afs := &afero.Afero{Fs: i.Fs} + content, err := afs.ReadFile(i.Path) + if err != nil { + return err + } + + i.Content = string(content) + } } return nil @@ -238,7 +241,7 @@ func (i *FileInfo) readListing(checker rules.Checker) error { } else { listing.NumFiles++ - err := file.detectType(true) + err := file.detectType(true, false) if err != nil { return err } diff --git a/frontend b/frontend index 95fc3dfd..0e7d4ef1 160000 --- a/frontend +++ b/frontend @@ -1 +1 @@ -Subproject commit 95fc3dfdfbe21b1d55538add66bf0d5f38197320 +Subproject commit 0e7d4ef110ee550375d4bf15dfa9ded70214076a diff --git a/http/static.go b/http/static.go index 6e84be85..bca3821e 100644 --- a/http/static.go +++ b/http/static.go @@ -85,9 +85,7 @@ func getStaticHandlers(storage *storage.Storage) (http.Handler, http.Handler) { return http.StatusNotFound, nil } - w.Header().Set("x-frame-options", "SAMEORIGIN") w.Header().Set("x-xss-protection", "1; mode=block") - return handleWithStaticData(w, r, d, box, "index.html", "text/html; charset=utf-8") }, "", storage) diff --git a/settings/settings.go b/settings/settings.go index e958514e..57d4863d 100644 --- a/settings/settings.go +++ b/settings/settings.go @@ -9,9 +9,7 @@ type AuthMethod string type Settings struct { Key []byte `json:"key"` BaseURL string `json:"baseURL"` - Log string `json:"log"` Scope string `json:"scope"` - Server Server `json:"server"` Signup bool `json:"signup"` Defaults UserDefaults `json:"defaults"` AuthMethod AuthMethod `json:"authMethod"` @@ -21,14 +19,6 @@ type Settings struct { Rules []rules.Rule `json:"rules"` } -// Server settings. -type Server struct { - Port int `json:"port"` - Address string `json:"address"` - TLSCert string `json:"tlsCert"` - TLSKey string `json:"tlsKey"` -} - // GetRules implements rules.Provider. func (s *Settings) GetRules() []rules.Rule { return s.Rules diff --git a/storage/bolt/importer/conf.go b/storage/bolt/importer/conf.go index efd98df7..335f4148 100644 --- a/storage/bolt/importer/conf.go +++ b/storage/bolt/importer/conf.go @@ -111,7 +111,6 @@ func importConf(db *storm.DB, path string, sto *storage.Storage) error { s := &settings.Settings{ Key: key, BaseURL: cfg.BaseURL, - Log: cfg.Log, Signup: false, Defaults: settings.UserDefaults{ Scope: cfg.Defaults.Scope, @@ -129,10 +128,6 @@ func importConf(db *storm.DB, path string, sto *storage.Storage) error { Download: true, }, }, - Server: settings.Server{ - Address: cfg.Address, - Port: cfg.Port, - }, } var auther auth.Auther