diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 7c2b915..0000000 --- a/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: go -go: - - "1.10" -script: - - make ci diff --git a/Makefile b/Makefile index f83cf95..c6aaa18 100755 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ run-extra: ./gossa -prefix="/fancy-path/" -symlinks=true test-fixture ci: - -@cd test-fixture && ln -s ../docker . + -@cd test-fixture && ln -s ../support . make build timeout 10 make run & sleep 11 && timeout 10 make run-extra & diff --git a/docker/caddy.Dockerfile b/docker/caddy.Dockerfile deleted file mode 100644 index 9571656..0000000 --- a/docker/caddy.Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -FROM alpine - -# download and prepare caddy -RUN apk update && apk add curl ca-certificates -RUN curl -L -o caddy.tar.gz "https://github.com/mholt/caddy/releases/download/v0.11.1/caddy_v0.11.1_linux_amd64.tar.gz" -RUN tar xvzf caddy.tar.gz && mv caddy /caddy - -# download and prepare gossa -RUN curl -L -o /gossa "https://github.com/pldubouilh/gossa/releases/download/v0.0.7/gossa-linux64" -RUN chmod +x /gossa /caddy - -# Caddy config: -# * http basic auth is implemented here, with bob as user and dylan as password -# * to enable https just set a valid domain instead of *:8001 - how simple ! -RUN echo -e '\n\ - *:8001\n\ - basicauth / bob dylan\n\ - proxy / 127.0.0.1:8000\n\ -'>> /Caddyfile - -RUN echo -e '/gossa -h 127.0.0.1 -p 8000 /shared & \n /caddy'>> /start.sh -ENTRYPOINT [ "sh", "/start.sh" ] diff --git a/docker/download.Dockerfile b/docker/download.Dockerfile deleted file mode 100644 index 62c66c7..0000000 --- a/docker/download.Dockerfile +++ /dev/null @@ -1,5 +0,0 @@ -FROM alpine -EXPOSE 8001 -RUN wget https://github.com/pldubouilh/gossa/releases/download/v0.0.7/gossa-linux64 && mv gossa-linux64 /gossa && chmod +x /gossa -ENTRYPOINT [ "/gossa", "-h", "0.0.0.0", "/shared" ] - diff --git a/gossa-ui b/gossa-ui index 1a8e83c..794fa10 160000 --- a/gossa-ui +++ b/gossa-ui @@ -1 +1 @@ -Subproject commit 1a8e83cc7a82ecdb3595c9dabbbd0374605c990d +Subproject commit 794fa1028d5c10b525142261abdf2c4c1e4cf19a diff --git a/readme.md b/readme.md index b92ecb7..2dafacd 100644 --- a/readme.md +++ b/readme.md @@ -1,14 +1,14 @@ gossa ============= -![e](https://user-images.githubusercontent.com/760637/52522293-942fa880-2c83-11e9-9f79-0a5b922bcc7f.gif) +![e](https://user-images.githubusercontent.com/760637/64459310-e0e34100-d0f7-11e9-9248-13163bed1696.gif) -[![build status](https://img.shields.io/travis/pldubouilh/gossa.svg?logo=travis)](https://travis-ci.org/pldubouilh/gossa) +[![build status](https://github.com/pldubouilh/gossa/workflows/Go/badge.svg)](https://github.com/pldubouilh/gossa/actions) [![docker build status](https://img.shields.io/docker/cloud/build/pldubouilh/gossa.svg?logo=docker)](https://hub.docker.com/r/pldubouilh/gossa) [![docker pulls](https://img.shields.io/docker/pulls/pldubouilh/gossa.svg?logo=docker)](https://hub.docker.com/r/pldubouilh/gossa) [![github downloads](https://img.shields.io/github/downloads/pldubouilh/gossa/total.svg?logo=github)](https://github.com/pldubouilh/gossa/releases) -a fast and simple webserver for your files, that's dependency-free and with under 200 lines of code, easy to review. +a fast and simple webserver for your files, that's dependency-free and with 200 lines of code, easy to review. a [simple UI](https://github.com/pldubouilh/gossa-ui) comes as default, featuring : @@ -16,13 +16,14 @@ a [simple UI](https://github.com/pldubouilh/gossa-ui) comes as default, featurin * πŸ“© drag-and-drop file/directory uploader * πŸ—ΊοΈ files handling - move/rename/delete * πŸ“Έ picture browser - * πŸ“½οΈ video streaming from the browser + * πŸ“½οΈ video streaming * ✍️ simple text editor * ⌨️ keyboard shortcuts - * πŸ₯‚ speed - showed rates above 100MB/s + * πŸ₯‚ speed - will easily fill available bandwidth + * πŸ”’ safe - easy/secure multi account setup ### 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. ### usage ```sh @@ -31,6 +32,16 @@ built blobs are available on the [release page](https://github.com/pldubouilh/go % ./gossa -h 192.168.100.33 ~/storage ``` +### fancier setups +release images are pushed to [dockerhub](https://hub.docker.com/r/pldubouilh/gossa), e.g. : + +```sh +# pull from dockerhub and run +% sudo docker run -v ~/LocalDirToShare:/shared -p 8001:8001 pldubouilh/gossa +``` + +in a do-one-thing-well mindset, HTTPS and authentication has been left to middlewares and proxies. for instance [caddy](https://caddyserver.com/) handles this very well - have a look at this small [caddy config](https://github.com/pldubouilh/gossa/blob/master/support/Caddyfile) with authentication and option for HTTPS that works along with gossa. + ### ui shortcuts |shortcut | action| | ------------- |-------------| @@ -54,10 +65,3 @@ built blobs are available on the [release page](https://github.com/pldubouilh/go |Ctrl/Meta + V | paste previously selected paths to directory| |\ | search| -### using with docker -a few docker/docker-compose files are provided in the [docker folder](https://github.com/pldubouilh/gossa/tree/master/docker). release images are also pushed to [dockerhub](https://hub.docker.com/r/pldubouilh/gossa), e.g. : - -```sh -# pull from dockerhub and run -% sudo docker run -v ~/LocalDirToShare:/shared -p 8001:8001 pldubouilh/gossa -``` diff --git a/src/gossa.go b/src/gossa.go index 4fceb93..da85dc9 100755 --- a/src/gossa.go +++ b/src/gossa.go @@ -20,12 +20,14 @@ import ( var host = flag.String("h", "127.0.0.1", "host 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 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", true, "verbosity") var skipHidden = flag.Bool("k", true, "skip hidden files") var initPath = "." - +var historyPath = "" +var state = make(map[string]string) var fs http.Handler var page, _ = template.New("pageTemplate").Parse(`template_will_be_here`) @@ -38,6 +40,7 @@ type rowTemplate struct { type pageTemplate struct { Title template.HTML + State template.HTML ExtraPath template.HTML RowsFiles []rowTemplate RowsFolders []rowTemplate @@ -75,7 +78,7 @@ 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) check(err) @@ -90,6 +93,7 @@ func replyList(w http.ResponseWriter, fullPath string, path string) { } p.ExtraPath = template.HTML(html.EscapeString(*extraPath)) p.Title = template.HTML(html.EscapeString(title)) + p.State = template.HTML(html.EscapeString(state[r.Header.Get("Authorization")+path])) for _, el := range _files { if *skipHidden && strings.HasPrefix(el.Name(), ".") { @@ -125,7 +129,7 @@ func doContent(w http.ResponseWriter, r *http.Request) { check(errStat) if stat.IsDir() { - replyList(w, fullPath, path) + replyList(w, r, fullPath, path) } else { fs.ServeHTTP(w, r) } @@ -154,6 +158,10 @@ func rpc(w http.ResponseWriter, r *http.Request) { err = os.Rename(checkPath(rpc.Args[0]), checkPath(rpc.Args[1])) } else if rpc.Call == "rm" { err = os.RemoveAll(checkPath(rpc.Args[0])) + } else if rpc.Call == "history" && *history { + state[r.Header.Get("Authorization")+rpc.Args[0]] = rpc.Args[1] + f, _ := json.MarshalIndent(state, "", " ") + ioutil.WriteFile(historyPath, f, 0644) } check(err) @@ -173,23 +181,27 @@ func checkPath(p string) string { } func main() { + var err error + flag.Usage = func() { + fmt.Printf("\nusage: ./gossa ~/directory-to-share\n\n") + flag.PrintDefaults() + } flag.Parse() if len(flag.Args()) > 0 { initPath = flag.Args()[0] } - var err error + historyPath = filepath.Join(initPath, ".gossa_history") + h, _ := ioutil.ReadFile(historyPath) + _ = json.Unmarshal(h, &state) initPath, err = filepath.Abs(initPath) check(err) - hostString := *host + ":" + *port - fmt.Println("Gossa startig on directory " + initPath) - fmt.Println("Listening on http://" + hostString + *extraPath) - http.HandleFunc(*extraPath+"rpc", rpc) http.HandleFunc(*extraPath+"post", upload) http.HandleFunc("/", doContent) fs = http.StripPrefix(*extraPath, http.FileServer(http.Dir(initPath))) - err = http.ListenAndServe(hostString, nil) + fmt.Printf("Gossa startig on directory %s\nListening on http://%s:%s%s\n", initPath, *host, *port, *extraPath) + err = http.ListenAndServe(*host+":"+*port, nil) check(err) } diff --git a/src/gossa_test.go b/src/gossa_test.go index 8847794..5a105f3 100644 --- a/src/gossa_test.go +++ b/src/gossa_test.go @@ -102,7 +102,6 @@ func doTest(t *testing.T, url string, symlinkEnabled bool) { fmt.Println("\r\n~~~~~~~~~~ test fetching regular files") bodyStr = get(t, url+"subdir_with%20space/file_with%20space.html") bodyStr2 := get(t, url+"fancy-path/a") - fmt.Println(bodyStr2) if !strings.Contains(bodyStr, `spacious!!`) || !strings.Contains(bodyStr2, `fancy!`) { t.Fatal("fetching a regular file errored") } @@ -191,7 +190,7 @@ func doTest(t *testing.T, url string, symlinkEnabled bool) { // ~~~~~~~~~~~~~~~~~ fmt.Println("\r\n~~~~~~~~~~ test symlink, should succeed: ", symlinkEnabled) - bodyStr = get(t, url+"/docker/readme.md") + bodyStr = get(t, url+"/support/readme.md") hasReadme := strings.Contains(bodyStr, `the master branch is automatically built and pushed`) if !symlinkEnabled && hasReadme { t.Fatal("error symlink reached where illegal") @@ -201,7 +200,7 @@ func doTest(t *testing.T, url string, symlinkEnabled bool) { if symlinkEnabled { fmt.Println("\r\n~~~~~~~~~~ test symlink mkdir") - bodyStr = postJSON(t, url+"rpc", `{"call":"mkdirp","args":["/docker/testfolder"]}`) + bodyStr = postJSON(t, url+"rpc", `{"call":"mkdirp","args":["/support/testfolder"]}`) if !strings.Contains(bodyStr, `ok`) { t.Fatal("error symlink mkdir") } @@ -225,7 +224,7 @@ func doTest(t *testing.T, url string, symlinkEnabled bool) { } if symlinkEnabled { - bodyStr = postJSON(t, url+"rpc", `{"call":"rm","args":["/docker/testfolder"]}`) + bodyStr = postJSON(t, url+"rpc", `{"call":"rm","args":["/support/testfolder"]}`) if !strings.Contains(bodyStr, `ok`) { t.Fatal("error symlink rm") } diff --git a/support/Caddyfile b/support/Caddyfile new file mode 100644 index 0000000..1646770 --- /dev/null +++ b/support/Caddyfile @@ -0,0 +1,8 @@ +# Caddy config +# to enable https just set a valid/reachable domain instead of *:8002 - how simple ! +# authentication has been setup with 2 users, alice and bob + +*:8002 +basicauth / alice paul +basicauth / bob dylan +proxy / 127.0.0.1:8001 \ No newline at end of file diff --git a/docker/build.Dockerfile b/support/build.Dockerfile similarity index 100% rename from docker/build.Dockerfile rename to support/build.Dockerfile diff --git a/support/caddy.Dockerfile b/support/caddy.Dockerfile new file mode 100644 index 0000000..238851b --- /dev/null +++ b/support/caddy.Dockerfile @@ -0,0 +1,11 @@ +FROM pldubouilh/gossa + +# download and prepare caddy +RUN apk update && apk add curl ca-certificates +RUN curl -L -o caddy.tar.gz "https://github.com/caddyserver/caddy/releases/download/v1.0.3/caddy_v1.0.3_linux_amd64.tar.gz" +RUN tar xvzf caddy.tar.gz && mv caddy /caddy + +COPY Caddyfile / + +RUN echo -e '/gossa -h 127.0.0.1 /shared & \n /caddy'>> /start.sh +ENTRYPOINT [ "sh", "/start.sh" ] diff --git a/docker/docker-compose.yml b/support/docker-compose.yml similarity index 100% rename from docker/docker-compose.yml rename to support/docker-compose.yml diff --git a/docker/readme.md b/support/readme.md similarity index 84% rename from docker/readme.md rename to support/readme.md index 3ec07b1..1fcee4e 100644 --- a/docker/readme.md +++ b/support/readme.md @@ -9,7 +9,7 @@ if you prefer building the image yourself : ```sh # build gossa within a build container, needs to be ran within the sources, ../ from here -% docker build -t gossa -f docker/build.Dockerfile . +% docker build -t gossa -f support/build.Dockerfile . # and to run it simply % sudo docker run -v ~/LocalDirToShare:/shared -p 8001:8001 gossa @@ -20,10 +20,10 @@ a fancy docker image using [Caddy](https://caddyserver.com/) is also provided. a ```sh # run with caddy, checkout the config in the dockerfile -% docker build -t gossa -f caddy.Dockerfile . +% docker build -t gossa-caddy -f caddy.Dockerfile . # run with caddy -% sudo docker run -v ~/LocalDirToShare:/shared --net=host gossa +% sudo docker run -v ~/LocalDirToShare:/shared --net=host gossa-caddy ``` a docker-compose example image is also provided. running docker compose should be straightforward : `docker-compose up .` have a look in `docker-compose.yml` for further configuration. \ No newline at end of file