From 6b19ab6613b12be7f075299cd98f4b41d43827c7 Mon Sep 17 00:00:00 2001 From: Oleg Lobanov Date: Sat, 24 Jul 2021 15:16:09 +0200 Subject: [PATCH 1/7] fix: don't remove files on unsuccessful updates (closes #1456) --- http/resource.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/http/resource.go b/http/resource.go index 366d017f..8c2125ee 100644 --- a/http/resource.go +++ b/http/resource.go @@ -158,12 +158,21 @@ var resourcePutHandler = withUser(func(w http.ResponseWriter, r *http.Request, d _, _ = io.Copy(ioutil.Discard, r.Body) }() + // Only allow PUT for files. if strings.HasSuffix(r.URL.Path, "/") { return http.StatusMethodNotAllowed, nil } - err := d.RunHook(func() error { + exists, err := afero.Exists(d.user.Fs, r.URL.Path) + if err != nil { + return http.StatusInternalServerError, err + } + if !exists { + return http.StatusNotFound, nil + } + + err = d.RunHook(func() error { info, writeErr := writeFile(d.user.Fs, r.URL.Path, r.Body) if writeErr != nil { return writeErr @@ -174,10 +183,6 @@ var resourcePutHandler = withUser(func(w http.ResponseWriter, r *http.Request, d return nil }, "save", r.URL.Path, "", d.user) - if err != nil { - _ = d.user.Fs.RemoveAll(r.URL.Path) - } - return errToStatus(err), err }) From 5072bbb2cbf5b29d041629faa8367f15e4d145a2 Mon Sep 17 00:00:00 2001 From: Oleg Lobanov Date: Sat, 24 Jul 2021 15:33:54 +0200 Subject: [PATCH 2/7] fix: break resource create/update handlers on error (closes #1464) --- http/resource.go | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/http/resource.go b/http/resource.go index 8c2125ee..b4ca81cf 100644 --- a/http/resource.go +++ b/http/resource.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "io" - "io/ioutil" "net/http" "net/url" "os" @@ -96,10 +95,6 @@ func resourcePostHandler(fileCache FileCache) handleFunc { return http.StatusForbidden, nil } - defer func() { - _, _ = io.Copy(ioutil.Discard, r.Body) - }() - // Directories creation on POST. if strings.HasSuffix(r.URL.Path, "/") { err := d.user.Fs.MkdirAll(r.URL.Path, 0775) @@ -154,11 +149,6 @@ var resourcePutHandler = withUser(func(w http.ResponseWriter, r *http.Request, d return http.StatusForbidden, nil } - defer func() { - _, _ = io.Copy(ioutil.Discard, r.Body) - }() - - // Only allow PUT for files. if strings.HasSuffix(r.URL.Path, "/") { return http.StatusMethodNotAllowed, nil From f2b5dd37871d3214b22380c424c970b036c197b6 Mon Sep 17 00:00:00 2001 From: Oleg Lobanov Date: Mon, 26 Jul 2021 10:41:56 +0200 Subject: [PATCH 3/7] chore: don't break folder download if any file processing causes an error --- http/raw.go | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/http/raw.go b/http/raw.go index 09ac329c..dcc484ae 100644 --- a/http/raw.go +++ b/http/raw.go @@ -1,21 +1,18 @@ package http import ( - "bytes" "errors" - "io/ioutil" + "log" "net/http" "net/url" gopath "path" "path/filepath" "strings" - "github.com/mholt/archiver" - "github.com/spf13/afero" - "github.com/filebrowser/filebrowser/v2/files" "github.com/filebrowser/filebrowser/v2/fileutils" "github.com/filebrowser/filebrowser/v2/users" + "github.com/mholt/archiver" ) func slashClean(name string) string { @@ -117,19 +114,16 @@ func addFile(ar archiver.Writer, d *data, path, commonPath string) error { return err } - var ( - file afero.File - arcReadCloser = ioutil.NopCloser(&bytes.Buffer{}) - ) - if !files.IsNamedPipe(info.Mode()) { - file, err = d.user.Fs.Open(path) - if err != nil { - return err - } - defer file.Close() - arcReadCloser = file + if !info.IsDir() && !info.Mode().IsRegular() { + return nil } + file, err := d.user.Fs.Open(path) + if err != nil { + return err + } + defer file.Close() + if path != commonPath { filename := strings.TrimPrefix(path, commonPath) filename = strings.TrimPrefix(filename, string(filepath.Separator)) @@ -138,7 +132,7 @@ func addFile(ar archiver.Writer, d *data, path, commonPath string) error { FileInfo: info, CustomName: filename, }, - ReadCloser: arcReadCloser, + ReadCloser: file, }) if err != nil { return err @@ -152,9 +146,10 @@ func addFile(ar archiver.Writer, d *data, path, commonPath string) error { } for _, name := range names { - err = addFile(ar, d, filepath.Join(path, name), commonPath) + fPath := filepath.Join(path, name) + err = addFile(ar, d, fPath, commonPath) if err != nil { - return err + log.Printf("Failed to archive %s: %v", fPath, err) } } } @@ -196,7 +191,7 @@ func rawDirHandler(w http.ResponseWriter, r *http.Request, d *data, file *files. for _, fname := range filenames { err = addFile(ar, d, fname, commonDir) if err != nil { - return http.StatusInternalServerError, err + log.Printf("Failed to archive %s: %v", fname, err) } } From 201329abce4e92ae9071b9ded81e267aae159fbd Mon Sep 17 00:00:00 2001 From: Oleg Lobanov Date: Mon, 26 Jul 2021 11:08:39 +0200 Subject: [PATCH 4/7] chore: add Content-Security-Policy header --- http/http.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/http/http.go b/http/http.go index bc798561..88acea75 100644 --- a/http/http.go +++ b/http/http.go @@ -25,6 +25,12 @@ func NewHandler( server.Clean() r := mux.NewRouter() + r.Use(func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Security-Policy", `default-src 'self'`) + next.ServeHTTP(w, r) + }) + }) index, static := getStaticHandlers(store, server, assetsFs) // NOTE: This fixes the issue where it would redirect if people did not put a From 34d7d2c8c4946acf762c2d2598841f65e64118d5 Mon Sep 17 00:00:00 2001 From: Oleg Lobanov Date: Mon, 26 Jul 2021 12:00:05 +0200 Subject: [PATCH 5/7] chore: upgrade golangci-lint --- .golangci.yml | 25 +++++++------------------ Makefile | 4 ++-- cmd/config.go | 2 +- cmd/root.go | 6 +++--- cmd/rule_rm.go | 2 +- cmd/users.go | 4 ++-- cmd/utils.go | 2 +- diskcache/file_cache.go | 4 ++-- files/file.go | 2 +- fileutils/file.go | 4 ++-- http/raw.go | 3 ++- http/resource.go | 6 +++--- http/share.go | 4 ++-- http/users.go | 4 ++-- img/service.go | 4 +++- settings/settings.go | 4 ++-- storage/bolt/bolt.go | 2 +- 17 files changed, 37 insertions(+), 45 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 8b71cfed..54ecb4a0 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -6,6 +6,8 @@ linters-settings: funlen: lines: 100 statements: 50 + gci: + local-prefixes: github.com/filebrowser/filebrowser goconst: min-len: 2 min-occurrences: 2 @@ -26,8 +28,6 @@ linters-settings: min-complexity: 15 goimports: local-prefixes: github.com/filebrowser/filebrowser - golint: - min-confidence: 0 gomnd: settings: mnd: @@ -58,26 +58,25 @@ linters: - dogsled - dupl - errcheck + - exportloopref + - exhaustive - funlen - gochecknoinits - goconst - gocritic - gocyclo - goimports - - golint - gomnd - goprintffuncname - gosec - gosimple - govet - ineffassign - - interfacer - lll - misspell - nakedret - nolintlint - rowserrcheck - - scopelint - staticcheck - structcheck - stylecheck @@ -89,19 +88,6 @@ linters: - whitespace - prealloc - # don't enable: - # - asciicheck - # - exhaustive (TODO: enable after next release; current release at time of writing is v1.27) - # - gochecknoglobals - # - gocognit - # - godot - # - godox - # - goerr113 - # - maligned - # - nestif - # - testpackage - # - wsl - issues: exclude-rules: - path: cmd/.*.go @@ -118,6 +104,9 @@ issues: - text: "Auther" linters: - misspell + - text: "strconv.Parse" + linters: + - gomnd run: skip-dirs: diff --git a/Makefile b/Makefile index 1feaeb35..92b28c68 100644 --- a/Makefile +++ b/Makefile @@ -32,10 +32,10 @@ $(BIN)/%: | $(BIN) ; $(info $(M) installing $(PACKAGE)…) $Q env GOBIN=$(BIN) $(GO) install $(PACKAGE) GOLANGCI_LINT = $(BIN)/golangci-lint -$(BIN)/golangci-lint: PACKAGE=github.com/golangci/golangci-lint/cmd/golangci-lint@v1.37.1 +$(BIN)/golangci-lint: PACKAGE=github.com/golangci/golangci-lint/cmd/golangci-lint@v1.41.1 GOIMPORTS = $(BIN)/goimports -$(BIN)/goimports: PACKAGE=golang.org/x/tools/cmd/goimports@v0.1.0 +$(BIN)/goimports: PACKAGE=golang.org/x/tools/cmd/goimports@v0.1.5 ## build: Build .PHONY: build diff --git a/cmd/config.go b/cmd/config.go index 5e4da979..8e2d3548 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -121,7 +121,7 @@ func getAuthentication(flags *pflag.FlagSet, defaults ...interface{}) (settings. } func printSettings(ser *settings.Server, set *settings.Settings, auther auth.Auther) { - w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) + w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) //nolint:gomnd fmt.Fprintf(w, "Sign up:\t%t\n", set.Signup) fmt.Fprintf(w, "Create User Dir:\t%t\n", set.CreateUserDir) diff --git a/cmd/root.go b/cmd/root.go index 7810f37d..c180c8e1 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -61,10 +61,10 @@ func addServerFlags(flags *pflag.FlagSet) { flags.StringP("key", "k", "", "tls key") flags.StringP("root", "r", ".", "root to prepend to relative paths") flags.String("socket", "", "socket to listen to (cannot be used with address, port, cert nor key flags)") - flags.Uint32("socket-perm", 0666, "unix socket file permissions") + flags.Uint32("socket-perm", 0666, "unix socket file permissions") //nolint:gomnd flags.StringP("baseurl", "b", "", "base url") flags.String("cache-dir", "", "file cache directory (disabled if empty)") - flags.Int("img-processors", 4, "image processors count") + flags.Int("img-processors", 4, "image processors count") //nolint:gomnd flags.Bool("disable-thumbnails", false, "disable image thumbnails") flags.Bool("disable-preview-resize", false, "disable resize of image previews") flags.Bool("disable-exec", false, "disables Command Runner feature") @@ -128,7 +128,7 @@ user created with the credentials from options "username" and "password".`, cacheDir, err := cmd.Flags().GetString("cache-dir") checkErr(err) if cacheDir != "" { - if err := os.MkdirAll(cacheDir, 0700); err != nil { //nolint:govet + if err := os.MkdirAll(cacheDir, 0700); err != nil { //nolint:govet,gomnd log.Fatalf("can't make directory %s: %s", cacheDir, err) } fileCache = diskcache.New(afero.NewOsFs(), cacheDir) diff --git a/cmd/rule_rm.go b/cmd/rule_rm.go index 4bdc87ed..77751069 100644 --- a/cmd/rule_rm.go +++ b/cmd/rule_rm.go @@ -28,7 +28,7 @@ You can also specify an optional parameter (index_end) so you can remove all commands from 'index' to 'index_end', including 'index_end'.`, Args: func(cmd *cobra.Command, args []string) error { - if err := cobra.RangeArgs(1, 2)(cmd, args); err != nil { + if err := cobra.RangeArgs(1, 2)(cmd, args); err != nil { //nolint:gomnd return err } diff --git a/cmd/users.go b/cmd/users.go index c985d827..495c293d 100644 --- a/cmd/users.go +++ b/cmd/users.go @@ -26,7 +26,7 @@ var usersCmd = &cobra.Command{ } func printUsers(usrs []*users.User) { - w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) + w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) //nolint:gomnd fmt.Fprintln(w, "ID\tUsername\tScope\tLocale\tV. Mode\tS.Click\tAdmin\tExecute\tCreate\tRename\tModify\tDelete\tShare\tDownload\tPwd Lock") for _, u := range usrs { @@ -53,7 +53,7 @@ func printUsers(usrs []*users.User) { } func parseUsernameOrID(arg string) (username string, id uint) { - id64, err := strconv.ParseUint(arg, 10, 0) + id64, err := strconv.ParseUint(arg, 10, 64) //nolint:gomnd if err != nil { return arg, 0 } diff --git a/cmd/utils.go b/cmd/utils.go index ad27cc03..57d1e137 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -72,7 +72,7 @@ func dbExists(path string) (bool, error) { d := filepath.Dir(path) _, err = os.Stat(d) if os.IsNotExist(err) { - if err := os.MkdirAll(d, 0700); err != nil { //nolint:govet + if err := os.MkdirAll(d, 0700); err != nil { //nolint:govet,gomnd return false, err } return false, nil diff --git a/diskcache/file_cache.go b/diskcache/file_cache.go index d299d2a0..e366c7fa 100644 --- a/diskcache/file_cache.go +++ b/diskcache/file_cache.go @@ -37,11 +37,11 @@ func (f *FileCache) Store(ctx context.Context, key string, value []byte) error { defer mu.Unlock() fileName := f.getFileName(key) - if err := f.fs.MkdirAll(filepath.Dir(fileName), 0700); err != nil { + if err := f.fs.MkdirAll(filepath.Dir(fileName), 0700); err != nil { //nolint:gomnd return err } - if err := afero.WriteFile(f.fs, fileName, value, 0700); err != nil { + if err := afero.WriteFile(f.fs, fileName, value, 0700); err != nil { //nolint:gomnd return err } diff --git a/files/file.go b/files/file.go index ad78ad06..22a1a57b 100644 --- a/files/file.go +++ b/files/file.go @@ -204,7 +204,7 @@ func (i *FileInfo) readFirstBytes() []byte { } defer reader.Close() - buffer := make([]byte, 512) + buffer := make([]byte, 512) //nolint:gomnd n, err := reader.Read(buffer) if err != nil && err != io.EOF { log.Print(err) diff --git a/fileutils/file.go b/fileutils/file.go index 6e6cd2af..0f782cf5 100644 --- a/fileutils/file.go +++ b/fileutils/file.go @@ -40,13 +40,13 @@ func CopyFile(fs afero.Fs, source, dest string) error { // Makes the directory needed to create the dst // file. - err = fs.MkdirAll(filepath.Dir(dest), 0666) + err = fs.MkdirAll(filepath.Dir(dest), 0666) //nolint:gomnd if err != nil { return err } // Create the destination file. - dst, err := fs.OpenFile(dest, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0775) + dst, err := fs.OpenFile(dest, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0775) //nolint:gomnd if err != nil { return err } diff --git a/http/raw.go b/http/raw.go index dcc484ae..a24d474a 100644 --- a/http/raw.go +++ b/http/raw.go @@ -9,10 +9,11 @@ import ( "path/filepath" "strings" + "github.com/mholt/archiver" + "github.com/filebrowser/filebrowser/v2/files" "github.com/filebrowser/filebrowser/v2/fileutils" "github.com/filebrowser/filebrowser/v2/users" - "github.com/mholt/archiver" ) func slashClean(name string) string { diff --git a/http/resource.go b/http/resource.go index b4ca81cf..ea4fbc29 100644 --- a/http/resource.go +++ b/http/resource.go @@ -97,7 +97,7 @@ func resourcePostHandler(fileCache FileCache) handleFunc { // Directories creation on POST. if strings.HasSuffix(r.URL.Path, "/") { - err := d.user.Fs.MkdirAll(r.URL.Path, 0775) + err := d.user.Fs.MkdirAll(r.URL.Path, 0775) //nolint:gomnd return errToStatus(err), err } @@ -255,12 +255,12 @@ func addVersionSuffix(source string, fs afero.Fs) string { func writeFile(fs afero.Fs, dst string, in io.Reader) (os.FileInfo, error) { dir, _ := path.Split(dst) - err := fs.MkdirAll(dir, 0775) + err := fs.MkdirAll(dir, 0775) //nolint:gomnd if err != nil { return nil, err } - file, err := fs.OpenFile(dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0775) + file, err := fs.OpenFile(dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0775) //nolint:gomnd if err != nil { return nil, err } diff --git a/http/share.go b/http/share.go index d813500e..193f0913 100644 --- a/http/share.go +++ b/http/share.go @@ -90,7 +90,7 @@ var sharePostHandler = withPermShare(func(w http.ResponseWriter, r *http.Request defer r.Body.Close() } - bytes := make([]byte, 6) + bytes := make([]byte, 6) //nolint:gomnd _, err := rand.Read(bytes) if err != nil { return http.StatusInternalServerError, err @@ -129,7 +129,7 @@ var sharePostHandler = withPermShare(func(w http.ResponseWriter, r *http.Request var token string if len(hash) > 0 { - tokenBuffer := make([]byte, 96) + tokenBuffer := make([]byte, 96) //nolint:gomnd if _, err := rand.Read(tokenBuffer); err != nil { return http.StatusInternalServerError, err } diff --git a/http/users.go b/http/users.go index 4e29c46a..a2ec72fe 100644 --- a/http/users.go +++ b/http/users.go @@ -25,7 +25,7 @@ type modifyUserRequest struct { func getUserID(r *http.Request) (uint, error) { vars := mux.Vars(r) - i, err := strconv.ParseUint(vars["id"], 10, 0) + i, err := strconv.ParseUint(vars["id"], 10, 0) //nolint:gomnd if err != nil { return 0, err } @@ -138,7 +138,7 @@ var userPostHandler = withAdmin(func(w http.ResponseWriter, r *http.Request, d * return http.StatusInternalServerError, err } - w.Header().Set("Location", "/settings/users/"+strconv.FormatUint(uint64(req.Data.ID), 10)) + w.Header().Set("Location", "/settings/users/"+strconv.FormatUint(uint64(req.Data.ID), 10)) //nolint:gomnd return http.StatusCreated, nil }) diff --git a/img/service.go b/img/service.go index ce90401d..1d72ad81 100644 --- a/img/service.go +++ b/img/service.go @@ -174,6 +174,8 @@ func (s *Service) Resize(ctx context.Context, in io.Reader, width, height int, o switch config.resizeMode { case ResizeModeFill: img = imaging.Fill(img, width, height, imaging.Center, config.quality.resampleFilter()) + case ResizeModeFit: + fallthrough //nolint:gocritic default: img = imaging.Fit(img, width, height, config.quality.resampleFilter()) } @@ -205,7 +207,7 @@ func getEmbeddedThumbnail(in io.Reader) ([]byte, io.Reader, error) { offset := 0 offsets := []int{12, 30} - head := make([]byte, 0xffff) + head := make([]byte, 0xffff) //nolint:gomnd _, err := r.Read(head) if err != nil { diff --git a/settings/settings.go b/settings/settings.go index 0f8616d2..9cd45af6 100644 --- a/settings/settings.go +++ b/settings/settings.go @@ -49,9 +49,9 @@ func (s *Server) Clean() { s.BaseURL = strings.TrimSuffix(s.BaseURL, "/") } -// GenerateKey generates a key of 256 bits. +// GenerateKey generates a key of 512 bits. func GenerateKey() ([]byte, error) { - b := make([]byte, 64) + b := make([]byte, 64) //nolint:gomnd _, err := rand.Read(b) // Note that err == nil only if we read len(b) bytes. if err != nil { diff --git a/storage/bolt/bolt.go b/storage/bolt/bolt.go index ce67adc0..50867893 100644 --- a/storage/bolt/bolt.go +++ b/storage/bolt/bolt.go @@ -17,7 +17,7 @@ func NewStorage(db *storm.DB) (*storage.Storage, error) { settingsStore := settings.NewStorage(settingsBackend{db: db}) authStore := auth.NewStorage(authBackend{db: db}, userStore) - err := save(db, "version", 2) + err := save(db, "version", 2) //nolint:gomnd if err != nil { return nil, err } From 8650d2ffe7a29cbafa800efcecbf6a61598a9f0c Mon Sep 17 00:00:00 2001 From: Oleg Lobanov Date: Mon, 26 Jul 2021 12:59:09 +0200 Subject: [PATCH 6/7] fix: failure on broken symlink deletion --- files/file.go | 76 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 63 insertions(+), 13 deletions(-) diff --git a/files/file.go b/files/file.go index 22a1a57b..e0534fa4 100644 --- a/files/file.go +++ b/files/file.go @@ -34,6 +34,7 @@ type FileInfo struct { ModTime time.Time `json:"modified"` Mode os.FileMode `json:"mode"` IsDir bool `json:"isDir"` + IsSymlink bool `json:"isSymlink"` Type string `json:"type"` Subtitles []string `json:"subtitles,omitempty"` Content string `json:"content,omitempty"` @@ -61,23 +62,11 @@ func NewFileInfo(opts FileOptions) (*FileInfo, error) { return nil, os.ErrPermission } - info, err := opts.Fs.Stat(opts.Path) + file, err := stat(opts) if err != nil { return nil, err } - file := &FileInfo{ - Fs: opts.Fs, - Path: opts.Path, - Name: info.Name(), - ModTime: info.ModTime(), - Mode: info.Mode(), - IsDir: info.IsDir(), - Size: info.Size(), - Extension: filepath.Ext(info.Name()), - Token: opts.Token, - } - if opts.Expand { if file.IsDir { if err := file.readListing(opts.Checker, opts.ReadHeader); err != nil { //nolint:govet @@ -95,6 +84,64 @@ func NewFileInfo(opts FileOptions) (*FileInfo, error) { return file, err } +func stat(opts FileOptions) (*FileInfo, error) { + var file *FileInfo + + if lstaterFs, ok := opts.Fs.(afero.Lstater); ok { + info, _, err := lstaterFs.LstatIfPossible(opts.Path) + if err != nil { + return nil, err + } + file = &FileInfo{ + Fs: opts.Fs, + Path: opts.Path, + Name: info.Name(), + ModTime: info.ModTime(), + Mode: info.Mode(), + IsDir: info.IsDir(), + IsSymlink: IsSymlink(info.Mode()), + Size: info.Size(), + Extension: filepath.Ext(info.Name()), + Token: opts.Token, + } + } + + // regular file + if file != nil && !file.IsSymlink { + return file, nil + } + + // fs doesn't support afero.Lstater interface or the file is a symlink + info, err := opts.Fs.Stat(opts.Path) + if err != nil { + // can't follow symlink + if file != nil && file.IsSymlink { + return file, nil + } + return nil, err + } + + // set correct file size in case of symlink + if file != nil && file.IsSymlink { + file.Size = info.Size() + return file, nil + } + + file = &FileInfo{ + Fs: opts.Fs, + Path: opts.Path, + Name: info.Name(), + ModTime: info.ModTime(), + Mode: info.Mode(), + IsDir: info.IsDir(), + Size: info.Size(), + Extension: filepath.Ext(info.Name()), + Token: opts.Token, + } + + return file, nil +} + // Checksum checksums a given File for a given User, using a specific // algorithm. The checksums data is saved on File object. func (i *FileInfo) Checksum(algo string) error { @@ -252,7 +299,9 @@ func (i *FileInfo) readListing(checker rules.Checker, readHeader bool) error { continue } + isSymlink := false if IsSymlink(f.Mode()) { + isSymlink = true // It's a symbolic link. We try to follow it. If it doesn't work, // we stay with the link information instead of the target's. info, err := i.Fs.Stat(fPath) @@ -268,6 +317,7 @@ func (i *FileInfo) readListing(checker rules.Checker, readHeader bool) error { ModTime: f.ModTime(), Mode: f.Mode(), IsDir: f.IsDir(), + IsSymlink: isSymlink, Extension: filepath.Ext(name), Path: fPath, } From 8ecc2da94765cefac4c4245c4fd7eb8c268c148f Mon Sep 17 00:00:00 2001 From: Oleg Lobanov Date: Mon, 26 Jul 2021 13:03:53 +0200 Subject: [PATCH 7/7] chore(release): 2.16.0 --- CHANGELOG.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 118a7467..050c1d16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,35 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [2.16.0](https://github.com/filebrowser/filebrowser/compare/v2.15.0...v2.16.0) (2021-07-26) + + +### Features + +* browser cache directives ([190cb99](https://github.com/filebrowser/filebrowser/commit/190cb99a79a0d438eca2da13539f8c6449ad73ac)) +* display error messages on settings ([6032038](https://github.com/filebrowser/filebrowser/commit/603203848a8b2221158088b6d849609db4c0c46c)) +* file name on page title ([16a34de](https://github.com/filebrowser/filebrowser/commit/16a34defc02554a77c6ac47b9e17e69d098a09fe)) +* gzip encoding for static js files ([aa172b8](https://github.com/filebrowser/filebrowser/commit/aa172b8bb5f17d5f5cb9666bfb5ee650d8091fb5)) +* loading spinner on views navigation ([976eb55](https://github.com/filebrowser/filebrowser/commit/976eb5583dae474125fd7ddec5dc19b6c291f98f)) +* message for connection error ([5e6f14b](https://github.com/filebrowser/filebrowser/commit/5e6f14b5dcb9c5efdf526f1346e09c2d0b2f6974)) +* mod time title on file info ([7d1e030](https://github.com/filebrowser/filebrowser/commit/7d1e03075d2c27148f60813defa0f68403d1d3c2)) +* open file option on share ([1c25f6e](https://github.com/filebrowser/filebrowser/commit/1c25f6ee69bd71eed82af7020006d0e27537a967)) +* show more button on share ([ba8c09f](https://github.com/filebrowser/filebrowser/commit/ba8c09f454feeadf4a1e97547a34151a81b389d5)) +* support for IE11 browser ([7ec24d9](https://github.com/filebrowser/filebrowser/commit/7ec24d9d7794fa37825f64ca2d1575f568fb1362)) + + +### Bug Fixes + +* break resource create/update handlers on error (closes [#1464](https://github.com/filebrowser/filebrowser/issues/1464)) ([5072bbb](https://github.com/filebrowser/filebrowser/commit/5072bbb2cbf5b29d041629faa8367f15e4d145a2)) +* copying files with special characters ([20ebbf6](https://github.com/filebrowser/filebrowser/commit/20ebbf6611b734371426fb1b9cb5e388be90bf7e)) +* delete image cache when moving ([8973c45](https://github.com/filebrowser/filebrowser/commit/8973c4598ff817647f1f1ad6ee36480054cd2776)) +* don't remove files on unsuccessful updates (closes [#1456](https://github.com/filebrowser/filebrowser/issues/1456)) ([6b19ab6](https://github.com/filebrowser/filebrowser/commit/6b19ab6613b12be7f075299cd98f4b41d43827c7)) +* failure on broken symlink deletion ([8650d2f](https://github.com/filebrowser/filebrowser/commit/8650d2ffe7a29cbafa800efcecbf6a61598a9f0c)) +* inconsistent double click on listing item ([ba7e71a](https://github.com/filebrowser/filebrowser/commit/ba7e71a7c3b0cc71012e5adf94b1c642e554972e)) +* no items displayed on file listing ([18889ad](https://github.com/filebrowser/filebrowser/commit/18889ad725f7f7e5a7e3f7abcf156487556dbeaf)) +* omit file content ([209f9fa](https://github.com/filebrowser/filebrowser/commit/209f9fa77f751054512355f2b74b9b7258465d0b)) +* short commit sha and typo fix in Makefile ([#1411](https://github.com/filebrowser/filebrowser/issues/1411)) ([46ee595](https://github.com/filebrowser/filebrowser/commit/46ee59538914dc2859f0da6b32e2d062d0a01b10)) + ## [2.15.0](https://github.com/filebrowser/filebrowser/compare/v2.14.1...v2.15.0) (2021-04-06)