hash state

This commit is contained in:
Pierre Dubouilh
2019-09-07 11:47:41 +02:00
parent 698a418e5d
commit e257d1145d
3 changed files with 61 additions and 31 deletions
+2 -2
View File
@@ -7,11 +7,11 @@ build:
run: run:
make build make build
./gossa test-fixture ./gossa -verb=true test-fixture
run-extra: run-extra:
make build make build
./gossa -prefix="/fancy-path/" -symlinks=true test-fixture ./gossa -verb=true -prefix="/fancy-path/" -symlinks=true test-fixture
ci: ci:
-@cd test-fixture && ln -s ../support . -@cd test-fixture && ln -s ../support .
+21 -15
View File
@@ -1,6 +1,7 @@
package main package main
import ( import (
"crypto/sha256"
"encoding/json" "encoding/json"
"errors" "errors"
"flag" "flag"
@@ -23,7 +24,7 @@ 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 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", true, "verbosity") var verb = flag.Bool("verb", false, "verbosity")
var skipHidden = flag.Bool("k", true, "skip hidden files") var skipHidden = flag.Bool("k", true, "skip hidden files")
var initPath = "." var initPath = "."
var historyPath = "" var historyPath = ""
@@ -32,15 +33,15 @@ var fs http.Handler
var page, _ = template.New("pageTemplate").Parse(`template_will_be_here`) var page, _ = template.New("pageTemplate").Parse(`template_will_be_here`)
type rowTemplate struct { type rowTemplate struct {
Name string Name string
Href template.HTML Href template.HTML
Size string Size string
Ext string Ext string
Selected bool
} }
type pageTemplate struct { type pageTemplate struct {
Title template.HTML Title template.HTML
State template.HTML
ExtraPath template.HTML ExtraPath template.HTML
RowsFiles []rowTemplate RowsFiles []rowTemplate
RowsFolders []rowTemplate RowsFolders []rowTemplate
@@ -57,6 +58,10 @@ func check(e error) {
} }
} }
func hash(s string) string {
return fmt.Sprintf("%x", sha256.Sum256([]byte(s)))
}
func exitPath(w http.ResponseWriter, s ...interface{}) { func exitPath(w http.ResponseWriter, s ...interface{}) {
if r := recover(); r != nil { if r := recover(); r != nil {
log.Println("error", s, r) log.Println("error", s, r)
@@ -81,7 +86,6 @@ func humanize(bytes int64) string {
func replyList(w http.ResponseWriter, r *http.Request, 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)
if !strings.HasSuffix(path, "/") { if !strings.HasSuffix(path, "/") {
path += "/" path += "/"
} }
@@ -89,11 +93,11 @@ func replyList(w http.ResponseWriter, r *http.Request, fullPath string, path str
title := "/" + strings.TrimPrefix(path, *extraPath) title := "/" + strings.TrimPrefix(path, *extraPath)
p := pageTemplate{} p := pageTemplate{}
if path != *extraPath { if path != *extraPath {
p.RowsFolders = append(p.RowsFolders, rowTemplate{"../", "../", "", "folder"}) p.RowsFolders = append(p.RowsFolders, rowTemplate{"../", "../", "", "folder", false})
} }
p.ExtraPath = template.HTML(html.EscapeString(*extraPath)) p.ExtraPath = template.HTML(html.EscapeString(*extraPath))
p.Title = template.HTML(html.EscapeString(title)) p.Title = template.HTML(html.EscapeString(title))
p.State = template.HTML(html.EscapeString(state[r.Header.Get("Authorization")+path])) loc := state[hash(r.Header.Get("Authorization")+path)]
for _, el := range _files { for _, el := range _files {
if *skipHidden && strings.HasPrefix(el.Name(), ".") { if *skipHidden && strings.HasPrefix(el.Name(), ".") {
@@ -105,11 +109,10 @@ func replyList(w http.ResponseWriter, r *http.Request, fullPath string, path str
href = strings.Replace(href, "/", "", 1) href = strings.Replace(href, "/", "", 1)
} }
if el.IsDir() { if el.IsDir() {
p.RowsFolders = append(p.RowsFolders, rowTemplate{el.Name() + "/", template.HTML(href), "", "folder"}) p.RowsFolders = append(p.RowsFolders, rowTemplate{el.Name() + "/", template.HTML(href), "", "folder", loc == hash(el.Name()+"/")})
} 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]), loc == hash(el.Name())})
p.RowsFiles = append(p.RowsFiles, rowTemplate{el.Name(), template.HTML(href), humanize(el.Size()), ext})
} }
} }
@@ -151,6 +154,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)
@@ -158,14 +162,16 @@ func rpc(w http.ResponseWriter, r *http.Request) {
err = os.Rename(checkPath(rpc.Args[0]), checkPath(rpc.Args[1])) err = os.Rename(checkPath(rpc.Args[0]), checkPath(rpc.Args[1]))
} else if rpc.Call == "rm" { } else if rpc.Call == "rm" {
err = os.RemoveAll(checkPath(rpc.Args[0])) err = os.RemoveAll(checkPath(rpc.Args[0]))
} else if rpc.Call == "history" && *history { } else if rpc.Call == "historySet" && *history {
state[r.Header.Get("Authorization")+rpc.Args[0]] = rpc.Args[1] state[hash(r.Header.Get("Authorization")+rpc.Args[0])] = rpc.Args[1] // first arg is always hashed (url), second is hashed on the browser depending on payload
f, _ := json.MarshalIndent(state, "", " ") f, _ := json.MarshalIndent(state, "", " ")
ioutil.WriteFile(historyPath, f, 0644) ioutil.WriteFile(historyPath, f, 0644)
} else if rpc.Call == "historyGet" && *history {
ret = state[hash(r.Header.Get("Authorization")+rpc.Args[0])]
} }
check(err) check(err)
w.Write([]byte("ok")) w.Write([]byte(ret))
} }
func checkPath(p string) string { func checkPath(p string) string {
+38 -14
View File
@@ -116,7 +116,7 @@ func doTest(t *testing.T, url string, symlinkEnabled bool) {
// ~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~
fmt.Println("\r\n~~~~~~~~~~ test mkdir rpc") fmt.Println("\r\n~~~~~~~~~~ test mkdir rpc")
bodyStr = postJSON(t, url+"rpc", `{"call":"mkdirp","args":["/AAA"]}`) bodyStr = postJSON(t, url+"rpc", `{"call":"mkdirp","args":["/AAA"]}`)
if !strings.Contains(bodyStr, `ok`) { if bodyStr != `ok` {
t.Fatal("mkdir rpc errored") t.Fatal("mkdir rpc errored")
} }
@@ -142,7 +142,7 @@ func doTest(t *testing.T, url string, symlinkEnabled bool) {
path = "%2F%E1%84%92%E1%85%A1%20%E1%84%92%E1%85%A1" // "하 하" encoded path = "%2F%E1%84%92%E1%85%A1%20%E1%84%92%E1%85%A1" // "하 하" encoded
payload = "123 하" payload = "123 하"
bodyStr = postDummyFile(t, url, path, payload) bodyStr = postDummyFile(t, url, path, payload)
if !strings.Contains(bodyStr, `ok`) { if bodyStr != `ok` {
t.Fatal("post file errored") t.Fatal("post file errored")
} }
@@ -166,7 +166,7 @@ func doTest(t *testing.T, url string, symlinkEnabled bool) {
// ~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~
fmt.Println("\r\n~~~~~~~~~~ test mv rpc") fmt.Println("\r\n~~~~~~~~~~ test mv rpc")
bodyStr = postJSON(t, url+"rpc", `{"call":"mv","args":["/AAA", "/hols/AAA"]}`) bodyStr = postJSON(t, url+"rpc", `{"call":"mv","args":["/AAA", "/hols/AAA"]}`)
if !strings.Contains(bodyStr, `ok`) { if bodyStr != `ok` {
t.Fatal("mv rpc errored") t.Fatal("mv rpc errored")
} }
@@ -175,6 +175,19 @@ func doTest(t *testing.T, url string, symlinkEnabled bool) {
t.Fatal("mv rpc folder not moved") t.Fatal("mv rpc folder not moved")
} }
// ~~~~~~~~~~~~~~~~~
// Test where auth header unset, otherwise it'd be apended to the first arg
fmt.Println("\r\n~~~~~~~~~~ test history rpc")
bodyStr = postJSON(t, url+"rpc", `{"call":"historySet","args":["a", "123"]}`)
if bodyStr != `ok` {
t.Fatal("mv rpc errored")
}
bodyStr = postJSON(t, url+"rpc", `{"call":"historyGet","args":["a"]}`)
if bodyStr != `123` {
t.Fatal("error historyGet")
}
// ~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~
fmt.Println("\r\n~~~~~~~~~~ test upload in new folder") fmt.Println("\r\n~~~~~~~~~~ test upload in new folder")
payload = "abcdef1234" payload = "abcdef1234"
@@ -199,17 +212,35 @@ func doTest(t *testing.T, url string, symlinkEnabled bool) {
} }
if symlinkEnabled { if symlinkEnabled {
fmt.Println("\r\n~~~~~~~~~~ test symlink mkdir") fmt.Println("\r\n~~~~~~~~~~ test symlink mkdir & cleanup")
bodyStr = postJSON(t, url+"rpc", `{"call":"mkdirp","args":["/support/testfolder"]}`) bodyStr = postJSON(t, url+"rpc", `{"call":"mkdirp","args":["/support/testfolder"]}`)
if !strings.Contains(bodyStr, `ok`) { if bodyStr != `ok` {
t.Fatal("error symlink mkdir") t.Fatal("error symlink mkdir")
} }
bodyStr = postJSON(t, url+"rpc", `{"call":"rm","args":["/support/testfolder"]}`)
if bodyStr != `ok` {
t.Fatal("error symlink rm")
}
}
//
fmt.Println("\r\n~~~~~~~~~~ test upload in new folder")
payload = "abcdef1234"
bodyStr = postDummyFile(t, url, "%2Fhols%2FAAA%2Fabcdef", payload)
if strings.Contains(bodyStr, `err`) {
t.Fatal("upload in new folder errored")
}
bodyStr = get(t, url+"hols/AAA/abcdef")
if !strings.Contains(bodyStr, payload) {
t.Fatal("upload in new folder error reaching new file")
} }
// ~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~
fmt.Println("\r\n~~~~~~~~~~ test rm rpc & cleanup") fmt.Println("\r\n~~~~~~~~~~ test rm rpc & cleanup")
bodyStr = postJSON(t, url+"rpc", `{"call":"rm","args":["/hols/AAA"]}`) bodyStr = postJSON(t, url+"rpc", `{"call":"rm","args":["/hols/AAA"]}`)
if !strings.Contains(bodyStr, `ok`) { if bodyStr != `ok` {
t.Fatal("cleanup errored #0") t.Fatal("cleanup errored #0")
} }
@@ -219,16 +250,9 @@ func doTest(t *testing.T, url string, symlinkEnabled bool) {
} }
bodyStr = postJSON(t, url+"rpc", `{"call":"rm","args":["/하 하"]}`) bodyStr = postJSON(t, url+"rpc", `{"call":"rm","args":["/하 하"]}`)
if !strings.Contains(bodyStr, `ok`) { if bodyStr != `ok` {
t.Fatal("cleanup errored #2") t.Fatal("cleanup errored #2")
} }
if symlinkEnabled {
bodyStr = postJSON(t, url+"rpc", `{"call":"rm","args":["/support/testfolder"]}`)
if !strings.Contains(bodyStr, `ok`) {
t.Fatal("error symlink rm")
}
}
} }
func TestGetFolder(t *testing.T) { func TestGetFolder(t *testing.T) {