├── .gitattributes ├── .github └── workflows │ └── golangci-lint.yml ├── .gitignore ├── LICENSE ├── codecs └── elfinder_unmarshal.go ├── connection ├── command_info.go ├── command_ls.go ├── command_open.go ├── command_parents.go ├── command_rm.go ├── command_tree.go ├── command_upload.go ├── commands.go └── connector.go ├── elfinder.go ├── error.go ├── errs └── errors.go ├── example ├── elf │ ├── css │ │ ├── elfinder.full.css │ │ ├── elfinder.min.css │ │ └── theme.css │ ├── img │ │ ├── arrows-active.png │ │ ├── arrows-normal.png │ │ ├── crop.gif │ │ ├── dialogs.png │ │ ├── edit_aceeditor.png │ │ ├── edit_ckeditor.png │ │ ├── edit_ckeditor5.png │ │ ├── edit_codemirror.png │ │ ├── edit_creativecloud.png │ │ ├── edit_onlineconvert.png │ │ ├── edit_pixlreditor.png │ │ ├── edit_pixlrexpress.png │ │ ├── edit_simplemde.png │ │ ├── edit_tinymce.png │ │ ├── edit_tuiimgedit.png │ │ ├── edit_zohooffice.png │ │ ├── editor-icons.png │ │ ├── icons-big.png │ │ ├── icons-big.svg │ │ ├── icons-small.png │ │ ├── logo.png │ │ ├── progress.gif │ │ ├── quicklook-bg.png │ │ ├── quicklook-icons.png │ │ ├── resize.png │ │ ├── spinner-mini.gif │ │ ├── toolbar.png │ │ ├── trashmesh.png │ │ ├── tui-icon-a.svg │ │ ├── tui-icon-b.svg │ │ ├── tui-icon-c.svg │ │ ├── tui-icon-d.svg │ │ ├── ui-icons_ffffff_256x240.png │ │ ├── volume_icon_box.png │ │ ├── volume_icon_box.svg │ │ ├── volume_icon_dropbox.png │ │ ├── volume_icon_dropbox.svg │ │ ├── volume_icon_ftp.png │ │ ├── volume_icon_ftp.svg │ │ ├── volume_icon_googledrive.png │ │ ├── volume_icon_googledrive.svg │ │ ├── volume_icon_local.png │ │ ├── volume_icon_local.svg │ │ ├── volume_icon_network.png │ │ ├── volume_icon_network.svg │ │ ├── volume_icon_onedrive.png │ │ ├── volume_icon_onedrive.svg │ │ ├── volume_icon_sql.png │ │ ├── volume_icon_sql.svg │ │ ├── volume_icon_trash.png │ │ ├── volume_icon_trash.svg │ │ ├── volume_icon_zip.png │ │ └── volume_icon_zip.svg │ ├── index.html │ ├── jquery │ │ ├── images │ │ │ ├── animated-overlay.gif │ │ │ ├── ui-bg_flat_0_aaaaaa_40x100.png │ │ │ ├── ui-bg_flat_75_ffffff_40x100.png │ │ │ ├── ui-bg_glass_55_fbf9ee_1x400.png │ │ │ ├── ui-bg_glass_65_ffffff_1x400.png │ │ │ ├── ui-bg_glass_75_dadada_1x400.png │ │ │ ├── ui-bg_glass_75_e6e6e6_1x400.png │ │ │ ├── ui-bg_glass_95_fef1ec_1x400.png │ │ │ ├── ui-bg_highlight-soft_75_cccccc_1x100.png │ │ │ ├── ui-icons_222222_256x240.png │ │ │ ├── ui-icons_2e83ff_256x240.png │ │ │ ├── ui-icons_444444_256x240.png │ │ │ ├── ui-icons_454545_256x240.png │ │ │ ├── ui-icons_555555_256x240.png │ │ │ ├── ui-icons_777620_256x240.png │ │ │ ├── ui-icons_777777_256x240.png │ │ │ ├── ui-icons_888888_256x240.png │ │ │ ├── ui-icons_cc0000_256x240.png │ │ │ ├── ui-icons_cd0a0a_256x240.png │ │ │ └── ui-icons_ffffff_256x240.png │ │ ├── jquery-2.1.1.js │ │ ├── jquery-3.3.1.js │ │ ├── jquery-ui-1.12.1.js │ │ └── jquery-ui.css │ ├── js │ │ ├── elfinder.full.js │ │ ├── elfinder.min.js │ │ ├── extras │ │ │ ├── editors.default.js │ │ │ ├── editors.default.min.js │ │ │ ├── quicklook.googledocs.js │ │ │ └── quicklook.googledocs.min.js │ │ ├── i18n │ │ │ ├── elfinder.LANG.js │ │ │ ├── elfinder.ar.js │ │ │ ├── elfinder.bg.js │ │ │ ├── elfinder.ca.js │ │ │ ├── elfinder.cs.js │ │ │ ├── elfinder.da.js │ │ │ ├── elfinder.de.js │ │ │ ├── elfinder.el.js │ │ │ ├── elfinder.es.js │ │ │ ├── elfinder.fa.js │ │ │ ├── elfinder.fallback.js │ │ │ ├── elfinder.fo.js │ │ │ ├── elfinder.fr.js │ │ │ ├── elfinder.he.js │ │ │ ├── elfinder.hr.js │ │ │ ├── elfinder.hu.js │ │ │ ├── elfinder.id.js │ │ │ ├── elfinder.it.js │ │ │ ├── elfinder.ja.js │ │ │ ├── elfinder.jp.js │ │ │ ├── elfinder.ko.js │ │ │ ├── elfinder.nl.js │ │ │ ├── elfinder.no.js │ │ │ ├── elfinder.pl.js │ │ │ ├── elfinder.pt_BR.js │ │ │ ├── elfinder.ro.js │ │ │ ├── elfinder.ru.js │ │ │ ├── elfinder.si.js │ │ │ ├── elfinder.sk.js │ │ │ ├── elfinder.sl.js │ │ │ ├── elfinder.sr.js │ │ │ ├── elfinder.sv.js │ │ │ ├── elfinder.tr.js │ │ │ ├── elfinder.ug_CN.js │ │ │ ├── elfinder.uk.js │ │ │ ├── elfinder.vi.js │ │ │ ├── elfinder.zh_CN.js │ │ │ ├── elfinder.zh_TW.js │ │ │ └── help │ │ │ │ ├── cs.html.js │ │ │ │ ├── en.html.js │ │ │ │ ├── es.html.js │ │ │ │ ├── ja.html.js │ │ │ │ ├── ko.html.js │ │ │ │ ├── pl.html.js │ │ │ │ ├── ru.html.js │ │ │ │ └── sk.html.js │ │ └── proxy │ │ │ └── elFinderSupportVer1.js │ └── sounds │ │ └── rm.wav └── main.go ├── go.mod ├── go.sum ├── http_header.go ├── log └── log.go ├── model ├── file_info.go └── options.go ├── request.go ├── response.go ├── utils └── util.go ├── volume.go ├── volumes └── fs_volume.go └── zipfilemanager.go /.gitattributes: -------------------------------------------------------------------------------- 1 | *.html linguist-detectable=false 2 | *.JavaScript linguist-detectable=false 3 | *.javascript linguist-detectable=false 4 | *.js linguist-detectable=false 5 | *.css linguist-detectable=false -------------------------------------------------------------------------------- /.github/workflows/golangci-lint.yml: -------------------------------------------------------------------------------- 1 | name: golangci-lint 2 | on: 3 | push: 4 | tags: 5 | - v* 6 | branches: 7 | - 'master' 8 | pull_request: 9 | permissions: 10 | contents: read 11 | # Optional: allow read access to pull request. Use with `only-new-issues` option. 12 | # pull-requests: read 13 | jobs: 14 | golangci: 15 | name: lint 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: golangci-lint 20 | uses: golangci/golangci-lint-action@v2 21 | with: 22 | # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version 23 | version: v1.29 24 | 25 | # Optional: working directory, useful for monorepos 26 | # working-directory: somedir 27 | 28 | # Optional: golangci-lint command line arguments. 29 | # args: --issues-exit-code=0 30 | 31 | # Optional: show only new issues if it's a pull request. The default value is `false`. 32 | # only-new-issues: true 33 | 34 | # Optional: if set to true then the action will use pre-installed Go. 35 | # skip-go-installation: true 36 | 37 | # Optional: if set to true then the action don't cache or restore ~/go/pkg. 38 | # skip-pkg-cache: true 39 | 40 | # Optional: if set to true then the action don't cache or restore ~/.cache/go-build. 41 | # skip-build-cache: true -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, build with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | .idea/ 14 | .vscode/ -------------------------------------------------------------------------------- /codecs/elfinder_unmarshal.go: -------------------------------------------------------------------------------- 1 | package codecs 2 | 3 | import ( 4 | "encoding" 5 | "errors" 6 | "reflect" 7 | "strconv" 8 | "strings" 9 | ) 10 | 11 | /* 12 | copy from https://github.com/labstack/echo/blob/902c55355238a226c356d5e6c706a62c76f64197/bind.go#L26 13 | */ 14 | 15 | const tagName = "elfinder" 16 | 17 | func UnmarshalElfinderTag(destination interface{}, data map[string][]string) error { 18 | 19 | if destination == nil || len(data) == 0 { 20 | return nil 21 | } 22 | typ := reflect.TypeOf(destination).Elem() 23 | val := reflect.ValueOf(destination).Elem() 24 | 25 | // Map 26 | if typ.Kind() == reflect.Map { 27 | for k, v := range data { 28 | val.SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(v[0])) 29 | } 30 | return nil 31 | } 32 | 33 | // !struct 34 | if typ.Kind() != reflect.Struct { 35 | return errors.New("binding element must be a struct") 36 | } 37 | 38 | for i := 0; i < typ.NumField(); i++ { 39 | typeField := typ.Field(i) 40 | structField := val.Field(i) 41 | if typeField.Anonymous { 42 | if structField.Kind() == reflect.Ptr { 43 | structField = structField.Elem() 44 | } 45 | } 46 | if !structField.CanSet() { 47 | continue 48 | } 49 | structFieldKind := structField.Kind() 50 | inputFieldName := typeField.Tag.Get(tagName) 51 | if typeField.Anonymous && structField.Kind() == reflect.Struct && inputFieldName != "" { 52 | // if anonymous struct with query/param/form tags, report an error 53 | return errors.New("query/param/form tags are not allowed with anonymous struct field") 54 | } 55 | inputValue, exists := data[inputFieldName] 56 | if !exists { 57 | // Go json.Unmarshal supports case insensitive binding. However the 58 | // url params are bound case sensitive which is inconsistent. To 59 | // fix this we must check all of the map values in a 60 | // case-insensitive search. 61 | for k, v := range data { 62 | if strings.EqualFold(k, inputFieldName) { 63 | inputValue = v 64 | exists = true 65 | break 66 | } 67 | } 68 | } 69 | 70 | if !exists { 71 | continue 72 | } 73 | 74 | // Call this first, in case we're dealing with an alias to an array type 75 | if ok, err := unmarshalField(typeField.Type.Kind(), inputValue[0], structField); ok { 76 | if err != nil { 77 | return err 78 | } 79 | continue 80 | } 81 | 82 | numElems := len(inputValue) 83 | if structFieldKind == reflect.Slice && numElems > 0 { 84 | sliceOf := structField.Type().Elem().Kind() 85 | slice := reflect.MakeSlice(structField.Type(), numElems, numElems) 86 | for j := 0; j < numElems; j++ { 87 | if err := setWithProperType(sliceOf, inputValue[j], slice.Index(j)); err != nil { 88 | return err 89 | } 90 | } 91 | val.Field(i).Set(slice) 92 | } else if err := setWithProperType(typeField.Type.Kind(), inputValue[0], structField); err != nil { 93 | return err 94 | 95 | } 96 | } 97 | return nil 98 | } 99 | 100 | func unmarshalField(valueKind reflect.Kind, val string, field reflect.Value) (bool, error) { 101 | switch valueKind { 102 | case reflect.Ptr: 103 | return unmarshalFieldPtr(val, field) 104 | default: 105 | return unmarshalFieldNonPtr(val, field) 106 | } 107 | } 108 | 109 | func unmarshalFieldNonPtr(value string, field reflect.Value) (bool, error) { 110 | fieldIValue := field.Addr().Interface() 111 | 112 | if unmarshaler, ok := fieldIValue.(encoding.TextUnmarshaler); ok { 113 | return true, unmarshaler.UnmarshalText([]byte(value)) 114 | } 115 | 116 | return false, nil 117 | } 118 | 119 | func unmarshalFieldPtr(value string, field reflect.Value) (bool, error) { 120 | if field.IsNil() { 121 | // Initialize the pointer to a nil value 122 | field.Set(reflect.New(field.Type().Elem())) 123 | } 124 | return unmarshalFieldNonPtr(value, field.Elem()) 125 | } 126 | 127 | func setWithProperType(valueKind reflect.Kind, val string, structField reflect.Value) error { 128 | // But also call it here, in case we're dealing with an array of BindUnmarshalers 129 | if ok, err := unmarshalField(valueKind, val, structField); ok { 130 | return err 131 | } 132 | 133 | switch valueKind { 134 | case reflect.Ptr: 135 | return setWithProperType(structField.Elem().Kind(), val, structField.Elem()) 136 | case reflect.Int: 137 | return setIntField(val, 0, structField) 138 | case reflect.Int8: 139 | return setIntField(val, 8, structField) 140 | case reflect.Int16: 141 | return setIntField(val, 16, structField) 142 | case reflect.Int32: 143 | return setIntField(val, 32, structField) 144 | case reflect.Int64: 145 | return setIntField(val, 64, structField) 146 | case reflect.Uint: 147 | return setUintField(val, 0, structField) 148 | case reflect.Uint8: 149 | return setUintField(val, 8, structField) 150 | case reflect.Uint16: 151 | return setUintField(val, 16, structField) 152 | case reflect.Uint32: 153 | return setUintField(val, 32, structField) 154 | case reflect.Uint64: 155 | return setUintField(val, 64, structField) 156 | case reflect.Bool: 157 | return setBoolField(val, structField) 158 | case reflect.Float32: 159 | return setFloatField(val, 32, structField) 160 | case reflect.Float64: 161 | return setFloatField(val, 64, structField) 162 | case reflect.String: 163 | structField.SetString(val) 164 | default: 165 | return errors.New("unknown type") 166 | } 167 | return nil 168 | } 169 | 170 | func setIntField(value string, bitSize int, field reflect.Value) error { 171 | if value == "" { 172 | value = "0" 173 | } 174 | intVal, err := strconv.ParseInt(value, 10, bitSize) 175 | if err == nil { 176 | field.SetInt(intVal) 177 | } 178 | return err 179 | } 180 | 181 | func setUintField(value string, bitSize int, field reflect.Value) error { 182 | if value == "" { 183 | value = "0" 184 | } 185 | uintVal, err := strconv.ParseUint(value, 10, bitSize) 186 | if err == nil { 187 | field.SetUint(uintVal) 188 | } 189 | return err 190 | } 191 | 192 | func setBoolField(value string, field reflect.Value) error { 193 | if value == "" { 194 | value = "false" 195 | } 196 | boolVal, err := strconv.ParseBool(value) 197 | if err == nil { 198 | field.SetBool(boolVal) 199 | } 200 | return err 201 | } 202 | 203 | func setFloatField(value string, bitSize int, field reflect.Value) error { 204 | if value == "" { 205 | value = "0.0" 206 | } 207 | floatVal, err := strconv.ParseFloat(value, bitSize) 208 | if err == nil { 209 | field.SetFloat(floatVal) 210 | } 211 | return err 212 | } 213 | -------------------------------------------------------------------------------- /connection/command_info.go: -------------------------------------------------------------------------------- 1 | package connection 2 | 3 | import ( 4 | "github.com/LeeEirc/elfinder/model" 5 | ) 6 | 7 | type InfoResponse struct { 8 | Files []model.FileInfo `json:"files"` 9 | } 10 | 11 | //func InfoCommand(connection *Connector, req *http.Request, rw http.ResponseWriter) { 12 | // targets := req.Form["targets[]"] 13 | // var resp InfoResponse 14 | // for _, target := range targets { 15 | // id, path, errs := connection.parseTarget(target) 16 | // if errs != nil { 17 | // log.Print(errs) 18 | // if errs != nil { 19 | // if jsonErr := SendJson(rw, NewErr(errs)); jsonErr != nil { 20 | // log.Print(jsonErr) 21 | // } 22 | // return 23 | // } 24 | // } 25 | // if vol := connection.Vols[id]; vol != nil { 26 | // dirs, err2 := volumes.ReadDir(vol, path) 27 | // if err2 != nil { 28 | // log.Print(err2) 29 | // if jsonErr := SendJson(rw, NewErr(err2)); jsonErr != nil { 30 | // log.Print(jsonErr) 31 | // } 32 | // return 33 | // } 34 | // 35 | // for i := range dirs { 36 | // info, errs := dirs[i].Info() 37 | // if errs != nil { 38 | // log.Print(err2) 39 | // if jsonErr := SendJson(rw, NewErr(err2)); jsonErr != nil { 40 | // log.Print(jsonErr) 41 | // } 42 | // return 43 | // } 44 | // subpath := filepath.Join(path, info.Name()) 45 | // cwd, errs := CreateFileInfo(id, vol, subpath, info) 46 | // if errs != nil { 47 | // log.Print(errs) 48 | // if jsonErr := SendJson(rw, NewErr(errs)); jsonErr != nil { 49 | // log.Print(jsonErr) 50 | // } 51 | // return 52 | // } 53 | // resp.Files = append(resp.Files, cwd) 54 | // 55 | // } 56 | // 57 | // } 58 | // } 59 | // if jsonErr := SendJson(rw, &resp); jsonErr != nil { 60 | // log.Print(jsonErr) 61 | // } 62 | // return 63 | // 64 | //} 65 | 66 | //func CreateFileInfo(id string, vol FsVolume, path string, fsInfo volumes.FileInfo) (FileInfo, error) { 67 | // var ( 68 | // pathHash string 69 | // parentHash string 70 | // MimeType string 71 | // HasDirs int 72 | // isRoot int 73 | // ) 74 | // parentPath := filepath.Dir(path) 75 | // pathHash = EncodeTarget(id, path) 76 | // if path != "" && path != "/" { 77 | // parentHash = EncodeTarget(id, parentPath) 78 | // } else { 79 | // isRoot = 1 80 | // } 81 | // MimeType = "file" 82 | // if fsInfo.IsDir() { 83 | // MimeType = "directory" 84 | // dirItems, err2 := volumes.ReadDir(vol, path) 85 | // if err2 != nil { 86 | // return FileInfo{}, err2 87 | // } 88 | // for i := range dirItems { 89 | // if dirItems[i].IsDir() { 90 | // HasDirs = 1 91 | // break 92 | // } 93 | // } 94 | // } 95 | // return FileInfo{ 96 | // Name: fsInfo.Name(), 97 | // PathHash: pathHash, 98 | // ParentHash: parentHash, 99 | // MimeType: MimeType, 100 | // Timestamp: fsInfo.ModTime().Unix(), 101 | // Size: fsInfo.Size(), 102 | // HasDirs: HasDirs, 103 | // ReadAble: 1, 104 | // WriteAble: 1, 105 | // Locked: 0, 106 | // Volumeid: id + "_", 107 | // Isroot: isRoot, 108 | // }, nil 109 | //} 110 | -------------------------------------------------------------------------------- /connection/command_ls.go: -------------------------------------------------------------------------------- 1 | package connection 2 | 3 | import ( 4 | "fmt" 5 | "github.com/LeeEirc/elfinder/codecs" 6 | "github.com/LeeEirc/elfinder/errs" 7 | "github.com/LeeEirc/elfinder/volumes" 8 | "net/http" 9 | ) 10 | 11 | type LsRequest struct { 12 | Target string `elfinder:"target"` 13 | Intersects []string `elfinder:"intersect[]"` 14 | } 15 | 16 | type LsResponse struct { 17 | List map[string]string `json:"list"` 18 | } 19 | 20 | func LsCommand(connector *Connector, req *http.Request, rw http.ResponseWriter) { 21 | var ( 22 | lsReq LsRequest 23 | res LsResponse 24 | ) 25 | 26 | if err := codecs.UnmarshalElfinderTag(&lsReq, req.URL.Query()); err != nil { 27 | connector.Logger.Error(err) 28 | return 29 | } 30 | var ( 31 | id string 32 | path string 33 | err error 34 | vol volumes.FsVolume 35 | ) 36 | vol = connector.DefaultVol 37 | id = connector.GetVolId(connector.DefaultVol) 38 | path = fmt.Sprintf("/%s", vol.Name()) 39 | 40 | if lsReq.Target != "" { 41 | id, path, err = connector.ParseTarget(lsReq.Target) 42 | if err != nil { 43 | connector.Logger.Errorf("parse target %s errs: %s", lsReq.Target, err) 44 | if jsonErr := SendJson(rw, NewErr(errs.ERRCmdParams, err)); jsonErr != nil { 45 | connector.Logger.Errorf("send response json errs: %s", err) 46 | } 47 | return 48 | } 49 | vol = connector.GetFsById(id) 50 | } 51 | if vol == nil { 52 | connector.Logger.Errorf("not found vol by id: %s", id) 53 | if jsonErr := SendJson(rw, NewErr(errs.ERRCmdParams, ErrNoFoundVol)); jsonErr != nil { 54 | connector.Logger.Errorf("send response json errs: %s", err) 55 | } 56 | return 57 | } 58 | 59 | resFiles, err := ReadFsVolDir(id, vol, path) 60 | if err != nil { 61 | if jsonErr := SendJson(rw, NewErr(errs.ERROpen, err)); jsonErr != nil { 62 | connector.Logger.Error(jsonErr) 63 | } 64 | return 65 | } 66 | if len(resFiles) > 0 { 67 | items := make(map[string]string, len(resFiles)) 68 | res.List = make(map[string]string, len(resFiles)) 69 | for i := range resFiles { 70 | items[resFiles[i].Name] = resFiles[i].PathHash 71 | } 72 | for i := range lsReq.Intersects { 73 | name := lsReq.Intersects[i] 74 | if hashPath, ok := items[name]; ok { 75 | res.List[hashPath] = name 76 | } 77 | } 78 | } 79 | 80 | if err = SendJson(rw, res); err != nil { 81 | connector.Logger.Errorf("send response json errs: %s", err) 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /connection/command_open.go: -------------------------------------------------------------------------------- 1 | package connection 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | 7 | "github.com/LeeEirc/elfinder" 8 | "github.com/LeeEirc/elfinder/codecs" 9 | "github.com/LeeEirc/elfinder/errs" 10 | "github.com/LeeEirc/elfinder/model" 11 | "github.com/LeeEirc/elfinder/volumes" 12 | ) 13 | 14 | type OpenRequest struct { 15 | Init bool `elfinder:"init"` // (true|false|not set) 16 | Target string `elfinder:"target"` 17 | Tree bool `elfinder:"tree"` 18 | } 19 | 20 | type OpenResponse struct { 21 | Api float32 `json:"api,omitempty"` 22 | Cwd model.FileInfo `json:"cwd"` 23 | Files []model.FileInfo `json:"files,omitempty"` 24 | NetDrivers []string `json:"netDrivers,omitempty"` 25 | UplMaxFile int `json:"uplMaxFile"` 26 | UplMaxSize string `json:"uplMaxSize"` // "32M" 27 | Options model.Option `json:"options,omitempty"` // Further information about the folder and its volume 28 | Debug *model.DebugOption `json:"debug,omitempty"` // Debug information, if you specify the corresponding connection option. 29 | } 30 | 31 | func OpenCommand(connector *Connector, req *http.Request, rw http.ResponseWriter) { 32 | var ( 33 | param OpenRequest 34 | res OpenResponse 35 | ) 36 | 37 | if err := codecs.UnmarshalElfinderTag(¶m, req.URL.Query()); err != nil { 38 | connector.Logger.Error(err) 39 | return 40 | } 41 | res.UplMaxSize = "32M" 42 | var ( 43 | id string 44 | path string 45 | err error 46 | vol volumes.FsVolume 47 | ) 48 | vol = connector.DefaultVol 49 | id = connector.GetVolId(connector.DefaultVol) 50 | path = fmt.Sprintf("/%s", vol.Name()) 51 | if param.Target != "" { 52 | id, path, err = connector.ParseTarget(param.Target) 53 | if err != nil { 54 | connector.Logger.Errorf("parse target %s errs: %s", param.Target, err) 55 | if jsonErr := SendJson(rw, NewErr(errs.ERROpen, err)); jsonErr != nil { 56 | connector.Logger.Errorf("send response json errs: %s", err) 57 | } 58 | return 59 | } 60 | vol = connector.GetFsById(id) 61 | } 62 | if vol == nil { 63 | connector.Logger.Errorf("not found vol by id: %s", id) 64 | if err = SendJson(rw, NewErr(errs.ERROpen, ErrNoFoundVol)); err != nil { 65 | connector.Logger.Errorf("send response json errs: %s", err) 66 | } 67 | return 68 | } 69 | 70 | cwd, err2 := StatFsVolFileByPath(id, vol, path) 71 | if err2 != nil { 72 | if jsonErr := SendJson(rw, NewErr(errs.ERROpen, err2)); jsonErr != nil { 73 | connector.Logger.Error(jsonErr) 74 | } 75 | return 76 | } 77 | res.Cwd = cwd 78 | resFiles, err := ReadFsVolDir(id, vol, path) 79 | if err != nil { 80 | if jsonErr := SendJson(rw, NewErr(errs.ERROpen, err)); jsonErr != nil { 81 | connector.Logger.Error(jsonErr) 82 | } 83 | return 84 | } 85 | res.Files = append(res.Files, cwd) 86 | res.Files = append(res.Files, resFiles...) 87 | 88 | if param.Tree { 89 | for vid := range connector.Vols { 90 | if connector.Vols[vid].Name() != vol.Name() { 91 | vItem, err3 := StatFsVolFileByPath(vid, connector.Vols[vid], fmt.Sprintf("/%s", vol.Name())) 92 | if err3 != nil { 93 | connector.Logger.Error(err3) 94 | if jsonErr := SendJson(rw, NewErr(errs.ERROpen, err3)); jsonErr != nil { 95 | connector.Logger.Error(jsonErr) 96 | } 97 | return 98 | } 99 | res.Files = append(res.Files, vItem) 100 | 101 | } 102 | } 103 | } 104 | if param.Init { 105 | res.Api = elfinder.APIVERSION 106 | opt := model.NewDefaultOption() 107 | opt.Path = res.Cwd.Name 108 | res.Options = opt 109 | res.Cwd.Options = &opt 110 | } 111 | if err := SendJson(rw, &res); err != nil { 112 | connector.Logger.Error(err) 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /connection/command_parents.go: -------------------------------------------------------------------------------- 1 | package connection 2 | 3 | import ( 4 | "github.com/LeeEirc/elfinder/codecs" 5 | "github.com/LeeEirc/elfinder/errs" 6 | "github.com/LeeEirc/elfinder/model" 7 | "net/http" 8 | "path/filepath" 9 | ) 10 | 11 | type ParentsResponse struct { 12 | Tree []model.FileInfo `json:"tree"` 13 | } 14 | 15 | type ParentsRequest struct { 16 | Target string `elfinder:"target"` 17 | } 18 | 19 | func ParentsCommand(connector *Connector, req *http.Request, rw http.ResponseWriter) { 20 | var ( 21 | param ParentsRequest 22 | res ParentsResponse 23 | ) 24 | 25 | err := codecs.UnmarshalElfinderTag(¶m, req.URL.Query()) 26 | if err != nil { 27 | connector.Logger.Error(err) 28 | if jsonErr := SendJson(rw, NewErr(errs.ERRCmdReq, err)); jsonErr != nil { 29 | connector.Logger.Error(jsonErr) 30 | } 31 | return 32 | } 33 | target := param.Target 34 | id, path, err := connector.ParseTarget(target) 35 | if err != nil { 36 | connector.Logger.Error(err) 37 | if jsonErr := SendJson(rw, NewErr(errs.ERRCmdReq, err)); jsonErr != nil { 38 | connector.Logger.Error(jsonErr) 39 | } 40 | return 41 | } 42 | vol := connector.Vols[id] 43 | cwdInfo, err := StatFsVolFileByPath(id, vol, path) 44 | if err != nil { 45 | connector.Logger.Error(err) 46 | return 47 | } 48 | res.Tree = append(res.Tree, cwdInfo) 49 | for { 50 | path = filepath.Dir(path) 51 | if path == "/" { 52 | break 53 | } 54 | cwdInfo, err = StatFsVolFileByPath(id, vol, path) 55 | if err != nil { 56 | connector.Logger.Error(err) 57 | return 58 | } 59 | res.Tree = append(res.Tree, cwdInfo) 60 | 61 | cwdDirs, err := ReadFsVolDir(id, vol, path) 62 | if err != nil { 63 | connector.Logger.Error(err) 64 | return 65 | } 66 | res.Tree = append(res.Tree, cwdDirs...) 67 | } 68 | 69 | if err := SendJson(rw, &res); err != nil { 70 | connector.Logger.Error(err) 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /connection/command_rm.go: -------------------------------------------------------------------------------- 1 | package connection 2 | 3 | import ( 4 | "fmt" 5 | "github.com/LeeEirc/elfinder/codecs" 6 | "github.com/LeeEirc/elfinder/errs" 7 | "net/http" 8 | "strings" 9 | ) 10 | 11 | type RmRequest struct { 12 | ReqId string `elfinder:"reqid"` 13 | Targets []string `elfinder:"targets[]"` 14 | } 15 | 16 | type RmResponse struct { 17 | Removed []string `json:"removed"` 18 | } 19 | 20 | func RmCommand(connector *Connector, req *http.Request, rw http.ResponseWriter) { 21 | var ( 22 | cmdReq RmRequest 23 | cmdResponse RmResponse 24 | ) 25 | err := codecs.UnmarshalElfinderTag(&cmdReq, req.URL.Query()) 26 | if err != nil { 27 | connector.Logger.Error(err) 28 | if jsonErr := SendJson(rw, NewErr(errs.ERRCmdReq, err)); jsonErr != nil { 29 | connector.Logger.Error(jsonErr) 30 | } 31 | return 32 | } 33 | for i := range cmdReq.Targets { 34 | target := cmdReq.Targets[i] 35 | id, path, err := connector.ParseTarget(target) 36 | if err != nil { 37 | connector.Logger.Error(err) 38 | if jsonErr := SendJson(rw, NewErr(errs.ERRCmdReq, err)); jsonErr != nil { 39 | connector.Logger.Error(jsonErr) 40 | } 41 | return 42 | } 43 | vol, ok := connector.Vols[id] 44 | if !ok { 45 | connector.Logger.Errorf("not found vol by id: %s", id) 46 | if err = SendJson(rw, NewErr(errs.ERROpen, ErrNoFoundVol)); err != nil { 47 | connector.Logger.Errorf("send response json errs: %s", err) 48 | } 49 | return 50 | } 51 | cwdInfo, err := StatFsVolFileByPath(id, vol, path) 52 | if err != nil { 53 | connector.Logger.Error(err) 54 | return 55 | } 56 | relativePath := strings.TrimPrefix(path, fmt.Sprintf("/%s/", vol.Name())) 57 | if err := vol.Remove(relativePath); err != nil { 58 | connector.Logger.Error(err) 59 | if jsonErr := SendJson(rw, NewErr(errs.ERRRm, err)); jsonErr != nil { 60 | connector.Logger.Error(jsonErr) 61 | } 62 | return 63 | } 64 | cmdResponse.Removed = append(cmdResponse.Removed, cwdInfo.PathHash) 65 | } 66 | if err := SendJson(rw, &cmdResponse); err != nil { 67 | connector.Logger.Error(err) 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /connection/command_tree.go: -------------------------------------------------------------------------------- 1 | package connection 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | 8 | "github.com/LeeEirc/elfinder/codecs" 9 | "github.com/LeeEirc/elfinder/errs" 10 | ) 11 | 12 | type TreeRequest struct { 13 | Target string `elfinder:"target"` 14 | ReqId string `elfinder:"reqid"` 15 | } 16 | 17 | func TreeCommand(connector *Connector, req *http.Request, rw http.ResponseWriter) { 18 | var param TreeRequest 19 | 20 | if err := codecs.UnmarshalElfinderTag(¶m, req.URL.Query()); err != nil { 21 | log.Print(err) 22 | return 23 | } 24 | id, path, err := connector.ParseTarget(param.Target) 25 | if err != nil { 26 | log.Print(err) 27 | if jsonErr := SendJson(rw, NewErr(errs.ERRCmdParams, err)); jsonErr != nil { 28 | log.Print(jsonErr) 29 | } 30 | return 31 | } 32 | fmt.Println(id, path) 33 | vol := connector.Vols[id] 34 | var res ParentsResponse 35 | cwdInfo, err := ReadFsVolDir(id, vol, path) 36 | if err != nil { 37 | log.Panicln(err) 38 | return 39 | } 40 | res.Tree = append(res.Tree, cwdInfo...) 41 | if err := SendJson(rw, &res); err != nil { 42 | log.Print(err) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /connection/command_upload.go: -------------------------------------------------------------------------------- 1 | package connection 2 | 3 | import ( 4 | "fmt" 5 | "github.com/LeeEirc/elfinder/codecs" 6 | "github.com/LeeEirc/elfinder/errs" 7 | "github.com/LeeEirc/elfinder/model" 8 | "github.com/LeeEirc/elfinder/volumes" 9 | "io" 10 | "net/http" 11 | "strings" 12 | ) 13 | 14 | const defaultSuffix = "_elfinder_" 15 | 16 | type UploadRequest struct { 17 | ReqId string `elfinder:"reqid"` 18 | Target string `elfinder:"target"` 19 | Uploads []string `elfinder:"upload[]"` 20 | UploadPaths []string `elfinder:"upload_path[]"` 21 | MTimes []string `elfinder:"mtime[]"` 22 | Names []string `elfinder:"name[]"` 23 | Renames []string `elfinder:"renames[]"` 24 | Suffix string `elfinder:"suffix"` 25 | Hashes []string `elfinder:"hashes[hash]"` 26 | Overwrite bool `elfinder:"overwrite"` 27 | 28 | Chunk string `elfinder:"chunk"` 29 | Cid string `elfinder:"cid"` 30 | Range string `elfinder:"range"` 31 | } 32 | 33 | type UploadResponse struct { 34 | Adds []model.FileInfo `json:"added"` 35 | Warnings []ErrResponse `json:"warning"` 36 | 37 | ChunkMerged string `json:"_chunkmerged"` 38 | ChunkName string `json:"_name"` 39 | } 40 | 41 | func UploadCommand(connector *Connector, req *http.Request, rw http.ResponseWriter) { 42 | var ( 43 | lsReq UploadRequest 44 | res UploadResponse 45 | ) 46 | if err := codecs.UnmarshalElfinderTag(&lsReq, req.MultipartForm.Value); err != nil { 47 | connector.Logger.Error(err) 48 | return 49 | } 50 | var ( 51 | id string 52 | path string 53 | err error 54 | vol volumes.FsVolume 55 | ) 56 | vol = connector.DefaultVol 57 | id = connector.GetVolId(connector.DefaultVol) 58 | path = fmt.Sprintf("/%s", vol.Name()) 59 | 60 | if lsReq.Target != "" { 61 | id, path, err = connector.ParseTarget(lsReq.Target) 62 | if err != nil { 63 | connector.Logger.Errorf("parse target %s errRet: %s", lsReq.Target, err) 64 | if jsonErr := SendJson(rw, NewErr(errs.ERRCmdParams, err)); jsonErr != nil { 65 | connector.Logger.Errorf("send response json errRet: %s", err) 66 | } 67 | return 68 | } 69 | vol = connector.GetFsById(id) 70 | } 71 | if vol == nil { 72 | connector.Logger.Errorf("not found vol by id: %s", id) 73 | if jsonErr := SendJson(rw, NewErr(errs.ERRCmdParams, ErrNoFoundVol)); jsonErr != nil { 74 | connector.Logger.Errorf("send response json errRet: %s", err) 75 | } 76 | return 77 | } 78 | 79 | uploadFiles := req.MultipartForm.File["upload[]"] 80 | var errRet []ErrResponse 81 | if lsReq.Chunk == "" { 82 | for i := range uploadFiles { 83 | cwdFile := uploadFiles[i] 84 | cwdFd, err := cwdFile.Open() 85 | if err != nil { 86 | errRet = append(errRet, NewErr(errs.ERRUpload, err)) 87 | continue 88 | } 89 | currentPath := strings.Join([]string{path, cwdFile.Filename}, model.Separator) 90 | relativePath := strings.TrimPrefix(currentPath, fmt.Sprintf("/%s/", vol.Name())) 91 | if writer, err2 := vol.Create(relativePath); err2 == nil { 92 | _, err3 := io.Copy(writer, cwdFd) 93 | if err3 != nil { 94 | connector.Logger.Errorf("upload file %s errRet:", cwdFile.Filename, err3) 95 | } else { 96 | if info, err := StatFsVolFileByPath(id, vol, currentPath); err == nil { 97 | res.Adds = append(res.Adds, info) 98 | } 99 | } 100 | _ = writer.Close() 101 | } 102 | _ = cwdFd.Close() 103 | } 104 | if len(errRet) > 0 { 105 | res.Warnings = errRet 106 | } 107 | } else { 108 | 109 | } 110 | if err := SendJson(rw, res); err != nil { 111 | connector.Logger.Errorf("send response json errRet: %s", err) 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /connection/commands.go: -------------------------------------------------------------------------------- 1 | package connection 2 | 3 | import ( 4 | "encoding/base64" 5 | "encoding/json" 6 | "errors" 7 | "fmt" 8 | "io/fs" 9 | "net/http" 10 | "path/filepath" 11 | "strings" 12 | 13 | "github.com/LeeEirc/elfinder" 14 | "github.com/LeeEirc/elfinder/errs" 15 | "github.com/LeeEirc/elfinder/model" 16 | "github.com/LeeEirc/elfinder/utils" 17 | "github.com/LeeEirc/elfinder/volumes" 18 | ) 19 | 20 | const defaultMaxMemory = 32 << 20 21 | 22 | const ( 23 | cmdOpen = "open" 24 | cmdInfo = "info" 25 | cmdParents = "parents" 26 | cmdTree = "tree" 27 | cmdLs = "ls" 28 | cmdUpload = "upload" 29 | cmdRm = "rm" 30 | ) 31 | 32 | var ( 33 | GetFormParse = func(req *http.Request) error { 34 | return req.ParseForm() 35 | } 36 | PostFormParse = func(req *http.Request) error { 37 | return req.ParseMultipartForm(defaultMaxMemory) 38 | } 39 | ) 40 | var ( 41 | supportedMethods = map[string]RequestFormParseFunc{ 42 | http.MethodGet: GetFormParse, 43 | http.MethodPost: PostFormParse, 44 | } 45 | 46 | supportedCommands = map[string]CommandHandler{ 47 | cmdOpen: OpenCommand, 48 | cmdParents: ParentsCommand, 49 | cmdTree: TreeCommand, 50 | cmdLs: LsCommand, 51 | cmdUpload: UploadCommand, 52 | cmdRm: RmCommand, 53 | } 54 | ) 55 | 56 | func DecodeTarget(target string) (id, path string, err error) { 57 | ret := strings.SplitN(target, "_", 2) 58 | if len(ret) != 2 { 59 | return "", "", ErrValidTarget 60 | } 61 | path, err = base64Decode(ret[1]) 62 | return ret[0], path, err 63 | } 64 | 65 | func EncodeTarget(id, path string) string { 66 | return strings.Join([]string{id, base64Encode(path)}, "_") 67 | } 68 | 69 | func base64Encode(path string) string { 70 | return base64.RawURLEncoding.EncodeToString([]byte(path)) 71 | } 72 | 73 | func base64Decode(hashPath string) (string, error) { 74 | path, err := base64.RawURLEncoding.DecodeString(hashPath) 75 | return string(path), err 76 | } 77 | 78 | var ( 79 | errNoFoundCmd = errors.New("no found cmd") 80 | ErrNoFoundVol = errors.New("no found volume") 81 | ErrValidTarget = errors.New("no valid target") 82 | ) 83 | 84 | func parseCommand(req *http.Request) (string, error) { 85 | var cmd string 86 | switch req.Method { 87 | case http.MethodGet: 88 | cmd = req.URL.Query().Get("cmd") 89 | case http.MethodPost: 90 | cmd = req.Form.Get("cmd") 91 | } 92 | if cmd == "" { 93 | return "", fmt.Errorf("%w: %s", errNoFoundCmd, req.URL) 94 | } 95 | return cmd, nil 96 | } 97 | 98 | type CommandHandler func(connector *Connector, req *http.Request, rw http.ResponseWriter) 99 | 100 | type RequestFormParseFunc func(req *http.Request) error 101 | 102 | func SendJson(w http.ResponseWriter, data interface{}) error { 103 | w.Header().Set(elfinder.HeaderContentType, elfinder.MIMEApplicationJavaScriptCharsetUTF8) 104 | return json.NewEncoder(w).Encode(data) 105 | } 106 | 107 | func StatFsVolFileByPath(id string, vol volumes.FsVolume, path string) (model.FileInfo, error) { 108 | pathHash := EncodeTarget(id, path) 109 | parentPath := filepath.Dir(path) 110 | parentPathHash := EncodeTarget(id, parentPath) 111 | isRoot := 0 112 | volRootPath := fmt.Sprintf("/%s", vol.Name()) 113 | if path == volRootPath { 114 | isRoot = 1 115 | parentPathHash = "" 116 | } 117 | relativePath := strings.TrimPrefix(strings.TrimPrefix(path, volRootPath), model.Separator) 118 | 119 | var name string 120 | if relativePath == "" { 121 | relativePath = "." 122 | name = vol.Name() 123 | } 124 | 125 | info, err := fs.Stat(vol, relativePath) 126 | if err != nil { 127 | return model.FileInfo{}, err 128 | } 129 | if name == "" { 130 | name = info.Name() 131 | } 132 | 133 | MimeType := "file" 134 | HasDirs := 0 135 | if info.IsDir() { 136 | MimeType = "directory" 137 | HasDirs = 1 138 | } 139 | Volumeid := "" 140 | if HasDirs == 1 { 141 | Volumeid = id + "_" 142 | } 143 | 144 | var locked int 145 | r, w := utils.ParseFileMode(info.Mode()) 146 | if w == 0 { 147 | locked = 1 148 | } 149 | return model.FileInfo{ 150 | Name: name, 151 | PathHash: pathHash, 152 | ParentHash: parentPathHash, 153 | MimeType: MimeType, 154 | Timestamp: info.ModTime().Unix(), 155 | Size: info.Size(), 156 | HasDirs: HasDirs, 157 | ReadAble: r, 158 | WriteAble: w, 159 | Locked: locked, 160 | Volumeid: Volumeid, 161 | Isroot: isRoot, 162 | }, nil 163 | } 164 | 165 | func ReadFsVolDir(id string, vol volumes.FsVolume, path string) ([]model.FileInfo, error) { 166 | volRootPath := fmt.Sprintf("/%s", vol.Name()) 167 | dirPath := strings.TrimPrefix(strings.TrimPrefix(path, volRootPath), "/") 168 | if dirPath == "" { 169 | dirPath = "." 170 | } 171 | files, err := fs.ReadDir(vol, dirPath) 172 | if err != nil { 173 | return nil, err 174 | } 175 | var res []model.FileInfo 176 | 177 | for i := range files { 178 | subPath := strings.Join([]string{path, files[i].Name()}, model.Separator) 179 | info, err2 := StatFsVolFileByPath(id, vol, subPath) 180 | if err2 != nil { 181 | return nil, err2 182 | } 183 | res = append(res, info) 184 | } 185 | 186 | return res, nil 187 | } 188 | 189 | func NewErr(errType errs.ErrType, errs ...error) (respErr ErrResponse) { 190 | respErr.Type = errType 191 | respErr.Errs = errs 192 | return 193 | } 194 | 195 | type ErrResponse struct { 196 | Type errs.ErrType 197 | Errs []error 198 | } 199 | 200 | func (e ErrResponse) MarshalJSON() ([]byte, error) { 201 | errs := make([]string, 0, len(e.Errs)+1) 202 | errs = append(errs, string(e.Type)) 203 | for i := range e.Errs { 204 | errs = append(errs, e.Errs[i].Error()) 205 | } 206 | data := map[string]interface{}{ 207 | "error": errs, 208 | } 209 | return json.Marshal(data) 210 | } 211 | -------------------------------------------------------------------------------- /connection/connector.go: -------------------------------------------------------------------------------- 1 | package connection 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "sync" 7 | "time" 8 | 9 | "github.com/LeeEirc/elfinder/errs" 10 | "github.com/LeeEirc/elfinder/log" 11 | "github.com/LeeEirc/elfinder/utils" 12 | "github.com/LeeEirc/elfinder/volumes" 13 | ) 14 | 15 | func NewConnector(opts ...Options) *Connector { 16 | opt := option{ 17 | Logger: &log.GlobalLogger, 18 | } 19 | for _, setter := range opts { 20 | setter(&opt) 21 | } 22 | 23 | volsMap := make(map[string]volumes.FsVolume, len(opt.Vols)) 24 | for i := range opt.Vols { 25 | vid := utils.MD5ID(opt.Vols[i].Name()) 26 | volsMap[vid] = opt.Vols[i] 27 | } 28 | var defaultVol volumes.FsVolume 29 | if len(opt.Vols) > 0 { 30 | defaultVol = opt.Vols[0] 31 | } 32 | return &Connector{ 33 | DefaultVol: defaultVol, 34 | Vols: volsMap, 35 | Created: time.Now(), 36 | Logger: opt.Logger, 37 | } 38 | } 39 | 40 | type Connector struct { 41 | DefaultVol volumes.FsVolume 42 | Vols map[string]volumes.FsVolume 43 | Created time.Time 44 | Logger log.Logger 45 | mux sync.Mutex 46 | } 47 | 48 | func (c *Connector) GetVolId(v volumes.FsVolume) string { 49 | for id, vol := range c.Vols { 50 | if vol.Name() == v.Name() { 51 | return id 52 | } 53 | } 54 | return "" 55 | } 56 | func (c *Connector) GetFsById(id string) volumes.FsVolume { 57 | return c.Vols[id] 58 | } 59 | 60 | func (c *Connector) ServeHTTP(w http.ResponseWriter, r *http.Request) { 61 | formParseFunc, ok := supportedMethods[r.Method] 62 | if !ok { 63 | c.Logger.Errorf("not support http method %s", r.Method) 64 | if err := SendJson(w, NewErr(errs.ERRCmdParams, fmt.Errorf("method: %s", r.Method))); err != nil { 65 | c.Logger.Error(err) 66 | } 67 | return 68 | } 69 | if err := formParseFunc(r); err != nil { 70 | c.Logger.Errorf("HTTP form parse errs: %s", err) 71 | if err := SendJson(w, NewErr(errs.ERRCmdParams, err)); err != nil { 72 | c.Logger.Error(err) 73 | } 74 | return 75 | } 76 | cmd, err := parseCommand(r) 77 | if err != nil { 78 | c.Logger.Errorf("Parse command errs: %s %+v", err, r.URL.Query()) 79 | if err := SendJson(w, NewErr(errs.ERRCmdParams, err)); err != nil { 80 | c.Logger.Error(err) 81 | } 82 | return 83 | } 84 | handleFunc, ok := supportedCommands[cmd] 85 | if !ok { 86 | c.Logger.Errorf("Command `%s` not supported", cmd) 87 | err = fmt.Errorf("command `%s` not supported", cmd) 88 | if err := SendJson(w, NewErr(errs.ERRUsupportType, err)); err != nil { 89 | c.Logger.Error(err) 90 | } 91 | return 92 | } 93 | handleFunc(c, r, w) 94 | } 95 | 96 | func (c *Connector) ParseTarget(target string) (vid, vPath string, err error) { 97 | return DecodeTarget(target) 98 | } 99 | 100 | type Options func(*option) 101 | 102 | type option struct { 103 | Vols []volumes.FsVolume 104 | Logger log.Logger 105 | } 106 | 107 | func WithVolumes(vols ...volumes.FsVolume) Options { 108 | return func(o *option) { 109 | o.Vols = vols 110 | } 111 | } 112 | 113 | func WithLogger(logger log.Logger) Options { 114 | return func(o *option) { 115 | o.Logger = logger 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /error.go: -------------------------------------------------------------------------------- 1 | package elfinder 2 | 3 | const ( 4 | errMsg = "error" 5 | errUnknownMsg = "errUnknown" 6 | errUnknownCmd = "errUnknownCmd" 7 | 8 | errJqui = "errJqui" 9 | errNode = "errNode" 10 | errURL = "errURL" 11 | errAccess = "errAccess" 12 | errConnect = "errConnect" 13 | errAbort = "errAbort" 14 | errTimeout = "errTimeout" 15 | errNotFound = "errNotFound" 16 | errResponse = "errResponse" 17 | errConf = "errConf" 18 | errJSON = "errJSON" 19 | errNoVolumes = "errNoVolumes" 20 | errCmdParams = "errCmdParams" 21 | errDataNotJSON = "errDataNotJSON" 22 | errDataEmpty = "errDataEmpty" 23 | errCmdReq = "errCmdReq" 24 | errOpen = "errOpen" 25 | errNotFolder = "errNotFolder" 26 | errNotFile = "errNotFile" 27 | errRead = "errRead" 28 | errWrite = "errWrite" 29 | errPerm = "errPerm" 30 | errLocked = "errLocked" 31 | errExists = "errExists" 32 | errInvName = "errInvName" 33 | errFolderNotFound = "errFolderNotFound" 34 | errFileNotFound = "errFileNotFound" 35 | errTrgFolderNotFound = "errTrgFolderNotFound" 36 | errPopup = "errPopup" 37 | errMkdir = "errMkdir" 38 | errMkfile = "errMkfile" 39 | errRename = "errRename" 40 | errCopyFrom = "errCopyFrom" 41 | errCopyTo = "errCopyTo" 42 | errMkOutLink = "errMkOutLink" 43 | 44 | errUpload = "errUpload" 45 | errUploadFile = "errUploadFile" 46 | errUploadNoFiles = "errUploadNoFiles" 47 | errUploadTotalSize = "errUploadTotalSize" 48 | errUploadFileSize = "errUploadFileSize" 49 | errUploadMime = "errUploadMime" 50 | errUploadTransfer = "errUploadTransfer" 51 | errUploadTemp = "errUploadTemp" 52 | 53 | errNotReplace = "errNotReplace" 54 | errReplace = "errReplace" 55 | errSave = "errSave" 56 | errCopy = "errCopy" 57 | errMove = "errMove" 58 | errCopyInItself = "errCopyInItself" 59 | errRm = "errRm" 60 | errRmSrc = "errRmSrc" 61 | errExtract = "errExtract" 62 | errArchive = "errArchive" 63 | errArcType = "errArcType" 64 | errNoArchive = "errNoArchive" 65 | errCmdNoSupport = "errCmdNoSupport" 66 | errReplByChild = "errReplByChild" 67 | errArcSymlinks = "errArcSymlinks" 68 | errArcMaxSize = "errArcMaxSize" 69 | 70 | errResize = "errResize" 71 | errResizeDegree = "errResizeDegree" 72 | errResizeRotate = "errResizeRotate" 73 | errResizeSize = "errResizeSize" 74 | errResizeNoChange = "errResizeNoChange" 75 | 76 | errUsupportType = "errUsupportType" 77 | errNotUTF8Content = "errNotUTF8Content" 78 | 79 | errNetMount = "errNetMount" 80 | errNetMountNoDriver = "errNetMountNoDriver" 81 | errNetMountFailed = "errNetMountFailed" 82 | errNetMountHostReq = "errNetMountHostReq" 83 | 84 | errSessionExpires = "errSessionExpires" 85 | errCreatingTempDir = "errCreatingTempDir" 86 | 87 | errFtpDownloadFile = "errFtpDownloadFile" 88 | errFtpUploadFile = "errFtpUploadFile" 89 | errFtpMkdir = "errFtpMkdir" 90 | 91 | errArchiveExec = "errArchiveExec" 92 | errExtractExec = "errExtractExec" 93 | errNetUnMount = "errNetUnMount" 94 | errConvUTF8 = "errConvUTF8" 95 | errFolderUpload = "errFolderUpload" 96 | errSearchTimeout = "errSearchTimeout" 97 | errReauthRequire = "errReauthRequire" 98 | errMaxTargets = "errMaxTargets" 99 | ) 100 | -------------------------------------------------------------------------------- /errs/errors.go: -------------------------------------------------------------------------------- 1 | package errs 2 | 3 | type ErrType string 4 | 5 | func (e ErrType) String() string { 6 | return string(e) 7 | } 8 | 9 | const ( 10 | ERRMsg ErrType = "error" 11 | ERRUnknownMsg ErrType = "errUnknown" 12 | ERRUnknownCmd ErrType = "errUnknownCmd" 13 | 14 | ERRJqui ErrType = "errJqui" 15 | ERRNode ErrType = "errNode" 16 | ERRURL ErrType = "errURL" 17 | ERRAccess ErrType = "errAccess" 18 | ERRConnect ErrType = "errConnect" 19 | ERRAbort ErrType = "errAbort" 20 | ERRTimeout ErrType = "errTimeout" 21 | ERRNotFound ErrType = "errNotFound" 22 | ERRResponse ErrType = "errResponse" 23 | ERRConf ErrType = "errConf" 24 | ERRJSON ErrType = "errJSON" 25 | ERRNoVolumes ErrType = "errNoVolumes" 26 | ERRCmdParams ErrType = "errCmdParams" 27 | ERRDataNotJSON ErrType = "errDataNotJSON" 28 | ERRDataEmpty ErrType = "errDataEmpty" 29 | ERRCmdReq ErrType = "errCmdReq" 30 | ERROpen ErrType = "errOpen" 31 | ERRNotFolder ErrType = "errNotFolder" 32 | ERRNotFile ErrType = "errNotFile" 33 | ERRRead ErrType = "errRead" 34 | ERRWrite ErrType = "errWrite" 35 | ERRPerm ErrType = "errPerm" 36 | ERRLocked ErrType = "errLocked" 37 | ERRExists ErrType = "errExists" 38 | ERRInvName ErrType = "errInvName" 39 | ERRFolderNotFound ErrType = "errFolderNotFound" 40 | ERRFileNotFound ErrType = "errFileNotFound" 41 | ERRTrgFolderNotFound ErrType = "errTrgFolderNotFound" 42 | ERRPopup ErrType = "errPopup" 43 | ERRMkdir ErrType = "errMkdir" 44 | ERRMkfile ErrType = "errMkfile" 45 | ERRRename ErrType = "errRename" 46 | ERRCopyFrom ErrType = "errCopyFrom" 47 | ERRCopyTo ErrType = "errCopyTo" 48 | ERRMkOutLink ErrType = "errMkOutLink" 49 | 50 | ERRUpload ErrType = "errUpload" 51 | ERRUploadFile ErrType = "errUploadFile" 52 | ERRUploadNoFiles ErrType = "errUploadNoFiles" 53 | ERRUploadTotalSize ErrType = "errUploadTotalSize" 54 | ERRUploadFileSize ErrType = "errUploadFileSize" 55 | ERRUploadMime ErrType = "errUploadMime" 56 | ERRUploadTransfer ErrType = "errUploadTransfer" 57 | ERRUploadTemp ErrType = "errUploadTemp" 58 | ERR 59 | ERRNotReplace ErrType = "errNotReplace" 60 | ERRReplace ErrType = "errReplace" 61 | ERRSave ErrType = "errSave" 62 | ERRCopy ErrType = "errCopy" 63 | ERRMove ErrType = "errMove" 64 | ERRCopyInItself ErrType = "errCopyInItself" 65 | ERRRm ErrType = "errRm" 66 | ERRRmSrc ErrType = "errRmSrc" 67 | ERRExtract ErrType = "errExtract" 68 | ERRArchive ErrType = "errArchive" 69 | ERRArcType ErrType = "errArcType" 70 | ERRNoArchive ErrType = "errNoArchive" 71 | ERRCmdNoSupport ErrType = "errCmdNoSupport" 72 | ERRReplByChild ErrType = "errReplByChild" 73 | ERRArcSymlinks ErrType = "errArcSymlinks" 74 | ERRArcMaxSize ErrType = "errArcMaxSize" 75 | 76 | ERRResize ErrType = "errResize" 77 | ERRResizeDegree ErrType = "errResizeDegree" 78 | ERRResizeRotate ErrType = "errResizeRotate" 79 | ERRResizeSize ErrType = "errResizeSize" 80 | ERRResizeNoChange ErrType = "errResizeNoChange" 81 | 82 | ERRUsupportType ErrType = "errUsupportType" 83 | ERRNotUTF8Content ErrType = "errNotUTF8Content" 84 | 85 | ERRNetMount ErrType = "errNetMount" 86 | ERRNetMountNoDriver ErrType = "errNetMountNoDriver" 87 | ERRNetMountFailed ErrType = "errNetMountFailed" 88 | ERRNetMountHostReq ErrType = "errNetMountHostReq" 89 | 90 | ERRSessionExpires ErrType = "errSessionExpires" 91 | ERRCreatingTempDir ErrType = "errCreatingTempDir" 92 | 93 | ERRFtpDownloadFile ErrType = "errFtpDownloadFile" 94 | ERRFtpUploadFile ErrType = "errFtpUploadFile" 95 | ERRFtpMkdir ErrType = "errFtpMkdir" 96 | ERRArchiveExec ErrType = "errArchiveExec" 97 | 98 | ERRExtractExec ErrType = "errExtractExec" 99 | ERRNetUnMount ErrType = "errNetUnMount" 100 | ERRConvUTF8 ErrType = "errConvUTF8" 101 | ERRFolderUpload ErrType = "errFolderUpload" 102 | ERRSearchTimeout ErrType = "errSearchTimeout" 103 | ERRReauthRequire ErrType = "errReauthRequire" 104 | ERRMaxTargets ErrType = "errMaxTargets" 105 | ) 106 | -------------------------------------------------------------------------------- /example/elf/css/theme.css: -------------------------------------------------------------------------------- 1 | /** 2 | * MacOS X like theme for elFinder. 3 | * Required jquery ui "smoothness" theme. 4 | * 5 | * @author Dmitry (dio) Levashov 6 | **/ 7 | 8 | /* scrollbar for Chrome and Safari */ 9 | .elfinder:not(.elfinder-mobile) *::-webkit-scrollbar { 10 | width: 10px; 11 | height: 10px; 12 | } 13 | 14 | .elfinder:not(.elfinder-mobile) *::-webkit-scrollbar-track { 15 | border-radius: 10px; 16 | box-shadow: inset 0 0 6px rgba(0, 0, 0, .1); 17 | } 18 | 19 | .elfinder:not(.elfinder-mobile) *::-webkit-scrollbar-thumb { 20 | background-color: rgba(0, 0, 50, 0.08); 21 | border-radius: 10px; 22 | box-shadow:0 0 0 1px rgba(255, 255, 255, .3); 23 | } 24 | 25 | .elfinder:not(.elfinder-mobile) *::-webkit-scrollbar-thumb:hover { 26 | background-color: rgba(0, 0, 50, 0.16); 27 | } 28 | 29 | .elfinder:not(.elfinder-mobile) *::-webkit-scrollbar-thumb:active { 30 | background-color: rgba(0, 0, 50, 0.24); 31 | } 32 | 33 | .elfinder:not(.elfinder-mobile) *::-webkit-scrollbar-corner { 34 | background-color: transparent; 35 | } 36 | 37 | .elfinder:not(.elfinder-mobile) *::-webkit-scrollbar-button { 38 | background-color: transparent; 39 | width: 10px; 40 | height: 10px; 41 | border: 5px solid transparent; 42 | } 43 | 44 | .elfinder:not(.elfinder-mobile) *::-webkit-scrollbar-button:hover { 45 | border: 5px solid rgba(0, 0, 50, 0.08); 46 | } 47 | 48 | .elfinder:not(.elfinder-mobile) *::-webkit-scrollbar-button:active { 49 | border: 5px solid rgba(0, 0, 50, 0.5); 50 | } 51 | 52 | .elfinder:not(.elfinder-mobile) *::-webkit-scrollbar-button:single-button:vertical:decrement { 53 | border-bottom: 8px solid rgba(0, 0, 50, 0.3); 54 | } 55 | 56 | .elfinder:not(.elfinder-mobile) *::-webkit-scrollbar-button:single-button:vertical:increment { 57 | border-top: 8px solid rgba(0, 0, 50, 0.3); 58 | } 59 | 60 | .elfinder:not(.elfinder-mobile) *::-webkit-scrollbar-button:single-button:horizontal:decrement { 61 | border-right: 8px solid rgba(0, 0, 50, 0.3); 62 | } 63 | 64 | .elfinder:not(.elfinder-mobile) *::-webkit-scrollbar-button:single-button:horizontal:increment { 65 | border-left: 8px solid rgba(0, 0, 50, 0.3); 66 | } 67 | 68 | /* input textarea */ 69 | .elfinder input, 70 | .elfinder textarea { 71 | color: #000; 72 | background-color: #FFF; 73 | border-color: #ccc; 74 | } 75 | 76 | /* dialogs */ 77 | .std42-dialog, .std42-dialog .ui-widget-content { 78 | background-color: #ededed; 79 | background-image: none; 80 | background-clip: content-box; 81 | } 82 | 83 | .std42-dialog.elfinder-bg-translucent { 84 | background-color: #fff; 85 | background-color: rgba(255, 255, 255, 0.9); 86 | } 87 | 88 | .std42-dialog.elfinder-bg-translucent .ui-widget-content { 89 | background-color: transparent; 90 | } 91 | 92 | .elfinder-quicklook-title { 93 | color: #fff; 94 | } 95 | 96 | .elfinder-quicklook-titlebar-icon { 97 | background-color: transparent; 98 | background-image: none; 99 | } 100 | 101 | .elfinder-quicklook-titlebar-icon .ui-icon { 102 | background-color: #d4d4d4; 103 | border-color: #8a8a8a; 104 | } 105 | 106 | .std42-dialog .ui-dialog-titlebar .ui-dialog-titlebar-close:hover .ui-icon, 107 | .elfinder-mobile .std42-dialog .ui-dialog-titlebar .ui-dialog-titlebar-close .ui-icon, 108 | .elfinder-quicklook-titlebar-icon .ui-icon.elfinder-icon-close:hover, 109 | .elfinder-mobile .elfinder-quicklook-titlebar-icon .ui-icon.elfinder-icon-close { 110 | background-color: #ff6252; 111 | border-color: #e5695d; 112 | background-image: url("../img/ui-icons_ffffff_256x240.png"); 113 | } 114 | 115 | .std42-dialog .ui-dialog-titlebar .elfinder-titlebar-minimize:hover .ui-icon, 116 | .elfinder-mobile .std42-dialog .ui-dialog-titlebar .elfinder-titlebar-minimize .ui-icon, 117 | .elfinder-quicklook-titlebar-icon .ui-icon.elfinder-icon-minimize:hover, 118 | .elfinder-mobile .elfinder-quicklook-titlebar-icon .ui-icon.elfinder-icon-minimize { 119 | background-color: #ffbc00; 120 | border-color: #e3a40b; 121 | background-image: url("../img/ui-icons_ffffff_256x240.png"); 122 | } 123 | 124 | .std42-dialog .ui-dialog-titlebar .elfinder-titlebar-full:hover .ui-icon, 125 | .elfinder-mobile .std42-dialog .ui-dialog-titlebar .elfinder-titlebar-full .ui-icon, 126 | .elfinder-quicklook-titlebar-icon .ui-icon.elfinder-icon-full:hover, 127 | .elfinder-mobile .elfinder-quicklook-titlebar-icon .ui-icon.elfinder-icon-full { 128 | background-color: #26c82f; 129 | border-color: #13ae10; 130 | background-image: url("../img/ui-icons_ffffff_256x240.png"); 131 | } 132 | 133 | .std42-dialog .elfinder-help, 134 | .std42-dialog .elfinder-help .ui-widget-content { 135 | background: #fff; 136 | } 137 | 138 | /* navbar */ 139 | .elfinder .elfinder-navbar { 140 | background: #dde4eb; 141 | } 142 | 143 | .elfinder-navbar .ui-state-hover { 144 | color: #000; 145 | background-color: #edf1f4; 146 | border-color: #bdcbd8; 147 | } 148 | 149 | .elfinder-navbar .ui-droppable-hover { 150 | background: transparent; 151 | } 152 | 153 | .elfinder-navbar .ui-state-active { 154 | background: #3875d7; 155 | border-color: #3875d7; 156 | color: #fff; 157 | } 158 | 159 | .elfinder-navbar .elfinder-droppable-active { 160 | background: #A7C6E5; 161 | } 162 | 163 | /* disabled elfinder */ 164 | .elfinder-disabled .elfinder-navbar .ui-state-active { 165 | background: #dadada; 166 | border-color: #aaa; 167 | color: #777; 168 | } 169 | 170 | /* workzone */ 171 | .elfinder-workzone { 172 | background: #fff; 173 | } 174 | 175 | /* current directory */ 176 | /* Is in trash */ 177 | .elfinder-cwd-wrapper.elfinder-cwd-wrapper-trash { 178 | background-color: #f0f0f0; 179 | } 180 | 181 | /* selected file in "icons" view */ 182 | .elfinder-cwd-view-icons .elfinder-cwd-file .ui-state-hover, 183 | .elfinder-cwd-view-icons .elfinder-cwd-file .ui-state-active { 184 | background: #ccc; 185 | } 186 | 187 | /* type badge in "icons" view */ 188 | /* default */ 189 | .elfinder-cwd-icon:before { 190 | color: white; 191 | background-color: #798da7; 192 | } 193 | 194 | /* type */ 195 | .elfinder-cwd-icon-text:before { 196 | background-color: #6f99e6 197 | } 198 | 199 | .elfinder-cwd-icon-image:before { 200 | background-color: #2ea26c 201 | } 202 | 203 | .elfinder-cwd-icon-audio:before { 204 | background-color: #7bad2a 205 | } 206 | 207 | .elfinder-cwd-icon-video:before { 208 | background-color: #322aad 209 | } 210 | 211 | /* subtype */ 212 | .elfinder-cwd-icon-x-empty:before, 213 | .elfinder-cwd-icon-plain:before { 214 | background-color: #719be6 215 | } 216 | 217 | .elfinder-cwd-icon-rtf:before, 218 | .elfinder-cwd-icon-rtfd:before { 219 | background-color: #83aae7 220 | } 221 | 222 | .elfinder-cwd-icon-pdf:before { 223 | background-color: #db7424 224 | } 225 | 226 | .elfinder-cwd-icon-html:before { 227 | background-color: #82bc12 228 | } 229 | 230 | .elfinder-cwd-icon-xml:before, 231 | .elfinder-cwd-icon-css:before { 232 | background-color: #7c7c7c 233 | } 234 | 235 | .elfinder-cwd-icon-x-shockwave-flash:before { 236 | background-color: #f43a36 237 | } 238 | 239 | .elfinder-cwd-icon-zip:before, 240 | .elfinder-cwd-icon-x-zip:before, 241 | .elfinder-cwd-icon-x-xz:before, 242 | .elfinder-cwd-icon-x-7z-compressed:before, 243 | .elfinder-cwd-icon-x-gzip:before, 244 | .elfinder-cwd-icon-x-tar:before, 245 | .elfinder-cwd-icon-x-bzip:before, 246 | .elfinder-cwd-icon-x-bzip2:before, 247 | .elfinder-cwd-icon-x-rar:before, 248 | .elfinder-cwd-icon-x-rar-compressed:before { 249 | background-color: #97638e 250 | } 251 | 252 | .elfinder-cwd-icon-javascript:before, 253 | .elfinder-cwd-icon-x-javascript:before, 254 | .elfinder-cwd-icon-x-perl:before, 255 | .elfinder-cwd-icon-x-python:before, 256 | .elfinder-cwd-icon-x-ruby:before, 257 | .elfinder-cwd-icon-x-sh:before, 258 | .elfinder-cwd-icon-x-shellscript:before, 259 | .elfinder-cwd-icon-x-c:before, 260 | .elfinder-cwd-icon-x-csrc:before, 261 | .elfinder-cwd-icon-x-chdr:before, 262 | .elfinder-cwd-icon-x-c--:before, 263 | .elfinder-cwd-icon-x-c--src:before, 264 | .elfinder-cwd-icon-x-c--hdr:before, 265 | .elfinder-cwd-icon-x-java:before, 266 | .elfinder-cwd-icon-x-java-source:before, 267 | .elfinder-cwd-icon-x-php:before { 268 | background-color: #7c607c 269 | } 270 | 271 | .elfinder-cwd-icon-msword:before, 272 | .elfinder-cwd-icon-vnd-ms-office:before, 273 | .elfinder-cwd-icon-vnd-ms-word:before, 274 | .elfinder-cwd-icon-vnd-ms-word-document-macroEnabled-12:before, 275 | .elfinder-cwd-icon-vnd-ms-word-template-macroEnabled-12:before, 276 | .elfinder-cwd-icon-vnd-openxmlformats-officedocument-wordprocessingml-document:before, 277 | .elfinder-cwd-icon-vnd-openxmlformats-officedocument-wordprocessingml-template:before { 278 | background-color: #2b569a 279 | } 280 | 281 | .elfinder-cwd-icon-ms-excel:before, 282 | .elfinder-cwd-icon-vnd-ms-excel:before, 283 | .elfinder-cwd-icon-vnd-ms-excel-addin-macroEnabled-12:before, 284 | .elfinder-cwd-icon-vnd-ms-excel-sheet-binary-macroEnabled-12:before, 285 | .elfinder-cwd-icon-vnd-ms-excel-sheet-macroEnabled-12:before, 286 | .elfinder-cwd-icon-vnd-ms-excel-template-macroEnabled-12:before, 287 | .elfinder-cwd-icon-vnd-openxmlformats-officedocument-spreadsheetml-sheet:before, 288 | .elfinder-cwd-icon-vnd-openxmlformats-officedocument-spreadsheetml-template:before { 289 | background-color: #107b10 290 | } 291 | 292 | .elfinder-cwd-icon-vnd-ms-powerpoint:before, 293 | .elfinder-cwd-icon-vnd-ms-powerpoint-addin-macroEnabled-12:before, 294 | .elfinder-cwd-icon-vnd-ms-powerpoint-presentation-macroEnabled-12:before, 295 | .elfinder-cwd-icon-vnd-ms-powerpoint-slide-macroEnabled-12:before, 296 | .elfinder-cwd-icon-vnd-ms-powerpoint-slideshow-macroEnabled-12:before, 297 | .elfinder-cwd-icon-vnd-ms-powerpoint-template-macroEnabled-12:before, 298 | .elfinder-cwd-icon-vnd-openxmlformats-officedocument-presentationml-presentation:before, 299 | .elfinder-cwd-icon-vnd-openxmlformats-officedocument-presentationml-slide:before, 300 | .elfinder-cwd-icon-vnd-openxmlformats-officedocument-presentationml-slideshow:before, 301 | .elfinder-cwd-icon-vnd-openxmlformats-officedocument-presentationml-template:before { 302 | background-color: #d24625 303 | } 304 | 305 | .elfinder-cwd-icon-vnd-oasis-opendocument-chart:before, 306 | .elfinder-cwd-icon-vnd-oasis-opendocument-database:before, 307 | .elfinder-cwd-icon-vnd-oasis-opendocument-formula:before, 308 | .elfinder-cwd-icon-vnd-oasis-opendocument-graphics:before, 309 | .elfinder-cwd-icon-vnd-oasis-opendocument-graphics-template:before, 310 | .elfinder-cwd-icon-vnd-oasis-opendocument-image:before, 311 | .elfinder-cwd-icon-vnd-oasis-opendocument-presentation:before, 312 | .elfinder-cwd-icon-vnd-oasis-opendocument-presentation-template:before, 313 | .elfinder-cwd-icon-vnd-oasis-opendocument-spreadsheet:before, 314 | .elfinder-cwd-icon-vnd-oasis-opendocument-spreadsheet-template:before, 315 | .elfinder-cwd-icon-vnd-oasis-opendocument-text:before, 316 | .elfinder-cwd-icon-vnd-oasis-opendocument-text-master:before, 317 | .elfinder-cwd-icon-vnd-oasis-opendocument-text-template:before, 318 | .elfinder-cwd-icon-vnd-oasis-opendocument-text-web:before, 319 | .elfinder-cwd-icon-vnd-openofficeorg-extension:before { 320 | background-color: #00a500 321 | } 322 | 323 | .elfinder-cwd-icon-postscript:before { 324 | background-color: #ff5722 325 | } 326 | 327 | /* list view*/ 328 | .elfinder-cwd table thead td.ui-state-hover { 329 | background: #ddd; 330 | } 331 | 332 | .elfinder-cwd table tr:nth-child(odd) { 333 | background-color: #edf3fe; 334 | } 335 | 336 | .elfinder-cwd table tr { 337 | border: 1px solid transparent; 338 | border-top: 1px solid #fff; 339 | } 340 | 341 | .elfinder-cwd .elfinder-droppable-active td { 342 | background: #A7C6E5; 343 | } 344 | 345 | .elfinder-cwd.elfinder-table-header-sticky table { 346 | border-top-color: #fff; 347 | } 348 | 349 | .elfinder-droppable-active .elfinder-cwd.elfinder-table-header-sticky table { 350 | border-top-color: #A7C6E5; 351 | } 352 | 353 | /* common selected background/color */ 354 | .elfinder-cwd-view-icons .elfinder-cwd-file .elfinder-cwd-filename.ui-state-hover, 355 | .elfinder-cwd table td.ui-state-hover, 356 | .elfinder-button-menu .ui-state-hover { 357 | background: #3875d7; 358 | color: #fff; 359 | } 360 | 361 | /* disabled elfinder */ 362 | .elfinder-disabled .elfinder-cwd-view-icons .elfinder-cwd-file .elfinder-cwd-filename.ui-state-hover, 363 | .elfinder-disabled .elfinder-cwd table td.ui-state-hover { 364 | background: #dadada; 365 | } 366 | 367 | /* statusbar */ 368 | .elfinder .elfinder-statusbar { 369 | color: #555; 370 | } 371 | 372 | .elfinder .elfinder-statusbar a { 373 | text-decoration: none; 374 | color: #555; 375 | } 376 | 377 | /* contextmenu */ 378 | .elfinder-contextmenu .ui-state-active { 379 | background: #6293df; 380 | color: #fff; 381 | } 382 | 383 | .elfinder-contextmenu .ui-state-hover { 384 | background: #3875d7; 385 | color: #fff; 386 | } 387 | 388 | .elfinder-contextmenu .ui-state-hover .elfinder-contextmenu-arrow { 389 | background-image: url('../img/arrows-active.png'); 390 | } 391 | 392 | /* dialog */ 393 | .elfinder .ui-dialog input:text.ui-state-hover, 394 | .elfinder .ui-dialog textarea.ui-state-hover { 395 | background-image: none; 396 | background-color: inherit; 397 | } 398 | 399 | /* edit dialog */ 400 | .elfinder-dialog-edit select.elfinder-edit-changed { 401 | border-bottom: 2px solid #13ae10; 402 | } 403 | 404 | /* tooltip */ 405 | .ui-widget-content.elfinder-ui-tooltip { 406 | background-color: #fff; 407 | } 408 | 409 | .elfinder-ui-tooltip.ui-widget-shadow, 410 | .elfinder .elfinder-ui-tooltip.ui-widget-shadow { 411 | box-shadow: 2px 6px 4px -4px #cecdcd; 412 | } 413 | -------------------------------------------------------------------------------- /example/elf/img/arrows-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/arrows-active.png -------------------------------------------------------------------------------- /example/elf/img/arrows-normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/arrows-normal.png -------------------------------------------------------------------------------- /example/elf/img/crop.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/crop.gif -------------------------------------------------------------------------------- /example/elf/img/dialogs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/dialogs.png -------------------------------------------------------------------------------- /example/elf/img/edit_aceeditor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/edit_aceeditor.png -------------------------------------------------------------------------------- /example/elf/img/edit_ckeditor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/edit_ckeditor.png -------------------------------------------------------------------------------- /example/elf/img/edit_ckeditor5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/edit_ckeditor5.png -------------------------------------------------------------------------------- /example/elf/img/edit_codemirror.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/edit_codemirror.png -------------------------------------------------------------------------------- /example/elf/img/edit_creativecloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/edit_creativecloud.png -------------------------------------------------------------------------------- /example/elf/img/edit_onlineconvert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/edit_onlineconvert.png -------------------------------------------------------------------------------- /example/elf/img/edit_pixlreditor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/edit_pixlreditor.png -------------------------------------------------------------------------------- /example/elf/img/edit_pixlrexpress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/edit_pixlrexpress.png -------------------------------------------------------------------------------- /example/elf/img/edit_simplemde.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/edit_simplemde.png -------------------------------------------------------------------------------- /example/elf/img/edit_tinymce.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/edit_tinymce.png -------------------------------------------------------------------------------- /example/elf/img/edit_tuiimgedit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/edit_tuiimgedit.png -------------------------------------------------------------------------------- /example/elf/img/edit_zohooffice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/edit_zohooffice.png -------------------------------------------------------------------------------- /example/elf/img/editor-icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/editor-icons.png -------------------------------------------------------------------------------- /example/elf/img/icons-big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/icons-big.png -------------------------------------------------------------------------------- /example/elf/img/icons-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/icons-small.png -------------------------------------------------------------------------------- /example/elf/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/logo.png -------------------------------------------------------------------------------- /example/elf/img/progress.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/progress.gif -------------------------------------------------------------------------------- /example/elf/img/quicklook-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/quicklook-bg.png -------------------------------------------------------------------------------- /example/elf/img/quicklook-icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/quicklook-icons.png -------------------------------------------------------------------------------- /example/elf/img/resize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/resize.png -------------------------------------------------------------------------------- /example/elf/img/spinner-mini.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/spinner-mini.gif -------------------------------------------------------------------------------- /example/elf/img/toolbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/toolbar.png -------------------------------------------------------------------------------- /example/elf/img/trashmesh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/trashmesh.png -------------------------------------------------------------------------------- /example/elf/img/ui-icons_ffffff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/ui-icons_ffffff_256x240.png -------------------------------------------------------------------------------- /example/elf/img/volume_icon_box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/volume_icon_box.png -------------------------------------------------------------------------------- /example/elf/img/volume_icon_box.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/elf/img/volume_icon_dropbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/volume_icon_dropbox.png -------------------------------------------------------------------------------- /example/elf/img/volume_icon_dropbox.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/elf/img/volume_icon_ftp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/volume_icon_ftp.png -------------------------------------------------------------------------------- /example/elf/img/volume_icon_ftp.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/elf/img/volume_icon_googledrive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/volume_icon_googledrive.png -------------------------------------------------------------------------------- /example/elf/img/volume_icon_googledrive.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/elf/img/volume_icon_local.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/volume_icon_local.png -------------------------------------------------------------------------------- /example/elf/img/volume_icon_local.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/elf/img/volume_icon_network.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/volume_icon_network.png -------------------------------------------------------------------------------- /example/elf/img/volume_icon_network.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/elf/img/volume_icon_onedrive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/volume_icon_onedrive.png -------------------------------------------------------------------------------- /example/elf/img/volume_icon_onedrive.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/elf/img/volume_icon_sql.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/volume_icon_sql.png -------------------------------------------------------------------------------- /example/elf/img/volume_icon_sql.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/elf/img/volume_icon_trash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/volume_icon_trash.png -------------------------------------------------------------------------------- /example/elf/img/volume_icon_trash.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/elf/img/volume_icon_zip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeEirc/elfinder/affa277e3d51b5de1e1b86c26cf5212b6f0f4191/example/elf/img/volume_icon_zip.png -------------------------------------------------------------------------------- /example/elf/img/volume_icon_zip.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/elf/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |Obsluha na uživatelském rozhraní je podobná standardnímu správci souborů operačního systému. Drag and Drop však není možné používat s mobilními prohlížeči.
3 |Operation on the UI is similar to operating system's standard file manager. However, Drag and Drop is not possible with mobile browsers.
3 |Operar en la Interfaz del Usuario es similar al administrador de archivos estandar del sistema operativo. Sin embargo, Arrastrar y soltar no es posible con los navegadores móviles.
3 |UIの操作は、オペレーティングシステムの標準ファイルマネージャにほぼ準拠しています。ただし、モバイルブラウザではドラッグ&ドロップはできません。
3 |UI 조작은 운영체제의 표준 파일 관리자를 사용하는 방법과 비슷합니다. 하지만 모바일 브라우저에서는 드래그앤드롭을 사용할 수 없습니다.
3 |Działanie w interfejsie użytkownika jest podobne do standardowego menedżera plików systemu operacyjnego. Jednak Przeciąganie i Upuszczanie nie jest możliwe w przeglądarkach mobilnych.
3 |Работа с пользовательским интерфейсом похожа на стандартный файловый менеджер операционной системы. Однако перетаскивание в мобильных браузерах невозможно.
3 |Obsluha na používateľskom rozhraní je podobná štandardnému správcovi súborov operačného systému. Drag and Drop však nie je možné používať s mobilnými prehliadačmi.
3 |