Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7330997281 | ||
|
|
0787522d7c | ||
|
|
46df72ac0e | ||
|
|
6839c15a7b | ||
|
|
d50dc90a54 | ||
|
|
4039efe4b2 | ||
|
|
2ab1ea44ff | ||
|
|
23a2c60d9f | ||
|
|
54e66bbc05 | ||
|
|
69b262f91a | ||
|
|
731cc45e05 | ||
|
|
a3960ff9a3 |
@@ -73,7 +73,3 @@ this are keywords case:insensitive
|
||||
# Contributing
|
||||
|
||||
The contributing guidelines can be found [here](https://github.com/hacdias/filemanager/blob/master/CONTRIBUTING.md).
|
||||
|
||||
# Donate
|
||||
|
||||
Enjoying this project? You can [donate to its creator](https://henriquedias.com/donate/). He will appreciate.
|
||||
|
||||
@@ -134,7 +134,7 @@ settings:
|
||||
您可以将该用户设置为管理员,也可以单独选择各项权限。\
|
||||
如果选择了“管理员”,则其他的选项会被自动勾上,\
|
||||
同时该用户可以管理其他用户。"
|
||||
profileSettings: 配置文件设置
|
||||
profileSettings: 个人设置
|
||||
ruleExample1: "\
|
||||
阻止用户访问所有文件夹下任何以 . 开头的文件\
|
||||
(隐藏文件, 例如: .git, .gitignore)。"
|
||||
|
||||
@@ -134,7 +134,7 @@ settings:
|
||||
您可以將該使用者設置為管理員,也可以單獨選擇各項權限。\
|
||||
如果選擇了“管理員”,則其他的選項會被自動勾上,\
|
||||
同時該使用者可以管理其他使用者。"
|
||||
profileSettings: 設定檔設定
|
||||
profileSettings: 個人設定
|
||||
ruleExample1: "\
|
||||
封鎖使用者存取所有資料夾下任何以 . 開頭的檔案\
|
||||
(隱藏文件, 例如: .git, .gitignore)。"
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
}
|
||||
body > a h1 {
|
||||
margin-top: .2em;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
28
build.sh
28
build.sh
@@ -1,14 +1,14 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Install rice tool if not present
|
||||
if ! [ -x "$(command -v rice)" ]; then
|
||||
go get github.com/GeertJohan/go.rice/rice
|
||||
fi
|
||||
|
||||
# Clean the dist folder and build the assets
|
||||
rm -rf assets/dist
|
||||
npm run build
|
||||
|
||||
# Embed the assets using rice
|
||||
rice embed-go
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Install rice tool if not present
|
||||
if ! [ -x "$(command -v rice)" ]; then
|
||||
go get github.com/GeertJohan/go.rice/rice
|
||||
fi
|
||||
|
||||
# Clean the dist folder and build the assets
|
||||
rm -rf assets/dist
|
||||
npm run build
|
||||
|
||||
# Embed the assets using rice
|
||||
rice embed-go
|
||||
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
|
||||
const (
|
||||
// Version is the current File Manager version.
|
||||
Version = "1.4.4"
|
||||
Version = "1.4.6"
|
||||
|
||||
ListViewMode = "list"
|
||||
MosaicViewMode = "mosaic"
|
||||
|
||||
@@ -38,10 +38,7 @@ func reCaptcha(secret string, response string) (bool, error) {
|
||||
}
|
||||
|
||||
var data struct {
|
||||
Success bool `json:"success"`
|
||||
ChallengeTS time.Time `json:"challenge_ts"`
|
||||
Hostname string `json:"hostname"`
|
||||
ErrorCodes interface{} `json:"error-codes"`
|
||||
Success bool `json:"success"`
|
||||
}
|
||||
|
||||
err = json.NewDecoder(resp.Body).Decode(&data)
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
@@ -45,72 +43,41 @@ func downloadHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int
|
||||
files = append(files, c.File.Path)
|
||||
}
|
||||
|
||||
// If the format is true, just set it to "zip".
|
||||
if query == "true" || query == "" {
|
||||
query = "zip"
|
||||
}
|
||||
|
||||
var (
|
||||
extension string
|
||||
temp string
|
||||
err error
|
||||
tempfile string
|
||||
ar archiver.Archiver
|
||||
)
|
||||
|
||||
// Create a temporary directory.
|
||||
temp, err = ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
defer os.RemoveAll(temp)
|
||||
|
||||
tempfile = filepath.Join(temp, "temp")
|
||||
|
||||
switch query {
|
||||
case "zip":
|
||||
extension, err = ".zip", archiver.Zip.Make(tempfile, files)
|
||||
// If the format is true, just set it to "zip".
|
||||
case "zip", "true", "":
|
||||
extension, ar = ".zip", archiver.Zip
|
||||
case "tar":
|
||||
extension, err = ".tar", archiver.Tar.Make(tempfile, files)
|
||||
extension, ar = ".tar", archiver.Tar
|
||||
case "targz":
|
||||
extension, err = ".tar.gz", archiver.TarGz.Make(tempfile, files)
|
||||
extension, ar = ".tar.gz", archiver.TarGz
|
||||
case "tarbz2":
|
||||
extension, err = ".tar.bz2", archiver.TarBz2.Make(tempfile, files)
|
||||
extension, ar = ".tar.bz2", archiver.TarBz2
|
||||
case "tarxz":
|
||||
extension, err = ".tar.xz", archiver.TarXZ.Make(tempfile, files)
|
||||
extension, ar = ".tar.xz", archiver.TarXZ
|
||||
default:
|
||||
return http.StatusNotImplemented, nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
|
||||
// Defines the file name.
|
||||
name := c.File.Name
|
||||
if name == "." || name == "" {
|
||||
name = "download"
|
||||
name = "archive"
|
||||
}
|
||||
name += extension
|
||||
|
||||
// Opens the file so it can be downloaded.
|
||||
file, err := os.Open(temp + "/temp")
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
defer file.Close()
|
||||
w.Header().Set("Content-Disposition", "attachment; filename*=utf-8''"+url.QueryEscape(name))
|
||||
err := ar.Write(w, files)
|
||||
|
||||
w.Header().Set("Content-Disposition", "attachment; filename=\""+name+"\"")
|
||||
_, err = io.Copy(w, file)
|
||||
return 0, err
|
||||
}
|
||||
|
||||
func downloadFileHandler(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, error) {
|
||||
if r.URL.Query().Get("inline") == "true" {
|
||||
w.Header().Set("Content-Disposition", "inline")
|
||||
} else {
|
||||
w.Header().Set("Content-Disposition", `attachment; filename="`+c.File.Name+`"`)
|
||||
}
|
||||
|
||||
file, err := os.Open(c.File.Path)
|
||||
defer file.Close()
|
||||
|
||||
@@ -118,10 +85,19 @@ func downloadFileHandler(c *fm.Context, w http.ResponseWriter, r *http.Request)
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
|
||||
_, err = io.Copy(w, file)
|
||||
stat, err := file.Stat()
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
|
||||
if r.URL.Query().Get("inline") == "true" {
|
||||
w.Header().Set("Content-Disposition", "inline")
|
||||
} else {
|
||||
// As per RFC6266 section 4.3
|
||||
w.Header().Set("Content-Disposition", "attachment; filename*=utf-8''"+url.QueryEscape(c.File.Name))
|
||||
}
|
||||
|
||||
http.ServeContent(w, r, stat.Name(), stat.ModTime(), file)
|
||||
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
15
http/http.go
15
http/http.go
@@ -86,7 +86,7 @@ func serve(c *fm.Context, w http.ResponseWriter, r *http.Request) (int, error) {
|
||||
|
||||
// Any other request should show the index.html file.
|
||||
w.Header().Set("x-frame-options", "SAMEORIGIN")
|
||||
w.Header().Set("x-content-type", "nosniff")
|
||||
w.Header().Set("x-content-type-options", "nosniff")
|
||||
w.Header().Set("x-xss-protection", "1; mode=block")
|
||||
|
||||
return renderFile(c, w, "index.html")
|
||||
@@ -223,13 +223,12 @@ func renderFile(c *fm.Context, w http.ResponseWriter, file string) (int, error)
|
||||
w.Header().Set("Content-Type", contentType+"; charset=utf-8")
|
||||
|
||||
data := map[string]interface{}{
|
||||
"BaseURL": c.RootURL(),
|
||||
"NoAuth": c.NoAuth,
|
||||
"Version": fm.Version,
|
||||
"CSS": template.CSS(c.CSS),
|
||||
"ReCaptcha": c.ReCaptchaKey != "" && c.ReCaptchaSecret != "",
|
||||
"ReCaptchaKey": c.ReCaptchaKey,
|
||||
"ReCaptchaSecret": c.ReCaptchaSecret,
|
||||
"BaseURL": c.RootURL(),
|
||||
"NoAuth": c.NoAuth,
|
||||
"Version": fm.Version,
|
||||
"CSS": template.CSS(c.CSS),
|
||||
"ReCaptcha": c.ReCaptchaKey != "" && c.ReCaptchaSecret != "",
|
||||
"ReCaptchaKey": c.ReCaptchaKey,
|
||||
}
|
||||
|
||||
if c.StaticGen != nil {
|
||||
|
||||
@@ -1 +1 @@
|
||||
2ba96e4a87cf7fcd056a9d72052623c5286ec7f1
|
||||
e48e71dd340a2bf3434e06c86032565365132976
|
||||
Reference in New Issue
Block a user