Merge remote-tracking branch 'upstream/master'
						commit
						8688af97b7
					
				| 
						 | 
				
			
			@ -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:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										29
									
								
								CHANGELOG.md
								
								
								
								
							
							
						
						
									
										29
									
								
								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)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										4
									
								
								Makefile
								
								
								
								
							| 
						 | 
				
			
			@ -29,10 +29,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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -122,7 +122,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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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")
 | 
			
		||||
| 
						 | 
				
			
			@ -129,7 +129,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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -65,23 +65,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
 | 
			
		||||
| 
						 | 
				
			
			@ -99,6 +87,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 {
 | 
			
		||||
| 
						 | 
				
			
			@ -208,7 +254,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)
 | 
			
		||||
| 
						 | 
				
			
			@ -256,8 +302,8 @@ func (i *FileInfo) readListing(checker rules.Checker, readHeader bool) error {
 | 
			
		|||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		isSymlink := IsSymlink(f.Mode())
 | 
			
		||||
		symlink := ""
 | 
			
		||||
		isSymlink := IsSymlink(f.Mode())
 | 
			
		||||
		if isSymlink {
 | 
			
		||||
			// 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.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										32
									
								
								http/raw.go
								
								
								
								
							
							
						
						
									
										32
									
								
								http/raw.go
								
								
								
								
							| 
						 | 
				
			
			@ -1,9 +1,8 @@
 | 
			
		|||
package http
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"log"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	gopath "path"
 | 
			
		||||
| 
						 | 
				
			
			@ -11,7 +10,6 @@ import (
 | 
			
		|||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/mholt/archiver"
 | 
			
		||||
	"github.com/spf13/afero"
 | 
			
		||||
 | 
			
		||||
	"github.com/filebrowser/filebrowser/v2/files"
 | 
			
		||||
	"github.com/filebrowser/filebrowser/v2/fileutils"
 | 
			
		||||
| 
						 | 
				
			
			@ -117,19 +115,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 +133,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 +147,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 +192,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)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,6 @@ import (
 | 
			
		|||
	"context"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"os"
 | 
			
		||||
| 
						 | 
				
			
			@ -161,13 +160,9 @@ 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)
 | 
			
		||||
			err := d.user.Fs.MkdirAll(r.URL.Path, 0775) //nolint:gomnd
 | 
			
		||||
			return errToStatus(err), err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -228,16 +223,20 @@ 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
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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
 | 
			
		||||
| 
						 | 
				
			
			@ -248,10 +247,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
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -378,12 +373,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
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -51,9 +51,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 {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue