add changes for read from 2 paths
This commit is contained in:
parent
fe5ca74aa1
commit
ccb9dbff03
@ -31,7 +31,6 @@ func addConfigFlags(flags *pflag.FlagSet) {
|
|||||||
addServerFlags(flags)
|
addServerFlags(flags)
|
||||||
addUserFlags(flags)
|
addUserFlags(flags)
|
||||||
flags.BoolP("signup", "s", false, "allow users to signup")
|
flags.BoolP("signup", "s", false, "allow users to signup")
|
||||||
flags.Bool("create-user-dir", false, "generate user's home directory automatically")
|
|
||||||
flags.String("shell", "", "shell command to which other commands should be appended")
|
flags.String("shell", "", "shell command to which other commands should be appended")
|
||||||
|
|
||||||
flags.String("auth.method", string(auth.MethodJSONAuth), "authentication type")
|
flags.String("auth.method", string(auth.MethodJSONAuth), "authentication type")
|
||||||
|
|||||||
@ -29,12 +29,11 @@ override the options.`,
|
|||||||
authMethod, auther := getAuthentication(flags)
|
authMethod, auther := getAuthentication(flags)
|
||||||
|
|
||||||
s := &settings.Settings{
|
s := &settings.Settings{
|
||||||
Key: generateKey(),
|
Key: generateKey(),
|
||||||
Signup: mustGetBool(flags, "signup"),
|
Signup: mustGetBool(flags, "signup"),
|
||||||
CreateUserDir: mustGetBool(flags, "create-user-dir"),
|
Shell: convertCmdStrToCmdArray(mustGetString(flags, "shell")),
|
||||||
Shell: convertCmdStrToCmdArray(mustGetString(flags, "shell")),
|
AuthMethod: authMethod,
|
||||||
AuthMethod: authMethod,
|
Defaults: defaults,
|
||||||
Defaults: defaults,
|
|
||||||
Branding: settings.Branding{
|
Branding: settings.Branding{
|
||||||
Name: mustGetString(flags, "branding.name"),
|
Name: mustGetString(flags, "branding.name"),
|
||||||
DisableExternal: mustGetBool(flags, "branding.disableExternal"),
|
DisableExternal: mustGetBool(flags, "branding.disableExternal"),
|
||||||
|
|||||||
@ -49,8 +49,6 @@ you want to change. Other options will remain unchanged.`,
|
|||||||
hasAuth = true
|
hasAuth = true
|
||||||
case "shell":
|
case "shell":
|
||||||
set.Shell = convertCmdStrToCmdArray(mustGetString(flags, flag.Name))
|
set.Shell = convertCmdStrToCmdArray(mustGetString(flags, flag.Name))
|
||||||
case "create-user-dir":
|
|
||||||
set.CreateUserDir = mustGetBool(flags, flag.Name)
|
|
||||||
case "branding.name":
|
case "branding.name":
|
||||||
set.Branding.Name = mustGetString(flags, flag.Name)
|
set.Branding.Name = mustGetString(flags, flag.Name)
|
||||||
case "branding.color":
|
case "branding.color":
|
||||||
|
|||||||
@ -60,6 +60,7 @@ func addServerFlags(flags *pflag.FlagSet) {
|
|||||||
flags.StringP("cert", "t", "", "tls certificate")
|
flags.StringP("cert", "t", "", "tls certificate")
|
||||||
flags.StringP("key", "k", "", "tls key")
|
flags.StringP("key", "k", "", "tls key")
|
||||||
flags.StringP("root", "r", ".", "root to prepend to relative paths")
|
flags.StringP("root", "r", ".", "root to prepend to relative paths")
|
||||||
|
flags.StringP("anotherPath", "R", "", "another path to use")
|
||||||
flags.String("socket", "", "socket to listen to (cannot be used with address, port, cert nor key flags)")
|
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") //nolint:gomnd
|
flags.Uint32("socket-perm", 0666, "unix socket file permissions") //nolint:gomnd
|
||||||
flags.StringP("baseurl", "b", "", "base url")
|
flags.StringP("baseurl", "b", "", "base url")
|
||||||
@ -205,6 +206,10 @@ func getRunParams(flags *pflag.FlagSet, st *storage.Storage) *settings.Server {
|
|||||||
server.Root = val
|
server.Root = val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if val, set := getParamB(flags, "anotherPath"); set {
|
||||||
|
server.AnotherPath = val
|
||||||
|
}
|
||||||
|
|
||||||
if val, set := getParamB(flags, "baseurl"); set {
|
if val, set := getParamB(flags, "baseurl"); set {
|
||||||
server.BaseURL = val
|
server.BaseURL = val
|
||||||
}
|
}
|
||||||
|
|||||||
137
files/file.go
137
files/file.go
@ -16,15 +16,15 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/spf13/afero"
|
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/errors"
|
"github.com/filebrowser/filebrowser/v2/errors"
|
||||||
"github.com/filebrowser/filebrowser/v2/rules"
|
"github.com/filebrowser/filebrowser/v2/rules"
|
||||||
|
"github.com/spf13/afero"
|
||||||
)
|
)
|
||||||
|
|
||||||
const PermFile = 0644
|
const PermFile = 0664
|
||||||
const PermDir = 0755
|
const PermDir = 0755
|
||||||
|
|
||||||
// FileInfo describes a file.
|
// FileInfo describes a file.
|
||||||
@ -50,14 +50,17 @@ type FileInfo struct {
|
|||||||
|
|
||||||
// FileOptions are the options when getting a file info.
|
// FileOptions are the options when getting a file info.
|
||||||
type FileOptions struct {
|
type FileOptions struct {
|
||||||
Fs afero.Fs
|
Fs afero.Fs
|
||||||
Path string
|
Path string
|
||||||
Modify bool
|
Modify bool
|
||||||
Expand bool
|
Expand bool
|
||||||
ReadHeader bool
|
ReadHeader bool
|
||||||
Token string
|
FolderSize bool
|
||||||
Checker rules.Checker
|
Token string
|
||||||
Content bool
|
Checker rules.Checker
|
||||||
|
Content bool
|
||||||
|
RootPath string
|
||||||
|
AnotherPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ImageResolution struct {
|
type ImageResolution struct {
|
||||||
@ -65,10 +68,25 @@ type ImageResolution struct {
|
|||||||
Height int `json:"height"`
|
Height int `json:"height"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// function that checks if given full path exists or not
|
||||||
|
// it helps to determine to which NFS we need to go IDC or KFS
|
||||||
|
func CheckIfExistsInPath(pathToCheck string) bool {
|
||||||
|
_, pathExistsErr := os.Stat(pathToCheck)
|
||||||
|
return !os.IsNotExist(pathExistsErr)
|
||||||
|
}
|
||||||
|
|
||||||
// NewFileInfo creates a File object from a path and a given user. This File
|
// NewFileInfo creates a File object from a path and a given user. This File
|
||||||
// object will be automatically filled depending on if it is a directory
|
// object will be automatically filled depending on if it is a directory
|
||||||
// or a file. If it's a video file, it will also detect any subtitles.
|
// or a file. If it's a video file, it will also detect any subtitles.
|
||||||
func NewFileInfo(opts FileOptions) (*FileInfo, error) {
|
func NewFileInfo(opts FileOptions) (*FileInfo, error) {
|
||||||
|
log.Printf("ROOT PATH - %v:", opts.RootPath)
|
||||||
|
log.Printf("ANOTHER PATH - %v:", opts.AnotherPath)
|
||||||
|
rootFilePath := opts.RootPath + opts.Path
|
||||||
|
if !CheckIfExistsInPath(rootFilePath) {
|
||||||
|
opts.Fs = afero.NewBasePathFs(afero.NewOsFs(), opts.AnotherPath)
|
||||||
|
} else {
|
||||||
|
opts.Fs = afero.NewBasePathFs(afero.NewOsFs(), opts.RootPath)
|
||||||
|
}
|
||||||
if !opts.Checker.Check(opts.Path) {
|
if !opts.Checker.Check(opts.Path) {
|
||||||
return nil, os.ErrPermission
|
return nil, os.ErrPermission
|
||||||
}
|
}
|
||||||
@ -77,10 +95,16 @@ func NewFileInfo(opts FileOptions) (*FileInfo, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if file.IsDir && opts.FolderSize {
|
||||||
|
size, err := getFolderSize(file.RealPath())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
file.Size = size
|
||||||
|
}
|
||||||
if opts.Expand {
|
if opts.Expand {
|
||||||
if file.IsDir {
|
if file.IsDir {
|
||||||
if err := file.readListing(opts.Checker, opts.ReadHeader); err != nil { //nolint:govet
|
if err := file.readListing(opts.Checker, opts.ReadHeader, opts.RootPath, opts.AnotherPath); err != nil { //nolint:govet
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return file, nil
|
return file, nil
|
||||||
@ -95,12 +119,31 @@ func NewFileInfo(opts FileOptions) (*FileInfo, error) {
|
|||||||
return file, err
|
return file, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getFolderSize(path string) (int64, error) {
|
||||||
|
var size int64
|
||||||
|
err := filepath.WalkDir(path, func(_ string, d os.DirEntry, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !d.IsDir() {
|
||||||
|
info, err := d.Info()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
size += info.Size()
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
return size, err
|
||||||
|
}
|
||||||
|
|
||||||
func stat(opts FileOptions) (*FileInfo, error) {
|
func stat(opts FileOptions) (*FileInfo, error) {
|
||||||
var file *FileInfo
|
var file *FileInfo
|
||||||
|
|
||||||
if lstaterFs, ok := opts.Fs.(afero.Lstater); ok {
|
if lstaterFs, ok := opts.Fs.(afero.Lstater); ok {
|
||||||
info, _, err := lstaterFs.LstatIfPossible(opts.Path)
|
info, _, err := lstaterFs.LstatIfPossible(opts.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Printf("stat current path error - %v:", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
file = &FileInfo{
|
file = &FileInfo{
|
||||||
@ -349,11 +392,60 @@ func (i *FileInfo) detectSubtitles() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *FileInfo) readListing(checker rules.Checker, readHeader bool) error {
|
// async read dir and append the data to given FileInfo slice
|
||||||
afs := &afero.Afero{Fs: i.Fs}
|
func readDirAsync(fs afero.Fs, fullPath string, wg *sync.WaitGroup, resultSlice *[]os.FileInfo) {
|
||||||
dir, err := afs.ReadDir(i.Path)
|
defer wg.Done()
|
||||||
|
|
||||||
|
dir, err := afero.ReadDir(fs, fullPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
log.Printf("Error reading directory: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append the result to the slice
|
||||||
|
*resultSlice = append(*resultSlice, dir...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *FileInfo) readListing(checker rules.Checker, readHeader bool, rootPath, anotherPath string) error {
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
var rootDir []os.FileInfo
|
||||||
|
var anotherDir []os.FileInfo
|
||||||
|
var finalDir []os.FileInfo
|
||||||
|
useAnotherDir := false
|
||||||
|
anotherFullPath := anotherPath + i.Path
|
||||||
|
rootFullPath := rootPath + i.Path
|
||||||
|
existsInRootPath := CheckIfExistsInPath(rootFullPath)
|
||||||
|
existsInAnotherPath := CheckIfExistsInPath(anotherFullPath)
|
||||||
|
log.Printf("%v %v %v %v", anotherFullPath, existsInAnotherPath, rootFullPath, existsInRootPath)
|
||||||
|
// if we aren't in home scenario use idcSite only because we are messing with opth.Path
|
||||||
|
// in some cases it can go to KFS site instead of going to IDC, so just to be sure...
|
||||||
|
if existsInRootPath && existsInAnotherPath && i.Path != "/" {
|
||||||
|
useAnotherDir = true
|
||||||
|
}
|
||||||
|
if existsInRootPath && !useAnotherDir {
|
||||||
|
wg.Add(1)
|
||||||
|
go readDirAsync(afero.NewOsFs(), rootFullPath, &wg, &rootDir)
|
||||||
|
}
|
||||||
|
if existsInAnotherPath {
|
||||||
|
wg.Add(1)
|
||||||
|
go readDirAsync(afero.NewOsFs(), anotherFullPath, &wg, &anotherDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for all goroutines to finish
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
if len(rootDir) > 0 && len(anotherDir) > 0 {
|
||||||
|
log.Printf("combining results")
|
||||||
|
finalDir = append(rootDir, anotherDir...)
|
||||||
|
} else if len(rootDir) > 0 {
|
||||||
|
finalDir = rootDir
|
||||||
|
} else {
|
||||||
|
finalDir = anotherDir
|
||||||
|
}
|
||||||
|
|
||||||
|
//in case of somehow the path exists in both paths due to some mess with opts.path use idc site
|
||||||
|
if useAnotherDir {
|
||||||
|
finalDir = anotherDir
|
||||||
}
|
}
|
||||||
|
|
||||||
listing := &Listing{
|
listing := &Listing{
|
||||||
@ -362,14 +454,12 @@ func (i *FileInfo) readListing(checker rules.Checker, readHeader bool) error {
|
|||||||
NumFiles: 0,
|
NumFiles: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, f := range dir {
|
for _, f := range finalDir {
|
||||||
name := f.Name()
|
name := f.Name()
|
||||||
fPath := path.Join(i.Path, name)
|
fPath := path.Join(i.Path, name)
|
||||||
|
|
||||||
if !checker.Check(fPath) {
|
if !checker.Check(fPath) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
isSymlink, isInvalidLink := false, false
|
isSymlink, isInvalidLink := false, false
|
||||||
if IsSymlink(f.Mode()) {
|
if IsSymlink(f.Mode()) {
|
||||||
isSymlink = true
|
isSymlink = true
|
||||||
@ -382,7 +472,6 @@ func (i *FileInfo) readListing(checker rules.Checker, readHeader bool) error {
|
|||||||
isInvalidLink = true
|
isInvalidLink = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
file := &FileInfo{
|
file := &FileInfo{
|
||||||
Fs: i.Fs,
|
Fs: i.Fs,
|
||||||
Name: name,
|
Name: name,
|
||||||
@ -393,9 +482,8 @@ func (i *FileInfo) readListing(checker rules.Checker, readHeader bool) error {
|
|||||||
IsSymlink: isSymlink,
|
IsSymlink: isSymlink,
|
||||||
Extension: filepath.Ext(name),
|
Extension: filepath.Ext(name),
|
||||||
Path: fPath,
|
Path: fPath,
|
||||||
currentDir: dir,
|
currentDir: finalDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
if !file.IsDir && strings.HasPrefix(mime.TypeByExtension(file.Extension), "image/") {
|
if !file.IsDir && strings.HasPrefix(mime.TypeByExtension(file.Extension), "image/") {
|
||||||
resolution, err := calculateImageResolution(file.Fs, file.Path)
|
resolution, err := calculateImageResolution(file.Fs, file.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -404,7 +492,6 @@ func (i *FileInfo) readListing(checker rules.Checker, readHeader bool) error {
|
|||||||
file.Resolution = resolution
|
file.Resolution = resolution
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if file.IsDir {
|
if file.IsDir {
|
||||||
listing.NumDirs++
|
listing.NumDirs++
|
||||||
} else {
|
} else {
|
||||||
@ -419,10 +506,8 @@ func (i *FileInfo) readListing(checker rules.Checker, readHeader bool) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
listing.Items = append(listing.Items, file)
|
listing.Items = append(listing.Items, file)
|
||||||
}
|
}
|
||||||
|
|
||||||
i.Listing = listing
|
i.Listing = listing
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,8 +7,6 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/files"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// MoveFile moves file from src to dst.
|
// MoveFile moves file from src to dst.
|
||||||
@ -42,13 +40,13 @@ func CopyFile(fs afero.Fs, source, dest string) error {
|
|||||||
|
|
||||||
// Makes the directory needed to create the dst
|
// Makes the directory needed to create the dst
|
||||||
// file.
|
// file.
|
||||||
err = fs.MkdirAll(filepath.Dir(dest), files.PermDir)
|
err = fs.MkdirAll(filepath.Dir(dest), 0666) //nolint:gomnd
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the destination file.
|
// Create the destination file.
|
||||||
dst, err := fs.OpenFile(dest, os.O_RDWR|os.O_CREATE|os.O_TRUNC, files.PermFile)
|
dst, err := fs.OpenFile(dest, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0775) //nolint:gomnd
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
8
frontend/package-lock.json
generated
8
frontend/package-lock.json
generated
@ -46,7 +46,7 @@
|
|||||||
"postcss": "^8.4.31",
|
"postcss": "^8.4.31",
|
||||||
"prettier": "^3.0.1",
|
"prettier": "^3.0.1",
|
||||||
"terser": "^5.19.2",
|
"terser": "^5.19.2",
|
||||||
"vite": "^4.5.2",
|
"vite": "^4.4.12",
|
||||||
"vite-plugin-compression2": "^0.10.3",
|
"vite-plugin-compression2": "^0.10.3",
|
||||||
"vite-plugin-rewrite-all": "^1.0.1"
|
"vite-plugin-rewrite-all": "^1.0.1"
|
||||||
}
|
}
|
||||||
@ -5663,9 +5663,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "4.5.2",
|
"version": "4.4.12",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-4.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-4.4.12.tgz",
|
||||||
"integrity": "sha512-tBCZBNSBbHQkaGyhGCDUGqeo2ph8Fstyp6FMSvTtsXeZSPpSMGlviAOav2hxVTqFcx8Hj/twtWKsMJXNY0xI8w==",
|
"integrity": "sha512-KtPlUbWfxzGVul8Nut8Gw2Qe8sBzWY+8QVc5SL8iRFnpnrcoCaNlzO40c1R6hPmcdTwIPEDkq0Y9+27a5tVbdQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.18.10",
|
"esbuild": "^0.18.10",
|
||||||
|
|||||||
@ -52,7 +52,7 @@
|
|||||||
"postcss": "^8.4.31",
|
"postcss": "^8.4.31",
|
||||||
"prettier": "^3.0.1",
|
"prettier": "^3.0.1",
|
||||||
"terser": "^5.19.2",
|
"terser": "^5.19.2",
|
||||||
"vite": "^4.5.2",
|
"vite": "^4.4.12",
|
||||||
"vite-plugin-compression2": "^0.10.3",
|
"vite-plugin-compression2": "^0.10.3",
|
||||||
"vite-plugin-rewrite-all": "^1.0.1"
|
"vite-plugin-rewrite-all": "^1.0.1"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -16,8 +16,6 @@
|
|||||||
[{[ if .Name -]}][{[ .Name ]}][{[ else ]}]File Browser[{[ end ]}]
|
[{[ if .Name -]}][{[ .Name ]}][{[ else ]}]File Browser[{[ end ]}]
|
||||||
</title>
|
</title>
|
||||||
|
|
||||||
<meta name="robots" content="noindex,nofollow">
|
|
||||||
|
|
||||||
<link
|
<link
|
||||||
rel="icon"
|
rel="icon"
|
||||||
type="image/png"
|
type="image/png"
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
<div
|
<div
|
||||||
class="shell"
|
class="shell"
|
||||||
:class="{ ['shell--hidden']: !showShell }"
|
:class="{ ['shell--hidden']: !showShell }"
|
||||||
:style="{ height: `${this.shellHeight}em`, direction: 'ltr' }"
|
:style="{ height: `${this.shellHeight}em` }"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@pointerdown="startDrag()"
|
@pointerdown="startDrag()"
|
||||||
|
|||||||
@ -38,7 +38,7 @@
|
|||||||
import { enableThumbs } from "@/utils/constants";
|
import { enableThumbs } from "@/utils/constants";
|
||||||
import { mapMutations, mapGetters, mapState } from "vuex";
|
import { mapMutations, mapGetters, mapState } from "vuex";
|
||||||
import { filesize } from "@/utils";
|
import { filesize } from "@/utils";
|
||||||
import moment from "moment/min/moment-with-locales";
|
import moment from "moment";
|
||||||
import { files as api } from "@/api";
|
import { files as api } from "@/api";
|
||||||
import * as upload from "@/utils/upload";
|
import * as upload from "@/utils/upload";
|
||||||
|
|
||||||
@ -191,12 +191,7 @@ export default {
|
|||||||
action(overwrite, rename);
|
action(overwrite, rename);
|
||||||
},
|
},
|
||||||
itemClick: function (event) {
|
itemClick: function (event) {
|
||||||
if (
|
if (this.singleClick && !this.$store.state.multiple) this.open();
|
||||||
!(event.ctrlKey || event.metaKey) &&
|
|
||||||
this.singleClick &&
|
|
||||||
!this.$store.state.multiple
|
|
||||||
)
|
|
||||||
this.open();
|
|
||||||
else this.click(event);
|
else this.click(event);
|
||||||
},
|
},
|
||||||
click: function (event) {
|
click: function (event) {
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
<div
|
<div
|
||||||
class="card-action"
|
class="card-action"
|
||||||
style="display: flex; align-items: center; justify-content: space-between"
|
style="display: flex; align-items: center; justify-content: space-between;"
|
||||||
>
|
>
|
||||||
<template v-if="user.perm.create">
|
<template v-if="user.perm.create">
|
||||||
<button
|
<button
|
||||||
@ -20,7 +20,7 @@
|
|||||||
@click="$refs.fileList.createDir()"
|
@click="$refs.fileList.createDir()"
|
||||||
:aria-label="$t('sidebar.newFolder')"
|
:aria-label="$t('sidebar.newFolder')"
|
||||||
:title="$t('sidebar.newFolder')"
|
:title="$t('sidebar.newFolder')"
|
||||||
style="justify-self: left"
|
style="justify-self: left;"
|
||||||
>
|
>
|
||||||
<span>{{ $t("sidebar.newFolder") }}</span>
|
<span>{{ $t("sidebar.newFolder") }}</span>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@ -89,7 +89,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { mapState, mapGetters } from "vuex";
|
import { mapState, mapGetters } from "vuex";
|
||||||
import { filesize } from "@/utils";
|
import { filesize } from "@/utils";
|
||||||
import moment from "moment/min/moment-with-locales";
|
import moment from "moment";
|
||||||
import { files as api } from "@/api";
|
import { files as api } from "@/api";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -133,13 +133,14 @@ export default {
|
|||||||
: this.req.items[this.selected[0]].isDir)
|
: this.req.items[this.selected[0]].isDir)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
resolution: function () {
|
resolution: function() {
|
||||||
if (this.selectedCount === 1) {
|
if (this.selectedCount === 1) {
|
||||||
const selectedItem = this.req.items[this.selected[0]];
|
const selectedItem = this.req.items[this.selected[0]];
|
||||||
if (selectedItem && selectedItem.type === "image") {
|
if (selectedItem && selectedItem.type === 'image') {
|
||||||
return selectedItem.resolution;
|
return selectedItem.resolution;
|
||||||
}
|
}
|
||||||
} else if (this.req && this.req.type === "image") {
|
}
|
||||||
|
else if (this.req && this.req.type === 'image') {
|
||||||
return this.req.resolution;
|
return this.req.resolution;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
<div
|
<div
|
||||||
class="card-action"
|
class="card-action"
|
||||||
style="display: flex; align-items: center; justify-content: space-between"
|
style="display: flex; align-items: center; justify-content: space-between;"
|
||||||
>
|
>
|
||||||
<template v-if="user.perm.create">
|
<template v-if="user.perm.create">
|
||||||
<button
|
<button
|
||||||
@ -19,7 +19,7 @@
|
|||||||
@click="$refs.fileList.createDir()"
|
@click="$refs.fileList.createDir()"
|
||||||
:aria-label="$t('sidebar.newFolder')"
|
:aria-label="$t('sidebar.newFolder')"
|
||||||
:title="$t('sidebar.newFolder')"
|
:title="$t('sidebar.newFolder')"
|
||||||
style="justify-self: left"
|
style="justify-self: left;"
|
||||||
>
|
>
|
||||||
<span>{{ $t("sidebar.newFolder") }}</span>
|
<span>{{ $t("sidebar.newFolder") }}</span>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@ -27,7 +27,6 @@ import Share from "./Share.vue";
|
|||||||
import Upload from "./Upload.vue";
|
import Upload from "./Upload.vue";
|
||||||
import ShareDelete from "./ShareDelete.vue";
|
import ShareDelete from "./ShareDelete.vue";
|
||||||
import Sidebar from "../Sidebar.vue";
|
import Sidebar from "../Sidebar.vue";
|
||||||
import DiscardEditorChanges from "./DiscardEditorChanges.vue";
|
|
||||||
import { mapGetters, mapState } from "vuex";
|
import { mapGetters, mapState } from "vuex";
|
||||||
import buttons from "@/utils/buttons";
|
import buttons from "@/utils/buttons";
|
||||||
|
|
||||||
@ -48,8 +47,7 @@ export default {
|
|||||||
ReplaceRename,
|
ReplaceRename,
|
||||||
Upload,
|
Upload,
|
||||||
ShareDelete,
|
ShareDelete,
|
||||||
Sidebar,
|
Sidebar
|
||||||
DiscardEditorChanges,
|
|
||||||
},
|
},
|
||||||
data: function () {
|
data: function () {
|
||||||
return {
|
return {
|
||||||
@ -64,16 +62,17 @@ export default {
|
|||||||
window.addEventListener("keydown", (event) => {
|
window.addEventListener("keydown", (event) => {
|
||||||
if (this.currentPrompt == null) return;
|
if (this.currentPrompt == null) return;
|
||||||
|
|
||||||
const promptName = this.currentPrompt.prompt;
|
let prompt = this.$refs.currentComponent;
|
||||||
const prompt = this.$refs[promptName];
|
|
||||||
|
|
||||||
if (event.code === "Escape") {
|
// Esc!
|
||||||
|
if (event.keyCode === 27) {
|
||||||
event.stopImmediatePropagation();
|
event.stopImmediatePropagation();
|
||||||
this.$store.commit("closeHovers");
|
this.$store.commit("closeHovers");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.code === "Enter") {
|
// Enter
|
||||||
switch (promptName) {
|
if (event.keyCode == 13) {
|
||||||
|
switch (this.currentPrompt.prompt) {
|
||||||
case "delete":
|
case "delete":
|
||||||
prompt.submit();
|
prompt.submit();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -128,7 +128,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { mapState, mapGetters } from "vuex";
|
import { mapState, mapGetters } from "vuex";
|
||||||
import { share as api, pub as pub_api } from "@/api";
|
import { share as api, pub as pub_api } from "@/api";
|
||||||
import moment from "moment/min/moment-with-locales";
|
import moment from "moment";
|
||||||
import Clipboard from "clipboard";
|
import Clipboard from "clipboard";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|||||||
@ -220,10 +220,6 @@ body.rtl .card .card-title>*:first-child {
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.rtl .card .card-action {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card .card-content.full {
|
.card .card-content.full {
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
|||||||
@ -38,8 +38,7 @@
|
|||||||
"update": "Update",
|
"update": "Update",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"openFile": "Open file",
|
"openFile": "Open file",
|
||||||
"continue": "Continue",
|
"continue": "Continue"
|
||||||
"discardChanges": "Discard"
|
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "Download File",
|
"downloadFile": "Download File",
|
||||||
@ -163,8 +162,7 @@
|
|||||||
"uploadFiles": "Uploading {files} files...",
|
"uploadFiles": "Uploading {files} files...",
|
||||||
"uploadMessage": "Select an option to upload.",
|
"uploadMessage": "Select an option to upload.",
|
||||||
"optionalPassword": "Optional password",
|
"optionalPassword": "Optional password",
|
||||||
"resolution": "Resolution",
|
"resolution": "Resolution"
|
||||||
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
|
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"images": "Images",
|
"images": "Images",
|
||||||
|
|||||||
@ -5,9 +5,8 @@
|
|||||||
"copy": "העתקה",
|
"copy": "העתקה",
|
||||||
"copyFile": "העתק קובץ",
|
"copyFile": "העתק קובץ",
|
||||||
"copyToClipboard": "העתק ללוח",
|
"copyToClipboard": "העתק ללוח",
|
||||||
"copyDownloadLinkToClipboard": "העתק קישור הורדה ללוח",
|
"create": "יצירה",
|
||||||
"create": "צור",
|
"delete": "מחיקה",
|
||||||
"delete": "מחק",
|
|
||||||
"download": "הורדה",
|
"download": "הורדה",
|
||||||
"file": "קובץ",
|
"file": "קובץ",
|
||||||
"folder": "תיקייה",
|
"folder": "תיקייה",
|
||||||
@ -19,7 +18,7 @@
|
|||||||
"new": "חדש",
|
"new": "חדש",
|
||||||
"next": "הבא",
|
"next": "הבא",
|
||||||
"ok": "אישור",
|
"ok": "אישור",
|
||||||
"permalink": "יצירת קישור קבוע",
|
"permalink": "צור קישור קבוע",
|
||||||
"previous": "הקודם",
|
"previous": "הקודם",
|
||||||
"publish": "פרסום",
|
"publish": "פרסום",
|
||||||
"rename": "שינוי שם",
|
"rename": "שינוי שם",
|
||||||
@ -37,18 +36,13 @@
|
|||||||
"toggleSidebar": "פתיחת/סגירת סרגל צד",
|
"toggleSidebar": "פתיחת/סגירת סרגל צד",
|
||||||
"update": "עדכון",
|
"update": "עדכון",
|
||||||
"upload": "העלאה",
|
"upload": "העלאה",
|
||||||
"openFile": "פתח קובץ",
|
"openFile": "פתח קובץ"
|
||||||
"continue": "המשך",
|
|
||||||
"discardChanges": "זריקת השינויים"
|
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "הורד קובץ",
|
"downloadFile": "הורד קובץ",
|
||||||
"downloadFolder": "הורד תיקייה",
|
"downloadFolder": "הורד תיקייה",
|
||||||
"downloadSelected": "הורד קבצים שנבחרו"
|
"downloadSelected": "הורד קבצים שנבחרו"
|
||||||
},
|
},
|
||||||
"upload": {
|
|
||||||
"abortUpload": "האם אתה בטוח שברצונך להפסיק את ההעלאה?"
|
|
||||||
},
|
|
||||||
"errors": {
|
"errors": {
|
||||||
"forbidden": "אין לך הרשאות גישה",
|
"forbidden": "אין לך הרשאות גישה",
|
||||||
"internal": "משהו השתבש",
|
"internal": "משהו השתבש",
|
||||||
@ -72,7 +66,7 @@
|
|||||||
"sortByLastModified": "מיין לפי השינוי האחרון",
|
"sortByLastModified": "מיין לפי השינוי האחרון",
|
||||||
"sortByName": "מיין לפי שם",
|
"sortByName": "מיין לפי שם",
|
||||||
"sortBySize": "מיין לפי גודל",
|
"sortBySize": "מיין לפי גודל",
|
||||||
"noPreview": "לא זמינה תצוגה מקדימה לקובץ זה"
|
"noPreview": "תצוגה מקדימה לא זמינה לקובץ זה"
|
||||||
},
|
},
|
||||||
"help": {
|
"help": {
|
||||||
"click": "בחר קובץ או תיקייה",
|
"click": "בחר קובץ או תיקייה",
|
||||||
@ -161,8 +155,7 @@
|
|||||||
"upload": "העלאה",
|
"upload": "העלאה",
|
||||||
"uploadFiles": "מעלה {files} קבצים...",
|
"uploadFiles": "מעלה {files} קבצים...",
|
||||||
"uploadMessage": "בחר אפשרות העלאה.",
|
"uploadMessage": "בחר אפשרות העלאה.",
|
||||||
"optionalPassword": "סיסמא אופציונלית",
|
"optionalPassword": "סיסמא אופציונלית"
|
||||||
"discardEditorChanges": "האם אתה בטוח שברצונך לבטל את השינויים שביצעת?"
|
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"images": "תמונות",
|
"images": "תמונות",
|
||||||
@ -197,7 +190,6 @@
|
|||||||
"customStylesheet": "עיצוב מותאם אישית (Stylesheet)",
|
"customStylesheet": "עיצוב מותאם אישית (Stylesheet)",
|
||||||
"defaultUserDescription": "הגדרות ברירת המחדל למשתמשים חדשים",
|
"defaultUserDescription": "הגדרות ברירת המחדל למשתמשים חדשים",
|
||||||
"disableExternalLinks": "השבת קישורים חיצוניים (למעט תיעוד)",
|
"disableExternalLinks": "השבת קישורים חיצוניים (למעט תיעוד)",
|
||||||
"disableUsedDiskPercentage": "אל תציג גרף שימוש בדיסק",
|
|
||||||
"documentation": "תיעוד",
|
"documentation": "תיעוד",
|
||||||
"examples": "דוגמאות",
|
"examples": "דוגמאות",
|
||||||
"executeOnShell": "בצע במסוף",
|
"executeOnShell": "בצע במסוף",
|
||||||
@ -226,7 +218,7 @@
|
|||||||
"share": "שיתוף קבצים"
|
"share": "שיתוף קבצים"
|
||||||
},
|
},
|
||||||
"permissions": "הרשאות",
|
"permissions": "הרשאות",
|
||||||
"permissionsHelp": "אתה יכול להגדיר את המשתמש להיות מנהל מערכת או לבחור את ההרשאות בנפרד. אם תבחר \"מנהל מערכת\", כל ההרשאות יינתנו אוטומטית. ניהול המשתמשים נשאר הרשאה של מנהל מערכת.\n",
|
"permissionsHelp": "אתה יכול להגדיר את המשתמש להיות מנהל מערכת או לבחור את ההרשאות בנפרד. אם תבחר \"מנהל מערכת\", כל ההרשאות ייבחרו אוטומטית. ניהול המשתמשים נשאר הרשאה של מנהל מערכת.\n",
|
||||||
"profileSettings": "הגדרות פרופיל",
|
"profileSettings": "הגדרות פרופיל",
|
||||||
"ruleExample1": "מנע גישה לקבצים נסתרים (כל קובץ/תיקייה שמתחיל בנקודה, לדוגמא .git)",
|
"ruleExample1": "מנע גישה לקבצים נסתרים (כל קובץ/תיקייה שמתחיל בנקודה, לדוגמא .git)",
|
||||||
"ruleExample2": "חסימת גישה לקובץ בשם Caddyfile בהיקף הראשי.",
|
"ruleExample2": "חסימת גישה לקובץ בשם Caddyfile בהיקף הראשי.",
|
||||||
|
|||||||
@ -3,87 +3,76 @@
|
|||||||
"cancel": "キャンセル",
|
"cancel": "キャンセル",
|
||||||
"close": "閉じる",
|
"close": "閉じる",
|
||||||
"copy": "コピー",
|
"copy": "コピー",
|
||||||
"copyFile": "ファイルのコピー",
|
"copyFile": "ファイルをコピー",
|
||||||
"copyToClipboard": "共有リンクをコピー",
|
"copyToClipboard": "クリップボードにコピー",
|
||||||
"copyDownloadLinkToClipboard": "ダウンロードリンクをコピー",
|
|
||||||
"create": "作成",
|
"create": "作成",
|
||||||
"delete": "削除",
|
"delete": "削除",
|
||||||
"download": "ダウンロード",
|
"download": "ダウンロード",
|
||||||
"file": "ファイル",
|
"hideDotfiles": "",
|
||||||
"folder": "フォルダー",
|
|
||||||
"hideDotfiles": "ドットで始まるファイルを表示しない",
|
|
||||||
"info": "情報",
|
"info": "情報",
|
||||||
"more": "さらに",
|
"more": "More",
|
||||||
"move": "移動",
|
"move": "移動",
|
||||||
"moveFile": "ファイルの移動",
|
"moveFile": "ファイルを移動",
|
||||||
"new": "新規",
|
"new": "新規",
|
||||||
"next": "次へ",
|
"next": "次",
|
||||||
"ok": "OK",
|
"ok": "OK",
|
||||||
"permalink": "パーマリンクを取得",
|
"permalink": "固定リンク",
|
||||||
"previous": "前へ",
|
"previous": "前",
|
||||||
"publish": "公開",
|
"publish": "発表",
|
||||||
"rename": "名前の変更",
|
"rename": "名前を変更",
|
||||||
"replace": "置換する",
|
"replace": "置き換える",
|
||||||
"reportIssue": "問題を報告",
|
"reportIssue": "問題を報告",
|
||||||
"save": "保存",
|
"save": "保存",
|
||||||
"schedule": "スケジュール",
|
"schedule": "スケジュール",
|
||||||
"search": "検索",
|
"search": "検索",
|
||||||
"select": "選択",
|
"select": "選択",
|
||||||
"selectMultiple": "複数選択",
|
"selectMultiple": "複数選択",
|
||||||
"share": "共有",
|
"share": "シェア",
|
||||||
"shell": "シェルの切り替え",
|
"shell": "Toggle shell",
|
||||||
"submit": "送信",
|
"switchView": "表示を切り替わる",
|
||||||
"switchView": "表示の切り替え",
|
"toggleSidebar": "サイドバーを表示する",
|
||||||
"toggleSidebar": "サイドバーの切り替え",
|
|
||||||
"update": "更新",
|
"update": "更新",
|
||||||
"upload": "アップロード",
|
"upload": "アップロード"
|
||||||
"openFile": "ファイルを開く",
|
|
||||||
"continue": "続行"
|
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "ファイルのダウンロード",
|
"downloadFile": "Download File",
|
||||||
"downloadFolder": "フォルダーのダウンロード",
|
"downloadFolder": "Download Folder",
|
||||||
"downloadSelected": "選択した項目のダウンロード"
|
"downloadSelected": ""
|
||||||
},
|
|
||||||
"upload": {
|
|
||||||
"abortUpload": "アップロードをキャンセルしますか?"
|
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"forbidden": "これにアクセスする権限がありません。",
|
"forbidden": "You don't have permissions to access this.",
|
||||||
"internal": "内部エラーが発生しました。",
|
"internal": "内部エラーが発生しました。",
|
||||||
"notFound": "リソースが見つかりませんでした。",
|
"notFound": "リソースが見つからなりませんでした。"
|
||||||
"connection": "サーバーに接続できませんでした。"
|
|
||||||
},
|
},
|
||||||
"files": {
|
"files": {
|
||||||
"body": "本文",
|
"body": "本文",
|
||||||
"clear": "消去",
|
"clear": "クリアー",
|
||||||
"closePreview": "プレビューを閉じる",
|
"closePreview": "プレビューを閉じる",
|
||||||
"files": "ファイル",
|
"files": "ファイル",
|
||||||
"folders": "フォルダー",
|
"folders": "フォルダ",
|
||||||
"home": "ホーム",
|
"home": "ホーム",
|
||||||
"lastModified": "更新日時",
|
"lastModified": "最終変更",
|
||||||
"loading": "読み込み中…",
|
"loading": "ローディング...",
|
||||||
"lonely": "ここには何もないようです…",
|
"lonely": "ここには何もない...",
|
||||||
"metadata": "メタデータ",
|
"metadata": "メタデータ",
|
||||||
"multipleSelectionEnabled": "複数選択が有効になっています",
|
"multipleSelectionEnabled": "複数選択有効",
|
||||||
"name": "名前",
|
"name": "名前",
|
||||||
"size": "サイズ",
|
"size": "サイズ",
|
||||||
"sortByLastModified": "更新日時で並べ替え",
|
"sortByLastModified": "最終変更日付によるソート",
|
||||||
"sortByName": "名前で並べ替え",
|
"sortByName": "名前によるソート",
|
||||||
"sortBySize": "サイズで並べ替え",
|
"sortBySize": "サイズによるソート"
|
||||||
"noPreview": "プレビューはこのファイルでは利用できません"
|
|
||||||
},
|
},
|
||||||
"help": {
|
"help": {
|
||||||
"click": "ファイルやフォルダーを選択",
|
"click": "ファイルやディレクトリを選択",
|
||||||
"ctrl": {
|
"ctrl": {
|
||||||
"click": "複数のファイルやフォルダーを選択",
|
"click": "複数のファイルやディレクトリを選択",
|
||||||
"f": "検索画面を開く",
|
"f": "検索を有効にする",
|
||||||
"s": "現在のフォルダーにあるファイルを保存またはダウンロード"
|
"s": "ファイルを保存またはカレントディレクトリをダウンロード"
|
||||||
},
|
},
|
||||||
"del": "選択した項目を削除",
|
"del": "選択した項目を削除",
|
||||||
"doubleClick": "ファイルやフォルダーを開く",
|
"doubleClick": "ファイルやディレクトリをオープン",
|
||||||
"esc": "選択を解除/ダイアログを閉じる",
|
"esc": "選択をクリアーまたはプロンプトを閉じる",
|
||||||
"f1": "ヘルプを表示",
|
"f1": "このヘルプを表示",
|
||||||
"f2": "ファイルの名前を変更",
|
"f2": "ファイルの名前を変更",
|
||||||
"help": "ヘルプ"
|
"help": "ヘルプ"
|
||||||
},
|
},
|
||||||
@ -92,193 +81,180 @@
|
|||||||
"hu": "Magyar",
|
"hu": "Magyar",
|
||||||
"ar": "العربية",
|
"ar": "العربية",
|
||||||
"de": "Deutsch",
|
"de": "Deutsch",
|
||||||
"el": "Ελληνικά",
|
|
||||||
"en": "English",
|
"en": "English",
|
||||||
"es": "Español",
|
"es": "Español",
|
||||||
"fr": "Français",
|
"fr": "Français",
|
||||||
"is": "Icelandic",
|
"is": "",
|
||||||
"it": "Italiano",
|
"it": "Italiano",
|
||||||
"ja": "日本語",
|
"ja": "日本語",
|
||||||
"ko": "한국어",
|
"ko": "한국어",
|
||||||
"nlBE": "Dutch (Belgium)",
|
"nlBE": "",
|
||||||
"pl": "Polski",
|
"pl": "Polski",
|
||||||
"pt": "Português",
|
"pt": "Português",
|
||||||
"ptBR": "Português (Brasil)",
|
"ptBR": "Português (Brasil)",
|
||||||
"ro": "Romanian",
|
"ro": "",
|
||||||
"ru": "Русский",
|
"ru": "Русский",
|
||||||
"sk": "Slovenčina",
|
"sk": "Slovenčina",
|
||||||
"svSE": "Swedish (Sweden)",
|
"svSE": "",
|
||||||
"tr": "Türkçe",
|
"tr" : "Türkçe",
|
||||||
"ua": "Українська",
|
"ua": "Українська",
|
||||||
"zhCN": "中文 (简体)",
|
"zhCN": "中文 (简体)",
|
||||||
"zhTW": "中文 (繁體)"
|
"zhTW": "中文 (繁體)"
|
||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"createAnAccount": "アカウントを作成",
|
"createAnAccount": "Create an account",
|
||||||
"loginInstead": "ログインする",
|
"loginInstead": "Already have an account",
|
||||||
"password": "パスワード",
|
"password": "パスワード",
|
||||||
"passwordConfirm": "パスワード(確認用)",
|
"passwordConfirm": "Password Confirmation",
|
||||||
"passwordsDontMatch": "パスワードが一致しません",
|
"passwordsDontMatch": "Passwords don't match",
|
||||||
"signup": "アカウント作成",
|
"signup": "Signup",
|
||||||
"submit": "ログイン",
|
"submit": "ログイン",
|
||||||
"username": "ユーザー名",
|
"username": "ユーザ名",
|
||||||
"usernameTaken": "ユーザー名はすでに取得されています",
|
"usernameTaken": "Username already taken",
|
||||||
"wrongCredentials": "ユーザー名またはパスワードが間違っています"
|
"wrongCredentials": "ユーザ名またはパスワードが間違っています。"
|
||||||
},
|
},
|
||||||
"permanent": "永久",
|
"permanent": "永久",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
"copy": "コピー",
|
"copy": "コピー",
|
||||||
"copyMessage": "ファイルをコピーする場所を選択してください:",
|
"copyMessage": "コピーの目標ディレクトリを選択してください:",
|
||||||
"currentlyNavigating": "現在閲覧しているディレクトリ:",
|
"currentlyNavigating": "現在閲覧しているディレクトリ:",
|
||||||
"deleteMessageMultiple": "{count} 個のファイルを削除してもよろしいですか?",
|
"deleteMessageMultiple": "{count} つのファイルを本当に削除してよろしいですか。",
|
||||||
"deleteMessageSingle": "このファイル/フォルダーを削除してもよろしいですか?",
|
"deleteMessageSingle": "このファイル/フォルダを本当に削除してよろしいですか。",
|
||||||
"deleteMessageShare": "共有中のファイル({path})を削除してもよろしいですか?",
|
"deleteTitle": "ファイルを削除",
|
||||||
"deleteTitle": "ファイルの削除",
|
"displayName": "名前:",
|
||||||
"displayName": "表示名:",
|
"download": "ファイルをダウンロード",
|
||||||
"download": "ファイルのダウンロード",
|
"downloadMessage": "圧縮形式を選択してください。",
|
||||||
"downloadMessage": "ダウンロードする際の圧縮形式を選んでください:",
|
"error": "あるエラーが発生しました。",
|
||||||
"error": "エラーが発生しました",
|
|
||||||
"fileInfo": "ファイル情報",
|
"fileInfo": "ファイル情報",
|
||||||
"filesSelected": "{count} 個のファイル/フォルダーが選択されています",
|
"filesSelected": "{count} つのファイルは選択されました。",
|
||||||
"lastModified": "更新日時",
|
"lastModified": "最終変更",
|
||||||
"move": "移動",
|
"move": "移動",
|
||||||
"moveMessage": "ファイル/フォルダーの新しいハウスを選択してください:",
|
"moveMessage": "移動の目標ディレクトリを選択してください:",
|
||||||
"newArchetype": "archetype に基づいて新しい投稿を作成します。ファイルは content フォルダーに作成されます。",
|
"newArchetype": "ある元型に基づいて新しいポストを作成します。ファイルは コンテンツフォルダに作成されます。",
|
||||||
"newDir": "新規フォルダー",
|
"newDir": "新しいディレクトリを作成",
|
||||||
"newDirMessage": "フォルダーの名前を入力してください:",
|
"newDirMessage": "新しいディレクトリの名前を入力してください。",
|
||||||
"newFile": "新規ファイル",
|
"newFile": "新しいファイルを作成",
|
||||||
"newFileMessage": "ファイルの名前を入力してください:",
|
"newFileMessage": "新しいファイルの名前を入力してください。",
|
||||||
"numberDirs": "ディレクトリの数",
|
"numberDirs": "ディレクトリ個数",
|
||||||
"numberFiles": "ファイルの数",
|
"numberFiles": "ファイル個数",
|
||||||
"rename": "名前変更",
|
"rename": "名前を変更",
|
||||||
"renameMessage": "変更後のファイルの名前を入力してください",
|
"renameMessage": "名前を変更しようファイルは:",
|
||||||
"replace": "ファイルの置き換え",
|
"replace": "置き換える",
|
||||||
"replaceMessage": "アップロードしようとしているファイルと既存のファイルの名前が重複しています。既存のものを置き換えずにアップロードを続けるか、既存のものを置き換えますか?\n",
|
"replaceMessage": "アップロードするファイルの中でかち合う名前が一つあります。 既存のファイルを置き換えりませんか。\n",
|
||||||
"schedule": "スケジュール",
|
"schedule": "スケジュール",
|
||||||
"scheduleMessage": "この投稿の公開予定日時を選んでください。",
|
"scheduleMessage": "このポストの発表日付をスケジュールしてください。",
|
||||||
"show": "表示",
|
"show": "表示",
|
||||||
"size": "サイズ",
|
"size": "サイズ",
|
||||||
"upload": "アップロード",
|
"upload": "",
|
||||||
"uploadFiles": "{files} 個のファイルをアップロードしています…",
|
"uploadMessage": ""
|
||||||
"uploadMessage": "アップロードするオプションを選択してください。",
|
|
||||||
"optionalPassword": "パスワード(オプション)"
|
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"images": "画像",
|
"images": "画像",
|
||||||
"music": "音楽",
|
"music": "音楽",
|
||||||
"pdf": "PDF",
|
"pdf": "PDF",
|
||||||
"pressToSearch": "エンターを押して検索します",
|
"pressToSearch": "Press enter to search...",
|
||||||
"search": "検索",
|
"search": "検索...",
|
||||||
"typeToSearch": "検索の種類",
|
"typeToSearch": "Type to search...",
|
||||||
"types": "ファイルの種類",
|
"types": "種類",
|
||||||
"video": "動画"
|
"video": "ビデオ"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"admin": "管理者",
|
"admin": "管理者",
|
||||||
"administrator": "管理者",
|
"administrator": "管理者",
|
||||||
"allowCommands": "コマンドの実行",
|
"allowCommands": "コマンドの実行",
|
||||||
"allowEdit": "ファイルやフォルダーの編集、名前の変更、削除",
|
"allowEdit": "ファイルやディレクトリの編集、名前変更と削除",
|
||||||
"allowNew": "ファイルやフォルダーの新規作成",
|
"allowNew": "ファイルとディレクトリの作成",
|
||||||
"allowPublish": "新しい投稿やページの公開",
|
"allowPublish": "ポストとぺーじの発表",
|
||||||
"allowSignup": "ユーザーの新規登録を許可",
|
"allowSignup": "Allow users to signup",
|
||||||
"avoidChanges": "(変更しない場合は空白のままにしてください)",
|
"avoidChanges": "(変更を避けるために空白にしてください)",
|
||||||
"branding": "ブランディング",
|
"branding": "Branding",
|
||||||
"brandingDirectoryPath": "ブランディングのディレクトリへのパス",
|
"brandingDirectoryPath": "Branding directory path",
|
||||||
"brandingHelp": "インスタンスの名前の変更、ロゴの変更、カスタムスタイルの追加、GitHub への外部リンクの無効化など、File Browser の見た目や使い勝手をカスタマイズすることができます。\nカスタムブランディングの詳細については、{0}をご覧ください。",
|
"brandingHelp": "You can customize how your File Browser instance looks and feels by changing its name, replacing the logo, adding custom styles and even disable external links to GitHub.\nFor more information about custom branding, please check out the {0}.",
|
||||||
"changePassword": "パスワードの変更",
|
"changePassword": "パスワードを変更",
|
||||||
"commandRunner": "コマンドランナー",
|
"commandRunner": "Command runner",
|
||||||
"commandRunnerHelp": "ここでは、指定したイベントの際に実行されるコマンドを設定することができます。1行に1つずつ書く必要があります。環境変数として {0} や {1} が使用可能で、{0} は {1} に関連した変数として扱われます。この機能と使用可能な環境変数の詳細については、{2}をお読みください。",
|
"commandRunnerHelp": "Here you can set commands that are executed in the named events. You must write one per line. The environment variables {0} and {1} will be available, being {0} relative to {1}. For more information about this feature and the available environment variables, please read the {2}.",
|
||||||
"commandsUpdated": "コマンドを更新しました!",
|
"commandsUpdated": "コマンドは更新されました!",
|
||||||
"createUserDir": "新規ユーザー追加時にユーザーのホームディレクトリを自動生成する",
|
"createUserDir": "Auto create user home dir while adding new user",
|
||||||
"tusUploads": "チャンクされたファイルアップロード",
|
"customStylesheet": "カスタムスタイルシ ート",
|
||||||
"tusUploadsHelp": "File Browser はチャンクされたファイルアップロードをサポートしており、信頼性の低いネットワーク上でも、効率的で信頼性の高い、再開可能なチャンクされたファイルアップロードを作成することができます。",
|
"defaultUserDescription": "This are the default settings for new users.",
|
||||||
"tusUploadsChunkSize": "1チャンクあたりのリクエストの最大サイズ。バイト数を示す整数か、10MB、1GBなどの文字列を入力できます。",
|
"disableExternalLinks": "Disable external links (except documentation)",
|
||||||
"tusUploadsRetryCount": "チャンクのアップロードに失敗した場合の再試行回数。",
|
"disableUsedDiskPercentage": "Disable used disk percentage graph",
|
||||||
"userHomeBasePath": "ユーザーのホームディレクトリのベースパス",
|
"documentation": "documentation",
|
||||||
"userScopeGenerationPlaceholder": "スコープは自動生成されます",
|
|
||||||
"createUserHomeDirectory": "ユーザーのホームディレクトリを作成する",
|
|
||||||
"customStylesheet": "カスタムスタイルシート",
|
|
||||||
"defaultUserDescription": "これらは新規ユーザーのデフォルト設定です。",
|
|
||||||
"disableExternalLinks": "外部リンクを無効にする(ドキュメントへのリンクを除く)",
|
|
||||||
"disableUsedDiskPercentage": "ディスク使用率のグラフを無効にする",
|
|
||||||
"documentation": "ドキュメント",
|
|
||||||
"examples": "例",
|
"examples": "例",
|
||||||
"executeOnShell": "シェルで実行する",
|
"executeOnShell": "Execute on shell",
|
||||||
"executeOnShellDescription": "デフォルトでは、File Browser はバイナリを直接呼び出してコマンドを実行します。代わりにシェル(Bash や PowerShell など)で実行したい場合は、必要な引数やフラグをここで指定します。値が指定されている場合、実行するコマンドが引数として追加されます。これは、ユーザーコマンドとイベントフックの両方に適用されます。",
|
"executeOnShellDescription": "By default, File Browser executes the commands by calling their binaries directly. If you want to run them on a shell instead (such as Bash or PowerShell), you can define it here with the required arguments and flags. If set, the command you execute will be appended as an argument. This apply to both user commands and event hooks.",
|
||||||
"globalRules": "これはグローバルな許可と不許可のルールセットです。これはすべてのユーザーに適用されます。ユーザーごとに特定のルールを設定することで、これらのルールを上書きすることができます。",
|
"globalRules": "This is a global set of allow and disallow rules. They apply to every user. You can define specific rules on each user's settings to override this ones.",
|
||||||
"globalSettings": "グローバル設定",
|
"globalSettings": "グローバル設定",
|
||||||
"hideDotfiles": "ドットで始まるファイルを表示しない",
|
"hideDotfiles": "",
|
||||||
"insertPath": "パスを入力してください",
|
"insertPath": "Insert the path",
|
||||||
"insertRegex": "正規表現を入力してください",
|
"insertRegex": "Insert regex expression",
|
||||||
"instanceName": "インスタンス名",
|
"instanceName": "Instance name",
|
||||||
"language": "言語",
|
"language": "言語",
|
||||||
"lockPassword": "ユーザーがパスワードを変更できないようにする",
|
"lockPassword": "新しいパスワードを変更に禁止",
|
||||||
"newPassword": "新しいパスワード",
|
"newPassword": "新しいパスワード",
|
||||||
"newPasswordConfirm": "新しいパスワード(再入力)",
|
"newPasswordConfirm": "新しいパスワードを確認します",
|
||||||
"newUser": "新規ユーザー作成",
|
"newUser": "新しいユーザー",
|
||||||
"password": "パスワード",
|
"password": "パスワード",
|
||||||
"passwordUpdated": "パスワードを更新しました!",
|
"passwordUpdated": "パスワードは更新されました!",
|
||||||
"path": "パス",
|
"path": "",
|
||||||
"perm": {
|
"perm": {
|
||||||
"create": "ファイルやフォルダーの作成",
|
"create": "Create files and directories",
|
||||||
"delete": "ファイルやフォルダーの削除",
|
"delete": "Delete files and directories",
|
||||||
"download": "ダウンロード",
|
"download": "Download",
|
||||||
"execute": "コマンドの実行",
|
"execute": "Execute commands",
|
||||||
"modify": "ファイルの編集",
|
"modify": "Edit files",
|
||||||
"rename": "ファイルやフォルダーの編集・移動",
|
"rename": "Rename or move files and directories",
|
||||||
"share": "ファイルの共有"
|
"share": "Share files"
|
||||||
},
|
},
|
||||||
"permissions": "権限",
|
"permissions": "権限",
|
||||||
"permissionsHelp": "ユーザーを管理者に設定するか、その他の権限を個別に選択することができます。「管理者」を選択すると、他のオプションはすべて自動的にチェックされます。ユーザーを管理するには管理者権限が必要です。\n",
|
"permissionsHelp": "あなたはユーザーを管理者に設定し、または権限を個々に設定しできます。\"管理者\"を選択する場合、その他のすべての選択肢は自動的に設定されます。ユーザーの管理は管理者の権限として保留されました。",
|
||||||
"profileSettings": "プロフィール設定",
|
"profileSettings": "プロファイル設定",
|
||||||
"ruleExample1": ".git や .gitignore のようなドットから始まるファイルへのアクセスを禁止します。\n",
|
"ruleExample1": "各フォルダに名前はドットで始まるファイル(例えば、.git、.gitignore)へのアクセスを制限します。",
|
||||||
"ruleExample2": "スコープのルートにある Caddyfile という名前のファイルへのアクセスを禁止します。",
|
"ruleExample2": "範囲のルートパスに名前は Caddyfile のファイルへのアクセスを制限します。",
|
||||||
"rules": "ルール",
|
"rules": "規則",
|
||||||
"rulesHelp": "ここでは、特定のユーザーに対して許可と不許可のルールを設定することができます。ブロックされたファイルはリストに表示されず、ユーザはアクセスできなくなります。正規表現とユーザースコープからの相対パスをサポートしています。\n",
|
"rulesHelp": "ここに、あなたはこのユーザーの許可または拒否規則を設定できます。ブロックされたファイルはリストに表示されません、それではアクセスも制限されます。正規表現(regex)のサポートと範囲に相対のパスが提供されています。",
|
||||||
"scope": "スコープ",
|
"scope": "範囲",
|
||||||
"setDateFormat": "正確な日時表記を使用する",
|
"settingsUpdated": "設定は更新されました!",
|
||||||
"settingsUpdated": "設定を更新しました!",
|
"shareDuration": "",
|
||||||
"shareDuration": "共有期間",
|
"shareManagement": "",
|
||||||
"shareManagement": "共有の管理",
|
"singleClick": "",
|
||||||
"shareDeleted": "ファイルの共有を削除しました!",
|
|
||||||
"singleClick": "ダブルクリックの代わりにクリックでファイルやフォルダーを開く",
|
|
||||||
"themes": {
|
"themes": {
|
||||||
"dark": "ダーク",
|
"dark": "",
|
||||||
"light": "ライト",
|
"light": "",
|
||||||
"title": "テーマ"
|
"title": ""
|
||||||
},
|
},
|
||||||
"user": "ユーザー",
|
"user": "ユーザー",
|
||||||
"userCommands": "コマンド",
|
"userCommands": "ユーザーのコマンド",
|
||||||
"userCommandsHelp": "このユーザーが使用可能なコマンドをスペースで区切ったリスト。例:\n",
|
"userCommandsHelp": "空白区切りの有効のコマンドのリストを指定してください。例:",
|
||||||
"userCreated": "ユーザーを作成しました!",
|
"userCreated": "ユーザーは作成されました!",
|
||||||
"userDefaults": "ユーザーのデフォルト設定",
|
"userDefaults": "User default settings",
|
||||||
"userDeleted": "ユーザーを削除しました!",
|
"userDeleted": "ユーザーは削除されました!",
|
||||||
"userManagement": "ユーザー管理",
|
"userManagement": "ユーザー管理",
|
||||||
"userUpdated": "ユーザーを更新しました!",
|
"userUpdated": "ユーザーは更新されました!",
|
||||||
"username": "ユーザー名",
|
"username": "ユーザー名",
|
||||||
"users": "ユーザー"
|
"users": "ユーザー"
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar": {
|
||||||
"help": "ヘルプ",
|
"help": "ヘルプ",
|
||||||
"hugoNew": "Hugo New",
|
"hugoNew": "Hugo New",
|
||||||
"login": "ログイン",
|
"login": "Login",
|
||||||
"logout": "ログアウト",
|
"logout": "ログアウト",
|
||||||
"myFiles": "マイファイル",
|
"myFiles": "私のファイル",
|
||||||
"newFile": "新規ファイル",
|
"newFile": "新しいファイルを作成",
|
||||||
"newFolder": "新規フォルダー",
|
"newFolder": "新しいフォルダを作成",
|
||||||
"preview": "プレビュー",
|
"preview": "プレビュー",
|
||||||
"settings": "設定",
|
"settings": "設定",
|
||||||
"signup": "サインアップ",
|
"signup": "Signup",
|
||||||
"siteSettings": "サイト設定"
|
"siteSettings": "サイト設定"
|
||||||
},
|
},
|
||||||
"success": {
|
"success": {
|
||||||
"linkCopied": "リンクをコピーしました!"
|
"linkCopied": "リンクがコピーされました!"
|
||||||
},
|
},
|
||||||
"time": {
|
"time": {
|
||||||
"days": "日",
|
"days": "日",
|
||||||
"hours": "時間",
|
"hours": "時間",
|
||||||
"minutes": "分",
|
"minutes": "分",
|
||||||
"seconds": "秒",
|
"seconds": "秒",
|
||||||
"unit": "時間の単位"
|
"unit": "時間単位"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import * as i18n from "@/i18n";
|
import * as i18n from "@/i18n";
|
||||||
import moment from "moment/min/moment-with-locales";
|
import moment from "moment";
|
||||||
|
|
||||||
const mutations = {
|
const mutations = {
|
||||||
closeHovers: (state) => {
|
closeHovers: (state) => {
|
||||||
|
|||||||
@ -183,7 +183,7 @@
|
|||||||
import { mapState, mapMutations, mapGetters } from "vuex";
|
import { mapState, mapMutations, mapGetters } from "vuex";
|
||||||
import { pub as api } from "@/api";
|
import { pub as api } from "@/api";
|
||||||
import { filesize } from "@/utils";
|
import { filesize } from "@/utils";
|
||||||
import moment from "moment/min/moment-with-locales";
|
import moment from "moment";
|
||||||
|
|
||||||
import HeaderBar from "@/components/header/HeaderBar.vue";
|
import HeaderBar from "@/components/header/HeaderBar.vue";
|
||||||
import Action from "@/components/header/Action.vue";
|
import Action from "@/components/header/Action.vue";
|
||||||
|
|||||||
@ -103,15 +103,13 @@ export default {
|
|||||||
if (theme == "dark") {
|
if (theme == "dark") {
|
||||||
this.editor.setTheme("ace/theme/twilight");
|
this.editor.setTheme("ace/theme/twilight");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.editor.focus();
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
back() {
|
||||||
|
let uri = url.removeLastDir(this.$route.path) + "/";
|
||||||
|
this.$router.push({ path: uri });
|
||||||
|
},
|
||||||
keyEvent(event) {
|
keyEvent(event) {
|
||||||
if (event.code === "Escape") {
|
|
||||||
this.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!event.ctrlKey && !event.metaKey) {
|
if (!event.ctrlKey && !event.metaKey) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -129,7 +127,6 @@ export default {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await api.put(this.$route.path, this.editor.getValue());
|
await api.put(this.$route.path, this.editor.getValue());
|
||||||
this.editor.session.getUndoManager().markClean();
|
|
||||||
buttons.success(button);
|
buttons.success(button);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
buttons.done(button);
|
buttons.done(button);
|
||||||
@ -137,11 +134,6 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
close() {
|
close() {
|
||||||
if (!this.editor.session.getUndoManager().isClean()) {
|
|
||||||
this.$store.commit("showHover", "discardEditorChanges");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$store.commit("updateRequest", {});
|
this.$store.commit("updateRequest", {});
|
||||||
|
|
||||||
let uri = url.removeLastDir(this.$route.path) + "/";
|
let uri = url.removeLastDir(this.$route.path) + "/";
|
||||||
|
|||||||
@ -63,7 +63,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { share as api, users } from "@/api";
|
import { share as api, users } from "@/api";
|
||||||
import { mapState, mapMutations } from "vuex";
|
import { mapState, mapMutations } from "vuex";
|
||||||
import moment from "moment/min/moment-with-locales";
|
import moment from "moment";
|
||||||
import Clipboard from "clipboard";
|
import Clipboard from "clipboard";
|
||||||
import Errors from "@/views/Errors.vue";
|
import Errors from "@/views/Errors.vue";
|
||||||
|
|
||||||
|
|||||||
2
go.mod
2
go.mod
@ -2,6 +2,8 @@ module github.com/filebrowser/filebrowser/v2
|
|||||||
|
|
||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
|
replace "github.com/filebrowser/filebrowser/v2/" v1.0.0 => .
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/asdine/storm/v3 v3.2.1
|
github.com/asdine/storm/v3 v3.2.1
|
||||||
github.com/disintegration/imaging v1.6.2
|
github.com/disintegration/imaging v1.6.2
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
PORT=${FB_PORT:-$(jq .port /.filebrowser.json)}
|
PORT=${FB_PORT:-$(jq .port /.filebrowser.json)}
|
||||||
ADDRESS=${FB_ADDRESS:-$(jq .address /.filebrowser.json)}
|
curl -f http://localhost:$PORT/health || exit 1
|
||||||
ADDRESS=${ADDRESS:-localhost}
|
|
||||||
curl -f http://$ADDRESS:$PORT/health || exit 1
|
|
||||||
|
|||||||
110
http/resource.go
110
http/resource.go
@ -11,34 +11,53 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/shirou/gopsutil/v3/disk"
|
|
||||||
"github.com/spf13/afero"
|
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/errors"
|
"github.com/filebrowser/filebrowser/v2/errors"
|
||||||
"github.com/filebrowser/filebrowser/v2/files"
|
"github.com/filebrowser/filebrowser/v2/files"
|
||||||
"github.com/filebrowser/filebrowser/v2/fileutils"
|
"github.com/filebrowser/filebrowser/v2/fileutils"
|
||||||
|
"github.com/shirou/gopsutil/v3/disk"
|
||||||
|
"github.com/spf13/afero"
|
||||||
)
|
)
|
||||||
|
|
||||||
var resourceGetHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
var resourceGetSizeHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
||||||
file, err := files.NewFileInfo(files.FileOptions{
|
folder, err := files.NewFileInfo(files.FileOptions{
|
||||||
Fs: d.user.Fs,
|
Fs: d.user.Fs,
|
||||||
Path: r.URL.Path,
|
Path: r.URL.Path,
|
||||||
Modify: d.user.Perm.Modify,
|
Modify: d.user.Perm.Modify,
|
||||||
Expand: true,
|
Expand: true,
|
||||||
ReadHeader: d.server.TypeDetectionByHeader,
|
FolderSize: true,
|
||||||
Checker: d,
|
ReadHeader: d.server.TypeDetectionByHeader,
|
||||||
Content: true,
|
Checker: d,
|
||||||
|
Content: true,
|
||||||
|
RootPath: d.server.Root,
|
||||||
|
AnotherPath: d.server.AnotherPath,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errToStatus(err), err
|
return errToStatus(err), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return renderJSON(w, r, folder)
|
||||||
|
})
|
||||||
|
|
||||||
|
var resourceGetHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
||||||
|
file, err := files.NewFileInfo(files.FileOptions{
|
||||||
|
Fs: d.user.Fs,
|
||||||
|
Path: r.URL.Path,
|
||||||
|
Modify: d.user.Perm.Modify,
|
||||||
|
Expand: true,
|
||||||
|
ReadHeader: d.server.TypeDetectionByHeader,
|
||||||
|
Checker: d,
|
||||||
|
Content: true,
|
||||||
|
RootPath: d.server.Root,
|
||||||
|
AnotherPath: d.server.AnotherPath,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return errToStatus(err), err
|
||||||
|
}
|
||||||
if file.IsDir {
|
if file.IsDir {
|
||||||
file.Listing.Sorting = d.user.Sorting
|
file.Listing.Sorting = d.user.Sorting
|
||||||
file.Listing.ApplySort()
|
file.Listing.ApplySort()
|
||||||
return renderJSON(w, r, file)
|
return renderJSON(w, r, file)
|
||||||
}
|
}
|
||||||
|
|
||||||
if checksum := r.URL.Query().Get("checksum"); checksum != "" {
|
if checksum := r.URL.Query().Get("checksum"); checksum != "" {
|
||||||
err := file.Checksum(checksum)
|
err := file.Checksum(checksum)
|
||||||
if err == errors.ErrInvalidOption {
|
if err == errors.ErrInvalidOption {
|
||||||
@ -50,7 +69,6 @@ var resourceGetHandler = withUser(func(w http.ResponseWriter, r *http.Request, d
|
|||||||
// do not waste bandwidth if we just want the checksum
|
// do not waste bandwidth if we just want the checksum
|
||||||
file.Content = ""
|
file.Content = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
return renderJSON(w, r, file)
|
return renderJSON(w, r, file)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -61,12 +79,14 @@ func resourceDeleteHandler(fileCache FileCache) handleFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
file, err := files.NewFileInfo(files.FileOptions{
|
file, err := files.NewFileInfo(files.FileOptions{
|
||||||
Fs: d.user.Fs,
|
Fs: d.user.Fs,
|
||||||
Path: r.URL.Path,
|
Path: r.URL.Path,
|
||||||
Modify: d.user.Perm.Modify,
|
Modify: d.user.Perm.Modify,
|
||||||
Expand: false,
|
Expand: false,
|
||||||
ReadHeader: d.server.TypeDetectionByHeader,
|
ReadHeader: d.server.TypeDetectionByHeader,
|
||||||
Checker: d,
|
Checker: d,
|
||||||
|
RootPath: d.server.Root,
|
||||||
|
AnotherPath: d.server.AnotherPath,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errToStatus(err), err
|
return errToStatus(err), err
|
||||||
@ -98,17 +118,19 @@ func resourcePostHandler(fileCache FileCache) handleFunc {
|
|||||||
|
|
||||||
// Directories creation on POST.
|
// Directories creation on POST.
|
||||||
if strings.HasSuffix(r.URL.Path, "/") {
|
if strings.HasSuffix(r.URL.Path, "/") {
|
||||||
err := d.user.Fs.MkdirAll(r.URL.Path, files.PermDir)
|
err := d.user.Fs.MkdirAll(r.URL.Path, 0775) //nolint:gomnd
|
||||||
return errToStatus(err), err
|
return errToStatus(err), err
|
||||||
}
|
}
|
||||||
|
|
||||||
file, err := files.NewFileInfo(files.FileOptions{
|
file, err := files.NewFileInfo(files.FileOptions{
|
||||||
Fs: d.user.Fs,
|
Fs: d.user.Fs,
|
||||||
Path: r.URL.Path,
|
Path: r.URL.Path,
|
||||||
Modify: d.user.Perm.Modify,
|
Modify: d.user.Perm.Modify,
|
||||||
Expand: false,
|
Expand: false,
|
||||||
ReadHeader: d.server.TypeDetectionByHeader,
|
ReadHeader: d.server.TypeDetectionByHeader,
|
||||||
Checker: d,
|
Checker: d,
|
||||||
|
RootPath: d.server.Root,
|
||||||
|
AnotherPath: d.server.AnotherPath,
|
||||||
})
|
})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if r.URL.Query().Get("override") != "true" {
|
if r.URL.Query().Get("override") != "true" {
|
||||||
@ -256,12 +278,12 @@ func addVersionSuffix(source string, fs afero.Fs) string {
|
|||||||
|
|
||||||
func writeFile(fs afero.Fs, dst string, in io.Reader) (os.FileInfo, error) {
|
func writeFile(fs afero.Fs, dst string, in io.Reader) (os.FileInfo, error) {
|
||||||
dir, _ := path.Split(dst)
|
dir, _ := path.Split(dst)
|
||||||
err := fs.MkdirAll(dir, files.PermDir)
|
err := fs.MkdirAll(dir, 0775) //nolint:gomnd
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
file, err := fs.OpenFile(dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, files.PermFile)
|
file, err := fs.OpenFile(dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0775) //nolint:gomnd
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -309,12 +331,14 @@ func patchAction(ctx context.Context, action, src, dst string, d *data, fileCach
|
|||||||
dst = path.Clean("/" + dst)
|
dst = path.Clean("/" + dst)
|
||||||
|
|
||||||
file, err := files.NewFileInfo(files.FileOptions{
|
file, err := files.NewFileInfo(files.FileOptions{
|
||||||
Fs: d.user.Fs,
|
Fs: d.user.Fs,
|
||||||
Path: src,
|
Path: src,
|
||||||
Modify: d.user.Perm.Modify,
|
Modify: d.user.Perm.Modify,
|
||||||
Expand: false,
|
Expand: false,
|
||||||
ReadHeader: false,
|
ReadHeader: false,
|
||||||
Checker: d,
|
Checker: d,
|
||||||
|
RootPath: d.server.Root,
|
||||||
|
AnotherPath: d.server.AnotherPath,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -339,13 +363,15 @@ type DiskUsageResponse struct {
|
|||||||
|
|
||||||
var diskUsage = withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
var diskUsage = withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
||||||
file, err := files.NewFileInfo(files.FileOptions{
|
file, err := files.NewFileInfo(files.FileOptions{
|
||||||
Fs: d.user.Fs,
|
Fs: d.user.Fs,
|
||||||
Path: r.URL.Path,
|
Path: r.URL.Path,
|
||||||
Modify: d.user.Perm.Modify,
|
Modify: d.user.Perm.Modify,
|
||||||
Expand: false,
|
Expand: false,
|
||||||
ReadHeader: false,
|
ReadHeader: false,
|
||||||
Checker: d,
|
Checker: d,
|
||||||
Content: false,
|
Content: false,
|
||||||
|
RootPath: d.server.Root,
|
||||||
|
AnotherPath: d.server.AnotherPath,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errToStatus(err), err
|
return errToStatus(err), err
|
||||||
|
|||||||
@ -37,6 +37,7 @@ func (s *Settings) GetRules() []rules.Rule {
|
|||||||
// Server specific settings.
|
// Server specific settings.
|
||||||
type Server struct {
|
type Server struct {
|
||||||
Root string `json:"root"`
|
Root string `json:"root"`
|
||||||
|
AnotherPath string `json:"anotherPath"`
|
||||||
BaseURL string `json:"baseURL"`
|
BaseURL string `json:"baseURL"`
|
||||||
Socket string `json:"socket"`
|
Socket string `json:"socket"`
|
||||||
TLSKey string `json:"tlsKey"`
|
TLSKey string `json:"tlsKey"`
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user