mirror of
https://github.com/pldubouilh/gossa.git
synced 2026-08-29 13:27:02 -04:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
698f3ffaf8 | ||
|
|
dc1011bb5f | ||
|
|
5096f46ba4 | ||
|
|
f77b10d3de | ||
|
|
ccd6ae2bea | ||
|
|
858d30be9b | ||
|
|
0b586c5df9 | ||
|
|
d913176daa | ||
|
|
beac60f3d8 | ||
|
|
da7f60d5fc | ||
|
|
39d2d4b13f | ||
|
|
ec7168e718 | ||
|
|
95f01e47dd | ||
|
|
c9266d8849 | ||
|
|
e257d1145d | ||
|
|
698a418e5d | ||
|
|
e9eb3bf45b |
@@ -7,10 +7,10 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- name: Set up Go 1.13
|
- name: Set up Go 1.12
|
||||||
uses: actions/setup-go@v1
|
uses: actions/setup-go@v1
|
||||||
with:
|
with:
|
||||||
go-version: 1.13
|
go-version: 1.12
|
||||||
id: go
|
id: go
|
||||||
|
|
||||||
- name: Check out code into the Go module directory
|
- name: Check out code into the Go module directory
|
||||||
@@ -19,4 +19,4 @@ jobs:
|
|||||||
submodules: true
|
submodules: true
|
||||||
|
|
||||||
- name: Run
|
- name: Run
|
||||||
run: make test
|
run: make ci
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ gossa-linux-arm
|
|||||||
gossa-linux-arm64
|
gossa-linux-arm64
|
||||||
gossa-mac
|
gossa-mac
|
||||||
gossa-windows.exe
|
gossa-windows.exe
|
||||||
gossa_test.go
|
|
||||||
|
|
||||||
.vscode
|
.vscode
|
||||||
test-fixture/*
|
test-fixture/*
|
||||||
|
|||||||
@@ -6,32 +6,29 @@ build:
|
|||||||
rm gossa.go
|
rm gossa.go
|
||||||
|
|
||||||
run:
|
run:
|
||||||
|
make build
|
||||||
./gossa -verb=true test-fixture
|
./gossa -verb=true test-fixture
|
||||||
|
|
||||||
run-ro:
|
|
||||||
./gossa -verb=true -ro=true test-fixture
|
|
||||||
|
|
||||||
run-extra:
|
run-extra:
|
||||||
|
make build
|
||||||
./gossa -verb=true -prefix="/fancy-path/" -k=false -symlinks=true test-fixture
|
./gossa -verb=true -prefix="/fancy-path/" -k=false -symlinks=true test-fixture
|
||||||
|
|
||||||
test:
|
ci:
|
||||||
make build
|
|
||||||
-rm gossa_test.go
|
|
||||||
-@cd test-fixture && ln -s ../support .
|
-@cd test-fixture && ln -s ../support .
|
||||||
cp src/gossa_test.go .
|
make build
|
||||||
go test
|
timeout 15 make run &
|
||||||
|
sleep 16 && timeout 15 make run-extra &
|
||||||
|
cp src/gossa_test.go . && go test
|
||||||
|
rm gossa_test.go
|
||||||
|
|
||||||
watch:
|
watch:
|
||||||
ls src/* gossa-ui/* | entr -rc make build run
|
ls src/* gossa-ui/* | entr -rc make run
|
||||||
|
|
||||||
watch-extra:
|
watch-extra:
|
||||||
ls src/* gossa-ui/* | entr -rc make build run-extra
|
ls src/* gossa-ui/* | entr -rc make run-extra
|
||||||
|
|
||||||
watch-ro:
|
watch-ci:
|
||||||
ls src/* gossa-ui/* | entr -rc make build run-ro
|
ls src/* gossa-ui/* | entr -rc make ci
|
||||||
|
|
||||||
watch-test:
|
|
||||||
ls src/* gossa-ui/* | entr -rc make test
|
|
||||||
|
|
||||||
build-all:
|
build-all:
|
||||||
cp src/gossa.go gossa.go
|
cp src/gossa.go gossa.go
|
||||||
|
|||||||
+1
-1
Submodule gossa-ui updated: 02cecdcaae...cc8fff1e26
@@ -1,7 +1,7 @@
|
|||||||
gossa
|
gossa
|
||||||
=============
|
=============
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
[](https://github.com/pldubouilh/gossa/actions)
|
[](https://github.com/pldubouilh/gossa/actions)
|
||||||
[](https://hub.docker.com/r/pldubouilh/gossa)
|
[](https://hub.docker.com/r/pldubouilh/gossa)
|
||||||
@@ -14,14 +14,13 @@ a [simple UI](https://github.com/pldubouilh/gossa-ui) comes as default, featurin
|
|||||||
|
|
||||||
* 🔍 files/directories browser
|
* 🔍 files/directories browser
|
||||||
* 📩 drag-and-drop file/directory uploader
|
* 📩 drag-and-drop file/directory uploader
|
||||||
* 🚀 lightweight, default ui weights 110kB and prints in ms
|
|
||||||
* 🗺️ files handling - move/rename/delete
|
* 🗺️ files handling - move/rename/delete
|
||||||
* 📸 picture browser
|
* 📸 picture browser
|
||||||
* 📽️ video streaming
|
* 📽️ video streaming
|
||||||
* ✍️ simple text editor
|
* ✍️ simple text editor
|
||||||
* ⌨️ keyboard shortcuts
|
* ⌨️ keyboard shortcuts
|
||||||
* 🥂 fast golang static server, easily fills available bandwidth
|
* 🥂 speed - will easily fill available bandwidth
|
||||||
* 🔒 easy/secure multi account setup
|
* 🔒 safe - easy/secure multi account setup
|
||||||
|
|
||||||
### build
|
### build
|
||||||
built blobs are available on the [release page](https://github.com/pldubouilh/gossa/releases) - or simply `make build` this repo.
|
built blobs are available on the [release page](https://github.com/pldubouilh/gossa/releases) - or simply `make build` this repo.
|
||||||
|
|||||||
+8
-15
@@ -14,18 +14,17 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var host = flag.String("h", "127.0.0.1", "host to listen to")
|
var host = flag.String("h", "127.0.0.1", "host to listen to")
|
||||||
var port = flag.String("p", "8001", "port to listen to")
|
var port = flag.String("p", "8001", "port to listen to")
|
||||||
|
var history = flag.Bool("history", true, "keep history for paths visited. default location is path/.gossa_history")
|
||||||
var extraPath = flag.String("prefix", "/", "url prefix at which gossa can be reached, e.g. /gossa/ (slashes of importance)")
|
var extraPath = flag.String("prefix", "/", "url prefix at which gossa can be reached, e.g. /gossa/ (slashes of importance)")
|
||||||
var symlinks = flag.Bool("symlinks", false, "follow symlinks \033[4mWARNING\033[0m: symlinks will by nature allow to escape the defined path (default: false)")
|
var symlinks = flag.Bool("symlinks", false, "follow symlinks \033[4mWARNING\033[0m: symlinks will by nature allow to escape the defined path (default: false)")
|
||||||
var verb = flag.Bool("verb", false, "verbosity")
|
var verb = flag.Bool("verb", false, "verbosity")
|
||||||
var skipHidden = flag.Bool("k", true, "\nskip hidden files")
|
var skipHidden = flag.Bool("k", true, "\nskip hidden files")
|
||||||
var ro = flag.Bool("ro", false, "read only mode (no upload, rename, move, etc...)")
|
|
||||||
var initPath = "."
|
var initPath = "."
|
||||||
|
|
||||||
var fs http.Handler
|
var fs http.Handler
|
||||||
@@ -41,7 +40,6 @@ type rowTemplate struct {
|
|||||||
type pageTemplate struct {
|
type pageTemplate struct {
|
||||||
Title template.HTML
|
Title template.HTML
|
||||||
ExtraPath template.HTML
|
ExtraPath template.HTML
|
||||||
Ro bool
|
|
||||||
RowsFiles []rowTemplate
|
RowsFiles []rowTemplate
|
||||||
RowsFolders []rowTemplate
|
RowsFolders []rowTemplate
|
||||||
}
|
}
|
||||||
@@ -79,11 +77,9 @@ func humanize(bytes int64) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func replyList(w http.ResponseWriter, fullPath string, path string) {
|
func replyList(w http.ResponseWriter, r *http.Request, fullPath string, path string) {
|
||||||
_files, err := ioutil.ReadDir(fullPath)
|
_files, err := ioutil.ReadDir(fullPath)
|
||||||
check(err)
|
check(err)
|
||||||
sort.Slice(_files, func(i, j int) bool { return strings.ToLower(_files[i].Name()) < strings.ToLower(_files[j].Name()) })
|
|
||||||
|
|
||||||
if !strings.HasSuffix(path, "/") {
|
if !strings.HasSuffix(path, "/") {
|
||||||
path += "/"
|
path += "/"
|
||||||
}
|
}
|
||||||
@@ -94,7 +90,6 @@ func replyList(w http.ResponseWriter, fullPath string, path string) {
|
|||||||
p.RowsFolders = append(p.RowsFolders, rowTemplate{"../", "../", "", "folder"})
|
p.RowsFolders = append(p.RowsFolders, rowTemplate{"../", "../", "", "folder"})
|
||||||
}
|
}
|
||||||
p.ExtraPath = template.HTML(html.EscapeString(*extraPath))
|
p.ExtraPath = template.HTML(html.EscapeString(*extraPath))
|
||||||
p.Ro = *ro
|
|
||||||
p.Title = template.HTML(html.EscapeString(title))
|
p.Title = template.HTML(html.EscapeString(title))
|
||||||
|
|
||||||
for _, el := range _files {
|
for _, el := range _files {
|
||||||
@@ -110,8 +105,7 @@ func replyList(w http.ResponseWriter, fullPath string, path string) {
|
|||||||
p.RowsFolders = append(p.RowsFolders, rowTemplate{el.Name() + "/", template.HTML(href), "", "folder"})
|
p.RowsFolders = append(p.RowsFolders, rowTemplate{el.Name() + "/", template.HTML(href), "", "folder"})
|
||||||
} else {
|
} else {
|
||||||
sl := strings.Split(el.Name(), ".")
|
sl := strings.Split(el.Name(), ".")
|
||||||
ext := strings.ToLower(sl[len(sl)-1])
|
p.RowsFiles = append(p.RowsFiles, rowTemplate{el.Name(), template.HTML(href), humanize(el.Size()), strings.ToLower(sl[len(sl)-1])})
|
||||||
p.RowsFiles = append(p.RowsFiles, rowTemplate{el.Name(), template.HTML(href), humanize(el.Size()), ext})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +125,7 @@ func doContent(w http.ResponseWriter, r *http.Request) {
|
|||||||
check(errStat)
|
check(errStat)
|
||||||
|
|
||||||
if stat.IsDir() {
|
if stat.IsDir() {
|
||||||
replyList(w, fullPath, path)
|
replyList(w, r, fullPath, path)
|
||||||
} else {
|
} else {
|
||||||
fs.ServeHTTP(w, r)
|
fs.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
@@ -153,6 +147,7 @@ func rpc(w http.ResponseWriter, r *http.Request) {
|
|||||||
bodyBytes, _ := ioutil.ReadAll(r.Body)
|
bodyBytes, _ := ioutil.ReadAll(r.Body)
|
||||||
json.Unmarshal(bodyBytes, &rpc)
|
json.Unmarshal(bodyBytes, &rpc)
|
||||||
defer exitPath(w, "rpc", rpc)
|
defer exitPath(w, "rpc", rpc)
|
||||||
|
ret := "ok"
|
||||||
|
|
||||||
if rpc.Call == "mkdirp" {
|
if rpc.Call == "mkdirp" {
|
||||||
err = os.MkdirAll(checkPath(rpc.Args[0]), os.ModePerm)
|
err = os.MkdirAll(checkPath(rpc.Args[0]), os.ModePerm)
|
||||||
@@ -163,7 +158,7 @@ func rpc(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
check(err)
|
check(err)
|
||||||
w.Write([]byte("ok"))
|
w.Write([]byte(ret))
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkPath(p string) string {
|
func checkPath(p string) string {
|
||||||
@@ -193,10 +188,8 @@ func main() {
|
|||||||
initPath, err = filepath.Abs(initPath)
|
initPath, err = filepath.Abs(initPath)
|
||||||
check(err)
|
check(err)
|
||||||
|
|
||||||
if !*ro {
|
http.HandleFunc(*extraPath+"rpc", rpc)
|
||||||
http.HandleFunc(*extraPath+"rpc", rpc)
|
http.HandleFunc(*extraPath+"post", upload)
|
||||||
http.HandleFunc(*extraPath+"post", upload)
|
|
||||||
}
|
|
||||||
http.HandleFunc("/", doContent)
|
http.HandleFunc("/", doContent)
|
||||||
fs = http.StripPrefix(*extraPath, http.FileServer(http.Dir(initPath)))
|
fs = http.StripPrefix(*extraPath, http.FileServer(http.Dir(initPath)))
|
||||||
fmt.Printf("Gossa startig on directory %s\nListening on http://%s:%s%s\n", initPath, *host, *port, *extraPath)
|
fmt.Printf("Gossa startig on directory %s\nListening on http://%s:%s%s\n", initPath, *host, *port, *extraPath)
|
||||||
|
|||||||
+12
-93
@@ -5,8 +5,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -86,7 +84,7 @@ func fetchAndTestDefault(t *testing.T, url string) string {
|
|||||||
return body0
|
return body0
|
||||||
}
|
}
|
||||||
|
|
||||||
func doTestRegular(t *testing.T, url string, testExtra bool) {
|
func doTest(t *testing.T, url string, testExtra bool) {
|
||||||
var payload, path, body0, body1, body2 string
|
var payload, path, body0, body1, body2 string
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~
|
||||||
@@ -231,99 +229,20 @@ func doTestRegular(t *testing.T, url string, testExtra bool) {
|
|||||||
if body0 != `ok` {
|
if body0 != `ok` {
|
||||||
t.Fatal("cleanup errored #2")
|
t.Fatal("cleanup errored #2")
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("\r\n=========\r\n")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func doTestReadonly(t *testing.T, url string) {
|
func TestGetFolder(t *testing.T) {
|
||||||
var payload, path, body0, body1 string
|
time.Sleep(6 * time.Second)
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~
|
|
||||||
fmt.Println("\r\n~~~~~~~~~~ test fetching default path")
|
|
||||||
fetchAndTestDefault(t, url)
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~
|
|
||||||
fmt.Println("\r\n~~~~~~~~~~ test fetching an invalid path - redirected to root")
|
|
||||||
fetchAndTestDefault(t, url+"../../")
|
|
||||||
fetchAndTestDefault(t, url+"hols/../../")
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~
|
|
||||||
fmt.Println("\r\n~~~~~~~~~~ test fetching regular files")
|
|
||||||
body0 = get(t, url+"subdir_with%20space/file_with%20space.html")
|
|
||||||
body1 = get(t, url+"fancy-path/a")
|
|
||||||
if body0 != `<b>spacious!!</b> ` || body1 != `fancy! ` {
|
|
||||||
t.Fatal("fetching a regular file errored")
|
|
||||||
}
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~
|
|
||||||
fmt.Println("\r\n~~~~~~~~~~ test fetching a invalid file")
|
|
||||||
path = "../../../../../../../../../../etc/passwd"
|
|
||||||
if get(t, url+path) != `error` {
|
|
||||||
t.Fatal("fetching a invalid file didnt errored")
|
|
||||||
}
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~
|
|
||||||
fmt.Println("\r\n~~~~~~~~~~ test mkdir rpc")
|
|
||||||
body0 = postJSON(t, url+"rpc", `{"call":"mkdirp","args":["/AAA"]}`)
|
|
||||||
if body0 == `ok` {
|
|
||||||
t.Fatal("mkdir rpc passed - should not be allowed")
|
|
||||||
}
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~
|
|
||||||
fmt.Println("\r\n~~~~~~~~~~ test post file")
|
|
||||||
path = "%2F%E1%84%92%E1%85%A1%20%E1%84%92%E1%85%A1" // "하 하" encoded
|
|
||||||
payload = "123 하"
|
|
||||||
body0 = postDummyFile(t, url, path, payload)
|
|
||||||
body1 = get(t, url+path)
|
|
||||||
if body0 == `ok` {
|
|
||||||
t.Fatal("post file passed - should not be allowed")
|
|
||||||
}
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~
|
|
||||||
fmt.Println("\r\n~~~~~~~~~~ test mv rpc")
|
|
||||||
body0 = postJSON(t, url+"rpc", `{"call":"mv","args":["/AAA", "/hols/AAA"]}`)
|
|
||||||
body1 = fetchAndTestDefault(t, url)
|
|
||||||
if body0 == `ok` {
|
|
||||||
t.Fatal("mv rpc passed - should not be allowed")
|
|
||||||
}
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~
|
|
||||||
fmt.Println("\r\n~~~~~~~~~~ test rm rpc & cleanup")
|
|
||||||
body0 = postJSON(t, url+"rpc", `{"call":"rm","args":["/hols/AAA"]}`)
|
|
||||||
if body0 == `ok` {
|
|
||||||
t.Fatal("cleanup passed - should not be allowed")
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("\r\n=========\r\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
func startGossa(what string) int {
|
|
||||||
cmd := exec.Command("/usr/bin/make", what)
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stdout
|
|
||||||
cmd.Start()
|
|
||||||
time.Sleep(3 * time.Second)
|
|
||||||
return cmd.Process.Pid
|
|
||||||
}
|
|
||||||
|
|
||||||
func killallgossa() {
|
|
||||||
cmd := exec.Command("/usr/bin/killall", "gossa")
|
|
||||||
cmd.Start()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGossa(t *testing.T) {
|
|
||||||
startGossa("run")
|
|
||||||
fmt.Println("========== testing normal path ============")
|
fmt.Println("========== testing normal path ============")
|
||||||
doTestRegular(t, "http://127.0.0.1:8001/", false)
|
url := "http://127.0.0.1:8001/"
|
||||||
killallgossa()
|
doTest(t, url, false)
|
||||||
|
|
||||||
startGossa("run-extra")
|
fmt.Printf("\r\n=========\r\n")
|
||||||
fmt.Println("========== testing extras options ============")
|
time.Sleep(10 * time.Second)
|
||||||
doTestRegular(t, "http://127.0.0.1:8001/fancy-path/", true)
|
|
||||||
killallgossa()
|
|
||||||
|
|
||||||
startGossa("run-ro")
|
url = "http://127.0.0.1:8001/fancy-path/"
|
||||||
fmt.Println("========== testing read only ============")
|
fmt.Println("========== testing at fancy path ============")
|
||||||
doTestReadonly(t, "http://127.0.0.1:8001/")
|
doTest(t, url, true)
|
||||||
killallgossa()
|
|
||||||
|
fmt.Printf("\r\n=========\r\n")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user