From 28b326ab1df32f41234c0d48f3555f1a18e2ffeb Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Sun, 6 Jan 2019 09:24:09 +0000 Subject: [PATCH 1/5] fix: do not read whole file on listings License: MIT Signed-off-by: Henrique Dias --- files/file.go | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) 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 } From 2d858e6738a1c3704cc5e894292b764b3fae7d9c Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Sun, 6 Jan 2019 09:29:23 +0000 Subject: [PATCH 2/5] fix: allow embedding into iframes (close #550) License: MIT Signed-off-by: Henrique Dias --- http/static.go | 2 -- 1 file changed, 2 deletions(-) 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) From d97bafb53b4a7bae1ba7dd507b62ab70e4aca017 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Sun, 6 Jan 2019 10:06:39 +0000 Subject: [PATCH 3/5] feat: update frontend License: MIT Signed-off-by: Henrique Dias --- frontend | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend b/frontend index 95fc3dfd..7a6397af 160000 --- a/frontend +++ b/frontend @@ -1 +1 @@ -Subproject commit 95fc3dfdfbe21b1d55538add66bf0d5f38197320 +Subproject commit 7a6397af22380eec65f20836d713256b5397d182 From 22f2287bc3416c3b241db92fd9f2173043c6942a Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Sun, 6 Jan 2019 12:01:44 +0000 Subject: [PATCH 4/5] feat: update frontend License: MIT Signed-off-by: Henrique Dias --- frontend | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend b/frontend index 7a6397af..0e7d4ef1 160000 --- a/frontend +++ b/frontend @@ -1 +1 @@ -Subproject commit 7a6397af22380eec65f20836d713256b5397d182 +Subproject commit 0e7d4ef110ee550375d4bf15dfa9ded70214076a From a8ff679ae3beec9df9e3f89d253002f8b1b4250a Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Sun, 6 Jan 2019 12:26:48 +0000 Subject: [PATCH 5/5] feat: dont persist server data on database License: MIT Signed-off-by: Henrique Dias --- cmd/config.go | 12 --- cmd/config_init.go | 7 -- cmd/config_set.go | 10 --- cmd/root.go | 136 +++++++++++----------------------- cmd/utils.go | 9 +++ settings/settings.go | 10 --- storage/bolt/importer/conf.go | 5 -- 7 files changed, 53 insertions(+), 136 deletions(-) diff --git a/cmd/config.go b/cmd/config.go index e03fb354..bca203c5 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -35,12 +35,6 @@ func addConfigFlags(cmd *cobra.Command) { 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().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") @@ -101,12 +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.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 cec455a0..f2e46c8a 100644 --- a/cmd/config_init.go +++ b/cmd/config_init.go @@ -43,17 +43,10 @@ override the options.`, s := &settings.Settings{ Key: generateRandomBytes(64), // 256 bit BaseURL: mustGetString(cmd, "baseURL"), - Log: mustGetString(cmd, "log"), Signup: mustGetBool(cmd, "signup"), 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 b2d4658a..b5e7b510 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 9444dc4c..c7f01598 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,7 +1,6 @@ package cmd import ( - "crypto/rand" "crypto/tls" "errors" "io/ioutil" @@ -14,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" ) @@ -30,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 for users") + 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", "", "root scope to which user's scope are relative too") } var rootCmd = &cobra.Command{ @@ -46,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": @@ -77,29 +57,46 @@ 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") + + 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) { @@ -115,15 +112,8 @@ func quickSetup(cmd *cobra.Command) { set := &settings.Settings{ Key: generateRandomBytes(64), // 256 bit BaseURL: "", - 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: scope, Locale: "en", @@ -140,7 +130,6 @@ func quickSetup(cmd *cobra.Command) { }, } - serverVisitAndReplace(cmd, set) st := getStorage(db) err = st.Settings.Save(set) @@ -164,40 +153,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) - - 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/settings/settings.go b/settings/settings.go index 60285721..b287be8d 100644 --- a/settings/settings.go +++ b/settings/settings.go @@ -9,8 +9,6 @@ type AuthMethod string type Settings struct { Key []byte `json:"key"` BaseURL string `json:"baseURL"` - Log string `json:"log"` - Server Server `json:"server"` Signup bool `json:"signup"` Defaults UserDefaults `json:"defaults"` AuthMethod AuthMethod `json:"authMethod"` @@ -20,14 +18,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