diff options
author | Antoni Sawicki <tenox@google.com> | 2022-05-25 02:27:00 -0700 |
---|---|---|
committer | Antoni Sawicki <tenox@google.com> | 2022-05-25 02:27:00 -0700 |
commit | 31a4d39d896040f691a42a0032cb6234edd6fe31 (patch) | |
tree | cc63ab939149aaa716618f4ee610c3fb05e4aae0 | |
parent | 27ee2d582eb2551c2799f631819d3ceaecc696a2 (diff) | |
download | wfm-31a4d39d896040f691a42a0032cb6234edd6fe31.tar.gz |
remove full filepath standardise on dir+file
-rw-r--r-- | TODO.md | 3 | ||||
-rw-r--r-- | dialogs.go | 23 | ||||
-rw-r--r-- | dir.go | 12 | ||||
-rw-r--r-- | fileio.go | 69 | ||||
-rw-r--r-- | handlers.go | 33 |
5 files changed, 66 insertions, 74 deletions
@@ -29,9 +29,8 @@ https://github.com/crazcalm/go/commit/8b0b644cd02c59fe2461908304c44d64e8be431e * html as template ## File IO -* basename/clean paths in mulf, dst -* remove uFp, there should be always uDir and uBn * deniedPfx should be fired in handlers not in fileio??? + this may be superseded by docker virtual path * file search function * path prefix, required for docker * path prefix per user @@ -5,7 +5,6 @@ import ( "html" "io/ioutil" "os" - "path/filepath" "runtime" "github.com/dustin/go-humanize" @@ -41,14 +40,14 @@ func (r wfmRequest) prompt(action string, mul []string) { <INPUT TYPE="TEXT" NAME="url" SIZE="40" VALUE=""> `)) case "rename": - eBn := html.EscapeString(r.uBn) + eBn := html.EscapeString(r.uFbn) r.w.Write([]byte(` <BR>Enter new name for the file <B>` + eBn + `</B>:<P> <INPUT TYPE="TEXT" NAME="dst" SIZE="40" VALUE="` + eBn + `"> <INPUT TYPE="HIDDEN" NAME="file" VALUE="` + eBn + `"> `)) case "move": - eBn := html.EscapeString(r.uBn) + eBn := html.EscapeString(r.uFbn) r.w.Write([]byte(` <BR>Select destination folder for <B>` + eBn + `</B>:<P> <SELECT NAME="dst"> @@ -57,13 +56,13 @@ func (r wfmRequest) prompt(action string, mul []string) { `)) case "delete": var a string - fi, _ := os.Stat(r.uDir + "/" + r.uBn) + fi, _ := os.Stat(r.uDir + "/" + r.uFbn) if fi.IsDir() { a = "directory - recursively" } else { a = "file, size " + humanize.Bytes(uint64(fi.Size())) } - eBn := html.EscapeString(r.uBn) + eBn := html.EscapeString(r.uFbn) r.w.Write([]byte(` <BR>Are you sure you want to delete:<BR><B>` + eBn + `</B> (` + a + `)<P> @@ -81,7 +80,7 @@ func (r wfmRequest) prompt(action string, mul []string) { fmt.Fprintf(r.w, " <BR>Move from: <B>%v</B><P>\n"+ "To: <SELECT NAME=\"dst\">%v</SELECT><P>\n<UL>Items:<P>\n", html.EscapeString(r.uDir), - upDnDir(r.uDir, r.uBn), + upDnDir(r.uDir, r.uFbn), ) for _, f := range mul { fE := html.EscapeString(f) @@ -108,8 +107,7 @@ func (r wfmRequest) prompt(action string, mul []string) { } func (r wfmRequest) editText() { - uFilePath := r.uFp // TODO(tenox): uDir + uBn - fi, err := os.Stat(uFilePath) + fi, err := os.Stat(r.uDir + "/" + r.uFbn) if err != nil { htErr(r.w, "Unable to get file attributes", err) return @@ -118,16 +116,16 @@ func (r wfmRequest) editText() { htErr(r.w, "edit", fmt.Errorf("the file is too large for editing")) return } - f, err := ioutil.ReadFile(uFilePath) + f, err := ioutil.ReadFile(r.uDir + "/" + r.uFbn) if err != nil { htErr(r.w, "Unable to read file", err) return } - header(r.w, filepath.Dir(uFilePath), r.eSort, `html, body, table, textarea, form { box-sizing: border-box; height:98%; }`) + header(r.w, r.uDir, r.eSort, `html, body, table, textarea, form { box-sizing: border-box; height:98%; }`) r.w.Write([]byte(` <TABLE BGCOLOR="#EEEEEE" BORDER="0" CELLSPACING="0" CELLPADDING="5" STYLE="width: 100%; height: 100%;"> <TR STYLE="height:1%;"> - <TD ALIGN="LEFT" VALIGN="MIDDLE" BGCOLOR="#CCCCCC">File Editor: ` + html.EscapeString(filepath.Base(uFilePath)) + `</TD> + <TD ALIGN="LEFT" VALIGN="MIDDLE" BGCOLOR="#CCCCCC">File Editor: ` + html.EscapeString(r.uFbn) + `</TD> <TD BGCOLOR="#CCCCCC" ALIGN="RIGHT"> </TD> </TR> <TR STYLE="height:99%;"> @@ -135,7 +133,8 @@ func (r wfmRequest) editText() { <TEXTAREA NAME="text" SPELLCHECK="false" COLS="80" ROWS="24" STYLE="width: 99%; height: 99%;">` + html.EscapeString(string(f)) + `</TEXTAREA><P> <INPUT TYPE="SUBMIT" NAME="save" VALUE="Save" STYLE="float: left;"> <INPUT TYPE="SUBMIT" NAME="cancel" VALUE="Cancel" STYLE="float: left; margin-left: 10px"> - <INPUT TYPE="HIDDEN" NAME="fp" VALUE="` + html.EscapeString(uFilePath) + `"> + <INPUT TYPE="HIDDEN" NAME="dir" VALUE="` + html.EscapeString(r.uDir) + `"> + <INPUT TYPE="HIDDEN" NAME="file" VALUE="` + html.EscapeString(r.uFbn) + `"> </TD></TR></TABLE> `)) footer(r.w) @@ -29,7 +29,7 @@ func (r wfmRequest) listFiles(hi string) { sortFiles(d, &sl, r.eSort) header(r.w, r.uDir, r.eSort, "") - toolbars(r.w, r.uDir, r.user, sl, i) + toolbars(r.w, r.uDir, r.userName, sl, i) qeDir := url.QueryEscape(r.uDir) z := 0 @@ -74,7 +74,7 @@ func (r wfmRequest) listFiles(hi string) { <TD NOWRAP> </TD> <TD NOWRAP ALIGN="right">(` + humanize.Time(f.ModTime()) + `) ` + f.ModTime().Format(time.Stamp) + `</TD> <TD NOWRAP ALIGN="right"> - <A HREF="` + *wfmPfx + `?fn=renp&dir=` + qeDir + `&oldf=` + qeFile + `&sort=` + r.eSort + `">` + i["re"] + `</A> + <A HREF="` + *wfmPfx + `?fn=renp&dir=` + qeDir + `&file=` + qeFile + `&sort=` + r.eSort + `">` + i["re"] + `</A> <A HREF="` + *wfmPfx + `?fn=movp&dir=` + qeDir + `&file=` + qeFile + `&sort=` + r.eSort + `">` + i["mv"] + `</A> <A HREF="` + *wfmPfx + `?fn=delp&dir=` + qeDir + `&file=` + qeFile + `&sort=` + r.eSort + `">` + i["rm"] + `</A> </TD> @@ -116,14 +116,14 @@ func (r wfmRequest) listFiles(hi string) { r.w.Write([]byte(` <TD NOWRAP ALIGN="LEFT"> <INPUT TYPE="CHECKBOX" NAME="mulf" VALUE="` + heFile + `"> - <A HREF="` + *wfmPfx + `?fn=disp&fp=` + qeDir + "/" + qeFile + `">` + fileIcon(qeFile, r.modern) + ` ` + heFile + `</A>` + li + ` + <A HREF="` + *wfmPfx + `?fn=disp&dir=` + qeDir + `&file=` + qeFile + `">` + fileIcon(qeFile, r.modern) + ` ` + heFile + `</A>` + li + ` </TD> <TD NOWRAP ALIGN="right">` + humanize.Bytes(uint64(f.Size())) + `</TD> <TD NOWRAP ALIGN="right">(` + humanize.Time(f.ModTime()) + `) ` + f.ModTime().Format(time.Stamp) + `</TD> <TD NOWRAP ALIGN="right"> - <A HREF="` + *wfmPfx + `?fn=down&fp=` + qeDir + "/" + qeFile + `">` + i["dn"] + `</A> - <A HREF="` + *wfmPfx + `?fn=edit&fp=` + qeDir + "/" + qeFile + `&sort=` + r.eSort + `">` + i["ed"] + `</A> - <A HREF="` + *wfmPfx + `?fn=renp&dir=` + qeDir + `&oldf=` + qeFile + `&sort=` + r.eSort + `">` + i["re"] + `</A> + <A HREF="` + *wfmPfx + `?fn=down&dir=` + qeDir + `&file=` + qeFile + `">` + i["dn"] + `</A> + <A HREF="` + *wfmPfx + `?fn=edit&dir=` + qeDir + `&file=` + qeFile + `&sort=` + r.eSort + `">` + i["ed"] + `</A> + <A HREF="` + *wfmPfx + `?fn=renp&dir=` + qeDir + `&file=` + qeFile + `&sort=` + r.eSort + `">` + i["re"] + `</A> <A HREF="` + *wfmPfx + `?fn=movp&dir=` + qeDir + `&file=` + qeFile + `&sort=` + r.eSort + `">` + i["mv"] + `</A> <A HREF="` + *wfmPfx + `?fn=delp&dir=` + qeDir + `&file=` + qeFile + `&sort=` + r.eSort + `">` + i["rm"] + `</A> </TD> @@ -27,7 +27,7 @@ func deniedPfx(pfx string) bool { } func (r wfmRequest) dispFile() { - fp := r.uFp // TODO(tenox): uDir + uBn + fp := r.uDir + "/" + r.uFbn // TODO(tenox): deniedpfx should be in handlers??? if deniedPfx(fp) { htErr(r.w, "access", fmt.Errorf("forbidden")) @@ -54,7 +54,7 @@ func (r wfmRequest) dispFile() { } func (r wfmRequest) downFile() { - fp := r.uFp // TODO(tenox): uDir + uBn + fp := r.uDir + "/" + r.uFbn if deniedPfx(fp) { htErr(r.w, "access", fmt.Errorf("forbidden")) return @@ -65,7 +65,7 @@ func (r wfmRequest) downFile() { return } r.w.Header().Set("Content-Type", "application/octet-stream") - r.w.Header().Set("Content-Disposition", "attachment; filename=\""+filepath.Base(fp)+"\";") + r.w.Header().Set("Content-Disposition", "attachment; filename=\""+url.QueryEscape(r.uFbn)+"\";") r.w.Header().Set("Content-Length", fmt.Sprint(f.Size())) r.w.Header().Set("Cache-Control", *cacheCtl) streamFile(r.w, fp) @@ -134,7 +134,7 @@ func streamFile(w http.ResponseWriter, uFilePath string) { } func (r wfmRequest) uploadFile(h *multipart.FileHeader, f multipart.File) { - if !r.rw { + if !r.rwAccess { htErr(r.w, "permission", fmt.Errorf("read only")) return } @@ -171,7 +171,7 @@ func (r wfmRequest) uploadFile(h *multipart.FileHeader, f multipart.File) { } func (r wfmRequest) saveText(uData string) { - if !r.rw { + if !r.rwAccess { htErr(r.w, "permission", fmt.Errorf("read only")) return } @@ -183,7 +183,7 @@ func (r wfmRequest) saveText(uData string) { htErr(r.w, "text save", fmt.Errorf("zero lenght data")) return } - fp := r.uFp // TODO(tenox): uDir + uBn + fp := r.uDir + "/" + r.uFbn tmpName := fp + ".tmp" err := ioutil.WriteFile(tmpName, []byte(uData), 0644) if err != nil { @@ -199,17 +199,17 @@ func (r wfmRequest) saveText(uData string) { htErr(r.w, "text save", fmt.Errorf("temp file size != input size")) return } - err = os.Rename(tmpName, r.uFp) + err = os.Rename(tmpName, fp) if err != nil { htErr(r.w, "text save", err) return } - log.Printf("Saved Text Dir=%v File=%v Size=%v", r.uDir, r.uFp, len(uData)) - redirect(r.w, *wfmPfx+"?dir="+url.QueryEscape(r.uDir)+"&sort="+r.eSort+"&hi="+url.QueryEscape(filepath.Base(r.uFp))) + log.Printf("Saved Text Dir=%v File=%v Size=%v", r.uDir, fp, len(uData)) + redirect(r.w, *wfmPfx+"?dir="+url.QueryEscape(r.uDir)+"&sort="+r.eSort+"&hi="+url.QueryEscape(r.uFbn)) } func (r wfmRequest) mkdir() { - if !r.rw { + if !r.rwAccess { htErr(r.w, "permission", fmt.Errorf("read only")) return } @@ -218,22 +218,21 @@ func (r wfmRequest) mkdir() { return } - if r.uBn == "" { + if r.uFbn == "" { htErr(r.w, "mkdir", fmt.Errorf("directory name is empty")) return } - uB := filepath.Base(r.uBn) - err := os.Mkdir(r.uDir+"/"+uB, 0755) + err := os.Mkdir(r.uDir+"/"+r.uFbn, 0755) if err != nil { htErr(r.w, "mkdir", err) log.Printf("mkdir error: %v", err) return } - redirect(r.w, *wfmPfx+"?dir="+url.QueryEscape(r.uDir)+"&sort="+r.eSort+"&hi="+url.QueryEscape(uB)) + redirect(r.w, *wfmPfx+"?dir="+url.QueryEscape(r.uDir)+"&sort="+r.eSort+"&hi="+url.QueryEscape(r.uFbn)) } func (r wfmRequest) mkfile() { - if !r.rw { + if !r.rwAccess { htErr(r.w, "permission", fmt.Errorf("read only")) return } @@ -242,22 +241,21 @@ func (r wfmRequest) mkfile() { return } - if r.uBn == "" { + if r.uFbn == "" { htErr(r.w, "mkfile", fmt.Errorf("file name is empty")) return } - fB := filepath.Base(r.uBn) - f, err := os.OpenFile(r.uDir+"/"+fB, os.O_RDWR|os.O_EXCL|os.O_CREATE, 0644) + f, err := os.OpenFile(r.uDir+"/"+r.uFbn, os.O_RDWR|os.O_EXCL|os.O_CREATE, 0644) if err != nil { htErr(r.w, "mkfile", err) return } f.Close() - redirect(r.w, *wfmPfx+"?dir="+url.QueryEscape(r.uDir)+"&sort="+r.eSort+"&hi="+url.QueryEscape(fB)) + redirect(r.w, *wfmPfx+"?dir="+url.QueryEscape(r.uDir)+"&sort="+r.eSort+"&hi="+url.QueryEscape(r.uFbn)) } func (r wfmRequest) mkurl(eUrl string) { - if !r.rw { + if !r.rwAccess { htErr(r.w, "permission", fmt.Errorf("read only")) return } @@ -265,15 +263,14 @@ func (r wfmRequest) mkurl(eUrl string) { htErr(r.w, "access", fmt.Errorf("forbidden")) return } - if r.uBn == "" { + if r.uFbn == "" { htErr(r.w, "mkurl", fmt.Errorf("url file name is empty")) return } - fB := filepath.Base(r.uBn) - if !strings.HasSuffix(fB, ".url") { - fB = fB + ".url" + if !strings.HasSuffix(r.uFbn, ".url") { + r.uFbn = r.uFbn + ".url" } - f, err := os.OpenFile(r.uDir+"/"+fB, os.O_RDWR|os.O_EXCL|os.O_CREATE, 0644) + f, err := os.OpenFile(r.uDir+"/"+r.uFbn, os.O_RDWR|os.O_EXCL|os.O_CREATE, 0644) if err != nil { htErr(r.w, "mkfile", err) return @@ -281,11 +278,11 @@ func (r wfmRequest) mkurl(eUrl string) { // TODO(tenox): add upport for creating webloc, desktop and other formats fmt.Fprintf(f, "[InternetShortcut]\r\nURL=%s\r\n", eUrl) f.Close() - redirect(r.w, *wfmPfx+"?dir="+url.QueryEscape(r.uDir)+"&sort="+r.eSort+"&hi="+url.QueryEscape(fB)) + redirect(r.w, *wfmPfx+"?dir="+url.QueryEscape(r.uDir)+"&sort="+r.eSort+"&hi="+url.QueryEscape(r.uFbn)) } func (r wfmRequest) renFile(uNewf string) { - if !r.rw { + if !r.rwAccess { htErr(r.w, "permission", fmt.Errorf("read only")) return } @@ -294,24 +291,24 @@ func (r wfmRequest) renFile(uNewf string) { return } - if r.uBn == "" || uNewf == "" { + if r.uFbn == "" || uNewf == "" { htErr(r.w, "rename", fmt.Errorf("filename is empty")) return } - fB := filepath.Base(uNewf) + newB := filepath.Base(uNewf) err := os.Rename( - r.uDir+"/"+r.uBn, - r.uDir+"/"+fB, + r.uDir+"/"+r.uFbn, + r.uDir+"/"+newB, ) if err != nil { htErr(r.w, "rename", err) return } - redirect(r.w, *wfmPfx+"?dir="+url.QueryEscape(r.uDir)+"&sort="+r.eSort+"&hi="+url.QueryEscape(fB)) + redirect(r.w, *wfmPfx+"?dir="+url.QueryEscape(r.uDir)+"&sort="+r.eSort+"&hi="+url.QueryEscape(newB)) } func (r wfmRequest) moveFiles(uFilePaths []string, uDst string) { - if !r.rw { + if !r.rwAccess { htErr(r.w, "permission", fmt.Errorf("read only")) return } @@ -320,7 +317,7 @@ func (r wfmRequest) moveFiles(uFilePaths []string, uDst string) { htErr(r.w, "access", fmt.Errorf("forbidden")) return } - log.Printf("move dir=%v files=%+v dst=%v user=%v@%v", r.uDir, uFilePaths, uDst, r.user, r.remAddr) + log.Printf("move dir=%v files=%+v dst=%v user=%v@%v", r.uDir, uFilePaths, uDst, r.userName, r.remAddr) lF := "" for _, f := range uFilePaths { @@ -339,7 +336,7 @@ func (r wfmRequest) moveFiles(uFilePaths []string, uDst string) { } func (r wfmRequest) deleteFiles(uFilePaths []string) { - if !r.rw { + if !r.rwAccess { htErr(r.w, "permission", fmt.Errorf("read only")) return } @@ -347,7 +344,7 @@ func (r wfmRequest) deleteFiles(uFilePaths []string) { htErr(r.w, "access", fmt.Errorf("forbidden")) return } - log.Printf("delete dir=%v files=%+v user=%v@%v", r.uDir, uFilePaths, r.user, r.remAddr) + log.Printf("delete dir=%v files=%+v user=%v@%v", r.uDir, uFilePaths, r.userName, r.remAddr) for _, f := range uFilePaths { err := os.RemoveAll(r.uDir + "/" + filepath.Base(f)) diff --git a/handlers.go b/handlers.go index 30c95ad..47e5486 100644 --- a/handlers.go +++ b/handlers.go @@ -9,38 +9,36 @@ import ( ) type wfmRequest struct { - w http.ResponseWriter - user string - remAddr string - rw bool - modern bool - eSort string // escaped sort order - uDir string // unescaped directory name - uFp string // unescaped (full) file path TODO(tenox): to be removed - uBn string // unescaped base name + w http.ResponseWriter + userName string + remAddr string + rwAccess bool + modern bool + eSort string // escaped sort order + uDir string // unescaped directory name + uFbn string // unescaped file base name } func wfmMain(w http.ResponseWriter, r *http.Request) { wfm := new(wfmRequest) r.ParseMultipartForm(10 << 20) - wfm.user, wfm.rw = auth(w, r) - if wfm.user == "" { + wfm.userName, wfm.rwAccess = auth(w, r) + if wfm.userName == "" { return } - go log.Printf("req from=%q user=%q uri=%q form=%v", r.RemoteAddr, wfm.user, r.RequestURI, noText(r.Form)) + go log.Printf("req from=%q user=%q uri=%q form=%v", r.RemoteAddr, wfm.userName, r.RequestURI, noText(r.Form)) wfm.w = w wfm.remAddr = r.RemoteAddr + wfm.eSort = url.QueryEscape(r.FormValue("sort")) if strings.HasPrefix(r.UserAgent(), "Mozilla/5") { wfm.modern = true } + wfm.uFbn = filepath.Base(r.FormValue("file")) wfm.uDir = filepath.Clean(r.FormValue("dir")) if wfm.uDir == "" || wfm.uDir == "." { wfm.uDir = "/" } - wfm.eSort = url.QueryEscape(r.FormValue("sort")) - wfm.uFp = filepath.Clean(r.FormValue("fp")) - wfm.uBn = filepath.Base(r.FormValue("file")) // button clicked switch { @@ -100,16 +98,15 @@ func wfmMain(w http.ResponseWriter, r *http.Request) { case "rename": wfm.renFile(r.FormValue("dst")) case "renp": - wfm.uBn = r.FormValue("oldf") wfm.prompt("rename", nil) case "movp": wfm.prompt("move", nil) case "delp": wfm.prompt("delete", nil) case "move": - wfm.moveFiles([]string{wfm.uBn}, r.FormValue("dst")) + wfm.moveFiles([]string{wfm.uFbn}, r.FormValue("dst")) case "delete": - wfm.deleteFiles([]string{wfm.uBn}) + wfm.deleteFiles([]string{wfm.uFbn}) case "multi_delete": wfm.deleteFiles(r.Form["mulf"]) case "multi_move": |